diff --git a/frontend/src/views/ProcessModel.vue b/frontend/src/views/ProcessModel.vue
index b7d316c..67793e3 100644
--- a/frontend/src/views/ProcessModel.vue
+++ b/frontend/src/views/ProcessModel.vue
@@ -176,7 +176,57 @@
{{ calcResult.warning }}
- 各槽酸洗详情
+
+ 速度安全区间
+
+
+
+
20
+
180
+
+
{{ calcResult.max_speed }} m/min
+
+
+
+
+ PI 累积曲线
+
+
+ 各槽酸洗详情
| 酸槽 | 停留时间 (s) | 累计PI (%) | 进度 |
@@ -356,6 +406,17 @@ export default {
acidHistory() {
return this.calibHistory.filter(h => h.model === 'acid_speed').slice(0, 10)
},
+ speedPct() {
+ if (!this.calcResult) return 0
+ const v = this.calcResult.max_speed
+ return Math.max(0, Math.min(100, ((v - 20) / 160) * 100))
+ },
+ chartPoints() {
+ if (!this.calcResult) return ''
+ return this.calcResult.pi_per_tank
+ .map((pi, i) => `${36 + (i+1)*71.2},${160 - pi*1.3}`)
+ .join(' ')
+ },
},
async mounted() {
await this.fetchL1Data()
@@ -534,6 +595,54 @@ export default {
border-left: 2px solid $border;
padding-left: 8px;
}
+.pi-chart {
+ width: 100%;
+ height: 180px;
+ display: block;
+ background: rgba(0,0,0,.18);
+ border: 1px solid $border;
+ border-radius: 4px;
+}
+.speed-bar-wrap { padding: 6px 8px 22px; }
+.speed-bar-track {
+ position: relative;
+ height: 8px;
+ background: rgba(255,255,255,.06);
+ border-radius: 4px;
+}
+.speed-bar-fill {
+ position: absolute;
+ left: 0; top: 0; bottom: 0;
+ background: linear-gradient(90deg, #28a745, #00c8ff);
+ border-radius: 4px;
+ transition: width .25s;
+}
+.speed-bar-tick {
+ position: absolute;
+ top: 12px;
+ font-size: 10px;
+ color: $text-muted;
+ font-family: monospace;
+}
+.speed-bar-marker {
+ position: absolute;
+ top: -3px;
+ width: 2px;
+ height: 14px;
+ background: #f0a500;
+ transform: translateX(-1px);
+ transition: left .25s;
+}
+.speed-bar-marker-label {
+ position: absolute;
+ top: 16px;
+ left: 50%;
+ transform: translateX(-50%);
+ font-size: 10px;
+ color: #f0a500;
+ font-family: monospace;
+ white-space: nowrap;
+}
.calib-predict-row {
display: flex;
align-items: center;