chenhaozhe
9 天以前 d2469cf65f097ce6d6faa6699ea252adcd3e954c
新增 质量每日运行状态分析 报表
1个文件已添加
1个文件已修改
559 ■■■■■ 已修改文件
WebTM/layuiadmin/Scripts/webConfig.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebTM/views/质量管理/质量报表/QC_DailyRunStateReport.html 555 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebTM/layuiadmin/Scripts/webConfig.js
@@ -4,8 +4,8 @@
  //var WEBURL = "http://localhost/API/";             //颜晓军本地配置
  //var WEBURL = "http://localhost:8082/API/";        //杜贺本地配置
  //var WEBURL = "http://localhost:81/API/"           //翁涛涛本地配置
   var WEBURL = "http://localhost:8082/API/"; //张瑞广本地配置
  // var WEBURL = "http://localhost:81/API/";          //陈镐哲本地配置
  // var WEBURL = "http://localhost:8082/API/"; //张瑞广本地配置
  var WEBURL = "http://localhost:81/API/";          //陈镐哲本地配置
  //var WEBURL = "http://localhost:8082/LuBaoAPI/";   //李林俊本地配置
  //var WEBURL = "http://localhost:8080/API/";        //王仪本地配置
  //var WEBURL = "http://localhost:8082/LuBaoAPI/";   //余思杰本地配置
WebTM/views/ÖÊÁ¿¹ÜÀí/ÖÊÁ¿±¨±í/QC_DailyRunStateReport.html
New file
@@ -0,0 +1,555 @@
<!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/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>
    <script src="../../../layuiadmin/Scripts/webConfig.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 }
                shoujian:  { chartTitle: '首检记录统计', chartType: 'bar', dataTableIndex: 0 },
                xunjian:  { chartTitle: '巡检记录统计', chartType: 'bar', dataTableIndex: 1 },
                mojian:  { chartTitle: '末检记录统计', chartType: 'bar', dataTableIndex: 2 },
                kucunjian:  { chartTitle: '库存检验记录统计', chartType: 'bar', dataTableIndex: 3 },
                chejianzijian:  { chartTitle: '车间自检记录统计', chartType: 'bar', dataTableIndex: 4 },
                lailiaorukujian:  { chartTitle: '来料入库检验统计', chartType: 'bar', dataTableIndex: 5 },
                shengchanrukujian:  { chartTitle: '生产入库检验统计', chartType: 'bar', dataTableIndex: 6 },
                chuchangjianyan:  { chartTitle: '出厂检验统计', chartType: 'bar', dataTableIndex: 7 },
                buliangpingchuli:  { chartTitle: '不良品处理统计', chartType: 'bar', dataTableIndex: 8 },
                buliangpingpingshengshengqing:  { chartTitle: '不良品评审申请统计', chartType: 'bar', dataTableIndex: 9 },
                buliangpingpingshengchuli:  { chartTitle: '不良品评审处理统计', chartType: 'bar', dataTableIndex: 10 },
                buliangpingpingshengyanshou:  { chartTitle: '不良品评审验收统计', chartType: 'bar', dataTableIndex: 11 },
                buliangpingpingshengyanshou:  { chartTitle: '不良品评审结论统计', chartType: 'bar', dataTableIndex: 12 },
                yichangfankui:  { chartTitle: '异常反馈统计', chartType: 'bar', dataTableIndex: 13 },
                yichangfankuiyanshou:  { chartTitle: '异常反馈验收统计', chartType: 'bar', dataTableIndex: 14 },
                yichangfankuiqiandao:  { chartTitle: '异常反馈签到统计', chartType: 'bar', dataTableIndex: 15 },
                yichangfankuichuli:  { chartTitle: '异常反馈处理统计', chartType: 'bar', dataTableIndex: 16 },
                yichangfankuiyanshou:  { chartTitle: '异常反馈验收统计', chartType: 'bar', dataTableIndex: 17 },
                jianyanquyang:  { chartTitle: '检验取样统计', chartType: 'bar', dataTableIndex: 18 },
                jianyanhuanyang:  { chartTitle: '检验还样统计', chartType: 'bar', dataTableIndex: 19 },
            };
            // ç”Ÿæˆé¡µé¢ç»“æž„
            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() + '/QC_CustomerAppealReport/QC_DailyRunStateReportList',
                    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_QC_DailyRunStateReport" + (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>