From 5ae359832cfc179b513781502ef7c97b5bfbc468 Mon Sep 17 00:00:00 2001 From: "lj7788@126.com" Date: Mon, 29 Sep 2025 11:39:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=A7=E5=B1=8F=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E5=AE=9E=E6=96=BD=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/schedule/task_trend.js | 387 +++++++++--------- 1 file changed, 194 insertions(+), 193 deletions(-) diff --git a/yanzhu-bigscreen/src/views/schedule/task_trend.js b/yanzhu-bigscreen/src/views/schedule/task_trend.js index d0c78afa..5f6f58f4 100644 --- a/yanzhu-bigscreen/src/views/schedule/task_trend.js +++ b/yanzhu-bigscreen/src/views/schedule/task_trend.js @@ -1,4 +1,7 @@ function aggregateDataByDate(executionData) { + if (executionData.length == 0) { + return []; + } const dateMap = new Map(); // 按start排序,相同时按end排序 executionData.sort((a, b) => { @@ -11,6 +14,7 @@ function aggregateDataByDate(executionData) { const endB = new Date(b.end); return endA - endB; }); + // 获取整个时间范围 let minDate = new Date(executionData[0].start); let maxDate = new Date(executionData[0].end); @@ -32,25 +36,43 @@ function aggregateDataByDate(executionData) { date: dateStr, planned: 0, completed: 0, - progressSum: 0, - progressCount: 0, }); currentDate.setDate(currentDate.getDate() + 1); } - // 为每个任务创建日期范围 + // 按新规则计算每个任务的计划天数和完成天数分布 executionData.forEach((task) => { const startDate = new Date(task.start); const endDate = new Date(task.end); + const days = task.days; + const process = task.process || 0; + const completedDays = days * process; - // 遍历任务的每一天 + // 计算任务覆盖的总天数 + const timeDiff = endDate.getTime() - startDate.getTime(); + const totalTaskDays = Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1; + + // 按照100%、100%、100%...的方式分配完成天数 const currentTaskDate = new Date(startDate); - while (currentTaskDate <= endDate) { + let remainingCompletedDays = completedDays; + + for (let i = 0; i < totalTaskDays; i++) { const dateStr = currentTaskDate.toISOString().split("T")[0]; if (dateMap.has(dateStr)) { - // 增加计划任务数 + // 每天计划1天 dateMap.get(dateStr).planned += 1; + + // 分配完成天数 + if (remainingCompletedDays >= 1) { + // 完成1天 + dateMap.get(dateStr).completed += 1; + remainingCompletedDays -= 1; + } else if (remainingCompletedDays > 0) { + // 完成剩余天数 + dateMap.get(dateStr).completed += remainingCompletedDays; + remainingCompletedDays = 0; + } } // 移动到下一天 @@ -58,59 +80,15 @@ function aggregateDataByDate(executionData) { } }); - // 统计完成任务(基于开始日期) - executionData.forEach((task) => { - if (task.process !== null) { - const startDate = task.start; - - if (dateMap.has(startDate)) { - dateMap.get(startDate).completed += 1; - dateMap.get(startDate).progressSum += task.process; - dateMap.get(startDate).progressCount += 1; - } - } - }); - // 转换为数组并按日期排序 const result = Array.from(dateMap.values()).sort((a, b) => { return new Date(a.date) - new Date(b.date); }); - // 获取今天的日期 - const today = new Date(); - today.setHours(0, 0, 0, 0); - - // 计算累积进度 - let totalPlanned = 0; - let totalCompleted = 0; - let totalProgressSum = 0; - let totalProgressCount = 0; - + // 四舍五入保留一位小数 result.forEach((item) => { - totalPlanned += item.planned; - // 检查日期是否在今天之后 - const itemDate = new Date(item.date); - if (itemDate > today) { - // 今日之后的数据设置为null - item.completed = null; - item.progressSum = null; - item.progressCount = null; - } else { - totalCompleted += item.completed || 0; - totalProgressSum += item.progressSum || 0; - totalProgressCount += item.progressCount || 0; - } - - // 添加累积数据 - item.cumulativePlanned = totalPlanned; - // 对于今日之后的数据,cumulativeCompleted也设置为null - if (new Date(item.date) > today) { - item.cumulativeCompleted = null; - } else { - item.cumulativeCompleted = totalCompleted; - } - item.cumulativeProgress = - totalProgressCount > 0 ? totalProgressSum / totalProgressCount : 0; + item.planned = Math.round(item.planned * 10) / 10; + item.completed = Math.round(item.completed * 10) / 10; }); return result; @@ -119,170 +97,184 @@ function aggregateDataByDate(executionData) { function makeTaskTrendOptions(that, datas) { // 填充统计数据表格 const summaryData = aggregateDataByDate(datas); + // 准备图表数据 + // 准备图表数据 const dates = summaryData.map((item) => item.date); - const cumulativePlanned = summaryData.map((item) => { - const totalTasks = summaryData[summaryData.length - 1].cumulativePlanned; - return totalTasks > 0 ? (item.cumulativePlanned / totalTasks) * 100 : 0; + + // 计算累积数据用于表格 + let tableCumulativePlanned = 0; + let tableCumulativeCompleted = 0; + summaryData.forEach((item) => { + // 计算累积数据 + tableCumulativePlanned += item.planned; + tableCumulativeCompleted += item.completed; + item.cumulativePlanned = tableCumulativePlanned; + item.cumulativeCompleted = tableCumulativeCompleted; + }); + // 获取今天的日期 + const today = new Date(); + today.setHours(0, 0, 0, 0); + + // 处理柱形图数据 + const plannedData = []; + const completedData = []; + + summaryData.forEach((item) => { + // 计划任务天数始终显示 + plannedData.push(item.planned); + + // 检查日期是否在今天之后 + const itemDate = new Date(item.date); + if (itemDate > today) { + // 今日之后的已完成任务天数设置为null + completedData.push(null); + } else { + // 今日及之前的已完成任务天数正常显示 + completedData.push(item.completed); + } }); - const cumulativeCompleted = summaryData.map((item) => { - // 如果completed为null,表示该日期在今日之后,返回null - if (item.cumulativeCompleted === null) { - return null; + // 计算累积数据用于图表 + let chartCumulativePlanned = 0; + let chartCumulativeCompleted = 0; + const cumulativePlannedData = []; + const cumulativeCompletedData = []; + + // 计算总计划天数和总完成天数用于百分比计算 + const totalPlannedDays = summaryData.reduce( + (sum, item) => sum + item.planned, + 0 + ); + const totalCompletedDays = summaryData.reduce( + (sum, item) => sum + item.completed, + 0 + ); + + summaryData.forEach((item, index) => { + chartCumulativePlanned += item.planned; + chartCumulativeCompleted += item.completed; + cumulativePlannedData.push( + totalPlannedDays > 0 + ? Math.round((chartCumulativePlanned / totalPlannedDays) * 1000) / 10 + : 0 + ); + + // 检查日期是否在今天之后 + const itemDate = new Date(item.date); + if (itemDate > today) { + // 今日之后的数据设置为null,这样折线图就不会显示 + cumulativeCompletedData.push(null); + } else { + cumulativeCompletedData.push( + totalPlannedDays > 0 + ? Math.round((chartCumulativeCompleted / totalPlannedDays) * 1000) / + 10 + : 0 + ); } - const totalTasks = summaryData[summaryData.length - 1].cumulativePlanned; - return totalTasks > 0 ? (item.cumulativeCompleted / totalTasks) * 100 : 0; }); + let is1K = that.$dpi() == "1K"; let is2K = that.$dpi() == "2K"; + // 配置图表选项 const option = { tooltip: { trigger: "axis", formatter: function (params) { + let planTotal = summaryData[summaryData.length - 1].cumulativePlanned; let result = params[0].name + "
"; - // 查找当前日期的数据 - const currentItem = summaryData.find( - (item) => item.date === params[0].name - ); - if (currentItem) { - // 计算统计数据 - const totalDays = summaryData.length; // 总天数 - // 计划完成天数(有计划任务的天数) - const plannedDays = summaryData.filter( - (item) => item.planned > 0 - ).length; - - // 实际完成天数处理 - let actualCompletedDays = 0; - const currentDate = new Date(currentItem.date); - const today = new Date(); - today.setHours(0, 0, 0, 0); - - if (currentDate > today) { - // 今日之后的日期,使用之前最大的完成天数值 - const pastData = summaryData.filter((item) => { - const itemDate = new Date(item.date); - return itemDate <= today && item.completed > 0; - }); - actualCompletedDays = pastData.length; - } else { - // 今日及之前的日期,使用当前的实际完成天数 - actualCompletedDays = summaryData.filter((item) => { - const itemDate = new Date(item.date); - return itemDate <= currentDate && item.completed > 0; - }).length; - } - - result += "总天数: " + totalDays + " 天
"; - result += "计划天数: " + plannedDays + " 天
"; - result += "完成天数: " + actualCompletedDays + " 天
"; - } - params.forEach((param) => { - // 处理null值和undefined的情况 - if (param.value === null || param.value === undefined) { - result += param.marker + param.seriesName + ": 无数据
"; + if ( + param.seriesName.includes("天数") && + !param.seriesName.includes("累积") + ) { + if (typeof param.value !== "undefined") { + result += + param.marker + + param.seriesName + + ": " + + param.value + + " 天
"; + } } else { - result += - param.marker + - param.seriesName + - ": " + - param.value.toFixed(2) + - "%
"; + if (typeof param.value !== "undefined") { + result += + param.marker + param.seriesName + ": " + param.value + "%
"; + } } }); + result += + "计划任务总天数:" + + planTotal.toFixed(2) + + "
" + + "累积计划任务天数:" + + summaryData[params[0].dataIndex].cumulativePlanned.toFixed(2) + + "
累积已完成任务天数:" + + summaryData[params[0].dataIndex].cumulativeCompleted.toFixed(2); return result; }, + axisPointer: { lineStyle: { color: "#57617B", }, - }, - textStyle: { - fontSize: is1K ? 12 : is2K ? 18 : 20, + textStyle: { + fontSize: is1K ? 12 : is2K ? 18 : 20, + }, }, }, + legend: { - icon: "rect", - itemWidth: 14, - itemHeight: 10, - itemGap: 15, - data: ["计划任务累积进度", "已完成任务累积进度"], - top: -5, + data: [ + "当天计划任务天数", + "当天已完成任务天数", + "累积计划任务天数", + "累积已完成任务天数", + ], textStyle: { - fontSize: is1K ? 12 : is2K ? 20 : 30, - color: "#c8dbfc", + fontSize: is1K ? 12 : is2K ? 14 : 18, + color: "#aaa", }, }, - grid: { - top: "10%", - left: "2%", - right: "3%", - bottom: "5%", - containLabel: true, - }, xAxis: { - boundaryGap: false, type: "category", data: dates, - axisLine: { - //坐标轴轴线相关设置。数学上的x轴 - show: true, - lineStyle: { - color: "#25597e", - type: "dashed", - }, - }, - axisTick: { - show: false, - }, - axisLabel: { - //坐标轴刻度标签的相关设置 - textStyle: { - color: "#c5d9fc", - margin: 20, - fontSize: 12, - }, + fontSize: is1K ? 12 : is2K ? 14 : 18, + color: "#aaa", }, }, - yAxis: { - type: "value", - name: "累积进度 (%)", - axisLabel: { - formatter: "{value} %", - //坐标轴刻度标签的相关设置 - textStyle: { - color: "#c5d9fc", - margin: 20, - fontSize: is1K ? 12 : is2K ? 16 : 20, + yAxis: [ + { + type: "value", + name: "任务天数", + position: "left", + nameTextStyle: { + color: "#bbb" , + fontSize: is1K ? 14 : is2K ? 16 : 20, + }, + axisLabel: { + fontSize: is1K ? 12 : is2K ? 14 : 18, + color: "#aaa", }, }, - nameTextStyle: { - color: "#c5d9fc", - fontSize: is1K ? 12 : is2K ? 18 : 24, - }, - axisLine: { - //坐标轴轴线相关设置。数学上的x轴 - show: false, - lineStyle: { - color: "#c5d9fc", - type: "dashed", + { + type: "value", + name: "百分比 (%)", + position: "right", + nameTextStyle: { + color: "#bbb" , + fontSize: is1K ? 14 : is2K ? 16 : 20, + }, + axisLabel: { + formatter: "{value} %", + fontSize: is1K ? 12 : is2K ? 14 : 18, + color: "#aaa", }, }, - axisTick: { - show: false, - }, - splitLine: { - show: true, - lineStyle: { - color: "#25597e", - type: "dashed", - }, - }, - }, + ], dataZoom: [ { type: "inside", @@ -296,31 +288,40 @@ function makeTaskTrendOptions(that, datas) { ], series: [ { - name: "计划任务累积进度", - type: "line", - data: cumulativePlanned, - smooth: true, + name: "当天计划任务天数", + type: "bar", + data: plannedData, itemStyle: { color: "#36A2EB", }, - areaStyle: { - color: "#36A2EB", - opacity: 0.2, - }, }, { - name: "已完成任务累积进度", - type: "line", - data: cumulativeCompleted, - connectNulls: false, // 不连接null值 - smooth: true, + name: "当天已完成任务天数", + type: "bar", + data: completedData, itemStyle: { color: "#FF6384", }, - areaStyle: { - color: "#FF6384", - opacity: 0.2, + }, + { + name: "累积计划任务天数", + type: "line", + data: cumulativePlannedData, + itemStyle: { + color: "#1f77b4", }, + smooth: true, + yAxisIndex: 1, + }, + { + name: "累积已完成任务天数", + type: "line", + data: cumulativeCompletedData, + itemStyle: { + color: "#d62728", + }, + smooth: true, + yAxisIndex: 1, }, ], };