|
<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>设备每日运行状态报表</title>
|
<meta name="renderer" content="webkit">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
<link rel="stylesheet" href="../../../layuiadmin/layui/css/layui.css" media="all">
|
<link rel="stylesheet" href="../../../layuiadmin/style/admin.css" media="all">
|
<script src="../../../layuiadmin/layui/layui.js"></script>
|
<script src="../../../layuiadmin/Scripts/json2.js"></script>
|
<script src="../../../layuiadmin/Scripts/jquery-1.4.1.js"></script>
|
<script src="../../../layuiadmin/Scripts/webConfig.js"></script>
|
<script src="../../../layuiadmin/PubCustom.js"></script>
|
<script src="../../../layuiadmin/zgqCustom/zgqCustom.js"></script>
|
<script src="../../../layuiadmin/HideButton.js"></script>
|
<script src='../../../layuiadmin/lib/extend/echarts.min.js'></script>
|
<style type="text/css">
|
* {
|
margin: 0;
|
padding: 0;
|
box-sizing: border-box;
|
}
|
|
html, body {
|
height: 100%;
|
}
|
|
.page-container {
|
height: 100%;
|
padding: 10px;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.query-bar {
|
background: #fff;
|
padding: 10px 15px;
|
border-radius: 6px;
|
margin-bottom: 10px;
|
flex-shrink: 0;
|
}
|
|
.summary-row {
|
display: flex;
|
flex-wrap: wrap;
|
margin-bottom: 10px;
|
flex-shrink: 0;
|
}
|
|
.chart-container {
|
background: #fff;
|
border-radius: 6px;
|
padding: 8px;
|
flex: 1;
|
overflow: auto;
|
min-height: 0;
|
display: grid;
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
gap: 8px;
|
}
|
|
.chart-box {
|
margin: 4px;
|
border: 1px solid #eee;
|
border-radius: 4px;
|
background: #fafbfc;
|
position: relative;
|
min-height: 260px;
|
display: flex;
|
align-items: stretch;
|
justify-content: stretch;
|
}
|
|
.empty-tip {
|
position: absolute;
|
left: 0;
|
top: 0;
|
width: 100%;
|
height: 100%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
color: #999;
|
font-size: 12px;
|
}
|
|
.summary-card {
|
margin: 4px;
|
border: 1px solid #eee;
|
border-radius: 4px;
|
background: #fafbfc;
|
text-align: center;
|
padding: 8px 4px;
|
min-width: 200px;
|
}
|
|
.summary-card.total-card {
|
background: linear-gradient(135deg, #1e9fff 0%, #5fb3ff 100%);
|
border-color: #1e9fff;
|
}
|
|
.summary-card.total-card .summary-number,
|
.summary-card.total-card .summary-label {
|
color: #fff;
|
}
|
|
.summary-number {
|
font-size: 16px;
|
font-weight: bold;
|
color: #1e9fff;
|
}
|
|
.summary-label {
|
font-size: 11px;
|
color: #888;
|
margin-top: 2px;
|
}
|
</style>
|
</head>
|
<body>
|
<div class="page-container">
|
<div class="query-bar">
|
<form class="layui-form" action="" lay-filter="component-form-group">
|
<div class="layui-collapse">
|
<div class="layui-colla-item">
|
<div class="layui-colla-title layui-inline">
|
<div class="layui-inline"><span>更多</span></div>
|
</div>
|
<div class="layui-inline">
|
<label class="layui-form-label" style="width:100px;">日期间隔</label>
|
<div class="layui-input-block">
|
<select name="HInitTimeCycle" id="HInitTimeCycle" class="ForFilteringSchemes" lay-filter="HInitTimeCycle" style="width:190px;">
|
</select>
|
</div>
|
</div>
|
<div class="layui-inline">
|
<label class="layui-form-label" style="width:100px;">开始日期</label>
|
<div class="layui-input-block">
|
<input type="date" class="layui-input ForFilteringSchemes" id="HBeginDate" style="width:160px;">
|
</div>
|
</div>
|
<div class="layui-inline">
|
<label class="layui-form-label" style="width:100px;">结束日期</label>
|
<div class="layui-input-block">
|
<input type="date" class="layui-input ForFilteringSchemes" id="HEndDate" style="width:160px;">
|
</div>
|
</div>
|
<button class="layui-btn layuiadmin-btn-order" type="button" lay-submit="" lay-filter="btnSearch" id="btnSearch">
|
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
|
</button>
|
<button class="layui-btn layuiadmin-btn-order" type="button" lay-submit="" lay-filter="btnReSearch" id="btnReSearch" style="padding:0 5px">重置</button>
|
</div>
|
<div class="layui-colla-content">
|
</div>
|
</div>
|
</form>
|
</div>
|
|
<div class="summary-row" id="summaryRow"></div>
|
<div class="chart-container" id="chartContainer"></div>
|
</div>
|
|
<script>
|
layui.config({
|
base: '../../../layuiadmin/'
|
}).extend({
|
index: 'lib/index',
|
}).use(['index', 'form', 'element'], function () {
|
|
var $ = layui.$, layer = layui.layer, form = layui.form;
|
var chartInstances = {};
|
var chartConfigKeys = [];
|
|
// 图表配置
|
var ChartConfig = {
|
dianjian: { chartTitle: '点检记录统计', chartType: 'bar', dataTableIndex: 0 },
|
baoyang: { chartTitle: '保养记录统计', chartType: 'bar', dataTableIndex: 1 },
|
guzhang: { chartTitle: '故障登记统计', chartType: 'pie', dataTableIndex: 2 },
|
weixiupaigong: { chartTitle: '维修派工统计', chartType: 'pie', dataTableIndex: 3 },
|
weixiuqiandao: { chartTitle: '维修签到统计', chartType: 'bar', dataTableIndex: 4 },
|
weixiujilu: { chartTitle: '维修记录统计', chartType: 'bar', dataTableIndex: 5 },
|
weixiuyanshou: { chartTitle: '维修验收统计', chartType: 'pie', dataTableIndex: 6 },
|
kaiji: { chartTitle: '设备开机统计', chartType: 'pie', dataTableIndex: 7 },
|
tingji: { chartTitle: '设备停机统计', chartType: 'bar', dataTableIndex: 8 },
|
gongyidianjian: { chartTitle: '工艺点检统计', chartType: 'bar', dataTableIndex: 9 }
|
};
|
|
// 生成页面结构
|
function generatePageStructure() {
|
chartConfigKeys = [];
|
for (var key in ChartConfig) { chartConfigKeys.push(key); }
|
generateSummaryCards();
|
generateChartBoxes();
|
}
|
function generateSummaryCards() {
|
var $summaryRow = $('#summaryRow'); $summaryRow.empty();
|
$summaryRow.append('<div class="summary-card total-card" id="card-total"><div class="summary-number">0</div><div class="summary-label">总计</div></div>');
|
chartConfigKeys.forEach(key => {
|
var config = ChartConfig[key];
|
var label = config.chartTitle.replace('统计', '');
|
$summaryRow.append(`<div class="summary-card" id="card-${key}"><div class="summary-number">0</div><div class="summary-label">${label}</div></div>`);
|
});
|
}
|
function generateChartBoxes() {
|
var $c = $('#chartContainer'); $c.empty();
|
chartConfigKeys.forEach(key => {
|
$c.append(`<div class="chart-box" id="chart-${key}"><div class="empty-tip">暂无数据</div></div>`);
|
});
|
}
|
|
//查询
|
form.on('submit(btnReSearch)', function (data) {
|
set_ClearQuery();
|
});
|
//重置
|
form.on('submit(btnSearch)', function (data) {
|
get_FastQuery();
|
});
|
//日期间隔下拉列表监听
|
form.on('select(HInitTimeCycle)', function (data) {
|
var HInitTimeCycle = $("#HInitTimeCycle").val() * 1;
|
if (HInitTimeCycle != -1) {
|
$('#HBeginDate').prop('disabled', true);
|
$('#HEndDate').prop('disabled', true);
|
$("#HBeginDate").val(Format(new Date(new Date() - 1000 * 60 * 60 * 24 * HInitTimeCycle), "yyyy-MM-dd"));
|
$("#HEndDate").val(Format(new Date(), "yyyy-MM-dd"));
|
get_FastQuery();
|
} else {
|
$('#HBeginDate').prop('disabled', false);
|
$('#HEndDate').prop('disabled', false);
|
}
|
});
|
|
//初始化
|
function set_ClearBill() {
|
generatePageStructure();
|
setSelect_HInitTimeCycle();
|
var HInitTimeCycle = $("#HInitTimeCycle").val() * 1;
|
if (HInitTimeCycle != -1) {
|
$('#HBeginDate').prop('disabled', true);
|
$('#HEndDate').prop('disabled', true);
|
} else {
|
$('#HBeginDate').prop('disabled', false);
|
$('#HEndDate').prop('disabled', false);
|
}
|
$("#HBeginDate").val(Format(new Date(new Date() - 1000 * 60 * 60 * 24 * HInitTimeCycle), "yyyy-MM-dd"));
|
$("#HEndDate").val(Format(new Date(), "yyyy-MM-dd"));
|
get_FastQuery();
|
}
|
|
//重置
|
function set_ClearQuery() {
|
var today = Format(new Date(), "yyyy-MM-dd");
|
$("#HBeginDate").val(today);
|
$("#HEndDate").val(today);
|
get_FastQuery();
|
}
|
|
//初始日期间隔 下拉列表
|
function setSelect_HInitTimeCycle() {
|
var valueList = [0, 1, 2, 3, 4, 5, 6, 29];
|
var titleList = ["今天", "近两天", "近三天", "近四天", "近五天", "近六天", "近七天", "近30天"];
|
var HInitTimeCycle_ArrayList = '<option value="-1" selected="selected" >任意间隔</option>';
|
for (var i = 0; i < valueList.length; i++) {
|
HInitTimeCycle_ArrayList += '<option style="color:blue;" value="' + valueList[i] + '">' + titleList[i] + '</option>';
|
}
|
$("#HInitTimeCycle").empty().append(HInitTimeCycle_ArrayList);
|
$("#HInitTimeCycle").val("0");
|
form.render('select');
|
}
|
// ==============================================
|
// 查询 自动补齐所有日期(空数据=0)
|
// ==============================================
|
function get_FastQuery() {
|
var wait = layer.load();
|
var beginDate = $("#HBeginDate").val();
|
var endDate = $("#HEndDate").val();
|
|
var sWhere = JSON.stringify({ HBeginDate: beginDate, HEndDate: endDate });
|
var params = { sWhere: sWhere, user: sessionStorage["HUserName"] || '' };
|
|
$.ajax({
|
url: GetWEBURL() + 'Sb_EquipDotCheckTaskReport/Sb_EquipDailyRunStateList',
|
type: 'GET',
|
data: params,
|
success: function (result) {
|
var data = {};
|
var fullDateList = getDateRange(beginDate, endDate);
|
|
if (result && result.code == "1" && result.data) {
|
chartConfigKeys.forEach(key => {
|
var cfg = ChartConfig[key];
|
var tb = "h_p_Sb_EquipDailyRunStateReport" + (cfg.dataTableIndex > 0 ? cfg.dataTableIndex : "");
|
var list = (result.data[tb] && Array.isArray(result.data[tb])) ? result.data[tb] : [];
|
|
// 转 map(日期统一格式化)
|
var dataMap = {};
|
list.forEach(x => {
|
var date = x.日期 || "";
|
try {
|
date = Format(new Date(date), "yyyy-MM-dd");
|
} catch (e) {
|
date = "";
|
}
|
var num = parseInt(x.数量) || 0;
|
if (date) dataMap[date] = num;
|
});
|
|
// 补齐所有日期
|
data[key] = fullDateList.map(date => ({
|
name: date,
|
value: dataMap[date] || 0
|
}));
|
});
|
} else {
|
// 后端无有效数据:全部初始化为 0
|
chartConfigKeys.forEach(key => {
|
data[key] = fullDateList.map(date => ({ name: date, value: 0 }));
|
});
|
}
|
|
renderAll(data);
|
layer.close(wait);
|
},
|
error: function () {
|
var fullDateList = getDateRange(beginDate, endDate);
|
var data = {};
|
chartConfigKeys.forEach(key => {
|
data[key] = fullDateList.map(date => ({ name: date, value: 0 }));
|
});
|
renderAll(data);
|
layer.close(wait);
|
}
|
});
|
}
|
|
// ==============================================
|
// 生成开始~结束的所有日期(自动跨月/跨年)
|
// ==============================================
|
function getDateRange(startDate, endDate) {
|
var arr = [];
|
var start = new Date(startDate);
|
var end = new Date(endDate);
|
while (start <= end) {
|
arr.push(Format(start, "yyyy-MM-dd"));
|
start.setDate(start.getDate() + 1);
|
}
|
return arr;
|
}
|
|
// ==============================================
|
// 渲染所有图表和卡片(取消“全0跳过”,始终绘图)
|
// ==============================================
|
function renderAll(data) {
|
chartConfigKeys.forEach(key => {
|
var cfg = ChartConfig[key];
|
var d = data[key] || [];
|
var $chartBox = $('#chart-' + key);
|
var dom = $chartBox[0];
|
var chartKey = 'chart-' + key;
|
|
// 1. 销毁旧实例,断开 ResizeObserver 并清空容器
|
if (chartInstances[chartKey]) {
|
try {
|
if (chartInstances[chartKey]._resizeObserver) chartInstances[chartKey]._resizeObserver.disconnect();
|
} catch (e) { }
|
chartInstances[chartKey].dispose();
|
delete chartInstances[chartKey];
|
}
|
$chartBox.empty();
|
|
// 2. 更新卡片总数
|
var total = d.reduce((a, b) => a + b.value, 0);
|
$('#card-' + key + ' .summary-number').text(total);
|
|
// 3. 始终绘制图表(柱状图会显示0值柱子,饼图全0时特殊处理)
|
if (cfg.chartType === 'pie') {
|
// 饼图无论是否有0都绘制
|
renderPie(key, cfg.chartTitle, d);
|
} else if (cfg.chartType === 'bar') {
|
// 柱状图无论是否有0都绘制,让横轴日期完整展示
|
renderBar(key, cfg.chartTitle, d);
|
}
|
});
|
|
// 更新总计卡片
|
var totalAll = 0;
|
chartConfigKeys.forEach(key => {
|
var d = data[key] || [];
|
totalAll += d.reduce((a, b) => a + b.value, 0);
|
});
|
$("#card-total .summary-number").text(totalAll);
|
}
|
|
function renderPie(key, title, data) {
|
var dom = document.getElementById('chart-' + key);
|
var $chartBox = $('#chart-' + key);
|
$chartBox.empty();
|
|
var chart = echarts.init(dom);
|
chartInstances['chart-' + key] = chart;
|
// 自动响应容器尺寸变化(优先使用 ResizeObserver)
|
if (window.ResizeObserver) {
|
try {
|
var ro = new ResizeObserver(function () { try { chart.resize(); } catch (e) { } });
|
ro.observe(dom);
|
chart._resizeObserver = ro;
|
} catch (e) { }
|
}
|
|
// 计算总和
|
var total = data.reduce((s, x) => s + x.value, 0);
|
var isAllZero = total === 0;
|
|
// 绘制数据(全0时用极小值占位)
|
var pieData = data.map(x => ({
|
name: x.name,
|
value: isAllZero ? 0.0001 : x.value,
|
originalValue: x.value
|
}));
|
|
// 基础系列配置
|
var seriesConfig = {
|
type: 'pie',
|
radius: ['30%', '50%'],
|
data: pieData,
|
label: {
|
show: true,
|
fontSize: 11,
|
// 强制显示标签,防止被隐藏
|
overflow: 'none',
|
hideOverlap: false
|
},
|
labelLine: {
|
show: true,
|
length: 10,
|
length2: 8
|
},
|
avoidLabelOverlap: false // 允许标签重叠,确保都显示
|
};
|
|
chart.setOption({
|
title: { text: title, left: 'center', textStyle: { fontSize: 12 } },
|
tooltip: {
|
trigger: 'item',
|
formatter: function (params) {
|
return `${params.name}: ${params.data.originalValue}`;
|
}
|
},
|
series: [
|
// 第一层:外部显示日期
|
{
|
...seriesConfig,
|
label: {
|
...seriesConfig.label,
|
position: 'outside',
|
formatter: function (params) {
|
// 外部始终显示日期(名称)
|
return params.name;
|
}
|
}
|
},
|
// 第二层:内部显示数量(全0时也显示0)
|
{
|
...seriesConfig,
|
label: {
|
...seriesConfig.label,
|
position: 'inside',
|
formatter: function (params) {
|
// 内部显示原始数量,全0时显示 '0'
|
return params.data.originalValue;
|
}
|
},
|
labelLine: { show: false } // 内部不需要引导线
|
}
|
]
|
});
|
}
|
|
// ==============================================
|
// 柱状图渲染(支持全0数据,显示横轴标签和0值)
|
// ==============================================
|
function renderBar(key, title, data) {
|
var dom = document.getElementById('chart-' + key);
|
var chart = echarts.init(dom);
|
chartInstances['chart-' + key] = chart;
|
if (window.ResizeObserver) {
|
try {
|
var ro = new ResizeObserver(function () { try { chart.resize(); } catch (e) { } });
|
ro.observe(dom);
|
chart._resizeObserver = ro;
|
} catch (e) { }
|
}
|
var colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
|
|
chart.setOption({
|
title: { text: title, left: 'center', textStyle: { fontSize: 12 } },
|
tooltip: { trigger: 'axis' },
|
xAxis: { type: 'category', data: data.map(x => x.name) },
|
yAxis: { type: 'value' },
|
series: [{
|
type: 'bar',
|
data: data.map(x => x.value),
|
barWidth: '40%',
|
itemStyle: {
|
color: function (params) {
|
return colorList[params.dataIndex % colorList.length];
|
},
|
borderRadius: [4, 4, 0, 0]
|
},
|
label: {
|
show: true,
|
position: 'top',
|
fontSize: 11,
|
formatter: '{c}'
|
}
|
}]
|
});
|
}
|
// 初始化
|
set_ClearBill();
|
|
window.onresize = function () {
|
for (var k in chartInstances) {
|
if (chartInstances[k]) chartInstances[k].resize();
|
}
|
};
|
});
|
</script>
|
</body>
|
</html>
|