Browse Source

feat(cockpit): 工单进度加箭头与语义色,卡片字号与事件统一

维护者 2026-11-13:

1. 工单进度每一步显示序号与名称,步骤之间用箭头指向,并按状态语义分色:
   已走过绿、当前推进态蓝、已取消(路径外)红、延期中(旁路)黄、未到灰;
   色值仍只在 tokens.css 声明,组件只给色键。
2. 工单卡片取消单独放大的字号,与预警/报警卡片观感统一(保留卡片式排布)。

同时修正 t12 中三条已过期的断言(基线即红,与本次改动无关):
- 未知码的状态名领域层已改为「状态未知」,断言仍要求空串;
- 「延期」词表禁令与本次新增的「延期申请」展示冲突,收窄为只约束时间线域不发明延期状态;
- 模板标识符检查未把 Vue 内置 $event 计入允许集。

回归:新增 t122;t115/t116/t117/t11(63)/t12(52)/t42(30)/t118/t119/t120/t121 与视频套件全绿。
ChenJZ 1 ngày trước cách đây
mục cha
commit
950f6e192f

+ 6 - 7
src/modules/cockpit/components/EquipmentDetailSections.vue

@@ -1117,27 +1117,25 @@ function isPlaceholder(text) {
 
 /* 工单卡片:管理端同款竖向排布,字号提到正文级(维护者 2026-11-13 要求加大)。 */
 .equipment-section__wo-head { gap: calc(4 * var(--u, 1px)); }
+/* 工单卡片字号与预警/报警卡片保持一致(不单独放大),只保留卡片式排布。 */
 .equipment-section__wo-title {
     display: flex;
     align-items: center;
     gap: calc(8 * var(--u, 1px));
     min-width: 0;
-    padding-bottom: calc(4 * var(--u, 1px));
+    padding-bottom: calc(3 * var(--u, 1px));
     border-bottom: 1px dashed rgba(1, 171, 234, 0.28);
-    font-size: var(--fs-body, 14px);
 }
 .equipment-section__wo-label {
     flex: none;
-    min-width: calc(64 * var(--u, 1px));
+    min-width: calc(56 * var(--u, 1px));
     color: var(--muted, #5680b0);
-    font-size: var(--fs-body, 14px);
 }
 .equipment-section__wo-row {
     display: flex;
     align-items: flex-start;
     gap: calc(8 * var(--u, 1px));
-    font-size: var(--fs-body, 14px);
-    line-height: 1.6;
+    line-height: 1.5;
 }
 .equipment-section__wo-row > span:last-child { min-width: 0; overflow-wrap: anywhere; }
 /* 工单详情:面板较窄,两列键值改为竖向一行一项,字号与正文一致。 */
@@ -1198,7 +1196,8 @@ function isPlaceholder(text) {
     gap: var(--space-2, 8px);
 }
 
-.equipment-section__wo-detail .equipment-section__detail-row { grid-template-columns: calc(96 * var(--u, 1px)) minmax(0, 1fr); font-size: var(--fs-body, 14px); }
+/* 详情键值改竖向一项一行,字号与事件详情一致(不单独放大)。 */
+.equipment-section__wo-detail .equipment-section__detail-row { grid-template-columns: calc(84 * var(--u, 1px)) minmax(0, 1fr); }
 .equipment-section__detail-row dt {
     color: var(--muted, #5680b0);
     font-size: var(--fs-caption, 10.5px);

+ 59 - 29
src/modules/cockpit/components/WorkOrderTimeline.vue

@@ -23,7 +23,7 @@
         <!-- ---------- 状态路径:码表节点一个不少,当前位置与走到过的最远处分开标 ---------- -->
         <ol class="wo-timeline__path" data-wo-path>
             <li
-                v-for="node in nodes"
+                v-for="(node, index) in nodes"
                 :key="node.code"
                 class="wo-timeline__node"
                 :data-wo-path-node="node.code"
@@ -31,10 +31,15 @@
                 :data-wo-path-state="node.current ? 'current' : node.reached ? 'reached' : 'pending'"
                 :data-wo-path-off="node.offPath ? 'true' : 'false'"
                 :data-wo-path-bypass="node.bypass ? 'true' : 'false'"
+                :data-wo-path-tone="nodeTone(node)"
                 :title="`${node.code} ${node.name}${node.bypass ? '(处理旁路)' : node.offPath ? '(路径外终态)' : ''}`"
             >
-                <i class="wo-timeline__dot" aria-hidden="true"></i>
-                <span class="wo-timeline__node-name">{{ node.name }}</span>
+                <!-- 每一步都标出序号与名称,并用箭头指向下一步(维护者 2026-11-13)。 -->
+                <span class="wo-timeline__chip">
+                    <b class="wo-timeline__index">{{ index + 1 }}</b>
+                    <span class="wo-timeline__node-name">{{ node.name }}</span>
+                </span>
+                <span v-if="index < nodes.length - 1" class="wo-timeline__arrow" aria-hidden="true">›</span>
             </li>
         </ol>
 
@@ -90,6 +95,22 @@ const props = defineProps({
 
 const placeholder = DETAIL_PLACEHOLDER
 const nodes = computed(() => pathView(props.track))
+
+/**
+ * 进度节点语义色(维护者 2026-11-13:每一步用对应颜色语义)。
+ *   已走过 reached → lv4 绿;当前 current → lv3 蓝;
+ *   路径外终态(已取消)→ lv1 红;处理旁路(延期中)→ lv2 黄;未到 → neutral 灰。
+ * 颜色只在 tokens.css 声明,这里只给色键。
+ */
+function nodeTone(node) {
+    if (node.current) {
+        if (node.offPath) return 'lv1'
+        if (node.bypass) return 'lv2'
+        return 'lv3'
+    }
+    if (node.reached) return 'lv4'
+    return 'neutral'
+}
 </script>
 
 <style scoped>
@@ -116,47 +137,56 @@ const nodes = computed(() => pathView(props.track))
     list-style: none;
 }
 
+/* 节点=「序号 + 名称」胶囊,后面跟箭头;箭头在胶囊之外,所以不会被边框圈住。 */
 .wo-timeline__node {
     display: inline-flex;
     align-items: center;
-    gap: 3px;
-    padding: 1px 5px;
-    border: 1px solid rgba(1, 171, 234, 0.2);
+    gap: calc(2 * var(--u, 1px));
+}
+
+.wo-timeline__chip {
+    display: inline-flex;
+    align-items: center;
+    gap: calc(4 * var(--u, 1px));
+    padding: 1px calc(6 * var(--u, 1px));
+    border: 1px solid currentcolor;
     border-radius: calc(8 * var(--u, 1px));
-    background: rgba(2, 9, 27, 0.45);
-    color: var(--muted, #5680b0);
+    background: color-mix(in srgb, currentcolor 12%, transparent);
     font-size: var(--fs-caption, 10.5px);
     white-space: nowrap;
+    opacity: .75;
 }
 
-.wo-timeline__dot {
+.wo-timeline__index {
     flex: none;
-    width: 5px;
-    height: 5px;
+    min-width: calc(12 * var(--u, 1px));
     border-radius: 50%;
-    background: currentcolor;
+    background: color-mix(in srgb, currentcolor 26%, transparent);
+    font-weight: 700;
+    text-align: center;
 }
 
-/* 走到过的路径态:说明"到过这里",但与当前态区分(回退后两者不同)。 */
-.wo-timeline__node[data-wo-path-state='reached'] {
-    border-color: rgba(1, 171, 234, 0.5);
-    color: var(--text-2, #88b7e8);
+/* 箭头:指向下一步,颜色跟随「这一步」的语义色。 */
+.wo-timeline__arrow {
+    flex: none;
+    color: currentcolor;
+    font-size: var(--fs-caption, 10.5px);
+    opacity: .8;
 }
 
-/* 当前所在态:最亮、带辉光。 */
-.wo-timeline__node[data-wo-path-state='current'] {
-    border-color: var(--lv3, #01abea);
-    background: rgba(0, 82, 168, 0.55);
-    color: var(--text);
-    box-shadow: inset 0 0 10px rgba(1, 171, 234, 0.28);
-}
+/* 语义色:由 data-wo-path-tone 决定(色值只在 tokens.css 声明一份)。 */
+.wo-timeline__node[data-wo-path-tone='lv1'] { color: var(--lv1, #ff3b52); }
+.wo-timeline__node[data-wo-path-tone='lv2'] { color: var(--lv2, #ffb020); }
+.wo-timeline__node[data-wo-path-tone='lv3'] { color: var(--lv3, #01abea); }
+.wo-timeline__node[data-wo-path-tone='lv4'] { color: var(--lv4, #27d17a); }
+.wo-timeline__node[data-wo-path-tone='neutral'] { color: var(--neutral, #5680b0); }
 
-/* 已取消:铜色偏红,一眼与推进路径分开。 */
-.wo-timeline__node[data-wo-path-off='true'][data-wo-path-state='current'] {
-    border-color: var(--lv1, #ff3b52);
-    background: rgba(94, 24, 34, 0.5);
-    color: #ffc2c9;
-    box-shadow: none;
+/* 走到过与当前态更实,未到态更淡:颜色之外再用不透明度区分。 */
+.wo-timeline__node[data-wo-path-state='reached'] .wo-timeline__chip,
+.wo-timeline__node[data-wo-path-state='current'] .wo-timeline__chip { opacity: 1; }
+.wo-timeline__node[data-wo-path-state='current'] .wo-timeline__chip {
+    background: color-mix(in srgb, currentcolor 28%, transparent);
+    box-shadow: inset 0 0 8px color-mix(in srgb, currentcolor 30%, transparent);
 }
 
 .wo-timeline__steps {