From 5a0ab7dbeaba63e7d370e9fa4586f1664e1da775 Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期三, 09 七月 2025 08:53:39 +0800
Subject: [PATCH] feat(eims-ui): 新增预测性维护主界面和cnc加工中心、空压机、smt贴片机、注塑机等详情界面

---
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue |  549 +++++++++++
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue                            |  409 ++++++++
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/air-compressor-detail.vue            |  513 ++++++++++
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue      |  505 ++++++++++
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/device-detail.vue                    |  439 ++++++++
 eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue               |  509 ++++++++++
 6 files changed, 2,924 insertions(+), 0 deletions(-)

diff --git a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/air-compressor-detail.vue b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/air-compressor-detail.vue
new file mode 100644
index 0000000..e6dea20
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/air-compressor-detail.vue
@@ -0,0 +1,513 @@
+<template>
+  <div class="device-detail-container">
+    <a-page-header
+      title="绌哄帇鏈洪娴嬫�х淮鎶よ鎯�"
+      :sub-title="deviceInfo.deviceName"
+      @back="() => $router.go(-1)"
+    />
+
+    <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-card>
+      </a-col>
+
+      <!-- 璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿 -->
+      <a-col :span="16">
+        <a-card title="璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿" class="mb-4" :style="{ height: '440px' }">
+          <a-row :gutter="16">
+            <a-col :span="8">
+              <a-statistic
+                title="鏁翠綋鍋ュ悍搴�"
+                :value="healthData.overallHealth"
+                :precision="0"
+                suffix="%"
+                :value-style="{ color: healthData.healthColor }"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="棰勬祴鍓╀綑瀵垮懡"
+                :value="healthData.predictedLife"
+                suffix="澶�"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="鏁呴殰椋庨櫓绛夌骇"
+                :value="healthData.riskLevel"
+                :value-style="{ color: healthData.riskColor }"
+              />
+            </a-col>
+          </a-row>
+          <div class="mt-4">
+            <a-progress
+              :percent="healthData.overallHealth"
+              :stroke-color="healthData.healthColor"
+              :show-info="false"
+            />
+          </div>
+          <a-divider orientation="left">棰勬祴鎬х淮鎶ゅ缓璁�</a-divider>
+          <a-table
+            :columns="maintenanceColumns"
+            :data-source="maintenanceData"
+            :pagination="false"
+            size="small"
+          >
+            <template #urgency="{ text }">
+              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
+            </template>
+            <template #action="{ record }">
+              <a-button type="link" size="small" @click="handleMaintenance(record)">澶勭悊</a-button>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+
+    <!-- 瀹炴椂鏁版嵁瓒嬪娍鍥� -->
+    <a-card title="瀹炴椂鏁版嵁瓒嬪娍鍥�" class="mb-4">
+      <a-row :gutter="16">
+        <a-col :span="8">
+          <div id="exhaustPressureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="exhaustTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="hostVibrationChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="mainBearingTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="mainMotorCurrentChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="oilTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="oilPressureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="oilLevelChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="inletPressureChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="inletTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="airFlowChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="dryerDewPointChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="coolingWaterTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="coolingWaterFlowChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="ambientTemperatureHumidityChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+    </a-card>
+    <a-row :gutter="16">
+      <!-- 澶囦欢瀵垮懡棰勬祴 -->
+      <a-col :span="12">
+        <a-card title="澶囦欢瀵垮懡棰勬祴" class="mb-4">
+          <a-table
+            :columns="sparePartColumns"
+            :data-source="sparePartData"
+            :pagination="false"
+            size="small"
+          >
+            <template #status="{ text }">
+              <a-tag :color="getStatusColor(text)">{{ text }}</a-tag>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+
+      <!-- 鍘嗗彶缁存姢璁板綍 -->
+      <a-col :span="12">
+        <a-card title="鍘嗗彶缁存姢璁板綍" class="mb-4">
+          <a-timeline>
+            <a-timeline-item v-for="item in historyData" :key="item.id" :color="item.color">
+              {{ item.date }} - {{ item.type }}: {{ item.description }}
+            </a-timeline-item>
+          </a-timeline>
+        </a-card>
+      </a-col>
+    </a-row>
+
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
+import * as echarts from 'echarts';
+
+export default defineComponent({
+  name: 'AirCompressorDetail',
+  setup() {
+    // 妯℃嫙鏁版嵁
+    const deviceInfo = reactive({
+      deviceName: '绌哄帇鏈� #AC-001',
+      deviceType: '绌哄帇鏈�',
+      deviceId: 'AC-2024-001',
+      installDate: '2023-05-10',
+      serviceLife: 10,
+      status: '杩愯涓�',
+      statusColor: '#52c41a'
+    });
+
+    const healthData = reactive({
+      overallHealth: 92,
+      healthColor: '#52c41a',
+      predictedLife: 3000,
+      riskLevel: '浣庨闄�',
+      riskColor: '#52c41a'
+    });
+
+    const maintenanceColumns = [
+      {
+        title: '缁存姢绫诲瀷',
+        dataIndex: 'type',
+        key: 'type'
+      },
+      {
+        title: '缁存姢鍐呭',
+        dataIndex: 'content',
+        key: 'content'
+      },
+      {
+        title: '寤鸿鏃堕棿',
+        dataIndex: 'suggestedTime',
+        key: 'suggestedTime'
+      },
+      {
+        title: '绱ф�ョ▼搴�',
+        dataIndex: 'urgency',
+        key: 'urgency',
+        slots: { customRender: 'urgency' }
+      },
+      {
+        title: '鎿嶄綔',
+        key: 'action',
+        slots: { customRender: 'action' }
+      }
+    ];
+
+    const maintenanceData = reactive([
+      {
+        key: '1',
+        type: '渚嬭淇濆吇',
+        content: '妫�鏌ヤ富鏈虹揣鍥轰欢',
+        suggestedTime: '2024-07-01',
+        urgency: '涓瓑'
+      },
+      {
+        key: '2',
+        type: '娑︽粦绯荤粺缁存姢',
+        content: '鏇存崲娑︽粦娌�',
+        suggestedTime: '2024-09-01',
+        urgency: '楂�'
+      },
+      {
+        key: '3',
+        type: '绌烘皵绯荤粺缁存姢',
+        content: '鏇存崲绌烘护鑺�',
+        suggestedTime: '2024-08-15',
+        urgency: '浣�'
+      }
+    ]);
+
+    const getUrgencyColor = (urgency: string) => {
+      switch (urgency) {
+        case '楂�':
+          return 'red';
+        case '涓瓑':
+          return 'orange';
+        case '浣�':
+          return 'green';
+        default:
+          return 'default';
+      }
+    };
+
+    const sparePartColumns = [
+      {
+        title: '澶囦欢鍚嶇О',
+        dataIndex: 'name',
+        key: 'name'
+      },
+      {
+        title: '褰撳墠瀵垮懡',
+        dataIndex: 'currentLife',
+        key: 'currentLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '棰勬祴鍓╀綑瀵垮懡',
+        dataIndex: 'remainingLife',
+        key: 'remainingLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        key: 'status',
+        slots: { customRender: 'status' }
+      }
+    ];
+
+    const sparePartData = reactive([
+      {
+        key: '1',
+        name: '绌烘护鑺�',
+        currentLife: 1000,
+        remainingLife: 200,
+        status: '棰勮'
+      },
+      {
+        key: '2',
+        name: '娌规护鑺�',
+        currentLife: 1500,
+        remainingLife: 500,
+        status: '鑹ソ'
+      },
+      {
+        key: '3',
+        name: '娌规皵鍒嗙鍣�',
+        currentLife: 2000,
+        remainingLife: 300,
+        status: '棰勮'
+      }
+    ]);
+
+    const historyData = reactive([
+      {
+        id: '1',
+        date: '2024-06-10',
+        type: '渚嬭淇濆吇',
+        description: '鏇存崲绌烘护鑺�佹补婊よ姱',
+        color: 'green'
+      },
+      {
+        id: '2',
+        date: '2024-03-05',
+        type: '鏁呴殰缁翠慨',
+        description: '涓绘満杞存壙娑︽粦鑴傝ˉ鍏�',
+        color: 'red'
+      },
+      {
+        id: '3',
+        date: '2023-12-01',
+        type: '骞村害淇濆吇',
+        description: '鍏ㄩ潰妫�鏌ヨ澶囪繍琛岀姸鎬�',
+        color: 'green'
+      }
+    ]);
+
+    const getStatusColor = (status: string) => {
+      switch (status) {
+        case '鑹ソ':
+          return '#52c41a';
+        case '棰勮':
+          return '#faad14';
+        case '鍗遍櫓':
+          return '#f5222d';
+        default:
+          return '#d9d9d9';
+      }
+    };
+
+    const handleMaintenance = (record: any) => {
+      console.log('澶勭悊缁存姢寤鸿:', record);
+      // 瀹為檯椤圭洰涓繖閲屼細璋冪敤API澶勭悊缁存姢寤鸿
+    };
+
+    return {
+      deviceInfo,
+      healthData,
+      maintenanceColumns,
+      maintenanceData,
+      sparePartColumns,
+      sparePartData,
+      historyData,
+      getStatusColor,
+      getUrgencyColor,
+      handleMaintenance
+    };
+  },
+
+  mounted() {
+    // 鍒濆鍖栧浘琛�
+    const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
+      const chart = echarts.init(document.getElementById(chartId));
+
+      // 棰勫厛鐢熸垚60涓暟鎹偣
+      for (let i = 0; i < 60; i++) {
+        const now = new Date(Date.now() - (60 - 1 - i) * 5000); // 鍊掓帹鏃堕棿
+        const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
+        const newValue = (baseValue + (Math.random() * fluctuation * 2 - fluctuation)).toFixed(2);
+        chartData.push({
+          time,
+          value: newValue
+        });
+      }
+
+      const updateChart = () => {
+        // 鐢熸垚鏂扮殑鏁版嵁鐐�
+        const now = new Date();
+        const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
+        const newValue = (baseValue + (Math.random() * fluctuation * 2 - fluctuation)).toFixed(2);
+
+        // 娣诲姞鏂版暟鎹偣锛屾渶澶氫繚鐣�60涓偣锛�5鍒嗛挓鏁版嵁锛�
+        chartData.push({
+          time,
+          value: newValue
+        });
+        if (chartData.length > 60) {
+          chartData.shift();
+        }
+
+        const option = {
+          title: {
+            text: title,
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis',
+            formatter: (params) => {
+              return `${params[0].axisValueLabel}<br/>${params[0].marker} ${params[0].seriesName}: ${params[0].data}${unit}`;
+            }
+          },
+          grid: {
+            left: '8%', // 澧炲姞宸︿晶杈硅窛
+            right: '5%',
+            bottom: '10%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: chartData.map(item => item.time)
+          },
+          yAxis: {
+            type: 'value',
+            axisLabel: {
+              formatter: (value) => `${value}${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)'
+                  }
+                ])
+              },
+            }
+          ]
+        };
+        chart.setOption(option);
+      };
+
+      // 鍒濆娓叉煋
+      updateChart();
+
+      // 姣�5绉掓洿鏂颁竴娆℃暟鎹�
+      const intervalId = setInterval(updateChart, 5000);
+
+      window.addEventListener('resize', () => {
+        chart.resize();
+      });
+      onUnmounted(() => {
+        clearInterval(intervalId);
+      });
+
+    };
+
+
+    initChart('exhaustPressureChart', '鎺掓皵鍘嬪姏', [], 'bar', 7.5, 0.2);
+    initChart('exhaustTemperatureChart', '鎺掓皵娓╁害', [], '掳C', 85, 2);
+    initChart('hostVibrationChart', '涓绘満鎸姩', [], 'mm/s', 3.5, 0.5);
+    initChart('mainBearingTemperatureChart', '涓昏酱鎵挎俯搴�', [], '掳C', 70, 3);
+    initChart('mainMotorCurrentChart', '涓荤數鏈虹數娴�', [], 'A', 120, 5);
+    initChart('oilTemperatureChart', '娌规俯', [], '掳C', 60, 2);
+    initChart('oilPressureChart', '娌瑰帇', [], 'bar', 4.0, 0.1);
+    initChart('oilLevelChart', '娌逛綅', [], '%', 80, 5);
+    initChart('inletPressureChart', '杩涙皵鍘嬪姏', [], 'bar', 1.0, 0.05);
+    initChart('inletTemperatureChart', '杩涙皵娓╁害', [], '掳C', 25, 2);
+    initChart('airFlowChart', '绌烘皵娴侀噺', [], 'm鲁/min', 15, 1);
+    initChart('dryerDewPointChart', '骞茬嚗鍣ㄩ湶鐐�', [], '掳C', 3, 1);
+    initChart('coolingWaterTemperatureChart', '鍐峰嵈姘存俯搴�', [], '掳C', 30, 2);
+    initChart('coolingWaterFlowChart', '鍐峰嵈姘存祦閲�', [], 'L/min', 10, 0.5);
+    initChart('ambientTemperatureHumidityChart', '鐜娓╂箍搴�', [], '掳C', 28, 2);
+  }
+
+});
+</script>
+
+<style scoped>
+.device-detail-container {
+  padding: 16px;
+  background: #f0f2f5;
+}
+
+.mt-4 {
+  margin-top: 16px;
+}
+
+.mb-4 {
+  margin-bottom: 16px;
+}
+</style>
+  
+
+<style scoped>
+.air-compressor-detail {
+  padding: 16px;
+  background-color: #f0f2f5;
+}
+.header-card {
+  margin-bottom: 16px;
+}
+</style>
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
new file mode 100644
index 0000000..eb36187
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue
@@ -0,0 +1,505 @@
+<template>
+  <div class="device-detail-container">
+    <a-page-header
+      title="CNC鍔犲伐涓績棰勬祴鎬х淮鎶よ鎯�"
+      :sub-title="deviceInfo.deviceName"
+      @back="() => $router.go(-1)"
+    />
+
+    <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-card>
+      </a-col>
+
+      <!-- 璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿 -->
+      <a-col :span="16">
+        <a-card title="璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿" class="mb-4" :style="{ height: '440px' }">
+          <a-row :gutter="16">
+            <a-col :span="8">
+              <a-statistic
+                title="鏁翠綋鍋ュ悍搴�"
+                :value="healthData.overallHealth"
+                :precision="0"
+                suffix="%"
+                :value-style="{ color: healthData.healthColor }"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="棰勬祴鍓╀綑瀵垮懡"
+                :value="healthData.predictedLife"
+                suffix="澶�"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="鏁呴殰椋庨櫓绛夌骇"
+                :value="healthData.riskLevel"
+                :value-style="{ color: healthData.riskColor }"
+              />
+            </a-col>
+          </a-row>
+          <div class="mt-4">
+            <a-progress
+              :percent="healthData.overallHealth"
+              :stroke-color="healthData.healthColor"
+              :show-info="false"
+            />
+          </div>
+          <a-divider orientation="left">棰勬祴鎬х淮鎶ゅ缓璁�</a-divider>
+          <a-table
+            :columns="maintenanceColumns"
+            :data-source="maintenanceData"
+            :pagination="false"
+            size="small"
+          >
+            <template #urgency="{ text }">
+              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
+            </template>
+            <template #action="{ record }">
+              <a-button type="link" size="small" @click="handleMaintenance(record)">澶勭悊</a-button>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+
+    <!-- 瀹炴椂鏁版嵁瓒嬪娍鍥� -->
+    <a-card title="瀹炴椂鏁版嵁瓒嬪娍鍥�" class="mb-4">
+      <a-row :gutter="16">
+        <a-col :span="8">
+          <div id="spindleVibrationChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="spindleTemperatureChart" 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>
+        </a-col>
+        <a-col :span="8">
+          <div id="coolantTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+
+    </a-card>
+    <a-row :gutter="16">
+      <!-- 澶囦欢瀵垮懡棰勬祴 -->
+      <a-col :span="12">
+        <a-card title="澶囦欢瀵垮懡棰勬祴" class="mb-4">
+          <a-table
+            :columns="sparePartColumns"
+            :data-source="sparePartData"
+            :pagination="false"
+            size="small"
+          >
+            <template #status="{ text }">
+              <a-tag :color="getStatusColor(text)">{{ text }}</a-tag>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+
+      <!-- 鍘嗗彶缁存姢璁板綍 -->
+      <a-col :span="12">
+        <a-card title="鍘嗗彶缁存姢璁板綍" class="mb-4">
+          <a-timeline>
+            <a-timeline-item v-for="item in historyData" :key="item.id" :color="item.color">
+              {{ item.date }} - {{ item.type }}: {{ item.description }}
+            </a-timeline-item>
+          </a-timeline>
+        </a-card>
+      </a-col>
+    </a-row>
+
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
+import * as echarts from 'echarts';
+
+export default defineComponent({
+  name: 'CNCMachiningCenterDetail',
+  setup() {
+    // 妯℃嫙鏁版嵁
+    const deviceInfo = reactive({
+      deviceName: 'CNC鍔犲伐涓績 #CNC-001',
+      deviceType: 'CNC鍔犲伐涓績',
+      deviceId: 'CNC-2024-001',
+      installDate: '2023-08-20',
+      serviceLife: 15,
+      status: '杩愯涓�',
+      statusColor: '#52c41a'
+    });
+
+    const healthData = reactive({
+      overallHealth: 95,
+      healthColor: '#52c41a',
+      predictedLife: 4500,
+      riskLevel: '浣庨闄�',
+      riskColor: '#52c41a'
+    });
+
+    const maintenanceColumns = [
+      {
+        title: '缁存姢绫诲瀷',
+        dataIndex: 'type',
+        key: 'type'
+      },
+      {
+        title: '缁存姢鍐呭',
+        dataIndex: 'content',
+        key: 'content'
+      },
+      {
+        title: '寤鸿鏃堕棿',
+        dataIndex: 'suggestedTime',
+        key: 'suggestedTime'
+      },
+      {
+        title: '绱ф�ョ▼搴�',
+        dataIndex: 'urgency',
+        key: 'urgency',
+        slots: { customRender: 'urgency' }
+      },
+      {
+        title: '鎿嶄綔',
+        key: 'action',
+        slots: { customRender: 'action' }
+      }
+    ];
+
+    const maintenanceData = reactive([
+      {
+        key: '1',
+        type: '渚嬭淇濆吇',
+        content: '妫�鏌ヤ富杞存鼎婊戠郴缁�',
+        suggestedTime: '2024-07-15',
+        urgency: '涓瓑'
+      },
+      {
+        key: '2',
+        type: '浼烘湇绯荤粺缁存姢',
+        content: '妫�鏌杞翠己鏈嶇數鏈�',
+        suggestedTime: '2024-09-01',
+        urgency: '浣�'
+      },
+      {
+        key: '3',
+        type: '瀵艰建缁存姢',
+        content: '琛ュ厖瀵艰建娑︽粦娌�',
+        suggestedTime: '2024-08-01',
+        urgency: '楂�'
+      }
+    ]);
+
+    const getUrgencyColor = (urgency: string) => {
+      switch (urgency) {
+        case '楂�':
+          return 'red';
+        case '涓瓑':
+          return 'orange';
+        case '浣�':
+          return 'green';
+        default:
+          return 'default';
+      }
+    };
+
+    const sparePartColumns = [
+      {
+        title: '澶囦欢鍚嶇О',
+        dataIndex: 'name',
+        key: 'name'
+      },
+      {
+        title: '褰撳墠瀵垮懡',
+        dataIndex: 'currentLife',
+        key: 'currentLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '棰勬祴鍓╀綑瀵垮懡',
+        dataIndex: 'remainingLife',
+        key: 'remainingLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        key: 'status',
+        slots: { customRender: 'status' }
+      }
+    ];
+
+    const sparePartData = reactive([
+      {
+        key: '1',
+        name: '涓昏酱杞存壙',
+        currentLife: 8000,
+        remainingLife: 500,
+        status: '棰勮'
+      },
+      {
+        key: '2',
+        name: 'X杞翠笣鏉�',
+        currentLife: 12000,
+        remainingLife: 2000,
+        status: '鑹ソ'
+      },
+      {
+        key: '3',
+        name: '娑插帇娌�',
+        currentLife: 3000,
+        remainingLife: 200,
+        status: '棰勮'
+      }
+    ]);
+
+    const historyData = reactive([
+      {
+        id: '1',
+        date: '2024-05-20',
+        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'
+      }
+    ]);
+
+    const getStatusColor = (status: string) => {
+      switch (status) {
+        case '鑹ソ':
+          return '#52c41a';
+        case '棰勮':
+          return '#faad14';
+        case '鍗遍櫓':
+          return '#f5222d';
+        default:
+          return '#d9d9d9';
+      }
+    };
+
+    const handleMaintenance = (record: any) => {
+      console.log('澶勭悊缁存姢寤鸿:', record);
+      // 瀹為檯椤圭洰涓繖閲屼細璋冪敤API澶勭悊缁存姢寤鸿
+    };
+
+    return {
+      deviceInfo,
+      healthData,
+      maintenanceColumns,
+      maintenanceData,
+      sparePartColumns,
+      sparePartData,
+      historyData,
+      getStatusColor,
+      getUrgencyColor,
+      handleMaintenance
+    };
+  },
+
+  mounted() {
+    // 鍒濆鍖栧浘琛�
+    const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
+      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
+        });
+        if (chartData.length > 60) {
+          chartData.shift();
+        }
+
+        const option = {
+          title: {
+            text: title,
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis',
+            formatter: (params) => {
+              return `${params[0].axisValueLabel}<br/>${params[0].marker} ${params[0].seriesName}: ${params[0].data}${unit}`;
+            }
+          },
+          grid: {
+            left: '8%', // 澧炲姞宸︿晶杈硅窛
+            right: '5%',
+            bottom: '10%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: chartData.map(item => item.time)
+          },
+          yAxis: {
+            type: 'value',
+            axisLabel: {
+              formatter: (value) => `${value}${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)'
+                  }
+                ])
+              },
+            }
+          ]
+        };
+        chart.setOption(option);
+      };
+      
+      // 鐢熸垚鍒濆鏁版嵁鐐癸紙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({
+          time,
+          value: newValue
+        });
+      }
+      
+      // 鍒濆娓叉煋
+      updateChart();
+      
+      // 姣�5绉掓洿鏂颁竴娆℃暟鎹�
+      const intervalId = setInterval(updateChart, 5000);
+      
+      window.addEventListener('resize', () => {
+        chart.resize();
+      });
+            onUnmounted(() => {
+        clearInterval(intervalId);
+      });
+
+    };
+
+
+
+
+    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);
+  }
+
+});
+</script>
+
+<style scoped>
+.device-detail-container {
+  padding: 16px;
+  background: #f0f2f5;
+}
+
+.mt-4 {
+  margin-top: 16px;
+}
+
+.mb-4 {
+  margin-bottom: 16px;
+}
+</style>
\ No newline at end of file
diff --git a/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/device-detail.vue b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/device-detail.vue
new file mode 100644
index 0000000..70a9732
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/device-detail.vue
@@ -0,0 +1,439 @@
+<template>
+  <div class="device-detail-container">
+    <a-page-header
+      title="璁惧棰勬祴鎬х淮鎶よ鎯�"
+      :sub-title="deviceInfo.deviceName"
+      @back="() => $router.go(-1)"
+    />
+
+    <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-card>
+      </a-col>
+
+      <!-- 璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿 -->
+      <a-col :span="16">
+        <a-card title="璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿" class="mb-4" :style="{ height: '440px' }">
+          <a-row :gutter="16">
+            <a-col :span="8">
+              <a-statistic
+                title="鏁翠綋鍋ュ悍搴�"
+                :value="healthData.overallHealth"
+                :precision="0"
+                suffix="%"
+                :value-style="{ color: healthData.healthColor }"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="棰勬祴鍓╀綑瀵垮懡"
+                :value="healthData.predictedLife"
+                suffix="澶�"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="鏁呴殰椋庨櫓绛夌骇"
+                :value="healthData.riskLevel"
+                :value-style="{ color: healthData.riskColor }"
+              />
+            </a-col>
+          </a-row>
+          <div class="mt-4">
+            <a-progress
+              :percent="healthData.overallHealth"
+              :stroke-color="healthData.healthColor"
+              :show-info="false"
+            />
+          </div>
+          <a-divider orientation="left">棰勬祴鎬х淮鎶ゅ缓璁�</a-divider>
+          <a-table
+            :columns="maintenanceColumns"
+            :data-source="maintenanceData"
+            :pagination="false"
+            size="small"
+          >
+            <template #urgency="{ text }">
+              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
+            </template>
+            <template #action="{ record }">
+              <a-button type="link" size="small" @click="handleMaintenance(record)">澶勭悊</a-button>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+
+    <!-- 瀹炴椂鏁版嵁瓒嬪娍鍥� -->
+    <a-card title="瀹炴椂鏁版嵁瓒嬪娍鍥�" class="mb-4">
+      <a-row :gutter="16">
+        <a-col :span="8">
+          <div id="temperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="vibrationChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="currentChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+    </a-card>
+    <a-row :gutter="16">
+      <!-- 澶囦欢瀵垮懡棰勬祴 -->
+      <a-col :span="12">
+        <a-card title="澶囦欢瀵垮懡棰勬祴" class="mb-4">
+          <a-table
+            :columns="sparePartColumns"
+            :data-source="sparePartData"
+            :pagination="false"
+            size="small"
+          >
+            <template #status="{ text }">
+              <a-tag :color="getStatusColor(text)">{{ text }}</a-tag>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+
+      <!-- 鍘嗗彶缁存姢璁板綍 -->
+      <a-col :span="12">
+        <a-card title="鍘嗗彶缁存姢璁板綍" class="mb-4">
+          <a-timeline>
+            <a-timeline-item v-for="item in historyData" :key="item.id" :color="item.color">
+              {{ item.date }} - {{ item.type }}: {{ item.description }}
+            </a-timeline-item>
+          </a-timeline>
+        </a-card>
+      </a-col>
+    </a-row>
+
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
+import * as echarts from 'echarts';
+
+export default defineComponent({
+  name: 'DeviceDetail',
+  setup() {
+    // 妯℃嫙鏁版嵁
+    const deviceInfo = reactive({
+      deviceName: 'CNC鍔犲伐涓績',
+      deviceType: '鏁版帶鏈哄簥',
+      deviceId: 'CNC-2023-001',
+      installDate: '2023-01-15',
+      serviceLife: 10,
+      status: '杩愯涓�',
+      statusColor: '#52c41a'
+    });
+
+    const healthData = reactive({
+      overallHealth: 85,
+      healthColor: '#52c41a',
+      predictedLife: 1825,
+      riskLevel: '涓闄�',
+      riskColor: '#faad14'
+    });
+
+    const maintenanceColumns = [
+      {
+        title: '缁存姢绫诲瀷',
+        dataIndex: 'type',
+        key: 'type'
+      },
+      {
+        title: '缁存姢鍐呭',
+        dataIndex: 'content',
+        key: 'content'
+      },
+      {
+        title: '寤鸿鏃堕棿',
+        dataIndex: 'suggestedTime',
+        key: 'suggestedTime'
+      },
+      {
+        title: '绱ф�ョ▼搴�',
+        dataIndex: 'urgency',
+        key: 'urgency'
+      },
+      {
+        title: '鎿嶄綔',
+        key: 'action',
+        slots: { customRender: 'action' }
+      },
+      {
+        title: '绱ф�ョ▼搴�',
+        dataIndex: 'urgency',
+        key: 'urgency',
+        slots: { customRender: 'urgency' }
+      },
+      {
+        title: '鎿嶄綔',
+        key: 'action',
+        slots: { customRender: 'action' }
+      }
+    ];
+
+    const maintenanceData = reactive([
+      {
+        key: '1',
+        type: '娑︽粦淇濆吇',
+        content: '涓昏酱娑︽粦绯荤粺闇�瑕佹洿鎹㈡鼎婊戞补',
+        suggestedTime: '2024-03-15',
+        urgency: '涓瓑'
+      },
+      {
+        key: '2',
+        type: '鏍″噯妫�鏌�',
+        content: 'X杞村杞ㄩ渶瑕侀噸鏂版牎鍑�',
+        suggestedTime: '2024-04-01',
+        urgency: '楂�'
+      }
+    ]);
+
+    const getUrgencyColor = (urgency: string) => {
+      switch (urgency) {
+        case '楂�':
+          return 'red';
+        case '涓瓑':
+          return 'orange';
+        case '浣�':
+          return 'green';
+        default:
+          return 'default';
+      }
+    };
+
+    const sparePartColumns = [
+      {
+        title: '澶囦欢鍚嶇О',
+        dataIndex: 'name',
+        key: 'name'
+      },
+      {
+        title: '褰撳墠瀵垮懡',
+        dataIndex: 'currentLife',
+        key: 'currentLife',
+        customRender: ({ text }: { text: number }) => `${text}澶ー
+      },
+      {
+        title: '棰勬祴鍓╀綑瀵垮懡',
+        dataIndex: 'remainingLife',
+        key: 'remainingLife',
+        customRender: ({ text }: { text: number }) => `${text}澶ー
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        key: 'status',
+        slots: { customRender: 'status' }
+      }
+    ];
+
+    const sparePartData = reactive([
+      {
+        key: '1',
+        name: '涓昏酱杞存壙',
+        currentLife: 365,
+        remainingLife: 120,
+        status: '鑹ソ'
+      },
+      {
+        key: '2',
+        name: 'X杞村杞�',
+        currentLife: 730,
+        remainingLife: 30,
+        status: '棰勮'
+      },
+      {
+        key: '3',
+        name: '鍒�鍏峰す澶�',
+        currentLife: 180,
+        remainingLife: 90,
+        status: '鑹ソ'
+      }
+    ]);
+
+    const historyData = reactive([
+      {
+        id: '1',
+        date: '2024-01-10',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚瀛e害淇濆吇锛屾洿鎹㈡鼎婊戞补鍜岃繃婊ゅ櫒',
+        color: 'green'
+      },
+      {
+        id: '2',
+        date: '2023-10-15',
+        type: '鏁呴殰缁翠慨',
+        description: '淇涓昏酱鐢垫満杩囩儹闂',
+        color: 'red'
+      },
+      {
+        id: '3',
+        date: '2023-07-20',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚鍗婂勾淇濆吇锛屾牎鍑嗗悇杞寸簿搴�',
+        color: 'green'
+      }
+    ]);
+
+    const getStatusColor = (status: string) => {
+      switch (status) {
+        case '鑹ソ':
+          return '#52c41a';
+        case '棰勮':
+          return '#faad14';
+        case '鍗遍櫓':
+          return '#f5222d';
+        default:
+          return '#d9d9d9';
+      }
+    };
+
+    const handleMaintenance = (record: any) => {
+      console.log('澶勭悊缁存姢寤鸿:', record);
+      // 瀹為檯椤圭洰涓繖閲屼細璋冪敤API澶勭悊缁存姢寤鸿
+    };
+
+    return {
+      deviceInfo,
+      healthData,
+      maintenanceColumns,
+      maintenanceData,
+      sparePartColumns,
+      sparePartData,
+      historyData,
+      getStatusColor,
+      getUrgencyColor,
+      handleMaintenance
+    };
+  },
+
+  mounted() {
+    // 鍒濆鍖栧浘琛�
+    const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
+      const chart = echarts.init(document.getElementById(chartId));
+
+      // 棰勭敓鎴�60涓暟鎹偣
+      for (let i = 0; i < 60; i++) {
+        const now = new Date(Date.now() - (60 - 1 - i) * 5000); // 5绉掗棿闅�
+        const value = +(Math.random() * fluctuation + baseValue - fluctuation / 2).toFixed(2);
+        chartData.push({
+          time: `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`,
+          value: value
+        });
+      }
+      
+      const updateChart = () => {
+        // 鐢熸垚鏂扮殑鏁版嵁鐐�
+        const now = new Date();
+        const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
+        const newValue = +(Math.random() * fluctuation + baseValue - fluctuation / 2).toFixed(2);
+        
+        // 娣诲姞鏂版暟鎹偣锛屾渶澶氫繚鐣�60涓偣锛�5鍒嗛挓鏁版嵁锛�
+        chartData.push({
+          time,
+          value: newValue
+        });
+        if (chartData.length > 60) {
+          chartData.shift();
+        }
+        
+        const option = {
+          title: {
+            text: title,
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis',
+            formatter: (params: any) => {
+              return `${params[0].axisValueLabel}<br/>${params[0].marker} ${params[0].seriesName}: ${params[0].data}${unit}`;
+            }
+          },
+          xAxis: {
+            type: 'category',
+            data: chartData.map(item => item.time)
+          },
+          yAxis: {
+            type: 'value',
+            axisLabel: {
+              formatter: (value: number) => {
+                return `${value}${unit}`;
+              }
+            }
+          },
+          series: [
+            {
+              data: chartData.map(item => parseFloat(item.value)),
+              type: 'line',
+              smooth: true,
+              lineStyle: {
+                width: 2,
+                color: chartId === 'temperatureChart' ? '#5470C6' : chartId === 'vibrationChart' ? '#91CC75' : '#FAC858' // 鏍规嵁鍥捐〃ID璁剧疆棰滆壊
+              },
+              areaStyle: {
+                opacity: 0.8,
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                  {
+                    offset: 0,
+                    color: chartId === 'temperatureChart' ? 'rgba(84,112,198,0.3)' : chartId === 'vibrationChart' ? 'rgba(145,204,117,0.3)' : 'rgba(250,200,88,0.3)'
+                  },
+                  {
+                    offset: 1,
+                    color: chartId === 'temperatureChart' ? 'rgba(84,112,198,0)' : chartId === 'vibrationChart' ? 'rgba(145,204,117,0)' : 'rgba(250,200,88,0)'
+                  }
+                ])
+              },
+            }
+          ]
+        };
+        chart.setOption(option);
+      };
+      
+      // 鍒濆娓叉煋
+      updateChart();
+      
+      // 姣�5绉掓洿鏂颁竴娆℃暟鎹�
+      const intervalId = setInterval(updateChart, 5000);
+      
+      window.addEventListener('resize', () => {
+        chart.resize();
+      });
+            onUnmounted(() => {
+        clearInterval(intervalId);
+      });
+
+    };
+
+    const temperatureData: any[] = reactive([]);
+    const vibrationData: any[] = reactive([]);
+    const currentData: any[] = reactive([]);
+
+    initChart('temperatureChart', '娓╁害瓒嬪娍', temperatureData, '掳C', 60, 5);
+    initChart('vibrationChart', '鎸姩瓒嬪娍', vibrationData, 'mm/s', 10, 2);
+    initChart('currentChart', '鐢垫祦瓒嬪娍', currentData, 'A', 50, 10);
+  }
+  
+});
+</script>
+
+<style scoped>
+.device-detail-container {
+  padding: 16px;
+  background: #f0f2f5;
+}
+</style>
\ No newline at end of file
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
new file mode 100644
index 0000000..4a04417
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue
@@ -0,0 +1,409 @@
+<template>
+  <Page :auto-content-height="true" :padding="false" class="p-0" content-class="flex flex-col w-full gap-4">
+    <div class="p-5">
+
+      <!-- 璁惧鍋ュ悍鐘舵�佸彲瑙嗗寲 -->
+      <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
+        <Card title="璁惧鍋ュ悍搴﹀垎甯�" >
+          <!-- 杩欓噷灏嗘斁缃仴搴峰害鍒嗗竷鍥捐〃 -->
+          <div ref="chartRef" class="h-64 w-full"></div>
+        </Card>
+        <Card title="鍏抽敭鎸囨爣" >
+          <div class="grid grid-cols-2 gap-2">
+            <div class="p-2 bg-blue-50 rounded">
+              <p class="text-sm text-gray-600">鍋ュ悍璁惧</p>
+              <p class="text-xl font-bold">85%</p>
+            </div>
+            <div class="p-2 bg-yellow-50 rounded">
+              <p class="text-sm text-gray-600">棰勮璁惧</p>
+              <p class="text-xl font-bold">12%</p>
+            </div>
+            <div class="p-2 bg-red-50 rounded">
+              <p class="text-sm text-gray-600">鏁呴殰璁惧</p>
+              <p class="text-xl font-bold">3%</p>
+            </div>
+            <div class="p-2 bg-green-50 rounded">
+              <p class="text-sm text-gray-600">缁存姢瀹屾垚</p>
+              <p class="text-xl font-bold">92%</p>
+            </div>
+            <div class="p-2 bg-blue-50 rounded">
+              <p class="text-sm text-gray-600">寰呭鐞嗗伐鍗�</p>
+              <p class="text-xl font-bold">{{ healthData.pendingWorkOrders }}</p>
+            </div>
+            <div class="p-2 bg-yellow-50 rounded">
+              <p class="text-sm text-gray-600">澶囦欢搴撳瓨棰勮</p>
+              <p class="text-xl font-bold">{{ healthData.sparePartWarnings }}</p>
+            </div>
+          </div>
+        </Card>
+      </div>
+
+      <!-- 鏁呴殰棰勬祴涓庨璀� -->
+      <Card title="鏁呴殰棰勬祴涓庨璀�" class="mb-6">
+        <div class="grid grid-cols-1 gap-4">
+
+            <!-- 杩欓噷灏嗘斁缃璀﹁〃鏍� -->
+            <a-table :columns="warningColumns" :data-source="warningData" :pagination="false" class="w-full">
+              <template #bodyCell="{ column, record }">
+                <template v-if="column.key === 'status'">
+                  <a-tag :color="getStatusColor(record.status)">
+                    {{ record.status }}
+                  </a-tag>
+                </template>
+                <template v-else-if="column.key === 'action'">
+                  <a-button type="link" @click="handleDetail(record)">璇︽儏</a-button>
+                  <a-button type="link" @click="generateWorkOrder(record)" :disabled="record.maintenanceSuggestion === '鏆傛棤寤鸿'">鐢熸垚宸ュ崟</a-button>
+                </template>
+              </template>
+            </a-table>
+          </div>
+
+      </Card>
+
+      <!-- 澶囦欢淇℃伅 -->
+      <div class="grid grid-cols-2 gap-4 mb-6">
+        <!-- 澶囦欢瀵垮懡棰勬祴 -->
+        <Card title="澶囦欢瀵垮懡棰勬祴">
+          <a-table :columns="lifePredictionColumns" :data-source="lifePredictionData" :pagination="false" class="w-full">
+            <template #bodyCell="{ column, record }">
+              <template v-if="column.key === 'lifeStatus'">
+                <a-tag :color="getLifeStatusColor(record.remainingDays)">
+                  {{ getLifeStatus(record.remainingDays) }}
+                </a-tag>
+              </template>
+              <template v-else-if="column.key === 'action'">
+                <a-button type="link" @click="showLifePredictionDetail(record)">璇︽儏</a-button>
+              </template>
+            </template>
+          </a-table>
+        </Card>
+
+        <!-- 澶囦欢搴撳瓨涓庨璀� -->
+        <Card title="澶囦欢搴撳瓨涓庨璀�">
+          <a-table :columns="sparePartColumns" :data-source="sparePartData" :pagination="false" class="w-full">
+            <template #bodyCell="{ column, record }">
+              <template v-if="column.key === 'stockStatus'">
+                <a-tag :color="getStockStatusColor(record.currentStock, record.safetyStock)">
+                  {{ getStockStatus(record.currentStock, record.safetyStock) }}
+                </a-tag>
+              </template>
+              <template v-else-if="column.key === 'action'">
+                <a-button type="link" @click="showSparePartDetail(record)">璇︽儏</a-button>
+              </template>
+            </template>
+          </a-table>
+        </Card>
+      </div>
+
+
+    </div>
+  </Page>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref } from 'vue';
+import { Page } from '@vben/common-ui';
+import { Card, Table, Tag, Button, Form, Input, Textarea, Select, message } from 'ant-design-vue';
+import * as echarts from 'echarts';
+
+const chartRef = ref<HTMLElement | null>(null);
+
+const healthData = {
+  healthy: 85,
+  warning: 12,
+  critical: 3,
+  maintained: 92,
+  pendingWorkOrders: 5, // 妯℃嫙寰呭鐞嗗伐鍗曟暟
+  sparePartWarnings: 2, // 妯℃嫙澶囦欢搴撳瓨棰勮鏁�
+};
+
+// 楂橀闄╄澶囬璀︽暟鎹�
+const warningColumns = [
+  { title: '璁惧鍚嶇О', dataIndex: 'name', key: 'name' },
+
+  { title: '鍏抽敭閮ㄤ欢', dataIndex: 'component', key: 'component' },
+  { title: '椋庨櫓鎸囨爣', dataIndex: 'indicator', key: 'indicator' },
+  { title: '褰撳墠鍊�', dataIndex: 'value', key: 'value' },
+  { title: '闃堝��', dataIndex: 'threshold', key: 'threshold' },
+  { title: '鐘舵��', dataIndex: 'status', key: 'status' },
+  { title: '缁存姢寤鸿', dataIndex: 'maintenanceSuggestion', key: 'maintenanceSuggestion' },
+  { title: '鎿嶄綔', key: 'action' },
+];
+
+// 妯℃嫙楂橀闄╄澶囨暟鎹�
+const warningData = ref([
+  {
+    key: '1',
+    name: 'SMT璐寸墖鏈�',
+    type: 'SMT鏈哄櫒',
+    component: '浼犻�佸甫',
+    indicator: '鎸姩骞呭害',
+    value: 0.8,
+    threshold: 0.5,
+    status: '楂橀闄�',
+    maintenanceSuggestion: '寤鸿鏇存崲浼犻�佸甫杞存壙',
+    maintenanceType: '棰勯槻鎬х淮鎶�',
+  },
+  {
+    key: '2',
+    name: 'CNC鍔犲伐涓績',
+    type: 'CNC',
+    component: '涓昏酱',
+    indicator: '娓╁害',
+    value: 85,
+    threshold: 80,
+    status: '涓闄�',
+    maintenanceSuggestion: '寤鸿瀵逛富杞磋繘琛屾鼎婊戜繚鍏�',
+    maintenanceType: '娑︽粦缁存姢',
+  },
+  {
+    key: '3',
+    name: '娉ㄥ鏈�',
+    type: '娉ㄥ璁惧',
+    component: '娑插帇绯荤粺',
+    indicator: '鍘嬪姏',
+    value: 120,
+    threshold: 150,
+    status: '浣庨闄�',
+    maintenanceSuggestion: '寤鸿妫�鏌ユ恫鍘嬬郴缁熷瘑灏佷欢',
+    maintenanceType: '妫�鏌ョ淮鎶�',
+  },
+  {
+    key: '4',
+    name: '绌哄帇鏈�',
+    type: '绌烘皵鍘嬬缉鏈�',
+    component: '鐢垫満',
+    indicator: '鐢垫祦',
+    value: 49,
+    threshold: 50,
+    status: '浣庨闄�',
+    maintenanceSuggestion: '鏆傛棤寤鸿',
+    maintenanceType: '鏃�',
+  },
+]);
+
+// 澶囦欢搴撳瓨鏁版嵁
+const sparePartColumns = [
+  { title: '澶囦欢鍚嶇О', dataIndex: 'name', key: 'name' },
+  { title: '褰撳墠搴撳瓨', dataIndex: 'currentStock', key: 'currentStock' },
+  { title: '瀹夊叏搴撳瓨', dataIndex: 'safetyStock', key: 'safetyStock' },
+  { title: '棰勬祴闇�姹�', dataIndex: 'predictedDemand', key: 'predictedDemand' },
+  { title: '搴撳瓨鐘舵��', dataIndex: 'stockStatus', key: 'stockStatus' },
+];
+
+// 妯℃嫙澶囦欢鏁版嵁
+const sparePartData = ref([
+  {
+    key: '1',
+    name: '浼犻�佸甫杞存壙',
+    currentStock: 10,
+    safetyStock: 5,
+    predictedDemand: 3,
+  },
+  {
+    key: '2',
+    name: '涓昏酱娑︽粦娌�',
+    currentStock: 2,
+    safetyStock: 3,
+    predictedDemand: 1,
+  },
+  {
+    key: '3',
+    name: '娑插帇绯荤粺瀵嗗皝浠�',
+    currentStock: 20,
+    safetyStock: 10,
+    predictedDemand: 5,
+  },
+  {
+    key: '4',
+    name: '鐢垫満纰冲埛',
+    currentStock: 8,
+    safetyStock: 10,
+    predictedDemand: 2,
+  },
+]);
+const getStatusColor = (status) => {
+  switch (status) {
+    case '楂橀闄�': return 'red';
+    case '涓闄�': return 'orange';
+    case '浣庨闄�': return 'yellow';
+    default: return 'green';
+  }
+};
+
+
+
+// 宸ュ崟琛ㄥ崟鏁版嵁
+const workOrderForm = ref({
+  type: '',
+  equipment: '',
+  content: '',
+  priority: 'medium',
+});
+
+const selectedMaintenance = ref(null);
+
+const lifePredictionColumns = [
+  { title: '璁惧鍚嶇О', dataIndex: 'deviceName', key: 'deviceName' },
+  { title: '閮ㄤ欢鍚嶇О', dataIndex: 'componentName', key: 'componentName' },
+  { title: '澶囦欢鍚嶇О', dataIndex: 'name', key: 'name' },
+  { title: '棰勬祴瀵垮懡 (澶�)', dataIndex: 'predictedLife', key: 'predictedLife' },
+  { title: '鍓╀綑瀵垮懡 (澶�)', dataIndex: 'remainingDays', key: 'remainingDays' },
+  { title: '鐘舵��', dataIndex: 'lifeStatus', key: 'lifeStatus' },
+  { title: '鎿嶄綔', dataIndex: 'action', key: 'action' },
+];
+
+const lifePredictionData = ref([
+  { key: '1', deviceName: 'SMT璐寸墖鏈�', componentName: '浼犻�佸甫', name: '杞存壙A', predictedLife: 365, remainingDays: 120 },
+  { key: '2', deviceName: 'CNC鍔犲伐涓績', componentName: '涓昏酱', name: '榻胯疆B', predictedLife: 730, remainingDays: 30 },
+  { key: '3', deviceName: '娉ㄥ鏈�', componentName: '娑插帇绯荤粺', name: '婊よ姱C', predictedLife: 180, remainingDays: 90 },
+  { key: '4', deviceName: '绌哄帇鏈�', componentName: '鐢垫満', name: '浼犳劅鍣―', predictedLife: 500, remainingDays: 10 },
+  { key: '5', deviceName: '鐒婃帴鏈哄櫒浜�', componentName: '鐒婃灙', name: '鐒婂槾E', predictedLife: 240, remainingDays: 60 }
+]);
+
+const getLifeStatus = (remainingDays) => {
+  if (remainingDays <= 30) {
+    return '鍗冲皢鍒版湡';
+  } else if (remainingDays <= 90) {
+    return '涓湡棰勮';
+  } else {
+    return '瀵垮懡鍏呰冻';
+  }
+};
+
+const getLifeStatusColor = (remainingDays) => {
+  if (remainingDays <= 30) {
+    return 'red';
+  } else if (remainingDays <= 90) {
+    return 'orange';
+  } else {
+    return 'green';
+  }
+};
+
+const showLifePredictionDetail = (record) => {
+  message.info(`澶囦欢鍚嶇О: ${record.name}, 棰勬祴瀵垮懡: ${record.predictedLife}澶�, 鍓╀綑瀵垮懡: ${record.remainingDays}澶ー);
+};
+
+
+
+const getStockStatus = (currentStock, safetyStock) => {
+  if (currentStock <= safetyStock) {
+    return '搴撳瓨棰勮';
+  } else {
+    return '搴撳瓨鍏呰冻';
+  }
+};
+
+const getStockStatusColor = (currentStock, safetyStock) => {
+  if (currentStock <= safetyStock) {
+    return 'red';
+  } else {
+    return 'green';
+  }
+};
+
+const showSparePartDetail = (record) => {
+  message.info(`澶囦欢鍚嶇О: ${record.name}, 褰撳墠搴撳瓨: ${record.currentStock}, 瀹夊叏搴撳瓨: ${record.safetyStock}, 棰勬祴闇�姹�: ${record.predictedDemand}`);
+};
+
+const generateWorkOrder = (record) => {
+  selectedMaintenance.value = record;
+  workOrderForm.value = {
+    type: record.maintenanceType,
+    equipment: record.name,
+    content: record.maintenanceSuggestion,
+    priority: 'medium',
+  };
+};
+
+const submitWorkOrder = () => {
+  console.log('鎻愪氦宸ュ崟:', workOrderForm.value);
+  // 杩欓噷鍙互娣诲姞宸ュ崟鎻愪氦閫昏緫
+  message.success('宸ュ崟鎻愪氦鎴愬姛');
+  selectedMaintenance.value = null;
+  workOrderForm.value = {
+    type: '',
+    equipment: '',
+    content: '',
+    priority: 'medium',
+  };
+};
+
+import { useRouter } from 'vue-router';
+
+const router = useRouter();
+
+const handleDetail = (record) => {
+  // 鏍规嵁璁惧鍚嶇О涓嶅悓璺宠浆涓嶅悓鐨勮鎯呴〉闈�
+  if (record.name === 'SMT璐寸墖鏈�') {
+    console.log('璁惧ID111:', record.name)
+    router.push({ path: '/predictive/smt-detail', query: { deviceId: record.key } });
+  } else if (record.name === 'CNC鍔犲伐涓績') {
+    router.push({ path: '/predictive/predictive-detail', query: { deviceId: record.key } });
+  } else if (record.name === '娉ㄥ鏈�') {
+    router.push({ path: '/predictive/injection-detail', query: { deviceId: record.key } });
+  } else {
+    router.push({ path: '/predictive/air-compressor-detail', query: { deviceId: record.key } });
+  }
+};
+
+onMounted(() => {
+  if (chartRef.value) {
+    const myChart = echarts.init(chartRef.value);
+    const option = {
+      tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+          type: 'shadow'
+        }
+      },
+      xAxis: {
+        type: 'category',
+        data: ['90%-100%', '80%-90%', '70%-80%', '60%-70%', '50%-60%', '40%-50%', '30%-40%', '20%-30%', '10%-20%', '0%-10%'],
+        axisLabel: {
+          rotate: 45
+        }
+      },
+      yAxis: {
+        type: 'value',
+        name: '璁惧鏁伴噺',
+        minInterval: 1
+      },
+      series: [
+        {
+          name: '璁惧鏁伴噺',
+          type: 'bar',
+          barWidth: '60%',
+          data: [
+            { value: 15, itemStyle: { color: '#52c41a' } },
+            { value: 20, itemStyle: { color: '#52c41a' } },
+            { value: 25, itemStyle: { color: '#faad14' } },
+            { value: 15, itemStyle: { color: '#faad14' } },
+            { value: 10, itemStyle: { color: '#faad14' } },
+            { value: 5, itemStyle: { color: '#ff4d4f' } },
+            { value: 5, itemStyle: { color: '#ff4d4f' } },
+            { value: 3, itemStyle: { color: '#ff4d4f' } },
+            { value: 1, itemStyle: { color: '#ff4d4f' } },
+            { value: 1, itemStyle: { color: '#ff4d4f' } }
+          ],
+          label: {
+            show: true,
+            position: 'top'
+          }
+        }
+      ]
+    };
+    myChart.setOption(option);
+
+    // 鍝嶅簲寮忚皟鏁村浘琛ㄥぇ灏�
+    window.addEventListener('resize', () => {
+      myChart.resize();
+    });
+  }
+});
+</script>
+
+<style scoped>
+/* 鍙互鍦ㄨ繖閲屾坊鍔犵粍浠舵牱寮� */
+</style>
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
new file mode 100644
index 0000000..61b3576
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue
@@ -0,0 +1,549 @@
+<script lang="ts">
+import { defineComponent, onUnmounted, reactive } from 'vue';
+
+import * as echarts from 'echarts';
+
+export default defineComponent({
+  name: 'InjectionMoldingMachineDetail',
+  setup() {
+    // 妯℃嫙鏁版嵁
+    const deviceInfo = reactive({
+      deviceName: '娉ㄥ鏈� #IM-001',
+      deviceType: '娉ㄥ鏈�',
+      deviceId: 'IM-2024-001',
+      installDate: '2023-08-20',
+      serviceLife: 15,
+      status: '杩愯涓�',
+      statusColor: '#52c41a'
+    });
+
+    const healthData = reactive({
+      overallHealth: 88,
+      healthColor: '#faad14',
+      predictedLife: 1500,
+      riskLevel: '涓闄�',
+      riskColor: '#faad14'
+    });
+
+    const maintenanceColumns = [
+      {
+        title: '缁存姢绫诲瀷',
+        dataIndex: 'type',
+        key: 'type'
+      },
+      {
+        title: '缁存姢鍐呭',
+        dataIndex: 'content',
+        key: 'content'
+      },
+      {
+        title: '寤鸿鏃堕棿',
+        dataIndex: 'suggestedTime',
+        key: 'suggestedTime'
+      },
+      {
+        title: '绱ф�ョ▼搴�',
+        dataIndex: 'urgency',
+        key: 'urgency',
+        slots: { customRender: 'urgency' }
+      },
+      {
+        title: '鎿嶄綔',
+        key: 'action',
+        slots: { customRender: 'action' }
+      }
+    ];
+
+    const maintenanceData = reactive([
+      {
+        key: '1',
+        type: '渚嬭淇濆吇',
+        content: '妫�鏌ユ恫鍘嬫补姹℃煋搴�',
+        suggestedTime: '2024-07-15',
+        urgency: '涓瓑'
+      },
+      {
+        key: '2',
+        type: '鏁呴殰棰勮',
+        content: '涓荤數鏈鸿酱鎵跨(鎹熼璀�',
+        suggestedTime: '2024-08-01',
+        urgency: '楂�'
+      },
+      {
+        key: '3',
+        type: '鍐峰嵈绯荤粺缁存姢',
+        content: '妫�鏌ュ喎鍗存按娴侀噺',
+        suggestedTime: '2024-07-01',
+        urgency: '浣�'
+      }
+    ]);
+
+    const getUrgencyColor = (urgency: string) => {
+      switch (urgency) {
+        case '涓瓑': {
+          return 'orange';
+        }
+        case '浣�': {
+          return 'green';
+        }
+        case '楂�': {
+          return 'red';
+        }
+        default: {
+          return 'default';
+        }
+      }
+    };
+
+    const sparePartColumns = [
+      {
+        title: '澶囦欢鍚嶇О',
+        dataIndex: 'name',
+        key: 'name'
+      },
+      {
+        title: '褰撳墠瀵垮懡',
+        dataIndex: 'currentLife',
+        key: 'currentLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '棰勬祴鍓╀綑瀵垮懡',
+        dataIndex: 'remainingLife',
+        key: 'remainingLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        key: 'status',
+        slots: { customRender: 'status' }
+      }
+    ];
+
+    const sparePartData = reactive([
+      {
+        key: '1',
+        name: '娑插帇娉�',
+        currentLife: 18_500,
+        remainingLife: 1500,
+        status: '棰勮'
+      },
+      {
+        key: '2',
+        name: '鍔犵儹鍦�',
+        currentLife: 12_000,
+        remainingLife: 3000,
+        status: '鑹ソ'
+      },
+      {
+        key: '3',
+        name: '铻烘潌鏂欑瓛',
+        currentLife: 25_000,
+        remainingLife: 5000,
+        status: '鑹ソ'
+      }
+    ]);
+
+    const historyData = reactive([
+      {
+        id: '1',
+        date: '2023-10-20',
+        type: '渚嬭淇濆吇',
+        description: '鏇存崲娑插帇娌规护鑺�',
+        color: 'green'
+      },
+      {
+        id: '2',
+        date: '2023-08-15',
+        type: '鏁呴殰缁翠慨',
+        description: '娉ㄥ皠鍗曞厓鍗℃粸锛屾竻鐞嗗紓鐗�',
+        color: 'red'
+      },
+      {
+        id: '3',
+        date: '2023-06-01',
+        type: '骞村害淇濆吇',
+        description: '鍏ㄩ潰妫�鏌ヨ澶囪繍琛岀姸鎬�',
+        color: 'blue'
+      }
+    ]);
+
+    const getStatusColor = (status: string) => {
+      switch (status) {
+        case '鍗遍櫓': {
+          return '#f5222d';
+        }
+        case '鑹ソ': {
+          return '#52c41a';
+        }
+        case '棰勮': {
+          return '#faad14';
+        }
+        default: {
+          return '#d9d9d9';
+        }
+      }
+    };
+
+    const handleMaintenance = (record: any) => {
+      console.log('澶勭悊缁存姢寤鸿:', record);
+      // 瀹為檯椤圭洰涓繖閲屼細璋冪敤API澶勭悊缁存姢寤鸿
+    };
+
+    return {
+      deviceInfo,
+      healthData,
+      maintenanceColumns,
+      maintenanceData,
+      sparePartColumns,
+      sparePartData,
+      historyData,
+      getStatusColor,
+      getUrgencyColor,
+      handleMaintenance
+    };
+  },
+
+  mounted() {
+    // 鍒濆鍖栧浘琛�
+    const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
+      const chart = echarts.init(document.getElementById(chartId));
+
+      // 纭繚鍒濆鏁版嵁鐐硅冻澶熸樉绀轰竴涓畬鏁寸殑瓒嬪娍
+      if (chartData.length === 0) {
+        const now = new Date();
+        for (let i = 0; i < 60; i++) { // 鐢熸垚60涓偣锛屼唬琛�5鍒嗛挓鐨勬暟鎹�
+          const time = new Date(now.getTime() - (59 - i) * 5000); // 姣忎釜鐐归棿闅�5绉�
+          chartData.push({
+            time: time.toLocaleTimeString(),
+            value: (baseValue + Math.random() * fluctuation * 2 - fluctuation).toFixed(2),
+          });
+        }
+      }
+
+      const updateChart = () => {
+        // 鐢熸垚鏂扮殑鏁版嵁鐐�
+        const now = new Date();
+        const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
+        const newValue = (baseValue + Math.random() * fluctuation * 2 - fluctuation).toFixed(2);
+
+        // 娣诲姞鏂版暟鎹偣锛屾渶澶氫繚鐣�60涓偣锛�5鍒嗛挓鏁版嵁锛�
+        chartData.push({
+          time,
+          value: newValue
+        });
+        if (chartData.length > 60) {
+          chartData.shift();
+        }
+
+        const option = {
+          title: {
+            text: title,
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis',
+            formatter: (params) => {
+              return `${params[0].axisValueLabel}<br/>${params[0].marker} ${params[0].seriesName}: ${params[0].data}${unit}`;
+            }
+          },
+          grid: {
+            left: '8%', // 澧炲姞宸︿晶杈硅窛
+            right: '5%',
+            bottom: '10%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: chartData.map(item => item.time)
+          },
+          yAxis: {
+            type: 'value',
+            axisLabel: {
+              formatter: (value) => `${value}${unit}`
+            }
+          },
+          series: [
+            {
+              data: chartData.map(item => Number.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)'
+                  }
+                ])
+              },
+            }
+          ]
+        };
+        chart.setOption(option);
+      };
+
+      // 鍒濆娓叉煋
+      updateChart();
+
+      // 姣�5绉掓洿鏂颁竴娆℃暟鎹�
+      const intervalId = setInterval(updateChart, 5000);
+
+      window.addEventListener('resize', () => {
+        chart.resize();
+      });
+      onUnmounted(() => {
+        clearInterval(intervalId);
+      });
+
+    };
+
+
+    const hydraulicOilTemperatureData: any[] = [];
+    const hydraulicOilPressureData: any[] = [];
+    const mainMotorCurrentData: any[] = [];
+    const screwSpeedData: any[] = [];
+    const moldClampingForceData: any[] = [];
+    const injectionPressureData: any[] = [];
+    const injectionSpeedData: any[] = [];
+    const barrelTemperatureData: any[] = [];
+    const coolingWaterTemperatureData: any[] = [];
+    const coolingWaterFlowData: any[] = [];
+    const ejectorPositionData: any[] = [];
+    const cycleTimeData: any[] = [];
+
+    initChart('hydraulicOilTemperatureChart', '娑插帇娌规俯', hydraulicOilTemperatureData, '掳C', 50, 2);
+    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('injectionSpeedChart', '娉ㄥ皠閫熷害', injectionSpeedData, 'mm/s', 150, 10);
+    initChart('barrelTemperatureChart', '鏂欑瓛娓╁害', barrelTemperatureData, '掳C', 200, 5);
+    initChart('coolingWaterTemperatureChart', '鍐峰嵈姘存俯搴�', coolingWaterTemperatureData, '掳C', 25, 2);
+    initChart('coolingWaterFlowChart', '鍐峰嵈姘存祦閲�', coolingWaterFlowData, 'L/min', 30, 3);
+    initChart('ejectorPositionChart', '椤跺嚭浣嶇疆', ejectorPositionData, 'mm', 50, 5);
+    initChart('cycleTimeChart', '寰幆鏃堕棿', cycleTimeData, 's', 30, 2);
+  }
+});
+</script>
+
+<template>
+  <div class="device-detail-container">
+    <a-page-header
+      :sub-title="deviceInfo.deviceName"
+      title="娉ㄥ鏈洪娴嬫�х淮鎶よ鎯�"
+      @back="() => $router.go(-1)"
+    />
+
+    <a-row :gutter="16" class="mt-4">
+      <!-- 璁惧鍩烘湰淇℃伅 -->
+      <a-col :span="8">
+        <a-card :style="{ height: '440px' }" class="mb-4" title="璁惧鍩烘湰淇℃伅">
+          <a-descriptions :column="1" bordered>
+            <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-card>
+      </a-col>
+
+      <!-- 璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿 -->
+      <a-col :span="16">
+        <a-card :style="{ height: '440px' }" class="mb-4" title="璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿">
+          <a-row :gutter="16">
+            <a-col :span="8">
+              <a-statistic
+                :precision="0"
+                :value="healthData.overallHealth"
+                :value-style="{ color: healthData.healthColor }"
+                suffix="%"
+                title="鏁翠綋鍋ュ悍搴�"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                :value="healthData.predictedLife"
+                suffix="澶�"
+                title="棰勬祴鍓╀綑瀵垮懡"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                :value="healthData.riskLevel"
+                :value-style="{ color: healthData.riskColor }"
+                title="鏁呴殰椋庨櫓绛夌骇"
+              />
+            </a-col>
+          </a-row>
+          <div class="mt-4">
+            <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"
+          >
+            <template #urgency="{ text }">
+              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
+            </template>
+            <template #action="{ record }">
+              <a-button size="small" type="link" @click="handleMaintenance(record)">澶勭悊</a-button>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+
+    <!-- 瀹炴椂鏁版嵁瓒嬪娍鍥� -->
+    <a-card class="mb-4" title="瀹炴椂鏁版嵁瓒嬪娍鍥�">
+      <a-row :gutter="16">
+        <a-col :span="8">
+          <div id="hydraulicOilTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="hydraulicOilPressureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="mainMotorCurrentChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="screwSpeedChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="moldClampingForceChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="injectionPressureChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="injectionSpeedChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="barrelTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="coolingWaterTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="coolingWaterFlowChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="ejectorPositionChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="cycleTimeChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+    </a-card>
+
+    <a-row :gutter="16">
+      <!-- 澶囦欢瀵垮懡棰勬祴 -->
+      <a-col :span="12">
+        <a-card class="mb-4" title="澶囦欢瀵垮懡棰勬祴">
+          <a-table
+            :columns="sparePartColumns"
+            :data-source="sparePartData"
+            :pagination="false"
+            size="small"
+          >
+            <template #status="{ text }">
+              <a-tag :color="getStatusColor(text)">{{ text }}</a-tag>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+
+      <!-- 鍘嗗彶缁存姢璁板綍 -->
+      <a-col :span="12">
+        <a-card class="mb-4" title="鍘嗗彶缁存姢璁板綍">
+          <a-timeline>
+            <a-timeline-item v-for="item in historyData" :key="item.id" :color="item.color">
+              {{ item.date }} - {{ item.type }}: {{ item.description }}
+            </a-timeline-item>
+          </a-timeline>
+        </a-card>
+      </a-col>
+    </a-row>
+  </div>
+</template>
+
+<style scoped>
+.device-detail-container {
+  padding: 16px;
+  background: #f0f2f5;
+}
+
+.mt-4 {
+  margin-top: 16px;
+}
+
+.mb-4 {
+  margin-bottom: 16px;
+}
+</style>
+
+
+<style scoped>
+.injection-molding-machine-detail {
+  padding: 16px;
+  background-color: #f0f2f5;
+}
+
+.header-card {
+  margin-bottom: 16px;
+}
+
+.device-info h2 {
+  font-size: 24px;
+  margin-bottom: 10px;
+}
+
+.device-info p {
+  margin-bottom: 5px;
+}
+
+.health-status h3 {
+  font-size: 20px;
+  margin-bottom: 10px;
+}
+
+.ant-statistic-content {
+  font-size: 20px !important;
+}
+
+.ant-list-item-meta-title {
+  font-size: 16px;
+}
+
+.ant-list-item-meta-description {
+  font-size: 14px;
+  color: rgba(0, 0, 0, 0.65);
+}
+</style>
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
new file mode 100644
index 0000000..5d391ab
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue
@@ -0,0 +1,509 @@
+<template>
+  <div class="device-detail-container">
+    <a-page-header
+      title="SMT璐寸墖鏈洪娴嬫�х淮鎶よ鎯�"
+      :sub-title="deviceInfo.deviceName"
+      @back="() => $router.go(-1)"
+    />
+
+    <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-card>
+      </a-col>
+
+      <!-- 璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿 -->
+      <a-col :span="16">
+        <a-card title="璁惧鍋ュ悍鐘舵�佷笌缁存姢寤鸿" class="mb-4" :style="{ height: '440px' }">
+          <a-row :gutter="16">
+            <a-col :span="8">
+              <a-statistic
+                title="鏁翠綋鍋ュ悍搴�"
+                :value="healthData.overallHealth"
+                :precision="0"
+                suffix="%"
+                :value-style="{ color: healthData.healthColor }"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="棰勬祴鍓╀綑瀵垮懡"
+                :value="healthData.predictedLife"
+                suffix="澶�"
+              />
+            </a-col>
+            <a-col :span="8">
+              <a-statistic
+                title="鏁呴殰椋庨櫓绛夌骇"
+                :value="healthData.riskLevel"
+                :value-style="{ color: healthData.riskColor }"
+              />
+            </a-col>
+          </a-row>
+          <div class="mt-4">
+            <a-progress
+              :percent="healthData.overallHealth"
+              :stroke-color="healthData.healthColor"
+              :show-info="false"
+            />
+          </div>
+          <a-divider orientation="left">棰勬祴鎬х淮鎶ゅ缓璁�</a-divider>
+          <a-table
+            :columns="maintenanceColumns"
+            :data-source="maintenanceData"
+            :pagination="false"
+            size="small"
+          >
+            <template #urgency="{ text }">
+              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
+            </template>
+            <template #action="{ record }">
+              <a-button type="link" size="small" @click="handleMaintenance(record)">澶勭悊</a-button>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+
+    <!-- 瀹炴椂鏁版嵁瓒嬪娍鍥� -->
+    <a-card title="瀹炴椂鏁版嵁瓒嬪娍鍥�" class="mb-4">
+      <!-- 杩愬姩绯荤粺 -->
+      <a-row :gutter="16">
+        <a-col :span="8">
+          <div id="xAxisMotorCurrentChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="yAxisMotorCurrentChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="zAxisMotorCurrentChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="motorTemperatureChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="motorVibrationChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="beltTensionChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+
+      <!-- 璐磋澶�/鍚稿槾 -->
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="nozzleVacuumChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="nozzleFlowChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="placementSpeedChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+
+      <!-- 瑙嗚绯荤粺 -->
+      <a-row :gutter="16" class="mt-4">
+                <a-col :span="8">
+          <div id="placementAccuracyChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="visionAlignmentChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="lightIntensityChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+
+      <!-- 鐜鍙傛暟 -->
+      <a-row :gutter="16" class="mt-4">
+        <a-col :span="8">
+          <div id="feederMotorCurrentChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="esdChart" style="height: 300px;"></div>
+        </a-col>
+        <a-col :span="8">
+          <div id="ambientTemperatureHumidityChart" style="height: 300px;"></div>
+        </a-col>
+      </a-row>
+    </a-card>
+    <a-row :gutter="16">
+      <!-- 澶囦欢瀵垮懡棰勬祴 -->
+      <a-col :span="12">
+        <a-card title="澶囦欢瀵垮懡棰勬祴" class="mb-4">
+          <a-table
+            :columns="sparePartColumns"
+            :data-source="sparePartData"
+            :pagination="false"
+            size="small"
+          >
+            <template #status="{ text }">
+              <a-tag :color="getStatusColor(text)">{{ text }}</a-tag>
+            </template>
+          </a-table>
+        </a-card>
+      </a-col>
+
+      <!-- 鍘嗗彶缁存姢璁板綍 -->
+      <a-col :span="12">
+        <a-card title="鍘嗗彶缁存姢璁板綍" class="mb-4">
+          <a-timeline>
+            <a-timeline-item v-for="item in historyData" :key="item.id" :color="item.color">
+              {{ item.date }} - {{ item.type }}: {{ item.description }}
+            </a-timeline-item>
+          </a-timeline>
+        </a-card>
+      </a-col>
+    </a-row>
+
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
+import * as echarts from 'echarts';
+
+export default defineComponent({
+  name: 'SmtMachineDetail',
+  setup() {
+    // 妯℃嫙鏁版嵁
+    const deviceInfo = reactive({
+      deviceName: 'SMT璐寸墖鏈�-001',
+      deviceType: '璐寸墖鏈�',
+      deviceId: 'SMT-2024-001',
+      installDate: '2024-01-01',
+      serviceLife: 8,
+      status: '杩愯涓�',
+      statusColor: '#52c41a'
+    });
+
+    const healthData = reactive({
+      overallHealth: 92,
+      healthColor: '#52c41a',
+      predictedLife: 2500,
+      riskLevel: '浣庨闄�',
+      riskColor: '#52c41a'
+    });
+
+    const maintenanceColumns = [
+      {
+        title: '缁存姢绫诲瀷',
+        dataIndex: 'type',
+        key: 'type'
+      },
+      {
+        title: '缁存姢鍐呭',
+        dataIndex: 'content',
+        key: 'content'
+      },
+      {
+        title: '寤鸿鏃堕棿',
+        dataIndex: 'suggestedTime',
+        key: 'suggestedTime'
+      },
+      {
+        title: '绱ф�ョ▼搴�',
+        dataIndex: 'urgency',
+        key: 'urgency',
+        slots: { customRender: 'urgency' }
+      },
+      {
+        title: '鎿嶄綔',
+        key: 'action',
+        slots: { customRender: 'action' }
+      }
+    ];
+
+    const maintenanceData = reactive([
+      {
+        key: '1',
+        type: '杩愬姩绯荤粺淇濆吇',
+        content: 'X/Y杞翠己鏈嶇數鏈烘鼎婊戞鏌�',
+        suggestedTime: '2024-03-20',
+        urgency: '涓瓑'
+      },
+      {
+        key: '2',
+        type: '璐磋澶寸淮鎶�',
+        content: '鍚稿槾鐪熺┖鍘嬪姏鏍″噯',
+        suggestedTime: '2024-04-05',
+        urgency: '楂�'
+      },
+      {
+        key: '3',
+        type: '渚涙枡绯荤粺妫�鏌�',
+        content: '椋炶揪鍗″甫/鍗℃枡娆℃暟娓呴浂',
+        suggestedTime: '2024-03-10',
+        urgency: '浣�'
+      }
+    ]);
+
+    const getUrgencyColor = (urgency: string) => {
+      switch (urgency) {
+        case '楂�':
+          return 'red';
+        case '涓瓑':
+          return 'orange';
+        case '浣�':
+          return 'green';
+        default:
+          return 'default';
+      }
+    };
+
+    const sparePartColumns = [
+      {
+        title: '澶囦欢鍚嶇О',
+        dataIndex: 'name',
+        key: 'name'
+      },
+      {
+        title: '褰撳墠瀵垮懡',
+        dataIndex: 'currentLife',
+        key: 'currentLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '棰勬祴鍓╀綑瀵垮懡',
+        dataIndex: 'remainingLife',
+        key: 'remainingLife',
+        customRender: ({ text }: { text: number }) => `${text}灏忔椂`
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        key: 'status',
+        slots: { customRender: 'status' }
+      }
+    ];
+
+    const sparePartData = reactive([
+      {
+        key: '1',
+        name: 'X杞翠己鏈嶇數鏈�',
+        currentLife: 5000,
+        remainingLife: 1500,
+        status: '鑹ソ'
+      },
+      {
+        key: '2',
+        name: '鍚稿槾',
+        currentLife: 1000,
+        remainingLife: 50,
+        status: '棰勮'
+      },
+      {
+        key: '3',
+        name: '椋炶揪',
+        currentLife: 8000,
+        remainingLife: 2000,
+        status: '鑹ソ'
+      }
+    ]);
+
+    const historyData = reactive([
+      {
+        id: '1',
+        date: '2024-02-15',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚瀛e害淇濆吇锛屾鏌ヨ繍鍔ㄧ郴缁熸鼎婊�',
+        color: 'green'
+      },
+      {
+        id: '2',
+        date: '2024-01-20',
+        type: '鏁呴殰缁翠慨',
+        description: '淇鍚稿槾鍫靛闂',
+        color: 'red'
+      },
+      {
+        id: '3',
+        date: '2023-12-01',
+        type: '瀹氭湡淇濆吇',
+        description: '瀹屾垚骞村害淇濆吇锛屾牎鍑嗚瑙夌郴缁�',
+        color: 'green'
+      }
+    ]);
+
+    const getStatusColor = (status: string) => {
+      switch (status) {
+        case '鑹ソ':
+          return '#52c41a';
+        case '棰勮':
+          return '#faad14';
+        case '鍗遍櫓':
+          return '#f5222d';
+        default:
+          return '#d9d9d9';
+      }
+    };
+
+    const handleMaintenance = (record: any) => {
+      console.log('澶勭悊缁存姢寤鸿:', record);
+      // 瀹為檯椤圭洰涓繖閲屼細璋冪敤API澶勭悊缁存姢寤鸿
+    };
+
+    return {
+      deviceInfo,
+      healthData,
+      maintenanceColumns,
+      maintenanceData,
+      sparePartColumns,
+      sparePartData,
+      historyData,
+      getStatusColor,
+      getUrgencyColor,
+      handleMaintenance
+    };
+  },
+
+  mounted() {
+    // 鍒濆鍖栧浘琛�
+    const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
+      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
+        });
+        if (chartData.length > 60) {
+          chartData.shift();
+        }
+        
+        const option = {
+          title: {
+            text: title,
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis',
+            formatter: (params) => {
+              return `${params[0].axisValueLabel}<br/>${params[0].marker} ${params[0].seriesName}: ${params[0].data}${unit}`;
+            }
+          },
+          grid: {
+            left: '8%', // 澧炲姞宸︿晶杈硅窛
+            right: '5%',
+            bottom: '10%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: chartData.map(item => item.time)
+          },
+          yAxis: {
+            type: 'value',
+            axisLabel: {
+              formatter: (value) => `${value}${unit}`
+            }
+          },
+          series: [
+            {
+              data: chartData.map(item => parseFloat(item.value)),
+              type: 'line',
+              smooth: true,
+              lineStyle: {
+                width: 2,
+                color: chartId === 'motorCurrentChart' ? '#5470C6' : chartId === 'motorTemperatureChart' ? '#91CC75' : '#FAC858' // 鏍规嵁鍥捐〃ID璁剧疆棰滆壊
+              },
+              areaStyle: {
+                opacity: 0.8,
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                  {
+                    offset: 0,
+                    color: chartId === 'motorCurrentChart' ? 'rgba(84,112,198,0.3)' : chartId === 'motorTemperatureChart' ? 'rgba(145,204,117,0.3)' : 'rgba(250,200,88,0.3)'
+                  },
+                  {
+                    offset: 1,
+                    color: chartId === 'motorCurrentChart' ? 'rgba(84,112,198,0)' : chartId === 'motorTemperatureChart' ? 'rgba(145,204,117,0)' : 'rgba(250,200,88,0)'
+                  }
+                ])
+              },
+            }
+          ]
+        };
+        chart.setOption(option);
+      };
+      
+      // 鐢熸垚鍒濆鏁版嵁鐐癸紙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({
+          time,
+          value: newValue
+        });
+      }
+      
+      // 鍒濆娓叉煋
+      updateChart();
+      
+      // 姣�5绉掓洿鏂颁竴娆℃暟鎹�
+      const intervalId = setInterval(updateChart, 5000);
+      
+      window.addEventListener('resize', () => {
+        chart.resize();
+      });
+            onUnmounted(() => {
+        clearInterval(intervalId);
+      });
+
+    };
+
+    // 杩愬姩绯荤粺鐩戞祴
+    initChart('xAxisMotorCurrentChart', 'X杞寸數鏈虹數娴�', [], 'A', 10, 1);
+    initChart('yAxisMotorCurrentChart', 'Y杞寸數鏈虹數娴�', [], 'A', 10, 1);
+    initChart('zAxisMotorCurrentChart', 'Z杞寸數鏈虹數娴�', [], 'A', 8, 0.8);
+    initChart('motorTemperatureChart', '鐢垫満娓╁害', [], '掳C', 45, 2);
+    initChart('motorVibrationChart', '鐢垫満鎸姩', [], 'mm/s', 5, 0.5);
+    initChart('beltTensionChart', '鐨甫寮犲姏', [], 'N', 50, 5);
+    
+    // 璐磋澶�/鍚稿槾鐩戞祴
+    initChart('nozzleVacuumChart', '鍚稿槾鐪熺┖鍘嬪姏', [], 'kPa', 80, 5);
+    initChart('nozzleFlowChart', '鍚稿槾娴侀噺', [], 'L/min', 5, 0.5);
+    initChart('placementSpeedChart', '璐磋閫熷害', [], 'mm/s', 100, 10);
+    initChart('placementAccuracyChart', '璐磋绮惧害', [], '渭m', 50, 5);
+    
+    // 瑙嗚绯荤粺鐩戞祴
+    initChart('visionAlignmentChart', '瑙嗚瀵逛綅绮惧害', [], '渭m', 30, 3);
+    initChart('lightIntensityChart', '鍏夋簮浜害', [], 'lux', 5000, 500);
+    
+    // 渚涙枡绯荤粺鐩戞祴
+    initChart('feederMotorCurrentChart', '渚涙枡鐢垫満鐢垫祦', [], 'A', 5, 0.5);
+    
+    // 鐜鐩戞祴
+    initChart('esdChart', '闈欑數鐩戞祴', [], 'kV', 0.1, 0.05);
+    initChart('ambientTemperatureHumidityChart', '鐜娓╂箍搴�', [], '掳C', 25, 2);
+  }
+  
+});
+</script>
+
+<style scoped>
+.device-detail-container {
+  padding: 16px;
+  background: #f0f2f5;
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3