From 9a58fa2b30595fc29d86dd8cf6098fb491cad9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Tue, 19 May 2026 15:39:53 +0800 Subject: [PATCH 1/7] =?UTF-8?q?fix(wms/coil):=20=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E5=BE=85=E6=93=8D=E4=BD=9C=E5=88=97=E8=A1=A8=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E6=A0=87=E8=AE=B0=E9=80=BB=E8=BE=91=E5=B9=B6=E4=BC=A0=E9=80=92?= =?UTF-8?q?actionId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 临时注释了根据actionId完成待操作任务的代码,同时在调用接口时传入当前actionId参数 --- klp-ui/src/views/wms/coil/split.vue | 8 ++++---- klp-ui/src/views/wms/coil/typing.vue | 10 ++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/klp-ui/src/views/wms/coil/split.vue b/klp-ui/src/views/wms/coil/split.vue index e3a6713d..2775ba04 100644 --- a/klp-ui/src/views/wms/coil/split.vue +++ b/klp-ui/src/views/wms/coil/split.vue @@ -680,7 +680,7 @@ export default { })) }; - const response = await splitMaterialCoil(splitData); + const response = await splitMaterialCoil({ ...splitData, actionId: this.actionId }); if (response.code === 200) { this.$message.success('分条保存成功'); @@ -698,9 +698,9 @@ export default { })); // 如果是从待操作列表进来的,标记操作为完成 - if (this.actionId) { - await completeAction(this.actionId, response.msg); - } + // if (this.actionId) { + // await completeAction(this.actionId, response.msg); + // } // 延迟返回,让用户看到成功提示 setTimeout(() => { diff --git a/klp-ui/src/views/wms/coil/typing.vue b/klp-ui/src/views/wms/coil/typing.vue index 34c30e14..683c8f97 100644 --- a/klp-ui/src/views/wms/coil/typing.vue +++ b/klp-ui/src/views/wms/coil/typing.vue @@ -686,7 +686,7 @@ export default { abnormals: this.abnormals, }; - const response = await updateMaterialCoil(updateData); + const response = await updateMaterialCoil({ ...updateData, actionId: this.actionId }); // 更新完成后如果选定了合同,需要增加与合同的绑定关系 const coilId = response.msg; @@ -701,11 +701,9 @@ export default { this.$message.success('钢卷信息更新成功'); // 如果是从待操作列表进来的,标记操作为完成 - if (this.actionId) { - await completeAction(this.actionId, response.msg); - } - - + // if (this.actionId) { + // await completeAction(this.actionId, response.msg); + // } // 延迟返回 setTimeout(() => { From 6343f66ff725e7fc9f47abfb9f9ee2dbcc5ba8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Tue, 19 May 2026 16:25:47 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat(wms/coil/do/split):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E9=95=80=E9=94=8C=E5=BE=85=E6=89=93=E5=8C=85=E4=BB=93?= =?UTF-8?q?=E5=BA=93=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- klp-ui/src/views/wms/coil/do/split.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/klp-ui/src/views/wms/coil/do/split.vue b/klp-ui/src/views/wms/coil/do/split.vue index 9c2387c8..fd534c40 100644 --- a/klp-ui/src/views/wms/coil/do/split.vue +++ b/klp-ui/src/views/wms/coil/do/split.vue @@ -33,6 +33,7 @@ {value: '1988150263284953089', label: '镀锌原料库'}, {value: '1988150323162836993', label: '镀锌成品库'}, {value: '1988150487185289217', label: '镀锌纵剪分条原料库'}, + {value: '2056545127927787522', label: '镀锌待打包'} ], '脱脂工序': [ {value: '1988150545175736322', label: '脱脂原料库'}, From df25151fa5d14edcdcb86e73ea089751f2280bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Tue, 19 May 2026 16:26:23 +0800 Subject: [PATCH 3/7] =?UTF-8?q?style(wms/waybill):=20=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81=E6=8D=A2=E8=A1=8C=E4=B8=8E=E7=BC=A9?= =?UTF-8?q?=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复多处代码行过长导致的可读性问题,调整长属性和标签的换行格式,同时补充打印前检查发货单非空的逻辑 --- .../src/views/wms/delivery/waybill/index.vue | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/klp-ui/src/views/wms/delivery/waybill/index.vue b/klp-ui/src/views/wms/delivery/waybill/index.vue index 22acffa5..ece8ba29 100644 --- a/klp-ui/src/views/wms/delivery/waybill/index.vue +++ b/klp-ui/src/views/wms/delivery/waybill/index.vue @@ -26,8 +26,8 @@
- + @@ -55,7 +55,7 @@ - + 搜索 重置 @@ -113,7 +113,8 @@ @@ -190,8 +192,10 @@ - - + + @@ -642,18 +646,24 @@ export default { handlePrint(row, printType) { this.loading = true; this.printType = printType || 0; - updateDeliveryWaybill({ - waybillId: row.waybillId, - status: 2 - }).then(() => { - row.status = 2; - }); // 获取发货单明细 listDeliveryWaybillDetail({ waybillId: row.waybillId, pageNum: 1, pageSize: 1000 // 获取所有明细 }).then(response => { + // 该发货单不能是空的 + if (response.rows.length === 0) { + this.$modal.msgError("发货单为空不能打印"); + this.loading = false; + return; + } + updateDeliveryWaybill({ + waybillId: row.waybillId, + status: 2 + }).then(() => { + row.status = 2; + }); // 处理字段映射,确保与wayBill组件使用的字段名一致 this.currentWaybillDetails = response.rows.map(item => ({ coilId: item.coilId, From 4a8fc4904ff7baab45728af9e8a7159949b9198f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Tue, 19 May 2026 16:42:16 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat(wms-report):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=93=81=E8=B4=A8=E7=AD=9B=E9=80=89=E6=9D=A1=E4=BB=B6=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E6=9F=A5=E8=AF=A2=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 多个报表页面新增品质筛选下拉选择器 2. 统一添加coil_quality_status字典依赖 3. 替换部分旧的逻辑库位选择组件为warehouse-select 4. 调整部分表单字段的prop属性和代码格式 --- klp-ui/src/views/wms/report/abnormal.vue | 12 +++++++++--- klp-ui/src/views/wms/report/delivery.vue | 16 +++++++--------- klp-ui/src/views/wms/report/receive.vue | 18 ++++++++++++------ .../src/views/wms/report/template/action.vue | 17 ++++++++++++----- .../wms/report/template/comprehensive.vue | 15 ++++++++++----- klp-ui/src/views/wms/report/template/day.vue | 11 ++++++++++- klp-ui/src/views/wms/report/template/loss.vue | 6 +++++- klp-ui/src/views/wms/report/template/mands.vue | 13 ++++++++++--- klp-ui/src/views/wms/report/template/merge.vue | 6 +++++- klp-ui/src/views/wms/report/template/month.vue | 16 ++++++++++------ klp-ui/src/views/wms/report/template/out.vue | 12 ++++++++++-- klp-ui/src/views/wms/report/template/team.vue | 12 ++++++++++-- klp-ui/src/views/wms/report/template/year.vue | 12 ++++++++++-- 13 files changed, 120 insertions(+), 46 deletions(-) diff --git a/klp-ui/src/views/wms/report/abnormal.vue b/klp-ui/src/views/wms/report/abnormal.vue index f36081df..24d5a068 100644 --- a/klp-ui/src/views/wms/report/abnormal.vue +++ b/klp-ui/src/views/wms/report/abnormal.vue @@ -37,6 +37,10 @@ + + + @@ -99,14 +103,16 @@ @@ -147,7 +153,7 @@ export default { ColumnsSetting, TimeRangePicker }, - dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'], + dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status'], data() { // 工具函数:个位数补零 const addZero = (num) => num.toString().padStart(2, '0') diff --git a/klp-ui/src/views/wms/report/delivery.vue b/klp-ui/src/views/wms/report/delivery.vue index fd892589..d3fb6ba6 100644 --- a/klp-ui/src/views/wms/report/delivery.vue +++ b/klp-ui/src/views/wms/report/delivery.vue @@ -3,14 +3,8 @@ - + + + + 查询 导出 @@ -93,7 +91,7 @@ export default { CoilTable, TimeRangePicker, }, - dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'], + dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status'], data() { // 工具函数:个位数补零,保证格式统一(比如 9 → 09,5 → 05) const addZero = (num) => num.toString().padStart(2, '0') diff --git a/klp-ui/src/views/wms/report/receive.vue b/klp-ui/src/views/wms/report/receive.vue index eb7b3006..4d48bf4b 100644 --- a/klp-ui/src/views/wms/report/receive.vue +++ b/klp-ui/src/views/wms/report/receive.vue @@ -20,26 +20,32 @@ - + - + - + - + - + + + + + + @@ -115,7 +121,7 @@ export default { HierarchicalPivot, CrossTable, }, - dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'], + dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status'], data() { // 工具函数:个位数补零,保证格式统一(比如 9 → 09,5 → 05) const addZero = (num) => num.toString().padStart(2, '0') diff --git a/klp-ui/src/views/wms/report/template/action.vue b/klp-ui/src/views/wms/report/template/action.vue index e010e378..38bc67ba 100644 --- a/klp-ui/src/views/wms/report/template/action.vue +++ b/klp-ui/src/views/wms/report/template/action.vue @@ -71,12 +71,19 @@ - - + + + + + 查询 @@ -219,7 +226,7 @@ export default { name: 'MergeTemplate', props: { actionType: { - type: Number, + type: [Number, String], required: true }, productionLine: { @@ -246,7 +253,7 @@ export default { ColumnsSetting, TimeRangePicker }, - dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'], + dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status'], data() { // 工具函数:个位数补零 const addZero = (num) => num.toString().padStart(2, '0') @@ -466,7 +473,7 @@ export default { this.loading = true; // 所有报表类型都使用原始的 listPendingAction 方式获取数据 - const res = await listPendingAction({ ...this.queryParams, actionType: this.actionType, actionStatus: 2 }); + const res = await listPendingAction({ ...this.queryParams, actionTypes: this.actionType, actionStatus: 2 }); // 获取两层数据 const lossIds = res.rows.filter(item => item.coilId).map(item => item.coilId); const lossActionIds = res.rows.filter(item => item.actionId).map(item => item.actionId); diff --git a/klp-ui/src/views/wms/report/template/comprehensive.vue b/klp-ui/src/views/wms/report/template/comprehensive.vue index d2b61d38..1a0abdd6 100644 --- a/klp-ui/src/views/wms/report/template/comprehensive.vue +++ b/klp-ui/src/views/wms/report/template/comprehensive.vue @@ -2,8 +2,6 @@
- - 日视图 月视图 @@ -42,10 +40,14 @@ - + + + + + + 查询 导出产出钢卷 @@ -86,7 +92,6 @@ {{ summary.countDiff }}(昨日: {{ yesterdaySummary.countDiff }}) {{ summary.weightDiff }}(昨日: {{ yesterdaySummary.weightDiff }}) {{ summary.avgWeightDiff }}t(昨日: {{ yesterdaySummary.avgWeightDiff }}t) - {{ summary.passRate }}(昨日: {{ yesterdaySummary.passRate }}) @@ -216,7 +221,7 @@ export default { default: '', }, }, - dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'], + dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status'], data() { // 工具函数:个位数补零 const addZero = (num) => num.toString().padStart(2, '0') diff --git a/klp-ui/src/views/wms/report/template/day.vue b/klp-ui/src/views/wms/report/template/day.vue index c9843b98..d123de91 100644 --- a/klp-ui/src/views/wms/report/template/day.vue +++ b/klp-ui/src/views/wms/report/template/day.vue @@ -14,10 +14,14 @@ - + + + + + + 查询 导出产出钢卷 @@ -153,6 +161,7 @@ export default { CoilTable, SplitSummary, }, + dicts: ['coil_quality_status'], props: { actionTypes: { type: Array, diff --git a/klp-ui/src/views/wms/report/template/loss.vue b/klp-ui/src/views/wms/report/template/loss.vue index f7601cc3..7f3bba64 100644 --- a/klp-ui/src/views/wms/report/template/loss.vue +++ b/klp-ui/src/views/wms/report/template/loss.vue @@ -40,6 +40,10 @@ + + + 查询 导出 @@ -111,7 +115,7 @@ export default { default: '', }, }, - dicts: ['coil_material', 'coil_manufacturer'], + dicts: ['coil_quality_status'], data() { // 工具函数:个位数补零,保证格式统一(比如 9 → 09,5 → 05) const addZero = (num) => num.toString().padStart(2, '0') diff --git a/klp-ui/src/views/wms/report/template/mands.vue b/klp-ui/src/views/wms/report/template/mands.vue index ce4a55f9..15e11a3c 100644 --- a/klp-ui/src/views/wms/report/template/mands.vue +++ b/klp-ui/src/views/wms/report/template/mands.vue @@ -42,10 +42,14 @@ - + + + + + + 查询 导出产出钢卷 @@ -163,7 +171,6 @@ + + diff --git a/klp-ui/src/views/micro/pages/dr/components/Plan.vue b/klp-ui/src/views/micro/pages/dr/components/Plan.vue new file mode 100644 index 00000000..46e56f0b --- /dev/null +++ b/klp-ui/src/views/micro/pages/dr/components/Plan.vue @@ -0,0 +1,516 @@ + + + + + diff --git a/klp-ui/src/views/micro/pages/dr/components/ProcessSpec.vue b/klp-ui/src/views/micro/pages/dr/components/ProcessSpec.vue new file mode 100644 index 00000000..cd68086f --- /dev/null +++ b/klp-ui/src/views/micro/pages/dr/components/ProcessSpec.vue @@ -0,0 +1,485 @@ + + + + + diff --git a/klp-ui/src/views/micro/pages/dr/index.vue b/klp-ui/src/views/micro/pages/dr/index.vue new file mode 100644 index 00000000..acbf332f --- /dev/null +++ b/klp-ui/src/views/micro/pages/dr/index.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/klp-ui/src/views/timing/acid/rollConfig.vue b/klp-ui/src/views/timing/acid/rollConfig.vue new file mode 100644 index 00000000..3ce9290f --- /dev/null +++ b/klp-ui/src/views/timing/acid/rollConfig.vue @@ -0,0 +1,355 @@ + + + + + diff --git a/klp-ui/src/views/timing/acid/rollHistory.vue b/klp-ui/src/views/timing/acid/rollHistory.vue new file mode 100644 index 00000000..c00b93f1 --- /dev/null +++ b/klp-ui/src/views/timing/acid/rollHistory.vue @@ -0,0 +1,273 @@ + + + + + diff --git a/klp-ui/src/views/wms/coil/do/dr-normal.vue b/klp-ui/src/views/wms/coil/do/dr-normal.vue new file mode 100644 index 00000000..874dc0b0 --- /dev/null +++ b/klp-ui/src/views/wms/coil/do/dr-normal.vue @@ -0,0 +1,243 @@ + + + + + diff --git a/klp-ui/src/views/wms/coil/do/dr-repair.vue b/klp-ui/src/views/wms/coil/do/dr-repair.vue new file mode 100644 index 00000000..3c1bf4a1 --- /dev/null +++ b/klp-ui/src/views/wms/coil/do/dr-repair.vue @@ -0,0 +1,231 @@ + + + + + diff --git a/klp-ui/src/views/wms/coil/panels/DrMatchPanel.vue b/klp-ui/src/views/wms/coil/panels/DrMatchPanel.vue new file mode 100644 index 00000000..4646b7ce --- /dev/null +++ b/klp-ui/src/views/wms/coil/panels/DrMatchPanel.vue @@ -0,0 +1,213 @@ + + + + + diff --git a/klp-ui/src/views/wms/coil/typing.vue b/klp-ui/src/views/wms/coil/typing.vue index 683c8f97..2eff8fe2 100644 --- a/klp-ui/src/views/wms/coil/typing.vue +++ b/klp-ui/src/views/wms/coil/typing.vue @@ -7,7 +7,7 @@ 钢卷信息更新
- +
--> @@ -26,9 +26,10 @@
- +
- + +
@@ -326,7 +327,8 @@ import AbnormalForm from './components/AbnormalForm'; import { generateCoilNoPrefix } from "@/utils/coil/coilNo"; import { addCoilContractRel } from "@/api/wms/coilContractRel"; import ContractSelect from "@/components/KLPService/ContractSelect"; -import L2MatchPanel from './panels/L2MatchPanel.vue'; +import L2MatchPanel from './panels/L2MatchPanel.vue' +import DrMatchPanel from './panels/DrMatchPanel.vue'; export default { @@ -340,6 +342,7 @@ export default { AbnormalForm, ContractSelect, L2MatchPanel, + DrMatchPanel, }, dicts: ['coil_quality_status', 'coil_abnormal_position', 'coil_abnormal_code', 'coil_abnormal_degree', 'coil_business_purpose'], data() { @@ -429,6 +432,7 @@ export default { ], }, actionId: null, + actionType: null, // 待操作类型,504/524 = 双机架 acidPrefill: { visible: false, type: 'info', @@ -462,6 +466,10 @@ export default { l2HotCoilId() { return (this.currentInfo && this.currentInfo.enterCoilNo) || '' }, + /** 是否双机架工序(actionType 504=正常 / 524=修复) */ + isDrAction() { + return this.actionType === 504 || this.actionType === 524 + }, // 动态显示标签 getItemLabel() { if (this.updateForm.materialType === '成品') { @@ -490,6 +498,11 @@ export default { // 填写生产开始时间 this.$set(this.updateForm, 'productionStartTime', pendingActionRes.data.createTime) + // 记录操作类型(用于判断是否双机架工序) + if (pendingActionRes.data && pendingActionRes.data.actionType != null) { + this.actionType = pendingActionRes.data.actionType + } + if (coilId) { await this.loadCoilInfo(coilId); } @@ -523,6 +536,20 @@ export default { } }, methods: { + /** 双机架计划/道次快捷写入 */ + applyDrFill(data) { + if (data.outThick != null) this.$set(this.updateForm, 'actualThickness', parseFloat(data.outThick)) + if (data.inMatWidth != null) this.$set(this.updateForm, 'actualWidth', parseFloat(data.inMatWidth)) + if (data.inMatWeight != null) { + this.$set(this.updateForm, 'netWeight', parseFloat(data.inMatWeight)) + this.$set(this.updateForm, 'grossWeight', parseFloat(data.inMatWeight)) + } + if (data.inMatLength != null) { + this.$set(this.updateForm, 'actualLength', parseFloat(data.inMatLength)) + this.$set(this.updateForm, 'length', parseFloat(data.inMatLength)) + } + }, + applyL2Fill(data) { if (data.entry_weight != null) { const w = parseFloat(data.entry_weight) diff --git a/klp-ui/src/views/wms/mill/dr-plan.vue b/klp-ui/src/views/wms/mill/dr-plan.vue new file mode 100644 index 00000000..b3f06c84 --- /dev/null +++ b/klp-ui/src/views/wms/mill/dr-plan.vue @@ -0,0 +1,385 @@ + + + + + diff --git a/klp-ui/src/views/wms/mill/dr-process.vue b/klp-ui/src/views/wms/mill/dr-process.vue new file mode 100644 index 00000000..357981d4 --- /dev/null +++ b/klp-ui/src/views/wms/mill/dr-process.vue @@ -0,0 +1,461 @@ + + + + + diff --git a/klp-ui/src/views/wms/processSpec/planSpec.vue b/klp-ui/src/views/wms/processSpec/planSpec.vue index 25035a53..51228f16 100644 --- a/klp-ui/src/views/wms/processSpec/planSpec.vue +++ b/klp-ui/src/views/wms/processSpec/planSpec.vue @@ -65,7 +65,7 @@ /> - 点位名称: + 参数名称: 新建参数 + 新建方案点位 + >管理点位 模板导入
- + - - - - - - - + + + + + + + + + + + + + - - -
@@ -361,6 +274,16 @@ + + + + + @@ -488,7 +411,7 @@ const TEMPLATE_HEADERS = ['段类型', '段名称', '点位名称', '参数名 /** 表头字段映射 */ const HEADER_MAP = { '段类型': 'segmentType', - '段名称': 'segmentName', + '段名称': 'segmentName', '点位名称': 'pointName', '参数名称': 'paramName', '设定值': 'targetValue', @@ -514,9 +437,8 @@ export default { appliedFilterName: '', planList: [], planLoading: false, - selectedPlan: null, - paramList: [], - paramLoading: false, + allParamList: [], + allParamLoading: false, planOpen: false, planTitle: '', planSubmitLoading: false, @@ -531,6 +453,7 @@ export default { paramSubmitLoading: false, paramForm: {}, paramRules: { + planId: [{ required: true, message: '请选择所属点位', trigger: 'change' }], paramCode: [{ required: true, message: '参数编码不能为空', trigger: 'blur' }], paramName: [{ required: true, message: '参数名称不能为空', trigger: 'blur' }] }, @@ -632,12 +555,6 @@ export default { extra.sort((a, b) => String(a.label).localeCompare(String(b.label), 'zh-CN')) return [...SEGMENT_FORM_OPTIONS, ...extra] }, - /** 当前选中点位下的异常条目 */ - planAnomalies() { - if (!this.selectedPlan) return [] - return this.allAnomalies.filter(a => a.paramCode === this.selectedPlan.pointCode || - this.paramList.some(p => p.paramCode === a.paramCode)) - }, /** paramCode → anomaly 的快速索引(用于状态列) */ paramAnomalyMap() { const map = {} @@ -648,45 +565,42 @@ export default { if (!this.coilAnomalyCoilId) return [] return this.allAnomalies.filter(a => a.coilId === this.coilAnomalyCoilId) }, - filteredPlans() { + /** 所有 plan 的参数平铺成一行,带 plan 的段/点位信息 */ + flatRows() { + const SEG_LABELS = { INLET: '入口段', PROCESS: '工艺段', OUTLET: '出口段' } + const planMap = {} + for (const plan of this.planList) planMap[plan.planId] = plan + const rows = [] + for (const param of this.allParamList) { + const plan = planMap[param.planId] + if (!plan) continue + rows.push({ + ...param, + _planId: plan.planId, + _segmentType: plan.segmentType, + _segmentLabel: SEG_LABELS[plan.segmentType] || plan.segmentName || plan.segmentType, + _pointName: plan.pointName, + _sortOrder: plan.sortOrder || 0 + }) + } + rows.sort((a, b) => { + const s = (a._sortOrder || 0) - (b._sortOrder || 0) + return s !== 0 ? s : (a.paramId || 0) - (b.paramId || 0) + }) + return rows + }, + filteredFlatRows() { const type = this.activeSegmentType - const sub = this.activeSegmentName - return this.planList.filter(p => { - const typeOk = - type === '' || type === undefined || type === null - ? true - : String(p.segmentType) === String(type) - let nameOkSeg = true - if (typeOk && type !== '' && type !== undefined && type !== null) { - if (sub === '' || sub === undefined || sub === null) { - nameOkSeg = true - } else if (sub === '__EMPTY__') { - const sn = p.segmentName != null ? String(p.segmentName).trim() : '' - nameOkSeg = !sn - } else { - const sn = p.segmentName != null ? String(p.segmentName).trim() : '' - nameOkSeg = sn === String(sub).trim() - } - } - const nameOk = !this.appliedFilterName || (p.pointName || '').includes(this.appliedFilterName) - return typeOk && nameOkSeg && nameOk + const name = this.appliedFilterName + return this.flatRows.filter(r => { + const typeOk = !type || String(r._segmentType) === String(type) + const nameOk = !name || (r.paramName || '').includes(name) || (r.paramCode || '').includes(name) + return typeOk && nameOk }) } }, watch: { $route: { immediate: true, handler() { this.syncFromRoute() } }, - planAnomalies: { - handler(list) { - if (list.length && this.anomalyExpanded) { - this.$nextTick(() => this.renderAnomalyChart()) - } - } - }, - anomalyExpanded(val) { - if (val && this.planAnomalies.length) { - this.$nextTick(() => this.renderAnomalyChart()) - } - }, segmentTypeTabOptions: { handler() { const a = this.activeSegmentType @@ -852,22 +766,26 @@ export default { }, loadPlans() { this.planLoading = true - this.selectedPlan = null - this.paramList = [] listProcessPlan({ versionId: this.versionId, pageNum: 1, pageSize: 500 }).then(res => { this.planList = res.rows || [] + this.loadAllParams() }).catch(e => console.error(e)).finally(() => { this.planLoading = false }) }, - loadParams(planId) { - this.paramLoading = true - listProcessPlanParam({ planId, pageNum: 1, pageSize: 500 }).then(res => { - this.paramList = res.rows || [] - }).catch(e => console.error(e)).finally(() => { this.paramLoading = false }) - }, - onPlanSelect(row) { - if (!row) return - this.selectedPlan = row - this.loadParams(row.planId) + async loadAllParams() { + if (!this.planList.length) { this.allParamList = []; return } + this.allParamLoading = true + try { + const results = await Promise.all( + this.planList.map(plan => + listProcessPlanParam({ planId: plan.planId, pageNum: 1, pageSize: 500 }) + .then(res => res.rows || []) + .catch(() => []) + ) + ) + this.allParamList = results.flat() + } finally { + this.allParamLoading = false + } }, applyFilter() { this.appliedFilterName = this.filterName }, resetFilter() { @@ -921,28 +839,33 @@ export default { }).catch(() => {}) }, openParamDialog(planRow, paramRow) { - const targetPlan = planRow || this.selectedPlan - if (!targetPlan) { this.$message.warning('请先选择一个方案点位'); return } - if (!this.selectedPlan || this.selectedPlan.planId !== targetPlan.planId) { - this.selectedPlan = targetPlan - this.loadParams(targetPlan.planId) - } this.paramForm = paramRow ? { ...paramRow } : { - planId: targetPlan.planId, - paramCode: undefined, - paramName: undefined, + planId: planRow ? planRow.planId : undefined, + paramCode: undefined, + paramName: undefined, targetValue: undefined, - lowerLimit: undefined, - upperLimit: undefined, - unit: undefined, - remark: undefined + lowerLimit: undefined, + upperLimit: undefined, + unit: undefined, + remark: undefined } this.paramTitle = paramRow ? '编辑方案参数' : '新建方案参数' this.paramOpen = true this.$nextTick(() => this.$refs.paramFormRef && this.$refs.paramFormRef.clearValidate()) }, + editParamFromFlat(row) { + this.openParamDialog(null, row) + }, + deleteParamFromFlat(row) { + this.$modal.confirm('确认删除该参数?').then(() => { + return delProcessPlanParam(row.paramId) + }).then(() => { + this.$modal.msgSuccess('删除成功') + this.loadAllParams() + }).catch(() => {}) + }, submitParam() { this.$refs.paramFormRef.validate(ok => { if (!ok) return @@ -951,18 +874,10 @@ export default { req.then(() => { this.$modal.msgSuccess('保存成功') this.paramOpen = false - this.loadParams(this.selectedPlan.planId) + this.loadAllParams() }).catch(e => console.error(e)).finally(() => { this.paramSubmitLoading = false }) }) }, - removeParam(row) { - this.$modal.confirm('确认删除该参数?').then(() => { - return delProcessPlanParam(row.paramId) - }).then(() => { - this.$modal.msgSuccess('删除成功') - this.loadParams(this.selectedPlan.planId) - }).catch(() => {}) - }, // ===================== 导入相关方法 ===================== /** * 打开导入对话框 @@ -1218,7 +1133,7 @@ export default { async batchImport() { // �照点位名称分组,每个点位创建一条记录,然后添加多个参数 const pointGroups = {} - + // 分组处理 this.tableData.forEach(row => { const pointKey = `${row.segmentType}_${row.segmentName}_${row.pointName}` @@ -1249,12 +1164,12 @@ export default { try { await this.importOnePoint(group) this.importedCount += group.params.length - + // 更新进度 index += group.params.length const currentProgress = Math.round((index / this.totalCount) * 100) this.progress = currentProgress - + await new Promise(resolve => setTimeout(resolve, 50)) } catch (error) { throw new Error(`导入点位"${group.pointName}"失败:${error.message}`) @@ -1275,7 +1190,7 @@ export default { pointCode: group.pointCode, sortOrder: 0 } - + const planRes = await addProcessPlan(planParams) if (planRes.code !== 200) { throw new Error(`点位创建失败:${planRes.msg || '接口返回异常'}`) @@ -1293,7 +1208,7 @@ export default { lowerLimit: param.lowerLimit ? Number(param.lowerLimit) : null, unit: param.unit } - + const paramRes = await addProcessPlanParam(paramParams) if (paramRes.code !== 200) { throw new Error(`参数"${param.paramName}"创建失败:${paramRes.msg || '接口返回异常'}`) @@ -1354,7 +1269,7 @@ export default { // 创建工作簿 const wb = XLSX.utils.book_new() const ws = XLSX.utils.aoa_to_sheet(templateData) - + // 设置列宽 ws['!cols'] = [ { wch: 10 }, // 段类型 @@ -1366,7 +1281,7 @@ export default { { wch: 10 }, // 下限 { wch: 10 } // 单位 ] - + XLSX.utils.book_append_sheet(wb, ws, '导入模板') XLSX.writeFile(wb, '方案点位导入模板.xlsx') }, @@ -1558,6 +1473,19 @@ export default { .btn-danger { color: #f56c6c; } +/* ── 段 chip ── */ +.seg-chip { + display: inline-block; + padding: 2px 7px; + border-radius: 10px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; +} +.seg-inlet { background: #ecf5ff; color: #3a6ea8; border: 1px solid #b3d8ff; } +.seg-process { background: #f0f9eb; color: #3a7a2a; border: 1px solid #b3e19d; } +.seg-outlet { background: #fdf6ec; color: #a86a00; border: 1px solid #f5dab1; } + /* ── 偏差分析 ── */ .anomaly-section-header { display: flex; diff --git a/klp-wms/src/main/java/com/klp/controller/DrMillProcessRecipeController.java b/klp-wms/src/main/java/com/klp/controller/DrMillProcessRecipeController.java new file mode 100644 index 00000000..b39ef854 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/controller/DrMillProcessRecipeController.java @@ -0,0 +1,94 @@ +package com.klp.controller; + +import com.klp.common.core.controller.BaseController; +import com.klp.common.core.domain.R; +import com.klp.domain.DrMillProcessRecipe; +import com.klp.domain.DrMillProcessRecipeVersion; +import com.klp.service.IDrMillProcessRecipeService; +import com.klp.service.IDrMillProcessRecipeVersionService; +import com.klp.service.impl.DrRecipeSyncService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/dr/mill/recipe") +public class DrMillProcessRecipeController extends BaseController { + + private final IDrMillProcessRecipeService recipeService; + private final IDrMillProcessRecipeVersionService versionService; + private final DrRecipeSyncService syncService; + + // ─── 方案 ──────────────────────────────────────────────── + + @GetMapping("/list") + public R> list(DrMillProcessRecipe query) { + List list = recipeService.selectList(query); + // 每次查询时补齐缺失的 L3 工艺规程(幂等,已存在则跳过) + syncService.syncRecipesToSpec(list); + return R.ok(list); + } + + @GetMapping("/{id}") + public R detail(@PathVariable Long id) { + return R.ok(recipeService.selectDetailById(id)); + } + + @PostMapping + public R add(@RequestBody DrMillProcessRecipe recipe) { + recipeService.save(recipe); + // 新增方案后立即同步 L3 工艺规程 + syncService.syncRecipesToSpec(Collections.singletonList(recipe)); + return R.ok(recipe.getRecipeId()); + } + + @PutMapping + public R edit(@RequestBody DrMillProcessRecipe recipe) { + recipeService.update(recipe); + return R.ok(); + } + + @DeleteMapping("/{ids}") + public R remove(@PathVariable Long[] ids) { + recipeService.deleteByIds(ids); + return R.ok(); + } + + // ─── 版本 ──────────────────────────────────────────────── + + @GetMapping("/version/list/{recipeId}") + public R> versionList(@PathVariable Long recipeId) { + return R.ok(versionService.listByRecipeId(recipeId)); + } + + @GetMapping("/version/{versionId}") + public R versionDetail(@PathVariable Long versionId) { + return R.ok(versionService.getDetailById(versionId)); + } + + @PostMapping("/version") + public R addVersion(@RequestBody DrMillProcessRecipeVersion version) { + return R.ok(versionService.save(version)); + } + + @PutMapping("/version") + public R editVersion(@RequestBody DrMillProcessRecipeVersion version) { + versionService.update(version); + return R.ok(); + } + + @PutMapping("/version/activate/{versionId}") + public R activate(@PathVariable Long versionId) { + versionService.activate(versionId); + return R.ok(); + } + + @DeleteMapping("/version/{versionId}") + public R deleteVersion(@PathVariable Long versionId) { + versionService.deleteById(versionId); + return R.ok(); + } +} diff --git a/klp-wms/src/main/java/com/klp/controller/DrMillProductionPlanController.java b/klp-wms/src/main/java/com/klp/controller/DrMillProductionPlanController.java new file mode 100644 index 00000000..e3a2ace9 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/controller/DrMillProductionPlanController.java @@ -0,0 +1,83 @@ +package com.klp.controller; + +import com.klp.common.core.controller.BaseController; +import com.klp.common.core.domain.R; +import com.klp.common.core.page.TableDataInfo; +import com.klp.domain.DrMillProductionPlan; +import com.klp.service.IDrMillProductionPlanService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 双机架生产计划管理 + */ +@RequiredArgsConstructor +@RestController +@RequestMapping("/dr/mill/plan") +public class DrMillProductionPlanController extends BaseController { + + private final IDrMillProductionPlanService planService; + + @GetMapping("/list") + public R> list(DrMillProductionPlan query) { + return R.ok(planService.selectList(query)); + } + + /** 实绩分页查询(按创建时间倒序,支持卷号/状态/时间范围过滤) */ + @GetMapping("/actual/page") + public TableDataInfo actualPage(DrMillProductionPlan query) { + return planService.selectPageList(query); + } + + @GetMapping("/{id}") + public R detail(@PathVariable Long id) { + return R.ok(planService.selectById(id)); + } + + /** + * 通过待操作ID查询绑定计划(含道次),供录入页快捷写入 + * planNo = "DR" + actionId + */ + @GetMapping("/byAction/{actionId}") + public R getByActionId(@PathVariable Long actionId) { + return R.ok(planService.selectByActionId(actionId)); + } + + @PostMapping + public R add(@RequestBody DrMillProductionPlan plan) { + planService.insert(plan); + return R.ok(); + } + + @PutMapping + public R edit(@RequestBody DrMillProductionPlan plan) { + planService.update(plan); + return R.ok(); + } + + @DeleteMapping("/{id}") + public R remove(@PathVariable Long id) { + planService.deleteById(id); + return R.ok(); + } + + @PutMapping("/moveUp/{id}") + public R moveUp(@PathVariable Long id) { + planService.moveUp(id); + return R.ok(); + } + + @PutMapping("/moveDown/{id}") + public R moveDown(@PathVariable Long id) { + planService.moveDown(id); + return R.ok(); + } + + @PutMapping("/finish/{id}") + public R finish(@PathVariable Long id) { + planService.finish(id); + return R.ok(); + } +} diff --git a/klp-wms/src/main/java/com/klp/controller/WmsMaterialCoilController.java b/klp-wms/src/main/java/com/klp/controller/WmsMaterialCoilController.java index 3ebed3ce..6a3a21e1 100644 --- a/klp-wms/src/main/java/com/klp/controller/WmsMaterialCoilController.java +++ b/klp-wms/src/main/java/com/klp/controller/WmsMaterialCoilController.java @@ -616,6 +616,16 @@ public class WmsMaterialCoilController extends BaseController { } } + /** + * 根据入场钢卷号或当前钢卷号查询钢卷信息,供双机架计划绑定使用 + * + * @param coilNo 入场钢卷号或当前钢卷号 + */ + @GetMapping("/queryByCoilNo") + public R queryByCoilNo(@NotBlank(message = "钢卷号不能为空") @RequestParam String coilNo) { + return R.ok(iWmsMaterialCoilService.queryByCoilNo(coilNo)); + } + /** * 冷硬卷切边统计 diff --git a/klp-wms/src/main/java/com/klp/domain/DrMillProcessPass.java b/klp-wms/src/main/java/com/klp/domain/DrMillProcessPass.java new file mode 100644 index 00000000..e2a6abd5 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/DrMillProcessPass.java @@ -0,0 +1,33 @@ +package com.klp.domain; + +import lombok.Data; +import java.math.BigDecimal; +import java.util.Date; + +/** 双机架工艺方案道次(对应 double-rack.mill_process_pass) */ +@Data +public class DrMillProcessPass { + + private Long passId; + private Long recipeId; + /** 所属版本 ID */ + private Long versionId; + private Integer passNo; + private BigDecimal inThick; + private BigDecimal outThick; + private BigDecimal width; + private BigDecimal rollForce; + private BigDecimal inTension; + private BigDecimal outTension; + private BigDecimal maxSpeed; + private BigDecimal inUnitTension; + private BigDecimal outUnitTension; + private BigDecimal reduction; + private BigDecimal totalReduction; + private String delFlag; + private String createBy; + private Date createTime; + private String updateBy; + private Date updateTime; + private String remark; +} diff --git a/klp-wms/src/main/java/com/klp/domain/DrMillProcessRecipe.java b/klp-wms/src/main/java/com/klp/domain/DrMillProcessRecipe.java new file mode 100644 index 00000000..5e1630df --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/DrMillProcessRecipe.java @@ -0,0 +1,31 @@ +package com.klp.domain; + +import lombok.Data; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** 双机架工艺方案主表(对应 double-rack.mill_process_recipe) */ +@Data +public class DrMillProcessRecipe { + + private Long recipeId; + private String recipeNo; + private String alloyNo; + private Integer passCount; + private BigDecimal inThick; + private BigDecimal outThick; + private BigDecimal outWidth; + /** 0-正常 1-停用 */ + private String status; + /** 0-存在 2-删除 */ + private String delFlag; + private String createBy; + private Date createTime; + private String updateBy; + private Date updateTime; + private String remark; + + /** 关联道次(非数据库字段) */ + private List passList; +} diff --git a/klp-wms/src/main/java/com/klp/domain/DrMillProcessRecipeVersion.java b/klp-wms/src/main/java/com/klp/domain/DrMillProcessRecipeVersion.java new file mode 100644 index 00000000..b76c98fd --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/DrMillProcessRecipeVersion.java @@ -0,0 +1,28 @@ +package com.klp.domain; + +import lombok.Data; +import java.util.Date; +import java.util.List; + +/** 双机架工艺方案版本(double-rack.mill_process_recipe_version) */ +@Data +public class DrMillProcessRecipeVersion { + + private Long versionId; + private Long recipeId; + /** 版本号,如 V1.0 */ + private String versionCode; + /** 1=已激活 0=未激活 */ + private Integer isActive; + /** 0=草稿 1=已发布 */ + private String status; + private String createBy; + private Date createTime; + private String updateBy; + private Date updateTime; + private String remark; + private String delFlag; + + /** 关联道次(非数据库字段) */ + private List passList; +} diff --git a/klp-wms/src/main/java/com/klp/domain/DrMillProductionPlan.java b/klp-wms/src/main/java/com/klp/domain/DrMillProductionPlan.java new file mode 100644 index 00000000..da89344b --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/DrMillProductionPlan.java @@ -0,0 +1,66 @@ +package com.klp.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 双机架生产计划(对应 double-rack.mill_production_plan)。 + * enterCoilNo / currentCoilNo 用于绑定三级 WMS 钢卷数据。 + */ +@Data +public class DrMillProductionPlan { + + private Long planId; + private String planNo; + /** 0-待生产 1-生产中 2-完成 3-撤销 */ + private String planStatus; + /** Idle / Rolling / NextCoil / Done */ + private String prodStatus; + private Integer sortNo; + private String inMatNo; + private String alloyNo; + private BigDecimal inMatThick; + private BigDecimal inMatWidth; + private BigDecimal inMatWeight; + private BigDecimal inMatLength; + private BigDecimal inMatId; + private BigDecimal inMatOd; + private BigDecimal outThick; + private Integer passCount; + private Long recipeId; + private String recipeNo; + /** 绑定的工艺版本 ID */ + private Long versionId; + /** 关联三级 WMS 入场钢卷号 */ + private String enterCoilNo; + /** 关联三级 WMS 当前钢卷号 */ + private String currentCoilNo; + /** 绑定方案的道次列表(非DB字段,按需填充) */ + private List passList; + + private String delFlag; + private String createBy; + private Date createTime; + private String updateBy; + private Date updateTime; + private String remark; + + // ── 非 DB 查询字段(分页 + 时间范围) ────────────── + @TableField(exist = false) + private Integer pageNum; + @TableField(exist = false) + private Integer pageSize; + @TableField(exist = false) + private String createStartTime; + @TableField(exist = false) + private String createEndTime; + + public int getOffset() { + int num = (pageNum != null && pageNum > 0) ? pageNum : 1; + int size = (pageSize != null && pageSize > 0) ? pageSize : 50; + return (num - 1) * size; + } +} diff --git a/klp-wms/src/main/java/com/klp/mapper/DrMillProcessPassMapper.java b/klp-wms/src/main/java/com/klp/mapper/DrMillProcessPassMapper.java new file mode 100644 index 00000000..021afd2c --- /dev/null +++ b/klp-wms/src/main/java/com/klp/mapper/DrMillProcessPassMapper.java @@ -0,0 +1,21 @@ +package com.klp.mapper; + +import com.klp.domain.DrMillProcessPass; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface DrMillProcessPassMapper { + List selectByVersionId(Long versionId); + List selectByRecipeId(Long recipeId); + int insertBatch(List list); + int deleteByVersionId(Long versionId); + int deleteByRecipeId(Long recipeId); + /** 查出所有 version_id 为空的道次所属 recipe_id(去重) */ + List selectDistinctRecipeIdsWithOrphanPasses(); + /** 将指定方案下所有 version_id 为空的道次批量设置 version_id */ + int updateVersionIdForOrphans(@Param("recipeId") Long recipeId, + @Param("versionId") Long versionId); +} diff --git a/klp-wms/src/main/java/com/klp/mapper/DrMillProcessRecipeMapper.java b/klp-wms/src/main/java/com/klp/mapper/DrMillProcessRecipeMapper.java new file mode 100644 index 00000000..6851396f --- /dev/null +++ b/klp-wms/src/main/java/com/klp/mapper/DrMillProcessRecipeMapper.java @@ -0,0 +1,14 @@ +package com.klp.mapper; + +import com.klp.domain.DrMillProcessRecipe; +import org.apache.ibatis.annotations.Mapper; +import java.util.List; + +@Mapper +public interface DrMillProcessRecipeMapper { + List selectList(DrMillProcessRecipe query); + DrMillProcessRecipe selectById(Long recipeId); + int insert(DrMillProcessRecipe recipe); + int update(DrMillProcessRecipe recipe); + int deleteBatchByIds(Long[] ids); +} diff --git a/klp-wms/src/main/java/com/klp/mapper/DrMillProcessRecipeVersionMapper.java b/klp-wms/src/main/java/com/klp/mapper/DrMillProcessRecipeVersionMapper.java new file mode 100644 index 00000000..c7b59b71 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/mapper/DrMillProcessRecipeVersionMapper.java @@ -0,0 +1,24 @@ +package com.klp.mapper; + +import com.klp.domain.DrMillProcessRecipeVersion; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface DrMillProcessRecipeVersionMapper { + List selectByRecipeId(Long recipeId); + /** 查询指定方案已有的 V1.0 版本(用于迁移幂等判断) */ + DrMillProcessRecipeVersion selectV1ByRecipeId(@Param("recipeId") Long recipeId); + /** 查询指定方案当前激活版本 */ + DrMillProcessRecipeVersion selectActiveByRecipeId(@Param("recipeId") Long recipeId); + DrMillProcessRecipeVersion selectById(Long versionId); + int insert(DrMillProcessRecipeVersion version); + int update(DrMillProcessRecipeVersion version); + int deleteById(Long versionId); + int deleteByRecipeIds(@Param("ids") Long[] ids); + /** 将同方案其他版本置为未激活 */ + int deactivateOthers(@Param("recipeId") Long recipeId, @Param("versionId") Long versionId); + /** 激活指定版本 */ + int activate(Long versionId); +} diff --git a/klp-wms/src/main/java/com/klp/mapper/DrMillProductionPlanMapper.java b/klp-wms/src/main/java/com/klp/mapper/DrMillProductionPlanMapper.java new file mode 100644 index 00000000..e3b387d7 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/mapper/DrMillProductionPlanMapper.java @@ -0,0 +1,21 @@ +package com.klp.mapper; + +import com.klp.domain.DrMillProductionPlan; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface DrMillProductionPlanMapper { + List selectList(DrMillProductionPlan query); + /** 分页查询(配合 PageHelper 或手动 LIMIT/OFFSET) */ + List selectPageList(DrMillProductionPlan query); + long countPageList(DrMillProductionPlan query); + DrMillProductionPlan selectById(Long planId); + DrMillProductionPlan selectByPlanNo(@Param("planNo") String planNo); + int insert(DrMillProductionPlan plan); + int update(DrMillProductionPlan plan); + int deleteById(Long planId); + int updateSortNo(@Param("planId") Long planId, @Param("sortNo") int sortNo); + int countByStatus(@Param("status") String status); +} diff --git a/klp-wms/src/main/java/com/klp/service/IDrMillProcessRecipeService.java b/klp-wms/src/main/java/com/klp/service/IDrMillProcessRecipeService.java new file mode 100644 index 00000000..7af1bbb9 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/IDrMillProcessRecipeService.java @@ -0,0 +1,12 @@ +package com.klp.service; + +import com.klp.domain.DrMillProcessRecipe; +import java.util.List; + +public interface IDrMillProcessRecipeService { + List selectList(DrMillProcessRecipe query); + DrMillProcessRecipe selectDetailById(Long id); + int save(DrMillProcessRecipe recipe); + int update(DrMillProcessRecipe recipe); + int deleteByIds(Long[] ids); +} diff --git a/klp-wms/src/main/java/com/klp/service/IDrMillProcessRecipeVersionService.java b/klp-wms/src/main/java/com/klp/service/IDrMillProcessRecipeVersionService.java new file mode 100644 index 00000000..048f24eb --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/IDrMillProcessRecipeVersionService.java @@ -0,0 +1,13 @@ +package com.klp.service; + +import com.klp.domain.DrMillProcessRecipeVersion; +import java.util.List; + +public interface IDrMillProcessRecipeVersionService { + List listByRecipeId(Long recipeId); + DrMillProcessRecipeVersion getDetailById(Long versionId); + Long save(DrMillProcessRecipeVersion version); + void update(DrMillProcessRecipeVersion version); + void activate(Long versionId); + void deleteById(Long versionId); +} diff --git a/klp-wms/src/main/java/com/klp/service/IDrMillProductionPlanService.java b/klp-wms/src/main/java/com/klp/service/IDrMillProductionPlanService.java new file mode 100644 index 00000000..304cc756 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/IDrMillProductionPlanService.java @@ -0,0 +1,20 @@ +package com.klp.service; + +import com.klp.common.core.page.TableDataInfo; +import com.klp.domain.DrMillProductionPlan; +import java.util.List; + +public interface IDrMillProductionPlanService { + List selectList(DrMillProductionPlan query); + /** 分页查询实绩(按创建时间倒序) */ + TableDataInfo selectPageList(DrMillProductionPlan query); + DrMillProductionPlan selectById(Long id); + /** 通过待操作ID查计划(planNo = "DR" + actionId),并附带道次列表 */ + DrMillProductionPlan selectByActionId(Long actionId); + int insert(DrMillProductionPlan plan); + int update(DrMillProductionPlan plan); + int deleteById(Long id); + int moveUp(Long id); + int moveDown(Long id); + int finish(Long id); +} diff --git a/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java b/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java index 583716e2..ba5ad1cb 100644 --- a/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java +++ b/klp-wms/src/main/java/com/klp/service/IWmsMaterialCoilService.java @@ -349,5 +349,10 @@ public interface IWmsMaterialCoilService { * @param response HTTP响应对象 */ void exportAbnormalReport(WmsMaterialCoilBo bo, HttpServletResponse response); + + /** + * 根据入场钢卷号或当前钢卷号查询钢卷,供双机架计划绑定使用 + */ + com.klp.domain.vo.WmsMaterialCoilVo queryByCoilNo(String coilNo); } diff --git a/klp-wms/src/main/java/com/klp/service/impl/DrMigrationService.java b/klp-wms/src/main/java/com/klp/service/impl/DrMigrationService.java new file mode 100644 index 00000000..4b4ff8b8 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/impl/DrMigrationService.java @@ -0,0 +1,65 @@ +package com.klp.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.klp.domain.DrMillProcessRecipeVersion; +import com.klp.mapper.DrMillProcessPassMapper; +import com.klp.mapper.DrMillProcessRecipeVersionMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 双机架历史道次版本迁移 + * 将所有 version_id IS NULL 的道次归入对应方案的 V1.0 版本 + */ +@Slf4j +@DS("double-rack") +@RequiredArgsConstructor +@Service +public class DrMigrationService { + + private final DrMillProcessPassMapper passMapper; + private final DrMillProcessRecipeVersionMapper versionMapper; + + @Transactional(rollbackFor = Exception.class) + public void migrateOrphanPassesToV1() { + List recipeIds = passMapper.selectDistinctRecipeIdsWithOrphanPasses(); + if (recipeIds.isEmpty()) { + log.info("[DR迁移] 无需迁移:所有道次已绑定版本"); + return; + } + + int newVersionCount = 0; + int migratedPassCount = 0; + + for (Long recipeId : recipeIds) { + // 幂等:V1.0 已存在则复用,避免重复执行时重复创建 + DrMillProcessRecipeVersion v1 = versionMapper.selectV1ByRecipeId(recipeId); + if (v1 == null) { + v1 = new DrMillProcessRecipeVersion(); + v1.setRecipeId(recipeId); + v1.setVersionCode("V1.0"); + v1.setIsActive(1); // 默认激活 + v1.setStatus("1"); // 已发布 + v1.setCreateBy("system"); + v1.setUpdateBy("system"); + v1.setRemark("系统启动时自动迁移历史数据"); + versionMapper.insert(v1); + newVersionCount++; + log.info("[DR迁移] 方案 {} 新建 V1.0,versionId={}", recipeId, v1.getVersionId()); + } else { + log.info("[DR迁移] 方案 {} 已有 V1.0(versionId={}),直接复用", recipeId, v1.getVersionId()); + } + + int rows = passMapper.updateVersionIdForOrphans(recipeId, v1.getVersionId()); + migratedPassCount += rows; + log.info("[DR迁移] 方案 {} 迁移 {} 条道次 → versionId={}", recipeId, rows, v1.getVersionId()); + } + + log.info("[DR迁移] 完成:共处理方案 {} 个,新建版本 {} 个,迁移道次 {} 条", + recipeIds.size(), newVersionCount, migratedPassCount); + } +} diff --git a/klp-wms/src/main/java/com/klp/service/impl/DrMillProcessRecipeServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/DrMillProcessRecipeServiceImpl.java new file mode 100644 index 00000000..5280a831 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/impl/DrMillProcessRecipeServiceImpl.java @@ -0,0 +1,75 @@ +package com.klp.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.klp.common.helper.LoginHelper; +import com.klp.domain.DrMillProcessRecipe; +import com.klp.domain.DrMillProcessRecipeVersion; +import com.klp.mapper.DrMillProcessPassMapper; +import com.klp.mapper.DrMillProcessRecipeMapper; +import com.klp.mapper.DrMillProcessRecipeVersionMapper; +import com.klp.service.IDrMillProcessRecipeService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@DS("double-rack") +@RequiredArgsConstructor +@Service +public class DrMillProcessRecipeServiceImpl implements IDrMillProcessRecipeService { + + private final DrMillProcessRecipeMapper recipeMapper; + private final DrMillProcessPassMapper passMapper; + private final DrMillProcessRecipeVersionMapper versionMapper; + + @Override + public List selectList(DrMillProcessRecipe query) { + return recipeMapper.selectList(query); + } + + @Override + public DrMillProcessRecipe selectDetailById(Long id) { + DrMillProcessRecipe recipe = recipeMapper.selectById(id); + if (recipe != null) { + // 优先取激活版本的道次;无激活版本则返回空列表,避免多版本混合 + DrMillProcessRecipeVersion active = versionMapper.selectActiveByRecipeId(id); + if (active != null) { + recipe.setPassList(passMapper.selectByVersionId(active.getVersionId())); + } + } + return recipe; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int save(DrMillProcessRecipe recipe) { + String user = LoginHelper.getUsername(); + recipe.setCreateBy(user); + recipe.setUpdateBy(user); + recipeMapper.insert(recipe); + // 道次现在通过版本接口管理,不再直接挂在方案上 + return 1; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int update(DrMillProcessRecipe recipe) { + recipe.setUpdateBy(LoginHelper.getUsername()); + recipeMapper.update(recipe); + // 道次通过版本接口管理,不在此处操作 + return 1; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteByIds(Long[] ids) { + for (Long id : ids) { + // 级联删版本下的道次,再删版本,再删方案 + passMapper.deleteByRecipeId(id); + versionMapper.deleteByRecipeIds(new Long[]{id}); + } + return recipeMapper.deleteBatchByIds(ids); + } + +} diff --git a/klp-wms/src/main/java/com/klp/service/impl/DrMillProcessRecipeVersionServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/DrMillProcessRecipeVersionServiceImpl.java new file mode 100644 index 00000000..51489c83 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/impl/DrMillProcessRecipeVersionServiceImpl.java @@ -0,0 +1,86 @@ +package com.klp.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.klp.common.helper.LoginHelper; +import com.klp.domain.DrMillProcessPass; +import com.klp.domain.DrMillProcessRecipeVersion; +import com.klp.mapper.DrMillProcessPassMapper; +import com.klp.mapper.DrMillProcessRecipeVersionMapper; +import com.klp.service.IDrMillProcessRecipeVersionService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@DS("double-rack") +@RequiredArgsConstructor +@Service +public class DrMillProcessRecipeVersionServiceImpl implements IDrMillProcessRecipeVersionService { + + private final DrMillProcessRecipeVersionMapper versionMapper; + private final DrMillProcessPassMapper passMapper; + + @Override + public List listByRecipeId(Long recipeId) { + return versionMapper.selectByRecipeId(recipeId); + } + + @Override + public DrMillProcessRecipeVersion getDetailById(Long versionId) { + DrMillProcessRecipeVersion v = versionMapper.selectById(versionId); + if (v != null) { + v.setPassList(passMapper.selectByVersionId(versionId)); + } + return v; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long save(DrMillProcessRecipeVersion version) { + String user = LoginHelper.getUsername(); + version.setCreateBy(user); + version.setUpdateBy(user); + versionMapper.insert(version); + savePassList(version); + return version.getVersionId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(DrMillProcessRecipeVersion version) { + version.setUpdateBy(LoginHelper.getUsername()); + versionMapper.update(version); + passMapper.deleteByVersionId(version.getVersionId()); + savePassList(version); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void activate(Long versionId) { + DrMillProcessRecipeVersion v = versionMapper.selectById(versionId); + if (v == null) throw new RuntimeException("版本不存在"); + versionMapper.deactivateOthers(v.getRecipeId(), versionId); + versionMapper.activate(versionId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteById(Long versionId) { + passMapper.deleteByVersionId(versionId); + versionMapper.deleteById(versionId); + } + + private void savePassList(DrMillProcessRecipeVersion version) { + List list = version.getPassList(); + if (list == null || list.isEmpty()) return; + String user = LoginHelper.getUsername(); + for (DrMillProcessPass p : list) { + p.setRecipeId(version.getRecipeId()); + p.setVersionId(version.getVersionId()); + p.setCreateBy(user); + p.setUpdateBy(user); + } + passMapper.insertBatch(list); + } +} diff --git a/klp-wms/src/main/java/com/klp/service/impl/DrMillProductionPlanServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/DrMillProductionPlanServiceImpl.java new file mode 100644 index 00000000..8d4f612e --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/impl/DrMillProductionPlanServiceImpl.java @@ -0,0 +1,118 @@ +package com.klp.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.klp.common.core.page.TableDataInfo; +import com.klp.common.helper.LoginHelper; +import com.klp.domain.DrMillProductionPlan; +import com.klp.mapper.DrMillProcessPassMapper; +import com.klp.mapper.DrMillProductionPlanMapper; +import com.klp.service.IDrMillProductionPlanService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@DS("double-rack") +@RequiredArgsConstructor +@Service +public class DrMillProductionPlanServiceImpl implements IDrMillProductionPlanService { + + private final DrMillProductionPlanMapper planMapper; + private final DrMillProcessPassMapper passMapper; + + @Override + public List selectList(DrMillProductionPlan query) { + return planMapper.selectList(query); + } + + @Override + public TableDataInfo selectPageList(DrMillProductionPlan query) { + if (query.getPageNum() == null || query.getPageNum() < 1) query.setPageNum(1); + if (query.getPageSize() == null || query.getPageSize() < 1) query.setPageSize(50); + long total = planMapper.countPageList(query); + List rows = planMapper.selectPageList(query); + TableDataInfo data = TableDataInfo.build(rows); + data.setTotal(total); + return data; + } + + @Override + public DrMillProductionPlan selectById(Long id) { + return planMapper.selectById(id); + } + + @Override + public DrMillProductionPlan selectByActionId(Long actionId) { + String planNo = "DR" + actionId; + DrMillProductionPlan plan = planMapper.selectByPlanNo(planNo); + if (plan != null && plan.getRecipeId() != null) { + plan.setPassList(passMapper.selectByRecipeId(plan.getRecipeId())); + } + return plan; + } + + @Override + public int insert(DrMillProductionPlan plan) { + String user = LoginHelper.getUsername(); + plan.setCreateBy(user); + plan.setUpdateBy(user); + List all = planMapper.selectList(new DrMillProductionPlan()); + plan.setSortNo(all.size() + 1); + if (plan.getPlanNo() == null || plan.getPlanNo().isEmpty()) { + plan.setPlanNo("DR" + System.currentTimeMillis()); + } + return planMapper.insert(plan); + } + + @Override + public int update(DrMillProductionPlan plan) { + plan.setUpdateBy(LoginHelper.getUsername()); + return planMapper.update(plan); + } + + @Override + public int deleteById(Long id) { + return planMapper.deleteById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int moveUp(Long id) { + DrMillProductionPlan cur = planMapper.selectById(id); + if (cur == null || cur.getSortNo() <= 1) return 0; + List all = planMapper.selectList(new DrMillProductionPlan()); + DrMillProductionPlan prev = all.stream() + .filter(p -> p.getSortNo() == cur.getSortNo() - 1) + .findFirst().orElse(null); + if (prev == null) return 0; + planMapper.updateSortNo(cur.getPlanId(), prev.getSortNo()); + planMapper.updateSortNo(prev.getPlanId(), cur.getSortNo()); + return 1; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int moveDown(Long id) { + DrMillProductionPlan cur = planMapper.selectById(id); + if (cur == null) return 0; + List all = planMapper.selectList(new DrMillProductionPlan()); + DrMillProductionPlan next = all.stream() + .filter(p -> p.getSortNo() == cur.getSortNo() + 1) + .findFirst().orElse(null); + if (next == null) return 0; + planMapper.updateSortNo(cur.getPlanId(), next.getSortNo()); + planMapper.updateSortNo(next.getPlanId(), cur.getSortNo()); + return 1; + } + + @Override + public int finish(Long id) { + DrMillProductionPlan plan = planMapper.selectById(id); + if (plan == null) return 0; + plan.setUpdateBy(LoginHelper.getUsername()); + plan.setPlanStatus("2"); + plan.setProdStatus("Done"); + return planMapper.update(plan); + } +} diff --git a/klp-wms/src/main/java/com/klp/service/impl/DrRecipeSyncService.java b/klp-wms/src/main/java/com/klp/service/impl/DrRecipeSyncService.java new file mode 100644 index 00000000..e61e5543 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/service/impl/DrRecipeSyncService.java @@ -0,0 +1,96 @@ +package com.klp.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.klp.domain.DrMillProcessRecipe; +import com.klp.domain.WmsProcessSpec; +import com.klp.domain.WmsProductionLine; +import com.klp.mapper.WmsProcessSpecMapper; +import com.klp.mapper.WmsProductionLineMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 双机架工艺方案 → L3规程(wms_process_spec)同步服务 + *

+ * 注意:此 Service 不标注 @DS,默认走 master 数据源, + * 供 Controller 在 double-rack 查询完方案列表后调用, + * 将缺失的 wms_process_spec 记录自动补齐。 + *

+ */ +@Slf4j +@RequiredArgsConstructor +@Service +public class DrRecipeSyncService { + + /** 双机架产线编号,与 wms_production_line.line_code 对应 */ + private static final String DR_LINE_CODE = "DR"; + private static final String DR_LINE_NAME = "双机架轧机"; + + /** spec_code 前缀,区分同名方案号属于哪条产线 */ + private static final String SPEC_CODE_PREFIX = "DR-"; + + private final WmsProcessSpecMapper specMapper; + private final WmsProductionLineMapper lineMapper; + + /** + * 检查并补充 wms_process_spec: + * 对列表中每条方案,若在 L3 规程表中不存在则自动新增。 + */ + @Transactional(rollbackFor = Exception.class) + public void syncRecipesToSpec(List recipes) { + if (recipes == null || recipes.isEmpty()) return; + + Long lineId = getOrCreateDrLineId(); + + int created = 0; + for (DrMillProcessRecipe recipe : recipes) { + String specCode = SPEC_CODE_PREFIX + recipe.getRecipeNo(); + LambdaQueryWrapper qw = Wrappers.lambdaQuery(); + qw.eq(WmsProcessSpec::getSpecCode, specCode); + if (specMapper.selectCount(qw) == 0) { + WmsProcessSpec spec = new WmsProcessSpec(); + spec.setSpecCode(specCode); + spec.setSpecName(recipe.getRecipeNo()); + spec.setSpecType("PROCESS"); + spec.setLineId(lineId); + spec.setIsEnabled(1); + spec.setRemark("由双机架工艺方案自动同步"); + specMapper.insert(spec); + created++; + log.info("[DR同步] 新增 wms_process_spec: specCode={}, recipeId={}", + specCode, recipe.getRecipeId()); + } + } + if (created > 0) { + log.info("[DR同步] 本次共补充 {} 条 L3 工艺规程", created); + } + } + + /** + * 查找或创建双机架产线记录,返回 line_id。 + */ + private Long getOrCreateDrLineId() { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(WmsProductionLine::getLineCode, DR_LINE_CODE); + WmsProductionLine line = lineMapper.selectOne(lqw); + if (line == null) { + line = new WmsProductionLine(); + line.setLineCode(DR_LINE_CODE); + line.setLineName(DR_LINE_NAME); + line.setCapacity(BigDecimal.ZERO); + line.setUnit("t"); + line.setIsEnabled(1); + line.setRemark("双机架轧机产线,系统自动创建"); + lineMapper.insert(line); + log.info("[DR同步] 新建 wms_production_line: lineCode={}, lineId={}", + DR_LINE_CODE, line.getLineId()); + } + return line.getLineId(); + } +} diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java index a58e1c2c..5a976247 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java @@ -19,8 +19,12 @@ import com.klp.domain.vo.TheoryCycleRegressionResultVo; import com.klp.domain.vo.TheoryCycleRegressionVo; import com.klp.domain.vo.WmsCoilPendingActionVo; import com.klp.domain.vo.WmsCoilPendingActionIdCoilVo; +import com.klp.domain.DrMillProductionPlan; +import com.klp.domain.WmsRawMaterial; +import com.klp.mapper.DrMillProductionPlanMapper; import com.klp.mapper.WmsCoilPendingActionMapper; import com.klp.mapper.WmsMaterialCoilMapper; +import com.klp.mapper.WmsRawMaterialMapper; import com.klp.service.IWmsCoilPendingActionService; import com.klp.system.service.ISysUserService; import lombok.RequiredArgsConstructor; @@ -52,8 +56,14 @@ public class WmsCoilPendingActionServiceImpl implements IWmsCoilPendingActionSer private final ISysUserService userService; private final WmsMaterialCoilMapper materialCoilMapper; + private final WmsRawMaterialMapper rawMaterialMapper; + private final DrMillProductionPlanMapper drPlanMapper; private final StringRedisTemplate stringRedisTemplate; + /** 双机架工序 / 修复的 actionType */ + private static final int ACTION_TYPE_DR_NORMAL = 504; + private static final int ACTION_TYPE_DR_REPAIR = 524; + private static final String REDIS_KEY_IDEAL_CYCLE = "oee:ideal-cycle-time"; /** @@ -256,10 +266,99 @@ public class WmsCoilPendingActionServiceImpl implements IWmsCoilPendingActionSer boolean flag = baseMapper.insert(add) > 0; if (flag) { bo.setActionId(add.getActionId()); + // 双机架工序/修复:同步在 double-rack 数据库创建生产计划 + if (ACTION_TYPE_DR_NORMAL == add.getActionType() || ACTION_TYPE_DR_REPAIR == add.getActionType()) { + autoCreateDrPlan(add); + } } return flag; } + /** + * 自动创建双机架生产计划(写入 double-rack 数据源)。 + * 同时查询钢卷库(wms_material_coil)和原材料库(wms_raw_material), + * 将完整的钢卷/原料规格信息写入计划。 + * planNo = "DR" + actionId,保证唯一且可追溯。 + */ + @com.baomidou.dynamic.datasource.annotation.DS("double-rack") + private void autoCreateDrPlan(WmsCoilPendingAction action) { + try { + DrMillProductionPlan plan = new DrMillProductionPlan(); + plan.setPlanNo("DR" + action.getActionId()); + + if (action.getCoilId() != null) { + // ① 查钢卷库 + WmsMaterialCoil coil = materialCoilMapper.selectById(action.getCoilId()); + if (coil != null) { + plan.setInMatNo(coil.getEnterCoilNo() != null ? coil.getEnterCoilNo() : coil.getCurrentCoilNo()); + plan.setEnterCoilNo(coil.getEnterCoilNo()); + plan.setCurrentCoilNo(coil.getCurrentCoilNo()); + + // 实测厚度(优先) + if (coil.getActualThickness() != null) { + try { plan.setInMatThick(new java.math.BigDecimal(coil.getActualThickness())); } catch (Exception ignored) {} + } + // 实测宽度(优先) + plan.setInMatWidth(coil.getActualWidth()); + // 净重 > 毛重 + plan.setInMatWeight(coil.getNetWeight() != null ? coil.getNetWeight() : coil.getGrossWeight()); + // 长度 + plan.setInMatLength(coil.getLength()); + + // ② 查原材料库(itemType='raw_material' 时通过 itemId 关联) + if ("raw_material".equals(coil.getItemType()) && coil.getItemId() != null) { + WmsRawMaterial rm = rawMaterialMapper.selectById(coil.getItemId()); + if (rm != null) { + // 钢种/合金号 + plan.setAlloyNo(rm.getSteelGrade()); + // 标称厚度(实测没有时用标称补齐) + if (plan.getInMatThick() == null && rm.getThickness() != null) { + plan.setInMatThick(rm.getThickness()); + } + // 标称宽度(实测没有时用标称补齐) + if (plan.getInMatWidth() == null && rm.getWidth() != null) { + plan.setInMatWidth(rm.getWidth()); + } + // 卷重(WMS 净重没有时用原材料卷重补齐) + if (plan.getInMatWeight() == null && rm.getCoilWeight() != null) { + plan.setInMatWeight(rm.getCoilWeight()); + } + // 目标冷轧厚度 / 宽度写入出口目标厚度 + if (rm.getTargetColdThickness() != null) { + plan.setOutThick(rm.getTargetColdThickness()); + } + } + } + } + } else if (action.getCurrentCoilNo() != null) { + plan.setInMatNo(action.getCurrentCoilNo()); + plan.setCurrentCoilNo(action.getCurrentCoilNo()); + } + + // 修复工序在备注中标记 + if (ACTION_TYPE_DR_REPAIR == action.getActionType()) { + plan.setRemark("[修复] " + (action.getRemark() != null ? action.getRemark() : "")); + } else { + plan.setRemark(action.getRemark()); + } + + String user = LoginHelper.getUsername(); + plan.setCreateBy(user); + plan.setUpdateBy(user); + plan.setPlanStatus("0"); + plan.setProdStatus("Idle"); + + // 排到队列末尾 + List all = drPlanMapper.selectList(new DrMillProductionPlan()); + plan.setSortNo(all.size() + 1); + + drPlanMapper.insert(plan); + } catch (Exception e) { + org.slf4j.LoggerFactory.getLogger(getClass()) + .error("[双机架] 自动创建生产计划失败, actionId={}", action.getActionId(), e); + } + } + /** * 修改钢卷待操作 */ diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java index 2fa05f60..d3734ce0 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java @@ -1356,12 +1356,12 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { } result = updateBySingle(bo, qrcodeStepType); // 返回新钢卷ID字符串 } - + // 如果有关联的操作记录ID,调用完成接口 if (bo.getActionId() != null && bo.getActionId() > 0) { coilPendingActionService.completeAction(bo.getActionId(), result); } - + return result; } @@ -5743,5 +5743,15 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { return baseMapper.update(null, updateWrapper) > 0; } + @Override + public WmsMaterialCoilVo queryByCoilNo(String coilNo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(WmsMaterialCoil::getEnterCoilNo, coilNo) + .or() + .eq(WmsMaterialCoil::getCurrentCoilNo, coilNo); + lqw.last("LIMIT 1"); + return baseMapper.selectVoOne(lqw); + } + } diff --git a/klp-wms/src/main/java/com/klp/task/DrMigrationRunner.java b/klp-wms/src/main/java/com/klp/task/DrMigrationRunner.java new file mode 100644 index 00000000..bef49bd8 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/task/DrMigrationRunner.java @@ -0,0 +1,33 @@ +package com.klp.task; + +import com.klp.service.impl.DrMigrationService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * 应用启动后自动执行双机架历史道次版本迁移。 + * 逻辑幂等:若已迁移完毕则无任何 DB 写操作,仅打印一条 info 日志。 + */ +@Slf4j +@Order(100) +@Component +@RequiredArgsConstructor +public class DrMigrationRunner implements ApplicationRunner { + + private final DrMigrationService migrationService; + + @Override + public void run(ApplicationArguments args) { + log.info("[DR迁移] 开始检查历史道次版本迁移..."); + try { + migrationService.migrateOrphanPassesToV1(); + } catch (Exception e) { + // 迁移失败不阻断服务启动,只记录错误 + log.error("[DR迁移] 执行异常,请人工检查 mill_process_pass 表", e); + } + } +} diff --git a/klp-wms/src/main/resources/mapper/DrMillProcessPassMapper.xml b/klp-wms/src/main/resources/mapper/DrMillProcessPassMapper.xml new file mode 100644 index 00000000..e249ca77 --- /dev/null +++ b/klp-wms/src/main/resources/mapper/DrMillProcessPassMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO mill_process_pass ( + recipe_id, version_id, pass_no, in_thick, out_thick, width, + roll_force, in_tension, out_tension, max_speed, + in_unit_tension, out_unit_tension, reduction, total_reduction, + create_by, create_time, update_by, update_time, remark, del_flag + ) VALUES + + (#{p.recipeId}, #{p.versionId}, #{p.passNo}, #{p.inThick}, #{p.outThick}, #{p.width}, + #{p.rollForce}, #{p.inTension}, #{p.outTension}, #{p.maxSpeed}, + #{p.inUnitTension}, #{p.outUnitTension}, #{p.reduction}, #{p.totalReduction}, + #{p.createBy}, NOW(), #{p.updateBy}, NOW(), #{p.remark}, '0') + + + + + UPDATE mill_process_pass SET del_flag = '2', update_time = NOW() + WHERE version_id = #{versionId} + + + + UPDATE mill_process_pass SET del_flag = '2', update_time = NOW() + WHERE recipe_id = #{recipeId} + + + + + + UPDATE mill_process_pass + SET version_id = #{versionId}, + update_time = NOW() + WHERE recipe_id = #{recipeId} + AND version_id IS NULL + AND del_flag = '0' + + + diff --git a/klp-wms/src/main/resources/mapper/DrMillProcessRecipeMapper.xml b/klp-wms/src/main/resources/mapper/DrMillProcessRecipeMapper.xml new file mode 100644 index 00000000..a59182f9 --- /dev/null +++ b/klp-wms/src/main/resources/mapper/DrMillProcessRecipeMapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + recipe_id, recipe_no, alloy_no, pass_count, in_thick, out_thick, out_width, + status, del_flag, create_by, create_time, update_by, update_time, remark + + + + + + + + INSERT INTO mill_process_recipe ( + recipe_no, alloy_no, pass_count, in_thick, out_thick, out_width, + status, create_by, create_time, update_by, update_time, remark, del_flag + ) VALUES ( + #{recipeNo}, #{alloyNo}, #{passCount}, #{inThick}, #{outThick}, #{outWidth}, + #{status}, #{createBy}, NOW(), #{updateBy}, NOW(), #{remark}, '0' + ) + + + + UPDATE mill_process_recipe + SET recipe_no = #{recipeNo}, + alloy_no = #{alloyNo}, + pass_count = #{passCount}, + in_thick = #{inThick}, + out_thick = #{outThick}, + out_width = #{outWidth}, + status = #{status}, + update_by = #{updateBy}, + update_time = NOW(), + remark = #{remark} + WHERE recipe_id = #{recipeId} + + + + UPDATE mill_process_recipe SET del_flag = '2', update_time = NOW() + WHERE recipe_id IN + #{id} + + + diff --git a/klp-wms/src/main/resources/mapper/DrMillProcessRecipeVersionMapper.xml b/klp-wms/src/main/resources/mapper/DrMillProcessRecipeVersionMapper.xml new file mode 100644 index 00000000..575d4991 --- /dev/null +++ b/klp-wms/src/main/resources/mapper/DrMillProcessRecipeVersionMapper.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + version_id, recipe_id, version_code, is_active, status, + create_by, create_time, update_by, update_time, remark, del_flag + + + + + + + + + + + + INSERT INTO mill_process_recipe_version ( + recipe_id, version_code, is_active, status, + create_by, create_time, update_by, update_time, remark, del_flag + ) VALUES ( + #{recipeId}, #{versionCode}, IFNULL(#{isActive}, 0), IFNULL(#{status}, '0'), + #{createBy}, NOW(), #{updateBy}, NOW(), #{remark}, '0' + ) + + + + UPDATE mill_process_recipe_version + SET version_code = #{versionCode}, + status = #{status}, + update_by = #{updateBy}, + update_time = NOW(), + remark = #{remark} + WHERE version_id = #{versionId} + + + + UPDATE mill_process_recipe_version SET del_flag = '2', update_time = NOW() + WHERE version_id = #{versionId} + + + + UPDATE mill_process_recipe_version SET del_flag = '2', update_time = NOW() + WHERE recipe_id IN + #{id} + + + + UPDATE mill_process_recipe_version + SET is_active = 0, update_time = NOW() + WHERE recipe_id = #{recipeId} AND version_id != #{versionId} AND del_flag = '0' + + + + UPDATE mill_process_recipe_version + SET is_active = 1, status = '1', update_time = NOW() + WHERE version_id = #{versionId} + + + diff --git a/klp-wms/src/main/resources/mapper/DrMillProductionPlanMapper.xml b/klp-wms/src/main/resources/mapper/DrMillProductionPlanMapper.xml new file mode 100644 index 00000000..c1eea7ba --- /dev/null +++ b/klp-wms/src/main/resources/mapper/DrMillProductionPlanMapper.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + plan_id, plan_no, plan_status, prod_status, sort_no, + in_mat_no, sg_sign, in_mat_thick, in_mat_width, in_mat_wt, in_mat_len, + in_mat_in_dia, in_mat_dia, out_thick, pass_count, recipe_id, recipe_no, + version_id, enter_coil_no, current_coil_no, + del_flag, create_by, create_time, update_by, update_time, remark + + + + + + + WHERE del_flag = '0' + + AND (in_mat_no LIKE CONCAT('%',#{inMatNo},'%') + OR enter_coil_no LIKE CONCAT('%',#{inMatNo},'%') + OR current_coil_no LIKE CONCAT('%',#{inMatNo},'%')) + + + AND plan_status = #{planStatus} + + + AND create_time >= #{createStartTime} + + + AND create_time <= #{createEndTime} + + + + + + + + + + + + + + + INSERT INTO mill_production_plan ( + plan_no, plan_status, prod_status, sort_no, + in_mat_no, sg_sign, in_mat_thick, in_mat_width, in_mat_wt, in_mat_len, + in_mat_in_dia, in_mat_dia, out_thick, pass_count, recipe_id, recipe_no, + version_id, enter_coil_no, current_coil_no, + create_by, create_time, update_by, update_time, remark, del_flag + ) VALUES ( + #{planNo}, IFNULL(#{planStatus},'0'), IFNULL(#{prodStatus},'Idle'), IFNULL(#{sortNo},0), + #{inMatNo}, #{alloyNo}, #{inMatThick}, #{inMatWidth}, #{inMatWeight}, #{inMatLength}, + #{inMatId}, #{inMatOd}, #{outThick}, IFNULL(#{passCount},0), #{recipeId}, #{recipeNo}, + #{versionId}, #{enterCoilNo}, #{currentCoilNo}, + #{createBy}, NOW(), #{updateBy}, NOW(), #{remark}, '0' + ) + + + + UPDATE mill_production_plan + SET plan_status = #{planStatus}, + prod_status = #{prodStatus}, + in_mat_no = #{inMatNo}, + sg_sign = #{alloyNo}, + in_mat_thick = #{inMatThick}, + in_mat_width = #{inMatWidth}, + in_mat_wt = #{inMatWeight}, + in_mat_len = #{inMatLength}, + in_mat_in_dia = #{inMatId}, + in_mat_dia = #{inMatOd}, + out_thick = #{outThick}, + pass_count = #{passCount}, + recipe_id = #{recipeId}, + recipe_no = #{recipeNo}, + version_id = #{versionId}, + enter_coil_no = #{enterCoilNo}, + current_coil_no = #{currentCoilNo}, + update_by = #{updateBy}, + update_time = NOW(), + remark = #{remark} + WHERE plan_id = #{planId} + + + + UPDATE mill_production_plan SET del_flag = '2', update_time = NOW() + WHERE plan_id = #{planId} + + + + UPDATE mill_production_plan SET sort_no = #{sortNo} WHERE plan_id = #{planId} + + + From 1d1c27bf40346a9a7ac4a75fd8d479cd25392f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Tue, 19 May 2026 17:54:27 +0800 Subject: [PATCH 7/7] =?UTF-8?q?fix(CoilSelector,acid):=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E8=A1=A8=E6=A0=BC=E9=AB=98=E5=BA=A6=E5=B9=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E4=BE=A7=E8=BE=B9=E8=8F=9C=E5=8D=95=E6=8E=92=E5=BA=8F?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修复CoilSelector组件表格高度计算,使用calc适配排序状态下的布局 2. 调整acid页面侧边菜单的菜单项顺序,将跟踪菜单移至正确位置 --- klp-ui/src/components/CoilSelector/index.vue | 2 +- klp-ui/src/views/micro/pages/acid/index.vue | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/klp-ui/src/components/CoilSelector/index.vue b/klp-ui/src/components/CoilSelector/index.vue index 8bf21d68..0e2d6efa 100644 --- a/klp-ui/src/components/CoilSelector/index.vue +++ b/klp-ui/src/components/CoilSelector/index.vue @@ -142,7 +142,7 @@
- + diff --git a/klp-ui/src/views/micro/pages/acid/index.vue b/klp-ui/src/views/micro/pages/acid/index.vue index 0675fa83..e8e39034 100644 --- a/klp-ui/src/views/micro/pages/acid/index.vue +++ b/klp-ui/src/views/micro/pages/acid/index.vue @@ -1,11 +1,7 @@