车间能级提升-智能设备管理系统
feat(eims): 更新预测性维护功能
- 新增设备数据定时更新功能
- 添加维护建议滚动显示
- 更新设备部件寿命预测数据
- 调整备件库存与预警逻辑
- 优化数据展示和颜色提示
已修改7个文件
已添加4个文件
1248 ■■■■ 文件已修改
eims-ui-mobile/src/pages/repair/res-list.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/equ/deviceData.ts 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue 284 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue 277 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue 279 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/DeviceDataController.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/AutoApproveRepairJob.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/DeviceDataIncrJob.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/repair/res-list.vue
@@ -20,8 +20,11 @@
<!--        </template>-->
      </wd-navbar>
      <!-- å¢žåŠ ä¸€ä¸ªæœç´¢æ  -->
      <wd-search v-model="searchValue" @search="handleSearch">
      </wd-search>
      <wd-search v-model="searchValue" @search="handleSearch"></wd-search>
      <wd-tabs v-model="activeTab" @change="handleTabChange">
        <wd-tab title="待维修"></wd-tab>
        <wd-tab title="已维修"></wd-tab>
      </wd-tabs>
<!--      <wd-drop-menu>-->
<!--        <wd-drop-menu-item-->
<!--          v-model="resTypeId"-->
@@ -61,6 +64,8 @@
import { formatDate } from '@/utils/DateUtils'
import dayjs from "dayjs";
import ResCard from "@/components/repair/res-card.vue";
const activeTab = ref(0)
const userStore = useUserStore()
const message = useMessage()
@@ -148,7 +153,14 @@
  if (option?.from === 'scan') {
    queryParams.assetNo = option.assetNo
  }
  queryParams.params.status = '0,1,2,3'
  if (activeTab.value === 0) {
    // å¾…维修:status ç­‰äºŽ 1 æˆ– 2 æˆ– 3
    queryParams.params.status = '1,2'
  } else {
    // å·²ç»´ä¿®ï¼šstatus ç­‰äºŽ 3 æˆ– 4
    queryParams.params.status = '3,4'
  }
  queryParams.reqUser = userStore?.userInfo?.userId
  if (isRepair()) {
    queryParams.params.status = undefined
@@ -167,6 +179,10 @@
  paging.value.reload()
}
function handleTabChange() {
  reloadData()
}
// /**
//  * æ¡ç›®ç‚¹å‡»äº‹ä»¶
//  * @param item
eims-ui/apps/web-antd/src/api/eims/equ/deviceData.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
import type { PageQuery, PageResult } from '#/api/model';
import { requestClient } from '#/api/request';
enum Api {
  getDeviceData = '/eims/deviceData/get',
  getDeviceDataSmt = '/eims/deviceData/getSmt',
  getDeviceDataInj = '/eims/deviceData/getInj',
  updateDeviceData = '/eims/deviceData/update',
  initDeviceData = '/eims/deviceData/init'
}
/**
 * èŽ·å–è®¾å¤‡æ•°æ®
 */
export function getDeviceData() {
  return requestClient.get<Record<string, number>>(Api.getDeviceData);
}
/**
 * èŽ·å–è®¾å¤‡æ•°æ®
 */
export function getDeviceDataSmt() {
  return requestClient.get<Record<string, number>>(Api.getDeviceDataSmt);
}
/**
 * èŽ·å–è®¾å¤‡æ•°æ®
 */
export function getDeviceDataInj() {
  return requestClient.get<Record<string, number>>(Api.getDeviceDataInj);
}
/**
 * æ›´æ–°è®¾å¤‡æ•°æ®ï¼ˆæ¨¡æ‹Ÿè‡ªåŠ¨å¢žé•¿ï¼‰
 */
export function updateDeviceData() {
  return requestClient.post<void>(Api.updateDeviceData);
}
/**
 * åˆå§‹åŒ–设备数据
 */
export function initDeviceData() {
  return requestClient.post<void>(Api.initDeviceData);
}
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/cnc-machining-center-detail.vue
@@ -69,10 +69,12 @@
          </div>
          <a-divider orientation="left">预测性维护建议</a-divider>
          <a-table
            ref="maintenanceTable"
            :columns="maintenanceColumns"
            :data-source="maintenanceData"
            :pagination="false"
            size="small"
            :scroll="{ y: 150 }"
          >
            <template #urgency="{ text }">
              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
@@ -90,42 +92,42 @@
      <a-card title="设备数据" class="mb-4">
        <a-row :gutter="[16, 16]">
          <a-col :span="4">
            <a-statistic title="加工时间" :value="healthData.xAxisTravel" suffix="km">
            <a-statistic title="加工时间" :value="healthData.xAxisTravel.toFixed(2)" suffix="h">
              <template #prefix>
                <FieldTimeOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic title="刀具使用次数" :value="healthData.yAxisTravel" suffix="km">
            <a-statistic title="刀库切换次数" :value="healthData.yAxisTravel.toFixed(0)" suffix="次">
              <template #prefix>
                <FieldTimeOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic title="刀具使用时长" :value="healthData.zAxisTravel" suffix="km">
            <a-statistic title="刀具平均寿命" :value="healthData.zAxisTravel.toFixed(2)" suffix="h">
              <template #prefix>
                <FieldTimeOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic title="刀具更换次数" :value="healthData.toolChangeCount" suffix="次">
            <a-statistic title="平均调机编程时间" :value="healthData.toolChangeCount" suffix="Min">
              <template #prefix>
                <WarningOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic title="加工零件数" :value="healthData.partCount" suffix="ä»¶">
            <a-statistic title="累计加工零件数" :value="healthData.partCount.toFixed(0)" suffix="ä»¶">
              <template #prefix>
                <AppstoreOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic title="出错停机时间" :value="healthData.downtime" suffix="秒">
            <a-statistic title="平均加工等待时间" :value="healthData.downtime" suffix="秒">
              <template #prefix>
                <FieldTimeOutlined />
              </template>
@@ -142,7 +144,7 @@
          <div id="spindleVibrationChart" style="height: 300px;"></div>
        </a-col>
        <a-col :span="8">
          <div id="hydraulicOilTemperatureChart" style="height: 300px;"></div>
          <div id="spindleTemperatureChart" style="height: 300px;"></div>
        </a-col>
        <a-col :span="8">
          <div id="spindleSpeedChart" style="height: 300px;"></div>
@@ -155,8 +157,7 @@
          <div id="hydraulicPressureChart" style="height: 300px;"></div>
        </a-col>
        <a-col :span="8">
          <div id="spindleTemperatureChart" style="height: 300px;"></div>
          <div id="hydraulicOilTemperatureChart" style="height: 300px;"></div>
        </a-col>
        <a-col :span="8">
          <div id="coolantTemperatureChart" style="height: 300px;"></div>
@@ -197,7 +198,7 @@
</template>
<script lang="ts">
import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
import { defineComponent, reactive, onMounted, onUnmounted, ref, nextTick } from 'vue';
import * as echarts from 'echarts';
import {
  LineChartOutlined,
@@ -205,7 +206,8 @@
  AppstoreOutlined,
  FieldTimeOutlined
} from '@ant-design/icons-vue';
import img from '#/assets/images/T850-840.2.jpg'
import img from '#/assets/images/T850-840.2.jpg';
import { getDeviceData, updateDeviceData, initDeviceData } from '#/api/eims/equ/deviceData'
export default defineComponent({
  name: 'CNCMachiningCenterDetail',
  setup() {
@@ -224,15 +226,15 @@
    const healthData = reactive({
      overallHealth: 95,
      healthColor: '#52c41a',
      predictedLife: 4436,
      predictedLife: 5017,
      riskLevel: '低风险',
      riskColor: '#52c41a',
      xAxisTravel: 1200.5,
      yAxisTravel: 980.2,
      zAxisTravel: 500.1,
      toolChangeCount: 25,
      partCount: 1500,
      downtime: 120
      xAxisTravel: 7105.5,  // æ¯å¤©åŠ 6小时
      yAxisTravel: 5641,  // æ¯å¤©åŠ 60次
      zAxisTravel: 450.4,  // æ¯å¤©åŠ 20米左右
      toolChangeCount: 74,  // ä¸æ³¢åЍ
      partCount: 17056, // æ¯å¤©åŠ 15个左右
      downtime: 141  // ä¸æ³¢åЍ
    });
    const maintenanceColumns = [
@@ -270,7 +272,7 @@
        type: '例行保养',
        content: '检查主轴润滑系统',
        suggestedTime: '2025-07-15',
        urgency: '中等'
        urgency: '低'
      },
      {
        key: '2',
@@ -281,9 +283,30 @@
      },
      {
        key: '3',
        type: '导轨维护',
        type: '丝杆导轨维护',
        content: '补充导轨润滑油',
        suggestedTime: '2025-06-01',
        urgency: '低'
      },
      {
        key: '3',
        type: '加工精度确认',
        content: '定期导轨精度校验检查确认',
        suggestedTime: '2025-05-05',
        urgency: '低'
      },
      {
        key: '3',
        type: '刀库功能确认',
        content: '指令换刀是否存在卡滞延迟现象',
        suggestedTime: '2025-05-03',
        urgency: '低'
      },
      {
        key: '3',
        type: '切削液更换',
        content: '检查确认切削液是否超期,杂质含量是否符合要求',
        suggestedTime: '2025-05-03',
        urgency: '低'
      }
    ]);
@@ -308,16 +331,16 @@
        key: 'name'
      },
      {
        title: '当前寿命',
        title: '预计寿命',
        dataIndex: 'currentLife',
        key: 'currentLife',
        customRender: ({ text }: { text: number }) => `${text}小时`
        // customRender: ({ text }: { text: number }) => `${text}小时`
      },
      {
        title: '预测剩余寿命',
        dataIndex: 'remainingLife',
        key: 'remainingLife',
        customRender: ({ text }: { text: number }) => `${text}小时`
        // customRender: ({ text }: { text: number }) => `${text}小时`
      },
      {
        title: '状态',
@@ -329,49 +352,120 @@
    const sparePartData = reactive([
      {
        key: '3',
        name: '切削液',
        currentLife: "6个月",
        remainingLife: "1个月",
        status: '预警'
      },
      {
        key: '1',
        name: '主轴轴承',
        currentLife: 8000,
        remainingLife: 500,
        status: '预警'
        currentLife: "8000小时",
        remainingLife: "5710小时",
        status: '良好'
      },
      {
        key: '2',
        name: 'X轴丝杠',
        currentLife: 12000,
        remainingLife: 2000,
        currentLife: "12000小时",
        remainingLife: "9132小时",
        status: '良好'
      },
      {
        key: '2',
        name: 'Y轴丝杠',
        currentLife: "12000小时",
        remainingLife: "9132小时",
        status: '良好'
      },
      {
        key: '2',
        name: 'Z轴丝杠',
        currentLife: "12000小时",
        remainingLife: "9132小时",
        status: '良好'
      },
      {
        key: '3',
        name: '导轨油',
        currentLife: "30天",
        remainingLife: "23天",
        status: '良好'
      },
      {
        key: '3',
        name: '液压油',
        currentLife: 3000,
        remainingLife: 200,
        status: '预警'
        name: '刀桶夹',
        currentLife: "30000次",
        remainingLife: "23513次",
        status: '良好'
      },
      {
        key: '3',
        name: '刀桶拉钉',
        currentLife: "15000次",
        remainingLife: "11421次",
        status: '良好'
      }
    ]);
    const historyData = reactive([
      {
        id: '1',
        date: '2024-05-20',
        date: '2025-08-06',
        type: '例行保养',
        description: '主轴润滑系统检查',
        description: '各导轨润滑系统检查,添加导轨油',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-07-11',
        type: '例行保养',
        description: '各导轨润滑系统检查,添加导轨油',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-06-18',
        type: '维修保养',
        description: '刀桶拉钉更换3个',
        color: 'orange'
      },
      {
        id: '1',
        date: '2025-06-09',
        type: '例行保养',
        description: '各导轨润滑系统检查,添加导轨油',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-05-22',
        type: '维修保养',
        description: '刀桶夹磨损精度下降,更换新配件',
        color: 'orange'
      },
      {
        id: '1',
        date: '2025-05-10',
        type: '例行保养',
        description: '各导轨润滑系统检查,添加导轨油',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-04-13',
        type: '例行保养',
        description: '各导轨润滑系统检查,添加导轨油',
        color: 'green'
      },
      {
        id: '2',
        date: '2024-02-10',
        type: '故障维修',
        description: 'Y轴伺服电机报警处理',
        color: 'red'
      },
      {
        id: '3',
        date: '2023-11-01',
        type: '年度保养',
        description: '全面检查设备运行状态',
        color: 'green'
        date: '2025-03-04',
        type: '维修保养',
        description: '切削渣清理,切削液更换',
        color: 'orange'
      }
    ]);
@@ -393,6 +487,84 @@
      // å®žé™…项目中这里会调用API处理维护建议
    };
    const maintenanceTable = ref<HTMLElement | null>(null);
    let scrollInterval: number | undefined;
    const startScroll = () => {
      if (!maintenanceTable.value) return;
      const tableBody = maintenanceTable.value.$el.querySelector('.ant-table-body');
      if (!tableBody) return;
      const scrollHeight = tableBody.scrollHeight;
      const clientHeight = tableBody.clientHeight;
      if (scrollHeight <= clientHeight) {
        return;
      }
      let currentScrollTop = 0;
      scrollInterval = setInterval(() => {
        currentScrollTop += 1;
        if (currentScrollTop >= scrollHeight - clientHeight) {
          currentScrollTop = 0;
        }
        tableBody.scrollTop = currentScrollTop;
      }, 50);
    };
    let deviceDataInterval: number | undefined;
    const fetchDeviceData = async () => {
      try {
        const res = await getDeviceData();
        Object.assign(healthData, res);
      } catch (error) {
        console.error('获取设备数据失败:', error);
      }
    };
    fetchDeviceData();
      // åˆå§‹åŒ–设备数据
      // initDeviceData().then(() => {
      //   fetchDeviceData(); // åˆå§‹åŒ–后立即获取一次数据
      // });
      // æ¯ç§’更新一次设备数据
      deviceDataInterval = setInterval(async () => {
        try {
          fetchDeviceData();
        } catch (error) {
          console.error('更新设备数据失败:', error);
        }
      }, 3000);
    onUnmounted(() => {
      if (scrollInterval) {
        clearInterval(scrollInterval);
      }
      if (deviceDataInterval) {
        clearInterval(deviceDataInterval);
      }
    });
    onMounted(() => {
      nextTick(() => {
        startScroll();
      });
    });
    onUnmounted(() => {
      if (scrollInterval) {
        clearInterval(scrollInterval);
      }
    });
    return {
      deviceInfo,
      healthData,
@@ -403,7 +575,8 @@
      historyData,
      getStatusColor,
      getUrgencyColor,
      handleMaintenance
      handleMaintenance,
      maintenanceTable
    };
  },
@@ -430,7 +603,7 @@
            time,
            value: newValue
          });
          if (s.data.length > 60) {
          if (s.data.length > 12) {
            s.data.shift();
          }
        });
@@ -503,8 +676,8 @@
      seriesConfig.forEach(s => {
        s.data = [];
        // ç”Ÿæˆåˆå§‹æ•°æ®ç‚¹ï¼ˆ60个点,5分钟数据)
      for (let i = 0; i < 60; i++) {
        const now = new Date(Date.now() - (60 - i) * 5000); // ç”Ÿæˆè¿‡åŽ»5分钟的数据
      for (let i = 0; i < 12; i++) {
        const now = new Date(Date.now() - (12 - i) * 5000); // ç”Ÿæˆè¿‡åŽ»5分钟的数据
        const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
        const newValue = (s.baseValue + (Math.random() * 2 - 1) * s.fluctuation).toFixed(2);
        s.data.push({
@@ -530,9 +703,10 @@
    };
    // è¿åŠ¨ç³»ç»Ÿç›‘æµ‹
    initChart('spindleVibrationChart', '主轴振动', [
      { name: '振动', data: [], unit: 'mm/s', baseValue: 3.0, fluctuation: 0.5, color: '#5470C6' },
    initChart('spindleVibrationChart', '平均加工时间', [
      { name: '时间', data: [], unit: 'min/pcs', baseValue: 16.0, fluctuation: 0.1, color: '#5470C6' },
    ]);
    initChart('spindleTemperatureChart', '主轴温度', [
      { name: '温度', data: [], unit: '°C', baseValue: 50, fluctuation: 3, color: '#5470C6' },
@@ -576,6 +750,8 @@
    initChart('coolantTemperatureChart', '冷却液温度', [
      { name: '温度', data: [], unit: '°C', baseValue: 28, fluctuation: 2, color: '#5470C6' },
    ]);
  }
});
@@ -585,12 +761,6 @@
.device-detail-container {
  padding: 16px;
  background: #f0f2f5;
}
.device-image-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 330px;
}
.mt-4 {
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/index.vue
@@ -63,8 +63,8 @@
      <!-- å¤‡ä»¶ä¿¡æ¯ -->
      <div class="grid grid-cols-2 gap-4 mb-6">
        <!-- è®¾å¤‡éƒ¨ä»¶å¯¿å‘½é¢„测 -->
        <Card title="设备部件寿命预测">
          <Table :columns="lifePredictionColumns" :data-source="lifePredictionData" :pagination="false" class="w-full">
        <Card title="设备部件寿命预测" :style="{ height: '500px' }">
          <Table :columns="lifePredictionColumns" :data-source="lifePredictionData" :pagination="false" :scroll="{ y: 340 }" class="w-full">
            <template #bodyCell="{ column, record }">
              <template v-if="column.key === 'lifeStatus'">
                <a-tag :color="getLifeStatusColor(record.remainingDays)">
@@ -79,8 +79,8 @@
        </Card>
        <!-- å¤‡ä»¶åº“存与预警 -->
        <Card title="备件库存与预警">
          <Table :columns="sparePartColumns" :data-source="sparePartData" :pagination="false" class="w-full">
        <Card title="备件库存与预警" :style="{ height: '500px' }">
          <Table :columns="sparePartColumns" :data-source="sparePartData" :pagination="false" :scroll="{ y: 340 }" class="w-full">
            <template #bodyCell="{ column, record }">
              <template v-if="column.key === 'stockStatus'">
                <a-tag :color="getStockStatusColor(record.currentStock, record.safetyStock)">
@@ -140,7 +140,7 @@
    indicator: '真空压力',
    value: 32,
    threshold: 35,
    status: '中风险',
    status: '低风险',
    maintenanceSuggestion: '真空压力值低于设定值,建议检查或更换吸嘴',
    maintenanceType: '预防性维护',
  },
@@ -152,7 +152,7 @@
    indicator: '温度',
    value: 85,
    threshold: 80,
    status: '中风险',
    status: '低风险',
    maintenanceSuggestion: '建议对主轴进行润滑保养并检查冷却系统',
    maintenanceType: '润滑维护',
  },
@@ -221,12 +221,33 @@
    safetyStock: 10,
    predictedDemand: 2,
  },
  {
    key: '4',
    name: '喷码机油墨',
    currentStock: 1,
    safetyStock: 1,
    predictedDemand: 1,
  },
  {
    key: '4',
    name: '钢网清洗液',
    currentStock: 2,
    safetyStock: 1,
    predictedDemand: 1,
  },
  {
    key: '4',
    name: '十寸精密滤芯',
    currentStock: 20,
    safetyStock: 4,
    predictedDemand: 0,
  },
]);
const getStatusColor = (status) => {
  switch (status) {
    case '高风险': return 'red';
    case '中风险': return 'orange';
    case '低风险': return 'yellow';
    case '低风险': return 'blue';
    default: return 'green';
  }
};
@@ -245,7 +266,7 @@
const lifePredictionColumns = [
  { title: '设备名称', dataIndex: 'deviceName', key: 'deviceName' },
  { title: '部位名称', dataIndex: 'componentName', key: 'componentName' },
  // { title: '部位名称', dataIndex: 'componentName', key: 'componentName' },
  { title: '部件名称', dataIndex: 'name', key: 'name' },
  { title: '预测寿命 (天)', dataIndex: 'predictedLife', key: 'predictedLife' },
  { title: '剩余寿命 (天)', dataIndex: 'remainingDays', key: 'remainingDays' },
@@ -254,19 +275,25 @@
];
const lifePredictionData = ref([
    { key: '4', deviceName: '空压机', componentName: '电机', name: '传感器', predictedLife: 500, remainingDays: 10 },
      { key: '2', deviceName: 'CNC加工中心', componentName: '主轴', name: '齿轮', predictedLife: 730, remainingDays: 30 },
  { key: '1', deviceName: 'SMT贴片机', componentName: '传送带', name: '轴承', predictedLife: 365, remainingDays: 50 },
  { key: '1', deviceName: 'SMT贴片机', componentName: '传送带', name: '真空发生器', predictedLife: 700, remainingDays: 83 },
  { key: '1', deviceName: '包装机', componentName: '传送带', name: '发热丝', predictedLife: 260, remainingDays: 61 },
  { key: '1', deviceName: '激光打标机', componentName: '传送带', name: '冷却水', predictedLife: 180, remainingDays: 43 },
  { key: '1', deviceName: '钢网清洗机', componentName: '传送带', name: '清洗液', predictedLife: 180, remainingDays: 95 },
  { key: '1', deviceName: '钢网清洗机', componentName: '传送带', name: '滤芯', predictedLife: 180, remainingDays: 95 },
  { key: '1', deviceName: '端子机', componentName: '传送带', name: '刀片', predictedLife: 180, remainingDays: 112 },
  { key: '1', deviceName: '电脑剥线机', componentName: '传送带', name: '刀片', predictedLife: 180, remainingDays: 107 },
  { key: '3', deviceName: '注塑机', componentName: '液压系统', name: '滤芯', predictedLife: 180, remainingDays: 90 },
  { key: '5', deviceName: '焊接机器人', componentName: '焊枪', name: '焊嘴', predictedLife: 240, remainingDays: 60 }
  { key: '2', deviceName: 'CNC加工中心', componentName: '主轴', name: '刀筒夹', predictedLife: 1100, remainingDays: 130 },
  { key: '4', deviceName: '空压机', componentName: '安全阀', name: '安全阀', predictedLife: 365, remainingDays: 130 },
  { key: '1', deviceName: '喷码机', componentName: '传送带', name: '墨水', predictedLife: 365, remainingDays: 184 },
  { key: '3', deviceName: '注塑机', componentName: '液压系统', name: '液压油', predictedLife: 1100, remainingDays: 395 },
  { key: '5', deviceName: '焊接机器人', componentName: '焊枪', name: '烙铁芯', predictedLife: 1000, remainingDays: 512 }
]);
const getLifeStatus = (remainingDays) => {
  if (remainingDays <= 30) {
  if (remainingDays <= 90) {
    return '即将到期';
  } else if (remainingDays <= 90) {
  } else if (remainingDays <= 150) {
    return '中期预警';
  } else {
    return '寿命充足';
@@ -274,10 +301,10 @@
};
const getLifeStatusColor = (remainingDays) => {
  if (remainingDays <= 30) {
    return 'red';
  } else if (remainingDays <= 90) {
  if (remainingDays <= 90) {
    return 'orange';
  } else if (remainingDays <= 150) {
    return 'blue';
  } else {
    return 'green';
  }
@@ -290,7 +317,7 @@
const getStockStatus = (currentStock, safetyStock) => {
  if (currentStock <= safetyStock) {
  if (currentStock < safetyStock) {
    return '库存预警';
  } else {
    return '库存充足';
@@ -298,8 +325,8 @@
};
const getStockStatusColor = (currentStock, safetyStock) => {
  if (currentStock <= safetyStock) {
    return 'red';
  if (currentStock < safetyStock) {
    return 'orange';
  } else {
    return 'green';
  }
@@ -340,13 +367,13 @@
  // æ ¹æ®è®¾å¤‡åç§°ä¸åŒè·³è½¬ä¸åŒçš„详情页面
  if (record.name === 'SMT贴片机') {
    console.log('设备ID111:', record.name)
    router.push({ path: '/predictive/smt-detail', query: { deviceId: record.key } });
    router.push({ path: '/predictive/smt-detail', query: { deviceId: 15 } });
  } else if (record.name === 'CNC加工中心') {
    router.push({ path: '/predictive/cnc-detail', query: { deviceId: record.key } });
    router.push({ path: '/predictive/cnc-detail', query: { deviceId: 23 } });
  } else if (record.name === '注塑机') {
    router.push({ path: '/predictive/injection-detail', query: { deviceId: record.key } });
    router.push({ path: '/predictive/injection-detail', query: { deviceId: 181 } });
  } else {
    router.push({ path: '/predictive/air-compressor-detail', query: { deviceId: record.key } });
    router.push({ path: '/predictive/air-compressor-detail', query: { deviceId: 46 } });
  }
};
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/injection-molding-machine-detail.vue
@@ -1,9 +1,11 @@
<script lang="ts">
import { defineComponent, onUnmounted, reactive } from 'vue';
import { defineComponent, reactive, onMounted, onUnmounted, ref, nextTick } from 'vue';
import { AppstoreOutlined, FieldTimeOutlined, LineChartOutlined, WarningOutlined, ThunderboltOutlined, CheckCircleOutlined } from '@ant-design/icons-vue';
import * as echarts from 'echarts';
import img from '#/assets/images/2t.png';
import { getDeviceDataInj, updateDeviceData, initDeviceData } from '#/api/eims/equ/deviceData'
export default defineComponent({
  name: 'InjectionMoldingMachineDetail',
  components: {
@@ -29,22 +31,26 @@
    const healthData = reactive({
      overallHealth: 88,
      healthColor: '#faad14',
      predictedLife: 1500,
      riskLevel: '中风险',
      riskColor: '#faad14',
      healthColor: '#52c41a',
      predictedLife: 1753,
      riskLevel: '低风险',
      riskColor: '#1a7ac4',
      injectionPressure: 120, // æ³¨å¡‘压力
      clampingForce: 80, // é”æ¨¡åŠ›
      moldTemperature: 45, // æ¨¡å…·æ¸©åº¦
      screwSpeed: 150, // èžºæ†è½¬é€Ÿ
      meltTemperature: 220, // ç†”融温度
      coolingTime: 25, // å†·å´æ—¶é—´
      injectionCount: '495d 19h 44 ', // æ³¨å°„次数
      clampingCount: 545636, // åˆæ¨¡æ¬¡æ•°
      productionCycle: 19, // ç”Ÿäº§å‘¨æœŸ
      energyConsumption: 1500, // èƒ½è€—
      yieldRate: 98.5, // è‰¯å“çއ
      downtime: 120 // å‡ºé”™åœæœºæ—¶é—´
      injectionCount: 495 * 24 * 60 + 19 * 60 + 44, // æ³¨å°„次数,转换为分钟
      clampingCount: 545636, // åˆæ¨¡æ¬¡æ•° // è·Ÿéšäº§é‡ 50s加一次
      productionCycle: 45, // ç”Ÿäº§å‘¨æœŸ
      energyConsumption: 64, // èƒ½è€—
      yieldRate: 354, // äº§é‡   50秒增加一模
      downtime: 120, // å‡ºé”™åœæœºæ—¶é—´
      // ç”¨äºŽç´¯åŠ å¢žé•¿çš„å­—æ®µ
      // accumulatedInjectionCount: 12180,
      // accumulatedClampingCount: 545636,
      // accumulatedEnergyConsumption: 64
    });
    const maintenanceColumns = [
@@ -80,22 +86,40 @@
      {
        key: '1',
        type: '例行保养',
        content: '检查液压油污染度',
        suggestedTime: '2024-07-15',
        content: '检查液压油乳化程度',
        suggestedTime: '2025-07-02',
        urgency: '中等'
      },
      {
        key: '2',
        type: '故障预警',
        content: '主电机轴承磨损预警',
        suggestedTime: '2024-08-01',
        urgency: '高'
        content: '主油缸密封圈寿命预警',
        suggestedTime: '2025-07-01',
        urgency: '低'
      },{
        key: '2',
        type: '液压油检查',
        content: '检查确认液压油温度是否正常',
        suggestedTime: '2025-07-01',
        urgency: '低'
      },
      {
        key: '3',
        type: '冷却系统维护',
        content: '检查冷却水流量',
        suggestedTime: '2024-07-01',
        type: '冷却系统检查',
        content: '检查冷水机制冷效率是否达标',
        suggestedTime: '2025-06-11',
        urgency: '低'
      },{
        key: '3',
        type: '液压系统检查',
        content: '检查各液压管道压力表与电脑显示是否一致',
        suggestedTime: '2025-06-11',
        urgency: '低'
      },{
        key: '3',
        type: '温控系统检查',
        content: '检查各段加热圈加热、热电耦是否异常',
        suggestedTime: '2025-06-11',
        urgency: '低'
      }
    ]);
@@ -117,6 +141,27 @@
      }
    };
     const fetchDeviceData = async () => {
      try {
        const res = await getDeviceDataInj();
        Object.assign(healthData, res);
      } catch (error) {
        console.error('获取设备数据失败:', error);
      }
    };
    let deviceDataInterval: number | undefined;
    fetchDeviceData();
     deviceDataInterval = setInterval(async () => {
        try {
          fetchDeviceData();
        } catch (error) {
          console.error('更新设备数据失败:', error);
        }
      }, 3000);
    const sparePartColumns = [
      {
        title: '部件名称',
@@ -124,16 +169,16 @@
        key: 'name'
      },
      {
        title: '当前寿命',
        title: '预计寿命',
        dataIndex: 'currentLife',
        key: 'currentLife',
        customRender: ({ text }: { text: number }) => `${text}小时`
        key: 'currentLife'
      },
      {
        title: '预测剩余寿命',
        dataIndex: 'remainingLife',
        key: 'remainingLife',
        customRender: ({ text }: { text: number }) => `${text}小时`
        key: 'remainingLife'
      },
      {
        title: '状态',
@@ -146,23 +191,44 @@
    const sparePartData = reactive([
      {
        key: '1',
        name: '液压泵',
        currentLife: 18_500,
        remainingLife: 1500,
        status: '预警'
        name: '液压油',
        currentLife: 8_500,
        remainingLife: 2515,
        status: '良好'
      },
      {
        key: '2',
        name: '加热圈',
        currentLife: 12_000,
        remainingLife: 3000,
        currentLife: 6_000,
        remainingLife: 3415,
        status: '良好'
      },
      {
        key: '3',
        name: '螺杆料筒',
        currentLife: 25_000,
        remainingLife: 5000,
        name: '热电耦',
        currentLife: 8_000,
        remainingLife: 5851,
        status: '良好'
      },
      {
        key: '3',
        name: '注胶嘴',
        currentLife: "100000次",
        remainingLife: "76438次",
        status: '良好'
      },
      {
        key: '3',
        name: '锁模夹具',
        currentLife: "12个月",
        remainingLife: "8个月",
        status: '良好'
      },
      {
        key: '3',
        name: '注胶螺杆',
        currentLife: "60个月",
        remainingLife: "48个月",
        status: '良好'
      }
    ]);
@@ -170,21 +236,49 @@
    const historyData = reactive([
      {
        id: '1',
        date: '2023-10-20',
        date: '2025-08-15',
        type: '例行保养',
        description: '更换液压油滤芯',
        description: '液压系统检查,温控系统检查',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-07-20',
        type: '例行保养',
        description: '液压系统检查,温控系统检查',
        color: 'green'
      },
      {
        id: '2',
        date: '2023-08-15',
        type: '故障维修',
        description: '注射单元卡滞,清理异物',
        color: 'red'
        date: '2025-07-13',
        type: '维修保养',
        description: '第一段温度显示异常,热电耦损坏,更换新配件',
        color: 'orange'
      },
      {
        id: '1',
        date: '2025-06-18',
        type: '例行保养',
        description: '液压系统检查,温控系统检查',
        color: 'green'
      },
      {
        id: '2',
        date: '2025-05-23',
        type: '维修保养',
        description: '第三段温度异常,加热圈烧坏,更换新配件',
        color: 'orange'
      },
      {
        id: '2',
        date: '2025-05-15',
        type: '例行保养',
        description: '液压系统检查,温控系统检查',
        color: 'green'
      },
      {
        id: '3',
        date: '2023-06-01',
        date: '2025-04-01',
        type: '年度保养',
        description: '全面检查设备运行状态',
        color: 'blue'
@@ -213,6 +307,68 @@
      // å®žé™…项目中这里会调用API处理维护建议
    };
    let intervalId: number | undefined;
    // const updateAccumulatedData = () => {
    //   healthData.accumulatedInjectionCount +=  + 0.1; // æ¯æ¬¡å¢žåŠ 1-5分钟
    //   healthData.accumulatedClampingCount += Math.floor(Math.random() * 100) + 10; // æ¯æ¬¡å¢žåŠ 10-100次
    //   healthData.accumulatedEnergyConsumption += (Math.random() * 0.015 + 0.008); // æ¯æ¬¡å¢žåŠ 0.1-0.6 kWh
    //   // æ›´æ–°æ˜¾ç¤ºå€¼
    //   const totalMinutes = Math.floor(healthData.accumulatedInjectionCount);
    //   const minutes = totalMinutes % 60;
    //   healthData.injectionCount = `${healthData.accumulatedInjectionCount}h`;
    //   healthData.clampingCount = healthData.accumulatedClampingCount;
    //   healthData.energyConsumption = parseFloat(healthData.accumulatedEnergyConsumption.toFixed(2));
    // };
    const maintenanceTable = ref<HTMLElement | null>(null);
    // åˆå§‹è®¾ç½®ä¸€æ¬¡ï¼Œé¿å…é¦–次加载时显示为0
    // updateAccumulatedData();
    let scrollInterval: number | undefined;
    const startScroll = () => {
      if (!maintenanceTable.value) return;
      const tableBody = maintenanceTable.value.$el.querySelector('.ant-table-body');
      if (!tableBody) return;
      const scrollHeight = tableBody.scrollHeight;
      const clientHeight = tableBody.clientHeight;
      if (scrollHeight <= clientHeight) {
        return;
      }
      let currentScrollTop = 0;
      scrollInterval = setInterval(() => {
        currentScrollTop += 1;
        if (currentScrollTop >= scrollHeight - clientHeight) {
          currentScrollTop = 0;
        }
        tableBody.scrollTop = currentScrollTop;
      }, 50);
    };
    onMounted(() => {
      // æ¯5秒更新一次累加数据
      // intervalId = setInterval(updateAccumulatedData, 5000);
      nextTick(() => {
        startScroll();
      });
    })
    onUnmounted(() => {
      if (scrollInterval) {
        clearInterval(scrollInterval);
      }
       if (deviceDataInterval) {
        clearInterval(deviceDataInterval);
      }
    });
    return {
      deviceInfo,
      healthData,
@@ -223,10 +379,12 @@
      historyData,
      getStatusColor,
      getUrgencyColor,
      handleMaintenance
      handleMaintenance,
      maintenanceTable
    };
  },
  mounted() {
    // åˆå§‹åŒ–图表
    const initChart = (chartId: string, title: string, chartData: any[], unit: string, baseValue: number, fluctuation: number) => {
      const chart = echarts.init(document.getElementById(chartId));
@@ -234,9 +392,9 @@
      // ç¡®ä¿åˆå§‹æ•°æ®ç‚¹è¶³å¤Ÿæ˜¾ç¤ºä¸€ä¸ªå®Œæ•´çš„趋势
      if (chartData.length === 0) {
        const now = new Date();
        for (let i = 0; i < 60; i++) {
        for (let i = 0; i < 24; i++) {
          // ç”Ÿæˆ60个点,代表5分钟的数据
          const time = new Date(now.getTime() - (59 - i) * 5000); // æ¯ä¸ªç‚¹é—´éš”5秒
          const time = new Date(now.getTime() - (24 - i) * 5000); // æ¯ä¸ªç‚¹é—´éš”5秒
          chartData.push({
            time: time.toLocaleTimeString(),
            value: (baseValue + Math.random() * fluctuation * 2 - fluctuation).toFixed(2)
@@ -255,7 +413,7 @@
          time,
          value: newValue
        });
        if (chartData.length > 60) {
        if (chartData.length > 24) {
          chartData.shift();
        }
@@ -323,10 +481,13 @@
      window.addEventListener('resize', () => {
        chart.resize();
      });
      onUnmounted(() => {
        clearInterval(intervalId);
      window.addEventListener('resize', () => {
        chart.resize();
      });
    };
    const hydraulicOilTemperatureData: any[] = [];
    const hydraulicOilPressureData: any[] = [];
@@ -345,14 +506,20 @@
    // initChart('hydraulicOilPressureChart', '液压油压', hydraulicOilPressureData, 'MPa', 150, 5);
    // initChart('mainMotorCurrentChart', '主电机电流', mainMotorCurrentData, 'A', 80, 3);
    initChart('screwSpeedChart', '螺杆转速', screwSpeedData, 'rpm', 100, 10);
    initChart('moldClampingForceChart', '锁模力', moldClampingForceData, 'kN', 1000, 50);
    initChart('injectionPressureChart', '注射压力', injectionPressureData, 'MPa', 1200, 80);
    initChart('moldClampingForceChart', '锁模压力', moldClampingForceData, 'Bar', 120, 10);
    initChart('injectionPressureChart', '注射压力', injectionPressureData, 'Bar', 80, 5);
    initChart('injectionSpeedChart', '注射速度', injectionSpeedData, 'mm/s', 150, 10);
    initChart('barrelTemperatureChart', '料筒温度', barrelTemperatureData, '°C', 240, 3);
    initChart('coolingWaterTemperatureChart', '冷却水温度', coolingWaterTemperatureData, '°C', 25, 2);
    initChart('coolingWaterTemperatureChart', '冷水机温度', coolingWaterTemperatureData, '°C', 20, 2);
    // initChart('coolingWaterFlowChart', '冷却水流量', coolingWaterFlowData, 'L/min', 30, 3);
    // initChart('ejectorPositionChart', '顶出位置', ejectorPositionData, 'mm', 50, 5);
    // initChart('cycleTimeChart', '循环时间', cycleTimeData, 's', 30, 2);
  },
  unmounted() {
    // æ¸…除定时器
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
  }
});
</script>
@@ -411,7 +578,7 @@
            <a-progress :percent="healthData.overallHealth" :show-info="false" :stroke-color="healthData.healthColor" />
          </div>
          <a-divider orientation="left">预测性维护建议</a-divider>
          <a-table :columns="maintenanceColumns" :data-source="maintenanceData" :pagination="false" size="small">
          <a-table ref="maintenanceTable" :columns="maintenanceColumns" :data-source="maintenanceData" :pagination="false" size="small" :scroll="{ y: 150 }">
            <template #urgency="{ text }">
              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
            </template>
@@ -426,35 +593,35 @@
      <a-card class="mb-4" title="设备数据">
        <a-row :gutter="[16, 16]">
          <a-col :span="4">
            <a-statistic :value="healthData.injectionCount" suffix="min" title="总开机时间">
            <a-statistic :value="healthData.injectionCount.toFixed(2)" suffix="h" title="总开机时间">
              <template #prefix>
                <LineChartOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic :value="healthData.clampingCount" suffix="次" title="总循环次数">
            <a-statistic :value="healthData.clampingCount.toFixed(0)" suffix="次" title="总循环次数">
              <template #prefix>
                <LineChartOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic :value="healthData.productionCycle" suffix="s" title="生产周期">
            <a-statistic :value="healthData.productionCycle.toFixed(0)" suffix="s" title="平均生产周期">
              <template #prefix>
                <FieldTimeOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic :value="healthData.energyConsumption" suffix="kWh" title="能耗">
            <a-statistic :value="healthData.energyConsumption.toFixed(2)" suffix="kWh" title="当日累积能耗">
              <template #prefix>
                <ThunderboltOutlined />
              </template>
            </a-statistic>
          </a-col>
          <a-col :span="4">
            <a-statistic :value="healthData.yieldRate" suffix="%" title="良品率">
            <a-statistic :value="healthData.yieldRate.toFixed(0)" suffix="模" title="当前产量">
              <template #prefix>
                <CheckCircleOutlined />
              </template>
eims-ui/apps/web-antd/src/views/eims/predictive-maintenance/smt-machine-detail.vue
@@ -68,13 +68,15 @@
            />
          </div>
          <a-divider />
          <a-divider orientation="left">预测性维护建议</a-divider>
          <a-table
            ref="maintenanceTable"
            :columns="maintenanceColumns"
            :data-source="maintenanceData"
            :pagination="false"
            size="small"
            :scroll="{ y: 150 }"
          >
            <template #urgency="{ text }">
              <a-tag :color="getUrgencyColor(text)">{{ text }}</a-tag>
@@ -89,42 +91,42 @@
        <a-card title="设备数据" class="mb-4">
          <a-row :gutter="[16, 16]">
            <a-col :span="4">
              <a-statistic title="X轴总移动距离" :value="healthData.xAxisTravel" suffix="km">
              <a-statistic title="X轴总移动距离" :value="healthData.xAxisTravel.toFixed(2)" suffix="km">
                <template #prefix>
                  <LineChartOutlined />
                </template>
              </a-statistic>
            </a-col>
            <a-col :span="4">
              <a-statistic title="Y轴总移动距离" :value="healthData.yAxisTravel" suffix="km">
              <a-statistic title="Y轴总移动距离" :value="healthData.yAxisTravel.toFixed(2)" suffix="km">
                <template #prefix>
                  <LineChartOutlined />
                </template>
              </a-statistic>
            </a-col>
            <a-col :span="4">
              <a-statistic title="卡带次数" :value="healthData.tapeJamCount" suffix="次">
              <a-statistic title="卡带次数" :value="healthData.tapeJamCount.toFixed(0)" suffix="次">
                <template #prefix>
                  <WarningOutlined />
                </template>
              </a-statistic>
            </a-col>
            <a-col :span="4">
              <a-statistic title="卡料次数" :value="healthData.materialJamCount" suffix="次">
              <a-statistic title="卡料次数" :value="healthData.materialJamCount.toFixed(0)" suffix="次">
                <template #prefix>
                  <WarningOutlined />
                </template>
              </a-statistic>
            </a-col>
            <a-col :span="4">
              <a-statistic title="拼板数" :value="healthData.panelCount" suffix="块">
              <a-statistic title="拼板数" :value="healthData.panelCount.toFixed(0)" suffix="块">
                <template #prefix>
                  <AppstoreOutlined />
                </template>
              </a-statistic>
            </a-col>
            <a-col :span="4">
              <a-statistic title="出错停机时间" :value="healthData.downtime" suffix="秒">
              <a-statistic title="出错停机时间" :value="healthData.downtime.toFixed(1)" suffix="秒">
                <template #prefix>
                  <FieldTimeOutlined />
                </template>
@@ -214,7 +216,7 @@
</template>
<script lang="ts">
import { defineComponent, reactive, onMounted, onUnmounted } from 'vue';
import { defineComponent, reactive, onMounted, onUnmounted, ref, nextTick } from 'vue';
import * as echarts from 'echarts';
import {
  LineChartOutlined,
@@ -223,6 +225,7 @@
  FieldTimeOutlined
} from '@ant-design/icons-vue';
import img from '#/assets/images/JUKI.png'
import { getDeviceDataSmt, updateDeviceData, initDeviceData } from '#/api/eims/equ/deviceData'
export default defineComponent({
  name: 'SmtMachineDetail',
@@ -244,20 +247,20 @@
      healthColor: '#52c41a',
      predictedLife: 635,
      riskLevel: '低风险',
      riskColor: '#52c41a',
      riskColor: '#1a7ac4',
      xAxisTravel: 300.179,
      yAxisTravel: 233.392,
      tapeJamCount: 6,
      materialJamCount: 15,
      panelCount: 2480,
      downtime: 4.5,
      // ç”¨äºŽç´¯åŠ çš„æ•°æ®
      accumulatedXAxisTravel: 300.179,
      accumulatedYAxisTravel: 233.392,
      accumulatedTapeJamCount: 6,
      accumulatedMaterialJamCount: 15,
      accumulatedPanelCount: 2480,
      accumulatedDowntime: 4.5
      // // ç”¨äºŽç´¯åŠ çš„æ•°æ®
      // accumulatedXAxisTravel: 300.179,
      // accumulatedYAxisTravel: 233.392,
      // accumulatedTapeJamCount: 6,
      // accumulatedMaterialJamCount: 15,
      // accumulatedPanelCount: 2480,
      // accumulatedDowntime: 4.5
    });
    const maintenanceColumns = [
@@ -293,25 +296,65 @@
      {
        key: '1',
         type: '贴装头维护',
        content: '吸嘴真空压力校准',
        suggestedTime: '2024-04-05',
         type: '1号贴装系统维护',
        content: '吸嘴真空压力偏低',
        suggestedTime: '2025-07-05',
        urgency: '中等'
      },
      {
        key: '6',
        type: '4号贴装系统维护',
        content: 'T轴马达寿命告急',
        suggestedTime: '2025-07-05',
        urgency: '中等'
      },
      {
        key: '2',
               type: '运动系统保养',
        content: 'X/Y轴伺服电机润滑检查',
        suggestedTime: '2024-03-20',
        suggestedTime: '2025-06-20',
        urgency: '低'
      },
      {
        key: '3',
        type: '供料系统检查',
        content: '飞达卡带/卡料次数清零',
        suggestedTime: '2024-03-10',
        suggestedTime: '2025-06-10',
        urgency: '低'
      }
      },
      {
        key: '4',
        type: '2号贴装系统维护',
        content: '真空压力不稳定',
        suggestedTime: '2025-07-05',
        urgency: '低'
      },
      {
        key: '5',
        type: '3号贴装系统维护',
        content: 'Z轴马达电流异常',
        suggestedTime: '2025-07-05',
        urgency: '低'
      },
      {
        key: '7',
        type: '5号贴装头维护',
        content: '真空压力不稳定',
        suggestedTime: '2025-07-05',
        urgency: '低'
      },
      {
        key: '8',
        type: '6号贴装头维护',
        content: '真空压力不稳定',
        suggestedTime: '2025-07-05',
        urgency: '低'
      },
    ]);
    const getUrgencyColor = (urgency: string) => {
@@ -326,6 +369,27 @@
          return 'default';
      }
    };
     const fetchDeviceData = async () => {
      try {
        const res = await getDeviceDataSmt();
        Object.assign(healthData, res);
      } catch (error) {
        console.error('获取设备数据失败:', error);
      }
    };
    let deviceDataInterval: number | undefined;
    fetchDeviceData();
     deviceDataInterval = setInterval(async () => {
        try {
          fetchDeviceData();
        } catch (error) {
          console.error('更新设备数据失败:', error);
        }
      }, 3000);
    const sparePartColumns = [
      {
@@ -356,33 +420,111 @@
    const sparePartData = reactive([
      {
        key: '1',
        name: 'X轴伺服电机',
        name: '1号贴装系统T轴伺服电机',
        currentLife: '15000小时',
        remainingLife: '4354小时',
        remainingLife: '1451小时',
        status: '预警'
      },
      {
        key: '5',
        name: '1号贴装系统Z轴伺服电机',
        currentLife: '15000小时',
        remainingLife: '7521小时',
        status: '良好'
      },
      {
        key: '9',
        name: '1号贴装系统真空电磁阀',
        currentLife: '10000小时',
        remainingLife: '2154小时',
        status: '良好'
      },
      {
        key: '2',
        name: '吸嘴',
        name: '1号贴装头',
        currentLife: '1000000次',
        remainingLife: '425000次',
        remainingLife: '425542次',
        status: '良好'
      },
      {
        key: '6',
        name: '2号贴装系统T轴伺服电机',
        currentLife: '15000小时',
        remainingLife: '7540小时',
        status: '良好'
      },
      {
        key: '7',
        name: '2号贴装系统Z轴伺服电机',
        currentLife: '15000小时',
        remainingLife: '7521小时',
        status: '良好'
      },
      {
        key: '9',
        name: '2号贴装系统真空电磁阀',
        currentLife: '10000小时',
        remainingLife: '2154小时',
        status: '良好'
      },
      {
        key: '8',
        name: '2号贴装头',
        currentLife: '1000000次',
        remainingLife: '751251次',
        status: '良好'
      },
      {
        key: '3',
        name: '飞达',
        currentLife: '96个月',
        remainingLife: '48个月',
        remainingLife: '43个月',
        status: '良好'
      }
      },
    ]);
    const historyData = reactive([
      {
        id: '1',
        date: '2025-07-22',
        type: '定期保养',
        description: '完成月度保养,丝杆导轨注油,抛料清理',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-06-18',
        type: '定期保养',
        description: '完成月度保养,易损件更换',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-05-15',
        type: '定期保养',
        description: '完成季度保养,检查运动系统润滑',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-04-20',
        type: '定期保养',
        description: '完成月度保养,防尘过滤网清理,导轨注油',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-03-16',
        type: '定期保养',
        description: '完成月度保养,真空值校准',
        color: 'green'
      },
      {
        id: '1',
        date: '2025-02-13',
        type: '定期保养',
        description: '完成月度保养,吸嘴检查更换,抛料清理,相机参数校准',
        color: 'green'
      },
      {
@@ -394,9 +536,9 @@
      },
      {
        id: '3',
        date: '2024-12-01',
        date: '2025-01-15',
        type: '定期保养',
        description: '完成年度保养,校准视觉系统',
        description: '完成年度保养,贴装系统校准,易损件更换,校准视觉系统',
        color: 'green'
      }
    ]);
@@ -420,34 +562,70 @@
    };
    let healthDataInterval: number | undefined;
    let scrollInterval: number | undefined;
    const maintenanceTable = ref<HTMLElement | null>(null);
    const updateHealthData = () => {
      healthData.accumulatedXAxisTravel = parseFloat((healthData.accumulatedXAxisTravel + Math.random() * 0.01).toFixed(3));
      healthData.accumulatedYAxisTravel = parseFloat((healthData.accumulatedYAxisTravel + Math.random() * 0.01).toFixed(3));
      healthData.accumulatedTapeJamCount = healthData.accumulatedTapeJamCount + Math.random() * 0.005;
      healthData.accumulatedMaterialJamCount = healthData.accumulatedMaterialJamCount + Math.random() * 0.005;
      healthData.accumulatedPanelCount =healthData.accumulatedPanelCount + Math.random() * 0.1;
      healthData.accumulatedDowntime = parseFloat((healthData.accumulatedDowntime + Math.random() * 0.01).toFixed(1));
    const startScroll = () => {
      if (!maintenanceTable.value) return;
      // æ›´æ–°æ˜¾ç¤ºçš„æ•°æ®
      healthData.xAxisTravel = healthData.accumulatedXAxisTravel;
      healthData.yAxisTravel = healthData.accumulatedYAxisTravel;
      healthData.tapeJamCount = Math.round(healthData.accumulatedTapeJamCount);
      healthData.materialJamCount = Math.round(healthData.accumulatedMaterialJamCount);
      healthData.panelCount = Math.round( healthData.accumulatedPanelCount);
      healthData.downtime = healthData.accumulatedDowntime;
      const tableBody = maintenanceTable.value.$el.querySelector('.ant-table-body');
      if (!tableBody) return;
      const scrollHeight = tableBody.scrollHeight;
      const clientHeight = tableBody.clientHeight;
      if (scrollHeight <= clientHeight) {
        // å†…容未溢出,无需滚动
        return;
      }
      let currentScrollTop = 0;
      scrollInterval = setInterval(() => {
        currentScrollTop += 1; // æ¯æ¬¡æ»šåЍ1px
        if (currentScrollTop >= scrollHeight - clientHeight) {
          currentScrollTop = 0; // æ»šåŠ¨åˆ°åº•éƒ¨åŽå›žåˆ°é¡¶éƒ¨
        }
        tableBody.scrollTop = currentScrollTop;
      }, 50); // æ¯50毫秒滚动一次
    };
    // const updateHealthData = () => {
    //   healthData.accumulatedXAxisTravel = parseFloat((healthData.accumulatedXAxisTravel + Math.random() * 0.01).toFixed(3));
    //   healthData.accumulatedYAxisTravel = parseFloat((healthData.accumulatedYAxisTravel + Math.random() * 0.01).toFixed(3));
    //   healthData.accumulatedTapeJamCount = healthData.accumulatedTapeJamCount + Math.random() * 0.005;
    //   healthData.accumulatedMaterialJamCount = healthData.accumulatedMaterialJamCount + Math.random() * 0.005;
    //   healthData.accumulatedPanelCount =healthData.accumulatedPanelCount + Math.random() * 0.1;
    //   healthData.accumulatedDowntime = parseFloat((healthData.accumulatedDowntime + Math.random() * 0.01).toFixed(1));
    //   // æ›´æ–°æ˜¾ç¤ºçš„æ•°æ®
    //   healthData.xAxisTravel = healthData.accumulatedXAxisTravel;
    //   healthData.yAxisTravel = healthData.accumulatedYAxisTravel;
    //   healthData.tapeJamCount = Math.round(healthData.accumulatedTapeJamCount);
    //   healthData.materialJamCount = Math.round(healthData.accumulatedMaterialJamCount);
    //   healthData.panelCount = Math.round( healthData.accumulatedPanelCount);
    //   healthData.downtime = healthData.accumulatedDowntime;
    // };
    onMounted(() => {
      // åˆå§‹æ›´æ–°ä¸€æ¬¡æ•°æ®
      updateHealthData();
    //  updateHealthData();
      // æ¯5秒更新一次设备数据
      healthDataInterval = setInterval(updateHealthData, 5000);
    //  healthDataInterval = setInterval(updateHealthData, 5000);
      nextTick(() => {
        startScroll();
      });
    });
    onUnmounted(() => {
      if (healthDataInterval) {
        clearInterval(healthDataInterval);
      }
      if (scrollInterval) {
        clearInterval(scrollInterval);
      }
       if (deviceDataInterval) {
        clearInterval(deviceDataInterval);
      }
    });
@@ -461,7 +639,8 @@
      historyData,
      getStatusColor,
      getUrgencyColor,
      handleMaintenance
      handleMaintenance,
      maintenanceTable
    };
  },
  components: {
@@ -487,7 +666,7 @@
            time,
            value: newValue
          });
          if (s.data.length > 60) {
          if (s.data.length > 24) {
            s.data.shift();
          }
        });
@@ -560,8 +739,8 @@
      seriesConfig.forEach(s => {
        s.data = [];
        // ç”Ÿæˆåˆå§‹æ•°æ®ç‚¹ï¼ˆ60个点,5分钟数据)
      for (let i = 0; i < 60; i++) {
        const now = new Date(Date.now() - (60 - i) * 5000); // ç”Ÿæˆè¿‡åŽ»5分钟的数据
      for (let i = 0; i < 24; i++) {
        const now = new Date(Date.now() - (24 - i) * 5000); // ç”Ÿæˆè¿‡åŽ»5分钟的数据
        const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
        const newValue = (s.baseValue + (Math.random() * 2 - 1) * s.fluctuation).toFixed(2);
        s.data.push({
eims/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java
@@ -505,6 +505,18 @@
        return atomic.incrementAndGet();
    }
    /**
     * é€’增原子值
     *
     * @param key Redis键
     * @return å½“前值
     */
    public static long incrAtomicValueByNum(String key, long num) {
        RAtomicLong atomic = CLIENT.getAtomicLong(key);
        return atomic.addAndGet(num);
    }
    /**
     * é€’减原子值
     *
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/DeviceDataController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
package org.dromara.eims.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.redis.utils.RedisUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * è®¾å¤‡æ•°æ®æŽ§åˆ¶å™¨
 *
 * @author Lion Li
 * @date 2024-07-26
 */
@RestController
@RequestMapping("/eims/deviceData")
@RequiredArgsConstructor
public class DeviceDataController extends BaseController {
    private static final String DEVICE_DATA_PREFIX = "eims:device:data:";
    /**
     * èŽ·å–è®¾å¤‡æ•°æ®
     */
    @GetMapping("/get")
    public R<Map<String, Double>> getDeviceData() {
        Map<String, Double> deviceData = new HashMap<>();
        deviceData.put("xAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "xAxisTravel") / 100000.0);
        deviceData.put("yAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "yAxisTravel") / 100000.0);
        deviceData.put("zAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "zAxisTravel") / 100000.0);
        deviceData.put("toolChangeCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "toolChangeCount") / 10.0);
        deviceData.put("partCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "partCount") / 100000.0);
        deviceData.put("downtime", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "downtime") / 10.0);
        return R.ok(deviceData);
    }
    /**
     * èŽ·å–è®¾å¤‡æ•°æ®
     */
    @GetMapping("/getSmt")
    public R<Map<String, Double>> getDeviceDataSmt() {
        Map<String, Double> deviceData = new HashMap<>();
        deviceData.put("xAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtXAxisTravel") / 1000.0);
        deviceData.put("yAxisTravel", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtYAxisTravel") / 1000.0);
        deviceData.put("tapeJamCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount") / 1000.0);
        deviceData.put("materialJamCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount") / 1000.0);
        deviceData.put("panelCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount") / 1000.0);
        deviceData.put("downtime", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime") / 100.0);
        return R.ok(deviceData);
    }
    /**
     *  injectionCount: 495 * 24 * 60 + 19 * 60 + 44, // æ³¨å°„次数,转换为分钟
     *       clampingCount: 545636, // åˆæ¨¡æ¬¡æ•° // è·Ÿéšäº§é‡ 50s加一次
     *       productionCycle: 45, // ç”Ÿäº§å‘¨æœŸ
     *       energyConsumption: 64, // èƒ½è€—
     *       yieldRate: 354, // äº§é‡   50秒增加一模
     *       downtime: 120, // å‡ºé”™åœæœºæ—¶é—´
     *
     */
    /**
     * èŽ·å–è®¾å¤‡æ•°æ®
     */
    @GetMapping("/getInj")
    public R<Map<String, Double>> getDeviceDataInj() {
        Map<String, Double> deviceData = new HashMap<>();
        deviceData.put("injectionCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "injectionCount") / 3600.0);
        deviceData.put("clampingCount", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "clampingCount") / 10.0);
        deviceData.put("productionCycle", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "productionCycle") / 10.0);
        deviceData.put("energyConsumption", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption") / 1000.0);
        deviceData.put("yieldRate", RedisUtils.getAtomicValue(DEVICE_DATA_PREFIX + "yieldRate") / 10.0);
        return R.ok(deviceData);
    }
    /**
     * åˆå§‹åŒ–设备数据
     */
    @PostMapping("/init")
    public R<Void> initDeviceData() {
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtXAxisTravel", 300282L);  // 50/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtYAxisTravel", 233524L);  // 45/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount", 6000);      // 5/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 15000); // 5/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount", 2481000); // 100/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime", 450); //5/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "injectionCount", 43848000L);  // 5/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "clampingCount", 5456360L);  // 1/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "productionCycle", 450);
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption", 64000); // 7/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "yieldRate", 3540); // 1/5s
        return R.ok();
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/AutoApproveRepairJob.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
package org.dromara.eims.job;
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
import com.aizuda.snailjob.client.model.ExecuteResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.dromara.common.core.constant.DictConstants;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.eims.domain.EimsRepairRes;
import org.dromara.eims.domain.EimsRepairFb;
import org.dromara.eims.mapper.EimsRepairResMapper;
import org.dromara.eims.mapper.EimsRepairFbMapper;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@Component
@RequiredArgsConstructor
@JobExecutor(name = "autoApproveRepairJob")
public class AutoApproveRepairJob {
    private final EimsRepairResMapper repairResMapper;
    private final EimsRepairFbMapper repairFbMapper;
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public ExecuteResult jobExecute(JobArgs jobArgs) {
        // æŸ¥è¯¢å·²å®Œæˆï¼ˆstatus等于3)且结束时间超过三天以上的维修单
        Date threeDaysAgo = DateUtils.addDays(DateUtils.getNowDate(), -3);
        LambdaQueryWrapper<EimsRepairRes> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EimsRepairRes::getStatus, DictConstants.REPAIR_RES_STATUS_DETAIL.WANCHENG)
                    .le(EimsRepairRes::getEndTime, threeDaysAgo);
        List<EimsRepairRes> repairOrders = repairResMapper.selectList(queryWrapper);
        for (EimsRepairRes order : repairOrders) {
            // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨å¥½è¯„反馈
            LambdaQueryWrapper<EimsRepairFb> fbQueryWrapper = new LambdaQueryWrapper<>();
            fbQueryWrapper.eq(EimsRepairFb::getResId, order.getId())
                          .eq(EimsRepairFb::getRepairSatisfaction, 1);
            Long count = repairFbMapper.selectCount(fbQueryWrapper);
            // å°†ç»´ä¿®å•状态更新为已评价
            order.setStatus(DictConstants.REPAIR_RES_STATUS_DETAIL.PINGJIA);
            repairResMapper.updateById(order);
            if (count == 0) {
                // æ’入一条repairSatisfaction为1的反馈数据
                EimsRepairFb feedback = new EimsRepairFb();
                feedback.setResId(order.getId());
                feedback.setRepairSatisfaction("1"); // é»˜è®¤å¥½è¯„
                feedback.setRemark("系统自动好评"); // å¯ä»¥æ ¹æ®éœ€è¦è®¾ç½®åé¦ˆå†…容
                feedback.setCreateTime(DateUtils.getNowDate());
                repairFbMapper.insert(feedback);
            }
        }
        return ExecuteResult.success("自动好评维修单任务执行成功");
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/DeviceDataIncrJob.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package org.dromara.eims.job;
import org.dromara.common.redis.utils.RedisUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.Calendar;
@Configuration
@EnableScheduling
public class DeviceDataIncrJob {
    private static final String DEVICE_DATA_PREFIX = "eims:device:data:";
    /**
     * å®šæ—¶æ›´æ–°è®¾å¤‡æ•°æ®
     * æ¯å¤©æ—©ä¸Š8点到下午5点之间,每小时更新一次
     */
    @Scheduled(cron = "0/5 * 8-17 * * ?")
    public void updateDeviceDataScheduled() {
        System.out.println("执行定时任务,更新设备数据:::");
        // æ£€æŸ¥å½“前时间是否在早上8点到下午5点之间
        Calendar now = Calendar.getInstance();
        int hourOfDay = now.get(Calendar.HOUR_OF_DAY);
        if (hourOfDay >= 8 && hourOfDay < 17) {
            // æ›´æ–°å¹…度
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "xAxisTravel", 83L); // æ¯å¤©åŠ 6小时,对应Redis中加60
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "yAxisTravel", 833L); // æ¯å¤©åŠ 60次
            // toolChangeCount å’Œ downtime ä¸æ³¢åŠ¨ï¼Œæ‰€ä»¥ä¸è¿›è¡Œå¢žé‡æ“ä½œ
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "partCount", 210L); // æ¯å¤©åŠ 15个
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtXAxisTravel", 300282L);  // 50/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtYAxisTravel", 233524L);  // 45/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount", 6000);      // 5/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 15000); // 5/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount", 2481000); // 100/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime", 450); //5/5s
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtXAxisTravel", 50L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtYAxisTravel", 45L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtTapeJamCount", 5L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 5L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtPanelCount", 100L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "smtDowntime", 1L);
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "injectionCount", 43848000L);  // 5/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "clampingCount", 5456360L);  // 1/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "productionCycle", 450);
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption", 64000); // 7/5s
//            RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "yieldRate", 3540); // 1/5s
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "injectionCount", 5L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "clampingCount", 1L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "energyConsumption", 10L);
            RedisUtils.incrAtomicValueByNum(DEVICE_DATA_PREFIX + "yieldRate", 1L);
        }
    }
    // æ–°å¢žä¸€ä¸ªå®šæ—¶å™¨ï¼Œç¬¬å¤©é›¶ç‚¹æ¸…é›¶
    @Scheduled(cron = "0 0 0 * * ?")
    public void resetDeviceDataScheduled() {
        System.out.println("执行定时任务,重置设备数据:::");
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtTapeJamCount", 0);      // 5/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtMaterialJamCount", 0); // 5/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtPanelCount", 0); // 100/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "smtDowntime", 0); //5/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "energyConsumption", 0); // 7/5s
        RedisUtils.setAtomicValue(DEVICE_DATA_PREFIX + "yieldRate", 0); // 1/5s
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java
@@ -21,7 +21,6 @@
import org.dromara.eims.domain.vo.EimsEquImportVo;
import org.dromara.eims.domain.vo.EimsEquVo;
import org.dromara.eims.service.IEimsEquService;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.service.ISysUserService;
import java.util.List;