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 ++++++++++--
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue                             |   83 ++-
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/AutoApproveRepairJob.java           |   64 +++
 eims-ui/apps/web-antd/src/api/eims/equ/deviceData.ts                                              |   45 ++
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue       |  284 ++++++++++--
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue                |  279 ++++++++++--
 eims/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java |   12 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/DeviceDataController.java    |  109 +++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/DeviceDataIncrJob.java              |   76 +++
 eims-ui-mobile/src/pages/repair/res-list.vue                                                      |   22 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java     |    1 
 11 files changed, 1,058 insertions(+), 194 deletions(-)

diff --git a/eims-ui-mobile/src/pages/repair/res-list.vue b/eims-ui-mobile/src/pages/repair/res-list.vue
index 3ca5864..c572112 100644
--- a/eims-ui-mobile/src/pages/repair/res-list.vue
+++ b/eims-ui-mobile/src/pages/repair/res-list.vue
@@ -20,8 +20,11 @@
 <!--        </template>-->
       </wd-navbar>
       <!-- 澧炲姞涓�涓悳绱㈡爮 -->
-      <wd-search v-model="searchValue" @search="handleSearch">
-      </wd-search>
+      <wd-search v-model="searchValue" @search="handleSearch"></wd-search>
+      <wd-tabs v-model="activeTab" @change="handleTabChange">
+        <wd-tab title="寰呯淮淇�"></wd-tab>
+        <wd-tab title="宸茬淮淇�"></wd-tab>
+      </wd-tabs>
 <!--      <wd-drop-menu>-->
 <!--        <wd-drop-menu-item-->
 <!--          v-model="resTypeId"-->
@@ -61,6 +64,8 @@
 import { formatDate } from '@/utils/DateUtils'
 import dayjs from "dayjs";
 import ResCard from "@/components/repair/res-card.vue";
+
+const activeTab = ref(0)
 const userStore = useUserStore()
 
 const message = useMessage()
@@ -148,7 +153,14 @@
   if (option?.from === 'scan') {
     queryParams.assetNo = option.assetNo
   }
-  queryParams.params.status = '0,1,2,3'
+  if (activeTab.value === 0) {
+    // 寰呯淮淇細status 绛変簬 1 鎴� 2 鎴� 3
+    queryParams.params.status = '1,2'
+  } else {
+    // 宸茬淮淇細status 绛変簬 3 鎴� 4
+    queryParams.params.status = '3,4'
+  }
+
   queryParams.reqUser = userStore?.userInfo?.userId
   if (isRepair()) {
     queryParams.params.status = undefined
@@ -167,6 +179,10 @@
   paging.value.reload()
 }
 
+function handleTabChange() {
+  reloadData()
+}
+
 // /**
 //  * 鏉$洰鐐瑰嚮浜嬩欢
 //  * @param item
diff --git a/eims-ui/apps/web-antd/src/api/eims/equ/deviceData.ts b/eims-ui/apps/web-antd/src/api/eims/equ/deviceData.ts
new file mode 100644
index 0000000..2b9f0df
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/api/eims/equ/deviceData.ts
@@ -0,0 +1,45 @@
+import type { PageQuery, PageResult } from '#/api/model';
+import { requestClient } from '#/api/request';
+
+enum Api {
+  getDeviceData = '/eims/deviceData/get',
+  getDeviceDataSmt = '/eims/deviceData/getSmt',
+  getDeviceDataInj = '/eims/deviceData/getInj',
+  updateDeviceData = '/eims/deviceData/update',
+  initDeviceData = '/eims/deviceData/init'
+}
+
+/**
+ * 鑾峰彇璁惧鏁版嵁
+ */
+export function getDeviceData() {
+  return requestClient.get<Record<string, number>>(Api.getDeviceData);
+}
+
+/**
+ * 鑾峰彇璁惧鏁版嵁
+ */
+export function getDeviceDataSmt() {
+  return requestClient.get<Record<string, number>>(Api.getDeviceDataSmt);
+}
+
+/**
+ * 鑾峰彇璁惧鏁版嵁
+ */
+export function getDeviceDataInj() {
+  return requestClient.get<Record<string, number>>(Api.getDeviceDataInj);
+}
+
+/**
+ * 鏇存柊璁惧鏁版嵁锛堟ā鎷熻嚜鍔ㄥ闀匡級
+ */
+export function updateDeviceData() {
+  return requestClient.post<void>(Api.updateDeviceData);
+}
+
+/**
+ * 鍒濆鍖栬澶囨暟鎹�
+ */
+export function initDeviceData() {
+  return requestClient.post<void>(Api.initDeviceData);
+}
\ No newline at end of file
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 4c2ea27..044774b 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
@@ -69,10 +69,12 @@
           </div>
           <a-divider orientation="left">棰勬祴鎬х淮鎶ゅ缓璁�</a-divider>
           <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>
@@ -90,42 +92,42 @@
       <a-card title="璁惧鏁版嵁" class="mb-4">
         <a-row :gutter="[16, 16]">
           <a-col :span="4">
-            <a-statistic title="鍔犲伐鏃堕棿" :value="healthData.xAxisTravel" suffix="km">
+            <a-statistic title="鍔犲伐鏃堕棿" :value="healthData.xAxisTravel.toFixed(2)" suffix="h">
               <template #prefix>
                 <FieldTimeOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic title="鍒�鍏蜂娇鐢ㄦ鏁�" :value="healthData.yAxisTravel" suffix="km">
+            <a-statistic title="鍒�搴撳垏鎹㈡鏁�" :value="healthData.yAxisTravel.toFixed(0)" suffix="娆�">
               <template #prefix>
                 <FieldTimeOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic title="鍒�鍏蜂娇鐢ㄦ椂闀�" :value="healthData.zAxisTravel" suffix="km">
+            <a-statistic title="鍒�鍏峰钩鍧囧鍛�" :value="healthData.zAxisTravel.toFixed(2)" suffix="h">
               <template #prefix>
                 <FieldTimeOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic title="鍒�鍏锋洿鎹㈡鏁�" :value="healthData.toolChangeCount" suffix="娆�">
+            <a-statistic title="骞冲潎璋冩満缂栫▼鏃堕棿" :value="healthData.toolChangeCount" suffix="Min">
               <template #prefix>
                 <WarningOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic title="鍔犲伐闆朵欢鏁�" :value="healthData.partCount" suffix="浠�">
+            <a-statistic title="绱鍔犲伐闆朵欢鏁�" :value="healthData.partCount.toFixed(0)" suffix="浠�">
               <template #prefix>
                 <AppstoreOutlined />
               </template>
             </a-statistic>
           </a-col>
           <a-col :span="4">
-            <a-statistic title="鍑洪敊鍋滄満鏃堕棿" :value="healthData.downtime" suffix="绉�">
+            <a-statistic title="骞冲潎鍔犲伐绛夊緟鏃堕棿" :value="healthData.downtime" suffix="绉�">
               <template #prefix>
                 <FieldTimeOutlined />
               </template>
@@ -142,7 +144,7 @@
           <div id="spindleVibrationChart" style="height: 300px;"></div>
         </a-col>
         <a-col :span="8">
-          <div id="hydraulicOilTemperatureChart" style="height: 300px;"></div>
+          <div id="spindleTemperatureChart" style="height: 300px;"></div>
         </a-col>
         <a-col :span="8">
           <div id="spindleSpeedChart" style="height: 300px;"></div>
@@ -155,8 +157,7 @@
           <div id="hydraulicPressureChart" 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="coolantTemperatureChart" style="height: 300px;"></div>
@@ -197,7 +198,7 @@
 </template>
 
 <script lang="ts">
-import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
+import { defineComponent, reactive, onMounted, onUnmounted, ref, nextTick } from 'vue';
 import * as echarts from 'echarts';
 import {
   LineChartOutlined,
@@ -205,7 +206,8 @@
   AppstoreOutlined,
   FieldTimeOutlined
 } from '@ant-design/icons-vue';
-import img from '#/assets/images/T850-840.2.jpg'
+import img from '#/assets/images/T850-840.2.jpg';
+import { getDeviceData, updateDeviceData, initDeviceData } from '#/api/eims/equ/deviceData'
 export default defineComponent({
   name: 'CNCMachiningCenterDetail',
   setup() {
@@ -224,15 +226,15 @@
     const healthData = reactive({
       overallHealth: 95,
       healthColor: '#52c41a',
-      predictedLife: 4436,
+      predictedLife: 5017,
       riskLevel: '浣庨闄�',
       riskColor: '#52c41a',
-      xAxisTravel: 1200.5,
-      yAxisTravel: 980.2,
-      zAxisTravel: 500.1,
-      toolChangeCount: 25,
-      partCount: 1500,
-      downtime: 120
+      xAxisTravel: 7105.5,  // 姣忓ぉ鍔�6灏忔椂
+      yAxisTravel: 5641,  // 姣忓ぉ鍔�60娆�
+      zAxisTravel: 450.4,  // 姣忓ぉ鍔�20绫冲乏鍙�
+      toolChangeCount: 74,  // 涓嶆尝鍔�
+      partCount: 17056, // 姣忓ぉ鍔�15涓乏鍙�
+      downtime: 141  // 涓嶆尝鍔�
     });
 
     const maintenanceColumns = [
@@ -270,7 +272,7 @@
         type: '渚嬭淇濆吇',
         content: '妫�鏌ヤ富杞存鼎婊戠郴缁�',
         suggestedTime: '2025-07-15',
-        urgency: '涓瓑'
+        urgency: '浣�'
       },
       {
         key: '2',
@@ -281,9 +283,30 @@
       },
       {
         key: '3',
-        type: '瀵艰建缁存姢',
+        type: '涓濇潌瀵艰建缁存姢',
         content: '琛ュ厖瀵艰建娑︽粦娌�',
         suggestedTime: '2025-06-01',
+        urgency: '浣�'
+      },
+      {
+        key: '3',
+        type: '鍔犲伐绮惧害纭',
+        content: '瀹氭湡瀵艰建绮惧害鏍¢獙妫�鏌ョ‘璁�',
+        suggestedTime: '2025-05-05',
+        urgency: '浣�'
+      },
+      {
+        key: '3',
+        type: '鍒�搴撳姛鑳界‘璁�',
+        content: '鎸囦护鎹㈠垁鏄惁瀛樺湪鍗℃粸寤惰繜鐜拌薄',
+        suggestedTime: '2025-05-03',
+        urgency: '浣�'
+      },
+      {
+        key: '3',
+        type: '鍒囧墛娑叉洿鎹�',
+        content: '妫�鏌ョ‘璁ゅ垏鍓婃恫鏄惁瓒呮湡锛屾潅璐ㄥ惈閲忔槸鍚︾鍚堣姹�',
+        suggestedTime: '2025-05-03',
         urgency: '浣�'
       }
     ]);
@@ -308,16 +331,16 @@
         key: 'name'
       },
       {
-        title: '褰撳墠瀵垮懡',
+        title: '棰勮瀵垮懡',
         dataIndex: 'currentLife',
         key: 'currentLife',
-        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+        // customRender: ({ text }: { text: number }) => `${text}灏忔椂`
       },
       {
         title: '棰勬祴鍓╀綑瀵垮懡',
         dataIndex: 'remainingLife',
         key: 'remainingLife',
-        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+        // customRender: ({ text }: { text: number }) => `${text}灏忔椂`
       },
       {
         title: '鐘舵��',
@@ -329,49 +352,120 @@
 
     const sparePartData = reactive([
       {
+        key: '3',
+        name: '鍒囧墛娑�',
+        currentLife: "6涓湀",
+        remainingLife: "1涓湀",
+        status: '棰勮'
+      },
+      {
         key: '1',
         name: '涓昏酱杞存壙',
-        currentLife: 8000,
-        remainingLife: 500,
-        status: '棰勮'
+        currentLife: "8000灏忔椂",
+        remainingLife: "5710灏忔椂",
+        status: '鑹ソ'
       },
       {
         key: '2',
         name: 'X杞翠笣鏉�',
-        currentLife: 12000,
-        remainingLife: 2000,
+        currentLife: "12000灏忔椂",
+        remainingLife: "9132灏忔椂",
+        status: '鑹ソ'
+      },
+      {
+        key: '2',
+        name: 'Y杞翠笣鏉�',
+        currentLife: "12000灏忔椂",
+        remainingLife: "9132灏忔椂",
+        status: '鑹ソ'
+      },
+      {
+        key: '2',
+        name: 'Z杞翠笣鏉�',
+        currentLife: "12000灏忔椂",
+        remainingLife: "9132灏忔椂",
+        status: '鑹ソ'
+      },
+
+      {
+        key: '3',
+        name: '瀵艰建娌�',
+        currentLife: "30澶�",
+        remainingLife: "23澶�",
         status: '鑹ソ'
       },
       {
         key: '3',
-        name: '娑插帇娌�',
-        currentLife: 3000,
-        remainingLife: 200,
-        status: '棰勮'
+        name: '鍒�妗跺す',
+        currentLife: "30000娆�",
+        remainingLife: "23513娆�",
+        status: '鑹ソ'
+      },
+      {
+        key: '3',
+        name: '鍒�妗舵媺閽�',
+        currentLife: "15000娆�",
+        remainingLife: "11421娆�",
+        status: '鑹ソ'
       }
     ]);
 
     const historyData = reactive([
       {
         id: '1',
-        date: '2024-05-20',
+        date: '2025-08-06',
         type: '渚嬭淇濆吇',
-        description: '涓昏酱娑︽粦绯荤粺妫�鏌�',
+        description: '鍚勫杞ㄦ鼎婊戠郴缁熸鏌ワ紝娣诲姞瀵艰建娌�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-07-11',
+        type: '渚嬭淇濆吇',
+        description: '鍚勫杞ㄦ鼎婊戠郴缁熸鏌ワ紝娣诲姞瀵艰建娌�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-06-18',
+        type: '缁翠慨淇濆吇',
+        description: '鍒�妗舵媺閽夋洿鎹�3涓�',
+        color: 'orange'
+      },
+      {
+        id: '1',
+        date: '2025-06-09',
+        type: '渚嬭淇濆吇',
+        description: '鍚勫杞ㄦ鼎婊戠郴缁熸鏌ワ紝娣诲姞瀵艰建娌�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-05-22',
+        type: '缁翠慨淇濆吇',
+        description: '鍒�妗跺す纾ㄦ崯绮惧害涓嬮檷锛屾洿鎹㈡柊閰嶄欢',
+        color: 'orange'
+      },
+      {
+        id: '1',
+        date: '2025-05-10',
+        type: '渚嬭淇濆吇',
+        description: '鍚勫杞ㄦ鼎婊戠郴缁熸鏌ワ紝娣诲姞瀵艰建娌�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-04-13',
+        type: '渚嬭淇濆吇',
+        description: '鍚勫杞ㄦ鼎婊戠郴缁熸鏌ワ紝娣诲姞瀵艰建娌�',
         color: 'green'
       },
       {
         id: '2',
-        date: '2024-02-10',
-        type: '鏁呴殰缁翠慨',
-        description: 'Y杞翠己鏈嶇數鏈烘姤璀﹀鐞�',
-        color: 'red'
-      },
-      {
-        id: '3',
-        date: '2023-11-01',
-        type: '骞村害淇濆吇',
-        description: '鍏ㄩ潰妫�鏌ヨ澶囪繍琛岀姸鎬�',
-        color: 'green'
+        date: '2025-03-04',
+        type: '缁翠慨淇濆吇',
+        description: '鍒囧墛娓f竻鐞嗭紝鍒囧墛娑叉洿鎹�',
+        color: 'orange'
       }
     ]);
 
@@ -393,6 +487,84 @@
       // 瀹為檯椤圭洰涓繖閲屼細璋冪敤API澶勭悊缁存姢寤鸿
     };
 
+    const maintenanceTable = ref<HTMLElement | null>(null);
+    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);
+    };
+
+    let deviceDataInterval: number | undefined;
+
+    const fetchDeviceData = async () => {
+      try {
+        const res = await getDeviceData();
+        Object.assign(healthData, res);
+      } catch (error) {
+        console.error('鑾峰彇璁惧鏁版嵁澶辫触:', error);
+      }
+    };
+
+
+    fetchDeviceData();
+
+      // 鍒濆鍖栬澶囨暟鎹�
+      // initDeviceData().then(() => {
+      //   fetchDeviceData(); // 鍒濆鍖栧悗绔嬪嵆鑾峰彇涓�娆℃暟鎹�
+      // });
+
+      // 姣忕鏇存柊涓�娆¤澶囨暟鎹�
+      deviceDataInterval = setInterval(async () => {
+        try {
+          fetchDeviceData();
+        } catch (error) {
+          console.error('鏇存柊璁惧鏁版嵁澶辫触:', error);
+        }
+      }, 3000);
+
+
+    onUnmounted(() => {
+      if (scrollInterval) {
+        clearInterval(scrollInterval);
+      }
+      if (deviceDataInterval) {
+        clearInterval(deviceDataInterval);
+      }
+    });
+
+    onMounted(() => {
+      nextTick(() => {
+        startScroll();
+      });
+    });
+
+    onUnmounted(() => {
+      if (scrollInterval) {
+        clearInterval(scrollInterval);
+      }
+    });
+
+
+
     return {
       deviceInfo,
       healthData,
@@ -403,7 +575,8 @@
       historyData,
       getStatusColor,
       getUrgencyColor,
-      handleMaintenance
+      handleMaintenance,
+      maintenanceTable
     };
   },
 
@@ -430,7 +603,7 @@
             time,
             value: newValue
           });
-          if (s.data.length > 60) {
+          if (s.data.length > 12) {
             s.data.shift();
           }
         });
@@ -503,8 +676,8 @@
       seriesConfig.forEach(s => {
         s.data = [];
         // 鐢熸垚鍒濆鏁版嵁鐐癸紙60涓偣锛�5鍒嗛挓鏁版嵁锛�
-      for (let i = 0; i < 60; i++) {
-        const now = new Date(Date.now() - (60 - i) * 5000); // 鐢熸垚杩囧幓5鍒嗛挓鐨勬暟鎹�
+      for (let i = 0; i < 12; i++) {
+        const now = new Date(Date.now() - (12 - i) * 5000); // 鐢熸垚杩囧幓5鍒嗛挓鐨勬暟鎹�
         const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
         const newValue = (s.baseValue + (Math.random() * 2 - 1) * s.fluctuation).toFixed(2);
         s.data.push({
@@ -530,9 +703,10 @@
 
     };
 
+
     // 杩愬姩绯荤粺鐩戞祴
-    initChart('spindleVibrationChart', '涓昏酱鎸姩', [
-      { name: '鎸姩', data: [], unit: 'mm/s', baseValue: 3.0, fluctuation: 0.5, color: '#5470C6' },
+    initChart('spindleVibrationChart', '骞冲潎鍔犲伐鏃堕棿', [
+      { name: '鏃堕棿', data: [], unit: 'min/pcs', baseValue: 16.0, fluctuation: 0.1, color: '#5470C6' },
     ]);
     initChart('spindleTemperatureChart', '涓昏酱娓╁害', [
       { name: '娓╁害', data: [], unit: '掳C', baseValue: 50, fluctuation: 3, color: '#5470C6' },
@@ -576,6 +750,8 @@
     initChart('coolantTemperatureChart', '鍐峰嵈娑叉俯搴�', [
       { name: '娓╁害', data: [], unit: '掳C', baseValue: 28, fluctuation: 2, color: '#5470C6' },
     ]);
+
+
   }
 
 });
@@ -585,12 +761,6 @@
 .device-detail-container {
   padding: 16px;
   background: #f0f2f5;
-}
-.device-image-container {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  height: 330px;
 }
 
 .mt-4 {
diff --git a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue
index 7b629cb..026b8c2 100644
--- a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue
@@ -63,8 +63,8 @@
       <!-- 澶囦欢淇℃伅 -->
       <div class="grid grid-cols-2 gap-4 mb-6">
         <!-- 璁惧閮ㄤ欢瀵垮懡棰勬祴 -->
-        <Card title="璁惧閮ㄤ欢瀵垮懡棰勬祴">
-          <Table :columns="lifePredictionColumns" :data-source="lifePredictionData" :pagination="false" class="w-full">
+        <Card title="璁惧閮ㄤ欢瀵垮懡棰勬祴" :style="{ height: '500px' }">
+          <Table :columns="lifePredictionColumns" :data-source="lifePredictionData" :pagination="false" :scroll="{ y: 340 }" class="w-full">
             <template #bodyCell="{ column, record }">
               <template v-if="column.key === 'lifeStatus'">
                 <a-tag :color="getLifeStatusColor(record.remainingDays)">
@@ -79,8 +79,8 @@
         </Card>
 
         <!-- 澶囦欢搴撳瓨涓庨璀� -->
-        <Card title="澶囦欢搴撳瓨涓庨璀�">
-          <Table :columns="sparePartColumns" :data-source="sparePartData" :pagination="false" class="w-full">
+        <Card title="澶囦欢搴撳瓨涓庨璀�" :style="{ height: '500px' }">
+          <Table :columns="sparePartColumns" :data-source="sparePartData" :pagination="false" :scroll="{ y: 340 }" class="w-full">
             <template #bodyCell="{ column, record }">
               <template v-if="column.key === 'stockStatus'">
                 <a-tag :color="getStockStatusColor(record.currentStock, record.safetyStock)">
@@ -140,7 +140,7 @@
     indicator: '鐪熺┖鍘嬪姏',
     value: 32,
     threshold: 35,
-    status: '涓闄�',
+    status: '浣庨闄�',
     maintenanceSuggestion: '鐪熺┖鍘嬪姏鍊间綆浜庤瀹氬�硷紝寤鸿妫�鏌ユ垨鏇存崲鍚稿槾',
     maintenanceType: '棰勯槻鎬х淮鎶�',
   },
@@ -152,7 +152,7 @@
     indicator: '娓╁害',
     value: 85,
     threshold: 80,
-    status: '涓闄�',
+    status: '浣庨闄�',
     maintenanceSuggestion: '寤鸿瀵逛富杞磋繘琛屾鼎婊戜繚鍏诲苟妫�鏌ュ喎鍗寸郴缁�',
     maintenanceType: '娑︽粦缁存姢',
   },
@@ -221,12 +221,33 @@
     safetyStock: 10,
     predictedDemand: 2,
   },
+  {
+    key: '4',
+    name: '鍠风爜鏈烘补澧�',
+    currentStock: 1,
+    safetyStock: 1,
+    predictedDemand: 1,
+  },
+  {
+    key: '4',
+    name: '閽㈢綉娓呮礂娑�',
+    currentStock: 2,
+    safetyStock: 1,
+    predictedDemand: 1,
+  },
+  {
+    key: '4',
+    name: '鍗佸绮惧瘑婊よ姱',
+    currentStock: 20,
+    safetyStock: 4,
+    predictedDemand: 0,
+  },
 ]);
 const getStatusColor = (status) => {
   switch (status) {
     case '楂橀闄�': return 'red';
     case '涓闄�': return 'orange';
-    case '浣庨闄�': return 'yellow';
+    case '浣庨闄�': return 'blue';
     default: return 'green';
   }
 };
@@ -245,7 +266,7 @@
 
 const lifePredictionColumns = [
   { title: '璁惧鍚嶇О', dataIndex: 'deviceName', key: 'deviceName' },
-  { title: '閮ㄤ綅鍚嶇О', dataIndex: 'componentName', key: 'componentName' },
+  // { title: '閮ㄤ綅鍚嶇О', dataIndex: 'componentName', key: 'componentName' },
   { title: '閮ㄤ欢鍚嶇О', dataIndex: 'name', key: 'name' },
   { title: '棰勬祴瀵垮懡 (澶�)', dataIndex: 'predictedLife', key: 'predictedLife' },
   { title: '鍓╀綑瀵垮懡 (澶�)', dataIndex: 'remainingDays', key: 'remainingDays' },
@@ -254,19 +275,25 @@
 ];
 
 const lifePredictionData = ref([
-    { key: '4', deviceName: '绌哄帇鏈�', componentName: '鐢垫満', name: '浼犳劅鍣�', predictedLife: 500, remainingDays: 10 },
-      { key: '2', deviceName: 'CNC鍔犲伐涓績', componentName: '涓昏酱', name: '榻胯疆', predictedLife: 730, remainingDays: 30 },
-  { key: '1', deviceName: 'SMT璐寸墖鏈�', componentName: '浼犻�佸甫', name: '杞存壙', predictedLife: 365, remainingDays: 50 },
+  { key: '1', deviceName: 'SMT璐寸墖鏈�', componentName: '浼犻�佸甫', name: '鐪熺┖鍙戠敓鍣�', predictedLife: 700, remainingDays: 83 },
+  { key: '1', deviceName: '鍖呰鏈�', componentName: '浼犻�佸甫', name: '鍙戠儹涓�', predictedLife: 260, remainingDays: 61 },
+  { key: '1', deviceName: '婵�鍏夋墦鏍囨満', componentName: '浼犻�佸甫', name: '鍐峰嵈姘�', predictedLife: 180, remainingDays: 43 },
+  { key: '1', deviceName: '閽㈢綉娓呮礂鏈�', componentName: '浼犻�佸甫', name: '娓呮礂娑�', predictedLife: 180, remainingDays: 95 },
+  { key: '1', deviceName: '閽㈢綉娓呮礂鏈�', componentName: '浼犻�佸甫', name: '婊よ姱', predictedLife: 180, remainingDays: 95 },
+  { key: '1', deviceName: '绔瓙鏈�', componentName: '浼犻�佸甫', name: '鍒�鐗�', predictedLife: 180, remainingDays: 112 },
+  { key: '1', deviceName: '鐢佃剳鍓ョ嚎鏈�', componentName: '浼犻�佸甫', name: '鍒�鐗�', predictedLife: 180, remainingDays: 107 },
 
-  { key: '3', deviceName: '娉ㄥ鏈�', componentName: '娑插帇绯荤粺', name: '婊よ姱', predictedLife: 180, remainingDays: 90 },
-
-  { key: '5', deviceName: '鐒婃帴鏈哄櫒浜�', componentName: '鐒婃灙', name: '鐒婂槾', predictedLife: 240, remainingDays: 60 }
+  { key: '2', deviceName: 'CNC鍔犲伐涓績', componentName: '涓昏酱', name: '鍒�绛掑す', predictedLife: 1100, remainingDays: 130 },
+  { key: '4', deviceName: '绌哄帇鏈�', componentName: '瀹夊叏闃�', name: '瀹夊叏闃�', predictedLife: 365, remainingDays: 130 },
+  { key: '1', deviceName: '鍠风爜鏈�', componentName: '浼犻�佸甫', name: '澧ㄦ按', predictedLife: 365, remainingDays: 184 },
+  { key: '3', deviceName: '娉ㄥ鏈�', componentName: '娑插帇绯荤粺', name: '娑插帇娌�', predictedLife: 1100, remainingDays: 395 },
+  { key: '5', deviceName: '鐒婃帴鏈哄櫒浜�', componentName: '鐒婃灙', name: '鐑欓搧鑺�', predictedLife: 1000, remainingDays: 512 }
 ]);
 
 const getLifeStatus = (remainingDays) => {
-  if (remainingDays <= 30) {
+  if (remainingDays <= 90) {
     return '鍗冲皢鍒版湡';
-  } else if (remainingDays <= 90) {
+  } else if (remainingDays <= 150) {
     return '涓湡棰勮';
   } else {
     return '瀵垮懡鍏呰冻';
@@ -274,10 +301,10 @@
 };
 
 const getLifeStatusColor = (remainingDays) => {
-  if (remainingDays <= 30) {
-    return 'red';
-  } else if (remainingDays <= 90) {
+  if (remainingDays <= 90) {
     return 'orange';
+  } else if (remainingDays <= 150) {
+    return 'blue';
   } else {
     return 'green';
   }
@@ -290,7 +317,7 @@
 
 
 const getStockStatus = (currentStock, safetyStock) => {
-  if (currentStock <= safetyStock) {
+  if (currentStock < safetyStock) {
     return '搴撳瓨棰勮';
   } else {
     return '搴撳瓨鍏呰冻';
@@ -298,8 +325,8 @@
 };
 
 const getStockStatusColor = (currentStock, safetyStock) => {
-  if (currentStock <= safetyStock) {
-    return 'red';
+  if (currentStock < safetyStock) {
+    return 'orange';
   } else {
     return 'green';
   }
@@ -340,13 +367,13 @@
   // 鏍规嵁璁惧鍚嶇О涓嶅悓璺宠浆涓嶅悓鐨勮鎯呴〉闈�
   if (record.name === 'SMT璐寸墖鏈�') {
     console.log('璁惧ID111:', record.name)
-    router.push({ path: '/predictive/smt-detail', query: { deviceId: record.key } });
+    router.push({ path: '/predictive/smt-detail', query: { deviceId: 15 } });
   } else if (record.name === 'CNC鍔犲伐涓績') {
-    router.push({ path: '/predictive/cnc-detail', query: { deviceId: record.key } });
+    router.push({ path: '/predictive/cnc-detail', query: { deviceId: 23 } });
   } else if (record.name === '娉ㄥ鏈�') {
-    router.push({ path: '/predictive/injection-detail', query: { deviceId: record.key } });
+    router.push({ path: '/predictive/injection-detail', query: { deviceId: 181 } });
   } else {
-    router.push({ path: '/predictive/air-compressor-detail', query: { deviceId: record.key } });
+    router.push({ path: '/predictive/air-compressor-detail', query: { deviceId: 46 } });
   }
 };
 
@@ -363,7 +390,7 @@
       xAxis: {
         type: 'category',
         data: ['10鍒�', '9鍒�', '8鍒�', '7鍒�', '6鍒�', '5鍒�', '4鍒�', '3鍒�', '2鍒�', '1鍒�'],
-        
+
       },
       yAxis: {
         type: 'value',
@@ -383,7 +410,7 @@
             { value: 21, itemStyle: { color: '#52c41a' } },
             { value: 8, itemStyle: { color: '#faad14' } },
             { value: 5, itemStyle: { color: '#faad14' } },
-           
+
           ],
           label: {
             show: true,
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>
diff --git a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue
index afb4146..b274799 100644
--- a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue
@@ -68,13 +68,15 @@
             />
           </div>
 
-          <a-divider />
+          <a-divider orientation="left">棰勬祴鎬х淮鎶ゅ缓璁�</a-divider>
 
           <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>
@@ -89,42 +91,42 @@
         <a-card title="璁惧鏁版嵁" class="mb-4">
           <a-row :gutter="[16, 16]">
             <a-col :span="4">
-              <a-statistic title="X杞存�荤Щ鍔ㄨ窛绂�" :value="healthData.xAxisTravel" suffix="km">
+              <a-statistic title="X杞存�荤Щ鍔ㄨ窛绂�" :value="healthData.xAxisTravel.toFixed(2)" suffix="km">
                 <template #prefix>
                   <LineChartOutlined />
                 </template>
               </a-statistic>
             </a-col>
             <a-col :span="4">
-              <a-statistic title="Y杞存�荤Щ鍔ㄨ窛绂�" :value="healthData.yAxisTravel" suffix="km">
+              <a-statistic title="Y杞存�荤Щ鍔ㄨ窛绂�" :value="healthData.yAxisTravel.toFixed(2)" suffix="km">
                 <template #prefix>
                   <LineChartOutlined />
                 </template>
               </a-statistic>
             </a-col>
             <a-col :span="4">
-              <a-statistic title="鍗″甫娆℃暟" :value="healthData.tapeJamCount" suffix="娆�">
+              <a-statistic title="鍗″甫娆℃暟" :value="healthData.tapeJamCount.toFixed(0)" suffix="娆�">
                 <template #prefix>
                   <WarningOutlined />
                 </template>
               </a-statistic>
             </a-col>
             <a-col :span="4">
-              <a-statistic title="鍗℃枡娆℃暟" :value="healthData.materialJamCount" suffix="娆�">
+              <a-statistic title="鍗℃枡娆℃暟" :value="healthData.materialJamCount.toFixed(0)" suffix="娆�">
                 <template #prefix>
                   <WarningOutlined />
                 </template>
               </a-statistic>
             </a-col>
             <a-col :span="4">
-              <a-statistic title="鎷兼澘鏁�" :value="healthData.panelCount" suffix="鍧�">
+              <a-statistic title="鎷兼澘鏁�" :value="healthData.panelCount.toFixed(0)" suffix="鍧�">
                 <template #prefix>
                   <AppstoreOutlined />
                 </template>
               </a-statistic>
             </a-col>
             <a-col :span="4">
-              <a-statistic title="鍑洪敊鍋滄満鏃堕棿" :value="healthData.downtime" suffix="绉�">
+              <a-statistic title="鍑洪敊鍋滄満鏃堕棿" :value="healthData.downtime.toFixed(1)" suffix="绉�">
                 <template #prefix>
                   <FieldTimeOutlined />
                 </template>
@@ -214,7 +216,7 @@
 </template>
 
 <script lang="ts">
-import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
+import { defineComponent, reactive, onMounted, onUnmounted, ref, nextTick } from 'vue';
 import * as echarts from 'echarts';
 import {
   LineChartOutlined,
@@ -223,6 +225,7 @@
   FieldTimeOutlined
 } from '@ant-design/icons-vue';
 import img from '#/assets/images/JUKI.png'
+import { getDeviceDataSmt, updateDeviceData, initDeviceData } from '#/api/eims/equ/deviceData'
 
 export default defineComponent({
   name: 'SmtMachineDetail',
@@ -244,20 +247,20 @@
       healthColor: '#52c41a',
       predictedLife: 635,
       riskLevel: '浣庨闄�',
-      riskColor: '#52c41a',
+      riskColor: '#1a7ac4',
       xAxisTravel: 300.179,
       yAxisTravel: 233.392,
       tapeJamCount: 6,
       materialJamCount: 15,
       panelCount: 2480,
       downtime: 4.5,
-      // 鐢ㄤ簬绱姞鐨勬暟鎹�
-      accumulatedXAxisTravel: 300.179,
-      accumulatedYAxisTravel: 233.392,
-      accumulatedTapeJamCount: 6,
-      accumulatedMaterialJamCount: 15,
-      accumulatedPanelCount: 2480,
-      accumulatedDowntime: 4.5
+      // // 鐢ㄤ簬绱姞鐨勬暟鎹�
+      // accumulatedXAxisTravel: 300.179,
+      // accumulatedYAxisTravel: 233.392,
+      // accumulatedTapeJamCount: 6,
+      // accumulatedMaterialJamCount: 15,
+      // accumulatedPanelCount: 2480,
+      // accumulatedDowntime: 4.5
     });
 
     const maintenanceColumns = [
@@ -293,25 +296,65 @@
       {
         key: '1',
 
-         type: '璐磋澶寸淮鎶�',
-        content: '鍚稿槾鐪熺┖鍘嬪姏鏍″噯',
-        suggestedTime: '2024-04-05',
+         type: '1鍙疯创瑁呯郴缁熺淮鎶�',
+        content: '鍚稿槾鐪熺┖鍘嬪姏鍋忎綆',
+        suggestedTime: '2025-07-05',
+        urgency: '涓瓑'
+      },
+      {
+        key: '6',
+
+        type: '4鍙疯创瑁呯郴缁熺淮鎶�',
+        content: 'T杞撮┈杈惧鍛藉憡鎬�',
+        suggestedTime: '2025-07-05',
         urgency: '涓瓑'
       },
       {
         key: '2',
                type: '杩愬姩绯荤粺淇濆吇',
         content: 'X/Y杞翠己鏈嶇數鏈烘鼎婊戞鏌�',
-        suggestedTime: '2024-03-20',
+        suggestedTime: '2025-06-20',
         urgency: '浣�'
       },
       {
         key: '3',
         type: '渚涙枡绯荤粺妫�鏌�',
         content: '椋炶揪鍗″甫/鍗℃枡娆℃暟娓呴浂',
-        suggestedTime: '2024-03-10',
+        suggestedTime: '2025-06-10',
         urgency: '浣�'
-      }
+      },
+      {
+        key: '4',
+
+        type: '2鍙疯创瑁呯郴缁熺淮鎶�',
+        content: '鐪熺┖鍘嬪姏涓嶇ǔ瀹�',
+        suggestedTime: '2025-07-05',
+        urgency: '浣�'
+      },
+      {
+        key: '5',
+        type: '3鍙疯创瑁呯郴缁熺淮鎶�',
+        content: 'Z杞撮┈杈剧數娴佸紓甯�',
+        suggestedTime: '2025-07-05',
+        urgency: '浣�'
+      },
+
+      {
+        key: '7',
+
+        type: '5鍙疯创瑁呭ご缁存姢',
+        content: '鐪熺┖鍘嬪姏涓嶇ǔ瀹�',
+        suggestedTime: '2025-07-05',
+        urgency: '浣�'
+      },
+      {
+        key: '8',
+
+        type: '6鍙疯创瑁呭ご缁存姢',
+        content: '鐪熺┖鍘嬪姏涓嶇ǔ瀹�',
+        suggestedTime: '2025-07-05',
+        urgency: '浣�'
+      },
     ]);
 
     const getUrgencyColor = (urgency: string) => {
@@ -326,6 +369,27 @@
           return 'default';
       }
     };
+
+
+     const fetchDeviceData = async () => {
+      try {
+        const res = await getDeviceDataSmt();
+        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 = [
       {
@@ -356,33 +420,111 @@
     const sparePartData = reactive([
       {
         key: '1',
-        name: 'X杞翠己鏈嶇數鏈�',
+        name: '1鍙疯创瑁呯郴缁烼杞翠己鏈嶇數鏈�',
         currentLife: '15000灏忔椂',
-        remainingLife: '4354灏忔椂',
+        remainingLife: '1451灏忔椂',
+        status: '棰勮'
+      },
+      {
+        key: '5',
+        name: '1鍙疯创瑁呯郴缁焃杞翠己鏈嶇數鏈�',
+        currentLife: '15000灏忔椂',
+        remainingLife: '7521灏忔椂',
+        status: '鑹ソ'
+      },
+      {
+        key: '9',
+        name: '1鍙疯创瑁呯郴缁熺湡绌虹數纾侀榾',
+        currentLife: '10000灏忔椂',
+        remainingLife: '2154灏忔椂',
         status: '鑹ソ'
       },
       {
         key: '2',
-        name: '鍚稿槾',
+        name: '1鍙疯创瑁呭ご',
         currentLife: '1000000娆�',
-        remainingLife: '425000娆�',
+        remainingLife: '425542娆�',
+        status: '鑹ソ'
+      },
+      {
+        key: '6',
+        name: '2鍙疯创瑁呯郴缁烼杞翠己鏈嶇數鏈�',
+        currentLife: '15000灏忔椂',
+        remainingLife: '7540灏忔椂',
+        status: '鑹ソ'
+      },
+      {
+        key: '7',
+        name: '2鍙疯创瑁呯郴缁焃杞翠己鏈嶇數鏈�',
+        currentLife: '15000灏忔椂',
+        remainingLife: '7521灏忔椂',
+        status: '鑹ソ'
+      },
+      {
+        key: '9',
+        name: '2鍙疯创瑁呯郴缁熺湡绌虹數纾侀榾',
+        currentLife: '10000灏忔椂',
+        remainingLife: '2154灏忔椂',
+        status: '鑹ソ'
+      },
+      {
+        key: '8',
+        name: '2鍙疯创瑁呭ご',
+        currentLife: '1000000娆�',
+        remainingLife: '751251娆�',
         status: '鑹ソ'
       },
       {
         key: '3',
         name: '椋炶揪',
         currentLife: '96涓湀',
-        remainingLife: '48涓湀',
+        remainingLife: '43涓湀',
         status: '鑹ソ'
-      }
+      },
+
     ]);
 
     const historyData = reactive([
       {
         id: '1',
+        date: '2025-07-22',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚鏈堝害淇濆吇锛屼笣鏉嗗杞ㄦ敞娌癸紝鎶涙枡娓呯悊',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-06-18',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚鏈堝害淇濆吇锛屾槗鎹熶欢鏇存崲',
+        color: 'green'
+      },
+      {
+        id: '1',
         date: '2025-05-15',
         type: '瀹氭湡淇濆吇',
         description: '瀹屾垚瀛e害淇濆吇锛屾鏌ヨ繍鍔ㄧ郴缁熸鼎婊�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-04-20',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚鏈堝害淇濆吇锛岄槻灏樿繃婊ょ綉娓呯悊锛屽杞ㄦ敞娌�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-03-16',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚鏈堝害淇濆吇锛岀湡绌哄�兼牎鍑�',
+        color: 'green'
+      },
+      {
+        id: '1',
+        date: '2025-02-13',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚鏈堝害淇濆吇锛屽惛鍢存鏌ユ洿鎹紝鎶涙枡娓呯悊锛岀浉鏈哄弬鏁版牎鍑�',
         color: 'green'
       },
       {
@@ -394,9 +536,9 @@
       },
       {
         id: '3',
-        date: '2024-12-01',
+        date: '2025-01-15',
         type: '瀹氭湡淇濆吇',
-        description: '瀹屾垚骞村害淇濆吇锛屾牎鍑嗚瑙夌郴缁�',
+        description: '瀹屾垚骞村害淇濆吇锛岃创瑁呯郴缁熸牎鍑嗭紝鏄撴崯浠舵洿鎹紝鏍″噯瑙嗚绯荤粺',
         color: 'green'
       }
     ]);
@@ -420,34 +562,70 @@
     };
 
     let healthDataInterval: number | undefined;
+    let scrollInterval: number | undefined;
+    const maintenanceTable = ref<HTMLElement | null>(null);
 
-    const updateHealthData = () => {
-      healthData.accumulatedXAxisTravel = parseFloat((healthData.accumulatedXAxisTravel + Math.random() * 0.01).toFixed(3));
-      healthData.accumulatedYAxisTravel = parseFloat((healthData.accumulatedYAxisTravel + Math.random() * 0.01).toFixed(3));
-      healthData.accumulatedTapeJamCount = healthData.accumulatedTapeJamCount + Math.random() * 0.005;
-      healthData.accumulatedMaterialJamCount = healthData.accumulatedMaterialJamCount + Math.random() * 0.005;
-      healthData.accumulatedPanelCount =healthData.accumulatedPanelCount + Math.random() * 0.1;
-      healthData.accumulatedDowntime = parseFloat((healthData.accumulatedDowntime + Math.random() * 0.01).toFixed(1));
+    const startScroll = () => {
+      if (!maintenanceTable.value) return;
 
-      // 鏇存柊鏄剧ず鐨勬暟鎹�
-      healthData.xAxisTravel = healthData.accumulatedXAxisTravel;
-      healthData.yAxisTravel = healthData.accumulatedYAxisTravel;
-      healthData.tapeJamCount = Math.round(healthData.accumulatedTapeJamCount);
-      healthData.materialJamCount = Math.round(healthData.accumulatedMaterialJamCount);
-      healthData.panelCount = Math.round( healthData.accumulatedPanelCount);
-      healthData.downtime = healthData.accumulatedDowntime;
+      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; // 姣忔婊氬姩1px
+        if (currentScrollTop >= scrollHeight - clientHeight) {
+          currentScrollTop = 0; // 婊氬姩鍒板簳閮ㄥ悗鍥炲埌椤堕儴
+        }
+        tableBody.scrollTop = currentScrollTop;
+      }, 50); // 姣�50姣婊氬姩涓�娆�
     };
+
+    // const updateHealthData = () => {
+    //   healthData.accumulatedXAxisTravel = parseFloat((healthData.accumulatedXAxisTravel + Math.random() * 0.01).toFixed(3));
+    //   healthData.accumulatedYAxisTravel = parseFloat((healthData.accumulatedYAxisTravel + Math.random() * 0.01).toFixed(3));
+    //   healthData.accumulatedTapeJamCount = healthData.accumulatedTapeJamCount + Math.random() * 0.005;
+    //   healthData.accumulatedMaterialJamCount = healthData.accumulatedMaterialJamCount + Math.random() * 0.005;
+    //   healthData.accumulatedPanelCount =healthData.accumulatedPanelCount + Math.random() * 0.1;
+    //   healthData.accumulatedDowntime = parseFloat((healthData.accumulatedDowntime + Math.random() * 0.01).toFixed(1));
+
+    //   // 鏇存柊鏄剧ず鐨勬暟鎹�
+    //   healthData.xAxisTravel = healthData.accumulatedXAxisTravel;
+    //   healthData.yAxisTravel = healthData.accumulatedYAxisTravel;
+    //   healthData.tapeJamCount = Math.round(healthData.accumulatedTapeJamCount);
+    //   healthData.materialJamCount = Math.round(healthData.accumulatedMaterialJamCount);
+    //   healthData.panelCount = Math.round( healthData.accumulatedPanelCount);
+    //   healthData.downtime = healthData.accumulatedDowntime;
+    // };
 
     onMounted(() => {
       // 鍒濆鏇存柊涓�娆℃暟鎹�
-      updateHealthData();
+    //  updateHealthData();
       // 姣�5绉掓洿鏂颁竴娆¤澶囨暟鎹�
-      healthDataInterval = setInterval(updateHealthData, 5000);
+    //  healthDataInterval = setInterval(updateHealthData, 5000);
+
+      nextTick(() => {
+        startScroll();
+      });
     });
 
     onUnmounted(() => {
       if (healthDataInterval) {
         clearInterval(healthDataInterval);
+      }
+      if (scrollInterval) {
+        clearInterval(scrollInterval);
+      }
+       if (deviceDataInterval) {
+        clearInterval(deviceDataInterval);
       }
     });
 
@@ -461,7 +639,8 @@
       historyData,
       getStatusColor,
       getUrgencyColor,
-      handleMaintenance
+      handleMaintenance,
+      maintenanceTable
     };
   },
   components: {
@@ -487,7 +666,7 @@
             time,
             value: newValue
           });
-          if (s.data.length > 60) {
+          if (s.data.length > 24) {
             s.data.shift();
           }
         });
@@ -560,8 +739,8 @@
       seriesConfig.forEach(s => {
         s.data = [];
         // 鐢熸垚鍒濆鏁版嵁鐐癸紙60涓偣锛�5鍒嗛挓鏁版嵁锛�
-      for (let i = 0; i < 60; i++) {
-        const now = new Date(Date.now() - (60 - i) * 5000); // 鐢熸垚杩囧幓5鍒嗛挓鐨勬暟鎹�
+      for (let i = 0; i < 24; i++) {
+        const now = new Date(Date.now() - (24 - i) * 5000); // 鐢熸垚杩囧幓5鍒嗛挓鐨勬暟鎹�
         const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
         const newValue = (s.baseValue + (Math.random() * 2 - 1) * s.fluctuation).toFixed(2);
         s.data.push({
diff --git a/eims/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java b/eims/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java
index 67be2fb..4a44042 100644
--- a/eims/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java
+++ b/eims/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java
@@ -505,6 +505,18 @@
         return atomic.incrementAndGet();
     }
 
+
+    /**
+     * 閫掑鍘熷瓙鍊�
+     *
+     * @param key Redis閿�
+     * @return 褰撳墠鍊�
+     */
+    public static long incrAtomicValueByNum(String key, long num) {
+        RAtomicLong atomic = CLIENT.getAtomicLong(key);
+        return atomic.addAndGet(num);
+    }
+
     /**
      * 閫掑噺鍘熷瓙鍊�
      *
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/DeviceDataController.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/DeviceDataController.java
new file mode 100644
index 0000000..c431bd8
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/DeviceDataController.java
@@ -0,0 +1,109 @@
+package org.dromara.eims.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.scheduling.annotation.Scheduled;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 璁惧鏁版嵁鎺у埗鍣�
+ *
+ * @author Lion Li
+ * @date 2024-07-26
+ */
+@RestController
+@RequestMapping("/eims/deviceData")
+@RequiredArgsConstructor
+public class DeviceDataController extends BaseController {
+
+    private static final String DEVICE_DATA_PREFIX = "eims:device:data:";
+
+    /**
+     * 鑾峰彇璁惧鏁版嵁
+     */
+    @GetMapping("/get")
+    public R<Map<String, Double>> getDeviceData() {
+
+
+        Map<String, Double> deviceData = new HashMap<>();
+        deviceData.put("xAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "xAxisTravel") / 100000.0);
+        deviceData.put("yAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "yAxisTravel") / 100000.0);
+        deviceData.put("zAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "zAxisTravel") / 100000.0);
+        deviceData.put("toolChangeCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "toolChangeCount") / 10.0);
+        deviceData.put("partCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "partCount") / 100000.0);
+        deviceData.put("downtime", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "downtime") / 10.0);
+        return R.ok(deviceData);
+    }
+
+    /**
+     * 鑾峰彇璁惧鏁版嵁
+     */
+    @GetMapping("/getSmt")
+    public R<Map<String, Double>> getDeviceDataSmt() {
+
+
+        Map<String, Double> deviceData = new HashMap<>();
+        deviceData.put("xAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtXAxisTravel") / 1000.0);
+        deviceData.put("yAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtYAxisTravel") / 1000.0);
+        deviceData.put("tapeJamCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount") / 1000.0);
+        deviceData.put("materialJamCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount") / 1000.0);
+        deviceData.put("panelCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount") / 1000.0);
+        deviceData.put("downtime", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime") / 100.0);
+        return R.ok(deviceData);
+    }
+
+    /**
+     *  injectionCount: 495 * 24 * 60 + 19 * 60 + 44, // 娉ㄥ皠娆℃暟锛岃浆鎹负鍒嗛挓
+     *       clampingCount: 545636, // 鍚堟ā娆℃暟 // 璺熼殢浜ч噺 50s鍔犱竴娆�
+     *       productionCycle: 45, // 鐢熶骇鍛ㄦ湡
+     *       energyConsumption: 64, // 鑳借��
+     *       yieldRate: 354, // 浜ч噺   50绉掑鍔犱竴妯�
+     *       downtime: 120, // 鍑洪敊鍋滄満鏃堕棿
+     *
+     */
+    /**
+     * 鑾峰彇璁惧鏁版嵁
+     */
+    @GetMapping("/getInj")
+    public R<Map<String, Double>> getDeviceDataInj() {
+
+
+        Map<String, Double> deviceData = new HashMap<>();
+        deviceData.put("injectionCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "injectionCount") / 3600.0);
+        deviceData.put("clampingCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "clampingCount") / 10.0);
+        deviceData.put("productionCycle", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "productionCycle") / 10.0);
+        deviceData.put("energyConsumption", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption") / 1000.0);
+        deviceData.put("yieldRate", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "yieldRate") / 10.0);
+
+        return R.ok(deviceData);
+    }
+
+
+
+    /**
+     * 鍒濆鍖栬澶囨暟鎹�
+     */
+    @PostMapping("/init")
+    public R<Void> initDeviceData() {
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtXAxisTravel", 300282L);  // 50/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtYAxisTravel", 233524L);  // 45/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount", 6000);      // 5/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 15000); // 5/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount", 2481000); // 100/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime", 450); //5/5s
+
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "injectionCount", 43848000L);  // 5/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "clampingCount", 5456360L);  // 1/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "productionCycle", 450);
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption", 64000); // 7/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "yieldRate", 3540); // 1/5s
+
+        return R.ok();
+    }
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/AutoApproveRepairJob.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/AutoApproveRepairJob.java
new file mode 100644
index 0000000..eaa444a
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/AutoApproveRepairJob.java
@@ -0,0 +1,64 @@
+package org.dromara.eims.job;
+
+import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
+import com.aizuda.snailjob.client.job.core.dto.JobArgs;
+import com.aizuda.snailjob.client.model.ExecuteResult;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import org.dromara.common.core.constant.DictConstants;
+import org.dromara.common.core.utils.DateUtils;
+import org.dromara.eims.domain.EimsRepairRes;
+import org.dromara.eims.domain.EimsRepairFb;
+import org.dromara.eims.mapper.EimsRepairResMapper;
+import org.dromara.eims.mapper.EimsRepairFbMapper;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+
+@Component
+@RequiredArgsConstructor
+@JobExecutor(name = "autoApproveRepairJob")
+public class AutoApproveRepairJob {
+
+    private final EimsRepairResMapper repairResMapper;
+    private final EimsRepairFbMapper repairFbMapper;
+
+    @SneakyThrows
+    @Transactional(rollbackFor = Exception.class)
+    public ExecuteResult jobExecute(JobArgs jobArgs) {
+        // 鏌ヨ宸插畬鎴愶紙status绛変簬3锛変笖缁撴潫鏃堕棿瓒呰繃涓夊ぉ浠ヤ笂鐨勭淮淇崟
+        Date threeDaysAgo = DateUtils.addDays(DateUtils.getNowDate(), -3);
+        LambdaQueryWrapper<EimsRepairRes> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(EimsRepairRes::getStatus, DictConstants.REPAIR_RES_STATUS_DETAIL.WANCHENG)
+                    .le(EimsRepairRes::getEndTime, threeDaysAgo);
+
+        List<EimsRepairRes> repairOrders = repairResMapper.selectList(queryWrapper);
+
+        for (EimsRepairRes order : repairOrders) {
+            // 妫�鏌ユ槸鍚﹀凡缁忓瓨鍦ㄥソ璇勫弽棣�
+            LambdaQueryWrapper<EimsRepairFb> fbQueryWrapper = new LambdaQueryWrapper<>();
+            fbQueryWrapper.eq(EimsRepairFb::getResId, order.getId())
+                          .eq(EimsRepairFb::getRepairSatisfaction, 1);
+            Long count = repairFbMapper.selectCount(fbQueryWrapper);
+
+            // 灏嗙淮淇崟鐘舵�佹洿鏂颁负宸茶瘎浠�
+            order.setStatus(DictConstants.REPAIR_RES_STATUS_DETAIL.PINGJIA);
+            repairResMapper.updateById(order);
+
+            if (count == 0) {
+                // 鎻掑叆涓�鏉epairSatisfaction涓�1鐨勫弽棣堟暟鎹�
+                EimsRepairFb feedback = new EimsRepairFb();
+                feedback.setResId(order.getId());
+                feedback.setRepairSatisfaction("1"); // 榛樿濂借瘎
+                feedback.setRemark("绯荤粺鑷姩濂借瘎"); // 鍙互鏍规嵁闇�瑕佽缃弽棣堝唴瀹�
+                feedback.setCreateTime(DateUtils.getNowDate());
+                repairFbMapper.insert(feedback);
+            }
+        }
+
+        return ExecuteResult.success("鑷姩濂借瘎缁翠慨鍗曚换鍔℃墽琛屾垚鍔�");
+    }
+}
\ No newline at end of file
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/DeviceDataIncrJob.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/DeviceDataIncrJob.java
new file mode 100644
index 0000000..5b2e888
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/DeviceDataIncrJob.java
@@ -0,0 +1,76 @@
+package org.dromara.eims.job;
+
+import org.dromara.common.redis.utils.RedisUtils;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.util.Calendar;
+
+@Configuration
+@EnableScheduling
+public class DeviceDataIncrJob {
+    private static final String DEVICE_DATA_PREFIX = "eims:device:data:";
+    /**
+     * 瀹氭椂鏇存柊璁惧鏁版嵁
+     * 姣忓ぉ鏃╀笂8鐐瑰埌涓嬪崍5鐐逛箣闂达紝姣忓皬鏃舵洿鏂颁竴娆�
+     */
+    @Scheduled(cron = "0/5 * 8-17 * * ?")
+    public void updateDeviceDataScheduled() {
+        System.out.println("鎵ц瀹氭椂浠诲姟锛屾洿鏂拌澶囨暟鎹細锛氾細");
+        // 妫�鏌ュ綋鍓嶆椂闂存槸鍚﹀湪鏃╀笂8鐐瑰埌涓嬪崍5鐐逛箣闂�
+        Calendar now = Calendar.getInstance();
+        int hourOfDay = now.get(Calendar.HOUR_OF_DAY);
+        if (hourOfDay >= 8 && hourOfDay < 17) {
+            // 鏇存柊骞呭害
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "xAxisTravel", 83L); // 姣忓ぉ鍔�6灏忔椂锛屽搴擱edis涓姞60
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "yAxisTravel", 833L); // 姣忓ぉ鍔�60娆�
+            // toolChangeCount 鍜� downtime 涓嶆尝鍔紝鎵�浠ヤ笉杩涜澧為噺鎿嶄綔
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "partCount", 210L); // 姣忓ぉ鍔�15涓�
+
+
+
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtXAxisTravel", 300282L);  // 50/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtYAxisTravel", 233524L);  // 45/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount", 6000);      // 5/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 15000); // 5/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount", 2481000); // 100/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime", 450); //5/5s
+
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtXAxisTravel", 50L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtYAxisTravel", 45L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtTapeJamCount", 5L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 5L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtPanelCount", 100L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtDowntime", 1L);
+
+
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "injectionCount", 43848000L);  // 5/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "clampingCount", 5456360L);  // 1/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "productionCycle", 450);
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption", 64000); // 7/5s
+//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "yieldRate", 3540); // 1/5s
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "injectionCount", 5L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "clampingCount", 1L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "energyConsumption", 10L);
+            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "yieldRate", 1L);
+        }
+    }
+
+
+    // 鏂板涓�涓畾鏃跺櫒锛岀澶╅浂鐐规竻闆�
+    @Scheduled(cron = "0 0 0 * * ?")
+    public void resetDeviceDataScheduled() {
+        System.out.println("鎵ц瀹氭椂浠诲姟锛岄噸缃澶囨暟鎹細锛氾細");
+
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount", 0);      // 5/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 0); // 5/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount", 0); // 100/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime", 0); //5/5s
+
+
+
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption", 0); // 7/5s
+        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "yieldRate", 0); // 1/5s
+    }
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java
index bf9b051..23d1e31 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java
@@ -21,7 +21,6 @@
 import org.dromara.eims.domain.vo.EimsEquImportVo;
 import org.dromara.eims.domain.vo.EimsEquVo;
 import org.dromara.eims.service.IEimsEquService;
-import org.dromara.system.domain.bo.SysUserBo;
 import org.dromara.system.service.ISysUserService;
 
 import java.util.List;

--
Gitblit v1.9.3