车间能级提升-智能设备管理系统
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue
@@ -1,28 +1,56 @@
<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: {
    LineChartOutlined,
    WarningOutlined,
    AppstoreOutlined,
    CheckCircleOutlined,
    FieldTimeOutlined,
    ThunderboltOutlined
  },
  setup() {
    // 模拟数据
    const deviceInfo = reactive({
      deviceName: '注塑机 #IM-001',
      deviceName: '立式注塑机',
      deviceType: '注塑机',
      deviceId: 'IM-2024-001',
      installDate: '2023-08-20',
      deviceId: 'GPC2013C027',
      installDate: '2014-01-06',
      serviceLife: 15,
      status: '运行中',
      statusColor: '#52c41a'
      statusColor: '#52c41a',
      imageUrl: img // 添加设备图片路径
    });
    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: 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 = [
@@ -58,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: '检查确认液压油温度是否正常',
        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: '低'
      }
    ]);
@@ -95,23 +141,44 @@
      }
    };
     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: '备件名称',
        title: '部件名称',
        dataIndex: 'name',
        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: '状态',
@@ -124,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: '良好'
      }
    ]);
@@ -148,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'
@@ -191,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,
@@ -201,11 +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));
@@ -213,11 +392,12 @@
      // 确保初始数据点足够显示一个完整的趋势
      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秒
        for (let i = 0; i < 24; i++) {
          // 生成60个点,代表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),
            value: (baseValue + Math.random() * fluctuation * 2 - fluctuation).toFixed(2)
          });
        }
      }
@@ -233,7 +413,7 @@
          time,
          value: newValue
        });
        if (chartData.length > 60) {
        if (chartData.length > 24) {
          chartData.shift();
        }
@@ -256,7 +436,7 @@
          },
          xAxis: {
            type: 'category',
            data: chartData.map(item => item.time)
            data: chartData.map((item) => item.time)
          },
          yAxis: {
            type: 'value',
@@ -266,7 +446,7 @@
          },
          series: [
            {
              data: chartData.map(item => Number.parseFloat(item.value)),
              data: chartData.map((item) => Number.parseFloat(item.value)),
              type: 'line',
              smooth: true,
              lineStyle: {
@@ -285,7 +465,7 @@
                    color: 'rgba(84,112,198,0)'
                  }
                ])
              },
              }
            }
          ]
        };
@@ -301,11 +481,12 @@
      window.addEventListener('resize', () => {
        chart.resize();
      });
      onUnmounted(() => {
        clearInterval(intervalId);
      window.addEventListener('resize', () => {
        chart.resize();
      });
    };
    const hydraulicOilTemperatureData: any[] = [];
@@ -321,49 +502,60 @@
    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('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('moldClampingForceChart', '锁模压力', moldClampingForceData, 'Bar', 120, 10);
    initChart('injectionPressureChart', '注射压力', injectionPressureData, 'Bar', 80, 5);
    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);
    initChart('barrelTemperatureChart', '料筒温度', barrelTemperatureData, '°C', 240, 3);
    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>
<template>
  <div class="device-detail-container">
    <a-page-header
      :sub-title="deviceInfo.deviceName"
      title="注塑机预测性维护详情"
      @back="() => $router.go(-1)"
    />
    <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-col :span="10">
        <a-card :style="{ height: '440px' }" class="mb-4" title="设备信息">
          <a-row :gutter="16">
            <a-col :span="12">
              <div class="device-image-container">
                <img :src="deviceInfo.imageUrl" alt="设备图片" class="device-image" />
              </div>
            </a-col>
            <a-col :span="12">
              <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-col>
          </a-row>
        </a-card>
      </a-col>
      <!-- 设备健康状态与维护建议 -->
      <a-col :span="16">
      <a-col :span="14">
        <a-card :style="{ height: '440px' }" class="mb-4" title="设备健康状态与维护建议">
          <a-row :gutter="16">
            <a-col :span="8">
@@ -376,34 +568,17 @@
              />
            </a-col>
            <a-col :span="8">
              <a-statistic
                :value="healthData.predictedLife"
                suffix="天"
                title="预测剩余寿命"
              />
              <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-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"
            />
            <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>
@@ -414,65 +589,109 @@
        </a-card>
      </a-col>
    </a-row>
    <a-col :span="24">
      <a-card class="mb-4" title="设备数据">
        <a-row :gutter="[16, 16]">
          <a-col :span="4">
            <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.toFixed(0)" suffix="次" title="总循环次数">
              <template #prefix>
                <LineChartOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <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.toFixed(2)" suffix="kWh" title="当日累积能耗">
              <template #prefix>
                <ThunderboltOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic :value="healthData.yieldRate.toFixed(0)" suffix="模" title="当前产量">
              <template #prefix>
                <CheckCircleOutlined />
              </template>
            </a-statistic>
          </a-col>
<!--          <a-col :span="4">-->
<!--            <a-statistic :value="healthData.downtime" suffix="s" title="出错停机时间">-->
<!--              <template #prefix>-->
<!--                <FieldTimeOutlined />-->
<!--              </template>-->
<!--            </a-statistic>-->
<!--          </a-col>-->
        </a-row>
      </a-card>
    </a-col>
    <!-- 实时数据趋势图 -->
    <a-card class="mb-4" title="实时数据趋势图">
      <a-row :gutter="16">
<!--      <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="hydraulicOilTemperatureChart" style="height: 300px;"></div>
          <div id="screwSpeedChart" style="height: 300px"></div>
        </a-col>
        <a-col :span="8">
          <div id="hydraulicOilPressureChart" style="height: 300px;"></div>
         <div id="barrelTemperatureChart" style="height: 300px"></div>
        </a-col>
        <a-col :span="8">
          <div id="mainMotorCurrentChart" style="height: 300px;"></div>
          <div id="injectionPressureChart" 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>
          <div id="injectionSpeedChart" style="height: 300px"></div>
        </a-col>
        <a-col :span="8">
          <div id="moldClampingForceChart" style="height: 300px;"></div>
           <div id="moldClampingForceChart" style="height: 300px"></div>
        </a-col>
        <a-col :span="8">
          <div id="injectionPressureChart" style="height: 300px;"></div>
          <div id="coolingWaterTemperatureChart" 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-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"
          >
          <a-table :columns="sparePartColumns" :data-source="sparePartData" :pagination="false" size="small">
            <template #status="{ text }">
              <a-tag :color="getStatusColor(text)">{{ text }}</a-tag>
            </template>
@@ -485,7 +704,7 @@
        <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 }}
              <p>{{ item.date }} - {{ item.type }}:{{ item.description }}</p>
            </a-timeline-item>
          </a-timeline>
        </a-card>
@@ -496,54 +715,28 @@
<style scoped>
.device-detail-container {
  padding: 16px;
  background: #f0f2f5;
  padding: 20px;
  background-color: #f0f2f5;
}
.mt-4 {
  margin-top: 16px;
.device-image-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 330px;
}
.device-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.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);
.mt-4 {
  margin-top: 16px;
}
</style>