| | |
| | | </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> |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | </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, |
| | |
| | | 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() { |
| | |
| | | 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 = [ |
| | |
| | | type: '例行保养', |
| | | content: '检查主轴润滑系统', |
| | | suggestedTime: '2025-07-15', |
| | | urgency: '中等' |
| | | urgency: '低' |
| | | }, |
| | | { |
| | | key: '2', |
| | |
| | | }, |
| | | { |
| | | 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: '低' |
| | | } |
| | | ]); |
| | |
| | | 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: '状态', |
| | |
| | | |
| | | 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' |
| | | } |
| | | ]); |
| | | |
| | |
| | | // 实际项目中这里会调用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, |
| | |
| | | historyData, |
| | | getStatusColor, |
| | | getUrgencyColor, |
| | | handleMaintenance |
| | | handleMaintenance, |
| | | maintenanceTable |
| | | }; |
| | | }, |
| | | |
| | |
| | | time, |
| | | value: newValue |
| | | }); |
| | | if (s.data.length > 60) { |
| | | if (s.data.length > 12) { |
| | | s.data.shift(); |
| | | } |
| | | }); |
| | |
| | | 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({ |
| | |
| | | |
| | | }; |
| | | |
| | | |
| | | // 运动系统监测 |
| | | 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' }, |
| | |
| | | initChart('coolantTemperatureChart', '冷却液温度', [ |
| | | { name: '温度', data: [], unit: '°C', baseValue: 28, fluctuation: 2, color: '#5470C6' }, |
| | | ]); |
| | | |
| | | |
| | | } |
| | | |
| | | }); |
| | |
| | | .device-detail-container { |
| | | padding: 16px; |
| | | background: #f0f2f5; |
| | | } |
| | | .device-image-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 330px; |
| | | } |
| | | |
| | | .mt-4 { |