1150 lines
38 KiB
JavaScript
1150 lines
38 KiB
JavaScript
let table, layer, form, laydate;
|
||
let civilProgressChart = null;
|
||
let electricalProgressChart = null;
|
||
let civilProgressBarChart = null;
|
||
let electricalProgressBarChart = null;
|
||
|
||
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();
|
||
|
||
// 初始化日期范围选择器
|
||
initDateRangePickers();
|
||
|
||
// 响应式调整
|
||
window.addEventListener('resize', debounce(function() {
|
||
handleResize();
|
||
}, 300));
|
||
});
|
||
|
||
// 防抖函数
|
||
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 initDateRangePickers() {
|
||
// 土建专业进度展示日期选择器
|
||
laydate.render({
|
||
elem: '#civilDateRange',
|
||
type: 'date',
|
||
range: true,
|
||
format: 'yyyy-MM-dd',
|
||
theme: 'dark',
|
||
max: 0,
|
||
done: function(value, date, endDate) {
|
||
// 日期范围选择完成
|
||
}
|
||
});
|
||
|
||
// 土建专业进度偏差分析日期选择器
|
||
laydate.render({
|
||
elem: '#civilDeviationDateRange',
|
||
type: 'date',
|
||
range: true,
|
||
format: 'yyyy-MM-dd',
|
||
theme: 'dark',
|
||
max: 0,
|
||
done: function(value, date, endDate) {
|
||
// 日期范围选择完成
|
||
}
|
||
});
|
||
|
||
// 电气专业进度展示日期选择器
|
||
laydate.render({
|
||
elem: '#electricalDateRange',
|
||
type: 'date',
|
||
range: true,
|
||
format: 'yyyy-MM-dd',
|
||
theme: 'dark',
|
||
max: 0,
|
||
done: function(value, date, endDate) {
|
||
// 日期范围选择完成
|
||
}
|
||
});
|
||
}
|
||
|
||
// 初始化土建专业工序整体进度环形图
|
||
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 `
|
||
<div style="font-weight: bold; margin-bottom: 10px; color: #FFFFFF; font-size: 13px;">土建专业工序整体进度</div>
|
||
<div style="display: flex; align-items: center; min-width: 150px;">
|
||
<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: ${color}; margin-right: 10px; flex-shrink: 0;"></span>
|
||
<span style="color: #B9D6D9; margin-right: 10px;">${name}</span>
|
||
<span style="color: #FFFFFF; margin-left: auto; font-weight: bold;">${value.toFixed(2)}%</span>
|
||
</div>
|
||
`;
|
||
}
|
||
},
|
||
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);
|
||
}
|
||
|
||
// 初始化土建专业进度柱状图(中间柱状图)
|
||
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 = `<div style="font-weight:bold;margin-bottom:8px;color:#FFFFFF;font-size:13px;">${name}</div>`;
|
||
params.forEach(function (item) {
|
||
// 只显示bar类型的tooltip,不显示pictorialBar
|
||
if (item.componentSubType === "bar") {
|
||
const color = item.color;
|
||
html += `
|
||
<div style="display:flex;align-items:center;margin-bottom:4px;min-width:140px;">
|
||
<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${color};margin-right:8px;flex-shrink:0;"></span>
|
||
<span style="color:#B9D6D9;margin-right:6px;">${item.seriesName}</span>
|
||
<span style="color:#FFFFFF;margin-left:auto;font-weight:bold;">${item.value}</span>
|
||
</div>
|
||
`;
|
||
}
|
||
});
|
||
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 = `<div style="font-weight:bold;margin-bottom:8px;color:#FFFFFF;font-size:13px;">${name}</div>`;
|
||
params.forEach(function (item) {
|
||
// 只显示bar类型的tooltip,不显示pictorialBar
|
||
if (item.componentSubType === "bar") {
|
||
const color = item.color;
|
||
html += `
|
||
<div style="display:flex;align-items:center;margin-bottom:4px;min-width:140px;">
|
||
<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${color};margin-right:8px;flex-shrink:0;"></span>
|
||
<span style="color:#B9D6D9;margin-right:6px;">${item.seriesName}</span>
|
||
<span style="color:#FFFFFF;margin-left:auto;font-weight:bold;">${item.value}</span>
|
||
</div>
|
||
`;
|
||
}
|
||
});
|
||
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 `
|
||
<div style="font-weight: bold; margin-bottom: 10px; color: #FFFFFF; font-size: 13px;">变电专业工序整体进度</div>
|
||
<div style="display: flex; align-items: center; min-width: 150px;">
|
||
<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: ${color}; margin-right: 10px; flex-shrink: 0;"></span>
|
||
<span style="color: #B9D6D9; margin-right: 10px;">${name}</span>
|
||
<span style="color: #FFFFFF; margin-left: auto; font-weight: bold;">${value.toFixed(2)}%</span>
|
||
</div>
|
||
`;
|
||
}
|
||
},
|
||
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);
|
||
}
|
||
|
||
// 初始化异常工序预警列表
|
||
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 `
|
||
<div class="warning-item">
|
||
<div class="warning-icon"></div>
|
||
<div class="warning-text" title="${fullText}">
|
||
${fullText}
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).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: 'processName', title: '工序名称', width: '15%', align: 'center'},
|
||
{field: 'personnelInput', title: '投入人员', width: '12%', align: 'center'},
|
||
{field: 'equipmentInput', title: '投入设备', width: '12%', align: 'center'},
|
||
{field: 'plannedProgress', title: '当前计划进度', width: '15%', align: 'center'},
|
||
{field: 'actualProgress', title: '实际进度', width: '15%', align: 'center'},
|
||
{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: 'processName', title: '工序名称', width: '15%', align: 'center'},
|
||
{field: 'personnelInput', title: '投入人员', width: '12%', align: 'center'},
|
||
{field: 'equipmentInput', title: '投入设备', width: '12%', align: 'center'},
|
||
{field: 'plannedProgress', title: '当前计划进度', width: '15%', align: 'center'},
|
||
{field: 'actualProgress', title: '实际进度', width: '15%', align: 'center'},
|
||
{field: 'analysis', title: '分析', width: '23%', align: 'left'}
|
||
]]
|
||
});
|
||
}
|
||
|
||
// 查询土建专业进度
|
||
function queryCivilProgress() {
|
||
const dateRange = $('#civilDateRange').val();
|
||
// 重新加载图表数据
|
||
getCivilProgressData(dateRange);
|
||
}
|
||
|
||
// 查询电气专业进度
|
||
function queryElectricalProgress() {
|
||
const dateRange = $('#electricalDateRange').val();
|
||
// 重新加载图表数据
|
||
getElectricalProgressData(dateRange);
|
||
}
|
||
|
||
// 查询土建专业进度偏差
|
||
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 getCivilProgressData(dateRange) {
|
||
const bidCode = parent.parent.$('#bidPro').val() || '';
|
||
const url = commonUrl + 'screen/largeScreen/dataAnalysis/getCivilProgress';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
headers: {
|
||
decrypt: 'decrypt',
|
||
Authorization: token
|
||
},
|
||
data: {
|
||
bidCode: bidCode,
|
||
dateRange: dateRange
|
||
},
|
||
success: function(res) {
|
||
if (res.code === 200 && res.data) {
|
||
updateCivilProgressChart(res.data);
|
||
updateCivilProgressBarChart(res.data);
|
||
}
|
||
},
|
||
error: function(err) {
|
||
console.error('获取土建专业进度数据失败:', err);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新土建专业进度图表
|
||
function updateCivilProgressChart(data) {
|
||
if (!civilProgressChart) return;
|
||
// 更新环形图数据
|
||
// 后续实现
|
||
}
|
||
|
||
// 更新土建专业进度柱状图
|
||
function updateCivilProgressBarChart(data) {
|
||
if (!civilProgressBarChart || !Array.isArray(data)) return;
|
||
|
||
const categories = data.map(item => item.processName || item.name || '');
|
||
const plannedData = data.map(item => item.planned || item.plan || 0);
|
||
const actualData = data.map(item => item.actual || item.real || 0);
|
||
|
||
civilProgressBarChart.setOption({
|
||
xAxis: { data: categories },
|
||
series: [
|
||
{ name: '计划', data: plannedData },
|
||
{ name: '实际', data: actualData }
|
||
]
|
||
});
|
||
}
|
||
|
||
// 获取电气专业进度数据(接口调用)
|
||
function getElectricalProgressData(dateRange) {
|
||
const bidCode = parent.parent.$('#bidPro').val() || '';
|
||
const url = commonUrl + 'screen/largeScreen/dataAnalysis/getElectricalProgress';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
headers: {
|
||
decrypt: 'decrypt',
|
||
Authorization: token
|
||
},
|
||
data: {
|
||
bidCode: bidCode,
|
||
dateRange: dateRange
|
||
},
|
||
success: function(res) {
|
||
if (res.code === 200 && res.data) {
|
||
updateElectricalProgressChart(res.data);
|
||
updateElectricalProgressBarChart(res.data);
|
||
}
|
||
},
|
||
error: function(err) {
|
||
console.error('获取电气专业进度数据失败:', err);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新电气专业进度图表
|
||
function updateElectricalProgressChart(data) {
|
||
if (!electricalProgressChart) return;
|
||
// 更新环形图数据
|
||
// 后续实现
|
||
}
|
||
|
||
// 更新电气专业进度柱状图
|
||
function updateElectricalProgressBarChart(data) {
|
||
if (!electricalProgressBarChart || !Array.isArray(data)) return;
|
||
|
||
const categories = data.map(item => item.processName || item.name || '');
|
||
const plannedData = data.map(item => item.planned || item.plan || 0);
|
||
const actualData = data.map(item => item.actual || item.real || 0);
|
||
|
||
electricalProgressBarChart.setOption({
|
||
xAxis: { data: categories },
|
||
series: [
|
||
{ name: '计划', data: plannedData },
|
||
{ name: '实际', data: actualData }
|
||
]
|
||
});
|
||
}
|