CNCEC_SUBQHSE_WUHUAN/SGGL/FineUIPro.Web/JDGL/SGManPower/ManPowerStat.aspx

721 lines
24 KiB
Plaintext
Raw Normal View History

2025-08-11 14:21:24 +08:00
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ManPowerStat.aspx.cs" Inherits="FineUIPro.Web.JDGL.SGManPower.ManPowerStat" %>
<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>人力统计</title>
<link href="../../res/index/css/reset.css" rel="stylesheet" />
<link href="../../res/index/css/home.css" rel="stylesheet" />
<link href="../../res/index/css/swiper-3.4.2.min.css" rel="stylesheet" />
<style type="text/css">
* {
box-sizing: border-box;
}
.flexV {
flex-direction: column;
}
.wrap {
height: 100%;
padding: 15px;
background-color: #FFFFFF;
}
.iteml {
margin-left: 5px;
}
.itemb {
margin-bottom: 5px;
}
.bottom-wrap {
padding: 0;
margin-bottom: 5px;
}
.bottom-wrap:last-child {
margin-bottom: 0;
}
.bw-b-bottom {
width: 100%;
height: 100%;
}
.bw-b-bottom-up {
border-radius: 0;
height: 100%;
margin: 0;
box-shadow: none;
}
.bw-item-content {
padding: 5px;
}
.top {
width: 100%;
}
.bw-b {
width: 50%;
}
.tab-wrap {
left: auto;
right: 15px;
top: 5px;
font-size: 12px;
}
.tab .t-item {
width: auto;
padding: 5px 10px;
color: #363636;
}
.tit-item {
padding: 0 10px;
justify-content: space-between;
font-size: 12px;
}
.tab-wrap .tab .t-item {
color: #1C1C1C;
}
.tip-item {
margin-left: 10px;
align-items: center;
font-size: 10px;
}
.tip {
width: 25px;
height: 13px;
background-color: #258F76;
border-radius: 2px;
margin-right: 5px;
}
.tip-next {
background-color: #4F4F4F;
}
.myTableClass {
width: 100%;
height: 100%;
overflow: auto;
margin: 2px 1px;
border-collapse: collapse;
border: 1px solid #BEBEBE;
background: #ffffff;
color: #8B8989;
text-align: center;
font-size: 14px;
}
.tab-title {
height: 48px;
color: #3CB371;
font-size: 16px;
font-weight: 700;
}
.tab-header {
height: 36px;
color: #1C86EE;
font-size: 14px;
font-weight: 600;
}
td, th {
border: 1px solid #BEBEBE;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.filter-options {
justify-content: flex-end;
padding: 10px;
background-color: #f8f8f8;
border-bottom: 1px solid #ddd;
}
.filter-options label {
margin-left: 10px;
font-size: 14px;
color: #333;
}
.filter-options input[type="radio"] {
margin-right: 5px;
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: none;
justify-content: center;
align-items: center;
z-index: 9999;
}
.loading-spinner {
width: 50px;
height: 50px;
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.chart-container {
width: 100%;
height: 100%;
min-height: 300px;
}
.error-message {
color: red;
text-align: center;
padding: 20px;
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="filter-options">
<label>
<input type="radio" name="data-filter" value="total" checked> 总数
</label>
<label>
<input type="radio" name="data-filter" value="annual"> 年度
</label>
<select id="year-select" style="display: none; margin-left: 10px; padding: 2px; font-size: 14px;">
<!-- 年份选项将通过JavaScript动态填充 -->
</select>
<label>
<input type="radio" name="data-filter" value="monthly"> 月度
</label>
<select id="month-select" style="display: none; margin-left: 10px; padding: 2px; font-size: 14px;">
<option value="1">1月</option>
<option value="2">2月</option>
<option value="3">3月</option>
<option value="4">4月</option>
<option value="5">5月</option>
<option value="6">6月</option>
<option value="7">7月</option>
<option value="8">8月</option>
<option value="9">9月</option>
<option value="10">10月</option>
<option value="11">11月</option>
<option value="12">12月</option>
</select>
</div>
<div class="wrap flex flexV">
<div class="bottom-wrap flex1">
<div class="top flex">
<div class="item flex2 iteml">
<div class="bw-b-bottom">
<div class="bw-b-bottom-up">
<div class="bw-item-content">
<div id='one' class="chart-container"></div>
<div id='one-error' class="error-message"></div>
</div>
</div>
</div>
</div>
<div class="item flex2 iteml">
<div class="bw-b-bottom">
<div class="bw-b-bottom-up">
<div class="bw-item-content">
<div id='two' class="chart-container"></div>
<div id='two-error' class="error-message"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottom-wrap flex1">
<div class="top flex">
<div class="item flex2 iteml">
<div class="bw-b-bottom">
<div class="bw-b-bottom-up">
<div class="bw-item-content">
<div id='three' class="chart-container"></div>
<div id='three-error' class="error-message"></div>
</div>
</div>
</div>
</div>
<div class="item flex2 iteml">
<div class="bw-b-bottom">
<div class="bw-b-bottom-up">
<div class="bw-item-content">
<div id='four' class="chart-container"></div>
<div id='four-error' class="error-message"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 加载动画 -->
<div id="loadingOverlay" class="loading-overlay">
<div class="loading-spinner"></div>
</div>
</body>
<script type="text/javascript" src="../../res/index/js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="../../res/index/js/swiper-3.4.2.jquery.min.js"></script>
<script type="text/javascript" src="../../res/index/js/echarts.min.js"></script>
<script type="text/javascript">
// 存储各图表的实例
var chartInstances = {};
// 页面加载完成后初始化图表
$(document).ready(function() {
// 填充年份下拉框
populateYearSelect();
// 获取当前URL中的type参数如果没有则默认为total
var urlParams = new URLSearchParams(window.location.search);
var currentType = urlParams.get('type') || 'total';
// 设置对应的单选按钮为选中状态
$('input[name="data-filter"][value="' + currentType + '"]').prop('checked', true);
// 根据选中的类型显示/隐藏年份下拉框
toggleYearSelect(currentType);
// 初始化图表
loadAndRenderCharts(currentType);
// 监听单选按钮变化事件
$('input[name="data-filter"]').change(function() {
var dataType = $(this).val();
toggleYearSelect(dataType);
});
// 监听年份下拉框变化事件
$('#year-select').change(function() {
var dataType = $('input[name="data-filter"]:checked').val();
if (dataType === 'annual' || dataType === 'monthly') {
loadAndRenderCharts(dataType);
}
});
// 监听月份下拉框变化事件
$('#month-select').change(function() {
var dataType = $('input[name="data-filter"]:checked').val();
if (dataType === 'monthly') {
loadAndRenderCharts(dataType);
}
});
});
// 填充年份下拉框
function populateYearSelect() {
var currentYear = new Date().getFullYear();
var yearSelect = $('#year-select');
// 添加最近10年的选项
for (var i = currentYear; i >= currentYear - 10; i--) {
yearSelect.append($('<option></option>').attr('value', i).text(i));
}
// 默认选中当前年份
yearSelect.val(currentYear);
}
// 根据选中的数据类型显示/隐藏年份下拉框
function toggleYearSelect(dataType) {
if (dataType === 'annual') {
$('#year-select').show();
$('#month-select').hide();
// 不再立即触发数据查询,只显示年份选择框
} else if (dataType === 'monthly') {
$('#year-select').show();
$('#month-select').show();
// 不再立即触发数据查询,只显示年份和月份选择框
} else {
$('#year-select').hide();
$('#month-select').hide();
}
}
// 通过Ajax加载数据并渲染图表
function loadAndRenderCharts(type) {
// 显示加载状态
showLoading();
// 隐藏所有错误信息
$('.error-message').hide();
// 获取选中的年份或月份
var selectedYear = $('#year-select').val();
var selectedMonth = $('#month-select').val();
// 使用Ajax并行获取四个图表的数据
$.when(
$.ajax({
url: 'ManPowerStat.aspx/GetChartData',
type: 'POST',
data: JSON.stringify(createParams(type, 'One', selectedYear, selectedMonth)),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
timeout: 30000 // 30秒超时
}),
$.ajax({
url: 'ManPowerStat.aspx/GetChartData',
type: 'POST',
data: JSON.stringify(createParams(type, 'Two', selectedYear, selectedMonth)),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
timeout: 30000
}),
$.ajax({
url: 'ManPowerStat.aspx/GetChartData',
type: 'POST',
data: JSON.stringify(createParams(type, 'Three', selectedYear, selectedMonth)),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
timeout: 30000
}),
$.ajax({
url: 'ManPowerStat.aspx/GetChartData',
type: 'POST',
data: JSON.stringify(createParams(type, 'Four', selectedYear, selectedMonth)),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
timeout: 30000
})
).done(function(oneResult, twoResult, threeResult, fourResult) {
try {
// 渲染四个图表
renderChart('one', oneResult[0].d, '五环管理人员统计分析');
renderChart('two', twoResult[0].d, '施工单位管理人员统计分析');
renderChart('three', threeResult[0].d, '作业人员统计分析');
renderChart('four', fourResult[0].d, '过程人力统计分析');
} catch (e) {
console.error('图表渲染错误:', e);
showError('图表渲染失败,请重试');
}
// 隐藏加载状态
hideLoading();
}).fail(function(jqXHR, textStatus, errorThrown) {
// 处理错误情况
console.error('Ajax请求失败:', textStatus, errorThrown);
console.error('响应内容:', jqXHR.responseText);
var errorMessage = '数据加载失败';
if (textStatus === 'timeout') {
errorMessage = '请求超时,请重试';
} else if (jqXHR.responseText) {
try {
var errorResponse = JSON.parse(jqXHR.responseText);
if (errorResponse.Message) {
errorMessage = errorResponse.Message;
}
} catch (e) {
errorMessage = jqXHR.responseText;
}
}
showError(errorMessage);
hideLoading();
});
}
// 创建传递给后端的参数对象
function createParams(type, chart, year, month) {
debugger
var params = {
type: type,
chart: chart ,
year:null,
month:null,
};
// 只有在需要时才添加year和month参数
if (type === 'annual' && year) {
params.year = year;
} else if (type === 'monthly' && year && month) {
params.year = year;
params.month = month;
}
// 确保参数对象中不包含值为undefined的属性
for (var key in params) {
if (params[key] === undefined) {
delete params[key];
}
}
return params;
}
// 渲染单个图表的通用方法
function renderChart(chartId, data, title) {
try {
// 隐藏错误信息
$('#' + chartId + '-error').hide();
// 解析数据
var chartData;
if (typeof data === 'string') {
chartData = JSON.parse(data);
} else {
chartData = data;
}
// 验证数据
if (!chartData || !chartData.categories || !chartData.series) {
throw new Error('数据格式不正确');
}
// 如果图表实例已存在,先销毁
if (chartInstances[chartId]) {
chartInstances[chartId].dispose();
}
var chartContainer = document.getElementById(chartId);
if (!chartContainer) {
throw new Error('找不到图表容器: ' + chartId);
}
var myChart = echarts.init(chartContainer);
var xArr = chartData.categories;
var num = chartData.xFontNum || 6;
// 确保series数据存在
var seriesData = [];
if (chartData.series && chartData.series.length >= 2) {
seriesData = [
{
name: '计划',
type: 'line',
data: chartData.series[1].data || [],
label: {
show: true,
position: 'top',
textStyle: {
fontSize: '12px',
color: '#363636'
},
formatter: function (params) {
return params.value === 0 ? '' : params.value;
},
},
itemStyle: { normal: { color: 'rgba(255,0,0, 0.5)' } },
smooth: true
},
{
name: '实际',
type: 'line',
data: chartData.series[0].data || [],
label: {
show: true,
position: 'top',
textStyle: {
fontSize: '12px',
color: '#363636'
},
formatter: function (params) {
return params.value === 0 ? '' : params.value;
},
},
itemStyle: { normal: { color: 'rgba(0,100,0,0.8)' } },
smooth: true
}
];
}
var option = {
title: {
text: title,
textStyle: {
color: '#1C1C1C',
fontSize: 16,
fontWeight: 700
},
show: true
},
tooltip: {},
legend: {
left: '80%',
show: true,
textStyle: {
color: '#363636',
fontSize: 12,
}
},
dataZoom: [
{
type: 'slider',
maxValueSpan: 6,
show: xArr && xArr.length > 6, // 只有数据超过6个才显示缩放
xAxisIndex: [0],
bottom: 0, height: 10,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'none',
brushSelect: false,
textStyle: {
color: 'rgba(0,0,0,0)'
},
selectedDataBackground: {
areaStyle: {
color: 'red',
borderWidth: 0
}
},
handleStyle: {
color: "#0a1449"
},
moveHandleStyle: {
color: '#0a1449'
}
}
],
xAxis: {
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: 'rgba(0,0,0, 0.3)',
}
},
axisLabel: {
show: true,
textStyle: {
color: 'rgba(0,0,0, 0.8)'
},
interval: 0,
rotate: -15,
formatter: function (value) {
if (!value) return '';
var ret = "";
var maxLength = num;
var valLength = value.length;
var rowN = Math.ceil(valLength / maxLength);
if (rowN > 1) {
for (var i = 0; i < rowN; i++) {
var temp = "";
var start = i * maxLength;
var end = start + maxLength;
temp = value.substring(start, end) + (i == rowN - 1 ? "" : "\n");
ret += temp;
}
return ret;
} else {
return value;
}
}
},
type: 'category',
data: xArr || [],
boundaryGap: [0, 0.01],
},
yAxis: {
axisTick: {
show: false
},
axisLine: {
show: false,
lineStyle: {
color: 'rgba(0,0,0, 0.3)'
}
},
axisLabel: {
show: true,
textStyle: {
color: 'rgba(0,0,0, 0.8)'
}
},
},
series: seriesData,
grid: {
top: '20%',
left: '0%',
right: '0%',
bottom: 40,
containLabel: true,
backgroundColor: 'rgba(0,162,233, 0.01)',
},
backgroundColor: 'rgba(0,162,233, 0.01)',
textStyle: {
color: 'rgba(0,0,0, 0.3)'
}
};
myChart.setOption(option);
chartInstances[chartId] = myChart;
// 监听窗口大小变化,重新调整图表大小
var resizeHandler = function() {
if (chartInstances[chartId]) {
chartInstances[chartId].resize();
}
};
// 避免重复绑定事件
if (window.addEventListener) {
window.removeEventListener('resize', resizeHandler);
window.addEventListener('resize', resizeHandler);
}
} catch (e) {
console.error('渲染图表失败 [' + chartId + ']:', e);
showError('图表渲染失败: ' + e.message, chartId);
}
}
// 显示错误信息
function showError(message, chartId) {
if (chartId) {
$('#' + chartId + '-error').text(message).show();
} else {
// 全局错误显示
alert(message);
}
}
// 显示加载状态
function showLoading() {
document.getElementById('loadingOverlay').style.display = 'flex';
}
// 隐藏加载状态
function hideLoading() {
document.getElementById('loadingOverlay').style.display = 'none';
}
</script>
</html>