You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

991 lines
22 KiB

11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
  1. <template>
  2. <div class="pda-container">
  3. <!-- 头部栏 -->
  4. <div class="header-bar" :style="getHeaderStyle()">
  5. <div class="header-left" @click="$router.back()">
  6. <i class="el-icon-arrow-left"></i>
  7. <span>{{ getProcessTitle() }}</span>
  8. </div>
  9. <div class="header-right" @click="$router.push({ path: '/' })">
  10. 首页
  11. </div>
  12. </div>
  13. <!-- 搜索框 -->
  14. <div class="search-container">
  15. <el-input clearable class="compact-input"
  16. v-model="scanCode"
  17. placeholder="请扫描HandlingUnit条码"
  18. prefix-icon="el-icon-search"
  19. @keyup.enter.native="handleScan"
  20. ref="scanInput"
  21. inputmode="none"
  22. autocomplete="off"
  23. autocorrect="off"
  24. spellcheck="false"
  25. />
  26. <div class="mode-switch">
  27. <el-switch
  28. class="custom-switch"
  29. v-model="isRemoveMode"
  30. active-color="#ff4949"
  31. inactive-color="#13ce66">
  32. </el-switch>
  33. <span v-if="isRemoveMode" class="switch-text">{{ '移除' }}</span>
  34. <span v-else class="switch-text2">{{ '添加' }}</span>
  35. </div>
  36. </div>
  37. <!-- 单据信息卡片 -->
  38. <div class="material-info-card" v-if="processInfo.transNo">
  39. <div class="card-title">
  40. <span class="title-label">{{ getProcessTitle() }}单据号:</span>
  41. <span class="title-value">{{ processInfo.transNo }}</span>
  42. </div>
  43. <div class="card-details">
  44. <div class="detail-item">
  45. <div class="detail-label">物料编码</div>
  46. <div class="detail-value">{{ processInfo.partNo }}</div>
  47. </div>
  48. <div class="detail-item">
  49. <div class="detail-label">{{ getQtyLabel() }}</div>
  50. <div class="detail-value">
  51. <span class="unqualified" :style="getQtyStyle()">{{ processInfo.unqualifiedQty }}</span>
  52. </div>
  53. </div>
  54. <div class="detail-item">
  55. <div class="detail-label">已扫描数量</div>
  56. <div class="detail-value">
  57. <span :class="getScannedQtyClass()">{{ getTotalScannedQty() }}</span>
  58. </div>
  59. </div>
  60. </div>
  61. </div>
  62. <!-- 处理信息确认标题 -->
  63. <div class="section-title" :style="getSectionStyle()">
  64. <div class="title-left">
  65. <i :class="getProcessIcon()" :style="getIconStyle()"></i>
  66. <span :style="getIconStyle()">{{ getProcessTitle() }}信息确认</span>
  67. </div>
  68. </div>
  69. <!-- 标签列表 -->
  70. <div class="label-list" v-if="scannedItems.length > 0" style="margin: 2px;">
  71. <el-form label-position="top" style="margin: 3px;">
  72. <el-row :gutter="5"
  73. v-for="(label, index) in scannedItems"
  74. :key="label.id"
  75. :class="index < scannedItems.length - 1 ? 'bottom-line-row' : ''"
  76. style="border: 1px solid #e0e0e0; border-radius: 4px; padding: 2px 6px;">
  77. <el-col :span="12">
  78. <el-form-item label="HandlingUnit"><span>{{ label.unitId }}</span></el-form-item>
  79. </el-col>
  80. <el-col :span="8">
  81. <el-form-item label="物料编码"><span>{{ label.partNo }}</span></el-form-item>
  82. </el-col>
  83. <el-col :span="4">
  84. <el-form-item label="数量"><span>{{ label.qty }} {{ label.unit}}</span></el-form-item>
  85. </el-col>
  86. <el-col :span="24" v-if="label.partDesc">
  87. <el-form-item label="物料描述"><span>{{ label.partDesc }}</span></el-form-item>
  88. </el-col>
  89. <el-col :span="12" v-if="label.batchNo">
  90. <el-form-item label="批次号"><span>{{ label.batchNo }}</span></el-form-item>
  91. </el-col>
  92. <el-col :span="12" v-if="label.locationId">
  93. <el-form-item label="库位"><span>{{ label.locationId }}</span></el-form-item>
  94. </el-col>
  95. </el-row>
  96. </el-form>
  97. </div>
  98. <!-- 空状态 -->
  99. <div v-if="scannedItems.length === 0" class="empty-labels">
  100. <p>暂无扫描HandlingUnit</p>
  101. </div>
  102. <!-- 底部操作按钮 -->
  103. <div class="bottom-actions">
  104. <button class="action-btn primary" :style="getButtonStyle()" @click="confirmProcess">
  105. 确认{{ getProcessTitle() }}
  106. </button>
  107. <button class="action-btn secondary" :style="getSecondaryButtonStyle()" style="margin-left: 10px;" @click="cancelProcess">
  108. 取消
  109. </button>
  110. </div>
  111. </div>
  112. </template>
  113. <script>
  114. import { scanHandlingUnitLabel, confirmUnqualifiedProcess } from '@/api/po/po.js';
  115. export default {
  116. data() {
  117. return {
  118. scanCode: '',
  119. processInfo: {},
  120. scannedItems: [],
  121. isRemoveMode: false, // 默认为添加模式
  122. processType: '' // RETURN/SCRAP/EXCHANGE
  123. };
  124. },
  125. computed: {
  126. // 处理类型配置
  127. processConfig() {
  128. const configs = {
  129. 'RETURN': {
  130. title: '退货',
  131. color: '#E6A23C',
  132. icon: 'el-icon-refresh-left',
  133. qtyLabel: '退货数量'
  134. },
  135. 'SCRAP': {
  136. title: '报废',
  137. color: '#F56C6C',
  138. icon: 'el-icon-delete',
  139. qtyLabel: '报废数量'
  140. },
  141. 'EXCHANGE': {
  142. title: '换货',
  143. color: '#409EFF',
  144. icon: 'el-icon-refresh',
  145. qtyLabel: '换货数量'
  146. }
  147. };
  148. return configs[this.processType] || configs['RETURN'];
  149. }
  150. },
  151. methods: {
  152. // 获取处理标题
  153. getProcessTitle() {
  154. return this.processConfig.title;
  155. },
  156. // 获取数量标签
  157. getQtyLabel() {
  158. return this.processConfig.qtyLabel;
  159. },
  160. // 获取处理图标
  161. getProcessIcon() {
  162. return this.processConfig.icon;
  163. },
  164. // 获取头部样式
  165. getHeaderStyle() {
  166. return `background: ${this.processConfig.color};`;
  167. },
  168. // 获取区域标题样式
  169. getSectionStyle() {
  170. return `border-bottom: 2px solid ${this.processConfig.color};`;
  171. },
  172. // 获取图标样式
  173. getIconStyle() {
  174. return `color: ${this.processConfig.color};`;
  175. },
  176. // 获取数量样式
  177. getQtyStyle() {
  178. return `color: ${this.processConfig.color}; font-weight: 500;`;
  179. },
  180. // 获取主按钮样式
  181. getButtonStyle() {
  182. return `border: 1px solid ${this.processConfig.color}; background: ${this.processConfig.color}; color: white;`;
  183. },
  184. // 获取次要按钮样式
  185. getSecondaryButtonStyle() {
  186. return `border: 1px solid ${this.processConfig.color}; background: white; color: ${this.processConfig.color};`;
  187. },
  188. // 处理扫描
  189. handleScan() {
  190. if (!this.scanCode.trim()) {
  191. return;
  192. }
  193. if (this.isRemoveMode) {
  194. this.removeLabelByCode(this.scanCode.trim());
  195. } else {
  196. this.validateAndAddLabel(this.scanCode.trim());
  197. }
  198. this.scanCode = '';
  199. },
  200. // 验证标签并添加到列表
  201. validateAndAddLabel(unitId) {
  202. const params = {
  203. unitId: unitId,
  204. site: localStorage.getItem('site'),
  205. };
  206. scanHandlingUnitLabel(params).then(({ data }) => {
  207. if (data && data.code === 0 && data.data) {
  208. const huInfo = data.data;
  209. // 检查是否已经扫描过
  210. const exists = this.scannedItems.find(item => item.unitId === unitId);
  211. if (exists) {
  212. this.$message.warning('该HandlingUnit已扫描,请勿重复扫描');
  213. return;
  214. }
  215. if (huInfo.inStockFlag !== 'X') {
  216. this.$message.error('HandlingUnit不是未入库状态,无法处理');
  217. return;
  218. }
  219. // 校验HU是否属于当前单据
  220. if (huInfo.site !== localStorage.getItem('site')) {
  221. this.$message.error('HandlingUnit站点不匹配');
  222. return;
  223. }
  224. // 检查单据是否匹配
  225. if (this.processInfo.transNo && huInfo.batchNo !== this.processInfo.transNo) {
  226. this.$message.error('单据号不匹配,请检查');
  227. return;
  228. }
  229. // 检查物料是否匹配
  230. if (this.processInfo.partNo && huInfo.partNo !== this.processInfo.partNo) {
  231. this.$message.error('物料编码不匹配,请检查');
  232. return;
  233. }
  234. // 添加到列表
  235. this.scannedItems.push({
  236. id: Date.now(),
  237. unitId: unitId,
  238. partNo: huInfo.partNo,
  239. partDesc: huInfo.partDesc,
  240. qty: huInfo.qty,
  241. unit: huInfo.unit,
  242. batchNo: huInfo.batchNo,
  243. locationId: huInfo.locationId
  244. });
  245. this.$message.success('扫描成功');
  246. } else {
  247. this.$message.error(data.msg || 'HandlingUnit不存在或查询失败');
  248. }
  249. }).catch(error => {
  250. this.$message.error('扫描失败');
  251. });
  252. },
  253. // 通过条码移除标签
  254. removeLabelByCode(unitId) {
  255. const index = this.scannedItems.findIndex(item => item.unitId === unitId);
  256. if (index !== -1) {
  257. this.scannedItems.splice(index, 1);
  258. this.$message.success('移除成功');
  259. } else {
  260. this.$message.warning('未找到该HandlingUnit');
  261. }
  262. },
  263. // 获取总扫描数量
  264. getTotalScannedQty() {
  265. return this.scannedItems.reduce((total, item) => {
  266. return total + (parseFloat(item.qty) || 0);
  267. }, 0);
  268. },
  269. // 获取已扫描数量的样式类
  270. getScannedQtyClass() {
  271. const totalScannedQty = this.getTotalScannedQty();
  272. const unqualifiedQty = parseFloat(this.processInfo.unqualifiedQty) || 0;
  273. if (totalScannedQty === 0) {
  274. return 'scanned-empty';
  275. } else if (totalScannedQty === unqualifiedQty) {
  276. return 'scanned-match';
  277. } else {
  278. return 'scanned-mismatch';
  279. }
  280. },
  281. // 确认处理
  282. confirmProcess() {
  283. if (this.scannedItems.length === 0) {
  284. this.$message.warning('请先扫描HandlingUnit');
  285. return;
  286. }
  287. // 校验扫描数量与退货/报废数量是否一致
  288. const totalScannedQty = this.getTotalScannedQty();
  289. const unqualifiedQty = parseFloat(this.processInfo.unqualifiedQty) || 0;
  290. if (totalScannedQty !== unqualifiedQty) {
  291. const processTitle = this.getProcessTitle();
  292. this.$message.error(`扫描的HU总数量(${totalScannedQty})与${processTitle}数量(${unqualifiedQty})不一致,请检查!`);
  293. return;
  294. }
  295. const processTitle = this.getProcessTitle();
  296. this.$confirm(`确认要${processTitle}这些物料吗?`, '提示', {
  297. confirmButtonText: '确定',
  298. cancelButtonText: '取消',
  299. type: 'warning'
  300. }).then(() => {
  301. this.submitConfirmProcess();
  302. }).catch(() => {
  303. // 用户取消
  304. });
  305. },
  306. // 提交确认处理
  307. submitConfirmProcess() {
  308. const handlingUnitIds = this.scannedItems.map(item => item.unitId);
  309. const params = {
  310. site: localStorage.getItem('site'),
  311. transNo: this.processInfo.transNo,
  312. processType: this.processInfo.processType,
  313. handlingUnitIds: handlingUnitIds
  314. };
  315. confirmUnqualifiedProcess(params).then(({ data }) => {
  316. if (data && data.code === 0) {
  317. const processTitle = this.getProcessTitle();
  318. this.$message.success(`${processTitle}处理成功`);
  319. this.$router.back();
  320. } else {
  321. this.$message.error(data.msg || '处理失败');
  322. }
  323. }).catch(error => {
  324. console.error('确认处理失败:', error);
  325. this.$message.error('处理失败,请重试');
  326. });
  327. },
  328. // 取消处理
  329. cancelProcess() {
  330. if (this.scannedItems.length > 0) {
  331. this.$confirm('取消后将清空已扫描的HandlingUnit,确定取消吗?', '提示', {
  332. confirmButtonText: '确定',
  333. cancelButtonText: '继续操作',
  334. type: 'warning'
  335. }).then(() => {
  336. this.$router.back();
  337. }).catch(() => {
  338. // 用户选择继续操作
  339. });
  340. } else {
  341. this.$router.back();
  342. }
  343. }
  344. },
  345. mounted() {
  346. // 获取路由参数
  347. const query = this.$route.query;
  348. this.processType = query.processType || 'RETURN';
  349. this.processInfo = {
  350. transNo: query.transNo,
  351. itemNo: query.itemNo,
  352. processType: query.processType,
  353. partNo: query.partNo,
  354. unqualifiedQty: query.unqualifiedQty
  355. };
  356. // 如果有传入的扫描项目,恢复它们
  357. if (query.scannedItems) {
  358. try {
  359. this.scannedItems = JSON.parse(query.scannedItems);
  360. } catch (e) {
  361. console.error('解析扫描项目失败:', e);
  362. }
  363. }
  364. // 聚焦扫描框
  365. this.$nextTick(() => {
  366. if (this.$refs.scanInput) {
  367. this.$refs.scanInput.focus();
  368. }
  369. });
  370. }
  371. };
  372. </script>
  373. <style scoped>
  374. /* 复用生产领料页面的样式,只修改必要的部分 */
  375. .pda-container {
  376. width: 100vw;
  377. height: 100vh;
  378. display: flex;
  379. flex-direction: column;
  380. background: #f5f5f5;
  381. }
  382. /* 头部栏 */
  383. .header-bar {
  384. display: flex;
  385. justify-content: space-between;
  386. align-items: center;
  387. padding: 8px 16px;
  388. background: #17B3A3;
  389. color: white;
  390. height: 40px;
  391. min-height: 40px;
  392. }
  393. .header-left {
  394. display: flex;
  395. align-items: center;
  396. cursor: pointer;
  397. font-size: 16px;
  398. font-weight: 500;
  399. }
  400. .header-left i {
  401. margin-right: 8px;
  402. font-size: 18px;
  403. }
  404. .header-right {
  405. cursor: pointer;
  406. font-size: 16px;
  407. font-weight: 500;
  408. }
  409. /* 搜索容器 */
  410. .search-container {
  411. padding: 12px 16px;
  412. background: white;
  413. display: flex;
  414. align-items: center;
  415. gap: 12px;
  416. }
  417. .search-container .el-input {
  418. width: 240px;
  419. margin-right: 12px;
  420. }
  421. /* 紧凑型输入框样式 */
  422. .compact-input ::v-deep .el-input__inner {
  423. height: 36px;
  424. padding: 0 12px 0 35px;
  425. font-size: 14px;
  426. }
  427. .compact-input ::v-deep .el-input__prefix {
  428. left: 10px;
  429. }
  430. .compact-input ::v-deep .el-input__suffix {
  431. right: 30px;
  432. }
  433. /* 模式切换开关 */
  434. .mode-switch {
  435. position: relative;
  436. display: inline-block;
  437. }
  438. .custom-switch {
  439. transform: scale(1.3);
  440. }
  441. /* 中间文字 */
  442. .switch-text {
  443. position: absolute;
  444. left: 25%;
  445. transform: translateX(-50%);
  446. top: 50%;
  447. transform: translateY(-50%) translateX(-50%);
  448. font-size: 12px;
  449. font-weight: 500;
  450. color: #606266;
  451. white-space: nowrap;
  452. pointer-events: none;
  453. z-index: 1;
  454. top: 53%;
  455. transform: translate(-50%, -50%);
  456. font-size: 12px;
  457. font-weight: bold;
  458. color: white;
  459. pointer-events: none;
  460. z-index: 2;
  461. }
  462. .switch-text2 {
  463. position: absolute;
  464. left: 75%;
  465. transform: translateX(-50%);
  466. top: 50%;
  467. transform: translateY(-50%) translateX(-50%);
  468. font-size: 12px;
  469. font-weight: 500;
  470. color: #606266;
  471. white-space: nowrap;
  472. pointer-events: none;
  473. z-index: 1;
  474. top: 53%;
  475. transform: translate(-50%, -50%);
  476. font-size: 12px;
  477. font-weight: bold;
  478. color: white;
  479. pointer-events: none;
  480. z-index: 2;
  481. }
  482. /* 调整 switch 尺寸以便容纳文字 */
  483. .custom-switch ::v-deep .el-switch__core {
  484. width: 60px;
  485. height: 28px;
  486. }
  487. /* 物料信息卡片 */
  488. .material-info-card {
  489. background: white;
  490. margin: 4px 4px;
  491. padding: 6px 20px;
  492. border-radius: 8px;
  493. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  494. border: 1px solid #f0f0f0;
  495. }
  496. .card-title {
  497. margin-bottom: 8px;
  498. display: flex;
  499. align-items: center;
  500. gap: 8px;
  501. }
  502. .title-label {
  503. font-size: 12px;
  504. color: #666;
  505. font-weight: 500;
  506. }
  507. .title-value {
  508. font-size: 16px;
  509. font-weight: bold;
  510. color: #333;
  511. line-height: 1.2;
  512. }
  513. .card-details {
  514. display: flex;
  515. justify-content: space-between;
  516. align-items: flex-start;
  517. gap: 4px;
  518. }
  519. .detail-item {
  520. flex: 1;
  521. text-align: center;
  522. min-width: 60px;
  523. max-width: 60px;
  524. }
  525. .detail-label {
  526. font-size: 11px;
  527. color: #999;
  528. margin-bottom: 6px;
  529. font-weight: normal;
  530. line-height: 1.2;
  531. margin-left: -12px;
  532. }
  533. .detail-value {
  534. font-size: 13px;
  535. color: #333;
  536. font-weight: 500;
  537. line-height: 1.2;
  538. }
  539. .detail-value .qualified {
  540. color: #17B3A3;
  541. font-weight: 500;
  542. }
  543. .detail-value .total {
  544. color: #333;
  545. font-weight: 500;
  546. }
  547. .detail-value .total::before {
  548. content: '/';
  549. color: #333;
  550. }
  551. /* 已扫描数量样式 */
  552. .detail-value .scanned-empty {
  553. color: #909399;
  554. font-weight: 500;
  555. }
  556. .detail-value .scanned-match {
  557. color: #67C23A;
  558. font-weight: 600;
  559. }
  560. .detail-value .scanned-mismatch {
  561. color: #F56C6C;
  562. font-weight: 600;
  563. }
  564. /* 区域标题 */
  565. .section-title {
  566. display: flex;
  567. align-items: center;
  568. justify-content: space-between;
  569. padding: 6px 8px;
  570. background: white;
  571. margin: 0 4px;
  572. margin-top: 4px;
  573. border-radius: 8px 8px 0 0;
  574. border-bottom: 2px solid #17B3A3;
  575. }
  576. .title-left {
  577. display: flex;
  578. align-items: center;
  579. }
  580. .title-left i {
  581. color: #17B3A3;
  582. font-size: 16px;
  583. margin-right: 8px;
  584. }
  585. .title-left span {
  586. color: #17B3A3;
  587. font-size: 14px;
  588. font-weight: 500;
  589. }
  590. .title-right {
  591. display: flex;
  592. align-items: center;
  593. }
  594. .material-list-link {
  595. color: #17B3A3;
  596. font-size: 14px;
  597. font-weight: 500;
  598. cursor: pointer;
  599. text-decoration: underline;
  600. transition: color 0.2s ease;
  601. }
  602. .material-list-link:hover {
  603. color: #0d8f7f;
  604. }
  605. /* 标签列表 */
  606. .label-list {
  607. background: white;
  608. margin: 0 4px 4px;
  609. border-radius: 0 0 8px 8px;
  610. overflow: hidden;
  611. }
  612. .label-list .el-form-item {
  613. margin-bottom: 1px;
  614. }
  615. .label-list .el-form-item__label {
  616. padding-bottom: 1px;
  617. margin-bottom: 0;
  618. line-height: 1.1;
  619. font-size: 11px;
  620. }
  621. .label-list .el-form-item__content {
  622. line-height: 1.2;
  623. font-size: 12px;
  624. }
  625. .empty-labels {
  626. padding: 40px 20px;
  627. text-align: center;
  628. color: #999;
  629. }
  630. .empty-labels p {
  631. margin: 0;
  632. font-size: 14px;
  633. }
  634. /* 底部操作按钮 */
  635. .bottom-actions {
  636. display: flex;
  637. padding: 16px;
  638. gap: 20px;
  639. background: white;
  640. margin-top: auto;
  641. }
  642. .action-btn {
  643. flex: 1;
  644. padding: 12px;
  645. border: 1px solid #17B3A3;
  646. background: white;
  647. color: #17B3A3;
  648. border-radius: 20px;
  649. font-size: 14px;
  650. cursor: pointer;
  651. transition: all 0.2s ease;
  652. }
  653. .action-btn:hover {
  654. background: #17B3A3;
  655. color: white;
  656. }
  657. .action-btn:active {
  658. transform: scale(0.98);
  659. }
  660. /* 物料清单弹窗样式 */
  661. .material-overlay {
  662. position: fixed;
  663. top: 0;
  664. left: 0;
  665. right: 0;
  666. bottom: 0;
  667. background: rgba(0, 0, 0, 0.5);
  668. z-index: 9999;
  669. display: flex;
  670. align-items: center;
  671. justify-content: center;
  672. padding: 20px;
  673. }
  674. .material-modal {
  675. background: white;
  676. border-radius: 12px;
  677. width: 100%;
  678. max-width: 800px;
  679. max-height: 80vh;
  680. box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  681. overflow: hidden;
  682. display: flex;
  683. flex-direction: column;
  684. }
  685. .material-modal .modal-header {
  686. background: #17B3A3;
  687. color: white;
  688. padding: 5px 16px;
  689. display: flex;
  690. justify-content: space-between;
  691. align-items: center;
  692. min-height: 28px;
  693. }
  694. .close-btn {
  695. font-size: 16px;
  696. cursor: pointer;
  697. color: white;
  698. transition: color 0.2s ease;
  699. padding: 4px;
  700. display: flex;
  701. align-items: center;
  702. justify-content: center;
  703. }
  704. .close-btn:hover {
  705. color: #e0e0e0;
  706. }
  707. .material-modal .modal-title {
  708. font-size: 16px;
  709. font-weight: 500;
  710. margin: 0;
  711. line-height: 1.2;
  712. }
  713. .material-modal .modal-body {
  714. flex: 1;
  715. overflow: auto;
  716. padding: 0;
  717. }
  718. .material-table {
  719. width: 100%;
  720. }
  721. .table-header {
  722. display: flex;
  723. background: #f8f9fa;
  724. padding: 10px 6px;
  725. border-bottom: 2px solid #17B3A3;
  726. font-size: 12px;
  727. color: #333;
  728. font-weight: 600;
  729. position: sticky;
  730. top: 0;
  731. z-index: 1;
  732. }
  733. .table-body {
  734. max-height: 400px;
  735. overflow-y: auto;
  736. }
  737. .table-row {
  738. display: flex;
  739. padding: 10px 6px;
  740. border-bottom: 1px solid #f0f0f0;
  741. font-size: 12px;
  742. color: #333;
  743. transition: background-color 0.2s ease;
  744. }
  745. .table-row:hover {
  746. background-color: #f8f9fa;
  747. }
  748. .table-row:last-child {
  749. border-bottom: none;
  750. }
  751. .material-table .col-no {
  752. width: 25px;
  753. text-align: center;
  754. flex-shrink: 0;
  755. font-size: 12px;
  756. }
  757. .material-table .col-material-code {
  758. flex: 1.8;
  759. text-align: center;
  760. min-width: 100px;
  761. font-size: 12px;
  762. word-break: break-all;
  763. }
  764. .material-table .col-required-qty {
  765. flex: 0.8;
  766. text-align: center;
  767. min-width: 65px;
  768. font-size: 12px;
  769. }
  770. .material-table .col-inbound-qty {
  771. flex: 0.8;
  772. text-align: center;
  773. min-width: 65px;
  774. font-size: 12px;
  775. }
  776. .material-modal .modal-footer {
  777. padding: 15px 20px;
  778. display: flex;
  779. justify-content: center;
  780. border-top: 1px solid #f0f0f0;
  781. }
  782. .btn-close {
  783. padding: 10px 20px;
  784. border-radius: 6px;
  785. font-size: 14px;
  786. cursor: pointer;
  787. transition: all 0.2s;
  788. border: 1px solid #17B3A3;
  789. background: white;
  790. color: #17B3A3;
  791. }
  792. .btn-close:hover {
  793. background: #17B3A3;
  794. color: white;
  795. }
  796. /* 加载状态样式 */
  797. .loading-container {
  798. display: flex;
  799. flex-direction: column;
  800. align-items: center;
  801. justify-content: center;
  802. padding: 60px 20px;
  803. color: #666;
  804. }
  805. .loading-container i {
  806. font-size: 24px;
  807. margin-bottom: 12px;
  808. color: #17B3A3;
  809. }
  810. .loading-container span {
  811. font-size: 14px;
  812. }
  813. /* 空数据状态样式 */
  814. .empty-material {
  815. display: flex;
  816. flex-direction: column;
  817. align-items: center;
  818. justify-content: center;
  819. padding: 60px 20px;
  820. color: #999;
  821. }
  822. .empty-material i {
  823. font-size: 48px;
  824. margin-bottom: 16px;
  825. color: #ddd;
  826. }
  827. .empty-material p {
  828. margin: 0;
  829. font-size: 14px;
  830. }
  831. /* 响应式设计 */
  832. @media (max-width: 360px) {
  833. .header-bar {
  834. padding: 8px 12px;
  835. }
  836. .search-container {
  837. padding: 8px 12px;
  838. }
  839. .material-info-card {
  840. margin: 4px 4px;
  841. padding: 6px 16px;
  842. }
  843. .section-title {
  844. margin: 0 4px;
  845. margin-top: 4px;
  846. }
  847. .label-list {
  848. margin: 0 12px 8px;
  849. }
  850. .card-details {
  851. flex-wrap: wrap;
  852. gap: 6px;
  853. }
  854. .detail-item {
  855. flex: 0 0 48%;
  856. margin-bottom: 6px;
  857. min-width: 50px;
  858. }
  859. .label-list .el-form-item__label {
  860. font-size: 10px;
  861. }
  862. .label-list .el-form-item__content {
  863. font-size: 10px;
  864. }
  865. .label-list .el-form-item {
  866. margin-bottom: 2px;
  867. }
  868. }
  869. </style>