From dc082351978a1e9f75d7a1471a0ca7ebeac552a5 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期一, 01 六月 2026 11:07:50 +0800
Subject: [PATCH] opo维护

---
 src/views/business/course/index.vue |  522 ++++++++++++++++++++++++---------------------------------
 1 files changed, 218 insertions(+), 304 deletions(-)

diff --git a/src/views/business/course/index.vue b/src/views/business/course/index.vue
index dcbb645..02501b3 100644
--- a/src/views/business/course/index.vue
+++ b/src/views/business/course/index.vue
@@ -2,13 +2,10 @@
   <div class="donation-process-detail">
     <el-card class="process-card">
       <div class="process-container">
-        <!-- 宸︿晶鏃堕棿绾� - 鐙珛鍥哄畾锛屽唴閮ㄥ彲婊氬姩 -->
+        <!-- 宸︿晶鏃堕棿绾� -->
         <div class="timeline-section">
           <div class="section-header">
             <h3>鎹愮尞杩涚▼鏃堕棿绾�</h3>
-            <el-tag :type="getOverallStatusTag(caseInfo.status)">
-              {{ getStatusText(caseInfo.status) }}
-            </el-tag>
           </div>
 
           <div class="timeline-scroll-container">
@@ -18,20 +15,20 @@
                 :key="stage.key"
                 class="timeline-item"
                 :class="{
-                  active: activeStage === stage.key,
-                  completed: stage.status === 'completed',
-                  'in-progress': stage.status === 'in_progress',
-                  pending: stage.status === 'pending'
+                  active: stage.status == 'active',
+                  completed: stage.status == 'completed',
+                  progress: stage.status == 'progress',
+                  pending: stage.status == 'pending'
                 }"
                 @click="handleStageClick(stage)"
               >
                 <div class="timeline-marker">
                   <i
-                    v-if="stage.status === 'completed'"
+                    v-if="stage.status == 'completed'"
                     class="el-icon-check"
                   ></i>
                   <i
-                    v-else-if="stage.status === 'in_progress'"
+                    v-else-if="stage.status == 'progress'"
                     class="el-icon-loading"
                   ></i>
                   <i v-else class="el-icon-time"></i>
@@ -40,25 +37,21 @@
                 <div class="timeline-content">
                   <div class="stage-header">
                     <span class="stage-name">{{ stage.name }}</span>
-                    <el-tag
-                      size="small"
-                      :type="getStageStatusTag(stage.status)"
-                    >
-                      {{ getStageStatusText(stage.status) }}
-                    </el-tag>
+                    <dict-tag
+                      :options="dict.type[stage.dict]"
+                      :value="stage.state"
+                    />
                   </div>
 
                   <div class="stage-info">
-                    <div v-if="stage.completeTime" class="time-info">
-                      <span
-                        >瀹屾垚鏃堕棿: {{ formatTime(stage.completeTime) }}</span
-                      >
+                    <div v-if="stage.createtime" class="time-info">
+                      鍒涘缓鏃堕棿: {{ formatTime(stage.createtime) }}
                     </div>
                     <div v-if="stage.updateTime" class="time-info">
-                      <span>鏈�杩戞洿鏂�: {{ formatTime(stage.updateTime) }}</span>
+                      鏈�杩戞洿鏂�: {{ formatTime(stage.updateTime) }}
                     </div>
                     <div v-if="stage.operator" class="operator-info">
-                      <span>璐熻矗浜�: {{ stage.operator }}</span>
+                      璐熻矗浜�: {{ stage.operator }}
                     </div>
                   </div>
                 </div>
@@ -67,19 +60,15 @@
           </div>
         </div>
 
-        <!-- 鍙充晶鍐呭鍖哄煙 - 鐙珛婊氬姩 -->
+        <!-- 鍙充晶鍐呭 -->
         <div class="content-section">
-          <!-- 妗堜緥鍩烘湰淇℃伅 - 鍥哄畾楂樺害锛屽彲婊氬姩 -->
           <case-basic-info :case-id="caseId" :show-attachment="true" />
 
-          <!-- 闃舵璇︽儏鍐呭 - 鑷�傚簲楂樺害锛屽彲婊氬姩 -->
           <div class="stage-detail-section">
             <div class="section-header">
               <h3>{{ activeStageName }} - 闃舵璇︽儏</h3>
-              <div class="stage-actions"></div>
             </div>
 
-            <!-- 鍔ㄦ�侀樁娈靛唴瀹� -->
             <div class="stage-content-wrapper">
               <component
                 :is="getStageComponent()"
@@ -96,135 +85,178 @@
 </template>
 
 <script>
+// ===================== 瀛楀吀 Label 鈫� UI 涓婚 =====================
+function mapDictLabelToTheme(label) {
+  if (!label) return "pending";
+
+  const l = label.trim();
+
+  // 寰� XX
+  if (/^寰�/.test(l)) {
+    return "progress";
+  }
+
+  // XX涓�
+  if (/涓�$/.test(l)) {
+    return "active";
+  }
+
+  // 瀹屾垚 / 瀹屾垚XX
+  if (/瀹屾垚/.test(l)) {
+    return "completed";
+  }
+
+  // 寮冪敤 / 鏀惧純
+  if (/寮冪敤|鏀惧純/.test(l)) {
+    return "danger";
+  }
+
+  return "pending";
+}
 import { getDonatebaseinfoflow } from "@/api/project/donatebaseinfo";
-import { getDonationProcessDetail } from "./donationProcess";
+import CaseBasicInfo from "@/components/CaseBasicInfo";
+
 import DonorMaintenanceStage from "./components/DonorMaintenanceStage";
-import MedicalAssessmentStage from "./components/MedicalAssessmentStage";
 import DeathJudgmentStage from "./components/DeathJudgmentStage";
+import MedicalAssessmentStage from "./components/MedicalAssessmentStage";
 import DonationConfirmStage from "./components/DonationConfirmStage";
 import EthicalReviewStage from "./components/EthicalReviewStage";
 import OrganAllocationStage from "./components/OrganAllocationStage";
 import OrganProcurementStage from "./components/OrganProcurementStage";
 import OrganUtilizationStage from "./components/OrganUtilizationStage";
-import CaseBasicInfo from "@/components/CaseBasicInfo";
 
 import dayjs from "dayjs";
+
+// ============== 瀛楀吀鏄犲皠锛堜綘鍚庨潰鑷繁鏀癸級 ==============
+const STAGE_DICT_MAP = {
+  donatemaintenance: "maintain_type",
+  deathinfo: "decide_type",
+  medicalevaluation: "state_Evaluation",
+  relativesconfirmation: "affirm_type",
+  donateflowcharts: "sys_ethical",
+  donateorgansService: "allocation_Status",
+  donationwitness: "Obtain_status",
+  donatecompletioninfo: "utilize_statue"
+};
+
+// state -> 娴佺▼鐘舵��
+const STATE_MAP = {
+  0: "pending",
+  1: "progress",
+  2: "completed",
+  3: "terminated"
+};
+
+// 闃舵閰嶇疆
+const STAGE_CONFIG = [
+  { key: "donor_maintenance", name: "渚涜�呯淮鎶�", apiKey: "donatemaintenance" },
+  { key: "death_judgment", name: "姝讳骸鍒ゅ畾", apiKey: "deathinfo" },
+  { key: "medical_assessment", name: "鍖诲璇勪及", apiKey: "medicalevaluation" },
+  {
+    key: "donation_confirm",
+    name: "鎹愮尞纭",
+    apiKey: "relativesconfirmation"
+  },
+  { key: "ethical_review", name: "浼︾悊瀹℃煡", apiKey: "donateflowcharts" },
+  { key: "organ_allocation", name: "鍣ㄥ畼鍒嗛厤", apiKey: "donateorgansService" },
+  { key: "organ_procurement", name: "鍣ㄥ畼鑾峰彇", apiKey: "donationwitness" },
+  { key: "organ_utilization", name: "鍣ㄥ畼鍒╃敤", apiKey: "donatecompletioninfo" }
+];
 
 export default {
   name: "DonationProcessDetail",
   components: {
+    CaseBasicInfo,
     DonorMaintenanceStage,
-    MedicalAssessmentStage,
     DeathJudgmentStage,
+    MedicalAssessmentStage,
     DonationConfirmStage,
     EthicalReviewStage,
     OrganAllocationStage,
     OrganProcurementStage,
-    OrganUtilizationStage,
-    CaseBasicInfo
+    OrganUtilizationStage
   },
-  dicts: ["sys_user_sex", "sys_BloodType", "sys_0_1"],
+  dicts: [
+    "decide_type",
+    "maintain_type",
+    "state_Evaluation",
+    "affirm_type",
+    "sys_ethical",
+    "allocation_Status",
+    "Obtain_status",
+    "utilize_statue"
+  ], // 杩欓噷鍙0鏄庝竴涓嵆鍙紝鍏朵綑閫氳繃 dict.type[xxx] 浣跨敤
   data() {
     return {
       caseId: null,
-      infoid: null,
-      caseInfo: {
-        id: "",
-        caseNo: "",
-        hospitalNo: "",
-        donorName: "",
-        gender: "",
-        age: "",
-        bloodType: "",
-        diagnosis: "",
-        status: "in_progress",
-        createTime: "",
-        registrant: "",
-        currentStage: "donor_maintenance"
-      },
-      processStages: [
-        {
-          key: "donor_maintenance",
-          name: "渚涜�呯淮鎶�",
-          status: "completed",
-          completeTime: "2025-12-01 10:00:00",
-          updateTime: "2025-12-01 10:00:00",
-          operator: "寮犲尰鐢�"
-        },
-        {
-          key: "death_judgment",
-          name: "姝讳骸鍒ゅ畾",
-          status: "completed",
-          completeTime: "2025-12-02 14:30:00",
-          updateTime: "2025-12-02 14:30:00",
-          operator: "鐜嬪尰鐢�"
-        },
-        {
-          key: "medical_assessment",
-          name: "鍖诲璇勪及",
-          status: "completed",
-
-          completeTime: "2025-12-03 09:15:00",
-          updateTime: "2025-12-03 09:15:00",
-          operator: "鏉庝富浠�"
-        },
-        {
-          key: "donation_confirm",
-          name: "鎹愮尞纭",
-          status: "completed",
-          completeTime: "2025-12-03 11:00:00",
-          updateTime: "2025-12-03 11:00:00",
-          operator: "璧靛崗璋冨憳"
-        },
-        {
-          key: "ethical_review",
-          name: "浼︾悊瀹℃煡",
-          status: "completed",
-          completeTime: "2025-12-03 15:20:00",
-          updateTime: "2025-12-03 15:20:00",
-          operator: "浼︾悊濮斿憳浼�"
-        },
-        {
-          key: "organ_allocation",
-          name: "鍣ㄥ畼鍒嗛厤",
-          status: "in_progress",
-          updateTime: "2025-12-04 10:00:00",
-          operator: "鍒嗛厤绯荤粺"
-        },
-        {
-          key: "organ_procurement",
-          name: "鍣ㄥ畼鑾峰彇",
-          status: "in_progress",
-          operator: "寰呭垎閰�"
-        },
-        {
-          key: "organ_utilization",
-          name: "鍣ㄥ畼鍒╃敤",
-          status: "in_progress",
-          operator: "寰呭垎閰�"
-        }
-      ],
-      activeStage: "organ_allocation",
-      activeStageName: "鍣ㄥ畼鍒嗛厤",
-      activeStageData: {},
-      loading: false
+      caseInfo: {},
+      processStages: [],
+      activeStage: "",
+      activeStageName: "",
+      activeStageData: {}
     };
   },
-  computed: {},
   created() {
     this.caseId = this.$route.query.id;
-    this.infoid = this.$route.query.id;
-
     if (this.caseId) {
       this.getDetail();
-    } else {
-      this.generateMockData();
     }
-    this.setActiveStage(this.activeStage);
   },
   methods: {
+    async getDetail() {
+      try {
+        const res = await getDonatebaseinfoflow(this.caseId);
+
+        const data = res;
+
+        this.caseInfo = data.donatebaseinfo || {};
+
+        this.processStages = STAGE_CONFIG.map(stage => {
+          const obj = data[stage.apiKey] || {};
+          console.log(stage.apiKey, "stage.apiKey");
+          console.log(this.dict?.type?.[STAGE_DICT_MAP[stage.apiKey]]);
+
+          const dictLabel =
+            this.dict?.type?.[STAGE_DICT_MAP[stage.apiKey]]?.find(
+              d => d.value == obj.state
+            )?.label || "";
+
+          const theme = mapDictLabelToTheme(dictLabel);
+
+          return {
+            key: stage.key,
+            name: stage.name,
+            dict: STAGE_DICT_MAP[stage.apiKey],
+            state: obj.state,
+            dictLabel,
+            status: theme, // 鉁� 鏍稿績锛歎I 涓婚鐢� dictLabel 鍐冲畾
+            createtime: obj.createtime,
+            updateTime: obj.updatetime,
+            operator: obj.updateperson || obj.createperson
+          };
+        });
+
+        const active =
+          this.processStages.find(s => s.status == "progress") ||
+          [...this.processStages].reverse().find(s => s.status == "completed");
+
+        this.setActiveStage(active?.key || STAGE_CONFIG[0].key);
+      } catch (e) {
+        console.error(e);
+        this.$message.error("鑾峰彇娴佺▼璇︽儏澶辫触");
+      }
+    },
+
+    setActiveStage(key) {
+      const stage = this.processStages.find(s => s.key == key);
+      if (!stage) return;
+      this.activeStage = key;
+      this.activeStageName = stage.name;
+      this.activeStageData = stage;
+    },
+
     getStageComponent() {
-      const componentMap = {
+      const map = {
         donor_maintenance: "DonorMaintenanceStage",
         death_judgment: "DeathJudgmentStage",
         medical_assessment: "MedicalAssessmentStage",
@@ -234,169 +266,19 @@
         organ_procurement: "OrganProcurementStage",
         organ_utilization: "OrganUtilizationStage"
       };
-      return componentMap[this.activeStage];
+      return map[this.activeStage];
     },
-    // 鑾峰彇璇︽儏鏁版嵁
-    async getDetail() {
-      this.loading = true;
-      try {
-        const response = await getDonatebaseinfoflow(this.caseId);
-        if (response.code === 200) {
-          this.caseInfo = response.data.caseInfo;
-          this.processStages = response.data.processStages;
-          this.setActiveStage(response.data.currentStage);
-        }
-      } catch (error) {
-        console.error("鑾峰彇鎹愮尞杩涚▼璇︽儏澶辫触:", error);
-        this.$message.error("鑾峰彇璇︽儏澶辫触");
-      } finally {
-        this.loading = false;
-      }
-    },
-    // 鐢熸垚妯℃嫙鏁版嵁
-    generateMockData() {
-      this.caseInfo = {
-        id: "202512001",
-        caseNo: "C202512001",
-        hospitalNo: "D202512001",
-        donorName: "寮犱笁",
-        gender: "0",
-        age: 45,
-        bloodType: "A",
-        diagnosis: "鑴戝浼�",
-        status: "in_progress",
-        createTime: "2025-12-01 08:00:00",
-        registrant: "鏉庡崗璋冨憳",
-        currentStage: "organ_allocation"
-      };
-    },
-    // 璁剧疆褰撳墠婵�娲婚樁娈�
-    setActiveStage(stageKey) {
-      this.activeStage = stageKey;
-      const stage = this.processStages.find(s => s.key === stageKey);
-      if (stage) {
-        this.activeStageName = stage.name;
-        this.activeStageData = stage;
-        console.log(this.activeStageData, "this.activeStageData");
-      }
-    },
-    // 澶勭悊闃舵鐐瑰嚮
+
     handleStageClick(stage) {
-      if (stage.status !== "pending") {
-        this.setActiveStage(stage.key);
-      } else {
-        this.$message.warning("璇ラ樁娈靛皻鏈紑濮嬶紝鏃犳硶鏌ョ湅璇︽儏");
+      if (stage.status == "pending") {
+        this.$message.warning("璇ラ樁娈靛皻鏈紑濮�");
+        return;
       }
+      this.setActiveStage(stage.key);
     },
-    // 鑾峰彇闃舵鐘舵�佹爣绛剧被鍨�
-    getStageStatusTag(status) {
-      const map = {
-        completed: "success",
-        in_progress: "warning",
-        pending: "info"
-      };
-      return map[status] || "info";
-    },
-    // 鑾峰彇闃舵鐘舵�佹枃鏈�
-    getStageStatusText(status) {
-      const map = {
-        completed: "宸插畬鎴�",
-        in_progress: "杩涜涓�",
-        pending: "鏈紑濮�"
-      };
-      return map[status] || "鏈煡";
-    },
-    // 鑾峰彇鏁翠綋鐘舵�佹爣绛剧被鍨�
-    getOverallStatusTag(status) {
-      const map = {
-        completed: "success",
-        in_progress: "warning",
-        pending: "info",
-        terminated: "danger"
-      };
-      return map[status] || "info";
-    },
-    // 鑾峰彇鏁翠綋鐘舵�佹枃鏈�
-    getStatusText(status) {
-      const map = {
-        completed: "宸插畬鎴�",
-        in_progress: "杩涜涓�",
-        pending: "鏈紑濮�",
-        terminated: "宸茬粓姝�"
-      };
-      return map[status] || "鏈煡";
-    },
-    // 鏃堕棿鏍煎紡鍖�
+
     formatTime(time) {
-      if (!time) return "-";
-      return dayjs(time).format("YYYY-MM-DD HH:mm");
-    },
-
-    // 鑾峰彇褰撳墠闃舵鍚嶇О
-    getCurrentStageName() {
-      const currentStage = this.processStages.find(
-        stage => stage.status === "in_progress"
-      );
-      return currentStage ? currentStage.name : "宸插畬鎴�";
-    },
-    // 缂栬緫鍩烘湰淇℃伅
-    handleEditBasicInfo() {
-      this.$message.info("缂栬緫鍩烘湰淇℃伅鍔熻兘");
-    },
-    // 瀹屾垚闃舵
-    handleCompleteStage() {
-      this.$confirm(`纭畾瑕佸畬鎴愩��${this.activeStageName}銆戦樁娈靛悧锛焋, "鎻愮ず", {
-        confirmButtonText: "纭畾",
-        cancelButtonText: "鍙栨秷",
-        type: "warning"
-      }).then(() => {
-        // 鏇存柊褰撳墠闃舵鐘舵��
-        const currentIndex = this.processStages.findIndex(
-          stage => stage.key === this.activeStage
-        );
-
-        if (currentIndex !== -1) {
-          this.processStages[currentIndex].status = "completed";
-          this.processStages[
-            currentIndex
-          ].completeTime = new Date().toISOString();
-
-          // 婵�娲讳笅涓�涓樁娈�
-          if (currentIndex < this.processStages.length - 1) {
-            this.processStages[currentIndex + 1].status = "in_progress";
-            this.setActiveStage(this.processStages[currentIndex + 1].key);
-          } else {
-            this.caseInfo.status = "completed";
-          }
-
-          this.$message.success("闃舵宸插畬鎴�");
-        }
-      });
-    },
-    // 鏌ョ湅璇︽儏
-    handleViewDetail() {
-      const routeMap = {
-        donor_maintenance: "/case/donorMaintenance/detail",
-        death_judgment: "/case/deathJudgment/detail",
-        medical_assessment: "/case/medicalAssessment/detail",
-        donation_confirm: "/case/donationConfirm/detail",
-        ethical_review: "/case/ethicalReview/detail",
-        organ_allocation: "/case/organAllocation/detail",
-        organ_procurement: "/case/organProcurement/detail",
-        organ_utilization: "/case/organUtilization/detail"
-      };
-
-      const route = routeMap[this.activeStage];
-      if (route) {
-        this.$router.push({
-          path: route,
-          query: { id: this.caseId }
-        });
-      }
-    },
-    // 淇敼闃舵淇℃伅
-    handleModifyStage() {
-      this.$message.info(`淇敼${this.activeStageName}淇℃伅鍔熻兘`);
+      return time ? dayjs(time).format("YYYY-MM-DD HH:mm") : "-";
     }
   }
 };
@@ -418,31 +300,40 @@
 
 .process-container {
   display: flex;
-  min-height: 600px; /* 璁剧疆涓�涓渶灏忛珮搴� */
+  min-height: 600px;
+  /* 璁剧疆涓�涓渶灏忛珮搴� */
   gap: 20px;
-  align-items: flex-start; /* 椤堕儴瀵归綈 */
+  align-items: flex-start;
+  /* 椤堕儴瀵归綈 */
 }
 
 /* 宸︿晶鏃堕棿绾挎牱寮� - 鍥哄畾楂樺害锛屽唴閮ㄦ粴鍔� */
 .timeline-section {
-  flex: 0 0 320px; /* 鍥哄畾瀹藉害 */
+  flex: 0 0 320px;
+  /* 鍥哄畾瀹藉害 */
   display: flex;
   flex-direction: column;
   background: white;
   border-radius: 6px;
   padding: 20px;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
-  height: calc(120vh - 120px); /* 鏍规嵁瑙嗗彛楂樺害鑷�傚簲 */
-  max-height: 1200px; /* 璁剧疆鏈�澶ч珮搴� */
-  position: sticky; /* 浣跨敤 sticky 瀹氫綅 */
-  top: 20px; /* 璺濈椤堕儴 20px */
+  height: calc(120vh - 120px);
+  /* 鏍规嵁瑙嗗彛楂樺害鑷�傚簲 */
+  max-height: 1200px;
+  /* 璁剧疆鏈�澶ч珮搴� */
+  position: sticky;
+  /* 浣跨敤 sticky 瀹氫綅 */
+  top: 20px;
+  /* 璺濈椤堕儴 20px */
 }
 
 .timeline-scroll-container {
   flex: 1;
-  overflow-y: auto; /* 鍐呴儴鍙粴鍔� */
+  overflow-y: auto;
+  /* 鍐呴儴鍙粴鍔� */
   margin-top: 20px;
-  padding-right: 8px; /* 涓烘粴鍔ㄦ潯鐣欏嚭绌洪棿 */
+  padding-right: 8px;
+  /* 涓烘粴鍔ㄦ潯鐣欏嚭绌洪棿 */
 }
 
 .timeline-scroll-container::-webkit-scrollbar {
@@ -476,7 +367,8 @@
   display: flex;
   flex-direction: column;
   gap: 20px;
-  min-height: 0; /* 閲嶈锛氬厑璁竑lex瀛愰」鍘嬬缉 */
+  min-height: 0;
+  /* 閲嶈锛氬厑璁竑lex瀛愰」鍘嬬缉 */
 }
 
 .basic-info-section {
@@ -486,13 +378,16 @@
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
   display: flex;
   flex-direction: column;
-  min-height: 0; /* 閲嶈 */
+  min-height: 0;
+  /* 閲嶈 */
 }
 
 .basic-info-content {
   flex: 1;
-  max-height: 300px; /* 鍩烘湰淇℃伅鍖哄煙鏈�澶ч珮搴� */
-  overflow-y: auto; /* 鍩烘湰淇℃伅鍐呴儴鍙粴鍔� */
+  max-height: 300px;
+  /* 鍩烘湰淇℃伅鍖哄煙鏈�澶ч珮搴� */
+  overflow-y: auto;
+  /* 鍩烘湰淇℃伅鍐呴儴鍙粴鍔� */
   margin-top: 20px;
   padding-right: 8px;
 }
@@ -520,24 +415,30 @@
 }
 
 .stage-detail-section {
-  flex: 1; /* 鍗犳嵁鍓╀綑绌洪棿 */
+  flex: 1;
+  /* 鍗犳嵁鍓╀綑绌洪棿 */
   background: white;
   border-radius: 6px;
   padding: 20px;
   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
   display: flex;
   flex-direction: column;
-  min-height: 400px; /* 鏈�灏忛珮搴� */
-  max-height: 800px; /* 鏈�澶ч珮搴︼紝鍙牴鎹渶瑕佽皟鏁� */
-  overflow: hidden; /* 闅愯棌澶栧眰婧㈠嚭 */
+  min-height: 400px;
+  /* 鏈�灏忛珮搴� */
+  max-height: 800px;
+  /* 鏈�澶ч珮搴︼紝鍙牴鎹渶瑕佽皟鏁� */
+  overflow: hidden;
+  /* 闅愯棌澶栧眰婧㈠嚭 */
 }
 
 .stage-content-wrapper {
   flex: 1;
-  overflow-y: auto; /* 闃舵璇︽儏鍐呴儴鍙粴鍔� */
+  overflow-y: auto;
+  /* 闃舵璇︽儏鍐呴儴鍙粴鍔� */
   margin-top: 20px;
   padding-right: 8px;
-  min-height: 0; /* 閲嶈 */
+  min-height: 0;
+  /* 閲嶈 */
 }
 
 .stage-content-wrapper::-webkit-scrollbar {
@@ -563,7 +464,8 @@
   display: flex;
   justify-content: space-between;
   align-items: center;
-  flex-shrink: 0; /* 闃叉琚帇缂� */
+  flex-shrink: 0;
+  /* 闃叉琚帇缂� */
 }
 
 .section-header h3 {
@@ -581,14 +483,22 @@
   cursor: pointer;
   transition: all 0.3s ease;
   border: 1px solid #e4e7ed;
-  flex-shrink: 0; /* 闃叉琚帇缂� */
+  flex-shrink: 0;
+  /* 闃叉琚帇缂� */
 }
 
 .timeline-item:hover {
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
   transform: translateY(-1px);
 }
+.timeline-item.danger {
+  border-color: #f56c6c;
+  background-color: #fef0f0;
+}
 
+.timeline-item.danger .timeline-marker {
+  background-color: #f56c6c;
+}
 .timeline-item.active {
   border-color: #409eff;
   background-color: #f0f9ff;
@@ -599,7 +509,7 @@
   background-color: #f0f9e8;
 }
 
-.timeline-item.in-progress {
+.timeline-item.progress {
   border-color: #e6a23c;
   background-color: #fdf6ec;
 }
@@ -624,8 +534,11 @@
 .timeline-item.completed .timeline-marker {
   background-color: #67c23a;
 }
+.timeline-item.active .timeline-marker {
+  background-color: #409eff;
+}
 
-.timeline-item.in-progress .timeline-marker {
+.timeline-item.progress .timeline-marker {
   background-color: #e6a23c;
 }
 
@@ -684,7 +597,8 @@
     width: 100%;
     height: auto;
     max-height: 300px;
-    position: static; /* 灏忓睆骞曞彇娑� sticky */
+    position: static;
+    /* 灏忓睆骞曞彇娑� sticky */
   }
 
   .timeline-scroll-container {

--
Gitblit v1.9.3