From 4334e4d5f680b4375d7af4ba9e4d8c8baef7266b Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 14 九月 2026 11:02:29 +0800
Subject: [PATCH] feat(production): 添加工序颜色配置和显示功能

---
 src/views/productionManagement/productionProcess/index.vue             |   47 ++++++++++++++-
 src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue |    5 +
 src/views/productionManagement/processStatistics/index.vue             |    4 +
 src/views/productionManagement/productionOrder/index.vue               |   56 ++++++++++++++++++
 src/views/reportAnalysis/productionAnalysis/components/left-top.vue    |   19 ++++--
 src/views/reportAnalysis/dataDashboard/index0.vue                      |    7 +
 src/views/productionManagement/workOrderManagement/index.vue           |    7 ++
 7 files changed, 131 insertions(+), 14 deletions(-)

diff --git a/src/views/productionManagement/processStatistics/index.vue b/src/views/productionManagement/processStatistics/index.vue
index 25fa531..c4bd777 100644
--- a/src/views/productionManagement/processStatistics/index.vue
+++ b/src/views/productionManagement/processStatistics/index.vue
@@ -33,7 +33,8 @@
                 class="mb-16">
           <div class="stats-card">
             <div class="card-header">
-              <span class="process-name">{{ item.name }}</span>
+              <span class="process-name"
+                    :style="item.color ? { backgroundColor: item.color, color: '#fff' } : {}">{{ item.name }}</span>
               <div class="header-stats">
                 <div class="stat-row">
                   <span class="label">璁″垝鏁�</span>
@@ -110,6 +111,7 @@
           good: item.goodQuantity || 0,
           bad: item.scrapQty || 0,
           percentage: Number(item.completionStatus || 0),
+          color: item.operationColor || "",
         }));
       })
       .finally(() => {
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 9ac0ffa..55edf93 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -83,6 +83,20 @@
                        :color="progressColor(toProgressPercentage(row?.completionStatus))"
                        :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
         </template>
+        <template #currentProcess="{ row }">
+          <template v-if="getCurrentProcess(row)">
+            <el-tag v-if="getCurrentProcess(row).done"
+                    type="success"
+                    size="small">鍏ㄩ儴瀹屾垚</el-tag>
+            <div v-else
+                 class="current-process-name">
+              <span class="process-color-dot"
+                    :style="{ background: getCurrentProcess(row).color || '#909399' }"></span>
+              <span :style="getCurrentProcess(row).color ? { color: getCurrentProcess(row).color } : {}">{{ getCurrentProcess(row).name }}</span>
+            </div>
+          </template>
+          <span v-else>-</span>
+        </template>
         <template #processRouteStatus="{ row }">
           <div v-if="row.processRouteStatus && row.processRouteStatus.length"
                class="process-progress-container">
@@ -95,7 +109,11 @@
                   <span class="step-percentage"
                         :style="{ color: item.percentage >= 70 ? item.percentage >= 100 ? '#67c23a' : '#f56c6c' : '#000' }">{{ item.percentage }}%</span>
                 </div>
-                <div class="step-name">{{ item.name }}</div>
+                <div class="step-name">
+                  <span v-if="item.color"
+                        :style="{ display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', marginRight: '4px', background: item.color }"></span>
+                  <span>{{ item.name }}</span>
+                </div>
               </div>
               <div v-if="index < row.processRouteStatus.length - 1"
                    class="step-line"></div>
@@ -285,6 +303,13 @@
       label: "鐢熶骇璁㈠崟鍙�",
       prop: "npsNo",
       width: "150px",
+    },
+    {
+      label: "褰撳墠宸ュ簭杩涘害",
+      prop: "currentProcess",
+      dataType: "slot",
+      slot: "currentProcess",
+      width: 160,
     },
     {
       label: "閿�鍞崟鍙�",
@@ -510,6 +535,19 @@
     if (p < 50) return "#e6a23c";
     if (p < 80) return "#409eff";
     return "#67c23a";
+  };
+
+  // 褰撳墠宸ュ簭锛氱涓�閬撳畬鎴愬害涓嶈冻100%鐨勫伐搴忥紱鍏ㄩ儴瀹屾垚杩斿洖 done
+  const getCurrentProcess = row => {
+    const list = row.processRouteStatus;
+    if (!Array.isArray(list) || list.length === 0) return null;
+    const current = list.find(item => toProgressPercentage(item.percentage) < 100);
+    if (!current) return { done: true };
+    return {
+      done: false,
+      name: current.name || "鏈煡宸ュ簭",
+      color: current.color || "",
+    };
   };
 
   // 娣诲姞琛ㄨ绫诲悕鏂规硶
@@ -865,6 +903,22 @@
     margin-top: unset;
   }
 
+  .current-process-name {
+    display: flex;
+    align-items: center;
+    font-size: 12px;
+    color: #303133;
+  }
+
+  .process-color-dot {
+    display: inline-block;
+    width: 8px;
+    height: 8px;
+    border-radius: 50%;
+    margin-right: 4px;
+    flex-shrink: 0;
+  }
+
   .process-progress-container {
     display: inline-flex;
     align-items: center;
diff --git a/src/views/productionManagement/productionProcess/index.vue b/src/views/productionManagement/productionProcess/index.vue
index ee49657..baa7264 100644
--- a/src/views/productionManagement/productionProcess/index.vue
+++ b/src/views/productionManagement/productionProcess/index.vue
@@ -21,7 +21,12 @@
                :class="{ active: selectedProcess?.id === process.id }"
                @click="selectProcess(process)">
             <div class="card-header">
-              <div class="process-name">{{ process.name }} <span class="process-code">{{ process.no }}</span></div>
+              <div class="process-name">
+                <span v-if="process.color"
+                      class="process-color-dot"
+                      :style="{ backgroundColor: process.color }"></span>
+                {{ process.name }} <span class="process-code">{{ process.no }}</span>
+              </div>
               <div class="card-actions">
                 <el-button link
                            type="primary"
@@ -138,6 +143,12 @@
             <el-radio :label="0">璁℃椂</el-radio>
             <el-radio :label="1">璁′欢</el-radio>
           </el-radio-group>
+        </el-form-item>
+        <el-form-item label="宸ュ簭棰滆壊"
+                      prop="color">
+          <el-color-picker v-model="processForm.color"
+                           :predefine="predefineColors" />
+          <span class="color-tip">鐢ㄤ簬鐢熶骇妯″潡宸ュ簭鏍囪瘑棰滆壊娓叉煋</span>
         </el-form-item>
         <el-form-item label="鍏宠仈璁惧"
                       prop="deviceLedgerId">
@@ -347,7 +358,18 @@
     remark: "",
     deviceLedgerId: null,
     type: 0,
+    color: "",
   });
+  const predefineColors = [
+    "#409eff",
+    "#67c23a",
+    "#e6a23c",
+    "#f56c6c",
+    "#909399",
+    "#9254de",
+    "#13c2c2",
+    "#fa8c16",
+  ];
   const processRules = {
     no: [{ required: true, message: "璇疯緭鍏ュ伐搴忕紪鐮�", trigger: "blur" }],
     name: [{ required: true, message: "璇疯緭鍏ュ伐搴忓悕绉�", trigger: "blur" }],
@@ -558,6 +580,7 @@
     processForm.remark = "";
     processForm.deviceLedgerId = null;
     processForm.type = 0;
+    processForm.color = "";
     processDialogVisible.value = true;
   };
 
@@ -575,6 +598,7 @@
     const hasDevice = deviceOptions.value.some(item => item.id === deviceId);
     processForm.deviceLedgerId = deviceId && hasDevice ? deviceId : null;
     processForm.type = process.type;
+    processForm.color = process.color || "";
     processDialogVisible.value = true;
   };
 
@@ -603,8 +627,10 @@
   const handleProcessSubmit = () => {
     processFormRef.value.validate(valid => {
       if (valid) {
+        // 棰滆壊娓呯┖鍚庝负 null锛屽悗绔� updateById 浼氬拷鐣� null 瀛楁锛岀粺涓�杞负绌轰覆鎻愪氦
+        const submitData = { ...processForm, color: processForm.color || "" };
         if (processForm.id) {
-          update(processForm)
+          update(submitData)
             .then(() => {
               ElMessage.success("缂栬緫鎴愬姛");
               processDialogVisible.value = false;
@@ -614,7 +640,7 @@
               ElMessage.error("缂栬緫澶辫触");
             });
         } else {
-          add(processForm)
+          add(submitData)
             .then(() => {
               ElMessage.success("鏂板鎴愬姛");
               processDialogVisible.value = false;
@@ -877,6 +903,15 @@
         font-family: "Courier New", monospace;
       }
 
+      .process-color-dot {
+        display: inline-block;
+        width: 10px;
+        height: 10px;
+        border-radius: 50%;
+        margin-right: 6px;
+        vertical-align: middle;
+      }
+
       .card-actions {
         display: flex;
         gap: 4px;
@@ -990,6 +1025,12 @@
     justify-content: center;
   }
 
+  .color-tip {
+    margin-left: 10px;
+    font-size: 12px;
+    color: #909399;
+  }
+
   // 琛ㄦ牸鏍峰紡
   :deep(.el-table) {
     border: none;
diff --git a/src/views/productionManagement/workOrderManagement/index.vue b/src/views/productionManagement/workOrderManagement/index.vue
index f388a69..bbb1858 100644
--- a/src/views/productionManagement/workOrderManagement/index.vue
+++ b/src/views/productionManagement/workOrderManagement/index.vue
@@ -44,6 +44,11 @@
                        :color="progressColor(toProgressPercentage(row?.completionStatus))"
                        :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
         </template>
+        <template #operationName="{ row }">
+          <span v-if="row.operationColor"
+                :style="{ display: 'inline-block', width: '8px', height: '8px', borderRadius: '50%', marginRight: '4px', background: row.operationColor }"></span>
+          <span>{{ row.operationName }}</span>
+        </template>
         <template #picked="{ row }">
           <el-tag :type="row.picked ? 'success' : 'info'"
                   size="small">
@@ -332,6 +337,8 @@
       label: "宸ュ簭鍚嶇О",
       prop: "operationName",
       width: "100",
+      dataType: "slot",
+      slot: "operationName",
     },
     {
       label: "闇�姹傛暟閲�",
diff --git a/src/views/reportAnalysis/dataDashboard/index0.vue b/src/views/reportAnalysis/dataDashboard/index0.vue
index ff92e41..b7424d5 100644
--- a/src/views/reportAnalysis/dataDashboard/index0.vue
+++ b/src/views/reportAnalysis/dataDashboard/index0.vue
@@ -820,8 +820,11 @@
 		}
 		
 		if (res.data.processQuantityDetails && Array.isArray(res.data.processQuantityDetails)) {
-			// 璁剧疆Y杞存暟鎹紙鍦ㄥ埗鍝佹暟閲忥級
-			workInProcessBarSeries.value[0].data = res.data.processQuantityDetails
+			// 璁剧疆Y杞存暟鎹紙鍦ㄥ埗鍝佹暟閲忥級锛屾湁宸ュ簭棰滆壊鏃舵寜棰滆壊娓叉煋鏌卞瓙
+			const processColors = Array.isArray(res.data.processColors) ? res.data.processColors : []
+			workInProcessBarSeries.value[0].data = res.data.processQuantityDetails.map((v, i) =>
+				processColors[i] ? { value: v, itemStyle: { color: processColors[i] } } : v
+			)
 		} else {
 			workInProcessBarSeries.value[0].data = []
 		}
diff --git a/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
index e6e8189..0413e6d 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
@@ -133,7 +133,10 @@
         workInProcessXAxis.value[0].data = []
       }
       if (res.data.processQuantityDetails && Array.isArray(res.data.processQuantityDetails)) {
-        workInProcessBarSeries.value[0].data = res.data.processQuantityDetails
+        const colors = Array.isArray(res.data.processColors) ? res.data.processColors : []
+        workInProcessBarSeries.value[0].data = res.data.processQuantityDetails.map((v, i) =>
+          colors[i] ? { value: v, itemStyle: { color: colors[i] } } : v
+        )
       } else {
         workInProcessBarSeries.value[0].data = []
       }
diff --git a/src/views/reportAnalysis/productionAnalysis/components/left-top.vue b/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
index c4532ad..1f7994b 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
@@ -60,7 +60,7 @@
     icon: 'circle',
     textStyle: {
       fontSize: 18,
-      color: pieColors[idx % pieColors.length],
+      color: d.color || pieColors[idx % pieColors.length],
     },
   }))
 
@@ -154,11 +154,18 @@
     .then((res) => {
       if (res.code === 200 && Array.isArray(res.data)) {
         const items = res.data
-        pieDatas.value = items.map((item) => ({
-          name: item.name,
-          value: parseFloat(item.value) || 0,
-          rate: item.rate,
-        }))
+        pieDatas.value = items.map((item) => {
+          const point = {
+            name: item.name,
+            value: parseFloat(item.value) || 0,
+            rate: item.rate,
+          }
+          if (item.color) {
+            point.color = item.color
+            point.itemStyle = { color: item.color }
+          }
+          return point
+        })
       }
     })
     .catch((err) => {

--
Gitblit v1.9.3