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.

984 lines
20 KiB

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