From 1524fa42ddf01fd72207a8a4b4667a48e4f233aa Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期五, 11 七月 2025 13:39:02 +0800
Subject: [PATCH] refactor(eims): 重构预测性维护模块

---
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue |  352 +++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 225 insertions(+), 127 deletions(-)

diff --git a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue
index eb36187..4c2ea27 100644
--- a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue
@@ -7,24 +7,33 @@
     />
 
     <a-row :gutter="16" class="mt-4">
-      <!-- 璁惧鍩烘湰淇℃伅 -->
-      <a-col :span="8">
-        <a-card title="璁惧鍩烘湰淇℃伅" class="mb-4" :style="{ height: '440px' }">
-          <a-descriptions bordered :column="1">
-            <a-descriptions-item label="璁惧鍚嶇О">{{ deviceInfo.deviceName }}</a-descriptions-item>
-            <a-descriptions-item label="璁惧绫诲瀷">{{ deviceInfo.deviceType }}</a-descriptions-item>
-            <a-descriptions-item label="璁惧缂栧彿">{{ deviceInfo.deviceId }}</a-descriptions-item>
-            <a-descriptions-item label="瀹夎鏃ユ湡">{{ deviceInfo.installDate }}</a-descriptions-item>
-            <a-descriptions-item label="浣跨敤骞撮檺">{{ deviceInfo.serviceLife }}骞�</a-descriptions-item>
-            <a-descriptions-item label="褰撳墠鐘舵��">
-              <a-tag :color="deviceInfo.statusColor">{{ deviceInfo.status }}</a-tag>
-            </a-descriptions-item>
-          </a-descriptions>
+      <!-- 璁惧鍥剧墖鍜岃澶囧熀鏈俊鎭悎骞� -->
+      <a-col :span="10">
+        <a-card title="璁惧淇℃伅" class="mb-4" :style="{ height: '440px' }">
+          <a-row :gutter="16">
+            <a-col :span="12">
+              <div class="device-image-container">
+                <img src="/src/assets/images/T850-840.2.jpg" alt="璁惧鍥剧墖" class="device-image" />
+              </div>
+            </a-col>
+            <a-col :span="12">
+              <a-descriptions bordered :column="1">
+                <a-descriptions-item label="璁惧鍚嶇О">{{ deviceInfo.deviceName }}</a-descriptions-item>
+                <a-descriptions-item label="璁惧绫诲瀷">{{ deviceInfo.deviceType }}</a-descriptions-item>
+                <a-descriptions-item label="璁惧缂栧彿">{{ deviceInfo.deviceId }}</a-descriptions-item>
+                <a-descriptions-item label="瀹夎鏃ユ湡">{{ deviceInfo.installDate }}</a-descriptions-item>
+                <a-descriptions-item label="浣跨敤骞撮檺">{{ deviceInfo.serviceLife }}骞�</a-descriptions-item>
+                <a-descriptions-item label="褰撳墠鐘舵��">
+                  <a-tag :color="deviceInfo.statusColor">{{ deviceInfo.status }}</a-tag>
+                </a-descriptions-item>
+              </a-descriptions>
+            </a-col>
+          </a-row>
         </a-card>
       </a-col>
 
       <!-- 璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿 -->
-      <a-col :span="16">
+      <a-col :span="14">
         <a-card title="璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿" class="mb-4" :style="{ height: '440px' }">
           <a-row :gutter="16">
             <a-col :span="8">
@@ -76,6 +85,56 @@
       </a-col>
     </a-row>
 
+    <!-- 璁惧鏁版嵁 -->
+    <a-col :span="24">
+      <a-card title="璁惧鏁版嵁" class="mb-4">
+        <a-row :gutter="[16, 16]">
+          <a-col :span="4">
+            <a-statistic title="鍔犲伐鏃堕棿" :value="healthData.xAxisTravel" suffix="km">
+              <template #prefix>
+                <FieldTimeOutlined />
+              </template>
+            </a-statistic>
+          </a-col>
+          <a-col :span="4">
+            <a-statistic title="鍒�鍏蜂娇鐢ㄦ鏁�" :value="healthData.yAxisTravel" suffix="km">
+              <template #prefix>
+                <FieldTimeOutlined />
+              </template>
+            </a-statistic>
+          </a-col>
+          <a-col :span="4">
+            <a-statistic title="鍒�鍏蜂娇鐢ㄦ椂闀�" :value="healthData.zAxisTravel" suffix="km">
+              <template #prefix>
+                <FieldTimeOutlined />
+              </template>
+            </a-statistic>
+          </a-col>
+          <a-col :span="4">
+            <a-statistic title="鍒�鍏锋洿鎹㈡鏁�" :value="healthData.toolChangeCount" suffix="娆�">
+              <template #prefix>
+                <WarningOutlined />
+              </template>
+            </a-statistic>
+          </a-col>
+          <a-col :span="4">
+            <a-statistic title="鍔犲伐闆朵欢鏁�" :value="healthData.partCount" suffix="浠�">
+              <template #prefix>
+                <AppstoreOutlined />
+              </template>
+            </a-statistic>
+          </a-col>
+          <a-col :span="4">
+            <a-statistic title="鍑洪敊鍋滄満鏃堕棿" :value="healthData.downtime" suffix="绉�">
+              <template #prefix>
+                <FieldTimeOutlined />
+              </template>
+            </a-statistic>
+          </a-col>
+        </a-row>
+      </a-card>
+    </a-col>
+
     <!-- 瀹炴椂鏁版嵁瓒嬪娍鍥� -->
     <a-card title="瀹炴椂鏁版嵁瓒嬪娍鍥�" class="mb-4">
       <a-row :gutter="16">
@@ -83,51 +142,21 @@
           <div id="spindleVibrationChart" style="height: 300px;"></div>
         </a-col>
         <a-col :span="8">
-          <div id="spindleTemperatureChart" style="height: 300px;"></div>
+          <div id="hydraulicOilTemperatureChart" style="height: 300px;"></div>
         </a-col>
-        <a-col :span="8">
-          <div id="spindleCurrentChart" style="height: 300px;"></div>
-        </a-col>
-      </a-row>
-      <a-row :gutter="16" class="mt-4">
         <a-col :span="8">
           <div id="spindleSpeedChart" style="height: 300px;"></div>
         </a-col>
-        <a-col :span="8">
-          <div id="servoMotorCurrentChart" style="height: 300px;"></div>
-        </a-col>
-        <a-col :span="8">
-          <div id="servoMotorTemperatureChart" style="height: 300px;"></div>
-        </a-col>
       </a-row>
-      <a-row :gutter="16" class="mt-4">
-        <a-col :span="8">
-          <div id="axisMotionSmoothnessChart" style="height: 300px;"></div>
-        </a-col>
-        <a-col :span="8">
-          <div id="guideRailTemperatureChart" style="height: 300px;"></div>
-        </a-col>
-        <a-col :span="8">
-          <div id="guideRailResistanceNoiseChart" style="height: 300px;"></div>
-        </a-col>
-      </a-row>
+
+
       <a-row :gutter="16" class="mt-4">
         <a-col :span="8">
           <div id="hydraulicPressureChart" style="height: 300px;"></div>
         </a-col>
         <a-col :span="8">
-          <div id="hydraulicFlowChart" style="height: 300px;"></div>
-        </a-col>
-        <a-col :span="8">
-          <div id="hydraulicOilTemperatureChart" style="height: 300px;"></div>
-        </a-col>
-      </a-row>
-      <a-row :gutter="16" class="mt-4">
-        <a-col :span="8">
-          <div id="airSourcePressureChart" style="height: 300px;"></div>
-        </a-col>
-        <a-col :span="8">
-          <div id="coolantFlowChart" style="height: 300px;"></div>
+          <div id="spindleTemperatureChart" style="height: 300px;"></div>
+
         </a-col>
         <a-col :span="8">
           <div id="coolantTemperatureChart" style="height: 300px;"></div>
@@ -136,9 +165,9 @@
 
     </a-card>
     <a-row :gutter="16">
-      <!-- 澶囦欢瀵垮懡棰勬祴 -->
+      <!-- 閮ㄤ欢瀵垮懡棰勬祴 -->
       <a-col :span="12">
-        <a-card title="澶囦欢瀵垮懡棰勬祴" class="mb-4">
+        <a-card title="閮ㄤ欢瀵垮懡棰勬祴" class="mb-4">
           <a-table
             :columns="sparePartColumns"
             :data-source="sparePartData"
@@ -170,27 +199,40 @@
 <script lang="ts">
 import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
 import * as echarts from 'echarts';
-
+import {
+  LineChartOutlined,
+  WarningOutlined,
+  AppstoreOutlined,
+  FieldTimeOutlined
+} from '@ant-design/icons-vue';
+import img from '#/assets/images/T850-840.2.jpg'
 export default defineComponent({
   name: 'CNCMachiningCenterDetail',
   setup() {
     // 妯℃嫙鏁版嵁
     const deviceInfo = reactive({
-      deviceName: 'CNC鍔犲伐涓績 #CNC-001',
+      deviceName: 'CNC鍔犲伐涓績',
       deviceType: 'CNC鍔犲伐涓績',
-      deviceId: 'CNC-2024-001',
-      installDate: '2023-08-20',
+      deviceId: 'GPC2024NL042',
+      installDate: '2024-08-14',
       serviceLife: 15,
       status: '杩愯涓�',
-      statusColor: '#52c41a'
+      statusColor: '#52c41a',
+      imageUrl: img // 娣诲姞璁惧鍥剧墖璺緞
     });
 
     const healthData = reactive({
       overallHealth: 95,
       healthColor: '#52c41a',
-      predictedLife: 4500,
+      predictedLife: 4436,
       riskLevel: '浣庨闄�',
-      riskColor: '#52c41a'
+      riskColor: '#52c41a',
+      xAxisTravel: 1200.5,
+      yAxisTravel: 980.2,
+      zAxisTravel: 500.1,
+      toolChangeCount: 25,
+      partCount: 1500,
+      downtime: 120
     });
 
     const maintenanceColumns = [
@@ -227,22 +269,22 @@
         key: '1',
         type: '渚嬭淇濆吇',
         content: '妫�鏌ヤ富杞存鼎婊戠郴缁�',
-        suggestedTime: '2024-07-15',
+        suggestedTime: '2025-07-15',
         urgency: '涓瓑'
       },
       {
         key: '2',
         type: '浼烘湇绯荤粺缁存姢',
         content: '妫�鏌杞翠己鏈嶇數鏈�',
-        suggestedTime: '2024-09-01',
+        suggestedTime: '2025-06-21',
         urgency: '浣�'
       },
       {
         key: '3',
         type: '瀵艰建缁存姢',
         content: '琛ュ厖瀵艰建娑︽粦娌�',
-        suggestedTime: '2024-08-01',
-        urgency: '楂�'
+        suggestedTime: '2025-06-01',
+        urgency: '浣�'
       }
     ]);
 
@@ -261,7 +303,7 @@
 
     const sparePartColumns = [
       {
-        title: '澶囦欢鍚嶇О',
+        title: '閮ㄤ欢鍚嶇О',
         dataIndex: 'name',
         key: 'name'
       },
@@ -365,25 +407,33 @@
     };
   },
 
+  components: {
+    LineChartOutlined,
+    WarningOutlined,
+    AppstoreOutlined,
+    FieldTimeOutlined
+  },
+
   mounted() {
     // 鍒濆鍖栧浘琛�
-    const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
+    const initChart = (chartId: string, title: string, seriesConfig: Array<{ name: string, data: any[], unit: string, baseValue: number, fluctuation: number, color: string }>) => {
       const chart = echarts.init(document.getElementById(chartId));
-      
+
       const updateChart = () => {
         // 鐢熸垚鏂扮殑鏁版嵁鐐�
         const now = new Date();
         const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
-        const newValue = (baseValue + (Math.random() * 2 - 1) * fluctuation).toFixed(2);
 
-        // 娣诲姞鏂版暟鎹偣锛屾渶澶氫繚鐣�60涓偣锛�5鍒嗛挓鏁版嵁锛�
-        chartData.push({
-          time,
-          value: newValue
+        seriesConfig.forEach(s => {
+          const newValue = (s.baseValue + (Math.random() * 2 - 1) * s.fluctuation).toFixed(2);
+          s.data.push({
+            time,
+            value: newValue
+          });
+          if (s.data.length > 60) {
+            s.data.shift();
+          }
         });
-        if (chartData.length > 60) {
-          chartData.shift();
-        }
 
         const option = {
           title: {
@@ -393,7 +443,11 @@
           tooltip: {
             trigger: 'axis',
             formatter: (params) => {
-              return `${params[0].axisValueLabel}<br/>${params[0].marker} ${params[0].seriesName}: ${params[0].data}${unit}`;
+              let result = `${params[0].axisValueLabel}<br/>`;
+              params.forEach(param => {
+                result += `${param.marker} ${param.seriesName}: ${param.data}${seriesConfig[param.seriesIndex].unit}<br/>`;
+              });
+              return result;
             }
           },
           grid: {
@@ -404,59 +458,69 @@
           },
           xAxis: {
             type: 'category',
-            data: chartData.map(item => item.time)
+            data: seriesConfig[0].data.map(item => item.time)
           },
-          yAxis: {
+          yAxis: seriesConfig.map((s, index) => ({
             type: 'value',
+            name: s.name,
+            position: index === 0 ? 'left' : 'right',
+            axisLine: {
+              show: true,
+            },
             axisLabel: {
-              formatter: (value) => `${value}${unit}`
+              formatter: (value) => `${value}${s.unit}`
             }
-          },
-          series: [
-            {
-              data: chartData.map(item => parseFloat(item.value)),
-              type: 'line',
-              smooth: true,
-              lineStyle: {
-                width: 2,
-                color: '#5470C6' // Default color
-              },
-              areaStyle: {
-                opacity: 0.8,
-                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-                  {
-                    offset: 0,
-                    color: 'rgba(84,112,198,0.3)'
-                  },
-                  {
-                    offset: 1,
-                    color: 'rgba(84,112,198,0)'
-                  }
-                ])
-              },
+          })),
+          series: seriesConfig.map((s, index) => ({
+            name: s.name,
+            data: s.data.map(item => parseFloat(item.value)),
+            type: 'line',
+            smooth: true,
+            yAxisIndex: index,
+            lineStyle: {
+              width: 2,
+              color: s.color
+            },
+            areaStyle: {
+              opacity: 0.8,
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                {
+                  offset: 0,
+                  color: 'rgba(84,112,198,0.3)'
+                },
+                {
+                  offset: 1,
+                  color: 'rgba(84,112,198,0)'
+                }
+              ])
+            },
             }
-          ]
+          )),
         };
         chart.setOption(option);
       };
-      
-      // 鐢熸垚鍒濆鏁版嵁鐐癸紙60涓偣锛�5鍒嗛挓鏁版嵁锛�
+
+      seriesConfig.forEach(s => {
+        s.data = [];
+        // 鐢熸垚鍒濆鏁版嵁鐐癸紙60涓偣锛�5鍒嗛挓鏁版嵁锛�
       for (let i = 0; i < 60; i++) {
         const now = new Date(Date.now() - (60 - i) * 5000); // 鐢熸垚杩囧幓5鍒嗛挓鐨勬暟鎹�
         const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
-        const newValue = (baseValue + (Math.random() * 2 - 1) * fluctuation).toFixed(2);
-        chartData.push({
+        const newValue = (s.baseValue + (Math.random() * 2 - 1) * s.fluctuation).toFixed(2);
+        s.data.push({
           time,
           value: newValue
         });
       }
-      
+      })
+
+
       // 鍒濆娓叉煋
       updateChart();
-      
+
       // 姣�5绉掓洿鏂颁竴娆℃暟鎹�
       const intervalId = setInterval(updateChart, 5000);
-      
+
       window.addEventListener('resize', () => {
         chart.resize();
       });
@@ -466,24 +530,52 @@
 
     };
 
-
-
-
-    initChart('spindleVibrationChart', '涓昏酱鎸姩', [], 'mm/s', 3.0, 0.5);
-    initChart('spindleTemperatureChart', '涓昏酱娓╁害', [], '掳C', 50, 3);
-    initChart('spindleCurrentChart', '涓昏酱鐢垫祦', [], 'A', 150, 10);
-    initChart('spindleSpeedChart', '涓昏酱杞��', [], 'RPM', 8000, 100);
-    initChart('servoMotorCurrentChart', '浼烘湇鐢垫満鐢垫祦', [], 'A', 50, 5);
-    initChart('servoMotorTemperatureChart', '浼烘湇鐢垫満娓╁害', [], '掳C', 45, 3);
-    initChart('axisMotionSmoothnessChart', '杞磋繍鍔ㄥ钩绋虫��', [], '', 0.8, 0.1);
-    initChart('guideRailTemperatureChart', '瀵艰建娓╁害', [], '掳C', 35, 2);
-    initChart('guideRailResistanceNoiseChart', '瀵艰建杩愬姩闃诲姏/鍣煶', [], 'dB', 10, 2);
-    initChart('hydraulicPressureChart', '娑插帇绯荤粺鍘嬪姏', [], 'bar', 150, 5);
-    initChart('hydraulicFlowChart', '娑插帇绯荤粺娴侀噺', [], 'L/min', 20, 2);
-    initChart('hydraulicOilTemperatureChart', '娑插帇娌规俯搴�', [], '掳C', 55, 3);
-    initChart('airSourcePressureChart', '姘旀簮鍘嬪姏', [], 'bar', 0.7, 0.05);
-    initChart('coolantFlowChart', '鍐峰嵈娑叉祦閲�', [], 'L/min', 30, 3);
-    initChart('coolantTemperatureChart', '鍐峰嵈娑叉俯搴�', [], '掳C', 28, 2);
+    // 杩愬姩绯荤粺鐩戞祴
+    initChart('spindleVibrationChart', '涓昏酱鎸姩', [
+      { name: '鎸姩', data: [], unit: 'mm/s', baseValue: 3.0, fluctuation: 0.5, color: '#5470C6' },
+    ]);
+    initChart('spindleTemperatureChart', '涓昏酱娓╁害', [
+      { name: '娓╁害', data: [], unit: '掳C', baseValue: 50, fluctuation: 3, color: '#5470C6' },
+    ]);
+    // initChart('spindleCurrentChart', '涓昏酱鐢垫祦', [
+    //   { name: '鐢垫祦', data: [], unit: 'A', baseValue: 150, fluctuation: 10, color: '#5470C6' },
+    // ]);
+    initChart('spindleSpeedChart', '涓昏酱杞��', [
+      { name: '杞��', data: [], unit: 'RPM', baseValue: 8000, fluctuation: 100, color: '#5470C6' },
+    ]);
+    // initChart('servoMotorCurrentChart', '浼烘湇鐢垫満鐢垫祦', [
+    //   { name: '鐢垫祦', data: [], unit: 'A', baseValue: 50, fluctuation: 5, color: '#5470C6' },
+    // ]);
+    // initChart('servoMotorTemperatureChart', '浼烘湇鐢垫満娓╁害', [
+    //   { name: '娓╁害', data: [], unit: '掳C', baseValue: 45, fluctuation: 3, color: '#5470C6' },
+    // ]);
+    // initChart('axisMotionSmoothnessChart', '杞磋繍鍔ㄥ钩绋虫��', [
+    //   { name: '骞崇ǔ鎬�', data: [], unit: '', baseValue: 0.8, fluctuation: 0.1, color: '#5470C6' },
+    // ]);
+    // initChart('guideRailTemperatureChart', '瀵艰建娓╁害', [
+    //   { name: '娓╁害', data: [], unit: '掳C', baseValue: 35, fluctuation: 2, color: '#5470C6' },
+    // ]);
+    // initChart('guideRailResistanceNoiseChart', '瀵艰建杩愬姩闃诲姏/鍣煶', [
+    //   { name: '闃诲姏/鍣煶', data: [], unit: 'dB', baseValue: 10, fluctuation: 2, color: '#5470C6' },
+    // ]);
+    initChart('hydraulicPressureChart', '娑插帇绯荤粺鍘嬪姏', [
+      { name: '鍘嬪姏', data: [], unit: 'bar', baseValue: 150, fluctuation: 5, color: '#5470C6' },
+    ]);
+    // initChart('hydraulicFlowChart', '娑插帇绯荤粺娴侀噺', [
+    //   { name: '娴侀噺', data: [], unit: 'L/min', baseValue: 20, fluctuation: 2, color: '#5470C6' },
+    // ]);
+    initChart('hydraulicOilTemperatureChart', '娑插帇娌规俯搴�', [
+      { name: '娓╁害', data: [], unit: '掳C', baseValue: 55, fluctuation: 3, color: '#5470C6' },
+    ]);
+    // initChart('airSourcePressureChart', '姘旀簮鍘嬪姏', [
+    //   { name: '鍘嬪姏', data: [], unit: 'bar', baseValue: 0.7, fluctuation: 0.05, color: '#5470C6' },
+    // ]);
+    // initChart('coolantFlowChart', '鍐峰嵈娑叉祦閲�', [
+    //   { name: '娴侀噺', data: [], unit: 'L/min', baseValue: 30, fluctuation: 3, color: '#5470C6' },
+    // ]);
+    initChart('coolantTemperatureChart', '鍐峰嵈娑叉俯搴�', [
+      { name: '娓╁害', data: [], unit: '掳C', baseValue: 28, fluctuation: 2, color: '#5470C6' },
+    ]);
   }
 
 });
@@ -494,6 +586,12 @@
   padding: 16px;
   background: #f0f2f5;
 }
+.device-image-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 330px;
+}
 
 .mt-4 {
   margin-top: 16px;
@@ -502,4 +600,4 @@
 .mb-4 {
   margin-bottom: 16px;
 }
-</style>
\ No newline at end of file
+</style>

--
Gitblit v1.9.3