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.

1118 lines
23 KiB

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