From ca285f78c697b53a5b9a69daa5275e2bf4648451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Mon, 1 Jun 2026 16:40:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(qc):=20=E6=96=B0=E5=A2=9E=E5=8E=82?= =?UTF-8?q?=E5=AE=B6=E5=8D=B7=E5=8F=B7=E5=8C=B9=E9=85=8D=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E5=8D=B7=E5=8F=B7=E5=BD=95=E5=85=A5?= =?UTF-8?q?=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次改动在检验任务、化学成分报告、物理性能报告模块中: 1. 支持通过入场卷号和厂家卷号双向搜索匹配 2. 新增多选卷号标签式展示与删除功能 3. 新增批量导入时厂家卷号自动匹配入场卷号的逻辑,包含多匹配结果弹窗选择 4. 在表格中新增厂家卷号展示列,更新导入模板支持厂家卷号字段 --- .../KLPService/SchemeSelect/index.vue | 123 +++++++++++-- .../views/mes/qc/certificate/chemistry.vue | 164 ++++++++++++++++- .../src/views/mes/qc/certificate/physics.vue | 167 ++++++++++++++++-- klp-ui/src/views/mes/qc/inspection/task.vue | 127 ++++++++++--- 4 files changed, 525 insertions(+), 56 deletions(-) diff --git a/klp-ui/src/components/KLPService/SchemeSelect/index.vue b/klp-ui/src/components/KLPService/SchemeSelect/index.vue index 1ddf9755..cf3a72c7 100644 --- a/klp-ui/src/components/KLPService/SchemeSelect/index.vue +++ b/klp-ui/src/components/KLPService/SchemeSelect/index.vue @@ -73,17 +73,56 @@ - - - +
+
+ + 可输入入场卷号或厂家卷号,两者互通匹配 +
+ +
+ + {{ coilNo }} + +
+ +
+ + {{ coilNo }} + +
+ +
+
+ @@ -297,7 +307,6 @@ -
@@ -327,9 +336,31 @@
{{ importErrorMsg }}
+ + - - + +
+ 厂家卷号匹配到多条入场卷号,请为每行选择对应记录 +
+ + + + + + +
@@ -343,12 +374,13 @@ import CoilSelector from "@/components/CoilSelector"; import { listMaterialCoil } from "@/api/wms/coil"; const PHYS_TEMPLATE_HEADERS = [ - '当前钢卷号', '屈服强度(MPa)', '抗拉强度(MPa)', '伸长率(%)', '规定塑性延伸强度(MPa)', '硬度(HRB)', + '当前钢卷号', '厂家卷号', '屈服强度(MPa)', '抗拉强度(MPa)', '伸长率(%)', '规定塑性延伸强度(MPa)', '硬度(HRB)', '镀层重量(g/m²)', '弯曲试验', '表面质量', '表面结构', '镀层表面结构', '边缘状态' ]; const PHYS_HEADER_MAP = { '当前钢卷号': 'coilNo', + '厂家卷号': 'supplierCoilNo', '屈服强度(MPa)': 'yieldStrength', '抗拉强度(MPa)': 'tensileStrength', '伸长率(%)': 'elongation', @@ -429,6 +461,10 @@ export default { importLoading: false, coilNoOptions: [], coilNoLoading: false, + tempSupplierCoilNo: '', + supplierCoilNoLoading: false, + ambiguousVisible: false, + ambiguousRows: [], }; }, created() { @@ -520,6 +556,34 @@ export default { this.coilNoLoading = false; }); }, + querySupplierCoilNo(queryString, cb) { + if (!queryString || queryString.length < 2) { + cb([]); + return; + } + this.supplierCoilNoLoading = true; + listMaterialCoil({ + supplierCoilNo: queryString, + pageNum: 1, + pageSize: 20 + }).then(response => { + const options = (response.rows || []).map(item => ({ + value: item.supplierCoilNo, + label: item.supplierCoilNo, + enterCoilNo: item.enterCoilNo + })); + cb(options); + }).finally(() => { + this.supplierCoilNoLoading = false; + }); + }, + handleSelectSupplierCoilNo(item) { + if (item.enterCoilNo) { + this.form.coilNo = item.enterCoilNo; + this.$refs["form"].validateField('coilNo'); + } + this.tempSupplierCoilNo = ''; + }, handleBatchAdd(rows) { this.loading = true; this.buttonLoading = true; @@ -589,12 +653,89 @@ export default { if (!this.importFile || !this.importRawData.length) { this.$message.warning('暂无数据可校验'); return; } this.importValidateLoading = true; this.importErrorList = []; - for (let i = 0; i < this.importRawData.length; i++) { + this.ambiguousRows = []; + const dataRows = this.importRawData; + for (let i = 0; i < dataRows.length; i++) { const rowNum = i + 2; - let coilNo = ''; - PHYS_TEMPLATE_HEADERS.forEach((h, j) => { if (PHYS_HEADER_MAP[h] === 'coilNo') coilNo = this.importRawData[i][j]; }); - if (!coilNo || !String(coilNo).trim()) this.importErrorList.push({ rowNum, errorMsg: '当前钢卷号不能为空' }); + let coilNo = '', supplierCoilNo = ''; + PHYS_TEMPLATE_HEADERS.forEach((h, j) => { + if (PHYS_HEADER_MAP[h] === 'coilNo') coilNo = dataRows[i][j]; + if (PHYS_HEADER_MAP[h] === 'supplierCoilNo') supplierCoilNo = dataRows[i][j]; + }); + coilNo = String(coilNo || '').trim(); + supplierCoilNo = String(supplierCoilNo || '').trim(); + if (!coilNo && !supplierCoilNo) { + this.importErrorList.push({ rowNum, errorMsg: '当前钢卷号和厂家卷号不能同时为空' }); + } } + // 处理仅填写厂家卷号的行 + if (this.importErrorList.length === 0) { + this.importTableData.forEach((row, idx) => { + const cn = (row.coilNo || '').trim(); + const sn = (row.supplierCoilNo || '').trim(); + row._sno = sn; + row._idx = idx; + row._fillCoilNo = cn; + if (sn && !cn) row._needMatch = true; + }); + const needMatchRows = this.importTableData.filter(r => r._needMatch); + if (needMatchRows.length > 0) { + const uniqueSnos = [...new Set(needMatchRows.map(r => r._sno))]; + const multiMap = {}; + try { + const results = await Promise.all( + uniqueSnos.map(sno => listMaterialCoil({ supplierCoilNo: sno, pageNum: 1, pageSize: 50 })) + ); + uniqueSnos.forEach((sno, idx) => { + const rows = (results[idx] && results[idx].rows) || []; + const enterNos = [...new Set(rows.map(r => r.enterCoilNo).filter(Boolean))]; + multiMap[sno] = enterNos; + }); + } catch (err) { + this.importValidateLoading = false; + this.importHandleError('厂家卷号匹配失败:' + err.message); + return; + } + const ambiguousList = []; + needMatchRows.forEach(row => { + const candidates = multiMap[row._sno] || []; + if (candidates.length === 0) { + this.importErrorList.push({ rowNum: (row.rowNum || (row._idx + 2)), errorMsg: `厂家卷号"${row._sno}"未匹配到入场卷号` }); + } else if (candidates.length === 1) { + row.coilNo = candidates[0]; + } else { + ambiguousList.push({ + _idx: row._idx, + supplierCoilNo: row._sno, + options: candidates, + selected: null + }); + } + }); + if (ambiguousList.length > 0) { + this.ambiguousRows = ambiguousList; + this.importValidateLoading = false; + this.ambiguousVisible = true; + return; + } + } + } + this.finishValidation(); + }, + confirmAmbiguous() { + const unselected = this.ambiguousRows.filter(r => !r.selected); + if (unselected.length > 0) { + this.$message.warning('请为所有行选择入场卷号'); + return; + } + this.ambiguousRows.forEach(item => { + this.importTableData[item._idx].coilNo = item.selected; + }); + this.ambiguousVisible = false; + this.importValidateLoading = true; + this.finishValidation(); + }, + finishValidation() { if (this.importErrorList.length > 0) { this.$message.error(`数据校验失败,共发现${this.importErrorList.length}条错误`); } else { @@ -647,10 +788,10 @@ export default { this.$refs.importUpload?.clearFiles(); }, importDownloadTemplate() { - const data = [PHYS_TEMPLATE_HEADERS, ['示例卷号', '300', '420', '35', '260', '85', '275', '合格', '良好', '光面', '无锌花', '良好']]; + const data = [PHYS_TEMPLATE_HEADERS, ['示例卷号', '示例厂家卷号', '300', '420', '35', '260', '85', '275', '合格', '良好', '光面', '无锌花', '良好']]; const wb = XLSX.utils.book_new(); const ws = XLSX.utils.aoa_to_sheet(data); - ws['!cols'] = [{ wch: 16 }, { wch: 16 }, { wch: 16 }, { wch: 10 }, { wch: 20 }, { wch: 10 }, { wch: 16 }, { wch: 10 }, { wch: 10 }, { wch: 10 }, { wch: 12 }, { wch: 10 }]; + ws['!cols'] = [{ wch: 16 }, { wch: 16 }, { wch: 16 }, { wch: 16 }, { wch: 10 }, { wch: 20 }, { wch: 10 }, { wch: 16 }, { wch: 10 }, { wch: 10 }, { wch: 10 }, { wch: 12 }, { wch: 10 }]; XLSX.utils.book_append_sheet(wb, ws, '导入模板'); XLSX.writeFile(wb, '物理性能导入模板.xlsx'); }, diff --git a/klp-ui/src/views/mes/qc/inspection/task.vue b/klp-ui/src/views/mes/qc/inspection/task.vue index b2c67be5..4c15fa84 100644 --- a/klp-ui/src/views/mes/qc/inspection/task.vue +++ b/klp-ui/src/views/mes/qc/inspection/task.vue @@ -75,6 +75,7 @@ + @@ -258,27 +259,57 @@ - -
- - {{ coilNo }} - + @@ -488,6 +519,9 @@ export default { enterCoilNoLoading: false, selectedEnterCoilNos: [], tempEnterCoilNo: '', + selectedSupplierCoilNos: [], + tempSupplierCoilNo: '', + supplierCoilNoLoading: false, attachmentOpen: false, attachmentTitle: '', attachmentLoading: false, @@ -558,6 +592,8 @@ export default { this.resetTaskForm(); this.selectedEnterCoilNos = []; this.tempEnterCoilNo = ''; + this.selectedSupplierCoilNos = []; + this.tempSupplierCoilNo = ''; this.taskOpen = true; this.taskTitle = "添加检验任务"; }, @@ -581,6 +617,13 @@ export default { this.selectedEnterCoilNos = []; } this.tempEnterCoilNo = ''; + // 初始化已选择的厂家卷号 + if (response.data.supplierCoilNos) { + this.selectedSupplierCoilNos = response.data.supplierCoilNos.split(',').filter(item => item.trim()); + } else { + this.selectedSupplierCoilNos = []; + } + this.tempSupplierCoilNo = ''; this.taskLoading = false; this.taskOpen = true; this.taskTitle = "修改检验任务"; @@ -636,7 +679,7 @@ export default { handleQuickCreate() { this.schemeVisible = true; }, - handleSchemeConfirm({ template, taskCode, taskType, belongCompany, coilIds, enterCoilNos }) { + handleSchemeConfirm({ template, taskCode, taskType, belongCompany, coilIds, enterCoilNos, supplierCoilNos }) { this.taskLoading = true; addInspectionTaskWithItems({ taskCode: taskCode, @@ -645,7 +688,8 @@ export default { belongCompany: belongCompany, taskType: taskType, coilIds: coilIds || undefined, - enterCoilNos: enterCoilNos || undefined + enterCoilNos: enterCoilNos || undefined, + supplierCoilNos: supplierCoilNos || undefined }).then(() => { this.$modal.msgSuccess("快捷创建成功"); this.getTaskList(); @@ -757,6 +801,43 @@ export default { this.selectedEnterCoilNos.splice(index, 1); this.taskForm.enterCoilNos = this.selectedEnterCoilNos.join(','); }, + querySupplierCoilNo(queryString, cb) { + if (!queryString || queryString.length < 2) { + cb([]); + return; + } + this.supplierCoilNoLoading = true; + listMaterialCoil({ + supplierCoilNo: queryString, + pageNum: 1, + pageSize: 20 + }).then(response => { + const options = (response.rows || []).map(item => ({ + value: item.supplierCoilNo, + label: item.supplierCoilNo, + enterCoilNo: item.enterCoilNo + })).filter(opt => !this.selectedSupplierCoilNos.includes(opt.value)); + cb(options); + }).finally(() => { + this.supplierCoilNoLoading = false; + }); + }, + handleSelectSupplierCoilNo(item) { + if (!this.selectedSupplierCoilNos.includes(item.value)) { + this.selectedSupplierCoilNos.push(item.value); + } + this.taskForm.supplierCoilNos = this.selectedSupplierCoilNos.join(','); + if (item.enterCoilNo && !this.selectedEnterCoilNos.includes(item.enterCoilNo)) { + this.selectedEnterCoilNos.push(item.enterCoilNo); + this.taskForm.enterCoilNos = this.selectedEnterCoilNos.join(','); + this.$refs["taskForm"].validateField('enterCoilNos'); + } + this.tempSupplierCoilNo = ''; + }, + removeSupplierCoilNo(index) { + this.selectedSupplierCoilNos.splice(index, 1); + this.taskForm.supplierCoilNos = this.selectedSupplierCoilNos.join(','); + }, cancelTask() { this.taskOpen = false; this.resetTaskForm(); @@ -787,6 +868,8 @@ export default { this.taskCoilList = []; this.selectedEnterCoilNos = []; this.tempEnterCoilNo = ''; + this.selectedSupplierCoilNos = []; + this.tempSupplierCoilNo = ''; this.resetForm("taskForm"); },