let table, layer, form, laydate; let civilProgressChart = null; let electricalProgressChart = null; let civilProgressBarChart = null; let electricalProgressBarChart = null; let modalProcessKeyword = ''; let currentGxType = 1; // 当前弹框的工序类型:1=土建,2=电气 // 工程ID & 日期范围(参考 proQualityAnalysis.js) let bidCode = parent.parent.$('#bidPro').val(); // 获取当天日期 function getTodayDate() { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); const day = String(now.getDate()).padStart(2, '0'); return year + '-' + month + '-' + day; } // 获取当月第一天和最后一天(保留用于其他功能) function getCurrentMonthRange() { const now = new Date(); const year = now.getFullYear(); const month = now.getMonth(); // 当月第一天 const firstDay = new Date(year, month, 1); const startDate = year + '-' + String(month + 1).padStart(2, '0') + '-' + String(firstDay.getDate()).padStart(2, '0'); // 当月最后一天 const lastDay = new Date(year, month + 1, 0); const endDate = year + '-' + String(month + 1).padStart(2, '0') + '-' + String(lastDay.getDate()).padStart(2, '0'); return { startDate, endDate }; } const today = getTodayDate(); let queryParams = { projectId: bidCode, startTestDay: today, endTestDay: today, }; layui.use(["layer", "table", "form", "laydate"], function () { layer = layui.layer; table = layui.table; form = layui.form; laydate = layui.laydate; // 响应成功后的拦截器 $.ajaxSetup({ beforeSend: function (xhr, options) { var originalSuccess = options.success; options.success = function (data, textStatus, jqXhr) { data = modifyResponseData(data); originalSuccess.apply(this, arguments); }; }, }); // 初始化页面 initPage(); // 初始化日期范围选择器 initDateRangePicker(); // 首次加载时刷新各模块数据 refreshAllModules(); // 为统计卡片添加点击事件 initStatItemClickEvents(); // 响应式调整 window.addEventListener('resize', debounce(function () { handleResize(); }, 300)); }); // 获取第一行整体进度(分别查询土建/电气,带工程和时间参数) function getFirstRowProgress() { const baseUrl = commonUrl + "screen/project/constructionProgress/summary"; // 土建专业(gxType=1) const civilUrl = baseUrl + "?projectId=" + (bidCode || '') + "&startTestDay=" + (queryParams.startTestDay || '') + "&endTestDay=" + (queryParams.endTestDay || '') + "&gxType=1"; ajaxRequestGet( civilUrl, "GET", true, function () { }, function (result) { console.log(result, "第一行整体进度-土建"); const data = result && (result.data || (Array.isArray(result.rows) ? result.rows[0] : null)); if (!data) return; updateCivilFirstRowProgress(data); }, aqEnnable ); // 电气专业(gxType=2) const electricalUrl = baseUrl + "?projectId=" + (bidCode || '') + "&startTestDay=" + (queryParams.startTestDay || '') + "&endTestDay=" + (queryParams.endTestDay || '') + "&gxType=2"; ajaxRequestGet( electricalUrl, "GET", true, function () { }, function (result) { console.log(result, "第一行整体进度-电气"); const data = result && (result.data || (Array.isArray(result.rows) ? result.rows[0] : null)); if (!data) return; updateElectricalFirstRowProgress(data); }, aqEnnable ); } // 获取第三行进度偏差分析 function getThirdRowProgressDeviation() { // 分页参数:pageNum=1,pageSize=9999 const url = commonUrl + "screen/project/constructionProgress/list" + "?projectId=" + (bidCode || '') + "&startTestDay=" + (queryParams.startTestDay || '') + "&endTestDay=" + (queryParams.endTestDay || '') + "&pageNum=1&pageSize=9999"; ajaxRequestGet( url, "GET", true, function () { }, function (result) { console.log(result, "第三行进度偏差分析"); const list = (result && Array.isArray(result.rows)) ? result.rows : []; // 工具方法:将进度值转为数字(去掉%等字符) function parseProgress(val) { if (val === null || val === undefined || val === '') return NaN; const str = String(val).replace('%', '').trim(); const num = parseFloat(str); return isNaN(num) ? NaN : num; } // 根据 gxType 分组:1=土建专业(左侧),2=电气专业(右侧) const civilList = []; const electricalList = []; list.forEach(function (item) { // 直接使用接口返回的 analysis 字段,不再进行计算 // analysis 字段由后端返回,前端直接使用 const gxType = item.gxType != null ? String(item.gxType) : ''; if (gxType === '1') { civilList.push(item); } else if (gxType === '2') { electricalList.push(item); } }); // 为表格增加序号字段,便于显示 civilList.forEach(function (item, index) { item.serialNumber = index + 1; }); electricalList.forEach(function (item, index) { item.serialNumber = index + 1; }); // 回显到第三行两个表格 if (table) { table.reload('civilDeviationTable', { data: civilList }); table.reload('electricalDeviationTable', { data: electricalList }); } // 中间两个柱状图:根据接口数据回显,最多只取前 12 条 const civilForChart = civilList.length > 12 ? civilList.slice(0, 12) : civilList; const electricalForChart = electricalList.length > 12 ? electricalList.slice(0, 12) : electricalList; if (civilProgressBarChart && civilForChart.length) { const civilCategories = civilForChart.map(function (item) { return item.gx || item.processName || item.name || ''; }); const civilPlannedData = civilForChart.map(function (item) { return parseProgress(item.sjprogress) || 0; }); const civilActualData = civilForChart.map(function (item) { return parseProgress(item.progress) || 0; }); // 动态计算yAxis的最大值:取计划进度和实际进度的最大值,向上取整到10的倍数,最小为20 const maxDataValue = Math.max( ...civilPlannedData, ...civilActualData ); const yAxisMax = Math.max(20, Math.ceil(maxDataValue / 10) * 10); civilProgressBarChart.setOption({ xAxis: { data: civilCategories }, yAxis: { max: yAxisMax }, series: [ { name: '计划', data: civilPlannedData }, { name: '实际', data: civilActualData } ] }); } if (electricalProgressBarChart && electricalForChart.length) { const electricalCategories = electricalForChart.map(function (item) { return item.gx || item.processName || item.name || ''; }); const electricalPlannedData = electricalForChart.map(function (item) { return parseProgress(item.sjprogress) || 0; }); const electricalActualData = electricalForChart.map(function (item) { return parseProgress(item.progress) || 0; }); // 动态计算yAxis的最大值:取计划进度和实际进度的最大值,向上取整到10的倍数,最小为20 const maxDataValue = Math.max( ...electricalPlannedData, ...electricalActualData ); const yAxisMax = Math.max(20, Math.ceil(maxDataValue / 10) * 10); electricalProgressBarChart.setOption({ xAxis: { data: electricalCategories }, yAxis: { max: yAxisMax }, series: [ { name: '计划', data: electricalPlannedData }, { name: '实际', data: electricalActualData } ] }); } }, aqEnnable ); } // 防抖函数 function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // 处理窗口大小变化 function handleResize() { if (civilProgressChart) { civilProgressChart.resize(); } if (electricalProgressChart) { electricalProgressChart.resize(); } if (civilProgressBarChart) { civilProgressBarChart.resize(); } if (electricalProgressBarChart) { electricalProgressBarChart.resize(); } if (table) { table.resize('civilDeviationTable'); table.resize('electricalDeviationTable'); } } // 初始化页面 function initPage() { initCivilProgressChart(); initElectricalProgressChart(); initCivilProgressBarChart(); initElectricalProgressBarChart(); initCivilDeviationTable(); initElectricalDeviationTable(); } // 初始化日期范围选择器(顶部日期栏) function initDateRangePicker() { // 设置初始显示值为当天范围 const initialValue = queryParams.startTestDay + ' ~ ' + queryParams.endTestDay; $('#dateRange').val(initialValue); // 使用范围选择器,单个输入框显示日期范围 laydate.render({ elem: '#dateRange', type: 'date', range: true, // 启用范围选择 format: 'yyyy-MM-dd', theme: 'dark', // 默认值使用当天范围 value: queryParams.startTestDay + ' - ' + queryParams.endTestDay, done: function (value, date, endDate) { // 重置为当天日期的函数 const resetToToday = function () { const today = getTodayDate(); queryParams.startTestDay = today; queryParams.endTestDay = today; $('#dateRange').val(today + ' ~ ' + today); refreshAllModules(); }; if (value && value.trim() !== '') { const dates = value.split(' - '); if (dates.length === 2) { const startDate = dates[0].trim(); const endDateStr = dates[1].trim(); // 在单个输入框中显示日期范围(格式:2026-01-15 ~ 2026-01-15) $('#dateRange').val(startDate + ' ~ ' + endDateStr); // 更新查询参数 queryParams.startTestDay = startDate; queryParams.endTestDay = endDateStr; // 日期变化后,重新调用所有模块接口 refreshAllModules(); } else { // 如果格式不正确,重置为当天日期 resetToToday(); } } else { // 清空时,重置为当天日期 resetToToday(); } } }); } // 刷新当前页面所有需要接口的数据 function refreshAllModules() { // 第一行整体进度(两个环形图 + 数字卡片) getFirstRowProgress(); // 第三行进度偏差 + 中间两个柱状图 getThirdRowProgressDeviation(); } // 初始化土建专业工序整体进度环形图 function initCivilProgressChart() { const chartDom = document.getElementById('civilProgressChart'); if (!chartDom) return; if (civilProgressChart) { civilProgressChart.dispose(); } civilProgressChart = echarts.init(chartDom); // 模拟数据 - 后续替换为真实接口数据 const progressRate = 50.00; const remainingRate = 50.00; const option = { backgroundColor: 'transparent', tooltip: { trigger: 'item', backgroundColor: 'rgba(13, 34, 37, 0.95)', borderColor: 'rgba(6, 189, 221, 0.8)', borderWidth: 1, borderRadius: 4, padding: [12, 16], position: 'right', textStyle: { color: '#FFFFFF', fontSize: 12 }, extraCssText: 'z-index: 9999999999;', formatter: function (params) { const name = params.name; const value = params.value; const color = params.color; return `
土建专业工序整体进度
${name} ${value.toFixed(2)}%
`; } }, series: [ // // 外层圆环 // { // name: '外层圆环', // type: 'pie', // radius: ['94%', '97%'], // center: ['50%', '50%'], // avoidLabelOverlap: false, // silent: true, // itemStyle: { // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ // offset: 0, // color: 'rgba(255, 255, 255, 0.9)' // }, { // offset: 1, // color: 'rgba(0, 255, 212, 0.8)' // }]), // borderRadius: 2, // borderColor: 'transparent', // borderWidth: 0, // shadowBlur: 8, // shadowColor: 'rgba(0, 255, 212, 0.6)' // }, // label: { // show: false // }, // labelLine: { // show: false // }, // data: [{ // value: 100, // name: '' // }] // }, // 内层圆环 { name: '土建专业工序整体进度', type: 'pie', radius: ['60%', '80%'], center: ['50%', '50%'], avoidLabelOverlap: false, gap: 3, itemStyle: { borderRadius: 5, borderColor: 'transparent', borderWidth: 0 }, label: { show: true, position: 'center', formatter: function () { return '{a|50}{b|%}'; }, rich: { a: { fontSize: 32, fontWeight: 'bold', color: '#FFFFFF', lineHeight: 40 }, b: { fontSize: 20, fontWeight: 'bold', color: '#FFFFFF', lineHeight: 40 } } }, emphasis: { itemStyle: { borderRadius: 6, shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' }, label: { rich: { a: { fontSize: 36, fontWeight: 'bold', color: '#FFFFFF' }, b: { fontSize: 22, fontWeight: 'bold', color: '#FFFFFF' } } } }, labelLine: { show: false }, data: [ { value: progressRate, name: '已完成', itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#00FFD4' }, { offset: 0.5, color: '#00D4FF' }, { offset: 1, color: '#00A8FF' }]) } }, { value: remainingRate, name: '未完成', itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(238, 248, 245, 1)' }, { offset: 1, color: 'rgba(238, 248, 245, 0.8)' }]) } } ] } ] }; civilProgressChart.setOption(option); // 添加点击事件监听 civilProgressChart.on('click', function (params) { openProcessDetailModal(1, '土建专业工序详情'); }); } // 更新土建专业第一行整体进度(环形图 + 数字卡片) function updateCivilFirstRowProgress(data) { if (!civilProgressChart) return; const totalCount = Number(data.totalCount) || 0; const finishedCount = Number(data.finishedCount) || 0; const abnormalCount = Number(data.abnormalCount) || 0; // 通过总工序和已完成工序计算完成率 let overallProgress = 0; if (totalCount > 0) { overallProgress = (finishedCount / totalCount) * 100; } // 进度百分比限制在 0-100 之间 overallProgress = Math.max(0, Math.min(100, overallProgress)); const remainingRate = Math.max(0, 100 - overallProgress); // 更新顶部统计数字 const totalEl = document.getElementById('civilTotalProcesses'); const finishedEl = document.getElementById('civilCompletedProcesses'); const abnormalEl = document.getElementById('civilAbnormalProcesses'); if (totalEl) totalEl.textContent = totalCount; if (finishedEl) finishedEl.textContent = finishedCount; if (abnormalEl) abnormalEl.textContent = abnormalCount; // 更新环形图数据和中心文案 civilProgressChart.setOption({ series: [{ name: '土建专业工序整体进度', label: { formatter: '{a|' + overallProgress.toFixed(2) + '}{b|%}' }, data: [ { value: overallProgress, name: '已完成' }, { value: remainingRate, name: '未完成' } ] }] }); } // 初始化土建专业进度柱状图(中间柱状图) function initCivilProgressBarChart() { const chartDom = document.getElementById('civilProgressBarChart'); if (!chartDom) return; if (civilProgressBarChart) { civilProgressBarChart.dispose(); } civilProgressBarChart = echarts.init(chartDom); // 模拟数据(后续可由接口覆盖) const categories = ['配电装置楼', '屋外场地', '围墙及大门', '辅助用房', '场坪工程', '系统构筑物', '站内外道路']; const plannedData = [10, 12, 9, 11, 8, 13, 10]; const actualData = [6, 9, 7, 8, 6, 10, 7]; // 颜色配置 - 计划(绿色/青色系,左侧较高柱体) const colorArr1 = ["#007A65", "#00A382", "#00D4AE", "#00FEFC"]; // 颜色配置 - 实际(青色/浅蓝色系,右侧较短柱体) const colorArr2 = ["#006F85", "#0090A8", "#00C2DD", "#00EFFF"]; // 计划柱体垂直渐变(从上到下:亮到暗) var color1 = { type: "linear", x: 0, x2: 0, y: 0, y2: 1, colorStops: [ { offset: 0, color: colorArr1[3] }, // 顶部最亮 { offset: 0.3, color: colorArr1[2] }, // 上部分 { offset: 0.7, color: colorArr1[1] }, // 下部分 { offset: 1, color: colorArr1[0] } // 底部较暗 ] }; // 实际柱体垂直渐变(从上到下:亮到暗) var color2 = { type: "linear", x: 0, x2: 0, y: 0, y2: 1, colorStops: [ { offset: 0, color: colorArr2[3] }, // 顶部最亮 { offset: 0.3, color: colorArr2[2] }, // 上部分 { offset: 0.7, color: colorArr2[1] }, // 下部分 { offset: 1, color: colorArr2[0] } // 底部较暗 ] }; var barWidth = 18; const option = { backgroundColor: 'transparent', tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, backgroundColor: 'rgba(13, 34, 37, 0.95)', borderColor: 'rgba(6, 189, 221, 0.8)', borderWidth: 1, borderRadius: 4, padding: [12, 16], textStyle: { color: '#FFFFFF', fontSize: 12 }, extraCssText: 'z-index:9999999999;', formatter: function (params) { if (!params || !params.length) return ''; const name = params[0].name || ''; let html = `
${name}
`; params.forEach(function (item) { // 只显示bar类型的tooltip,不显示pictorialBar if (item.componentSubType === "bar") { const color = item.color; html += `
${item.seriesName} ${item.value}
`; } }); return html; } }, legend: { data: ['计划', '实际'], top: 8, right: 20, textStyle: { color: '#FFFFFF', fontSize: 12 }, itemWidth: 12, itemHeight: 12 }, grid: { left: '6%', right: '4%', bottom: '10%', top: '22%', containLabel: true }, xAxis: { type: 'category', data: categories, axisLabel: { color: '#FFFFFF', fontSize: 12 }, axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)', type: 'dashed' } }, axisTick: { show: false } }, yAxis: { type: 'value', min: 0, max: 20, axisLabel: { color: '#FFFFFF', fontSize: 12 }, axisLine: { show: false }, splitLine: { lineStyle: { color: 'rgba(0, 255, 255, 0.2)', type: 'dashed', opacity: 0.3 } }, axisTick: { show: false } }, series: [ { z: 1, name: '计划', type: 'bar', data: plannedData, barWidth: barWidth, barGap: '0%', itemStyle: { color: color1 } }, { z: 3, name: '计划', type: 'pictorialBar', symbolPosition: 'end', data: plannedData, symbol: 'diamond', symbolOffset: ['-75%', '-60%'], symbolSize: [18, 12], itemStyle: { borderWidth: 2, borderColor: 'rgba(0, 254, 252, 0.5)', color: colorArr1[3] // 使用最亮的颜色作为钻石顶部 }, tooltip: { show: false } }, { z: 1, name: '实际', type: 'bar', data: actualData, barWidth: barWidth, barGap: '50%', itemStyle: { color: color2 } }, { z: 3, name: '实际', type: 'pictorialBar', symbolPosition: 'end', data: actualData, symbol: 'diamond', symbolOffset: ['75%', '-60%'], symbolSize: [18, 12], itemStyle: { borderWidth: 2, borderColor: 'rgba(0, 239, 255, 0.5)', color: colorArr2[3] // 使用最亮的颜色作为钻石顶部 }, tooltip: { show: false } } ] }; civilProgressBarChart.setOption(option); } // 初始化电气专业进度柱状图(中间柱状图) function initElectricalProgressBarChart() { const chartDom = document.getElementById('electricalProgressBarChart'); if (!chartDom) return; if (electricalProgressBarChart) { electricalProgressBarChart.dispose(); } electricalProgressBarChart = echarts.init(chartDom); // 模拟数据(后续可由接口覆盖) const categories = ['变压器安装', '控制及直流系统', 'GIS配电装置', '10kV站用配电', '户外照明安装']; const plannedData = [16, 15, 18, 14, 12]; const actualData = [12, 13, 15, 11, 10]; // 颜色配置 - 计划(绿色/青色系,左侧较高柱体) const colorArr1 = ["#007A65", "#00A382", "#00D4AE", "#00FEFC"]; // 颜色配置 - 实际(青色/浅蓝色系,右侧较短柱体) const colorArr2 = ["#006F85", "#0090A8", "#00C2DD", "#00EFFF"]; // 计划柱体垂直渐变(从上到下:亮到暗) var color1 = { type: "linear", x: 0, x2: 0, y: 0, y2: 1, colorStops: [ { offset: 0, color: colorArr1[3] }, // 顶部最亮 { offset: 0.3, color: colorArr1[2] }, // 上部分 { offset: 0.7, color: colorArr1[1] }, // 下部分 { offset: 1, color: colorArr1[0] } // 底部较暗 ] }; // 实际柱体垂直渐变(从上到下:亮到暗) var color2 = { type: "linear", x: 0, x2: 0, y: 0, y2: 1, colorStops: [ { offset: 0, color: colorArr2[3] }, // 顶部最亮 { offset: 0.3, color: colorArr2[2] }, // 上部分 { offset: 0.7, color: colorArr2[1] }, // 下部分 { offset: 1, color: colorArr2[0] } // 底部较暗 ] }; var barWidth = 18; const option = { backgroundColor: 'transparent', tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, backgroundColor: 'rgba(13, 34, 37, 0.95)', borderColor: 'rgba(6, 189, 221, 0.8)', borderWidth: 1, borderRadius: 4, padding: [12, 16], textStyle: { color: '#FFFFFF', fontSize: 12 }, extraCssText: 'z-index:9999999999;', formatter: function (params) { if (!params || !params.length) return ''; const name = params[0].name || ''; let html = `
${name}
`; params.forEach(function (item) { // 只显示bar类型的tooltip,不显示pictorialBar if (item.componentSubType === "bar") { const color = item.color; html += `
${item.seriesName} ${item.value}
`; } }); return html; } }, legend: { data: ['计划', '实际'], top: 8, right: 20, textStyle: { color: '#FFFFFF', fontSize: 12 }, itemWidth: 12, itemHeight: 12 }, grid: { left: '6%', right: '4%', bottom: '10%', top: '22%', containLabel: true }, xAxis: { type: 'category', data: categories, axisLabel: { color: '#FFFFFF', fontSize: 12 }, axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)', type: 'dashed' } }, axisTick: { show: false } }, yAxis: { type: 'value', min: 0, max: 20, axisLabel: { color: '#FFFFFF', fontSize: 12 }, axisLine: { show: false }, splitLine: { lineStyle: { color: 'rgba(0, 255, 255, 0.2)', type: 'dashed', opacity: 0.3 } }, axisTick: { show: false } }, series: [ { z: 1, name: '计划', type: 'bar', data: plannedData, barWidth: barWidth, barGap: '0%', itemStyle: { color: color1 } }, { z: 3, name: '计划', type: 'pictorialBar', symbolPosition: 'end', data: plannedData, symbol: 'diamond', symbolOffset: ['-75%', '-60%'], symbolSize: [18, 12], itemStyle: { borderWidth: 2, borderColor: 'rgba(0, 254, 252, 0.5)', color: colorArr1[3] // 使用最亮的颜色作为钻石顶部 }, tooltip: { show: false } }, { z: 1, name: '实际', type: 'bar', data: actualData, barWidth: barWidth, barGap: '50%', itemStyle: { color: color2 } }, { z: 3, name: '实际', type: 'pictorialBar', symbolPosition: 'end', data: actualData, symbol: 'diamond', symbolOffset: ['75%', '-60%'], symbolSize: [18, 12], itemStyle: { borderWidth: 2, borderColor: 'rgba(0, 239, 255, 0.5)', color: colorArr2[3] // 使用最亮的颜色作为钻石顶部 }, tooltip: { show: false } } ] }; electricalProgressBarChart.setOption(option); } // 初始化电气专业工序整体进度环形图 function initElectricalProgressChart() { const chartDom = document.getElementById('electricalProgressChart'); if (!chartDom) return; if (electricalProgressChart) { electricalProgressChart.dispose(); } electricalProgressChart = echarts.init(chartDom); // 模拟数据 - 后续替换为真实接口数据 const progressRate = 50.00; const remainingRate = 50.00; const option = { backgroundColor: 'transparent', tooltip: { trigger: 'item', backgroundColor: 'rgba(13, 34, 37, 0.95)', borderColor: 'rgba(6, 189, 221, 0.8)', borderWidth: 1, borderRadius: 4, padding: [12, 16], position: 'right', textStyle: { color: '#FFFFFF', fontSize: 12 }, extraCssText: 'z-index: 9999999999;', formatter: function (params) { const name = params.name; const value = params.value; const color = params.color; return `
变电专业工序整体进度
${name} ${value.toFixed(2)}%
`; } }, series: [ // // 外层圆环 // { // name: '外层圆环', // type: 'pie', // radius: ['94%', '97%'], // center: ['50%', '50%'], // avoidLabelOverlap: false, // silent: true, // itemStyle: { // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ // offset: 0, // color: 'rgba(255, 255, 255, 0.9)' // }, { // offset: 1, // color: 'rgba(0, 255, 212, 0.8)' // }]), // borderRadius: 2, // borderColor: 'transparent', // borderWidth: 0, // shadowBlur: 8, // shadowColor: 'rgba(0, 255, 212, 0.6)' // }, // label: { // show: false // }, // labelLine: { // show: false // }, // data: [{ // value: 100, // name: '' // }] // }, // 内层圆环 { name: '变电专业工序整体进度', type: 'pie', radius: ['60%', '80%'], center: ['50%', '50%'], avoidLabelOverlap: false, gap: 3, itemStyle: { borderRadius: 5, borderColor: 'transparent', borderWidth: 0 }, label: { show: true, position: 'center', formatter: function () { return '{a|50}{b|%}'; }, rich: { a: { fontSize: 32, fontWeight: 'bold', color: '#FFFFFF', lineHeight: 40 }, b: { fontSize: 20, fontWeight: 'bold', color: '#FFFFFF', lineHeight: 40 } } }, emphasis: { itemStyle: { borderRadius: 6, shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' }, label: { rich: { a: { fontSize: 36, fontWeight: 'bold', color: '#FFFFFF' }, b: { fontSize: 22, fontWeight: 'bold', color: '#FFFFFF' } } } }, labelLine: { show: false }, data: [ { value: progressRate, name: '已完成', itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#00FFD4' }, { offset: 0.5, color: '#00D4FF' }, { offset: 1, color: '#00A8FF' }]) } }, { value: remainingRate, name: '未完成', itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(238, 248, 245, 1)' }, { offset: 1, color: 'rgba(238, 248, 245, 0.8)' }]) } } ] } ] }; electricalProgressChart.setOption(option); // 添加点击事件监听 electricalProgressChart.on('click', function (params) { openProcessDetailModal(2, '电气专业工序详情'); }); } // 更新电气专业第一行整体进度(环形图 + 数字卡片) function updateElectricalFirstRowProgress(data) { if (!electricalProgressChart) return; const totalCount = Number(data.totalCount) || 0; const finishedCount = Number(data.finishedCount) || 0; const abnormalCount = Number(data.abnormalCount) || 0; // 通过总工序和已完成工序计算完成率 let overallProgress = 0; if (totalCount > 0) { overallProgress = (finishedCount / totalCount) * 100; } // 进度百分比限制在 0-100 之间 overallProgress = Math.max(0, Math.min(100, overallProgress)); const remainingRate = Math.max(0, 100 - overallProgress); // 更新顶部统计数字 const totalEl = document.getElementById('electricalTotalProcesses'); const finishedEl = document.getElementById('electricalCompletedProcesses'); const abnormalEl = document.getElementById('electricalAbnormalProcesses'); if (totalEl) totalEl.textContent = totalCount; if (finishedEl) finishedEl.textContent = finishedCount; if (abnormalEl) abnormalEl.textContent = abnormalCount; // 更新环形图数据和中心文案 electricalProgressChart.setOption({ series: [{ name: '变电专业工序整体进度', label: { formatter: '{a|' + overallProgress.toFixed(2) + '}{b|%}' }, data: [ { value: overallProgress, name: '已完成' }, { value: remainingRate, name: '未完成' } ] }] }); } // 初始化异常工序预警列表 function initWarningList() { // 生成模拟警告数据 const warnings = []; const teams = ['施工队A', '施工队B', '施工队C', '施工队D', '施工队E']; const processes = ['钢筋绑扎工序', '混凝土浇筑工序', '模板安装工序', '钢筋焊接工序', '混凝土养护工序']; const messages = ['进度滞后', '质量异常', '人员不足', '设备故障', '材料短缺']; const today = new Date(); for (let i = 0; i < 15; i++) { const date = new Date(today); date.setDate(date.getDate() - Math.floor(i / 3)); const dateStr = date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0'); warnings.push({ date: dateStr, team: teams[Math.floor(Math.random() * teams.length)], process: processes[Math.floor(Math.random() * processes.length)], message: messages[Math.floor(Math.random() * messages.length)] }); } const warningItemsHtml = warnings.map(function (warning) { const fullText = `${warning.date} ${warning.team} ${warning.process}${warning.message}`; return `
${fullText}
`; }).join(''); const $warningList = $('#civilWarningList'); $warningList.html(warningItemsHtml); setTimeout(function () { const $container = $warningList.parent(); const contentHeight = $warningList[0].scrollHeight; const containerHeight = $container.height(); if (contentHeight > containerHeight) { const duplicatedHtml = warningItemsHtml + warningItemsHtml; // 2 copies $warningList.html(duplicatedHtml); setTimeout(function () { const newContentHeight = $warningList[0].scrollHeight; const singleListHeight = newContentHeight / 2; // Height of one copy $warningList.addClass('warning-list-scroll'); const animationDuration = Math.max(20, Math.ceil(singleListHeight / 30)); // 30px per second $warningList.css({ 'animation': `scrollWarning ${animationDuration}s linear infinite forwards` }); }, 100); } }, 300); } // 生成土建专业进度偏差模拟数据 function generateCivilDeviationMockData() { const processNames = []; const mockData = []; for (let i = 0; i < 10; i++) { mockData.push({ serialNumber: i + 1, processName: processNames[Math.floor(Math.random() * processNames.length)], personnelInput: Math.floor(Math.random() * 20) + 5, equipmentInput: Math.floor(Math.random() * 10) + 2, plannedProgress: (Math.random() * 40 + 40).toFixed(0) + '%', actualProgress: (Math.random() * 30 + 30).toFixed(0) + '%', analysis: '当前进度滞后,请合理安排工作计划及投入的人员设备等资源' }); } return mockData; } // 初始化土建专业进度偏差分析表格 function initCivilDeviationTable() { const mockData = generateCivilDeviationMockData(); table.render({ elem: '#civilDeviationTable', data: mockData, skin: 'line', page: false, height: 'full-80', cols: [[ { field: 'serialNumber', title: '序号', width: '8%', align: 'center' }, { field: 'gx', title: '工序名称', width: '15%', align: 'center' }, { field: 'inUser', title: '投入人员', width: '12%', align: 'center' }, { field: 'inDevice', title: '投入设备', width: '12%', align: 'center' }, { field: 'sjprogress', title: '计划进度', width: '15%', align: 'center', templet: function (d) { if (d.sjprogress === null || d.sjprogress === undefined || d.sjprogress === '') { return ''; } const str = String(d.sjprogress).replace('%', '').trim(); const num = parseFloat(str); if (isNaN(num)) { return d.sjprogress; } return num + '%'; } }, { field: 'progress', title: '实际进度', width: '15%', align: 'center', templet: function (d) { if (d.progress === null || d.progress === undefined || d.progress === '') { return ''; } const str = String(d.progress).replace('%', '').trim(); const num = parseFloat(str); if (isNaN(num)) { return d.progress; } return num + '%'; } }, { field: 'analysis', title: '分析', width: '23%', align: 'left' } ]] }); } // 初始化电气专业进度偏差分析表格(与左侧相同列表) function initElectricalDeviationTable() { const mockData = generateCivilDeviationMockData(); table.render({ elem: '#electricalDeviationTable', data: mockData, skin: 'line', page: false, height: 'full-80', cols: [[ { field: 'serialNumber', title: '序号', width: '8%', align: 'center' }, { field: 'gx', title: '工序名称', width: '15%', align: 'center' }, { field: 'inUser', title: '投入人员', width: '12%', align: 'center' }, { field: 'inDevice', title: '投入设备', width: '12%', align: 'center' }, { field: 'sjprogress', title: '计划进度', width: '15%', align: 'center', templet: function (d) { if (d.sjprogress === null || d.sjprogress === undefined || d.sjprogress === '') { return ''; } const str = String(d.sjprogress).replace('%', '').trim(); const num = parseFloat(str); if (isNaN(num)) { return d.sjprogress; } return num + '%'; } }, { field: 'progress', title: '实际进度', width: '15%', align: 'center', templet: function (d) { if (d.progress === null || d.progress === undefined || d.progress === '') { return ''; } const str = String(d.progress).replace('%', '').trim(); const num = parseFloat(str); if (isNaN(num)) { return d.progress; } return num + '%'; } }, { field: 'analysis', title: '分析', width: '23%', align: 'left' } ]] }); } // 查询土建专业进度偏差 function queryCivilDeviation() { const keyword = $('#civilKeywordInput').val(); const dateRange = $('#civilDeviationDateRange').val(); table.reload('civilDeviationTable', { where: { keyword: keyword, dateRange: dateRange, bidCode: parent.parent.$('#bidPro').val() || '' }, page: { curr: 1 } }); } // 此处原先的进度图表日期查询与接口调用已移除, // 进度展示图表暂时使用页面内的模拟数据进行展示。 // 初始化统计卡片点击事件 function initStatItemClickEvents() { // 土建专业统计卡片 $('#civilTotalProcesses').closest('.stat-item').on('click', function () { openProcessDetailModal(1, '土建专业工序详情'); }); $('#civilCompletedProcesses').closest('.stat-item').on('click', function () { openProcessDetailModal(1, '土建专业工序详情'); }); $('#civilAbnormalProcesses').closest('.stat-item').on('click', function () { openProcessDetailModal(1, '土建专业工序详情'); }); // 电气专业统计卡片 $('#electricalTotalProcesses').closest('.stat-item').on('click', function () { openProcessDetailModal(2, '电气专业工序详情'); }); $('#electricalCompletedProcesses').closest('.stat-item').on('click', function () { openProcessDetailModal(2, '电气专业工序详情'); }); $('#electricalAbnormalProcesses').closest('.stat-item').on('click', function () { openProcessDetailModal(2, '电气专业工序详情'); }); } // 打开工序详情弹框 function openProcessDetailModal(gxType, title) { currentGxType = gxType; const modal = $('#processDetailModal'); $('#processDetailModalTitle').text(title); modal.addClass('show'); // 重置关键字输入框 modalProcessKeyword = ''; $('#modalProcessKeywordInput').val(''); // 延迟初始化表格,确保弹框完全显示后再渲染表格 setTimeout(function () { initModalProcessDetailTable(); }, 100); } // 关闭工序详情弹框 function closeProcessDetailModal() { const modal = $('#processDetailModal'); modal.removeClass('show'); } // 初始化弹框内工序详情表格 function initModalProcessDetailTable() { table.render({ elem: '#modalProcessDetailTable', id: 'modalProcessDetailTable', url: commonUrl + 'screen/project/constructionProgress/detail', headers: { decrypt: 'decrypt', Authorization: token }, method: 'GET', where: { projectId: bidCode, startTestDay: queryParams.startTestDay, endTestDay: queryParams.endTestDay, gxType: currentGxType, keyword: modalProcessKeyword || '' }, skin: 'line', page: { layout: ['prev', 'page', 'next', 'count', 'skip'], groups: 5, limit: 10, limits: [10, 20, 30, 50] }, height: 'full', request: { pageName: 'pageNum', limitName: 'pageSize' }, response: { statusName: 'code', statusCode: 200, msgName: 'msg', countName: 'total', dataName: 'data' }, cols: [[ { type: 'numbers', title: '序号', width: '10%', align: 'center' }, { field: 'gxType', title: '工序类型', width: '12%', align: 'center', templet: function (d) { return d.gxType == 1 ? '土建' : (d.gxType == 2 ? '电气' : ''); } }, { field: 'gx', title: '工序', width: '18%', align: 'center' }, { field: 'planStartTime', title: '计划开始时间', width: '15%', align: 'center' }, { field: 'planEndTime', title: '计划结束时间', width: '15%', align: 'center' }, { field: 'endTime', title: '实际结束时间', width: '15%', align: 'center' }, { field: 'status', title: '状态', width: '15%', align: 'center', templet: function (d) { // 状态:1=已完成,2=进行中,3=未开始,4=延期 const status = d.status; if (status === 1 || status === '1') { return '已完成'; } else if (status === 2 || status === '2') { return '进行中'; } else if (status === 3 || status === '3') { return '未开始'; } else if (status === 4 || status === '4') { return '延期'; } else { // 如果没有status字段,根据实际结束时间判断 if (d.endTime && d.endTime.trim() !== '') { return '已完成'; } else { return '进行中'; } } } } ]] }); } // 弹框内查询工序记录 function queryModalProcessRecords() { modalProcessKeyword = $('#modalProcessKeywordInput').val() || ''; // 重新加载表格 table.reload('modalProcessDetailTable', { where: { projectId: bidCode, startTestDay: queryParams.startTestDay, endTestDay: queryParams.endTestDay, gxType: currentGxType, keyword: modalProcessKeyword }, page: { curr: 1 } }); }