diff --git a/frontend/src/views/Material.vue b/frontend/src/views/Material.vue index 13e4fbb..f0905df 100644 --- a/frontend/src/views/Material.vue +++ b/frontend/src/views/Material.vue @@ -32,41 +32,6 @@ - -
-
- 在线计划(入口队列) - 在线 {{ onlinePlans.length }} / 生产中 {{ producingPlan ? 1 : 0 }} - 点击「移动」把队列卷推到入口并开始生产 -
-
-
- 生产中 - 冷卷号{{ producingPlan.cold_coil_no || producingPlan.plan_no }} - 钢种{{ producingPlan.steel_grade || '—' }} - 规格{{ fmt(producingPlan.product_thickness) }}×{{ fmt(producingPlan.product_width, 0) }} - 分卷{{ producingPlan.split_count || 1 }} -
- - - - - - - - - - - - - -
冷卷号钢种厚度宽度分卷下达时间操作
{{ p.cold_coil_no || p.plan_no }}{{ p.steel_grade || '—' }}{{ fmt(p.product_thickness) }}{{ fmt(p.product_width, 0) }}{{ p.split_count || 1 }}{{ fmtTime(p.plan_date) }} - -
-
暂无在线计划
-
-
-
推拉酸洗线 - 物料跟踪总图
@@ -267,57 +232,199 @@
- -
-
-
物料跟踪表 共 {{ equipments.length }} 台设备
-
-
- - - - - - - - - - - - - - - - - - - - - - - -
#设备状态当前钢卷辊缝 (mm)速度张力/温度
{{ i + 1 }}{{ eq.label }} - 加工中 - 已过 - 待入 - {{ rowOf(eq, i).coil }}{{ rowOf(eq, i).gap }}{{ rowOf(eq, i).speed }}{{ rowOf(eq, i).aux }}
+ +
+
+
+ {{ t.label }} + {{ t.count }} +
+
+ {{ rtItems.length }} 项实时数据 +
+ + +
+
+ +
+
在线计划 · 入口移动 + 在线 {{ onlinePlans.length }} / 生产中 {{ producingPlan ? 1 : 0 }} +
+
+
+ 生产中 + 冷卷号{{ producingPlan.cold_coil_no || producingPlan.plan_no }} + 钢种{{ producingPlan.steel_grade || '—' }} + 规格{{ fmt(producingPlan.product_thickness) }}×{{ fmt(producingPlan.product_width, 0) }} +
+ + + + + + + + + + + + +
冷卷号钢种厚度宽度分卷操作
{{ p.cold_coil_no || p.plan_no }}{{ p.steel_grade || '—' }}{{ fmt(p.product_thickness) }}{{ fmt(p.product_width, 0) }}{{ p.split_count || 1 }} + +
+
暂无在线计划
+
+
+ +
+
入口段实时参数
+
+
+
+
{{ it.label }}
+
{{ it.val }}{{ it.unit }}
+
+
+
-
-
实时数据 {{ rtItems.length }} 项
-
-
-
- {{ it.label }} - {{ it.val }} - {{ it.unit }} + +
+
+
+
{{ i+1 }}# 酸洗槽
+
+
+
槽温度
{{ fix(a.temp,1) }}°C
+
罐液位
{{ fix(a.level,2) }}m
+
槽浓度
{{ fix(a.conc,1) }}g/L
+
槽电导率
{{ fix(a.cond,1) }}mS/cm
+
罐浓度
{{ fix(a.tank_conc,1) }}g/L
+
罐电导率
{{ fix(a.tank_cond,1) }}mS/cm
+
+
+
+
+
酸雾塔 + 冷凝水罐
+
+
+
酸雾塔 PH
{{ fix(acid_mist.ph,2) }}
+
变频器频率
{{ fix(acid_mist.vfd_speed,1) }}Hz
+
变频器电流
{{ fix(acid_mist.vfd_current,1) }}A
+
冷凝罐液位
{{ fix(acid_cond.level,2) }}m
+
冷凝罐温度
{{ fix(acid_cond.temp,1) }}°C
+
冷凝电导率
{{ fix(acid_cond.cond,1) }}μS/cm
+
+ + +
+
+
+
{{ i+1 }}# 漂洗
+
+
+
槽温度
{{ fix(rinse_tank_temp[i],1) }}°C
+
罐液位
{{ fix(r.level,2) }}m
+
槽浓度
{{ fix(r.conc,2) }}g/L
+
槽电导率
{{ fix(r.cond,2) }}μS/cm
+
罐浓度
{{ fix(r.tank_conc,2) }}g/L
+
罐电导率
{{ fix(r.tank_cond,2) }}μS/cm
+
+
+
+
+
漂洗酸雾塔 + 冷凝罐 + 烘干
+
+
+
雾塔 PH
{{ fix(rinse_mist.ph,2) }}
+
变频器频率
{{ fix(rinse_mist.vfd_speed,1) }}Hz
+
变频器电流
{{ fix(rinse_mist.vfd_current,1) }}A
+
冷凝液位
{{ fix(rinse_cond.level,2) }}m
+
冷凝温度
{{ fix(rinse_cond.temp,1) }}°C
+
冷凝电导率
{{ fix(rinse_cond.cond,2) }}μS/cm
+
烘干 1 段
{{ fix(dryer.t1,0) }}°C
+
烘干 2 段
{{ fix(dryer.t2,0) }}°C
+
烘干 3 段
{{ fix(dryer.t3,0) }}°C
+
+
+
+
+
+ + +
+
+
+
三辊张力装置
+
+ + + + + + + + + + +
变频器速度 m/min电流 A扭矩 kN·m
VFD-{{ i+1 }}{{ fix(v.speed,1) }}{{ fix(v.current,0) }}{{ fix(v.torque,2) }}
+
+
+
+
平整 + 涂油 + 收卷
+
+
+
平整辊缝
{{ fix(leveler.gap,2) }}mm
+
轧制力
{{ fix(leveler.force,0) }}kN
+
延伸率
{{ fix(leveler.elongation,2) }}%
+
收卷张力
{{ fix(recoiler.tension,1) }}kN
+
收卷直径
{{ fix(recoiler.diameter,0) }}mm
+
收卷速度
{{ fix(recoiler.speed,1) }}m/min
+
+
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + +
#设备状态当前钢卷辊缝 mm速度张力/温度
{{ i + 1 }}{{ eq.label }} + 加工中 + 已过 + 待入 + {{ rowOf(eq, i).coil }}{{ rowOf(eq, i).gap }}{{ rowOf(eq, i).speed }}{{ rowOf(eq, i).aux }}
+
@@ -407,9 +514,38 @@ export default { _plansTimer: null, plans: [], moving: false, + tab: 'entry', } }, computed: { + tabs() { + return [ + { k: 'entry', label: '入口段', count: this.onlinePlans.length }, + { k: 'acid', label: '酸洗段', count: 5 }, + { k: 'rinse', label: '漂洗段', count: 5 }, + { k: 'exit', label: '出口段', count: 3 }, + { k: 'track', label: '物料跟踪表', count: this.equipments.length }, + ] + }, + entryItems() { + const f = (v, n=1) => Number(v).toFixed(n) + return [ + { k:'u_t', label:'开卷机张力', val: f(this.uncoiler.tension, 1), unit:'kN' }, + { k:'p_s', label:'工艺段速度', val: f(this.current.speed, 1), unit:'m/min' }, + { k:'u_s', label:'开卷机速度', val: f(this.uncoiler.speed, 1), unit:'m/min' }, + { k:'u_d', label:'开卷机卷径', val: f(this.uncoiler.diameter, 0),unit:'mm' }, + { k:'u_c', label:'开卷机电流', val: f(this.uncoiler.current, 0), unit:'A' }, + { k:'u_q', label:'开卷机扭矩', val: f(this.uncoiler.torque, 2), unit:'kN·m' }, + { k:'st_s',label:'九辊矫直机 速度', val: f(this.straightener.speed, 1), unit:'m/min' }, + { k:'st_g',label:'九辊矫直机 辊缝', val: f(this.straightener.gap, 2), unit:'mm' }, + { k:'st_c',label:'九辊矫直机 电流', val: f(this.straightener.current, 0),unit:'A' }, + { k:'st_q',label:'九辊矫直机 扭矩', val: f(this.straightener.torque, 2), unit:'kN·m' }, + { k:'b1s', label:'1号夹送辊 速度', val: f(this.br1.speed, 1), unit:'m/min' }, + { k:'b1g', label:'1号夹送辊 辊缝', val: f(this.br1.gap, 2), unit:'mm' }, + { k:'b1c', label:'1号夹送辊 电流', val: f(this.br1.current, 0), unit:'A' }, + { k:'b1q', label:'1号夹送辊 扭矩', val: f(this.br1.torque, 2), unit:'kN·m' }, + ] + }, onlinePlans() { return this.plans.filter(p => p.status === 'online') }, producingPlan() { return this.plans.find(p => p.status === 'producing') || null }, equipments() { @@ -455,7 +591,7 @@ export default { push('r_t', '收卷机 收卷张力', fix(this.recoiler.tension, 1), 'kN') this.acid.forEach((a, i) => { - push(`at${i}`, `酸洗${i+1}# 槽/罐温度(公用)`, fix(a.temp, 1), '°C') + push(`at${i}`, `酸洗${i+1}# 槽温度`, fix(a.temp, 1), '°C') push(`al${i}`, `酸洗${i+1}# 罐液位`, fix(a.level, 2), 'm') push(`ac${i}`, `酸洗${i+1}# 槽浓度`, fix(a.conc, 1), 'g/L') push(`ae${i}`, `酸洗${i+1}# 槽电导率`, fix(a.cond, 1), 'mS/cm') @@ -471,7 +607,7 @@ export default { this.rinse.forEach((r, i) => { const t = this.rinse_tank_temp[i] - push(`rt${i}`, `漂洗${i+1}# 槽/罐温度(公用)`, fix(t, 1), '°C') + push(`rt${i}`, `漂洗${i+1}# 槽温度`, fix(t, 1), '°C') push(`rl${i}`, `漂洗${i+1}# 罐液位`, fix(r.level, 2), 'm') push(`rc${i}`, `漂洗${i+1}# 槽浓度`, fix(r.conc, 2), 'g/L') push(`re${i}`, `漂洗${i+1}# 槽电导率`, fix(r.cond, 2), 'μS/cm') @@ -498,6 +634,7 @@ export default { }, methods: { fmt(v, n = 2) { return v != null && v !== '' ? Number(v).toFixed(n) : '—' }, + fix(v, n = 1) { return Number(v).toFixed(n) }, fmtTime(t) { return t ? t.slice(0, 16).replace('T', ' ') : '—' }, async loadPlans() { try { @@ -656,31 +793,63 @@ export default { .line-body { padding: 6px 10px 10px; background: #0a1218; } .line-svg { width: 100%; height: 280px; display: block; } -.split-row { display: grid; grid-template-columns: 1.05fr 1fr; gap: 10px; align-items: stretch; } -.split-left, .split-right { display: flex; flex-direction: column; min-height: 540px; } -.split-right .card-body { flex: 1; overflow-y: auto; } +.sec-card { padding: 0; } +.tab-bar { + display: flex; align-items: center; gap: 2px; + border-bottom: 1px solid $border; padding: 0 10px; + background: #161d24; +} +.tab { + padding: 9px 16px; font-size: 12.5px; cursor: pointer; + color: $text-muted; border-bottom: 2px solid transparent; + user-select: none; +} +.tab:hover { color: #c8d4e0; } +.tab.active { color: $sms-highlight; border-bottom-color: $sms-highlight; font-weight: 600; } +.tab-cnt { + display: inline-block; margin-left: 5px; + background: rgba(255,255,255,.06); border-radius: 9px; + padding: 0 6px; font-size: 10px; color: #9aa8b6; +} +.tab.active .tab-cnt { background: rgba(0,200,255,.15); color: #00c8ff; } +.tab-spacer { flex: 1; } -.track-scroll { max-height: 640px; overflow-y: auto; } +.pane { padding: 10px 12px; } +.pane-grid { display: grid; grid-template-columns: 1fr 1.4fr; gap: 10px; } +.pane-grid.two { grid-template-columns: 1fr 1fr; } +.entry-grid { grid-template-columns: 1fr 1.3fr; } +.tank-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; } -.producing-row { display: flex; align-items: center; gap: 10px; padding: 6px 4px 10px; font-size: 12px; border-bottom: 1px dashed $border; margin-bottom: 6px; - .kv-label { color: $text-muted; font-size: 11px; margin-left: 6px; } +.sub-card { background: #0f161c; border: 1px solid $border; border-radius: 4px; display: flex; flex-direction: column; } +.sub-header { + padding: 6px 10px; font-size: 12px; color: #c8d4e0; + background: #161d24; border-bottom: 1px solid $border; + display: flex; align-items: center; gap: 8px; +} +.sub-header.acid { color: #ffaa44; } +.sub-header.rinse { color: #3aa0c8; } +.sub-body { padding: 8px 10px; flex: 1; } + +.kpi-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px 10px; } +.kpi-grid.two { grid-template-columns: repeat(2, 1fr); } +.kpi { display: flex; flex-direction: column; gap: 2px; } +.kpi-label { color: #8b9aab; font-size: 10.5px; } +.kpi-value { + color: #00c8ff; font-family: monospace; font-size: 14px; font-weight: 600; + background: #0a1218; border: 1px solid #2a3540; border-radius: 3px; + padding: 3px 8px; text-align: right; +} +.kpi-unit { color: #6b7c8d; font-size: 10px; font-weight: 400; margin-left: 4px; } + +.producing-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; + padding: 6px 4px 8px; font-size: 12px; + border-bottom: 1px dashed $border; margin-bottom: 6px; + .kv-label { color: $text-muted; font-size: 11px; margin-left: 4px; } .kv-value { color: $sms-highlight; font-weight: 600; } } +.empty-row { text-align: center; padding: 10px; font-size: 12px; } .btn-sm { padding: 2px 10px; font-size: 11px; } - -.hd-cnt { font-size: 11px; color: #6b7c8d; margin-left: 8px; font-weight: 400; } - -.sec-body { padding: 10px 14px; background: #161d24; } - -.dg { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 4px 18px; } -.dg-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #c8d4e0; padding: 2px 0; } -.dg-item .lbl { color: #8b9aab; flex: 1; min-width: 140px; } -.dg-item .vbox { - background: #0e1418; border: 1px solid #2a3540; padding: 1px 8px; - min-width: 70px; text-align: right; font-family: monospace; - color: #00c8ff; border-radius: 2px; -} -.dg-item .unit { color: #6b7c8d; font-size: 11px; min-width: 44px; } +.hd-cnt { font-size: 11px; color: #6b7c8d; font-weight: 400; } .data-table.compact th, .data-table.compact td { padding: 5px 8px; font-size: 11.5px; } .tracking-table tr.row-active { background: rgba(255, 221, 68, 0.10); }