From 3d5cc34ad6e69be337399cb128199d236e7ea08e Mon Sep 17 00:00:00 2001 From: cqf <2252655793@qq.com> Date: 星期二, 24 五月 2022 17:51:16 +0800 Subject: [PATCH] 隐患图表接口对接 --- src/views/chartAnalysis/index.vue | 260 ++++++++++++++++----- src/views/common/jdSelect.vue | 394 ++++++++++++++++++++++++++++++++ src/api/sgyhpczl/chartAnalysis.js | 15 + 3 files changed, 606 insertions(+), 63 deletions(-) diff --git a/src/api/sgyhpczl/chartAnalysis.js b/src/api/sgyhpczl/chartAnalysis.js index bae5a80..6ffc711 100644 --- a/src/api/sgyhpczl/chartAnalysis.js +++ b/src/api/sgyhpczl/chartAnalysis.js @@ -14,3 +14,18 @@ data }); } + +export function chart_compare(data) { + return request({ + headers:{ + 'token': getTokenAndVerify().token, + 'verify':getTokenAndVerify().verify + }, + url: "/taboi/danger/chart_compare", + contentType: "application/json", + method: 'POST', + data + }); +} + + diff --git a/src/views/chartAnalysis/index.vue b/src/views/chartAnalysis/index.vue index e69c6d1..e6bea92 100644 --- a/src/views/chartAnalysis/index.vue +++ b/src/views/chartAnalysis/index.vue @@ -38,24 +38,30 @@ </el-form-item> <el-form-item style="margin-left: 30px;"> <el-radio-group v-model="formData.model"> - <el-radio label="1">按隐患单位</el-radio> - <el-radio label="2">按类别</el-radio> - <el-radio label="3">按级别</el-radio> - <el-radio label="4">按检查单位</el-radio> - <el-radio label="5">按录入单位</el-radio> - <el-radio label="6">按检查类别</el-radio> - <el-radio label="7">按当前警情</el-radio> + <el-radio label="0">按隐患单位</el-radio> + <el-radio label="1">按类别</el-radio> + <el-radio label="2">按级别</el-radio> + <el-radio label="3">按检查单位</el-radio> + <el-radio label="4">按录入单位</el-radio> + <el-radio label="5">按检查类别</el-radio> + <el-radio label="6">按当前警情</el-radio> </el-radio-group> - <el-radio-group v-model="chartType" style="margin-left: 50px;"> + <el-radio-group v-model="chartType" v-if="!THDB" style="margin-left: 50px;"> <el-radio label="line">曲线图</el-radio> <el-radio label="pie">饼状图</el-radio> <el-radio label="column">柱形图</el-radio> + </el-radio-group> + + <el-radio-group v-model="timeDes" v-if="THDB" @change="initTHDBTime" style="margin-left: 50px;"> + <el-radio label="month">月度</el-radio> + <el-radio label="quarter">季度</el-radio> + <el-radio label="year">年度</el-radio> </el-radio-group> </el-form-item> </div> <div class="center"> <el-form-item label="已选单位:"> - <el-input autosize v-model="form.name"></el-input> + <el-input autosize v-model="form.name"></el-input> </el-form-item> <el-form-item autosize label="已选类别:"> <el-input v-model="formData.ht_typesub.join(',')"></el-input> @@ -72,8 +78,9 @@ <el-form-item label="已选当前警情:"> <el-input v-model="formData.curWarningLevel.join(',')"></el-input> </el-form-item> - <el-form-item label="检查时间:" class="time"> + <el-form-item label="检查时间:" v-if="!THDB" class="time" style="width: 300px"> <el-date-picker + style="width: 218px" v-model="time" type="daterange" range-separator="至" @@ -81,11 +88,39 @@ end-placeholder="结束日期"> </el-date-picker> </el-form-item> + + <el-form-item label="对比时间:" v-if="THDB" class="time" style="width: 340px"> + <div v-if="timeDes!='quarter'"> + <el-date-picker + v-model="THDBBegin" + :type="timeDes" + style="width: 40%;float: left" + :value-format="timeDes=='month'?'yyyy年MM月':'yyyy年'" + :placeholder="timeDes=='month'?'请选择月':'请选择年'"> + </el-date-picker> + <span style="width: 20px">-</span> + <el-date-picker + v-model="THDBEnd" + :type="timeDes" + :value-format="timeDes=='month'?'yyyy年MM月':'yyyy年'" + style="width: 40%" + :placeholder="timeDes=='month'?'请选择月':'请选择年'"> + </el-date-picker> + </div> + <div v-if="timeDes=='quarter'"> + + <el-quarter-picker v-model="THDBBegin" style="width: 45%" placeholder="选择季度"/> + <span style="width: 20px">-</span> + <el-quarter-picker v-model="THDBEnd" style="width: 45%" placeholder="选择季度"/> + </div> + + </el-form-item> + <el-form-item> <el-button class="btn" size="small" type="primary" @click="getData()" >汇总 </el-button> - <el-button class="btn" size="small" type="primary" @click="close()" + <el-button v-if="!THDB" class="btn" size="small" type="primary" @click="THDB=true" >同比环比 </el-button> </el-form-item> @@ -100,7 +135,8 @@ <div class="legend-body"> <div v-for="(item,index) in this.columnChartData.xList" class="legend-item"> - <div :class="'legendItemBack'+index"></div>{{item}} + <div :class="'legendItemBack'+index"></div> + {{ item }} </div> </div> </div> @@ -109,7 +145,7 @@ </template> <script> import {echarts} from "../../global"; -import {chart_analysis} from "@/api/sgyhpczl/chartAnalysis"; +import {chart_analysis,chart_compare} from "@/api/sgyhpczl/chartAnalysis"; import { initJCBM, initYHLX, @@ -126,6 +162,7 @@ import loadExporting from "highcharts/modules/exporting"; import exportExcel from "highcharts/modules/export-data.src"; import highcharts3d from 'highcharts/highcharts-3d' +import ElQuarterPicker from "../common/jdSelect"; loadExporting(Highcharts); exportExcel(Highcharts); @@ -134,8 +171,11 @@ export default { name: "index", + components: {ElQuarterPicker}, + data() { return { + value: '', form: { name: '众泰煤焦化', time: '', @@ -148,7 +188,7 @@ }, formData: { "echart_type": "line", //line:折线图;column:柱状图;pie :饼状图 - "model": "1", //0: + "model": "0", //0: "beginTime": "", //开始时间 "endTime": "", //结束时间 "ht_typesub": [], //隐患类别 @@ -174,8 +214,12 @@ JCLBList: [], YHBMList: [], YHJBList: [], + THDB: false, + THDBBegin: "", + THDBEnd: "", + timeDes: "month", YHZTList: [], - columnXData:[] + columnXData: [] } }, mounted() { @@ -187,17 +231,38 @@ this.initLlr() this.initYHBM() this.initYHZT() - this.changeJCDW(0) + this.changeJCDW(1) this.getData() + this.initTHDBTime() }, watch: { "chartType": function (newVal, oldVal) { this.formData.echart_type = newVal; - console.log(this.formData.echart_type) this.getData(); - } + }, + "formData.model": function (newVal, oldVal) { + this.formData.model = newVal; + this.getData(); + + }, + // "timeDes": function (newVal, oldVal) { + // this.initTHDBTime(); + // } }, methods: { + initTHDBTime() { + var dayStr = this.getCurrentMonthFirst(); + if (this.timeDes == "month") { + this.THDBBegin = dayStr.split("-")[0] + "年" + (parseInt(dayStr.split("-")[1]) - 1) + "月"; + this.THDBEnd = dayStr.split("-")[0] + "年" + (dayStr.split("-")[1]) + "月"; + } else if (this.timeDes == "year") { + this.THDBBegin = (parseInt(dayStr.split("-")[0]) - 1) + "年"; + this.THDBEnd = dayStr.split("-")[0] + "年"; + } else { + this.THDBBegin = dayStr.split("-")[0] + "年第1季度"; + this.THDBEnd = dayStr.split("-")[0] + "年第2季度"; + } + }, initYHLX() { initYHLX().then(res => { if (res.data.ok == 1) { @@ -220,7 +285,6 @@ initReformStatus().then(res => { if (res.data.ok == 1) { this.YHZTList = res.data.data - console.log(this.YHZTList) } else { this.$message({type: 'error', message: res.data.msg, duration: 3000}) } @@ -313,24 +377,72 @@ getData() { this.formData.beginTime = this.time[0] this.formData.endTime = this.time[1] + if(this.THDB) { + this.formData.beginTime = this.THDBBegin + this.formData.endTime = this.THDBEnd + this.formData.compare_type = this.timeDes; + } let requestData = JSON.parse(JSON.stringify(this.formData)); - console.log(requestData) requestData.ht_typesub = requestData.ht_typesub.join(",") requestData.level = requestData.level.join(",") requestData.superior = requestData.superior.join(",") requestData.checktype = requestData.checktype.join(",") requestData.curWarningLevel = requestData.curWarningLevel.join(",") + if(this.THDB){ + chart_compare(requestData).then(res=>{ + let data = res.data; + if (data.ok) { + this.lineChartData = {} + let dataList = []; + let timeList = []; + if (data.data != null && data.data.length > 0) { + data.data[0].forEach(n => { + if (timeList.indexOf(n.graph) == -1) { + timeList.push(n.graph) + } + let obj = dataList.find(v => v.name == n.xAxes); + if (obj == null) { + // obj.data.push(n.counts); + obj = { + name: n.xAxes, + data: [], + // type: 'line', + // areaStyle: {} + } + dataList.push(obj) + } + }) + timeList.forEach(time => { + let singileData = data.data[0].filter(n => n.graph == time) + dataList.forEach(n => { + let searchData = singileData.find(v => v.xAxes == n.name); + if (searchData != null) { + n.data.push(parseInt(searchData.yAxes)) + } else { + n.data.push(0) + } + }) + }) + } + this.lineChartData.timeList = timeList; + this.lineChartData.dataList = dataList; + this.initLineChart() + } + }) + return; + } + + + chart_analysis(requestData).then(res => { let data = res.data; if (data.ok) { - console.log(this.formData.echart_type) if (this.formData.echart_type == "column") { this.columnChartData = {}; let xList = []; let dataList = []; if (data.data != null && data.data.length > 0) { - console.log("柱图",data) data.data[0].forEach(n => { xList.push(n.graph); let singleData = { @@ -346,13 +458,13 @@ }) } this.columnChartData.xList = xList; - this.columnChartData.dataList=[] + this.columnChartData.dataList = [] this.columnChartData.dataList.push( { - data:dataList, - colorByPoint:true + data: dataList, + colorByPoint: true } - ); + ); this.initCloumnChart() } else if (this.formData.echart_type == "line") { this.lineChartData = {} @@ -389,7 +501,6 @@ } this.lineChartData.timeList = timeList; this.lineChartData.dataList = dataList; - console.log(this.lineChartData) this.initLineChart() } else { this.pieChartData = [] @@ -490,15 +601,15 @@ // myChart.setOption(option) var option = { - chart:{ - type:'area' + chart: { + type: 'area' }, title: { text: '众泰煤焦化各隐患单位隐患走势分析' }, yAxis: { - title:{ - enabled:false + title: { + enabled: false } }, colors: ['#9a0202', '#02cccc', '#0202ff', '#ff9a02', '#02ff02', '#CC02CCFF', '#35FF02FF', '#CCFF67FF', '#35CC67FF', '#9A0202FF'], @@ -526,35 +637,33 @@ }, initCloumnChart() { - console.log("this.columnChartData.xList",this.columnChartData.xList) - console.log("this.columnChartData.dataList",this.columnChartData.dataList) var option = { - chart:{ - type:'column', - marginBottom:70 + chart: { + type: 'column', + marginBottom: 70 }, title: { text: null }, yAxis: { - title:{ - enabled:false + title: { + enabled: false } }, - tooltip:{ - formatter:function () { - return this.x+" : "+this.y + tooltip: { + formatter: function () { + return this.x + " : " + this.y } }, colors: ['#ff6600', '#fcd202', '#b0de09', '#0289cc', '#2001cd', '#cd0d74', '#cc0000', '#00cc00', '#0000cc', '#dddddd', '#999999', '#333333', '#990000', '#92e3d4', '#f09aea'], legend: { - enabled:false, + enabled: false, }, xAxis: { // type: 'category', // boundaryGap: false, categories: this.columnChartData.xList, - max:this.columnChartData.xList.length-1 + max: this.columnChartData.xList.length - 1 // data: ['2022-05-01', '', '2022-05-03', '', '2022-05-05', '', '2022-05-07', '', '2022-05-09', '', '2022-05-11'] }, series: this.columnChartData.dataList, @@ -605,11 +714,14 @@ </script> <style scoped> -.legend{ - position: absolute;bottom: 10px;z-index: 2; +.legend { + position: absolute; + bottom: 10px; + z-index: 2; width: 100%; } -.legend-body{ + +.legend-body { width: 100%; display: flex; justify-content: center; @@ -617,63 +729,81 @@ font-size: 12px; height: 100%; } -.legend-item{ + +.legend-item { display: flex; justify-content: flex-start; align-items: center; margin-left: 20px; line-height: 1.5; } -.legend-item div{ + +.legend-item div { width: 20px; height: 15px; margin-right: 10px; } -.legendItemBack0{ + +.legendItemBack0 { background-color: #ff6600; } -.legendItemBack1{ + +.legendItemBack1 { background-color: #fcd202; } -.legendItemBack2{ + +.legendItemBack2 { background-color: #b0de09; } -.legendItemBack3{ + +.legendItemBack3 { background-color: #0289cc; } -.legendItemBack4{ + +.legendItemBack4 { background-color: #2001cd; } -.legendItemBack5{ + +.legendItemBack5 { background-color: #cd0d74; } -.legendItemBack6{ + +.legendItemBack6 { background-color: #cc0000; } -.legendItemBack7{ + +.legendItemBack7 { background-color: #00cc00; } -.legendItemBack8{ + +.legendItemBack8 { background-color: #0000cc; } -.legendItemBack9{ + +.legendItemBack9 { background-color: #dddddd; } -.legendItemBack10{ + +.legendItemBack10 { background-color: #999999; } -.legendItemBack11{ + +.legendItemBack11 { background-color: #333333; } -.legendItemBack12{ + +.legendItemBack12 { background-color: #990000; } -.legendItemBack13{ + +.legendItemBack13 { background-color: #92e3d4; } -.legendItemBack14{ + +.legendItemBack14 { background-color: #f09aea; } + .top { padding: 10px 5px; background: #e4edf4; @@ -779,4 +909,8 @@ background-color: #034ea2; border: 1px solid #034ea2; } + +>>> .center .time[data-v-21f55eb3] .el-input__inner { + width: 100px; +} </style> diff --git a/src/views/common/jdSelect.vue b/src/views/common/jdSelect.vue new file mode 100644 index 0000000..5bf91f1 --- /dev/null +++ b/src/views/common/jdSelect.vue @@ -0,0 +1,394 @@ + +<template> + <div class="el-quarter-picker"> + <el-popover + v-model="visible" + :disabled="!canPopover" + :tabindex="null" + placement="bottom-start" + transition="el-zoom-in-top" + trigger="click"> + + <div class="el-date-picker"> + <div class="el-picker-panel__body"> + <div class="el-date-picker__header el-date-picker__header--bordered" style="margin:0px; line-height:30px"> + <button + type="button" + @click="clickLast" + aria-label="前一年" + class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left"></button> + <span role="button" class="el-date-picker__header-label" @click="clickYear">{{ title }}</span> + <button + type="button" + @click="clickNext" + aria-label="后一年" + class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right"></button> + </div> + <div class="el-picker-panel__content" style="margin:0px; width:100%"> + <table class="el-month-table" style=""> + <tbody> + <tr v-for="line in lineCount" :key="line"> + <td v-for="index in (line * 4 <= viewList.length ? 4 : viewList.length - (line - 1) * 4)" :key="index" :class="{ today: viewList[(line - 1) * 4 + index - 1].current, current: viewList[(line - 1) * 4 + index - 1].active }"> + <div><a class="cell" @click="clickItem(viewList[(line - 1) * 4 + index - 1])">{{ viewList[(line - 1) * 4 + index - 1].label }}</a></div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + + <el-input + slot="reference" + @change="changeText" + @mouseenter.native="mouseEnter" + @mouseleave.native="mouseLeave" + :placeholder="placeholder" + v-model="text" + :size="size" + :readonly="!canEdit" + :disabled="disabled"> + <i slot="prefix" class="el-input__icon el-icon-date"></i> + <i slot="suffix" class="el-input__icon el-icon-circle-close" v-show="showClear" style="cursor:pointer" @click.stop="clear"></i> + </el-input> + </el-popover> + </div> +</template> + +<script> +export default { + name: 'ElQuarterPicker', + props: { + placeholder: { + type: String, + default: '' + }, + size: { + type: String, + default: '' + }, + readonly: { + type: Boolean, + default: false + }, + clearable: { + type: Boolean, + default: true + }, + editable: { + type: Boolean, + default: true + }, + disabled: { + type: Boolean, + default: false + }, + format: { + type: String, + default: 'yyyy年第Q季度' + }, + valueFormat: { + type: String, + default: 'yyyy年第q季度' + }, + value: { + type: String, + default: '' + } + }, + model: { + prop: 'value', + event: 'change' + }, + watch: { + value(val) { + // console.log('change-------', val) + this.changeValue(val) + }, + readonly(val) { + this.canEdit = !val && this.editable + this.canPopover = !this.disabled && !val + }, + editable(val) { + this.canEdit = !this.readonly && val + }, + disabled(val) { + this.canPopover = !val && !this.readonly + } + }, + data() { + return { + visible: false, + showClear: false, // 控制清空按钮展示 + canEdit: true, // 是否可编辑 + canPopover: true, // 选择器弹出是否可用 + text: '', // 文本框值 + viewType: 1, // 视图类型,1季度,2年度 + viewYear: 0, // 当前年份 + viewList: [], // 数据列表 + lineCount: 0, // 数据行数 + title: '', // 选择器标题 + data: [0, 0] // 当前选择年度-季度 + } + }, + mounted() { + // console.log('mounted--------', this.value) + this.changeValue(this.value) + + // 设置文本框是否可编辑 + this.canEdit = !this.readonly && this.editable + this.canPopover = !this.disabled && !this.readonly + + // 监听按键(上下左右键可以切换季度) + document.onkeydown = (event) => { + if (this.visible) { + const data = [this.data[0], this.data[1]] + if (data[0] < 1 || data[1] < 1) { + // 以当前季度为标准 + const curDate = new Date() + data[0] = curDate.getFullYear() + data[1] = parseInt(curDate.getMonth() / 3) + 1 + } + if (event.code === 'ArrowLeft') { + // 上一个季度 + if (data[1] === 1) { + data[0] = data[0] - 1 + data[1] = 4 + } else { + data[1] = data[1] - 1 + } + } else if (event.code === 'ArrowRight') { + // 下一个季度 + if (data[1] === 4) { + data[0] = data[0] + 1 + data[1] = 1 + } else { + data[1] = data[1] + 1 + } + } else if (event.code === 'ArrowUp') { + // 上一年季度 + data[0] = data[0] - 1 + } else if (event.code === 'ArrowDown') { + // 下一年季度 + data[0] = data[0] + 1 + } else { + return + } + + // 超过年限的不处理 + if (data[0] < 1000 || data[0] > 9999) { + return + } + this.data = data + this.viewType = 1 + this.viewYear = data[0] + this.$emit('change', this.formatTo(data, this.valueFormat)) + } + } + }, + destroyed() { + document.onkeydown = null + }, + methods: { + // 季度文本变更 + changeText() { + if (this.checkFormat(this.format, this.text)) { + // 设置值 + this.formatFrom(this.text, this.format) + this.$emit('change', this.formatTo(this.data, this.valueFormat)) + } else { + // 输入了无效的格式,还原回原来的值 + if (this.data[0] < 1 || this.data[1] < 1) { + this.text = '' + } else { + this.text = this.formatTo(this.data, this.format) + } + } + this.visible = false + }, + // 鼠标进入 + mouseEnter() { + if (!this.disabled && !this.readonly && this.clearable && this.text !== '') { + this.showClear = true + } + }, + // 鼠标离开 + mouseLeave() { + if (!this.disabled && this.clearable) { + this.showClear = false + } + }, + // 清除季度 + clear() { + this.showClear = false + this.visible = false + this.$emit('change', '') + }, + // 季度值变更 + changeValue(val) { + this.viewType = 1 + if (val) { + // 反向格式化 + this.formatFrom(val, this.valueFormat) + this.text = this.formatTo(this.data, this.format) + this.viewYear = this.data[0] + } else { + this.text = '' + this.data = [0, 0] + this.viewYear = new Date().getFullYear() + } + this.initView() + }, + // 初始化视图数据 + initView() { + const list = [] + const curDate = new Date() + const curYear = curDate.getFullYear() + const curQuarter = parseInt(curDate.getMonth() / 3) + 1 + if (this.viewType === 1) { + let index = 0 + for (const i of '一二三四') { + index++ + const item = { label: '第' + i + '季度', year: this.viewYear, quarter: index, current: false, active: false } + if (this.viewYear === curYear && index === curQuarter) { + item.current = true + } else if (this.viewYear === this.data[0] && index === this.data[1]) { + item.active = true + } + list.push(item) + } + this.title = this.viewYear + ' 年' + } else { + const start = parseInt(this.viewYear / 10) * 10 + this.viewYear = start + for (let i = 0; i < 10; i++) { + const year = start + i + const item = { label: year + '', year: year, current: false, active: false } + if (year === curYear) { + item.current = true + } else if (year === this.data[0]) { + item.active = true + } + list.push(item) + } + this.title = start + ' 年 - ' + (start + 9) + ' 年' + } + this.viewList = list + this.lineCount = parseInt(list.length / 4) + if (list.length % 4 > 0) { + this.lineCount++ + } + }, + // 校验季度格式是否正确 + checkFormat(pattern, val) { + // 格式转成正则表达式 + let text = '' + for (const char of pattern) { + const dict = '\\^$.+?*[]{}!' + if (dict.indexOf(char) === -1) { + text += char + } else { + text += '\\' + char + } + } + text = text.replace('yyyy', '[1-9]\\d{3}') + text = text.replace('qq', '0[1-4]') + text = text.replace('q', '[1-4]') + text = text.replace('Q', '[一二三四]') + text = '^' + text + '$' + const patt = new RegExp(text) + return patt.test(val) + }, + // 格式化季度到指定格式 + formatTo(data, pattern) { + let text = pattern.replace('yyyy', '' + data[0]) + text = text.replace('qq', '0' + data[1]) + text = text.replace('q', '' + data[1]) + text = text.replace('Q', '一二三四'.substr(data[1] - 1, 1)) + return text + }, + // 以指定格式解析季度 + formatFrom(str, pattern) { + const year = this.findText(str, pattern, 'yyyy') + const quarter = this.findText(str, pattern, ['qq', 'q', 'Q']) + this.data = [year, quarter] + }, + // 查找文本数值 + findText(str, pattern, find) { + if (find instanceof Array) { + for (const f of find) { + const val = this.findText(str, pattern, f) + if (val !== -1) { + return val + } + } + return -1 + } + const index = pattern.indexOf(find) + if (index === -1) { + return index + } + const val = str.substr(index, find.length) + if (find === 'Q') { + return '一二三四'.indexOf(val) + 1 + } else { + return parseInt(val) + } + }, + // 年份点击 + clickYear() { + if (this.viewType !== 1) { + return + } + // 切换年度选择器 + this.viewType = 2 + this.initView() + }, + // 季度选择 + clickItem(item) { + // console.log('select--------', item) + if (this.viewType === 1) { + // 选择季度 + this.$emit('change', this.formatTo([item.year, item.quarter], this.valueFormat)) + this.visible = false + } else { + // 选择年度 + this.viewType = 1 + this.viewYear = item.year + this.initView() + } + }, + // 上一年 + clickLast() { + if (this.viewYear > 1000) { + if (this.viewType === 1) { + this.viewYear-- + this.initView() + } else { + this.viewYear = this.viewYear - 10 + this.initView() + } + } + }, + // 下一年 + clickNext() { + if (this.viewYear < 9999) { + if (this.viewType === 1) { + this.viewYear++ + this.initView() + } else { + this.viewYear = this.viewYear + 10 + this.initView() + } + } + } + } +} +</script> + +<style> +.el-quarter-picker { + width: 220px; + display: inline-block; +} +</style> -- Gitblit v1.9.2