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