diff --git a/klp-ui/src/views/wms/coil/info.vue b/klp-ui/src/views/wms/coil/info.vue index 17fa4101..5b26b913 100644 --- a/klp-ui/src/views/wms/coil/info.vue +++ b/klp-ui/src/views/wms/coil/info.vue @@ -27,7 +27,7 @@ 📦 入库
+ v-if="coil && coil.currentCoilNo !== '-'">
{{ coil.currentCoilNo }} {{ coil.netWeight ? coil.netWeight + ' t' : '-' }} @@ -174,7 +174,7 @@
无钢卷信息
@@ -201,7 +201,7 @@ 变更前
+ v-if="coil && coil.currentCoilNo !== '-'">
{{ coil.currentCoilNo }} {{ coil.netWeight ? coil.netWeight + ' t' : '-' }} @@ -347,7 +347,7 @@
无钢卷信息
@@ -371,7 +371,7 @@ 变更后
+ v-if="coil && coil.currentCoilNo !== '-'">
{{ coil.currentCoilNo }} {{ coil.netWeight ? coil.netWeight + ' t' : '-' }} @@ -517,7 +517,7 @@
无钢卷信息
@@ -727,6 +727,24 @@ + + +
+
+ 📈 + 生产工艺数据 + 加载中… + ({{ perfSegCount }} 段) +
+
+
+
+
+
+
+ +
+
@@ -739,6 +757,9 @@ import { listCoilAbnormal } from '@/api/wms/coilAbnormal' import { listTransferOrderItem } from '@/api/wms/transferOrderItem' // 查询技术部改判调拨的记录 import { listCoilQualityRejudge } from '@/api/wms/coilQualityRejudge' +// 引入 ECharts 和 L2 时序数据 API +import * as echarts from 'echarts' +import { getTimingSegByEncoilId } from '@/api/l2/timing' import AbnormalTable from '@/views/wms/coil/components/AbnormalTable.vue'; import FileList from "@/components/FileList"; @@ -768,15 +789,28 @@ export default { abmornalList: [], transferOrderItemList: [], // 批量调拨记录 coilQualityRejudgeList: [], // 技术部改判记录 - tranferList: [] // 合并后的调拨记录 + tranferList: [], // 合并后的调拨记录 + // 生产数据相关 + perfLoading: false, + perfSeries: null, + perfSegCount: 0 } }, computed: { salesInfo() { return this.coilInfo.orderList?.[0] || {}; + }, + // 判断是否为冷硬卷 + isColdHardCoil() { + return this.coilInfo.itemName && this.coilInfo.itemName.includes('冷硬卷'); + }, + hasPerfData() { + return this.perfSeries && this.perfSegCount > 0; } }, async created() { + this.chartInstances = []; + this.resizeHandler = null; this.coilId = this.$route.params.coilId; this.loading = true; await this.getCoilInfo(); @@ -786,8 +820,15 @@ export default { await this.getTransferOrderItemList(); await this.getCoilQualityRejudgeList(); this.mergeTransferList(); + // 如果是冷硬卷,加载生产数据 + if (this.isColdHardCoil) { + await this.loadProductionData(); + } this.loading = false; }, + beforeDestroy() { + this.disposeCharts(); + }, methods: { async getCoilInfo() { const res = await getMaterialCoil(this.coilId); @@ -992,7 +1033,7 @@ export default { if (standardStep.action === '创建') { listMaterialCoil({ currentCoilNo: originalStep.current_coil_no, enterCoilNo: originalStep.current_coil_no }).then(res => { - standardStep.newCoilInfoList = res.rows[0] || []; + standardStep.newCoilInfoList = res.rows || []; }); } @@ -1009,26 +1050,28 @@ export default { if (!coilIds || !coilIds.length) return []; return coilIds.map(coilId => { const coil = this.coilDetails[coilId] || {}; + // 确保 coil 不为 null 或 undefined + const safeCoil = coil || {}; return { - ...coil, - enterCoilNo: coil.enterCoilNo || '-', - currentCoilNo: coil.currentCoilNo || '-', - materialType: coil.materialType || '-', - itemName: coil.itemName || '-', - specification: coil.specification || '-', - material: coil.material || '-', - netWeight: coil.netWeight || 0, - warehouseName: coil.warehouseName || '-', - actualWarehouseName: coil.actualWarehouseName || '-', - manufacturer: coil.manufacturer || '-', - zincLayer: coil.zincLayer || '-', - qualityStatus: coil.qualityStatus || '-', - createTime: coil.createTime || '-', - status: coil.status || 0, - exportByName: coil.exportByName || '-', - exportTime: coil.exportTime || '-', + ...safeCoil, + enterCoilNo: safeCoil.enterCoilNo || '-', + currentCoilNo: safeCoil.currentCoilNo || '-', + materialType: safeCoil.materialType || '-', + itemName: safeCoil.itemName || '-', + specification: safeCoil.specification || '-', + material: safeCoil.material || '-', + netWeight: safeCoil.netWeight || 0, + warehouseName: safeCoil.warehouseName || '-', + actualWarehouseName: safeCoil.actualWarehouseName || '-', + manufacturer: safeCoil.manufacturer || '-', + zincLayer: safeCoil.zincLayer || '-', + qualityStatus: safeCoil.qualityStatus || '-', + createTime: safeCoil.createTime || '-', + status: safeCoil.status || 0, + exportByName: safeCoil.exportByName || '-', + exportTime: safeCoil.exportTime || '-', }; - }); + }).filter(coil => coil); // 过滤掉 null/undefined 的项 }, collectCoilIds() { if (!this.standardSteps.length) return []; @@ -1101,6 +1144,105 @@ export default { } return step.newCoilInfoList; }, + // ECharts 辅助函数 + makeLine(name, data) { + return { name, type: 'line', smooth: true, symbol: 'none', data }; + }, + baseOption(title, xData, series, yName) { + return { + title: { text: title, textStyle: { fontSize: 12, fontWeight: 'normal' }, top: 4, left: 8 }, + tooltip: { trigger: 'axis' }, + legend: { top: 4, right: 8, textStyle: { fontSize: 11 } }, + grid: { top: 36, bottom: 28, left: 8, right: 8, containLabel: true }, + xAxis: { + type: 'category', + data: xData, + name: 'pos(m)', + nameTextStyle: { fontSize: 10 }, + axisLabel: { fontSize: 10 } + }, + yAxis: { type: 'value', name: yName, nameTextStyle: { fontSize: 10 }, axisLabel: { fontSize: 10 } }, + series + }; + }, + // 加载生产数据 + async loadProductionData() { + const encoilId = this.coilInfo.currentCoilNo; + if (!encoilId) return; + + this.perfLoading = true; + try { + const res = await getTimingSegByEncoilId(encoilId); + const series = res?.data?.series || null; + const rows = res?.data?.rows || []; + this.perfSegCount = rows.length; + this.perfSeries = series; + + if (series && rows.length) { + await this.$nextTick(); + this.renderCharts(series); + } + } catch (error) { + console.error('获取生产数据异常:', error); + this.perfSeries = null; + this.perfSegCount = 0; + } finally { + this.perfLoading = false; + } + }, + // 销毁图表 + disposeCharts() { + if (this.resizeHandler) { + window.removeEventListener('resize', this.resizeHandler); + this.resizeHandler = null; + } + if (this.chartInstances && this.chartInstances.length) { + this.chartInstances.forEach(c => { if (c) c.dispose(); }); + this.chartInstances = []; + } + }, + // 渲染图表 + renderCharts(series) { + this.disposeCharts(); + if (!this.$refs.chartSpeed || !this.$refs.chartMillSpeed || !this.$refs.chartTension) { + return; + } + + const pick = key => (series[key] || []).map(v => v == null ? null : Number(v).toFixed(2)); + const xData = (series.startpos || []).map(v => v == null ? '' : Number(v).toFixed(1)); + + const c1 = echarts.init(this.$refs.chartSpeed); + c1.setOption(this.baseOption( + '速度趋势 (m/min)', xData, + [ + this.makeLine('轧制速度 plspeed', pick('plspeed')), + this.makeLine('剪切速度 trimspeed', pick('trimspeed')) + ], + 'm/min' + )); + + const c2 = echarts.init(this.$refs.chartMillSpeed); + c2.setOption(this.baseOption( + '轧机出口速度 (m/min)', xData, + [this.makeLine('millexitspeed', pick('millexitspeed'))], + 'm/min' + )); + + const c3 = echarts.init(this.$refs.chartTension); + c3.setOption(this.baseOption( + '张力趋势 (N)', xData, + [ + this.makeLine('出口张力 pltens', pick('pltens')), + this.makeLine('入口张力 enltens', pick('enltens')), + this.makeLine('cxltens', pick('cxltens')) + ], + 'N' + )); + + this.chartInstances = [c1, c2, c3]; + this.resizeHandler = () => this.chartInstances.forEach(c => { if (c) c.resize(); }); + window.addEventListener('resize', this.resizeHandler); + }, }, } @@ -1966,4 +2108,23 @@ export default { border: 1px solid rgba(59, 130, 246, 0.2); letter-spacing: 0.6px; } + +/* 生产数据样式 */ +.perf-count { + font-weight: normal; + color: #909399; + font-size: 12px; + margin-left: 4px; +} + +.charts-wrap { + display: flex; + flex-direction: column; + gap: 12px; +} + +.chart-box { + width: 100%; + height: 200px; +}