From 59dad192962871959b7420b324c197a87bcbe547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= <2178503051@qq.com> Date: Sat, 27 Jun 2026 17:58:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(cost):=20=E6=96=B0=E5=A2=9E=E6=88=90?= =?UTF-8?q?=E6=9C=AC=E7=BB=BC=E5=90=88=E9=A1=B5=E7=9A=84=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=88=86=E6=9E=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增异常分析弹窗组件AnomalyAnalysis,支持基于3σ法则检测异常数据 2. 在综合成本页面右上角添加异常分析入口按钮 3. 为异常单元格添加红色高亮样式,标记异常数据 4. 实现异常数据的接收、存储和表格标记逻辑 --- .../views/cost/components/AnomalyAnalysis.vue | 640 ++++++++++++++++++ klp-ui/src/views/cost/comprehensive.vue | 37 +- 2 files changed, 673 insertions(+), 4 deletions(-) create mode 100644 klp-ui/src/views/cost/components/AnomalyAnalysis.vue diff --git a/klp-ui/src/views/cost/components/AnomalyAnalysis.vue b/klp-ui/src/views/cost/components/AnomalyAnalysis.vue new file mode 100644 index 000000000..705c7a8cc --- /dev/null +++ b/klp-ui/src/views/cost/components/AnomalyAnalysis.vue @@ -0,0 +1,640 @@ + + + + + 开始分析 + 应用到表格 + + + + + + + + + + {{ s.label }} + {{ s.msg }} + + + + + + + 吨钢指标分布(3σ) + + + + + + + + + + 异常数据列表(共 {{ anomalyList.length }} 条) + + + + + + + + + {{ s.row.deviationSigma }} + + + + + + 未发现异常数据 + + + + 关 闭 + + + + + + + diff --git a/klp-ui/src/views/cost/comprehensive.vue b/klp-ui/src/views/cost/comprehensive.vue index 1719a2926..4afc366f3 100644 --- a/klp-ui/src/views/cost/comprehensive.vue +++ b/klp-ui/src/views/cost/comprehensive.vue @@ -22,6 +22,7 @@ 保存 列配置 价格管理 + 异常分析 {{ inputMode ? '录入' : '查看' }} @@ -39,7 +40,7 @@ {{ col.itemName }}{{ col.unit ? '('+col.unit+')' : '' }} - + 乙 - + @@ -317,6 +318,9 @@ 关 闭 + + + @@ -334,6 +338,7 @@ import { listAuxiliaryConsume, addAuxiliaryConsume, updateAuxiliaryConsume } fro import { listProductionLine } from "@/api/wms/productionLine" import { listRollGrindAll } from "@/api/mes/roll/rollGrind" import { listEnergyRecord, addEnergyRecord, updateEnergyRecord } from "@/api/ems/energyRecord" +import AnomalyAnalysis from "./components/AnomalyAnalysis" function parseDateRange(detailDate) { const d = (detailDate || '').slice(0, 10) @@ -444,6 +449,7 @@ registerBackfillHandler('能耗', async (queryCondition, row, col, report, shift export default { name: "CostComprehensive", + components: { AnomalyAnalysis }, data() { return { loading: false, list: [], tabs: [], total: 0, sel: 0, selIds: [], showSearch: true, @@ -465,7 +471,8 @@ export default { inputMode: false, priceOpen: false, priceList: [], priceSaving: false, backfilling: false, - progressOpen: false, progressTitle: '', progressTasks: [] + progressOpen: false, progressTitle: '', progressTasks: [], + anomalyOpen: false, anomalyMap: {} } }, computed: { @@ -1060,6 +1067,27 @@ export default { else return row.lineType || '-' } }, + onAnomalyFound(list) { + const map = {} + list.forEach(a => { + // Normalize date to yyyy-MM-dd string + const dt = (a.detailDate || '').slice(0, 10) + if (!dt) return + if (!map[dt]) map[dt] = new Set() + map[dt].add(String(a.itemId)) + }) + this.anomalyMap = map + this.anomalyOpen = false + this.$forceUpdate() + this.$modal.msgSuccess(`已将 ${list.length} 条异常数据标记到表格`) + }, + isAnomalyCell(detailDate, itemId) { + if (!detailDate) return false + const dt = (detailDate || '').slice ? detailDate.slice(0, 10) : String(detailDate).slice(0, 10) + const set = this.anomalyMap[dt] + if (!set) return false + return set.has(String(itemId)) + }, async loadItems() { if (!this.allItems.length) { const r = await listItem({ pageNum:1, pageSize:999 }); this.allItems = r.rows || [] } }, async loadAllMetrics(rid) { const q = { pageNum:1, pageSize:99999 }; if (rid) q.reportId = rid @@ -1113,4 +1141,5 @@ export default { .ica-fetch { color: #409eff; } .ica-backfill { color: #67c23a; margin-right: 1px; } .ica:hover { opacity: 0.7; } +/deep/ .anomaly-input .el-input__inner { background: #fef0f0 !important; border-color: #f56c6c !important; }