577 lines
17 KiB
JavaScript
577 lines
17 KiB
JavaScript
let table, layer, form, laydate;
|
||
let avgTasksChart = null;
|
||
let equipmentUsageChart = 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 initPage() {
|
||
initPersonnelTables();
|
||
initTradeProportion();
|
||
initAvgTasksChart();
|
||
initEquipmentUsageChart();
|
||
initEquipmentFailureList();
|
||
initWarningTable();
|
||
initMockData();
|
||
}
|
||
|
||
// 防抖函数
|
||
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();
|
||
|
||
$('#dateRange').val(startDate + ' ~ ' + endDateStr);
|
||
|
||
queryParams.startTestDay = startDate;
|
||
queryParams.endTestDay = endDateStr;
|
||
|
||
refreshAllModules();
|
||
} else {
|
||
resetToCurrentMonth();
|
||
}
|
||
} else {
|
||
resetToCurrentMonth();
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 刷新所有模块数据
|
||
function refreshAllModules() {
|
||
initPersonnelTables();
|
||
initTradeProportion();
|
||
if (avgTasksChart) {
|
||
initAvgTasksChart();
|
||
}
|
||
if (equipmentUsageChart) {
|
||
initEquipmentUsageChart();
|
||
}
|
||
initEquipmentFailureList();
|
||
if (table) {
|
||
table.reload('warningTable');
|
||
}
|
||
}
|
||
|
||
// 初始化人员数据表格(前5名和后5名)
|
||
function initPersonnelTables() {
|
||
// 前5名表格
|
||
table.render({
|
||
elem: '#top5PersonnelTable',
|
||
url: '', // 后续替换为真实接口
|
||
headers: {
|
||
decrypt: 'decrypt',
|
||
Authorization: token
|
||
},
|
||
method: 'GET',
|
||
where: {
|
||
projectId: bidCode,
|
||
startTestDay: queryParams.startTestDay,
|
||
endTestDay: queryParams.endTestDay,
|
||
type: 'top5'
|
||
},
|
||
skin: 'line',
|
||
page: false,
|
||
height: 'full',
|
||
cols: [[
|
||
{ type: 'numbers', title: '序号', width: '10%', align: 'center' },
|
||
{ field: 'specialty', title: '专业', width: '15%', align: 'center' },
|
||
{ field: 'team', title: '班组', width: '20%', align: 'center' },
|
||
{ field: 'teamLeader', title: '班组负责人', width: '18%', align: 'center' },
|
||
{ field: 'teamSize', title: '班组人数', width: '12%', align: 'center' },
|
||
{ field: 'presentToday', title: '当日到岗', width: '12%', align: 'center' },
|
||
{
|
||
field: 'utilizationRate',
|
||
title: '利用率',
|
||
width: '13%',
|
||
align: 'center',
|
||
templet: function (d) {
|
||
const rate = d.utilizationRate || 0;
|
||
return rate + '%';
|
||
}
|
||
}
|
||
]]
|
||
});
|
||
|
||
// 后5名表格
|
||
table.render({
|
||
elem: '#bottom5PersonnelTable',
|
||
url: '', // 后续替换为真实接口
|
||
headers: {
|
||
decrypt: 'decrypt',
|
||
Authorization: token
|
||
},
|
||
method: 'GET',
|
||
where: {
|
||
projectId: bidCode,
|
||
startTestDay: queryParams.startTestDay,
|
||
endTestDay: queryParams.endTestDay,
|
||
type: 'bottom5'
|
||
},
|
||
skin: 'line',
|
||
page: false,
|
||
height: 'full',
|
||
cols: [[
|
||
{ type: 'numbers', title: '序号', width: '10%', align: 'center' },
|
||
{ field: 'specialty', title: '专业', width: '15%', align: 'center' },
|
||
{ field: 'team', title: '班组', width: '20%', align: 'center' },
|
||
{ field: 'teamLeader', title: '班组负责人', width: '18%', align: 'center' },
|
||
{ field: 'teamSize', title: '班组人数', width: '12%', align: 'center' },
|
||
{ field: 'presentToday', title: '当日到岗', width: '12%', align: 'center' },
|
||
{
|
||
field: 'utilizationRate',
|
||
title: '利用率',
|
||
width: '13%',
|
||
align: 'center',
|
||
templet: function (d) {
|
||
const rate = d.utilizationRate || 0;
|
||
return rate + '%';
|
||
}
|
||
}
|
||
]]
|
||
});
|
||
}
|
||
|
||
// 初始化各工种任务占比(六边形卡片)
|
||
function initTradeProportion() {
|
||
// 模拟数据 - 后续替换为真实接口数据
|
||
const data = [
|
||
{ value: 28.57, label: '架子鼓' },
|
||
{ value: 23.81, label: '高空作业工' },
|
||
{ value: 19.05, label: 'XX工' },
|
||
{ value: 14.29, label: 'XX工' },
|
||
{ value: 9.52, label: 'XX工' },
|
||
{ value: -4.78, label: 'XX工' }
|
||
];
|
||
|
||
const container = document.getElementById('tradeProportionContainer');
|
||
if (!container) return;
|
||
|
||
const html = data.map(function (item) {
|
||
return `
|
||
<div class="trade-proportion-box">
|
||
<div class="trade-proportion-value">${item.value}%</div>
|
||
<div class="trade-proportion-label">${item.label}</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
container.innerHTML = html;
|
||
}
|
||
|
||
// 初始化各工种人均任务数柱状图
|
||
function initAvgTasksChart() {
|
||
const chartDom = document.getElementById('avgTasksChart');
|
||
if (!chartDom) return;
|
||
|
||
if (avgTasksChart) {
|
||
avgTasksChart.dispose();
|
||
}
|
||
|
||
avgTasksChart = echarts.init(chartDom);
|
||
|
||
// 模拟数据 - 后续替换为真实接口数据
|
||
const categories = ['XXX', 'XXX', 'XXX', 'XXX', 'XXX', 'XXX'];
|
||
const data = [25, 30, 20, 35, 15, 28];
|
||
|
||
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
|
||
},
|
||
formatter: function (params) {
|
||
if (!params || !params.length) return '';
|
||
const name = params[0].name || '';
|
||
const value = params[0].value || 0;
|
||
return `${name}<br/>人均任务数: ${value}`;
|
||
}
|
||
},
|
||
grid: {
|
||
left: '10%',
|
||
right: '10%',
|
||
bottom: '15%',
|
||
top: '10%',
|
||
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: 50,
|
||
interval: 10,
|
||
axisLabel: {
|
||
color: '#FFFFFF',
|
||
fontSize: 12
|
||
},
|
||
axisLine: {
|
||
show: false
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: 'rgba(255, 255, 255, 0.15)',
|
||
type: 'dashed'
|
||
}
|
||
},
|
||
axisTick: { show: false }
|
||
},
|
||
series: [
|
||
{
|
||
name: '人均任务数',
|
||
type: 'bar',
|
||
data: data,
|
||
barWidth: '40%',
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||
offset: 0,
|
||
color: '#00FFB8'
|
||
}, {
|
||
offset: 0.5,
|
||
color: '#00D4FF'
|
||
}, {
|
||
offset: 1,
|
||
color: '#00A8FF'
|
||
}]),
|
||
borderRadius: [2, 2, 0, 0]
|
||
},
|
||
label: {
|
||
show: true,
|
||
position: 'top',
|
||
color: '#FFFFFF',
|
||
fontSize: 12
|
||
}
|
||
}
|
||
]
|
||
};
|
||
|
||
avgTasksChart.setOption(option);
|
||
|
||
// 响应式调整
|
||
window.addEventListener('resize', debounce(function () {
|
||
if (avgTasksChart) {
|
||
avgTasksChart.resize();
|
||
}
|
||
}, 300));
|
||
}
|
||
|
||
// 初始化各设备使用率折线图
|
||
function initEquipmentUsageChart() {
|
||
const chartDom = document.getElementById('equipmentUsageChart');
|
||
if (!chartDom) return;
|
||
|
||
if (equipmentUsageChart) {
|
||
equipmentUsageChart.dispose();
|
||
}
|
||
|
||
equipmentUsageChart = echarts.init(chartDom);
|
||
|
||
// 模拟数据 - 后续替换为真实接口数据
|
||
const categories = ['吊车', '挖掘机', '滤油机', 'XXXXX', 'XXXXX', 'XXXXX'];
|
||
const data1 = [12, 15, 20, 18, 16, 14]; // 滤油机
|
||
const data2 = [8, 10, 6, 12, 9, 11]; // XXX
|
||
|
||
const option = {
|
||
backgroundColor: 'transparent',
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
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
|
||
}
|
||
},
|
||
legend: {
|
||
data: ['滤油机', 'XXX'],
|
||
top: '5%',
|
||
right: '5%',
|
||
textStyle: {
|
||
color: '#FFFFFF',
|
||
fontSize: 12
|
||
},
|
||
itemWidth: 12,
|
||
itemHeight: 12
|
||
},
|
||
grid: {
|
||
left: '10%',
|
||
right: '10%',
|
||
bottom: '15%',
|
||
top: '20%',
|
||
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: 80,
|
||
interval: 20,
|
||
axisLabel: {
|
||
color: '#FFFFFF',
|
||
fontSize: 12
|
||
},
|
||
axisLine: {
|
||
show: false
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: 'rgba(255, 255, 255, 0.15)',
|
||
type: 'dashed'
|
||
}
|
||
},
|
||
axisTick: { show: false }
|
||
},
|
||
series: [
|
||
{
|
||
name: '滤油机',
|
||
type: 'line',
|
||
data: data1,
|
||
itemStyle: {
|
||
color: '#00FFB8'
|
||
},
|
||
lineStyle: {
|
||
width: 2,
|
||
color: '#00FFB8'
|
||
},
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||
offset: 0,
|
||
color: 'rgba(0, 255, 184, 0.3)'
|
||
}, {
|
||
offset: 1,
|
||
color: 'rgba(0, 255, 184, 0.05)'
|
||
}])
|
||
}
|
||
},
|
||
{
|
||
name: 'XXX',
|
||
type: 'line',
|
||
data: data2,
|
||
itemStyle: {
|
||
color: '#50E3C2'
|
||
},
|
||
lineStyle: {
|
||
width: 2,
|
||
color: '#50E3C2'
|
||
},
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||
offset: 0,
|
||
color: 'rgba(80, 227, 194, 0.3)'
|
||
}, {
|
||
offset: 1,
|
||
color: 'rgba(80, 227, 194, 0.05)'
|
||
}])
|
||
}
|
||
}
|
||
]
|
||
};
|
||
|
||
equipmentUsageChart.setOption(option);
|
||
|
||
// 响应式调整
|
||
window.addEventListener('resize', debounce(function () {
|
||
if (equipmentUsageChart) {
|
||
equipmentUsageChart.resize();
|
||
}
|
||
}, 300));
|
||
}
|
||
|
||
// 初始化设备故障排名列表
|
||
function initEquipmentFailureList() {
|
||
// 模拟数据 - 后续替换为真实接口数据
|
||
const data = [
|
||
{ equipment: '挖掘机', count: 10 },
|
||
{ equipment: '滤油机', count: 10 },
|
||
{ equipment: '吊车', count: 8 },
|
||
{ equipment: 'XXX', count: 6 }
|
||
];
|
||
|
||
const container = document.getElementById('equipmentFailureList');
|
||
if (!container) return;
|
||
|
||
const html = data.map(function (item) {
|
||
return `
|
||
<div class="failure-item">
|
||
<span class="failure-equipment">${item.equipment}</span>
|
||
<span class="failure-count">累计故障${item.count}次</span>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
container.innerHTML = html;
|
||
}
|
||
|
||
// 初始化分析预警表格
|
||
function initWarningTable() {
|
||
table.render({
|
||
elem: '#warningTable',
|
||
url: '', // 后续替换为真实接口
|
||
headers: {
|
||
decrypt: 'decrypt',
|
||
Authorization: token
|
||
},
|
||
method: 'GET',
|
||
where: {
|
||
projectId: bidCode,
|
||
startTestDay: queryParams.startTestDay,
|
||
endTestDay: queryParams.endTestDay
|
||
},
|
||
skin: 'line',
|
||
page: false,
|
||
height: 'full',
|
||
cols: [[
|
||
{ type: 'numbers', title: '序号', width: '10%', align: 'center' },
|
||
{ field: 'warningTime', title: '预警时间', width: '20%', align: 'center' },
|
||
{ field: 'warningContent', title: '预警内容', width: '60%', align: 'left' },
|
||
{
|
||
title: '操作',
|
||
width: '10%',
|
||
align: 'center',
|
||
templet: function (d) {
|
||
return '<a href="javascript:void(0)" style="color: #00FFB8;" onclick="formulateStrategy(\'' + (d.id || '') + '\')">制定策略</a>';
|
||
}
|
||
}
|
||
]]
|
||
});
|
||
}
|
||
|
||
// 制定策略(占位函数)
|
||
function formulateStrategy(id) {
|
||
console.log('制定策略,ID:', id);
|
||
// 后续实现
|
||
}
|
||
|
||
// 初始化模拟数据(后续替换为真实接口数据)
|
||
function initMockData() {
|
||
// 人员数据表格使用layui table的url自动加载
|
||
// 其他模块数据已在各自的init函数中初始化
|
||
}
|