From 7b4cd6ef04b358e0805846d49e3acf02d7eae5cb Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期三, 30 七月 2025 11:08:33 +0800
Subject: [PATCH] feat(eims): 更新预测性维护功能 - 新增设备数据定时更新功能 - 添加维护建议滚动显示 - 更新设备部件寿命预测数据 - 调整备件库存与预警逻辑 - 优化数据展示和颜色提示

---
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue |  277 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 222 insertions(+), 55 deletions(-)

diff --git a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue
index 5ec94fc..46237fd 100644
--- a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue
@@ -1,9 +1,11 @@
 <script lang="ts">
-import { defineComponent, onUnmounted, reactive } from 'vue';
+import { defineComponent, reactive, onMounted, onUnmounted, ref, nextTick } from 'vue';
 
 import { AppstoreOutlined, FieldTimeOutlined, LineChartOutlined, WarningOutlined, ThunderboltOutlined, CheckCircleOutlined } from '@ant-design/icons-vue';
 import * as echarts from 'echarts';
 import img from '#/assets/images/2t.png';
+import { getDeviceDataInj, updateDeviceData, initDeviceData } from '#/api/eims/equ/deviceData'
+
 export default defineComponent({
   name: 'InjectionMoldingMachineDetail',
   components: {
@@ -29,22 +31,26 @@
 
     const healthData = reactive({
       overallHealth: 88,
-      healthColor: '#faad14',
-      predictedLife: 1500,
-      riskLevel: '涓闄�',
-      riskColor: '#faad14',
+      healthColor: '#52c41a',
+      predictedLife: 1753,
+      riskLevel: '浣庨闄�',
+      riskColor: '#1a7ac4',
       injectionPressure: 120, // 娉ㄥ鍘嬪姏
       clampingForce: 80, // 閿佹ā鍔�
       moldTemperature: 45, // 妯″叿娓╁害
       screwSpeed: 150, // 铻烘潌杞��
       meltTemperature: 220, // 鐔旇瀺娓╁害
       coolingTime: 25, // 鍐峰嵈鏃堕棿
-      injectionCount: '495d 19h 44 ', // 娉ㄥ皠娆℃暟
-      clampingCount: 545636, // 鍚堟ā娆℃暟
-      productionCycle: 19, // 鐢熶骇鍛ㄦ湡
-      energyConsumption: 1500, // 鑳借��
-      yieldRate: 98.5, // 鑹搧鐜�
-      downtime: 120 // 鍑洪敊鍋滄満鏃堕棿
+      injectionCount: 495 * 24 * 60 + 19 * 60 + 44, // 娉ㄥ皠娆℃暟锛岃浆鎹负鍒嗛挓
+      clampingCount: 545636, // 鍚堟ā娆℃暟 // 璺熼殢浜ч噺 50s鍔犱竴娆�
+      productionCycle: 45, // 鐢熶骇鍛ㄦ湡
+      energyConsumption: 64, // 鑳借��
+      yieldRate: 354, // 浜ч噺   50绉掑鍔犱竴妯�
+      downtime: 120, // 鍑洪敊鍋滄満鏃堕棿
+      // 鐢ㄤ簬绱姞澧為暱鐨勫瓧娈�
+      // accumulatedInjectionCount: 12180,
+      // accumulatedClampingCount: 545636,
+      // accumulatedEnergyConsumption: 64
     });
 
     const maintenanceColumns = [
@@ -80,22 +86,40 @@
       {
         key: '1',
         type: '渚嬭淇濆吇',
-        content: '妫�鏌ユ恫鍘嬫补姹℃煋搴�',
-        suggestedTime: '2024-07-15',
+        content: '妫�鏌ユ恫鍘嬫补涔冲寲绋嬪害',
+        suggestedTime: '2025-07-02',
         urgency: '涓瓑'
       },
       {
         key: '2',
         type: '鏁呴殰棰勮',
-        content: '涓荤數鏈鸿酱鎵跨(鎹熼璀�',
-        suggestedTime: '2024-08-01',
-        urgency: '楂�'
+        content: '涓绘补缂稿瘑灏佸湀瀵垮懡棰勮',
+        suggestedTime: '2025-07-01',
+        urgency: '浣�'
+      },{
+        key: '2',
+        type: '娑插帇娌规鏌�',
+        content: '妫�鏌ョ‘璁ゆ恫鍘嬫补娓╁害鏄惁姝e父',
+        suggestedTime: '2025-07-01',
+        urgency: '浣�'
       },
       {
         key: '3',
-        type: '鍐峰嵈绯荤粺缁存姢',
-        content: '妫�鏌ュ喎鍗存按娴侀噺',
-        suggestedTime: '2024-07-01',
+        type: '鍐峰嵈绯荤粺妫�鏌�',
+        content: '妫�鏌ュ喎姘存満鍒跺喎鏁堢巼鏄惁杈炬爣',
+        suggestedTime: '2025-06-11',
+        urgency: '浣�'
+      },{
+        key: '3',
+        type: '娑插帇绯荤粺妫�鏌�',
+        content: '妫�鏌ュ悇娑插帇绠¢亾鍘嬪姏琛ㄤ笌鐢佃剳鏄剧ず鏄惁涓�鑷�',
+        suggestedTime: '2025-06-11',
+        urgency: '浣�'
+      },{
+        key: '3',
+        type: '娓╂帶绯荤粺妫�鏌�',
+        content: '妫�鏌ュ悇娈靛姞鐑湀鍔犵儹銆佺儹鐢佃�︽槸鍚﹀紓甯�',
+        suggestedTime: '2025-06-11',
         urgency: '浣�'
       }
     ]);
@@ -117,6 +141,27 @@
       }
     };
 
+     const fetchDeviceData = async () => {
+      try {
+        const res = await getDeviceDataInj();
+        Object.assign(healthData, res);
+      } catch (error) {
+        console.error('鑾峰彇璁惧鏁版嵁澶辫触:', error);
+      }
+    };
+
+    let deviceDataInterval: number | undefined;
+    fetchDeviceData();
+
+     deviceDataInterval = setInterval(async () => {
+        try {
+          fetchDeviceData();
+        } catch (error) {
+          console.error('鏇存柊璁惧鏁版嵁澶辫触:', error);
+        }
+      }, 3000);
+
+
     const sparePartColumns = [
       {
         title: '閮ㄤ欢鍚嶇О',
@@ -124,16 +169,16 @@
         key: 'name'
       },
       {
-        title: '褰撳墠瀵垮懡',
+        title: '棰勮瀵垮懡',
         dataIndex: 'currentLife',
-        key: 'currentLife',
-        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+        key: 'currentLife'
+
       },
       {
         title: '棰勬祴鍓╀綑瀵垮懡',
         dataIndex: 'remainingLife',
-        key: 'remainingLife',
-        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+        key: 'remainingLife'
+
       },
       {
         title: '鐘舵��',
@@ -146,23 +191,44 @@
     const sparePartData = reactive([
       {
         key: '1',
-        name: '娑插帇娉�',
-        currentLife: 18_500,
-        remainingLife: 1500,
-        status: '棰勮'
+        name: '娑插帇娌�',
+        currentLife: 8_500,
+        remainingLife: 2515,
+        status: '鑹ソ'
       },
       {
         key: '2',
         name: '鍔犵儹鍦�',
-        currentLife: 12_000,
-        remainingLife: 3000,
+        currentLife: 6_000,
+        remainingLife: 3415,
         status: '鑹ソ'
       },
       {
         key: '3',
-        name: '铻烘潌鏂欑瓛',
-        currentLife: 25_000,
-        remainingLife: 5000,
+        name: '鐑數鑰�',
+        currentLife: 8_000,
+        remainingLife: 5851,
+        status: '鑹ソ'
+      },
+      {
+        key: '3',
+        name: '娉ㄨ兌鍢�',
+        currentLife: "100000娆�",
+        remainingLife: "76438娆�",
+        status: '鑹ソ'
+      },
+      {
+        key: '3',
+        name: '閿佹ā澶瑰叿',
+        currentLife: "12涓湀",
+        remainingLife: "8涓湀",
+        status: '鑹ソ'
+      },
+      {
+        key: '3',
+        name: '娉ㄨ兌铻烘潌',
+        currentLife: "60涓湀",
+        remainingLife: "48涓湀",
         status: '鑹ソ'
       }
     ]);
@@ -170,21 +236,49 @@
     const historyData = reactive([
       {
         id: '1',
-        date: '2023-10-20',
+        date: '2025-08-15',
         type: '渚嬭淇濆吇',
-        description: '鏇存崲娑插帇娌规护鑺�',
+        description: '娑插帇绯荤粺妫�鏌ワ紝娓╂帶绯荤粺妫�鏌�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-07-20',
+        type: '渚嬭淇濆吇',
+        description: '娑插帇绯荤粺妫�鏌ワ紝娓╂帶绯荤粺妫�鏌�',
         color: 'green'
       },
       {
         id: '2',
-        date: '2023-08-15',
-        type: '鏁呴殰缁翠慨',
-        description: '娉ㄥ皠鍗曞厓鍗℃粸锛屾竻鐞嗗紓鐗�',
-        color: 'red'
+        date: '2025-07-13',
+        type: '缁翠慨淇濆吇',
+        description: '绗竴娈垫俯搴︽樉绀哄紓甯革紝鐑數鑰︽崯鍧忥紝鏇存崲鏂伴厤浠�',
+        color: 'orange'
+      },
+      {
+        id: '1',
+        date: '2025-06-18',
+        type: '渚嬭淇濆吇',
+        description: '娑插帇绯荤粺妫�鏌ワ紝娓╂帶绯荤粺妫�鏌�',
+        color: 'green'
+      },
+      {
+        id: '2',
+        date: '2025-05-23',
+        type: '缁翠慨淇濆吇',
+        description: '绗笁娈垫俯搴﹀紓甯革紝鍔犵儹鍦堢儳鍧忥紝鏇存崲鏂伴厤浠�',
+        color: 'orange'
+      },
+      {
+        id: '2',
+        date: '2025-05-15',
+        type: '渚嬭淇濆吇',
+        description: '娑插帇绯荤粺妫�鏌ワ紝娓╂帶绯荤粺妫�鏌�',
+        color: 'green'
       },
       {
         id: '3',
-        date: '2023-06-01',
+        date: '2025-04-01',
         type: '骞村害淇濆吇',
         description: '鍏ㄩ潰妫�鏌ヨ澶囪繍琛岀姸鎬�',
         color: 'blue'
@@ -213,6 +307,68 @@
       // 瀹為檯椤圭洰涓繖閲屼細璋冪敤API澶勭悊缁存姢寤鸿
     };
 
+    let intervalId: number | undefined;
+
+    // const updateAccumulatedData = () => {
+    //   healthData.accumulatedInjectionCount +=  + 0.1; // 姣忔澧炲姞1-5鍒嗛挓
+    //   healthData.accumulatedClampingCount += Math.floor(Math.random() * 100) + 10; // 姣忔澧炲姞10-100娆�
+    //   healthData.accumulatedEnergyConsumption += (Math.random() * 0.015 + 0.008); // 姣忔澧炲姞0.1-0.6 kWh
+
+    //   // 鏇存柊鏄剧ず鍊�
+    //   const totalMinutes = Math.floor(healthData.accumulatedInjectionCount);
+
+    //   const minutes = totalMinutes % 60;
+    //   healthData.injectionCount = `${healthData.accumulatedInjectionCount}h`;
+    //   healthData.clampingCount = healthData.accumulatedClampingCount;
+    //   healthData.energyConsumption = parseFloat(healthData.accumulatedEnergyConsumption.toFixed(2));
+    // };
+    const maintenanceTable = ref<HTMLElement | null>(null);
+    // 鍒濆璁剧疆涓�娆★紝閬垮厤棣栨鍔犺浇鏃舵樉绀轰负0
+    // updateAccumulatedData();
+    let scrollInterval: number | undefined;
+
+    const startScroll = () => {
+      if (!maintenanceTable.value) return;
+
+      const tableBody = maintenanceTable.value.$el.querySelector('.ant-table-body');
+      if (!tableBody) return;
+
+      const scrollHeight = tableBody.scrollHeight;
+      const clientHeight = tableBody.clientHeight;
+
+      if (scrollHeight <= clientHeight) {
+        return;
+      }
+
+      let currentScrollTop = 0;
+      scrollInterval = setInterval(() => {
+        currentScrollTop += 1;
+        if (currentScrollTop >= scrollHeight - clientHeight) {
+          currentScrollTop = 0;
+        }
+        tableBody.scrollTop = currentScrollTop;
+      }, 50);
+    };
+
+
+
+    onMounted(() => {
+      // 姣�5绉掓洿鏂颁竴娆$疮鍔犳暟鎹�
+      // intervalId = setInterval(updateAccumulatedData, 5000);
+      nextTick(() => {
+        startScroll();
+      });
+    })
+    onUnmounted(() => {
+      if (scrollInterval) {
+        clearInterval(scrollInterval);
+      }
+       if (deviceDataInterval) {
+        clearInterval(deviceDataInterval);
+      }
+    });
+
+
     return {
       deviceInfo,
       healthData,
@@ -223,10 +379,12 @@
       historyData,
       getStatusColor,
       getUrgencyColor,
-      handleMaintenance
+      handleMaintenance,
+      maintenanceTable
     };
   },
   mounted() {
+
     // 鍒濆鍖栧浘琛�
     const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
       const chart = echarts.init(document.getElementById(chartId));
@@ -234,9 +392,9 @@
       // 纭繚鍒濆鏁版嵁鐐硅冻澶熸樉绀轰竴涓畬鏁寸殑瓒嬪娍
       if (chartData.length === 0) {
         const now = new Date();
-        for (let i = 0; i < 60; i++) {
+        for (let i = 0; i < 24; i++) {
           // 鐢熸垚60涓偣锛屼唬琛�5鍒嗛挓鐨勬暟鎹�
-          const time = new Date(now.getTime() - (59 - i) * 5000); // 姣忎釜鐐归棿闅�5绉�
+          const time = new Date(now.getTime() - (24 - i) * 5000); // 姣忎釜鐐归棿闅�5绉�
           chartData.push({
             time: time.toLocaleTimeString(),
             value: (baseValue + Math.random() * fluctuation * 2 - fluctuation).toFixed(2)
@@ -255,7 +413,7 @@
           time,
           value: newValue
         });
-        if (chartData.length > 60) {
+        if (chartData.length > 24) {
           chartData.shift();
         }
 
@@ -323,10 +481,13 @@
       window.addEventListener('resize', () => {
         chart.resize();
       });
-      onUnmounted(() => {
-        clearInterval(intervalId);
+      window.addEventListener('resize', () => {
+        chart.resize();
       });
+
     };
+
+
 
     const hydraulicOilTemperatureData: any[] = [];
     const hydraulicOilPressureData: any[] = [];
@@ -345,14 +506,20 @@
     // initChart('hydraulicOilPressureChart', '娑插帇娌瑰帇', hydraulicOilPressureData, 'MPa', 150, 5);
     // initChart('mainMotorCurrentChart', '涓荤數鏈虹數娴�', mainMotorCurrentData, 'A', 80, 3);
     initChart('screwSpeedChart', '铻烘潌杞��', screwSpeedData, 'rpm', 100, 10);
-    initChart('moldClampingForceChart', '閿佹ā鍔�', moldClampingForceData, 'kN', 1000, 50);
-    initChart('injectionPressureChart', '娉ㄥ皠鍘嬪姏', injectionPressureData, 'MPa', 1200, 80);
+    initChart('moldClampingForceChart', '閿佹ā鍘嬪姏', moldClampingForceData, 'Bar', 120, 10);
+    initChart('injectionPressureChart', '娉ㄥ皠鍘嬪姏', injectionPressureData, 'Bar', 80, 5);
     initChart('injectionSpeedChart', '娉ㄥ皠閫熷害', injectionSpeedData, 'mm/s', 150, 10);
     initChart('barrelTemperatureChart', '鏂欑瓛娓╁害', barrelTemperatureData, '掳C', 240, 3);
-    initChart('coolingWaterTemperatureChart', '鍐峰嵈姘存俯搴�', coolingWaterTemperatureData, '掳C', 25, 2);
+    initChart('coolingWaterTemperatureChart', '鍐锋按鏈烘俯搴�', coolingWaterTemperatureData, '掳C', 20, 2);
     // initChart('coolingWaterFlowChart', '鍐峰嵈姘存祦閲�', coolingWaterFlowData, 'L/min', 30, 3);
     // initChart('ejectorPositionChart', '椤跺嚭浣嶇疆', ejectorPositionData, 'mm', 50, 5);
     // initChart('cycleTimeChart', '寰幆鏃堕棿', cycleTimeData, 's', 30, 2);
+  },
+  unmounted() {
+    // 娓呴櫎瀹氭椂鍣�
+    if (this.intervalId) {
+      clearInterval(this.intervalId);
+    }
   }
 });
 </script>
@@ -411,7 +578,7 @@
             <a-progress :percent="healthData.overallHealth" :show-info="false" :stroke-color="healthData.healthColor" />
           </div>
           <a-divider orientation="left">棰勬祴鎬х淮鎶ゅ缓璁�</a-divider>
-          <a-table :columns="maintenanceColumns" :data-source="maintenanceData" :pagination="false" size="small">
+          <a-table ref="maintenanceTable" :columns="maintenanceColumns" :data-source="maintenanceData" :pagination="false" size="small" :scroll="{ y: 150 }">
             <template #urgency="{ text }">
               <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
             </template>
@@ -426,35 +593,35 @@
       <a-card class="mb-4" title="璁惧鏁版嵁">
         <a-row :gutter="[16, 16]">
           <a-col :span="4">
-            <a-statistic :value="healthData.injectionCount" suffix="min" title="鎬诲紑鏈烘椂闂�">
+            <a-statistic :value="healthData.injectionCount.toFixed(2)" suffix="h" title="鎬诲紑鏈烘椂闂�">
               <template #prefix>
                 <LineChartOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic :value="healthData.clampingCount" suffix="娆�" title="鎬诲惊鐜鏁�">
+            <a-statistic :value="healthData.clampingCount.toFixed(0)" suffix="娆�" title="鎬诲惊鐜鏁�">
               <template #prefix>
                 <LineChartOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic :value="healthData.productionCycle" suffix="s" title="鐢熶骇鍛ㄦ湡">
+            <a-statistic :value="healthData.productionCycle.toFixed(0)" suffix="s" title="骞冲潎鐢熶骇鍛ㄦ湡">
               <template #prefix>
                 <FieldTimeOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic :value="healthData.energyConsumption" suffix="kWh" title="鑳借��">
+            <a-statistic :value="healthData.energyConsumption.toFixed(2)" suffix="kWh" title="褰撴棩绱Н鑳借��">
               <template #prefix>
                 <ThunderboltOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic :value="healthData.yieldRate" suffix="%" title="鑹搧鐜�">
+            <a-statistic :value="healthData.yieldRate.toFixed(0)" suffix="妯�" title="褰撳墠浜ч噺">
               <template #prefix>
                 <CheckCircleOutlined />
               </template>

--
Gitblit v1.9.3