<template>
|
<div style="width:100%">
|
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
|
<el-tab-pane label="城市空气质量排名" name="first">
|
<div class="topSelect">
|
<div>
|
<el-radio-group v-model="dateRadio" style="margin-left:20px">
|
<el-radio-button label="今日累计" />
|
<el-radio-button label="小时" />
|
<el-radio-button label="日报" />
|
<el-radio-button label="月报" />
|
<el-radio-button label="年报" />
|
<el-radio-button label="自定义" />
|
</el-radio-group>
|
<el-input v-if="dataType === 'today'" v-model="currentTimes" :disabled="true" placeholder="请输入内容" style="width:166px" />
|
<component :is="dataType" v-else :class="{'w160':w160,'w400':w400}" :value1="currentDate" style="padding-left:0;margin-left:10px" @sendPickerChild="showPickerChild" />
|
<el-radio-group v-model="cityRadio" style="margin-left:20px">
|
<el-radio-button label="省内城市" />
|
<el-radio-button label="市区范围" />
|
<el-radio-button label="2+26城市" />
|
</el-radio-group>
|
</div>
|
<div>
|
<el-button type="primary" @click="getData()">查询</el-button>
|
<el-button type="primary" @click="setExport2Excel()">报表导出</el-button>
|
</div>
|
</div>
|
<div class="topTitle">
|
<el-table
|
:id="'mytable'"
|
ref="mytable"
|
height="720"
|
:data="tableData"
|
border
|
style="width: 100%"
|
:default-sort="{prop: 'rank', order: 'ascending'}"
|
:cell-class-name="tableCellClassName"
|
@sort-change="changeTableSort"
|
>
|
<el-table-column
|
prop="rank"
|
label="排名"
|
align="center"
|
/>
|
<el-table-column
|
prop="cityName"
|
label="城市"
|
align="center"
|
/>
|
<el-table-column
|
prop="compositeIndex"
|
label="综合指数"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
v-if="isAqi"
|
prop="AQI"
|
label="AQI"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
v-if="isMonthContrast"
|
prop="monthContrast"
|
label="同上月对比"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
v-if="isYearContrast"
|
prop="yearContrast"
|
label="同上年对比"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
prop="PM10"
|
label="PM10"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
prop="PM2_5"
|
label="PM2.5"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
prop="SO2"
|
label="SO2"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
prop="NO2"
|
label="NO2"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
prop="CO"
|
label="CO"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
prop="O3"
|
label="O3"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
prop="O3_8H"
|
label="O3_8H"
|
align="center"
|
sortable
|
/>
|
<el-table-column
|
v-if="!isMonthContrast&&!isYearContrast"
|
prop="primaryPollutant"
|
label="首要污染物"
|
align="center"
|
/>
|
</el-table>
|
</div>
|
</el-tab-pane>
|
<el-tab-pane label="城市空气质量同期对比" name="second">
|
<CityAirYoyContrast ref="CAC" />
|
</el-tab-pane>
|
<!-- <el-tab-pane label="城市空气质量变化率" name="third">城市空气质量变化率</el-tab-pane> -->
|
<!-- <el-tab-pane label="城市空气质量排名对比" name="fourth">城市空气质量排名对比</el-tab-pane> -->
|
</el-tabs>
|
</div>
|
</template>
|
|
<script>
|
// import FileSaver from 'file-saver'
|
// import XLSX from 'xlsx'
|
import XLSX2 from 'xlsx'
|
import XLSX from 'xlsx-style'
|
import TimePicker1 from '@/components/Form/TimePicker1'
|
import HourPicker1 from '@/components/Form/HourPicker1'
|
import DatePicker1 from '@/components/Form/DatePicker1'
|
import MouthPicker1 from '@/components/Form/MouthPicker1'
|
import CustomPicker1 from '@/components/Form/CustomPicker1'
|
import CityAirYoyContrast from './cityAirYoyContrast'
|
|
export default {
|
components: {
|
TimePicker1,
|
HourPicker1,
|
DatePicker1,
|
MouthPicker1,
|
CustomPicker1,
|
CityAirYoyContrast
|
},
|
data() {
|
return {
|
dataType: 'today',
|
tableData: [],
|
govMt: [],
|
value: [], // 绑定多选下拉框数据
|
dateValue: '', // 绑定日期数据
|
pickerOptions: {
|
disabledDate(time) {
|
return time.getTime() > Date.now()
|
}
|
},
|
options: [],
|
sensorArr: [
|
{ code: 'PM2_5', name: 'PM2.5' },
|
{ code: 'PM10', name: 'PM10' },
|
{ code: 'SO2', name: 'SO2' },
|
{ code: 'NO2', name: 'NO2' },
|
{ code: 'CO', name: 'CO' },
|
{ code: 'O3', name: 'O3' },
|
{ code: 'O3_8H', name: 'O3_8H' },
|
{ code: 'AQI', name: 'AQI' }
|
],
|
aqi: { code: 'aqi', name: 'AQI' },
|
// 因子报警区间
|
levelSensor: {
|
'PM2_5': [35, 75, 115, 150, 250],
|
'PM10': [50, 150, 250, 350, 420],
|
'SO2': [150, 500, 650, 800, 1600],
|
'NO2': [100, 200, 700, 1200, 2340],
|
'CO': [5, 10, 35, 60, 90],
|
'O3': [160, 200, 300, 400, 800],
|
'O3_8H': [100, 160, 215, 265, 800],
|
'AQI': [50, 100, 150, 200, 300]
|
},
|
// 标题
|
title: '',
|
dateRadio: '今日累计',
|
cityRadio: '省内城市',
|
unit: 'today',
|
currentCityType: 'province',
|
currentDate: '',
|
w160: true,
|
w400: false,
|
isAqi: false,
|
isMonthContrast: false,
|
isYearContrast: false,
|
activeName: 'first',
|
excelTime: '',
|
excelCity: '省内城市'
|
}
|
},
|
computed: {
|
// 获取当前时间的整点小时
|
currentTimes() {
|
var t = new Date()
|
var month = t.getMonth() < 9 ? '0' + (t.getMonth() + 1) : t.getMonth() + 1
|
var date = t.getDate() <= 9 ? '0' + t.getDate() : t.getDate()
|
var now = t.toLocaleTimeString().replace(/^\D*/, '')
|
var num = now.indexOf(':')
|
var time = t.getFullYear() + '-' + month + '-' + date + ' ' + now.substring(0, num) + ':00'
|
return time
|
},
|
govMtC() {
|
let name = 'c'
|
const newResults = []
|
this.govMt.forEach(data => {
|
let showData = false
|
if (name !== data.name) {
|
showData = true
|
}
|
let map = {}
|
map = { id: data.id, name: data.name, showData: showData }
|
newResults.push(map)
|
name = data.name
|
})
|
return newResults
|
}
|
},
|
watch: {
|
// 日期切换组件
|
dateRadio(nv, ov) {
|
this.w160 = true
|
this.w400 = false
|
if (nv === '今日累计') {
|
this.dataType = 'today'
|
this.unit = 'today'
|
// this.currentDate = this.currentTime
|
} else if (nv === '小时') {
|
this.dataType = 'TimePicker1'
|
this.unit = 'hour'
|
this.currentHour()
|
} else if (nv === '日报') {
|
this.dataType = 'HourPicker1'
|
this.unit = 'day'
|
this.currentDay()
|
} else if (nv === '月报') {
|
this.dataType = 'DatePicker1'
|
this.unit = 'month'
|
this.currentMonth()
|
} else if (nv === '年报') {
|
this.dataType = 'MouthPicker1'
|
this.unit = 'year'
|
this.currentYear()
|
} else {
|
this.dataType = 'CustomPicker1'
|
this.unit = 'custom'
|
this.currentTime()
|
this.w160 = !this.w160
|
this.w400 = !this.w400
|
}
|
},
|
// 城市切换组件
|
cityRadio(nv, ov) {
|
if (nv === '2+26城市') {
|
this.currentCityType = '28'
|
} else if (nv === '省内城市') {
|
this.currentCityType = 'province'
|
} else if (nv === '市区范围') {
|
this.currentCityType = 'city'
|
}
|
}
|
},
|
created() {
|
this.getData()
|
},
|
methods: {
|
// 重新添加rank排名
|
changeTableSort() {
|
var sortTableData = this.$refs.mytable.tableData
|
for (let i = 0; i < sortTableData.length; i++) {
|
sortTableData[i].rank = i + 1
|
}
|
},
|
// 获得子组件时间选择器传递的数据
|
showPickerChild(data) {
|
this.currentDate = data
|
},
|
// 查询数据
|
getData() {
|
this.tableData = []
|
if (this.dataType !== 'today' && !this.currentDate) {
|
this.$message({
|
message: '请选择日期',
|
type: 'warning'
|
})
|
} else {
|
this.$request({
|
url: '/aqi/rankingDetails',
|
method: 'get',
|
params: {
|
// organizationId: this.$store.state.orgId,
|
regionCode: this.$store.state.regionCode,
|
type: this.unit,
|
time: this.currentDate ? typeof this.currentDate === 'string' ? this.currentDate : null : null,
|
cityType: this.currentCityType,
|
start: typeof this.currentDate === 'string' ? null : this.currentDate[0],
|
end: typeof this.currentDate === 'string' ? null : this.currentDate[1]
|
}
|
}).then((res) => {
|
// console.log('获得时间对应因子数据')
|
// console.log(res)
|
var tempData = res.data
|
if (tempData.length !== 0) {
|
for (let i = 0; i < tempData.length; i++) {
|
tempData[i].rank = i + 1
|
if (tempData[i].AQI) {
|
this.isAqi = true
|
this.isMonthContrast = false
|
this.isYearContrast = false
|
} else if (tempData[i].monthContrast) {
|
this.isMonthContrast = true
|
this.isAqi = false
|
this.isYearContrast = false
|
} else if (tempData[i].yearContrast) {
|
this.isYearContrast = true
|
this.isAqi = false
|
this.isMonthContrast = false
|
}
|
}
|
this.tableData = tempData
|
} else {
|
this.$message.warning('当前时间没有数据')
|
}
|
}).catch((err) => {
|
console.log(err)
|
})
|
}
|
this.currentDate ? this.excelTime = this.currentDate : this.excelTime = this.currentTimes
|
this.excelCity = this.cityRadio
|
},
|
// 单元格样式
|
tableCellClassName({ row, column, rowIndex, columnIndex }) {
|
for (const key in row) {
|
if (key === column.property) {
|
const code = column.property
|
if (code !== 'rank' && code !== 'cityName' && code !== 'compositeIndex' && code !== 'primaryPollutant' && code !== 'monthContrast' && code !== 'yearContrast') {
|
if (row[key] === 0 || row[key] === '' || row[key] === null) {
|
return ''
|
} else if (row[key] <= this.levelSensor[code][0]) {
|
return 'green'
|
} else if (row[key] <= this.levelSensor[code][1]) {
|
return 'yellow'
|
} else if (row[key] <= this.levelSensor[code][2]) {
|
return 'orange'
|
} else if (row[key] <= this.levelSensor[code][3]) {
|
return 'red'
|
} else if (row[key] <= this.levelSensor[code][4]) {
|
return 'oRed'
|
} else {
|
return 'violet'
|
}
|
}
|
}
|
}
|
return ''
|
},
|
// 报表导出
|
setExport2Excel() {
|
/* generate workbook object from table */
|
var wb = XLSX2.utils.table_to_sheet(document.querySelector('#mytable'))// mytable为表格的id名
|
// console.log(wb)
|
// if (!wb['!merges']) {
|
// this.$message.warning('无法导出:报表无数据')
|
// return
|
// }
|
const sum = 12 // 列的数量
|
for (var i = 0; i < sum; i++) {
|
if (i === sum - 1) {
|
wb['!cols'][i] = { wpx: 120 } // 设置列宽
|
} else {
|
wb['!cols'][i] = { wpx: 60 }
|
}
|
}
|
// 样式的文档地址
|
// https://www.npmjs.com/package/xlsx-style
|
const list = []
|
for (const key in wb) {
|
if (key.indexOf('!') === -1) {
|
wb[key].s = {
|
font: {// 字体设置
|
sz: 13,
|
bold: false,
|
color: {
|
rgb: '000000'// 十六进制,不带#
|
}
|
},
|
border: { // 设置边框
|
top: { style: 'thin' },
|
bottom: { style: 'thin' },
|
left: { style: 'thin' },
|
right: { style: 'thin' }
|
},
|
alignment: {// 文字居中
|
horizontal: 'center',
|
vertical: 'center',
|
wrap_text: true
|
}
|
}
|
var num = key.replace(/[^0-9]/ig, '')
|
if (num === '1') {
|
const map = {}
|
for (let i = 0; i < this.sensorArr.length; i++) {
|
if (this.sensorArr[i].name === wb[key].v) {
|
var b = key.replace(/[^a-z]+/ig, '')
|
map.key = b
|
map.code = this.sensorArr[i].code
|
break
|
}
|
}
|
if (map.key) {
|
list.push(map)
|
}
|
}
|
|
// else if (num === '1') {
|
// const map = {}
|
// if (this.aqi.name === wb[key].v) {
|
// var b = key.replace(/[^a-z]+/ig, '')
|
// map.key = b
|
// map.code = this.aqi.code
|
// }
|
// if (map.key) {
|
// list.push(map)
|
// }
|
// }
|
}
|
}
|
|
for (const key in wb) {
|
var b = key.replace(/[^a-z]+/ig, '')
|
for (let i = 0; i < list.length; i++) {
|
if (b === list[i].key) {
|
if (typeof wb[key].v === 'number') {
|
if (wb[key].v <= this.levelSensor[list[i].code][0]) {
|
wb[key].s.fill = {
|
fgColor: { rgb: '65dd77' }
|
}
|
} else if (wb[key].v <= this.levelSensor[list[i].code][1]) {
|
wb[key].s.fill = {
|
fgColor: { rgb: 'fcdf56' }
|
}
|
} else if (wb[key].v <= this.levelSensor[list[i].code][2]) {
|
wb[key].s.fill = {
|
fgColor: { rgb: 'fd7c43' }
|
}
|
} else if (wb[key].v <= this.levelSensor[list[i].code][3]) {
|
wb[key].s.fill = {
|
fgColor: { rgb: 'fc5656' }
|
}
|
} else if (wb[key].v <= this.levelSensor[list[i].code][4]) {
|
wb[key].s.fill = {
|
fgColor: { rgb: 'fc5689' }
|
}
|
} else {
|
wb[key].s.fill = {
|
fgColor: { rgb: 'cd3a3a' }
|
}
|
}
|
}
|
}
|
}
|
}
|
// var data = this.addRangeBorder(wb['!merges'], wb) // 合并项添加边框
|
var filedata = this.sheet2blob(wb)
|
// return
|
this.openDownloadDialog(filedata, this.excelCity + '空气质量排名-' + this.excelTime + '.xlsx')
|
},
|
// 为合并项添加边框
|
addRangeBorder(range, ws) {
|
const arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
|
range.forEach(item => {
|
const startColNumber = Number(item.s.r); const endColNumber = Number(item.e.r)
|
const startRowNumber = Number(item.s.c); const endRowNumber = Number(item.e.c)
|
const test = ws[arr[startRowNumber] + (startColNumber + 1)]
|
for (let col = startColNumber; col <= endColNumber; col++) {
|
for (let row = startRowNumber; row <= endRowNumber; row++) {
|
ws[arr[row] + (col + 1)] = test
|
}
|
}
|
})
|
return ws
|
},
|
// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
|
sheet2blob(sheet, sheetName) {
|
sheetName = sheetName || 'sheet1'
|
var workbook = {
|
SheetNames: [sheetName],
|
Sheets: {}
|
}
|
workbook.Sheets[sheetName] = sheet // 生成excel的配置项
|
|
var wopts = {
|
bookType: 'xlsx', // 要生成的文件类型
|
bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
|
type: 'binary'
|
}
|
var wbout = XLSX.write(workbook, wopts)
|
var blob = new Blob([s2ab(wbout)], {
|
type: 'application/octet-stream'
|
}) // 字符串转ArrayBuffer
|
function s2ab(s) {
|
var buf = new ArrayBuffer(s.length)
|
var view = new Uint8Array(buf)
|
for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
|
return buf
|
}
|
return blob
|
},
|
openDownloadDialog(url, saveName) {
|
if (typeof url === 'object' && url instanceof Blob) {
|
url = URL.createObjectURL(url) // 创建blob地址
|
}
|
var aLink = document.createElement('a')
|
aLink.href = url
|
aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
|
var event
|
if (window.MouseEvent) event = new MouseEvent('click')
|
else {
|
event = document.createEvent('MouseEvents')
|
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
|
}
|
aLink.dispatchEvent(event)
|
},
|
// 当前小时默认值
|
currentHour() {
|
var aData = new Date()
|
var month = aData.getMonth() < 9 ? '0' + (aData.getMonth() + 1) : aData.getMonth() + 1
|
var date = aData.getDate() <= 9 ? '0' + aData.getDate() : aData.getDate()
|
var hour = aData.getHours() <= 9 ? '0' + aData.getHours() - 1 : aData.getHours() - 1
|
var currentDate = aData.getFullYear() + '-' + month + '-' + date + ' ' + hour
|
this.currentDate = currentDate.toString()
|
},
|
// 当日默认值
|
currentDay() {
|
var aData = new Date()
|
var month = aData.getMonth() < 9 ? '0' + (aData.getMonth() + 1) : aData.getMonth() + 1
|
var date = aData.getDate() <= 9 ? '0' + aData.getDate() - 1 : aData.getDate() - 1
|
var currentDate = aData.getFullYear() + '-' + month + '-' + date
|
this.currentDate = currentDate.toString()
|
},
|
// 当前月份默认值
|
currentMonth() {
|
var aData = new Date()
|
var month = aData.getMonth() < 9 ? '0' + (aData.getMonth()) : aData.getMonth()
|
var currentDate = aData.getFullYear() + '-' + month
|
this.currentDate = currentDate.toString()
|
},
|
// 当前年份默认值
|
currentYear() {
|
var aData = new Date()
|
var currentDate = aData.getFullYear() - 1
|
this.currentDate = currentDate.toString()
|
},
|
// 当前自定义默认值
|
currentTime() {
|
var aData = new Date()
|
var month = aData.getMonth() < 9 ? '0' + (aData.getMonth() + 1) : aData.getMonth() + 1
|
var date = aData.getDate() <= 9 ? '0' + aData.getDate() : aData.getDate()
|
var currentDate = aData.getFullYear() + '-' + month + '-' + date
|
this.currentDate = [currentDate, currentDate]
|
},
|
handleClick(tab, event) {
|
if (tab.index === '1') {
|
this.$refs.CAC.getData()
|
}
|
}
|
}
|
}
|
</script>
|
|
<style scoped lang="scss">
|
.topSelect{
|
display: flex;
|
margin-bottom: 20px;
|
padding: 20px 15px 0 15px;
|
display: flex;
|
justify-content: space-between;
|
span:first-child{
|
flex: 1;
|
}
|
|
// div:last-child{
|
// width: 300px;
|
// line-height: 40px;
|
// padding-left: 6px;
|
// }
|
}
|
.el-date-editor{
|
// float: left;
|
}
|
.el-select{
|
// float: left;
|
// left: 40px;
|
}
|
|
.topTitle{
|
width: 100%;
|
justify-content: space-between;
|
margin-bottom: 20px;
|
padding: 10px 15px;
|
}
|
.timeClass {
|
float: left;
|
width: 4%;
|
border-collapse: collapse;/*关键代码*/
|
text-align: center;
|
color: black;
|
font-weight: 700;
|
}
|
.w160{
|
width: 160px;
|
}
|
.w400{
|
width: 400px;
|
}
|
///deep/.el-table .cell {
|
// white-space: nowrap;
|
// width: fit-content;
|
//}
|
|
/deep/.el-table th>.cell {
|
font-size: 14px;
|
padding: 0;
|
}
|
/deep/.gutter {
|
display: none;
|
}
|
|
/deep/.green{
|
background: #65dd77!important;
|
}
|
/deep/.yellow{
|
background-color: #fcdf56!important;
|
}
|
/deep/.orange{
|
background-color: #fd7c43!important;
|
}
|
/deep/.red{
|
background-color: #fc5656!important;
|
color: #620000;
|
}
|
/deep/.oRed{
|
background-color: #fc5689!important;
|
}
|
/deep/.violet{
|
background-color: #cd3a3a!important;
|
}
|
|
</style>
|