<!-- 历史数据 -->
|
<script>
|
import { defineAsyncComponent } from 'vue'
|
import { ElMessage } from 'element-plus'
|
import * as XLSX from 'xlsx/xlsx.mjs'
|
import dayjs from 'dayjs'
|
import axiosInstanceInstance from '@/utils/request.js'
|
import TimeSelect from '@/sfc/TimeSelect.vue'
|
|
const ShopNameAndID = defineAsyncComponent(() => import('@/sfc/ShopNameAndID.vue'))
|
|
// 异步组件
|
const lineChart = defineAsyncComponent(() => import('@/sfc/FumeFanPurifierChart.vue'))
|
export default {
|
components: {
|
lineChart,
|
ShopNameAndID,
|
TimeSelect,
|
},
|
data() {
|
return {
|
button: {
|
// 查询的按钮
|
queryButton: false,
|
},
|
// 空状态
|
isNoData: false,
|
// 下拉框一开始展示的名字
|
beginShowShopName: [],
|
options: {},
|
// 分机/净化器电流折线图切换
|
radio: 1,
|
ispurifier: false,
|
checkAll: false,
|
isIndeterminate: false,
|
checkedCities: ['付小姐在成都'],
|
cities: [
|
'付小姐在成都',
|
'吉刻联盟',
|
'家在塔啦',
|
'狼来了',
|
'乐凯撒星游店',
|
'馨远美食小镇(哈尼美食广场)',
|
'棒约翰',
|
'弄堂咪道',
|
'杨记齐齐哈尔烤肉',
|
'上海稔传餐饮管理有限公司(人生一串)',
|
'缘家',
|
'泉盛餐饮(上海)有限公司(食其家)',
|
'丰茂烤串',
|
'上海泰煌餐饮管理有限公司(泰煌鸡)',
|
'徐汇区辰熙餐馆(小铁君串烧居酒屋)',
|
],
|
// 导出时选择的开始时间
|
exportBeginTime: '',
|
// 导出时选择的结束时间
|
exportEndTime: '',
|
exportData: [],
|
// 导出Excel弹出的对话框
|
dialogFormVisible: false,
|
|
// 加载中
|
loading: false,
|
currentDateTime: '',
|
oneWeekAgoDateTime: '',
|
|
// 分页展示数据
|
// 每页展示的数据
|
displayData: [],
|
// 存放后端返回的json数据
|
jsonData: [],
|
// 当前页
|
currentPage: 1,
|
// 每页条数
|
pageSize: 10,
|
total: 0,
|
|
isSwitch: false,
|
// 历史数据
|
exceedingData: [],
|
beginTime: '',
|
endTime: '',
|
optionsTime: [
|
{
|
value: '10',
|
label: '10分钟数据',
|
disabled: true,
|
},
|
],
|
// 选择店铺名
|
devId: [null, null],
|
}
|
},
|
|
watch: {
|
// 使页面打开时,渲染折线图
|
// 当查询的数据发生变化时,重新渲染折线图
|
exceedingData() {
|
this.setChart()
|
},
|
},
|
mounted() {
|
// 获取最近一周的历史数据
|
this.backMinuteDataAWeekAgo()
|
},
|
|
beforeRouteUpdate(to, from, next) {
|
if (to.name === this.$route.name) {
|
this.backMinuteDataAWeekAgo()
|
}
|
next()
|
},
|
methods: {
|
// 从时间选择器组件拿到开始和结束时间
|
giveTime(val) {
|
//将中国标准时间转为指定格式(该组件返回的标准时间的格式,所以必须的加这个函数)
|
this.beginTime = dayjs(val[0]).format('YYYY-MM-DD HH:mm:ss')
|
this.endTime = dayjs(val[1]).format('YYYY-MM-DD HH:mm:ss')
|
},
|
|
// 复选框选择改变时 渲染折线图
|
setChart() {
|
// 油烟浓度
|
if (this.exceedingData.length) {
|
if (this.radio == 1) {
|
// x轴日期时间
|
let dateList = []
|
// 历史油烟浓度
|
let fumeConcentration = []
|
this.exceedingData.forEach((item) => {
|
//x轴日期
|
dateList.push(item.mvDataTime)
|
// 历史油烟浓度
|
fumeConcentration.push(item.mvFumeConcentration2)
|
})
|
this.options = {
|
xAxis: {
|
name: '时间',
|
data: dateList,
|
},
|
legend: {
|
data: ['油烟浓度'],
|
},
|
yAxis: {
|
type: 'value',
|
axisLabel: {
|
show: true,
|
interval: 'auto',
|
},
|
name: 'mg/m³',
|
},
|
series: [
|
{
|
name: '油烟浓度',
|
type: 'line',
|
data: fumeConcentration,
|
},
|
],
|
}
|
} else if (this.radio == 2) {
|
// x轴日期时间
|
let dateList = []
|
// 历史风机电
|
let mvFanElectricity = []
|
this.exceedingData.forEach((item) => {
|
//x轴日期
|
dateList.push(item.mvDataTime)
|
// 历史风机电
|
mvFanElectricity.push(item.mvFanElectricity)
|
})
|
this.options = {
|
legend: {
|
data: ['风机电流'],
|
},
|
xAxis: {
|
data: dateList,
|
name: '时间',
|
},
|
yAxis: {
|
type: 'value',
|
axisLabel: {
|
show: true,
|
interval: 'auto',
|
},
|
name: 'A',
|
},
|
series: [
|
{
|
name: '风机电流',
|
type: 'line',
|
data: mvFanElectricity,
|
},
|
],
|
}
|
} else {
|
// x轴日期时间
|
let dateList = []
|
|
// 净化器电流
|
let mvPurifierElectricity = []
|
|
// item与后端实体类的对应
|
// 比率
|
this.exceedingData.forEach((item) => {
|
//x轴日期
|
dateList.push(item.mvDataTime)
|
|
// 净化器电流
|
mvPurifierElectricity.push(item.mvPurifierElectricity)
|
})
|
this.options = {
|
legend: {
|
data: ['净化器电流'],
|
},
|
xAxis: {
|
data: dateList,
|
name: '时间',
|
},
|
yAxis: {
|
type: 'value',
|
axisLabel: {
|
show: true,
|
interval: 'auto',
|
},
|
name: 'A',
|
},
|
series: [
|
{
|
name: '净化器电流',
|
type: 'line',
|
data: mvPurifierElectricity,
|
},
|
],
|
}
|
}
|
}
|
},
|
// 返回前一周分钟数据表数据
|
backMinuteDataAWeekAgo() {
|
// 给级联选择器设置默认的选择项
|
this.beginShowShopName = ['付小姐在成都', 'qinshi_31010320210010']
|
this.devId = ['付小姐在成都', 'qinshi_31010320210010']
|
|
// 给时间选择器设置默认时间
|
// this.beginTime = dayjs().subtract(1, 'week').format('YYYY-MM-DD HH:mm:ss');
|
// this.endTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
|
// 将时间同步给导出时间
|
this.exportBeginTime = this.beginTime
|
this.exportEndTime = this.endTime
|
|
let params = {}
|
params['devId'] = 'qinshi_31010320210010'
|
params['beginTime'] = this.beginTime
|
params['endTime'] = this.endTime
|
this.loading = true
|
axiosInstanceInstance.get('/fume/history', { params: params }).then((response) => {
|
// 保存返回的
|
this.exceedingData = response.data.data
|
this.loading = false
|
if (response.data.data.length == 0) {
|
ElMessage('该时段无数据')
|
this.isNoData = true
|
return
|
}
|
|
// 分页
|
this.total = this.exceedingData.length
|
// 默认显示第一页
|
this.handleCurrentChange(1)
|
})
|
},
|
|
lineChart() {
|
// 判断日期时间是否超过1个月
|
if (this.isExceedOneMonth(this.beginTime, this.endTime)) {
|
alert('时间跨度不能超过一个月')
|
return
|
}
|
// 将时间同步给导出时间
|
this.exportBeginTime = this.beginTime
|
this.exportEndTime = this.endTime
|
let params = {}
|
if (this.devId[1]) {
|
params['devId'] = this.devId[1]
|
}
|
if (this.beginTime) {
|
params['beginTime'] = this.beginTime
|
}
|
if (this.endTime) {
|
params['endTime'] = this.endTime
|
}
|
this.loading = true
|
this.button.queryButton = true
|
axiosInstanceInstance.get('/fume/history', { params: params }).then((response) => {
|
// 保存返回的
|
this.exceedingData = response.data.data
|
this.loading = false
|
this.button.queryButton = false
|
if (response.data.data.length == 0) {
|
ElMessage('该时段无数据')
|
this.isNoData = true
|
return
|
}
|
// 移除空数据状态
|
this.isNoData = false
|
// 分页
|
this.total = this.exceedingData.length
|
// 默认显示第一页
|
this.handleCurrentChange(1)
|
})
|
},
|
|
handleSizeChange(val) {
|
this.pageSize = val
|
// 改变每页显示数目时跳到第一页
|
this.handleCurrentChange(1)
|
},
|
handleCurrentChange(val) {
|
const startIndex = (val - 1) * this.pageSize
|
const endIndex = startIndex + this.pageSize
|
this.displayData = this.exceedingData.slice(startIndex, endIndex)
|
},
|
|
// 点击按钮 时将
|
switchChart() {},
|
selectExport() {
|
let temp = this.checkedCities.join()
|
let params = {}
|
if (this.checkedCities.length != 0) {
|
params['shops'] = temp
|
}
|
|
if (this.exportBeginTime) {
|
params['exportBeginTime'] = this.exportBeginTime
|
}
|
if (this.exportEndTime) {
|
params['exportEndTime'] = this.exportEndTime
|
}
|
|
axiosInstanceInstance.get('/fume/export', { params: params }).then((result) => {
|
this.exportData = result.data.data
|
})
|
},
|
exportExcel() {
|
const fields = [
|
'mvStatCode',
|
'diName',
|
'mvDataTime',
|
'mvFanElectricity',
|
'mvPurifierElectricity',
|
'mvFumeConcentration2',
|
]
|
const itemsFormatted = this.exportData.map((item) => {
|
const newItem = {}
|
fields.forEach((field) => {
|
newItem[field] = item[field]
|
})
|
return newItem
|
})
|
// 创建xlsx对象
|
const xls = XLSX.utils.json_to_sheet(itemsFormatted)
|
|
// 编辑表头行 修改表头
|
xls['A1'].v = '设备编号'
|
xls['B1'].v = '店铺名称'
|
xls['C1'].v = '采集时间'
|
xls['D1'].v = '风机电流(A)'
|
xls['E1'].v = '净化器电流(A)'
|
xls['F1'].v = '油烟浓度(mg/m³)'
|
|
// 创建workbook,并把sheet添加进去
|
const wb = XLSX.utils.book_new()
|
XLSX.utils.book_append_sheet(wb, xls, 'Sheet1')
|
|
// 将workbook转为二进制xlsx文件并下载
|
XLSX.writeFile(wb, '分析数据.xlsx')
|
},
|
exportDom() {
|
// 关闭弹窗
|
this.dialogFormVisible = false
|
// 请求
|
// 根据用户选择的店铺名请求数据
|
this.selectExport()
|
|
setTimeout(() => {
|
// 导出
|
this.exportExcel()
|
}, 1000)
|
},
|
|
isExceedOneMonth(dateStr1, dateStr2) {
|
// 超过一个月,返回True,否则返回False
|
// 将日期字符串转为日期对象
|
const date1 = new Date(dateStr1)
|
const date2 = new Date(dateStr2)
|
|
// 获取两个日期的年、月、日
|
const year1 = date1.getFullYear()
|
const month1 = date1.getMonth()
|
const day1 = date1.getDate()
|
|
const year2 = date2.getFullYear()
|
const month2 = date2.getMonth()
|
const day2 = date2.getDate()
|
|
// 判断两个日期是否相差一个月
|
if (year1 === year2) {
|
// 年份相等,比较月份差值
|
if (Math.abs(month1 - month2) === 1) {
|
// 月份差值为1,还需要判断具体日期
|
if ((month1 < month2 && day1 < day2) || (month1 > month2 && day1 > day2)) {
|
return true
|
}
|
}
|
} else if (Math.abs(year1 - year2) === 1) {
|
// 年份差值为1,比较月份和日期
|
if (
|
(year1 < year2 && month1 === 11 && month2 === 0 && day1 < day2) ||
|
(year1 > year2 && month1 === 0 && month2 === 11 && day1 > day2)
|
) {
|
return true
|
}
|
}
|
|
// 默认返回false,表示两个日期字符串不相差一个月
|
return false
|
},
|
handleCheckAllChange(val) {
|
this.checkedCities = val ? this.cities : []
|
this.isIndeterminate = false
|
},
|
handleCheckedCitiesChange(value) {
|
const checkedCount = value.length
|
this.checkAll = checkedCount === this.cities.length
|
this.isIndeterminate = checkedCount > 0 && checkedCount < this.cities.length
|
},
|
},
|
}
|
</script>
|
|
<template>
|
<!-- solid #000000 -->
|
<div style="margin: 20px; padding: 10px; border: 1px; height: 620px">
|
<div style="display: flex">
|
<!-- <span class="palce-text"><span class="palce-text-area">区域:</span>静安区 </span> -->
|
|
<!-- 店铺名 级联 -->
|
<!-- <el-cascader v-model="devId" :options="optionsShop" :props="{ expandTrigger: 'hover' }" placeholder="请选择店铺名"
|
clearable /> -->
|
<span class="describe-info">店铺名选择:</span>
|
<ShopNameAndID @submit-id="(n) => (devId[1] = n)" :devId="beginShowShopName"></ShopNameAndID>
|
|
<!-- <span class="describe-time-text">起止时间:</span> -->
|
<!-- 日期时间选择器 -->
|
<!-- <el-date-picker v-model="beginTime" type="datetime" placeholder="开始时间" value-format="YYYY-MM-DD HH:mm:ss" />
|
<el-date-picker v-model="endTime" type="datetime" placeholder="结束时间" value-format="YYYY-MM-DD HH:mm:ss" /> -->
|
<TimeSelect @submit-time="giveTime"></TimeSelect>
|
<el-button type="primary" plain :loading="button.queryButton" @click="lineChart"
|
>查询</el-button
|
>
|
|
<el-tooltip
|
class="box-item"
|
effect="dark"
|
content="点击折线图/表格切换"
|
placement="top-start"
|
>
|
<el-icon class="iconSwich clickable" :size="25" @click="isSwitch = !isSwitch">
|
<i-ep-DataLine v-show="isSwitch" />
|
<!-- 展示折线图 -->
|
<i-ep-Grid v-show="!isSwitch" />
|
<!-- 展示数据表格 -->
|
</el-icon>
|
</el-tooltip>
|
|
<el-tooltip
|
class="box-item"
|
effect="dark"
|
content="点击可导出Excel文件"
|
placement="top-start"
|
>
|
<el-icon class="iconExcel clickable" @click="dialogFormVisible = !dialogFormVisible">
|
<i-ep-Download />
|
<!-- 导出为Excel -->
|
</el-icon>
|
</el-tooltip>
|
</div>
|
<hr style="margin-top: 10px" />
|
|
<!-- 弹出导出Excel页面 -->
|
<el-dialog v-model="dialogFormVisible" title="历史油烟数据导出">
|
<el-checkbox
|
v-model="checkAll"
|
:indeterminate="isIndeterminate"
|
@change="handleCheckAllChange"
|
>全选</el-checkbox
|
>
|
<el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange">
|
<el-checkbox v-for="city in cities" :key="city" :label="city">{{ city }}</el-checkbox>
|
</el-checkbox-group>
|
|
<!-- 时间选择器 -->
|
<div style="margin-top: 30px">
|
<span>起止时间:</span>
|
<el-date-picker
|
v-model="exportBeginTime"
|
type="datetime"
|
placeholder="开始时间"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
|
<el-date-picker
|
v-model="exportEndTime"
|
type="datetime"
|
placeholder="结束时间"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
</div>
|
|
<div style="margin-top: 50px; font-size: 15px">
|
<span>已选择的店铺个数为:{{ checkedCities.length }}</span>
|
</div>
|
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="dialogFormVisible = false">取消</el-button>
|
<el-button type="primary" @click="exportDom">
|
<!--同时导出为Excel -->
|
导出Excel
|
</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<div>
|
<el-radio-group v-model="radio" v-show="!isSwitch" @change="setChart">
|
<el-radio :label="1">油烟浓度</el-radio>
|
<el-radio :label="2">风机电流</el-radio>
|
<el-radio :label="3">净化器电流</el-radio>
|
</el-radio-group>
|
</div>
|
|
<div v-show="!isSwitch && !isNoData" v-loading="loading" class="chart-container">
|
<lineChart :chartData="options"></lineChart>
|
</div>
|
|
<!-- 表格数据 -->
|
<div v-show="isSwitch && !isNoData" v-loading="loading" class="container">
|
<el-table
|
:data="displayData"
|
style="width: 100%; margin-top: 25px"
|
height="500px"
|
table-layout="fixed"
|
:show-overflow-tooltip="true"
|
>
|
<el-table-column fixed prop="mvStatCode" label="设备编号"> </el-table-column>
|
<el-table-column prop="diName" label="店铺名称"> </el-table-column>
|
<el-table-column prop="mvDataTime" label="采集时间"> </el-table-column>
|
<el-table-column prop="mvFanElectricity" label="风机电流(A)"> </el-table-column>
|
<el-table-column prop="mvPurifierElectricity" label="净化器电流(A)"> </el-table-column>
|
<el-table-column prop="mvFumeConcentration2" label="油烟浓度(mg/m³)"> </el-table-column>
|
</el-table>
|
<el-pagination
|
background
|
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
:page-sizes="[10, 20, 50, 100]"
|
:total="total"
|
:page-size="pageSize"
|
layout="total,prev, pager, next, jumper"
|
/>
|
|
<!-- layout="total, sizes, prev, pager, next, jumper" -->
|
</div>
|
<el-empty v-show="isNoData" :image-size="200" />
|
</div>
|
</template>
|
|
<style scoped>
|
/* 地区文本 */
|
.palce-text {
|
margin-top: 5px;
|
margin-right: 20px;
|
}
|
/* 区域文本 */
|
.palce-text-area {
|
font-weight: bold;
|
}
|
/* 店铺名选择文本 */
|
.describe-info {
|
margin-top: 5px;
|
font-weight: bold;
|
}
|
/* 时间选择文本 */
|
.describe-time-text {
|
margin-left: 30px;
|
margin-top: 5px;
|
font-weight: bold;
|
}
|
/* 可鼠标箭头变为可点击状态 */
|
.clickable {
|
cursor: pointer;
|
}
|
.button-header-switch {
|
margin-top: 30px;
|
margin-bottom: 30px;
|
}
|
|
.ellipsis {
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
}
|
|
.iconSwich {
|
margin-left: 60px;
|
bottom: -6px;
|
}
|
|
.iconExcel {
|
font-size: 25px;
|
margin-left: 20px;
|
bottom: -6px;
|
}
|
|
.container {
|
display: flex;
|
flex-direction: column;
|
}
|
:deep().el-dialog {
|
border-radius: 9px;
|
}
|
|
.el-table {
|
color: #000000;
|
}
|
.chart-container {
|
height: 60vh;
|
width: 80vw;
|
}
|
</style>
|