520 lines
18 KiB
JavaScript
520 lines
18 KiB
JavaScript
let table, layer, form, laydate;
|
||
let delayDistributionChart = 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 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 currentMonth = getCurrentMonthRange();
|
||
let queryParams = {
|
||
projectId: bidCode,
|
||
startTestDay: currentMonth.startDate,
|
||
endTestDay: currentMonth.endDate,
|
||
}
|
||
|
||
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();
|
||
});
|
||
|
||
// 获取左上角近七天用电趋势
|
||
function getElectricTrend() {
|
||
const url = commonUrl + "screen/worker/analysis/summary?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
||
ajaxRequestGet(url, "GET", true, function () {
|
||
|
||
}, function (result) {
|
||
console.log(result, '近七天用电趋势');
|
||
if (result) {
|
||
updateElectricTrendData(result.data);
|
||
}
|
||
}, aqEnnable);
|
||
}
|
||
|
||
// 更新近七天用电趋势数据
|
||
function updateElectricTrendData(data) {
|
||
const totalCount = data.totalCount || 0;
|
||
const finishedCount = data.finishedCount || 0;
|
||
const processingCount = data.processingCount || 0;
|
||
const notStartedCount = data.notStartedCount || 0;
|
||
const delayCount = data.delayCount || 0;
|
||
|
||
// 更新中心的任务总数
|
||
$('#totalTasks').text(totalCount);
|
||
|
||
// 计算百分比(保留2位小数)
|
||
const calculatePercent = function (count, total) {
|
||
if (total === 0) return '0.00';
|
||
return ((count / total) * 100).toFixed(2);
|
||
};
|
||
|
||
// 更新四个方向的显示:数量 + 百分比
|
||
const finishedPercent = calculatePercent(finishedCount, totalCount);
|
||
$('#completedPercent').text(finishedCount + ' ' + finishedPercent + '%');
|
||
|
||
const processingPercent = calculatePercent(processingCount, totalCount);
|
||
$('#inProgressPercent').text(processingCount + ' ' + processingPercent + '%');
|
||
|
||
const notStartedPercent = calculatePercent(notStartedCount, totalCount);
|
||
$('#notStartedPercent').text(notStartedCount + ' ' + notStartedPercent + '%');
|
||
|
||
const delayPercent = calculatePercent(delayCount, totalCount);
|
||
$('#delayedPercent').text(delayCount + ' ' + delayPercent + '%');
|
||
}
|
||
|
||
// 获取右上角月工种任务分布
|
||
function getTaskDistribution() {
|
||
const url = commonUrl + "screen/worker/analysis/gzsummary?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
||
ajaxRequestGet(url, "GET", true, function () {
|
||
|
||
}, function (result) {
|
||
console.log(result, '月工种任务分布');
|
||
}, aqEnnable);
|
||
}
|
||
|
||
// 获取左下角月任务延期排名top5
|
||
function getTaskDelayRanking() {
|
||
const url = commonUrl + "screen/worker/analysis/delay/person?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
||
ajaxRequestGet(url, "GET", true, function () {
|
||
|
||
}, function (result) {
|
||
console.log(result, '月任务延期排名top5');
|
||
}, aqEnnable);
|
||
}
|
||
|
||
// 获取下方中间的月任务延期分布
|
||
function getTaskDelayDistribution() {
|
||
const url = commonUrl + "screen/worker/analysis/delay/workType?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
||
ajaxRequestGet(url, "GET", true, function () {
|
||
|
||
}, function (result) {
|
||
console.log(result, '月任务延期分布');
|
||
}, aqEnnable);
|
||
}
|
||
|
||
// 获取右下方分析预警
|
||
function getAnalysisWarning() {
|
||
const url = commonUrl + "screen/worker/analysis/yujingdetail?projectId=" + bidCode + "&startTestDay=" + queryParams.startTestDay + "&endTestDay=" + queryParams.endTestDay;
|
||
ajaxRequestGet(url, "GET", true, function () {
|
||
|
||
}, function (result) {
|
||
console.log(result, '分析预警');
|
||
}, aqEnnable);
|
||
}
|
||
|
||
// 获取数据(在页面初始化时调用)
|
||
// getElectricTrend();
|
||
// getTaskDistribution();
|
||
// getTaskDelayRanking();
|
||
// getTaskDelayDistribution();
|
||
// getAnalysisWarning();
|
||
|
||
// 初始化页面
|
||
function initPage() {
|
||
initDelayDistributionChart();
|
||
initMockData();
|
||
// 调用接口获取真实数据
|
||
getElectricTrend();
|
||
getTaskDistribution();
|
||
getTaskDelayRanking();
|
||
getTaskDelayDistribution();
|
||
getAnalysisWarning();
|
||
}
|
||
|
||
// 防抖函数
|
||
function debounce(func, wait) {
|
||
let timeout;
|
||
return function executedFunction(...args) {
|
||
const later = () => {
|
||
clearTimeout(timeout);
|
||
func(...args);
|
||
};
|
||
clearTimeout(timeout);
|
||
timeout = setTimeout(later, wait);
|
||
};
|
||
}
|
||
|
||
// 初始化日期范围选择器
|
||
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 resetToCurrentMonth = function () {
|
||
const currentMonth = getCurrentMonthRange();
|
||
queryParams.startTestDay = currentMonth.startDate;
|
||
queryParams.endTestDay = currentMonth.endDate;
|
||
$('#dateRange').val(currentMonth.startDate + ' ~ ' + currentMonth.endDate);
|
||
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-01 ~ 2026-01-31)
|
||
$('#dateRange').val(startDate + ' ~ ' + endDateStr);
|
||
|
||
// 更新查询参数
|
||
queryParams.startTestDay = startDate;
|
||
queryParams.endTestDay = endDateStr;
|
||
|
||
// 日期变化后,重新调用所有模块接口
|
||
refreshAllModules();
|
||
} else {
|
||
// 如果格式不正确,重置为当月日期
|
||
resetToCurrentMonth();
|
||
}
|
||
} else {
|
||
// 清空时,重置为当月日期
|
||
resetToCurrentMonth();
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 刷新所有模块数据
|
||
function refreshAllModules() {
|
||
// 重新调用所有接口
|
||
getElectricTrend();
|
||
getTaskDistribution();
|
||
getTaskDelayRanking();
|
||
getTaskDelayDistribution();
|
||
getAnalysisWarning();
|
||
// 重新加载图表
|
||
if (delayDistributionChart) {
|
||
initDelayDistributionChart();
|
||
}
|
||
}
|
||
|
||
// 初始化月任务延期分布饼图
|
||
function initDelayDistributionChart() {
|
||
const chartDom = document.getElementById('delayDistributionChart');
|
||
if (!chartDom) return;
|
||
|
||
if (delayDistributionChart) {
|
||
delayDistributionChart.dispose();
|
||
}
|
||
|
||
delayDistributionChart = echarts.init(chartDom);
|
||
|
||
// 模拟数据 - 后续替换为真实接口数据
|
||
const data = [
|
||
{ value: 15.87, name: '架子工' },
|
||
{ value: 26.50, name: '高空作业工' },
|
||
{ value: 23.14, name: 'XX工' },
|
||
{ value: 20.50, name: 'XX工' },
|
||
{ value: 10.28, name: 'XX工' }
|
||
];
|
||
|
||
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],
|
||
textStyle: {
|
||
color: '#FFFFFF',
|
||
fontSize: 12
|
||
},
|
||
formatter: function (params) {
|
||
return `${params.name}<br/>${params.value}%`;
|
||
}
|
||
},
|
||
legend: {
|
||
show: false
|
||
},
|
||
series: [
|
||
{
|
||
name: '月任务延期分布',
|
||
type: 'pie',
|
||
radius: ['40%', '70%'],
|
||
center: ['50%', '50%'],
|
||
avoidLabelOverlap: false,
|
||
itemStyle: {
|
||
borderRadius: 4,
|
||
borderColor: 'transparent',
|
||
borderWidth: 0
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: 'outside',
|
||
formatter: function (params) {
|
||
return params.name + ': ' + params.value + '%';
|
||
},
|
||
color: '#FFFFFF',
|
||
fontSize: 12
|
||
},
|
||
labelLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: 'rgba(255, 255, 255, 0.5)'
|
||
}
|
||
},
|
||
data: data.map(function (item, index) {
|
||
const colors = [
|
||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: '#00FFD4' },
|
||
{ offset: 1, color: '#00A8FF' }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: '#FF9C65' },
|
||
{ offset: 1, color: '#FFD700' }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: '#50E3C2' },
|
||
{ offset: 1, color: '#00D4FF' }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: '#87CEEB' },
|
||
{ offset: 1, color: '#4A90E2' }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: '#FF6B6B' },
|
||
{ offset: 1, color: '#FF8E53' }
|
||
])
|
||
];
|
||
return {
|
||
...item,
|
||
itemStyle: {
|
||
color: colors[index % colors.length]
|
||
}
|
||
};
|
||
})
|
||
}
|
||
]
|
||
};
|
||
|
||
delayDistributionChart.setOption(option);
|
||
|
||
// 更新图例
|
||
updateDelayLegend(data);
|
||
|
||
// 响应式调整
|
||
window.addEventListener('resize', debounce(function () {
|
||
if (delayDistributionChart) {
|
||
delayDistributionChart.resize();
|
||
}
|
||
}, 300));
|
||
}
|
||
|
||
// 更新延期分布图例
|
||
function updateDelayLegend(data) {
|
||
const legendContainer = document.getElementById('delayLegend');
|
||
if (!legendContainer) return;
|
||
|
||
const colors = ['#00FFD4', '#FF9C65', '#50E3C2', '#87CEEB', '#FF6B6B'];
|
||
const legendHtml = data.map(function (item, index) {
|
||
return `
|
||
<div class="legend-item">
|
||
<span class="legend-dot" style="background-color: ${colors[index % colors.length]}"></span>
|
||
<span class="legend-label">${item.name}</span>
|
||
<span class="legend-value">${item.value}%</span>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
legendContainer.innerHTML = legendHtml;
|
||
}
|
||
|
||
// 初始化模拟数据(后续替换为真实接口数据)
|
||
function initMockData() {
|
||
// 模块1:任务统计
|
||
updateTaskStatistics({
|
||
total: 233,
|
||
completed: 47,
|
||
inProgress: 47,
|
||
notStarted: 47,
|
||
delayed: 47
|
||
});
|
||
|
||
// 模块2:工种任务分布
|
||
updateJobTypeDistribution([
|
||
{ name: '挖掘机', value: '人均2.5任务' },
|
||
{ name: '滤油机', value: '人均2.0任务' },
|
||
{ name: '架子工', value: '人均1.8任务' },
|
||
{ name: '高空作业工', value: '人均1.5任务' },
|
||
{ name: 'XX工', value: '人均1.2任务' }
|
||
]);
|
||
|
||
// 模块3:延期排名TOP5
|
||
updateDelayRanking([
|
||
{ name: '李铮辉', count: 15 },
|
||
{ name: '何颖顾', count: 12 },
|
||
{ name: '张三', count: 10 },
|
||
{ name: '李四', count: 8 },
|
||
{ name: '王五', count: 6 }
|
||
]);
|
||
|
||
// 模块5:分析预警
|
||
initWarningList();
|
||
}
|
||
|
||
// 更新任务统计(模块1)
|
||
function updateTaskStatistics(data) {
|
||
const total = data.total || 0;
|
||
const completed = data.completed || 0;
|
||
const inProgress = data.inProgress || 0;
|
||
const notStarted = data.notStarted || 0;
|
||
const delayed = data.delayed || 0;
|
||
|
||
$('#totalTasks').text(total);
|
||
$('#completedTasks').text(completed);
|
||
$('#inProgressTasks').text(inProgress);
|
||
$('#notStartedTasks').text(notStarted);
|
||
$('#delayedTasks').text(delayed);
|
||
|
||
// 更新百分比
|
||
const totalCount = total || 1;
|
||
$('.hexagon-top .hexagon-percent').text(Math.round((completed / totalCount) * 100) + '%');
|
||
$('.hexagon-left .hexagon-percent').text(Math.round((inProgress / totalCount) * 100) + '%');
|
||
$('.hexagon-right .hexagon-percent').text(Math.round((notStarted / totalCount) * 100) + '%');
|
||
$('.hexagon-bottom .hexagon-percent').text(Math.round((delayed / totalCount) * 100) + '%');
|
||
}
|
||
|
||
// 更新工种任务分布(模块2)
|
||
function updateJobTypeDistribution(data) {
|
||
const container = document.getElementById('jobTypeList');
|
||
if (!container) return;
|
||
|
||
const html = data.map(function (item) {
|
||
return `
|
||
<div class="job-type-item">
|
||
<span class="job-type-name">${item.name}</span>
|
||
<span class="job-type-value">${item.value}</span>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
container.innerHTML = html;
|
||
}
|
||
|
||
// 更新延期排名(模块3)
|
||
function updateDelayRanking(data) {
|
||
const container = document.getElementById('delayRankingList');
|
||
if (!container) return;
|
||
|
||
const maxCount = data.length > 0 ? Math.max(...data.map(item => item.count)) : 1;
|
||
|
||
const html = data.map(function (item, index) {
|
||
const percentage = (item.count / maxCount) * 100;
|
||
return `
|
||
<div class="delay-ranking-item">
|
||
<div class="ranking-number">${index + 1}</div>
|
||
<div class="ranking-name">${item.name}</div>
|
||
<div class="ranking-count">延期${item.count}次</div>
|
||
<div class="ranking-bar-container">
|
||
<div class="ranking-bar" style="width: ${percentage}%"></div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
container.innerHTML = html;
|
||
}
|
||
|
||
// 初始化警告列表(模块5)
|
||
function initWarningList() {
|
||
// 模拟警告数据 - 后续替换为真实接口数据
|
||
const warnings = [
|
||
{ date: '2026-01-15', message: '张三本月出现3次任务延期,请关注该人员,建议定期开展技能培训与考核,确保施工进度。' },
|
||
{ date: '2026-01-13', message: '张三本月出现3次任务延期,请关注该人员,建议定期开展技能培训与考核,确保施工进度。' },
|
||
{ date: '2026-01-12', message: '张三本月出现3次任务延期,请关注该人员,建议定期开展技能培训与考核,确保施工进度。' }
|
||
];
|
||
|
||
const warningItemsHtml = warnings.map(function (warning) {
|
||
const fullText = `${warning.date} ${warning.message}`;
|
||
return `
|
||
<div class="warning-item">
|
||
<div class="warning-icon"></div>
|
||
<div class="warning-text" title="${fullText}">
|
||
${fullText}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
const $warningList = $('#warningList');
|
||
$warningList.html(warningItemsHtml);
|
||
|
||
// 检查是否需要滚动
|
||
setTimeout(function () {
|
||
const $container = $warningList.parent();
|
||
const $listElement = $warningList[0];
|
||
|
||
if (!$listElement) return;
|
||
|
||
const contentHeight = $listElement.scrollHeight;
|
||
const containerHeight = $container.height();
|
||
|
||
// 如果内容高度超过容器高度,启用无缝滚动
|
||
if (contentHeight > containerHeight) {
|
||
const duplicatedHtml = warningItemsHtml + warningItemsHtml;
|
||
$warningList.html(duplicatedHtml);
|
||
|
||
setTimeout(function () {
|
||
const newContentHeight = $listElement.scrollHeight;
|
||
const singleListHeight = newContentHeight / 2;
|
||
|
||
$warningList.addClass('warning-list-scroll');
|
||
|
||
const animationDuration = Math.max(25, Math.ceil(singleListHeight / 25));
|
||
|
||
$warningList.css({
|
||
'animation': `scrollWarning ${animationDuration}s linear infinite`,
|
||
'animation-fill-mode': 'forwards'
|
||
});
|
||
}, 200);
|
||
} else {
|
||
$warningList.addClass('warning-list-scroll');
|
||
}
|
||
}, 500);
|
||
}
|