修复酸轧实绩提交问题,规程重新完成逻辑
This commit is contained in:
@@ -160,6 +160,7 @@ import {
|
||||
delProcessSpecVersion,
|
||||
activateProcessSpecVersion
|
||||
} from '@/api/wms/processSpecVersion'
|
||||
import { listDrRecipe, listDrRecipeVersions } from '@/api/wms/drMill'
|
||||
|
||||
const STATUS_OPTIONS = [
|
||||
{ value: 'DRAFT', label: '草稿' },
|
||||
@@ -179,7 +180,7 @@ export default {
|
||||
versionList: [],
|
||||
versionLoading: false,
|
||||
total: 0,
|
||||
queryParams: { pageNum: 1, pageSize: 10, specType: '', lineId: '' },
|
||||
queryParams: { pageNum: 1, pageSize: 20, specType: '', lineId: '' },
|
||||
|
||||
specOpen: false,
|
||||
specTitle: '',
|
||||
@@ -237,18 +238,43 @@ export default {
|
||||
},
|
||||
onSpecRowClick(row) { this.selectSpec(row) },
|
||||
|
||||
loadVersions() {
|
||||
async loadVersions() {
|
||||
if (!this.currentSpecId) return
|
||||
this.versionLoading = true
|
||||
listProcessSpecVersion({ specId: this.currentSpecId, pageNum: 1, pageSize: 200 }).then(res => {
|
||||
try {
|
||||
// DR 规程(specCode 以 "DR-" 开头):先触发一次跨库同步,
|
||||
// 确保 double-rack 库中的版本已写入 master wms_process_spec_version
|
||||
const specCode = (this.currentSpec && this.currentSpec.specCode) || ''
|
||||
if (specCode.startsWith('DR-')) {
|
||||
const recipeNo = specCode.slice(3)
|
||||
try {
|
||||
const rRes = await listDrRecipe({ recipeNo })
|
||||
const recipe = (rRes.data || [])[0]
|
||||
if (recipe) {
|
||||
await listDrRecipeVersions(recipe.recipeId) // 后端自动同步版本到 master
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[DR同步] 触发版本同步失败,将直接读取 master 库', e)
|
||||
}
|
||||
}
|
||||
const res = await listProcessSpecVersion({ specId: this.currentSpecId, pageNum: 1, pageSize: 200 })
|
||||
this.versionList = res.rows || []
|
||||
}).catch(e => console.error(e)).finally(() => { this.versionLoading = false })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
this.versionLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
goPlanSpec(row) {
|
||||
this.$router.push({
|
||||
path: `/process/processSpec/planSpec`,
|
||||
query: { specId: this.currentSpecId, versionId: String(row.versionId), versionCode: row.versionCode }
|
||||
query: {
|
||||
specId: this.currentSpecId,
|
||||
versionId: String(row.versionId),
|
||||
versionCode: row.versionCode,
|
||||
specCode: this.currentSpec ? (this.currentSpec.specCode || '') : ''
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@@ -16,16 +16,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 全局异常提示条 -->
|
||||
<el-alert
|
||||
v-if="allAnomalies.length"
|
||||
:title="`检测到 ${allAnomalies.length} 项实际生产偏差(来自最近一次实绩分析),请选择对应点位查看详情`"
|
||||
type="warning"
|
||||
show-icon
|
||||
:closable="false"
|
||||
style="margin-bottom:10px"
|
||||
/>
|
||||
|
||||
<div class="main-layout">
|
||||
<!-- 左侧段分组 -->
|
||||
<div class="left-tree">
|
||||
@@ -95,9 +85,19 @@
|
||||
>模板导入</el-button>
|
||||
</div>
|
||||
|
||||
<!-- DR 道次参数同步提示 -->
|
||||
<el-alert
|
||||
v-if="drSyncLoading"
|
||||
title="正在从双机架版本同步道次参数,请稍候…"
|
||||
type="info"
|
||||
show-icon
|
||||
:closable="false"
|
||||
style="margin-bottom:10px"
|
||||
/>
|
||||
|
||||
<!-- 参数平铺表 -->
|
||||
<el-table
|
||||
v-loading="planLoading || allParamLoading"
|
||||
v-loading="planLoading || allParamLoading || drSyncLoading"
|
||||
:data="filteredFlatRows"
|
||||
size="small"
|
||||
border
|
||||
@@ -113,17 +113,6 @@
|
||||
<el-table-column label="设定值" prop="targetValue" align="right" width="82" />
|
||||
<el-table-column label="下限" prop="lowerLimit" align="right" width="72" />
|
||||
<el-table-column label="上限" prop="upperLimit" align="right" width="72" />
|
||||
<el-table-column label="实际状态" align="center" width="90">
|
||||
<template slot-scope="{ row }">
|
||||
<span v-if="paramAnomalyMap[row.paramCode]" class="anomaly-badge">
|
||||
<i class="el-icon-warning-outline" /> 异常
|
||||
</span>
|
||||
<span v-else-if="row.upperLimit != null || row.lowerLimit != null" class="normal-badge">
|
||||
<i class="el-icon-circle-check" /> 正常
|
||||
</span>
|
||||
<span v-else class="no-data-badge">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="right" width="100" fixed="right">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button type="text" size="mini" @click="editParamFromFlat(row)">编辑</el-button>
|
||||
@@ -134,98 +123,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 服役钢卷记录 -->
|
||||
<div class="coil-record-section" v-loading="coilRecordLoading">
|
||||
<div class="coil-record-hd">
|
||||
<i class="el-icon-data-line" style="margin-right:5px;color:#5F7BA0" />
|
||||
服役钢卷记录
|
||||
<span class="coil-total-badge">共 {{ coilRecordTotal }} 根</span>
|
||||
<span v-if="coilRecords.filter(r => r.hasAnomaly).length" class="coil-anomaly-badge">
|
||||
其中 {{ coilRecords.filter(r => r.hasAnomaly).length }} 根有异常
|
||||
</span>
|
||||
</div>
|
||||
<el-table :data="coilRecords" size="small" border>
|
||||
<el-table-column label="出口钢卷号" prop="coilId" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="入口钢卷号" prop="enCoilId" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="检测时间" min-width="140">
|
||||
<template slot-scope="{ row }">{{ (row.processTime || '').substring(0, 16) || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数异常情况" align="center" min-width="160">
|
||||
<template slot-scope="{ row }">
|
||||
<template v-if="row.hasAnomaly">
|
||||
<el-tag type="danger" size="mini" effect="plain" style="margin-right:4px">
|
||||
<i class="el-icon-warning-outline" /> {{ row.anomalyCnt }} 项参数超限
|
||||
</el-tag>
|
||||
<el-button type="text" size="mini" style="color:#F56C6C;padding:0"
|
||||
@click="jumpToAnomaly(row.coilId)">查看</el-button>
|
||||
</template>
|
||||
<span v-else class="normal-badge"><i class="el-icon-circle-check" /> 全部正常</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" min-width="80">
|
||||
<template slot-scope="{ row }">
|
||||
<el-tag :type="row.hasAnomaly ? 'danger' : 'success'" size="mini" effect="dark">
|
||||
{{ row.hasAnomaly ? '异常' : '正常' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="coilRecordTotal > 0"
|
||||
:total="coilRecordTotal"
|
||||
:page.sync="coilRecordPage"
|
||||
:limit.sync="coilRecordPageSize"
|
||||
@pagination="loadCoilRecords"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 钢卷异常明细 dialog -->
|
||||
<el-dialog
|
||||
:title="`钢卷 ${coilAnomalyCoilId} — 异常明细`"
|
||||
:visible.sync="coilAnomalyDialog"
|
||||
width="900px"
|
||||
append-to-body
|
||||
>
|
||||
<el-table :data="coilAnomalyList" size="small" border>
|
||||
<el-table-column label="参数名称" prop="paramName" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column label="异常类型" align="center" width="120">
|
||||
<template slot-scope="{ row }">
|
||||
<el-tag v-if="row.anomalyType === 'OVER_MAX' || row.anomalyType === 'BOTH'" size="mini" type="danger" style="margin:1px">超上限</el-tag>
|
||||
<el-tag v-if="row.anomalyType === 'UNDER_MIN' || row.anomalyType === 'BOTH'" size="mini" type="warning" style="margin:1px">低于下限</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规程设定值" prop="storedTarget" align="right" width="100" />
|
||||
<el-table-column label="规程上限" prop="storedUpper" align="right" width="90" />
|
||||
<el-table-column label="规程下限" prop="storedLower" align="right" width="90" />
|
||||
<el-table-column label="实际最大值" align="right" width="100">
|
||||
<template slot-scope="{ row }">
|
||||
<span :class="(row.anomalyType === 'OVER_MAX' || row.anomalyType === 'BOTH') ? 'val-over' : ''">{{ row.actualMax }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实际最小值" align="right" width="100">
|
||||
<template slot-scope="{ row }">
|
||||
<span :class="(row.anomalyType === 'UNDER_MIN' || row.anomalyType === 'BOTH') ? 'val-under' : ''">{{ row.actualMin }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最大偏差" align="right" width="90">
|
||||
<template slot-scope="{ row }">
|
||||
<span v-if="row.deviationMax != null" class="val-over">+{{ row.deviationMax }}</span>
|
||||
<span v-else>—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最小偏差" align="right" width="90">
|
||||
<template slot-scope="{ row }">
|
||||
<span v-if="row.deviationMin != null" class="val-under">{{ row.deviationMin }}</span>
|
||||
<span v-else>—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" prop="unit" align="center" width="60" />
|
||||
</el-table>
|
||||
<div slot="footer">
|
||||
<el-button size="small" @click="coilAnomalyDialog = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 方案点位 dialog -->
|
||||
<el-dialog :title="planTitle" :visible.sync="planOpen" width="520px" append-to-body @close="planForm = {}">
|
||||
<el-form ref="planFormRef" :model="planForm" :rules="planRules" label-width="90px" size="small">
|
||||
@@ -392,11 +289,9 @@
|
||||
|
||||
<script>
|
||||
import * as XLSX from 'xlsx'
|
||||
import * as echarts from 'echarts'
|
||||
import { listProcessPlan, addProcessPlan, updateProcessPlan, delProcessPlan } from '@/api/wms/processPlan'
|
||||
import { listProcessPlanParam, addProcessPlanParam, updateProcessPlanParam, delProcessPlanParam } from '@/api/wms/processPlanParam'
|
||||
import { listAllProcessAnomaly } from '@/api/wms/processAnomaly'
|
||||
import { listProcessCoilRecord } from '@/api/wms/processCoilRecord'
|
||||
import { listDrRecipe, listDrRecipeVersions, getDrRecipeVersionDetail } from '@/api/wms/drMill'
|
||||
|
||||
/** 表单内可选段类型(新建/编辑仍支持全部枚举) */
|
||||
const SEGMENT_FORM_OPTIONS = [
|
||||
@@ -428,6 +323,8 @@ export default {
|
||||
versionId: undefined,
|
||||
versionCode: '',
|
||||
specId: undefined,
|
||||
specCode: '', // 规程编码,DR 规程以 "DR-" 开头
|
||||
drSyncLoading: false, // DR 道次参数同步中
|
||||
configMode: 'configurable',
|
||||
/** 左侧:段类型;空=全部 */
|
||||
activeSegmentType: '',
|
||||
@@ -457,19 +354,6 @@ export default {
|
||||
paramCode: [{ required: true, message: '参数编码不能为空', trigger: 'blur' }],
|
||||
paramName: [{ required: true, message: '参数名称不能为空', trigger: 'blur' }]
|
||||
},
|
||||
// 偏差分析
|
||||
allAnomalies: [],
|
||||
anomalyExpanded: true,
|
||||
anomalyChartInst: null,
|
||||
// 服役钢卷记录
|
||||
coilRecords: [],
|
||||
coilRecordTotal: 0,
|
||||
coilRecordPage: 1,
|
||||
coilRecordPageSize: 20,
|
||||
coilRecordLoading: false,
|
||||
// 钢卷异常明细弹窗
|
||||
coilAnomalyDialog: false,
|
||||
coilAnomalyCoilId: '',
|
||||
// 导入相关数据
|
||||
importOpen: false,
|
||||
file: null,
|
||||
@@ -487,6 +371,10 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 当前规程是否为双机架规程(specCode 以 DR- 开头) */
|
||||
isDrSpec() {
|
||||
return typeof this.specCode === 'string' && this.specCode.startsWith('DR-')
|
||||
},
|
||||
/**
|
||||
* 左侧 Tab:仅从点位数据汇总「段类型」,展示用语义名称(入口段/工艺段/出口段)
|
||||
*/
|
||||
@@ -555,16 +443,6 @@ export default {
|
||||
extra.sort((a, b) => String(a.label).localeCompare(String(b.label), 'zh-CN'))
|
||||
return [...SEGMENT_FORM_OPTIONS, ...extra]
|
||||
},
|
||||
/** paramCode → anomaly 的快速索引(用于状态列) */
|
||||
paramAnomalyMap() {
|
||||
const map = {}
|
||||
this.allAnomalies.forEach(a => { map[a.paramCode] = a })
|
||||
return map
|
||||
},
|
||||
coilAnomalyList() {
|
||||
if (!this.coilAnomalyCoilId) return []
|
||||
return this.allAnomalies.filter(a => a.coilId === this.coilAnomalyCoilId)
|
||||
},
|
||||
/** 所有 plan 的参数平铺成一行,带 plan 的段/点位信息 */
|
||||
flatRows() {
|
||||
const SEG_LABELS = { INLET: '入口段', PROCESS: '工艺段', OUTLET: '出口段' }
|
||||
@@ -629,124 +507,16 @@ export default {
|
||||
methods: {
|
||||
syncFromRoute() {
|
||||
const q = this.$route.query
|
||||
this.versionId = q.versionId || undefined
|
||||
this.versionId = q.versionId || undefined
|
||||
this.versionCode = q.versionCode || ''
|
||||
this.specId = q.specId || undefined
|
||||
this.specId = q.specId || undefined
|
||||
this.specCode = q.specCode || ''
|
||||
this._drSyncAttempted = false // 路由切换时重置,避免重复同步
|
||||
if (this.versionId) {
|
||||
this.loadPlans()
|
||||
this.loadAnomalies()
|
||||
this.loadCoilRecords()
|
||||
}
|
||||
},
|
||||
loadAnomalies() {
|
||||
if (!this.versionId) return
|
||||
listAllProcessAnomaly({ versionId: this.versionId }).then(res => {
|
||||
this.allAnomalies = res.data || []
|
||||
}).catch(() => { this.allAnomalies = [] })
|
||||
},
|
||||
loadCoilRecords() {
|
||||
if (!this.versionId) return
|
||||
this.coilRecordLoading = true
|
||||
listProcessCoilRecord({ versionId: this.versionId, pageNum: this.coilRecordPage, pageSize: this.coilRecordPageSize })
|
||||
.then(res => {
|
||||
this.coilRecords = res.rows || []
|
||||
this.coilRecordTotal = res.total || 0
|
||||
}).catch(() => {}).finally(() => { this.coilRecordLoading = false })
|
||||
},
|
||||
renderAnomalyChart() {
|
||||
const el = this.$refs.anomalyChart
|
||||
if (!el || !this.planAnomalies.length) return
|
||||
if (this.anomalyChartInst && !this.anomalyChartInst.isDisposed()) {
|
||||
this.anomalyChartInst.dispose()
|
||||
}
|
||||
this.anomalyChartInst = echarts.init(el)
|
||||
const items = this.planAnomalies
|
||||
const names = items.map(a => a.paramName)
|
||||
// 范围对比:规程范围 vs 实际范围,使用自定义 bar 叠加实现
|
||||
const specRangeData = items.map(a => {
|
||||
const lo = a.storedLower ?? a.storedTarget ?? 0
|
||||
const hi = a.storedUpper ?? a.storedTarget ?? 0
|
||||
return [lo, hi]
|
||||
})
|
||||
const actualRangeData = items.map(a => {
|
||||
const lo = a.actualMin ?? 0
|
||||
const hi = a.actualMax ?? 0
|
||||
return [lo, hi]
|
||||
})
|
||||
// 把真实值编入 data,让 ECharts 正确推断 y 轴范围
|
||||
// data item: [categoryIndex, lo, hi]
|
||||
const specSeriesData = specRangeData.map(([lo, hi], i) => [i, lo, hi])
|
||||
const actualSeriesData = actualRangeData.map(([lo, hi], i) => [i, lo, hi])
|
||||
|
||||
const allVals = [...specRangeData, ...actualRangeData].flat().filter(v => v != null && isFinite(v))
|
||||
const yMin = allVals.length ? Math.min(...allVals) : 0
|
||||
const yMax = allVals.length ? Math.max(...allVals) : 1
|
||||
const pad = (yMax - yMin) * 0.15 || 1
|
||||
|
||||
const option = {
|
||||
title: { text: '规程范围 vs 实际范围对比', textStyle: { fontSize: 12, fontWeight: 'normal' }, top: 6, left: 8 },
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter(params) {
|
||||
const idx = params[0].dataIndex
|
||||
const name = names[idx]
|
||||
const spec = specRangeData[idx]
|
||||
const actual = actualRangeData[idx]
|
||||
return `${name}<br/>规程范围:${spec[0]} ~ ${spec[1]}<br/>实际范围:${actual[0]} ~ ${actual[1]}`
|
||||
}
|
||||
},
|
||||
legend: { data: ['规程范围', '实际范围'], top: 6, right: 8, textStyle: { fontSize: 11 } },
|
||||
grid: { top: 44, bottom: 36, left: 12, right: 20, containLabel: true },
|
||||
xAxis: { type: 'category', data: names, axisLabel: { fontSize: 11, rotate: names.length > 5 ? 30 : 0 } },
|
||||
yAxis: { type: 'value', min: yMin - pad, max: yMax + pad, axisLabel: { fontSize: 11 } },
|
||||
series: [
|
||||
{
|
||||
name: '规程范围',
|
||||
type: 'custom',
|
||||
renderItem(params, api) {
|
||||
const idx = api.value(0)
|
||||
const lo = api.value(1)
|
||||
const hi = api.value(2)
|
||||
const start = api.coord([idx, lo])
|
||||
const end = api.coord([idx, hi])
|
||||
const w = api.size([1, 0])[0] * 0.3
|
||||
return {
|
||||
type: 'rect',
|
||||
shape: { x: start[0] - w / 2, y: end[1], width: w, height: Math.max(start[1] - end[1], 2) },
|
||||
style: { fill: 'rgba(95,123,160,0.35)', stroke: '#5F7BA0', lineWidth: 1 }
|
||||
}
|
||||
},
|
||||
data: specSeriesData,
|
||||
encode: { x: 0, y: [1, 2] }
|
||||
},
|
||||
{
|
||||
name: '实际范围',
|
||||
type: 'custom',
|
||||
renderItem(params, api) {
|
||||
const idx = api.value(0)
|
||||
const lo = api.value(1)
|
||||
const hi = api.value(2)
|
||||
const start = api.coord([idx, lo])
|
||||
const end = api.coord([idx, hi])
|
||||
const w = api.size([1, 0])[0] * 0.18
|
||||
return {
|
||||
type: 'rect',
|
||||
shape: { x: start[0] - w / 2, y: end[1], width: w, height: Math.max(start[1] - end[1], 2) },
|
||||
style: { fill: 'rgba(245,108,108,0.45)', stroke: '#F56C6C', lineWidth: 1.5 }
|
||||
}
|
||||
},
|
||||
data: actualSeriesData,
|
||||
encode: { x: 0, y: [1, 2] }
|
||||
}
|
||||
]
|
||||
}
|
||||
this.anomalyChartInst.setOption(option)
|
||||
},
|
||||
goBack() { this.$router.go(-1) },
|
||||
jumpToAnomaly(coilId) {
|
||||
this.coilAnomalyCoilId = coilId
|
||||
this.coilAnomalyDialog = true
|
||||
},
|
||||
selectSegmentType(val) {
|
||||
this.activeSegmentType = val === undefined || val === null ? '' : val
|
||||
this.activeSegmentName = ''
|
||||
@@ -768,9 +538,100 @@ export default {
|
||||
this.planLoading = true
|
||||
listProcessPlan({ versionId: this.versionId, pageNum: 1, pageSize: 500 }).then(res => {
|
||||
this.planList = res.rows || []
|
||||
this.loadAllParams()
|
||||
// DR 规程:首次加载如果没有道次数据,自动从双机架版本同步
|
||||
if (this.planList.length === 0 && this.isDrSpec && !this._drSyncAttempted) {
|
||||
this._drSyncAttempted = true
|
||||
this.drAutoSyncPasses()
|
||||
} else {
|
||||
this.loadAllParams()
|
||||
}
|
||||
}).catch(e => console.error(e)).finally(() => { this.planLoading = false })
|
||||
},
|
||||
/**
|
||||
* DR 规程专用:自动从双机架版本道次数据同步到 wms_process_plan / wms_process_plan_param。
|
||||
* 仅在首次加载且 planList 为空时触发(通过 _drSyncAttempted 防止重入)。
|
||||
*/
|
||||
async drAutoSyncPasses() {
|
||||
this.drSyncLoading = true
|
||||
try {
|
||||
const recipeNo = this.specCode.slice(3) // "DR-R001" → "R001"
|
||||
|
||||
// 1. 找到对应双机架方案
|
||||
const rRes = await listDrRecipe({ recipeNo })
|
||||
const recipe = (rRes.data || [])[0]
|
||||
if (!recipe) {
|
||||
this.$message.warning(`未找到双机架方案 ${recipeNo},请手动新建参数`)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 在版本列表中找到与当前 versionCode 匹配的版本
|
||||
const vRes = await listDrRecipeVersions(recipe.recipeId)
|
||||
const drVersion = (vRes.data || []).find(v => v.versionCode === this.versionCode)
|
||||
if (!drVersion) {
|
||||
this.$message.warning(`未找到双机架版本 ${this.versionCode},请手动新建参数`)
|
||||
return
|
||||
}
|
||||
|
||||
// 3. 拉取完整版本详情(含 passList)
|
||||
const dRes = await getDrRecipeVersionDetail(drVersion.versionId)
|
||||
const passList = dRes.data?.passList || []
|
||||
if (!passList.length) {
|
||||
this.$message.info('双机架版本暂无道次数据,可手动新建参数')
|
||||
return
|
||||
}
|
||||
|
||||
// 4. 逐道次写入 wms_process_plan + wms_process_plan_param
|
||||
const PASS_PARAMS = [
|
||||
{ code: 'IN_THICK', name: '入口厚度', unit: 'mm', key: 'inThick' },
|
||||
{ code: 'OUT_THICK', name: '出口厚度', unit: 'mm', key: 'outThick' },
|
||||
{ code: 'ROLL_FORCE', name: '轧制力', unit: 'kN', key: 'rollForce' },
|
||||
{ code: 'IN_TENSION', name: '入口张力', unit: 'kN', key: 'inTension' },
|
||||
{ code: 'OUT_TENSION', name: '出口张力', unit: 'kN', key: 'outTension' },
|
||||
{ code: 'MAX_SPEED', name: '最高速度', unit: 'm/min', key: 'maxSpeed' },
|
||||
{ code: 'IN_UNIT_TEN', name: '入口单位张力', unit: '', key: 'inUnitTension' },
|
||||
{ code: 'OUT_UNIT_TEN', name: '出口单位张力', unit: '', key: 'outUnitTension' }
|
||||
]
|
||||
|
||||
for (const pass of passList) {
|
||||
const planRes = await addProcessPlan({
|
||||
versionId: this.versionId,
|
||||
segmentType: 'PROCESS',
|
||||
segmentName: '轧制道次',
|
||||
pointName: `第 ${pass.passNo} 道次`,
|
||||
pointCode: `PASS_${pass.passNo}`,
|
||||
sortOrder: pass.passNo || 0,
|
||||
remark: '由双机架版本道次自动导入'
|
||||
})
|
||||
const planId = planRes.data
|
||||
if (!planId) continue
|
||||
|
||||
for (const p of PASS_PARAMS) {
|
||||
const raw = pass[p.key]
|
||||
if (raw === null || raw === undefined || raw === '') continue
|
||||
const num = Number(raw)
|
||||
if (!isFinite(num)) continue
|
||||
await addProcessPlanParam({
|
||||
planId,
|
||||
paramCode: p.code,
|
||||
paramName: p.name,
|
||||
unit: p.unit || null,
|
||||
targetValue: num
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.$message.success(`已从双机架版本同步 ${passList.length} 道次参数,可继续设置上下限`)
|
||||
// 重新加载(此时 _drSyncAttempted=true,不会再触发同步)
|
||||
this.loadPlans()
|
||||
} catch (e) {
|
||||
console.warn('[DR同步] 道次参数同步失败', e)
|
||||
this.$message.warning('道次参数同步失败,可手动新建参数')
|
||||
this.loadAllParams() // 同步失败也继续尝试加载已有数据
|
||||
} finally {
|
||||
this.drSyncLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
async loadAllParams() {
|
||||
if (!this.planList.length) { this.allParamList = []; return }
|
||||
this.allParamLoading = true
|
||||
@@ -1486,27 +1347,6 @@ export default {
|
||||
.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;
|
||||
align-items: center;
|
||||
padding: 10px 0 8px;
|
||||
margin-top: 14px;
|
||||
border-top: 2px solid #fdf6ec;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #E6A23C;
|
||||
}
|
||||
.anomaly-chart {
|
||||
width: 100%;
|
||||
height: 260px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.anomaly-badge { font-size: 12px; color: #F56C6C; font-weight: 600; }
|
||||
.normal-badge { font-size: 12px; color: #67C23A; }
|
||||
.no-data-badge { font-size: 12px; color: #c0c4cc; }
|
||||
.val-over { color: #F56C6C; font-weight: 600; }
|
||||
.val-under { color: #E6A23C; font-weight: 600; }
|
||||
|
||||
/* 导入对话框样式 */
|
||||
.import-container {
|
||||
@@ -1564,34 +1404,4 @@ export default {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* ── 服役钢卷记录 ── */
|
||||
.coil-record-section {
|
||||
margin-top: 16px;
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.coil-record-hd {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 14px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
border-bottom: 1px solid #f0f2f5;
|
||||
background: #fafafa;
|
||||
}
|
||||
.coil-total-badge {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #606266;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.coil-anomaly-badge {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #f56c6c;
|
||||
margin-left: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user