<!-- 历史数据 -->
|
<script >
|
import * as XLSX from 'xlsx/xlsx.mjs';
|
import dayjs from 'dayjs';
|
import axiosInstanceInstance from '../utils/request.js'
|
import TimeSelect from '../sfc/TimeSelect.vue';
|
|
// import ShopNameAndID from '../sfc/TimeSelect.vue';
|
|
const ShopNameAndID = defineAsyncComponent(() =>
|
import('../sfc/../sfc/ShopNameAndID.vue')
|
)
|
|
// 异步组件
|
const lineChart = defineAsyncComponent(() =>
|
import('../sfc/FumeFanPurifierChart.vue')
|
)
|
export default {
|
components: {
|
lineChart,
|
ShopNameAndID,
|
TimeSelect
|
},
|
data() {
|
return {
|
// 空状态
|
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
|
}
|
]
|
}
|
console.log('option为:',this.options);
|
}
|
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
|
},
|
|
]
|
}
|
console.log('option为:',this.options);
|
}
|
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
|
}
|
]
|
}
|
}
|
console.log('option为:',this.options);
|
}
|
else{
|
console.log('exceedingData无数据');
|
}
|
|
|
},
|
// 返回前一周分钟数据表数据
|
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
|
|
console.log(this.currentDateTime, this.oneWeekAgoDateTime);
|
|
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);
|
// this.drawChart();
|
this.loading = false;
|
console.log('历史数据为:', this.exceedingData);
|
})
|
|
},
|
|
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
|
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.isNoData = false
|
// this.displayData = response.data.data //表格渲染
|
// 分页
|
this.total = this.exceedingData.length;
|
// 默认显示第一页
|
this.handleCurrentChange(1);
|
// 展示折线图
|
// this.drawChart();
|
})
|
},
|
|
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;
|
console.log(this.exportData);
|
});
|
},
|
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();
|
console.log(month1, month2);
|
|
// 判断两个日期是否相差一个月
|
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">
|
<h1 style="margin-bottom: 20px; display: flex; white-space: nowrap">油烟历史数据</h1>
|
<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 @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="auto">
|
<el-table-column fixed prop="mvStatCode" label="设备编号">
|
<template #default="{ row }">
|
<el-tooltip effect="dark" :content="row.mvStatCode">
|
<div class="cell ellipsis">{{ row.mvStatCode }}</div>
|
</el-tooltip>
|
</template>
|
</el-table-column>
|
<el-table-column prop="diName" label="店铺名称">
|
<template #default="{ row }">
|
<el-tooltip effect="dark" :content="row.diName">
|
<div class="cell ellipsis">{{ row.diName }}</div>
|
</el-tooltip>
|
</template>
|
</el-table-column>
|
|
<el-table-column prop="mvDataTime" label="采集时间">
|
<template #default="{ row }">
|
<el-tooltip effect="dark" :content="row.mvDataTime">
|
<div class="cell ellipsis">{{ row.mvDataTime }}</div>
|
</el-tooltip>
|
</template>
|
</el-table-column>
|
<el-table-column prop="mvFanElectricity" label="风机电流(A)">
|
<template #default="{ row }">
|
<el-tooltip effect="dark" :content="row.mvFanElectricity">
|
<div class="cell ellipsis">{{ row.mvFanElectricity }}</div>
|
</el-tooltip>
|
</template>
|
</el-table-column>
|
<el-table-column prop="mvPurifierElectricity" label="净化器电流(A)">
|
<template #default="{ row }">
|
<el-tooltip effect="dark" :content="row.mvPurifierElectricity">
|
<div class="cell ellipsis">{{ row.mvPurifierElectricity }}</div>
|
</el-tooltip>
|
</template>
|
</el-table-column>
|
<el-table-column prop="mvFumeConcentration2" label="油烟浓度(mg/m³)">
|
<template #default="{ row }">
|
<el-tooltip effect="dark" :content="row.mvFumeConcentration2">
|
<div class="cell ellipsis">{{ row.mvFumeConcentration2 }}</div>
|
</el-tooltip>
|
</template>
|
</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;
|
}
|
</style>
|