// 检查 ECharts 是否加载完成 function checkEchartsLoaded(callback, maxAttempts = 10) { let attempts = 0; const checkInterval = setInterval(() => { attempts++; if (window.echarts) { clearInterval(checkInterval); callback(); } else if (attempts >= maxAttempts) { clearInterval(checkInterval); console.error('ECharts 加载失败'); alert('图表组件加载失败,请刷新页面重试'); } }, 500); } // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', function() { // 等待 ECharts 加载完成后初始化图表 checkEchartsLoaded(() => { // 初始化所有图表 initCharts(); // 启动数据更新循环 setInterval(updateData, 30000); }); }); // 初始化所有图表 function initCharts() { initEquipmentTopology(); initGanttChart(); initFaultTrend(); initEfficiencyChart(); initQualityIssues(); updateHeaderData(); updateOrderList(); updateFaultList(); } // 更新头部数据 function updateHeaderData() { document.getElementById('oee').innerText = MockData.random(80, 95) + '%'; document.getElementById('production').innerText = MockData.random(2000, 3000).toLocaleString(); document.getElementById('quality').innerText = (MockData.random(975, 995) / 10) + '%'; document.getElementById('downtime').innerText = (MockData.random(15, 35) / 10) + '%'; } // 初始化设备拓扑图 function initEquipmentTopology() { const dom = document.getElementById('equipment-topology'); if (!dom) { console.error('找不到设备拓扑图容器'); return; } try { const chart = echarts.init(dom); const categories = ['运行', '停机', '故障', '维护']; const option = { tooltip: {}, series: [{ type: 'graph', layout: 'circular', symbolSize: 60, roam: true, focusNodeAdjacency: true, categories: categories.map(name => ({ name: name })), label: { show: true, color: '#fff' }, edgeSymbol: ['circle', 'arrow'], edgeSymbolSize: [4, 10], data: [ {name: '成型机A', value: 'running', category: '运行', symbolSize: 70}, {name: '成型机B', value: 'running', category: '运行', symbolSize: 70}, {name: '硫化机A', value: 'warning', category: '故障', symbolSize: 70}, {name: '硫化机B', value: 'running', category: '运行', symbolSize: 70}, {name: '检测台A', value: 'maintenance', category: '维护', symbolSize: 60}, {name: '检测台B', value: 'running', category: '运行', symbolSize: 60}, {name: '包装机', value: 'running', category: '运行', symbolSize: 65} ], links: [ {source: '成型机A', target: '硫化机A'}, {source: '成型机B', target: '硫化机B'}, {source: '硫化机A', target: '检测台A'}, {source: '硫化机B', target: '检测台B'}, {source: '检测台A', target: '包装机'}, {source: '检测台B', target: '包装机'} ], itemStyle: { borderColor: '#fff', borderWidth: 1, shadowBlur: 10, shadowColor: 'rgba(30, 84, 231, 0.5)' }, lineStyle: { color: '#1890ff', width: 2 } }] }; chart.setOption(option); } catch (error) { console.error('初始化设备拓扑图失败:', error); } } // 初始化甘特图 function initGanttChart() { const dom = document.getElementById('gantt-chart'); if (!dom) { console.error('找不到甘特图容器'); return; } try { const chart = echarts.init(dom); const option = { tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, formatter: function(params) { const data = params[0]; return `工单进度:${data.value}%
预计完成时间:${new Date().toLocaleDateString()}`; } }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: { type: 'value', axisLabel: { color: '#fff' } }, yAxis: { type: 'category', data: ['工单1', '工单2', '工单3', '工单4'], axisLabel: { color: '#fff' } }, series: [{ name: '完成', type: 'bar', stack: 'total', itemStyle: { color: '#52c41a' }, data: [80, 60, 40, 20] }, { name: '剩余', type: 'bar', stack: 'total', itemStyle: { color: '#1890ff' }, data: [20, 40, 60, 80] }] }; chart.setOption(option); } catch (error) { console.error('初始化甘特图失败:', error); } } // 初始化故障趋势图 function initFaultTrend() { const dom = document.getElementById('fault-trend'); if (!dom) { console.error('找不到故障趋势图容器'); return; } try { const chart = echarts.init(dom); const option = { tooltip: { trigger: 'axis', formatter: function(params) { return `${params[0].name}
故障次数:${params[0].value}次
同比上周:${params[0].value > 4 ? '↑' : '↓'}${Math.abs(params[0].value - 4)}次`; } }, xAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], axisLabel: { color: '#fff' } }, yAxis: { type: 'value', axisLabel: { color: '#fff' } }, series: [{ data: [5, 3, 4, 2, 6, 4, 3], type: 'line', smooth: true, itemStyle: { color: '#ff4d4f' }, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(255, 77, 79, 0.3)' }, { offset: 1, color: 'rgba(255, 77, 79, 0)' }]) } }] }; chart.setOption(option); } catch (error) { console.error('初始化故障趋势图失败:', error); } } // 初始化效率图表 function initEfficiencyChart() { const dom = document.getElementById('efficiency-chart'); if (!dom) { console.error('找不到效率图表容器'); return; } try { const chart = echarts.init(dom); const {dates, values} = MockData.getEfficiencyData(); const option = { title: { text: '生产效率趋势', textStyle: { color: '#fff', fontSize: 14 }, subtextStyle: { color: '#66a3ff' } }, grid: { top: 50, right: 30, bottom: 30, left: 50 }, tooltip: { trigger: 'axis' }, xAxis: { type: 'category', data: dates, axisLabel: { color: '#fff' } }, yAxis: { type: 'value', min: 70, axisLabel: { color: '#fff' } }, series: [{ data: values, type: 'line', smooth: true, itemStyle: { color: '#1890ff' } }] }; chart.setOption(option); } catch (error) { console.error('初始化效率图表失败:', error); } } // 初始化质量问题图表 function initQualityIssues() { const dom = document.getElementById('quality-issues'); if (!dom) { console.error('找不到质量问题图表容器'); return; } try { const chart = echarts.init(dom); const issues = MockData.getQualityIssues(); const option = { title: { text: '质量问题分布', textStyle: { color: '#fff', fontSize: 14 } }, legend: { orient: 'vertical', right: 10, top: 'center', textStyle: { color: '#fff' } }, tooltip: { trigger: 'item' }, series: [{ type: 'pie', radius: ['40%', '70%'], center: ['40%', '50%'], roseType: 'radius', data: issues.map(issue => ({ name: issue.name, value: issue.value })), itemStyle: { borderColor: '#0a1128', borderWidth: 2 }, label: { color: '#fff' } }] }; chart.setOption(option); } catch (error) { console.error('初始化质量问题图表失败:', error); } } // 更新工单列表 function updateOrderList() { const tbody = document.getElementById('order-list-body'); const orders = MockData.getOrders(); tbody.innerHTML = orders.map(order => ` ${order.id} ${order.model} ${order.planned} ${order.completed} ${order.status === 'delayed' ? '延迟' : '正常'} `).join(''); } // 更新故障列表 function updateFaultList() { const container = document.getElementById('fault-list-container'); const faults = MockData.getFaults(); container.innerHTML = faults.map(fault => `
${fault.equipment} - ${fault.code}
发生时间:${fault.time}
状态:${fault.status}
`).join(''); } // 定时更新数据 function updateData() { updateHeaderData(); updateOrderList(); updateFaultList(); // 重新初始化图表以更新数据 initEfficiencyChart(); initQualityIssues(); initFaultTrend(); }