// 项目管理分析页面 let expenditureTrendChart = null; let expenditureProportionChart = null; let projectRiskChart = null; let riskAnalysisChart = null; let civilSpecialtyChart = null; let electricalSpecialtyChart = null; let bidCode = parent.parent.$('#bidPro').val(); // 获取当月第一天和最后一天 function getCurrentMonthRange() { const now = new Date(); const year = now.getFullYear(); const month = now.getMonth(); const firstDay = new Date(year, month, 1); const lastDay = new Date(year, month + 1, 0); const startDate = formatDate(firstDay); const endDate = formatDate(lastDay); return { startDate, endDate }; } const currentMonth = getCurrentMonthRange(); let queryParams = { projectId: bidCode, startTime: currentMonth.startDate, endTime: currentMonth.endDate, }; // 页面初始化 $(document).ready(function () { // 等待layui加载完成 layui.use(['laydate', 'layer'], function () { initDateRange(); // 初始化项目信息模块的图表 initRiskAnalysisChart(); initCivilSpecialtyChart(); initElectricalSpecialtyChart(); // 初始化其他模块的图表 initExpenditureTrendChart(); initExpenditureProportionChart(); initProjectRiskChart(); initWarningTable(); // 页面初始化时,按默认当月日期加载一次接口数据 refreshAllModules(); // 窗口大小改变时重新调整图表 window.addEventListener('resize', debounce(() => { if (riskAnalysisChart) riskAnalysisChart.resize(); if (civilSpecialtyChart) civilSpecialtyChart.resize(); if (electricalSpecialtyChart) electricalSpecialtyChart.resize(); if (expenditureTrendChart) expenditureTrendChart.resize(); if (expenditureProportionChart) expenditureProportionChart.resize(); if (projectRiskChart) projectRiskChart.resize(); }, 300)); }); }); // 防抖函数 function debounce(fn, delay) { let t = null; return function () { clearTimeout(t); t = setTimeout(() => fn.apply(this, arguments), delay); }; } // 获取左上角工序进度 function getProcessProgress() { const url = commonUrl + 'screen/largeScreen/sjNewProManage/getProProgress' + '?bidCode=' + (bidCode || '') + '&startTime=' + (queryParams.startTime || '') + '&endTime=' + (queryParams.endTime || ''); ajaxRequestGet(url, 'GET', true, function () { }, function (result) { if (result && result.data) { updateProcessProgress(result.data); } else if (result) { updateProcessProgress(result); } }, aqEnnable); } // 获取左上角风险分析饼图数据 function getRiskAnalysisChartData() { const url = commonUrl + 'screen/largeScreen/sjNewProManage/getRiskData' + '?bidCode=' + (bidCode || '') + '&startTime=' + (queryParams.startTime || '') + '&endTime=' + (queryParams.endTime || ''); ajaxRequestGet(url, 'GET', true, function () { }, function (result) { if (result) { updateRiskAnalysisChart(result); } else if (result && result.data) { updateRiskAnalysisChart(result.data); } }, aqEnnable); } // 获取右上侧折线图数据 // 获取土建和电气专业图表数据 function getLineChartData() { const url = commonUrl + 'screen/largeScreen/sjNewProManage/getProgressList' + '?bidCode=' + (bidCode || '') + '&startTime=' + (queryParams.startTime || '') + '&endTime=' + (queryParams.endTime || ''); ajaxRequestGet(url, 'GET', true, function () { }, function (result) { if (result && result.data) { updateSpecialtyCharts(result.data); } else if (result) { updateSpecialtyCharts(result); } }, aqEnnable); } // 获取项目支出趋势和项目支出占比 function getExpenditureTrendAndProportion() { const url = commonUrl + 'screen/largeScreen/sjNewProManage/getProjectCost' + '?bidCode=' + (bidCode || '') + '&startTime=' + (queryParams.startTime || '') + '&endTime=' + (queryParams.endTime || ''); ajaxRequestGet(url, 'GET', true, function () { }, function (result) { if (result && result.data) { updateExpenditureTrendChart(result.data); updateExpenditureProportionChart(result.data); } else if (result) { updateExpenditureTrendChart(result); updateExpenditureProportionChart(result); } }, aqEnnable); } // 获取项目风险饼图 function getProjectRiskChartData() { const url = commonUrl + 'screen/largeScreen/sjNewProManage/getProjectRisk' + '?bidCode=' + (bidCode || '') + '&startTime=' + (queryParams.startTime || '') + '&endTime=' + (queryParams.endTime || ''); ajaxRequestGet(url, 'GET', true, function () { }, function (result) { if (result && result.data) { updateProjectRiskChart(result.data); } else if (result) { updateProjectRiskChart(result.data); } }, aqEnnable); } // 获取分析预警 function getAnalysisWarning(txType) { // txType: "全部"传空字符串,其他传对应的中文 const txTypeParam = txType === 'all' ? '' : (txType === 'progress' ? '进度' : txType === 'cost' ? '成本' : txType === 'risk' ? '风险' : ''); const url = commonUrl + 'screen/largeScreen/sjNewProManage/getWarnList' + '?bidCode=' + (bidCode || '') + '&startTime=' + (queryParams.startTime || '') + '&endTime=' + (queryParams.endTime || '') + (txTypeParam ? '&txType=' + txTypeParam : ''); ajaxRequestGet(url, 'GET', true, function () { }, function (result) { console.log(result, '分析预警'); if (result && Array.isArray(result)) { updateWarningTable(result); } else if (result && result.data && Array.isArray(result.data)) { updateWarningTable(result.data); } else if (result && result.rows && Array.isArray(result.rows)) { updateWarningTable(result.rows); } }, aqEnnable); } // 更新工序进度数据 function updateProcessProgress(data) { if (!data) return; // 土建工序进度 // bdGx: 本段工序(土建总工序) // bdYwcGx: 本段已完成工序(土建已完成) const civilTotal = data.bdGx || '0'; const civilCompleted = data.bdYwcGx || '0'; $('#civilTotal').text(civilTotal); $('#civilCompleted').text(civilCompleted); // 电气工序进度 // dqGx: 当前工序(电气总工序) // dqYwcGx: 当前已完成工序(电气已完成) const electricalTotal = data.dqGx || '0'; const electricalCompleted = data.dqYwcGx || '0'; $('#electricalTotal').text(electricalTotal); $('#electricalCompleted').text(electricalCompleted); } // 刷新所有模块数据 function refreshAllModules() { // 调用工序进度接口 getProcessProgress(); // 调用风险分析饼图数据接口 getRiskAnalysisChartData(); // 调用土建和电气专业图表数据接口 getLineChartData(); // 调用项目支出趋势和项目支出占比接口 getExpenditureTrendAndProportion(); // 调用项目风险饼图接口 getProjectRiskChartData(); // 调用分析预警接口 getAnalysisWarning(currentWarningFilter); } // 初始化日期范围选择器(逻辑与工程质量分析保持一致) function initDateRange() { const laydate = layui.laydate; // 初始显示为当月范围 $('#dateRange').val(queryParams.startTime + ' ~ ' + queryParams.endTime); laydate.render({ elem: '#dateRange', type: 'date', range: true, format: 'yyyy-MM-dd', theme: 'dark', // laydate 内部使用 "起始 - 结束" 作为分隔符 value: queryParams.startTime + ' - ' + queryParams.endTime, done: function (value) { const resetToCurrentMonth = function () { const cur = getCurrentMonthRange(); queryParams.startTime = cur.startDate; queryParams.endTime = cur.endDate; $('#dateRange').val(cur.startDate + ' ~ ' + cur.endDate); refreshAllModules(); }; if (value && value.trim() !== '') { const dates = value.split(' - '); if (dates.length === 2) { const startDate = dates[0].trim(); const endDateStr = dates[1].trim(); // 回显到输入框(使用 ~,与质量分析一致) $('#dateRange').val(startDate + ' ~ ' + endDateStr); // 更新查询参数 queryParams.startTime = startDate; queryParams.endTime = endDateStr; // 日期变化后,重新拉取接口数据 refreshAllModules(); } else { resetToCurrentMonth(); } } else { resetToCurrentMonth(); } } }); } // 格式化日期 function formatDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return year + '-' + month + '-' + day; } // 查询数据 function queryData() { const dateRange = $('#dateRange').val(); if (!dateRange) { layui.layer.msg('请选择日期范围', { icon: 0 }); return; } // 点击查询按钮时,基于当前日期范围刷新接口数据 refreshAllModules(); layui.layer.msg('查询成功', { icon: 1, time: 1000 }); } // 加载数据 function loadData(dateRange) { // 模拟数据加载 // 实际应该调用API updateCharts(); } // 初始化风险分析饼图 function initRiskAnalysisChart() { riskAnalysisChart = echarts.init(document.getElementById('riskAnalysisChart')); const option = { tooltip: { trigger: 'item', backgroundColor: 'rgba(19, 51, 55, 0.9)', borderColor: 'rgba(0, 254, 252, 0.5)', borderWidth: 1, textStyle: { color: '#fff' }, formatter: '{b}: {c}个 ({d}%)' }, legend: { orient: 'vertical', right: 10, top: 'center', textStyle: { color: '#fff', fontSize: 12 }, itemWidth: 12, itemHeight: 8, itemGap: 10, formatter: function (name) { const item = option.series[0].data.find(d => d.name === name); return name + ' ' + (item ? item.value + '%' : ''); } }, series: [ { name: '风险分析', type: 'pie', radius: ['40%', '70%'], center: ['35%', '50%'], avoidLabelOverlap: false, itemStyle: { borderRadius: 5, borderColor: 'rgba(13, 34, 37, 0.8)', borderWidth: 2 }, label: { show: false }, emphasis: { label: { show: true, fontSize: 14, fontWeight: 'bold', color: '#fff' } }, data: [ { value: 0, name: '二级风险', itemStyle: { color: '#4A90E2' } }, { value: 0, name: '三级风险', itemStyle: { color: '#1CFFA3' } }, { value: 0, name: '四级风险', itemStyle: { color: '#00FEFC' } }, { value: 0, name: '五级风险', itemStyle: { color: '#FF9C65' } } ] } ], graphic: [ { type: 'text', left: '35%', top: '85%', style: { text: '今日风险数量 0个', textAlign: 'center', fill: '#fff', fontSize: 13 } } ] }; riskAnalysisChart.setOption(option); } // 更新风险分析饼图数据 function updateRiskAnalysisChart(data) { if (!riskAnalysisChart || !data) return; // 获取各风险等级的数量 const twoRisk = parseInt(data.twoRisk || 0); const threeRisk = parseInt(data.threeRisk || 0); const fourRisk = parseInt(data.fourRisk || 0); const fiveRisk = parseInt(data.fiveRisk || 0); // 计算总风险数量 const totalRisk = twoRisk + threeRisk + fourRisk + fiveRisk; // 计算百分比 let twoRiskPercent = 0; let threeRiskPercent = 0; let fourRiskPercent = 0; let fiveRiskPercent = 0; if (totalRisk > 0) { twoRiskPercent = (twoRisk / totalRisk * 100).toFixed(1); threeRiskPercent = (threeRisk / totalRisk * 100).toFixed(1); fourRiskPercent = (fourRisk / totalRisk * 100).toFixed(1); fiveRiskPercent = (fiveRisk / totalRisk * 100).toFixed(1); } // 更新图表数据 riskAnalysisChart.setOption({ series: [ { data: [ { value: parseFloat(twoRiskPercent), name: '二级风险', itemStyle: { color: '#4A90E2' } }, { value: parseFloat(threeRiskPercent), name: '三级风险', itemStyle: { color: '#1CFFA3' } }, { value: parseFloat(fourRiskPercent), name: '四级风险', itemStyle: { color: '#00FEFC' } }, { value: parseFloat(fiveRiskPercent), name: '五级风险', itemStyle: { color: '#FF9C65' } } ] } ], graphic: [ { type: 'text', left: '35%', top: '85%', style: { text: '今日风险数量 ' + totalRisk + '个', textAlign: 'center', fill: '#fff', fontSize: 13 } } ] }); } // 初始化土建专业双柱状图 function initCivilSpecialtyChart() { civilSpecialtyChart = echarts.init(document.getElementById('civilSpecialtyChart')); const option = { tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, backgroundColor: 'rgba(19, 51, 55, 0.9)', borderColor: 'rgba(0, 254, 252, 0.5)', borderWidth: 1, textStyle: { color: '#fff' }, formatter: function (params) { if (!params || !params.length) return ''; let html = `
${params[0].name}
`; params.forEach(p => { html += `
${p.seriesName} ${p.value}%
`; }); return html; } }, legend: { data: ['计划进度', '实际进度'], top: 8, right: 20, textStyle: { color: '#fff', fontSize: 12 }, itemWidth: 12, itemHeight: 8, itemGap: 15 }, grid: { top: '20%', left: '8%', right: '6%', bottom: '15%' }, xAxis: { type: 'category', data: [], axisLabel: { color: '#fff', fontSize: 10, rotate: 0 }, axisLine: { lineStyle: { color: '#5A6E71' } }, axisTick: { show: false } }, yAxis: { type: 'value', min: 0, max: 100, axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}%' }, axisLine: { lineStyle: { color: '#5A6E71' } }, splitLine: { lineStyle: { color: 'rgba(90, 110, 113, 0.3)', type: 'dashed' } } }, series: [ { name: '计划进度', type: 'bar', data: [], itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#4A90E2' }, { offset: 1, color: '#357ABD' } ]) }, barWidth: '30%' }, { name: '实际进度', type: 'bar', data: [], itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#1CFFA3' }, { offset: 1, color: '#19CC8A' } ]) }, barWidth: '30%' } ] }; civilSpecialtyChart.setOption(option); } // 初始化电气专业双柱状图 function initElectricalSpecialtyChart() { electricalSpecialtyChart = echarts.init(document.getElementById('electricalSpecialtyChart')); const option = { tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, backgroundColor: 'rgba(19, 51, 55, 0.9)', borderColor: 'rgba(0, 254, 252, 0.5)', borderWidth: 1, textStyle: { color: '#fff' }, formatter: function (params) { if (!params || !params.length) return ''; let html = `
${params[0].name}
`; params.forEach(p => { html += `
${p.seriesName} ${p.value}%
`; }); return html; } }, legend: { data: ['计划进度', '实际进度'], top: 8, right: 20, textStyle: { color: '#fff', fontSize: 12 }, itemWidth: 12, itemHeight: 8, itemGap: 15 }, grid: { top: '20%', left: '8%', right: '6%', bottom: '15%' }, xAxis: { type: 'category', data: [], axisLabel: { color: '#fff', fontSize: 10, rotate: 0 }, axisLine: { lineStyle: { color: '#5A6E71' } }, axisTick: { show: false } }, yAxis: { type: 'value', min: 0, max: 100, axisLabel: { color: '#fff', fontSize: 10, formatter: '{value}%' }, axisLine: { lineStyle: { color: '#5A6E71' } }, splitLine: { lineStyle: { color: 'rgba(90, 110, 113, 0.3)', type: 'dashed' } } }, series: [ { name: '计划进度', type: 'bar', data: [], itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#4A90E2' }, { offset: 1, color: '#357ABD' } ]) }, barWidth: '30%' }, { name: '实际进度', type: 'bar', data: [], itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#1CFFA3' }, { offset: 1, color: '#19CC8A' } ]) }, barWidth: '30%' } ] }; electricalSpecialtyChart.setOption(option); } // 更新土建和电气专业图表数据 function updateSpecialtyCharts(data) { if (!data) return; // 更新土建专业图表 if (civilSpecialtyChart) { const bdGx = data.bdGx || []; const bdPlanProgress = (data.bdPlanProgress || []).map(val => parseFloat(val) || 0); const bdProgress = (data.bdProgress || []).map(val => parseFloat(val) || 0); civilSpecialtyChart.setOption({ xAxis: { data: bdGx }, series: [ { name: '计划进度', data: bdPlanProgress }, { name: '实际进度', data: bdProgress } ] }); } // 更新电气专业图表 if (electricalSpecialtyChart) { const dqGx = data.dqGx || []; const dqPlanProgress = (data.dqPlanProgress || []).map(val => parseFloat(val) || 0); const dqProgress = (data.dqProgress || []).map(val => parseFloat(val) || 0); electricalSpecialtyChart.setOption({ xAxis: { data: dqGx }, series: [ { name: '计划进度', data: dqPlanProgress }, { name: '实际进度', data: dqProgress } ] }); } } // 初始化项目支出趋势图表 function initExpenditureTrendChart() { expenditureTrendChart = echarts.init(document.getElementById('expenditureTrendChart')); const dates = ['XXXX-XX-01', 'XXXX-XX-02', 'XXXX-XX-03', 'XXXX-XX-04', 'XXXX-XX-05', 'XXXX-XX-06', 'XXXX-XX-07', 'XXXX-XX-08']; const expenditure = [48, 45, 42, 32, 35, 38, 30, 28]; const option = { tooltip: { trigger: 'axis', axisPointer: { type: 'line' }, backgroundColor: 'rgba(19, 51, 55, 0.9)', borderColor: 'rgba(0, 254, 252, 0.5)', borderWidth: 1, textStyle: { color: '#fff' } }, grid: { top: '15%', left: '8%', right: '6%', bottom: '15%' }, xAxis: { type: 'category', data: dates, axisLabel: { color: '#fff', fontSize: 11 }, axisLine: { lineStyle: { color: '#5A6E71' } }, axisTick: { show: false } }, yAxis: { type: 'value', min: 0, max: 60, interval: 10, axisLabel: { color: '#fff', fontSize: 11 }, axisLine: { lineStyle: { color: '#5A6E71' } }, splitLine: { lineStyle: { color: 'rgba(90, 110, 113, 0.3)', type: 'dashed' } } }, series: [ { type: 'line', data: expenditure, smooth: true, lineStyle: { width: 2, color: '#00FEFC' }, itemStyle: { color: '#00FEFC' }, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: 'rgba(0, 254, 252, 0.4)' }, { offset: 1, color: 'rgba(0, 254, 252, 0.05)' } ]) } } ] }; expenditureTrendChart.setOption(option); } // 初始化项目支出占比图表(环形图) function initExpenditureProportionChart() { expenditureProportionChart = echarts.init(document.getElementById('expenditureProportionChart')); const option = { tooltip: { trigger: 'item', backgroundColor: 'rgba(19, 51, 55, 0.9)', borderColor: 'rgba(0, 254, 252, 0.5)', borderWidth: 1, textStyle: { color: '#fff' }, formatter: '{b}: {d}%' }, legend: { bottom: 10, left: 'center', textStyle: { color: '#fff', fontSize: 12 }, itemWidth: 12, itemHeight: 8, itemGap: 15 }, series: [ { name: '支出占比', type: 'pie', radius: ['50%', '70%'], center: ['50%', '45%'], avoidLabelOverlap: false, itemStyle: { borderRadius: 5, borderColor: 'rgba(13, 34, 37, 0.8)', borderWidth: 2 }, label: { show: true, formatter: '{b}\n{d}%', color: '#fff', fontSize: 12, fontWeight: 'bold' }, emphasis: { label: { show: true, fontSize: 14, fontWeight: 'bold' } }, data: [ { value: 0, name: '支出', itemStyle: { color: '#00FEFC' } }, { value: 0, name: '预算剩余', itemStyle: { color: '#FFFFFF' } } ] } ] }; expenditureProportionChart.setOption(option); } // 更新项目支出趋势图表 function updateExpenditureTrendChart(data) { if (!expenditureTrendChart || !data) return; // 格式化时间列表:从 "2026-01-01" 转换为 "01-01" const timeList = (data.timeList || []).map(dateStr => { if (!dateStr) return ''; const parts = dateStr.split('-'); if (parts.length >= 2) { return parts[1] + '-' + parts[2]; } return dateStr; }); // 转换数值列表为数字 const valueList = (data.valueList || []).map(val => parseFloat(val) || 0); // 确保两个数组长度一致,取最小长度 const minLength = Math.min(timeList.length, valueList.length); const finalTimeList = timeList.slice(0, minLength); const finalValueList = valueList.slice(0, minLength); // 计算最大值,用于设置y轴范围 const maxValue = finalValueList.length > 0 ? Math.max(...finalValueList, 0) : 0; const yAxisMax = maxValue > 0 ? Math.ceil(maxValue * 1.2) : 100; expenditureTrendChart.setOption({ xAxis: { data: finalTimeList }, yAxis: { max: yAxisMax, interval: Math.ceil(yAxisMax / 5) }, series: [ { data: finalValueList } ] }); } // 更新项目支出占比图表 function updateExpenditureProportionChart(data) { if (!expenditureProportionChart || !data) return; // allCost 是预算,proCount 是支出 const budget = parseFloat(data.allCost || 0); const expenditure = parseFloat(data.proCount || 0); const remaining = budget - expenditure; // 计算百分比 let expenditurePercent = 0; let remainingPercent = 0; if (budget > 0) { expenditurePercent = (expenditure / budget * 100).toFixed(1); remainingPercent = (remaining / budget * 100).toFixed(1); } expenditureProportionChart.setOption({ series: [ { data: [ { value: parseFloat(expenditurePercent), name: '支出', itemStyle: { color: '#00FEFC' } }, { value: parseFloat(remainingPercent), name: '预算剩余', itemStyle: { color: '#FFFFFF' } } ] } ] }); } // 初始化项目风险图表 function initProjectRiskChart() { projectRiskChart = echarts.init(document.getElementById('projectRiskChart')); const option = { tooltip: { trigger: 'item', backgroundColor: 'rgba(19, 51, 55, 0.9)', borderColor: 'rgba(0, 254, 252, 0.5)', borderWidth: 1, textStyle: { color: '#fff' }, formatter: function (params) { // params.data 包含数据项的所有信息,包括自定义属性 const actualCount = params.data.actualCount || 0; const percent = params.percent || 0; return params.name + ': ' + actualCount + '个 (' + percent.toFixed(1) + '%)'; } }, legend: { orient: 'vertical', right: 10, top: 'center', textStyle: { color: '#fff', fontSize: 12 }, itemWidth: 12, itemHeight: 8, itemGap: 10, formatter: function (name) { // 获取当前图表的数据 const currentOption = projectRiskChart.getOption(); const seriesData = currentOption.series && currentOption.series[0] && currentOption.series[0].data; if (seriesData) { const item = seriesData.find(d => d.name === name); if (item) { const actualCount = item.actualCount || 0; const percent = item.value || 0; return name + ' ' + actualCount + '个 ' + percent.toFixed(1) + '%'; } } return name; } }, series: [ { name: '项目风险', type: 'pie', roseType: 'area', radius: ['10%', '70%'], center: ['35%', '45%'], avoidLabelOverlap: false, itemStyle: { borderRadius: 5, borderColor: 'rgba(13, 34, 37, 0.8)', borderWidth: 2 }, label: { show: false }, emphasis: { label: { show: true, fontSize: 14, fontWeight: 'bold', color: '#fff' }, itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 254, 252, 0.5)' } }, data: [ { value: 0, actualCount: 0, name: '二级风险', itemStyle: { color: '#4A90E2' } }, { value: 0, actualCount: 0, name: '三级风险', itemStyle: { color: '#1CFFA3' } }, { value: 0, actualCount: 0, name: '四级风险', itemStyle: { color: '#00FEFC' } }, { value: 0, actualCount: 0, name: '五级风险', itemStyle: { color: '#FF9C65' } } ] } ] }; projectRiskChart.setOption(option); } // 更新项目风险图表 function updateProjectRiskChart(data) { if (!projectRiskChart || !data) return; // 获取各风险等级的数量 const twoRisk = parseInt(data.twoRisk || 0); const threeRisk = parseInt(data.threeRisk || 0); const fourRisk = parseInt(data.fourRisk || 0); const fiveRisk = parseInt(data.fiveRisk || 0); // 计算总风险数量(用于显示) const allRisk = parseInt(data.allRisk || 0); // 计算各风险等级的总数(用于计算百分比) const totalRiskCount = twoRisk + threeRisk + fourRisk + fiveRisk; // 计算百分比 let twoRiskPercent = 0; let threeRiskPercent = 0; let fourRiskPercent = 0; let fiveRiskPercent = 0; if (totalRiskCount > 0) { twoRiskPercent = (twoRisk / totalRiskCount * 100).toFixed(1); threeRiskPercent = (threeRisk / totalRiskCount * 100).toFixed(1); fourRiskPercent = (fourRisk / totalRiskCount * 100).toFixed(1); fiveRiskPercent = (fiveRisk / totalRiskCount * 100).toFixed(1); } // 更新图表数据,同时保存实际数量和百分比 projectRiskChart.setOption({ series: [ { data: [ { value: parseFloat(twoRiskPercent), actualCount: twoRisk, name: '二级风险', itemStyle: { color: '#4A90E2' } }, { value: parseFloat(threeRiskPercent), actualCount: threeRisk, name: '三级风险', itemStyle: { color: '#1CFFA3' } }, { value: parseFloat(fourRiskPercent), actualCount: fourRisk, name: '四级风险', itemStyle: { color: '#00FEFC' } }, { value: parseFloat(fiveRiskPercent), actualCount: fiveRisk, name: '五级风险', itemStyle: { color: '#FF9C65' } } ] } ] }); // 更新总风险数量显示 $('#totalRiskDisplay').text('总风险数量:' + allRisk + '个'); // 更新右侧统计数据 const xhRisk = data.xhRisk || '0'; const lastRiskNum = data.lastRiskNum || '0'; const lastTwoRisk = data.lastTwoRisk || '0'; $('#closedRisk').text(xhRisk); $('#remainingRisk').text(lastRiskNum); $('#remainingLevel2Risk').text(lastTwoRisk); } // 初始化分析预警表格 function initWarningTable() { // 初始化时调用接口获取数据 getAnalysisWarning(currentWarningFilter); } // 更新分析预警表格数据 function updateWarningTable(data) { if (!data || !Array.isArray(data)) { $('#warningTableBody').html('暂无预警'); return; } renderWarningTable(data); } // 渲染分析预警表格 function renderWarningTable(warnings) { const tbody = $('#warningTableBody'); tbody.empty(); if (!warnings || warnings.length === 0) { tbody.html('暂无预警'); return; } warnings.forEach((warning, index) => { // 根据接口返回的字段映射 const id = (index + 1).toString().padStart(2, '0'); const time = warning.txTime || warning.warnTime || warning.time || ''; const type = warning.txType || warning.warnType || warning.type || ''; const content = warning.content || warning.warnContent || ''; const action = warning.action || '制定策略'; const row = ` ${id} ${time} ${type} ${content} ${action} `; tbody.append(row); }); } // 筛选分析预警 let currentWarningFilter = 'all'; function filterWarning(type) { currentWarningFilter = type; // 更新标签状态 $('.warning-tab').removeClass('active'); $(`.warning-tab[data-type="${type}"]`).addClass('active'); // 重新调用接口获取筛选后的数据 getAnalysisWarning(type); } // 更新图表 function updateCharts() { // 这里可以重新加载图表数据 // 实际应该从API获取数据并更新图表 if (riskAnalysisChart) riskAnalysisChart.resize(); if (civilSpecialtyChart) civilSpecialtyChart.resize(); if (electricalSpecialtyChart) electricalSpecialtyChart.resize(); if (expenditureTrendChart) expenditureTrendChart.resize(); if (expenditureProportionChart) expenditureProportionChart.resize(); if (projectRiskChart) projectRiskChart.resize(); }