| | |
| | | <template> |
| | | <div class="exception-root-container"> |
| | | <el-row ref="h1"> |
| | | <el-col> |
| | | <!-- 菜单读标题 --> |
| | | <div ref="h1" class="header-container"> |
| | | <span class="describe-info">店铺名选择:</span> |
| | | <!-- 店铺名 级联 --> |
| | | <ShopNameAndID |
| | | @submit-id="(n) => (deviceId[1] = n)" |
| | | :devId="全部" |
| | | ></ShopNameAndID> |
| | | |
| | | <!-- 异常类型选择 --> |
| | | <ExceptionType @submitExceptionType="(val) => (exceptionValue = val)"> |
| | | </ExceptionType> |
| | | |
| | | <!-- <div style="display: flex"> --> |
| | | <!-- <span class="describe-time-text">起止时间:</span> --> |
| | | <!-- 日期时间选择器 --> |
| | | <TimeSelect @submit-time="giveTime"></TimeSelect> |
| | | <!-- </div> --> |
| | | </div> |
| | | <div ref="h2" style="display: flex; margin-top: 2px; justify-content: right"> |
| | | <!-- <span class="collapse-header-text"> |
| | | 静安区 {{ beginTime }} —— {{ endTime }} 油烟检测异常信息汇总</span |
| | | > --> |
| | | <!-- 做成表单 --> |
| | | <div |
| | | ref="h2" |
| | | style="display: flex; margin-top: 2px; justify-content: right" |
| | | > |
| | | |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="showTable" |
| | | style="margin-left: 20px" |
| | | >查询</el-button |
| | | > |
| | | <el-button |
| | | type="warning" |
| | | plain |
| | | @click="getAllData" |
| | | style="margin-left: 20px" |
| | | >查询全部</el-button |
| | | > |
| | | |
| | | <el-tooltip |
| | |
| | | </el-icon> |
| | | </el-tooltip> |
| | | </div> |
| | | <div style="display: flex; justify-content: right"> |
| | | <div style="display: flex; justify-content: right;margin-right:40px"> |
| | | <span class="collapse-header-text"> |
| | | 静安区 {{ beginTime }} —— {{ endTime }} 油烟检测异常信息汇总</span |
| | | > |
| | |
| | | content="点击可折叠" |
| | | placement="right-start" |
| | | > |
| | | |
| | | </el-tooltip> |
| | | </template> |
| | | <el-card class="box-card"> |
| | | <el-row :gutter="25"> |
| | | <el-col :span="8"> |
| | | <div style="display: flex;"> |
| | | <img src="@/assets/exceed.jpg" style="width: 25px;height: 25px;margin-top: 5px;" /> |
| | | <span style="font-size: 16px;font-weight: bold;margin-top: 4px;margin-left: 4px;">油烟浓度超标</span> |
| | | <div style="display: flex"> |
| | | <img |
| | | src="@/assets/exceed.jpg" |
| | | style="width: 25px; height: 25px; margin-top: 5px" |
| | | /> |
| | | <span |
| | | style=" |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | margin-top: 4px; |
| | | margin-left: 4px; |
| | | " |
| | | >油烟浓度超标</span |
| | | > |
| | | </div> |
| | | |
| | | <div class="box-card-label"> |
| | | <el-scrollbar> |
| | | <span class="box-card-label">店铺数量:</span> |
| | | <span style="font-size: 20px" |
| | | >{{ exception0.length }} /{{ shopsTotal }}</span |
| | |
| | | ((exception0.length / shopsTotal) * 100).toFixed(1) |
| | | }}%</span |
| | | > |
| | | </el-scrollbar> |
| | | </div> |
| | | |
| | | <hr /> |
| | | <div class="box-card-butcontainer"> |
| | | <el-card class="sub-box-card"> |
| | | <el-scrollbar max-height="70px"> |
| | | <ExceptionText |
| | | v-for="(item,index) in exception0" |
| | | :key="item" |
| | |
| | | @submit-exception-data="getAbnormalDataByClick" |
| | | > |
| | | {{ item.diName }} |
| | | <span v-if="index<exception0.length-1" class="text-blank"> , </span> |
| | | <span |
| | | v-if="index < exception0.length - 1" |
| | | class="text-blank" |
| | | >,</span |
| | | > |
| | | </ExceptionText> |
| | | </el-scrollbar> |
| | | </el-card> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="8"> |
| | | <div style="display: flex;"> |
| | | <img src="@/assets/exception.jpg" style="width: 25px;height: 25px;margin-top: 5px;" /> |
| | | <span style=" font-size: 16px;font-weight: bold;margin-top: 5px;margin-left: 4px;" |
| | | <div style="display: flex"> |
| | | <img |
| | | src="@/assets/exception.jpg" |
| | | style="width: 25px; height: 25px; margin-top: 5px" |
| | | /> |
| | | <span |
| | | style=" |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | margin-top: 5px; |
| | | margin-left: 4px; |
| | | " |
| | | >供电异常</span |
| | | > |
| | | </div> |
| | | <div class="box-card-label"> |
| | | <el-scrollbar> |
| | | <span class="box-card-label">店铺数量:</span> |
| | | <span style="font-size: 20px" |
| | | >{{ exception1.length }} /{{ shopsTotal }}</span |
| | |
| | | ((exception1.length / shopsTotal) * 100).toFixed(1) |
| | | }}%</span |
| | | > |
| | | </el-scrollbar> |
| | | </div> |
| | | |
| | | <hr /> |
| | | |
| | | <div> |
| | | |
| | | <el-card class="sub-box-card"> |
| | | <el-scrollbar max-height="70px"> |
| | | <ExceptionText |
| | | v-for="(item,index) in exception1" |
| | | :key="item" |
| | |
| | | @submit-exception-data="getAbnormalDataByClick" |
| | | > |
| | | {{ item.diName }} |
| | | <span v-if="index < exception1.length-1" class="text-blank"> , </span> |
| | | <span |
| | | v-if="index < exception1.length - 1" |
| | | class="text-blank" |
| | | >,</span |
| | | > |
| | | </ExceptionText> |
| | | </el-scrollbar> |
| | | </el-card> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="8"> |
| | | <div style="display: flex;"> |
| | | <img src="@/assets/offline.jpg" style="width: 25px;height: 25px;margin-top: 5px;" /> |
| | | <span style=" font-size: 16px;font-weight: bold;margin-top: 5px;margin-left: 4px;">掉线</span> |
| | | <div style="display: flex"> |
| | | <img |
| | | src="@/assets/offline.jpg" |
| | | style="width: 25px; height: 25px; margin-top: 5px" |
| | | /> |
| | | <span |
| | | style=" |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | margin-top: 5px; |
| | | margin-left: 4px; |
| | | " |
| | | >掉线</span |
| | | > |
| | | </div> |
| | | <div class="box-card-label"> |
| | | <el-scrollbar> |
| | | <span class="box-card-label">店铺数量:</span> |
| | | <span style="font-size: 20px" |
| | | >{{ exception2.length }} /{{ shopsTotal }}</span |
| | |
| | | ((exception2.length / shopsTotal) * 100).toFixed(1) |
| | | }}%</span |
| | | > |
| | | </el-scrollbar> |
| | | </div> |
| | | <hr /> |
| | | <div> |
| | | <el-card class="sub-box-card"> |
| | | <el-scrollbar max-height="70px"> |
| | | <ExceptionText |
| | | v-for="(item,index) in exception2" |
| | | :key="item" |
| | |
| | | @submit-exception-data="getAbnormalDataByClick" |
| | | > |
| | | {{ item.diName }} |
| | | <span v-if="index<exception2.length-1" class="text-blank"> , </span> |
| | | <span |
| | | v-if="index < exception2.length - 1" |
| | | class="text-blank" |
| | | >,</span |
| | | > |
| | | </ExceptionText> |
| | | </el-scrollbar> |
| | | </el-card> |
| | | </div> |
| | | </el-col> |
| | |
| | | <!-- <hr/> |
| | | <br> --> |
| | | <h4 class="table-text"> 异常数据</h4> |
| | | <!-- --> |
| | | </el-col> |
| | | </el-row> |
| | | <el-card class="table-page" v-show="!isNoData"> |
| | | |
| | | <el-table |
| | | ref="tableH" |
| | | v-loading="loading" |
| | | :data="displayData" |
| | | style="width: 100%" |
| | | :row-class-name="tableRowClassName" |
| | | stripe |
| | | border |
| | | :height=tableHeight |
| | | :height="tableHeight" |
| | | > |
| | | <el-table-column fixed prop="diName" label="店铺名称" width="340"> |
| | | <el-table-column fixed prop="diName" label="店铺名称" > |
| | | <template #default="{ row }"> |
| | | <el-tooltip effect="dark" :content="row.diName"> |
| | | <div class="cell ellipsis">{{ row.diName }}</div> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="devId" label="设备编号" width="230"> |
| | | <el-table-column prop="devId" label="设备编号" > |
| | | <template #default="{ row }"> |
| | | <el-tooltip effect="dark" :content="row.devId"> |
| | | <div class="cell ellipsis">{{ row.devId }}</div> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="exception" label="异常分类" width="150"> |
| | | <el-table-column prop="exception" label="异常分类" > |
| | | <template #default="{ row }"> |
| | | <el-tooltip effect="dark" :content="row.exception"> |
| | | <div class="cell ellipsis">{{ row.exception }}</div> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="异常类型" width="150"> |
| | | <el-table-column label="异常类型" > |
| | | <template #default="{ row }"> |
| | | <span v-if="row.exceptionType == '0'">油烟数据超标</span> |
| | | <span v-else-if="row.exceptionType == '1'">疑似供电异常</span> |
| | | <span v-else-if="row.exceptionType == '2'">掉线</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="region" label="地区" width="150"> |
| | | <el-table-column prop="region" label="地区" > |
| | | <template #default="{ row }"> |
| | | <el-tooltip effect="dark" :content="row.region"> |
| | | <div class="cell ellipsis">{{ row.region }}</div> |
| | |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="200"> |
| | | <el-table-column label="操作" > |
| | | <template #default="{ row }"> |
| | | <el-button type="warning" @click="showDrawer(row)" |
| | | >查看详情</el-button |
| | |
| | | <template #header> |
| | | <div style="font-size: 17px"> |
| | | 店铺名:{{ rowShopName }} |
| | | <di style="margin-left: 40px">异常类型:</di> |
| | | <span style="margin-left: 40px">异常类型:</span> |
| | | <span v-if="rowExceptionType == '0'">油烟数据超标</span> |
| | | <span v-else-if="rowExceptionType == '1'">供电异常</span> |
| | | <span v-else-if="rowExceptionType == '2'">掉线</span> |
| | |
| | | |
| | | <!-- 超标数据时 --> |
| | | <!-- 折线图 --> |
| | | <div |
| | | ref="chart" |
| | | |
| | | <!-- 掉线 --> |
| | | <!-- <div |
| | | ref="ref" |
| | | v-show="isOfflineShow" |
| | | style=" |
| | | width: 100%; |
| | | height: 300px; |
| | |
| | | margin-left: 10px; |
| | | min-width: 350px; |
| | | " |
| | | ></div> |
| | | ></div> --> |
| | | |
| | | <!-- v-show="!isAbnormal" --> |
| | | <!-- 表格 --> |
| | | <ExceptionTypeLineChart :option="option" :is-open-dialog="centerDialogVisible"></ExceptionTypeLineChart> |
| | | |
| | | <!-- --> |
| | | <div style="margin-top: 40px; margin-bottom: 5px; border: 1px"> |
| | |
| | | </div> |
| | | |
| | | <el-tag type="success" class="mx-1" effect="dark" round |
| | | ><span class="table-line-lable">异常记录: </span> |
| | | ><span class="table-line-lable" v-show="rowExceptionType == '0'">异常记录: </span> |
| | | <span v-show="rowExceptionType == '1' || rowExceptionType == '2'">缺失数据:</span> |
| | | <span class="table-line-num">{{ exceptionTotal }}条</span> |
| | | <span v-show="rowExceptionType === '1' || rowExceptionType === '2'"> |
| | | (逻辑计算)</span |
| | | > |
| | | </el-tag> |
| | | <!-- <el-tag type="success" class="mx-1" effect="dark" round v-show="rowExceptionType === '1'" |
| | | ><span class="table-line-lable">表格行数: </span> |
| | | <span class="table-line-num">{{ exceptionTotal }}</span></el-tag> --> |
| | | </el-dialog> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import ExceptionType from '../sfc/ExceptionType.vue'; |
| | | import TimeSelect from '../sfc/TimeSelect.vue'; |
| | | import ExceptionText from '../sfc/ExceptionText.vue'; |
| | | import * as echarts from 'echarts'; |
| | | import * as XLSX from 'xlsx/xlsx.mjs'; |
| | | import dayjs from 'dayjs'; |
| | | import axiosInstanceInstance from '../utils/request.js'; |
| | |
| | | const ShopNameAndID = defineAsyncComponent(() => |
| | | import('../sfc/../sfc/ShopNameAndID.vue') |
| | | ); |
| | | export default { |
| | | |
| | | // 异常图形异步组件 |
| | | const ExceptionTypeLineChart = defineAsyncComponent(() => |
| | | import('../sfc/ExceptionTypeLineChart.vue') |
| | | ); |
| | | export default { |
| | | name: 'TablePage', |
| | | components: { |
| | | ExceptionType, |
| | | TimeSelect, |
| | | ShopNameAndID, |
| | | ExceptionText |
| | | ExceptionText, |
| | | ExceptionTypeLineChart |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | // 异常折线图的配置 |
| | | option: {}, |
| | | // 折线图展示 |
| | | isChartShow: false, |
| | | // table元素 |
| | | tableRef:null, |
| | | // 异常表格数据 |
| | |
| | | // 无数据时增加的后40分钟数据 |
| | | afterData: [], |
| | | |
| | | // 折线图实例 |
| | | chart: null, |
| | | // -1表示未选择表格的行 |
| | | selectedRowIndex: -1, |
| | | |
| | |
| | | // 抽屉加载动画 |
| | | loadingDrawer: true, |
| | | // 分页展示数据 |
| | | // 每页展示的数据 |
| | | |
| | | // 异常表的数据 |
| | | displayData: [], |
| | | // 存放后端返回的json数据 |
| | | jsonData: [], |
| | |
| | | endTime: '', |
| | | // 异常表数据 |
| | | abnormalData: [], |
| | | // 该时段的详细超标数据 |
| | | // 弹出的对话框中的异常表格数据 |
| | | exceedingData: [], |
| | | drawerVisible: false, |
| | | // 表格的一行数据 |
| | |
| | | optionsShop: [], |
| | | // 异常类型选择器 |
| | | exceptionValue: [], |
| | | exceptionOptions: [ |
| | | { |
| | | value: '0', |
| | | label: '油烟浓度超标' |
| | | }, |
| | | { |
| | | value: '1', |
| | | label: '疑似供电异常' |
| | | }, |
| | | { |
| | | value: '2', |
| | | label: '掉线' |
| | | } |
| | | ] |
| | | }; |
| | | }, |
| | | // 监听 判断按钮是否可点击 |
| | | watch: { |
| | | selectedRowIndex(newVaue) { |
| | | // 处于表格的第一条数据 设置‘上一条’按钮不可点 |
| | | if (newVaue === 0) { |
| | | // 处于表格的最后一条数据 设置‘上一条’按钮不可点 |
| | | if (newVaue === this.displayData.length - 1) { |
| | | this.isPreCantouch = true; |
| | | //用户先点了表格最后一条,next为true,然后点击第一条,pre为true。此时两个按钮都被封锁 |
| | | //用户先点了第一条,pre为true,然后点击最后一条,next为true。此时两个按钮都被封锁 |
| | | if (this.isNextCantouch == true) { |
| | | this.isNextCantouch = false; |
| | | } |
| | | } |
| | | // 处于表格最后一提哦啊数据 设置‘下一条’按钮不可点 |
| | | else if (newVaue === this.displayData.length - 1) { |
| | | // 处于表格第一条数据 设置‘下一条’按钮不可点 |
| | | else if (newVaue === 0) { |
| | | this.isNextCantouch = true; |
| | | //用户先点了第一条,pre为true,然后点击最后一条,next为true。此时两个按钮都被封锁 |
| | | //用户先点了表格最后一条,next为true,然后点击第一条,pre为true。此时两个按钮都被封锁 |
| | | if (this.isPreCantouch == true) { |
| | | this.isPreCantouch = false; |
| | | } |
| | |
| | | }, |
| | | endTime() { |
| | | this.getShopNames(); |
| | | }, |
| | | centerDialogVisible() { |
| | | window.addEventListener('resize', this.updateChart); |
| | | } |
| | | }, |
| | | |
| | | mounted() { |
| | | |
| | | // 从接口获取店铺名称 给级联下拉框 |
| | | this.getDeviceInfo(); |
| | | |
| | | // 展示最近7天数据 |
| | | this.getRecentSevenDays(); |
| | | |
| | | // 根据异常类型返回店铺名称和设备编号 渲染异常分析部分对应的店铺名 |
| | | this.getShopNames(); |
| | | this.calcTableHeight() |
| | | window.addEventListener('resize', this.updateChart); |
| | | // this.tableHeight = this.calcTableHeight() |
| | | |
| | | }, |
| | | methods: { |
| | | // calcTableHeight() { |
| | | // const h1 = this.$refs.h1.offsetHeight; |
| | | // const h2 = this.$refs.h2.offsetHeight; |
| | | // const h3 = this.$refs.h3.$el.offsetHeight; |
| | | // const h4 = this.$refs.h4.$el.offsetHeight; |
| | | // // return `calc(100vh - ${h1}px - ${h2}px - var(--el-main-padding) * 2 - var(--el-header-height))`; |
| | | // return `calc(100vh - ${h1}px - ${h2}px- ${h3}px - ${h4}px - 60px - var(--el-main-padding) * 2)`; |
| | | // }, |
| | | |
| | | warn() { |
| | | alert('点击了'); |
| | | // 动态计算表格高度 |
| | | calcTableHeight(){ |
| | | const h1 = this.$refs.h1.$el.offsetHeight; |
| | | const h2 = this.$refs.h4.$el.offsetHeight; |
| | | this.tableHeight = `calc(100vh - ${h1}px - ${h2}px - 45px - var(--el-main-padding) * 2 - var(--el-card-padding))`; |
| | | }, |
| | | |
| | | // 时间是否超过10分钟 |
| | | isTimeDifferenceGreaterThan10Minutes(dateString1, dateString2) { |
| | | const date1 = new Date(dateString1); |
| | | const date2 = new Date(dateString2); |
| | | |
| | | // 计算两个日期的时间差(毫秒) |
| | | const timeDifferenceMs = Math.abs(date1 - date2); |
| | | |
| | | // 转换为分钟 |
| | | const timeDifferenceMinutes = Math.floor(timeDifferenceMs / (1000 * 60)); |
| | | |
| | | // 判断时间差是否大于10分钟 |
| | | return timeDifferenceMinutes > 10; |
| | | }, |
| | | |
| | | // 以10分钟为间隔返回时间字符串数组 |
| | | generateTimePoints(timePoints, yAxisData) { |
| | | let updatedTimePoints = []; |
| | | let yAxisDataAdressed = []; |
| | | for (let i = 0; i < timePoints.length; i++) { |
| | | updatedTimePoints.push(timePoints[i]); |
| | | yAxisDataAdressed.push(yAxisData[i]); |
| | | if (i < timePoints.length - 1) { |
| | | let current = timePoints[i]; |
| | | let next = timePoints[i + 1]; |
| | | while (this.isTimeDifferenceGreaterThan10Minutes(current, next)) { |
| | | console.log('generateTimePoints'); |
| | | current = dayjs(current) |
| | | .add(10, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | updatedTimePoints.push(current); |
| | | yAxisDataAdressed.push(null); |
| | | } |
| | | } |
| | | } |
| | | let obj = {}; |
| | | obj['time'] = updatedTimePoints; |
| | | obj['data'] = yAxisDataAdressed; |
| | | return obj; |
| | | }, |
| | | |
| | | 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; |
| | | }, |
| | | |
| | | // 刚打开卡片时第一个图形不会自动伸缩 当点击上/下一条时会自动伸缩 |
| | | // 图形响应式变化 |
| | | updateChart() { |
| | | this.$nextTick(() => { |
| | | if (this.chart) { |
| | | this.chart.resize(); |
| | | } |
| | | }); |
| | | }, |
| | | // updateChart() { |
| | | // this.$nextTick(() => { |
| | | // if (this.chart1) { |
| | | // this.chart1.resize(); |
| | | // } |
| | | // if (this.chart2) { |
| | | // this.chart2.resize(); |
| | | // } |
| | | // }); |
| | | // }, |
| | | // 从时间选择器组件拿到开始和结束时间 |
| | | giveTime(val) { |
| | | //将中国标准时间转为指定格式(该组件返回的标准时间的格式,所以必须的加这个函数) |
| | |
| | | this.endTime = dayjs(val[1]).format('YYYY-MM-DD HH:mm:ss'); |
| | | }, |
| | | |
| | | // 异常的开始和结束时间。返回时间数组,从开始时间的后10分钟到结束时间为止。 |
| | | // 参数:异常的开始和结束时间。返回时间数组,从开始时间的后10分钟到结束时间为止。 |
| | | // 比如12:00:00 -13:00:00 所以返回的数组元素是 12:10:00 ,12:20:00,12:30:00....13:00:00 |
| | | descTenTime(begin, end) { |
| | | // 保留结果 |
| | | let time = []; |
| | | if(begin == end){ |
| | | time.push(begin) |
| | | return time |
| | | } |
| | | // 保留结果 00 10 20 30 |
| | | let temp = dayjs(begin).add(10, 'minute').format('YYYY-MM-DD HH:mm:ss'); |
| | | while (temp != end) { |
| | | time.push(temp); |
| | |
| | | } |
| | | // 加上异常的结束时间 |
| | | time.push(temp); |
| | | |
| | | return time; |
| | | }, |
| | | |
| | |
| | | this.rowBeginTime = this.displayData[index].beginTime; |
| | | this.rowEndTime = this.displayData[index].endTime; |
| | | this.rowMvStatCode = this.displayData[index].devId; |
| | | console.log('行名字:', this.rowShopName); |
| | | console.log('行名字:', this.rowExceptionType); |
| | | console.log('行名字:', this.rowBeginTime); |
| | | console.log('行名字:', this.rowEndTime); |
| | | }, |
| | | // 供电异常和掉线时的表格数据 |
| | | |
| | | //功能: 供电异常和掉线时的表格数据 |
| | | setExceptionData() { |
| | | // 清空,让历史数据条数隐藏,使无数据的标签条数显示出来 |
| | | // this.exceedingData=[] |
| | | // 清空上次的数据,防止影响本次的展示数 |
| | | // this.abnormalTimeTenMinute = []; |
| | | // 无数据时的时间数组 时间相差10分钟 |
| | | const abnormalTimeTenMinute = this.descTenTime( |
| | | this.rowBeginTime, |
| | | this.rowEndTime |
| | | ); |
| | | ) |
| | | // 去除供电异常和掉线区间的第一个有元素的值 |
| | | this.exceedingData = [] |
| | | |
| | | for (let i = 0; i < abnormalTimeTenMinute.length; i++) { |
| | | this.exceedingData.push({ |
| | | mvStatCode: this.rowMvStatCode, |
| | |
| | | mvFumeConcentration2: '' |
| | | }); |
| | | } |
| | | |
| | | // 保存无数据时表格条数 |
| | | this.exceptionTotal = abnormalTimeTenMinute.length; |
| | | }, |
| | |
| | | this.selectedRowIndex = this.displayData.indexOf(row); |
| | | // 进入抽屉页面更新头部数据 |
| | | this.setinfo(this.selectedRowIndex); |
| | | console.log('选择中行:', this.selectedRowIndex); |
| | | }, |
| | | |
| | | // 获取获取表格上一行数据 |
| | | getPreviousRowData() { |
| | | // 不是表格的第一行 |
| | | if (this.selectedRowIndex !== 0) { |
| | | // ’下一条‘的按钮恢复点击 |
| | | // this.isNextCantouch = false |
| | | |
| | | //得到上一行数据索引 |
| | | this.selectedRowIndex = this.selectedRowIndex - 1; |
| | | console.log('上', this.selectedRowIndex); |
| | | |
| | | console.log(this.displayData[this.selectedRowIndex]); |
| | | //请求数据 改变exceedingData |
| | | this.setinfo(this.selectedRowIndex); |
| | | let params = {}; |
| | | if (this.drawerData.devId) { |
| | | params['devId'] = this.displayData[this.selectedRowIndex].devId; |
| | | } |
| | | if (this.drawerData.beginTime) { |
| | | params['beginTime'] = |
| | | this.displayData[this.selectedRowIndex].beginTime; |
| | | } |
| | | if (this.drawerData.endTime) { |
| | | params['endTime'] = this.displayData[this.selectedRowIndex].endTime; |
| | | } |
| | | |
| | | axiosInstanceInstance |
| | | .get('/fume/exceed', { params: params }) |
| | | .then((response) => { |
| | | // 保存返回的超标数据 |
| | | this.exceedingData = response.data.data; |
| | | this.chart = null; |
| | | this.drawChart(); |
| | | this.exceptionTotal = this.exceedingData.length; |
| | | }); |
| | | } |
| | | //表格的第一行,则上一条无数据 |
| | | else if (this.selectedRowIndex === 0) { |
| | | console.log(null); |
| | | // 警告 |
| | | // ElMessage.warn('已是第一条数据'); |
| | | // ElMessage.info('已是该页第一条数据'); |
| | | |
| | | // ’上一条‘的按钮不可点击 |
| | | // this.isPreCantouch = true |
| | | } |
| | | }, |
| | | |
| | | // 获取获取表格下一行数据 |
| | | getNextRowData() { |
| | | // 不是表格的第一行 |
| | | if (this.selectedRowIndex < this.displayData.length - 1) { |
| | | // ’上一条‘的按钮恢复点击 |
| | | // this.isPreCantouch = false |
| | | |
| | | if (this.selectedRowIndex !== 0) { |
| | | //得到上一行数据索引 |
| | | this.selectedRowIndex = this.selectedRowIndex + 1; |
| | | console.log('上', this.selectedRowIndex); |
| | | |
| | | console.log(this.displayData[this.selectedRowIndex]); |
| | | this.selectedRowIndex = this.selectedRowIndex - 1; |
| | | //请求数据 改变exceedingData |
| | | this.setinfo(this.selectedRowIndex); |
| | | let params = {}; |
| | |
| | | if (this.drawerData.endTime) { |
| | | params['endTime'] = this.displayData[this.selectedRowIndex].endTime; |
| | | } |
| | | |
| | | axiosInstanceInstance |
| | | .get('/fume/exceed', { params: params }) |
| | | .then((response) => { |
| | | // 保存返回的超标数据 |
| | | this.exceedingData = response.data.data; |
| | | console.log('返回的异常数据为:'); |
| | | console.log(this.exceedingData); |
| | | this.chart = null; |
| | | this.drawChart(); |
| | | // this.chart = null; |
| | | // this.drawChart(); |
| | | this.drawChartTest(); |
| | | this.exceptionTotal = this.exceedingData.length; |
| | | }); |
| | | } |
| | | //表格的第一行,则上一条无数据 |
| | | else { |
| | | console.log(null); |
| | | // 警告 |
| | | // ElMessage.info('已是该页最后一条数据'); |
| | | } |
| | | }, |
| | | |
| | | // ’下一条‘的按钮不可点击 |
| | | // this.isNextCantouch = true |
| | | // 获取获取表格下一行数据 |
| | | getPreviousRowData() { |
| | | // 不是表格的第一行 |
| | | if (this.selectedRowIndex < this.displayData.length - 1) { |
| | | //得到上一行数据索引 |
| | | |
| | | this.selectedRowIndex = this.selectedRowIndex + 1; |
| | | console.log('上', this.selectedRowIndex); |
| | | |
| | | //请求数据 改变exceedingData |
| | | this.setinfo(this.selectedRowIndex); |
| | | let params = {}; |
| | | if (this.drawerData.devId) { |
| | | params['devId'] = this.displayData[this.selectedRowIndex].devId; |
| | | } |
| | | if (this.drawerData.beginTime) { |
| | | params['beginTime'] = |
| | | this.displayData[this.selectedRowIndex].beginTime; |
| | | } |
| | | if (this.drawerData.endTime) { |
| | | params['endTime'] = this.displayData[this.selectedRowIndex].endTime; |
| | | } |
| | | axiosInstanceInstance |
| | | .get('/fume/exceed', { params: params }) |
| | | .then((response) => { |
| | | // 保存返回的超标数据 |
| | | this.exceedingData = response.data.data; |
| | | console.log(this.exceedingData); |
| | | this.drawChartTest(); |
| | | this.exceptionTotal = this.exceedingData.length; |
| | | }); |
| | | } |
| | | //表格的第一行,则上一条无数据 |
| | | else { |
| | | console.log(null); |
| | | } |
| | | }, |
| | | |
| | |
| | | this.selectTableRow(row); |
| | | |
| | | this.rowTable = row; |
| | | console.log('赋值后row', this.rowTable); |
| | | console.log('赋值后row', this.rowTable); |
| | | // 展开抽屉 |
| | | |
| | | // 表格的行数据以对象形式给drawerData |
| | | this.drawerData = row; |
| | | |
| | | this.centerDialogVisible = true; |
| | | // this.drawerVisible = true; |
| | | console.log(this.drawerData); |
| | | |
| | | // 根据行数据请求详细超标数据渲染折线图 |
| | | let params = {}; |
| | | if (this.drawerData.devId) { |
| | |
| | | .then((response) => { |
| | | // 保存返回的超标数据 |
| | | this.exceedingData = response.data.data; |
| | | this.loadingDrawer = !this.loadingDrawer; |
| | | // this.total = this.exceedingData.length; |
| | | // this.handleCurrentChange(1); // 默认显示第一页 |
| | | console.log('返回的异常数据为:'); |
| | | console.log(this.exceedingData); |
| | | this.drawChart(); |
| | | this.drawChartTest(); |
| | | this.exceptionTotal = this.exceedingData.length; |
| | | }); |
| | | }, |
| | | |
| | | // 用户根据输入的条件查询 |
| | | showTable() { |
| | | if (this.beginTime > this.endTime) { |
| | | alert('请输入正确的时间范围'); |
| | | if (this.isExceedOneMonth(this.beginTime, this.endTime)) { |
| | | alert('时间跨度不能超过一个月'); |
| | | return; |
| | | } |
| | | let params = {}; |
| | | // params['page'] = this.startIndex |
| | | // params['pageSize'] = 10 |
| | | |
| | | if (this.deviceId[1]) { |
| | | params['devId'] = this.deviceId[1]; |
| | | } |
| | |
| | | this.total = this.abnormalData.length; |
| | | this.loading = false; |
| | | if (response.data.data.length == 0) { |
| | | alert('该时段无数据'); |
| | | ElMessage('该时段无数据'); |
| | | this.isNoData = true; |
| | | return; |
| | | } |
| | |
| | | this.handleCurrentChange(1); |
| | | }, |
| | | handleCurrentChange(val) { |
| | | // this.startIndex = (val - 1) * this.pageSize; |
| | | // const endIndex = this.startIndex + this.pageSize; |
| | | |
| | | const startIndex = (val - 1) * this.pageSize; |
| | | const endIndex = startIndex + this.pageSize; |
| | | // console.log('起始索引为:',this.startIndex) |
| | | // console.log('页面大小为:',this.pageSize) |
| | | this.displayData = this.abnormalData.slice(startIndex, endIndex); |
| | | // setTimeout(() => { |
| | | // this.displayData = this.abnormalData |
| | | |
| | | // }, 1000); |
| | | // console.log(this.displayData); |
| | | this.displayData = this.abnormalData.slice(startIndex, endIndex); |
| | | }, |
| | | |
| | | //相差多少个十分钟 计算中并不包括开始时间,但包括结束时间。 |
| | |
| | | return diffInTenMinutes; |
| | | }, |
| | | |
| | | // 供电异常和掉线的折线图 |
| | | linechart(xAxisData1, abnormalBeginTime, abnormalEndTime, fumeExceeding) { |
| | | this.chart = echarts.init(this.$refs.chart); |
| | | // $('#ModalGrade').on('shown.bs.modal', function(){ |
| | | // this.chart.resize() |
| | | // }) |
| | | this.chart.setOption({ |
| | | title: { |
| | | // text: '油烟超标数据', |
| | | // left: 'center' |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | tooltip: {}, |
| | | // legend: { |
| | | // data: ['油烟超标数据'] |
| | | // }, |
| | | toolbox: { |
| | | // 工具栏 |
| | | feature: { |
| | | dataZoom: { |
| | | // 区域缩放 |
| | | yAxisIndex: 'none' |
| | | }, |
| | | |
| | | // 保存为图片 |
| | | saveAsImage: {} |
| | | } |
| | | }, |
| | | xAxis: { |
| | | // type: 'time', |
| | | // 在类目轴(type: 'category')中有效。 |
| | | data: xAxisData1, |
| | | name: '时间' |
| | | // axisLabel: { |
| | | // interval:3, |
| | | // rotate:40 |
| | | // } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLabel: { |
| | | show: true, |
| | | interval: 'auto' |
| | | // formatter:'{value} %' |
| | | }, |
| | | name: 'mg/m³' |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '油烟超标数据', |
| | | type: 'line', |
| | | data: fumeExceeding, |
| | | markLine: { |
| | | silent: true, |
| | | |
| | | data: [ |
| | | // 标注无数据时间段的效果,将这个时间段的数轴部分变为红色 |
| | | { |
| | | name: '无数据', |
| | | xAxis: abnormalBeginTime |
| | | }, |
| | | { |
| | | xAxis: abnormalEndTime |
| | | } |
| | | ], |
| | | lineStyle: { |
| | | color: 'red' |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }); |
| | | }, |
| | | |
| | | // 展示折线图 |
| | | drawChart() { |
| | | // 当出现供电异常和掉线时,时段无数据 则拼接前后段数据 |
| | | if ( |
| | | this.exceedingData.length === 0 || |
| | | this.rowExceptionType === '1' || |
| | | this.rowExceptionType === '2' |
| | | ) { |
| | | // 重构表格 手动填充 |
| | | this.setExceptionData(); |
| | | |
| | | // 展示 |
| | | this.isAbnormal = true; |
| | | // 拼接日期 |
| | | //异常的开始时间 |
| | | this.abnormalBt = this.displayData[this.selectedRowIndex].beginTime; |
| | | //异常的结束时间 |
| | | this.abnormalEt = this.displayData[this.selectedRowIndex].endTime; |
| | | console.log( |
| | | '供电开始', |
| | | this.displayData[this.selectedRowIndex].beginTime |
| | | ); |
| | | console.log( |
| | | '供电结束', |
| | | this.displayData[this.selectedRowIndex].endTime |
| | | ); |
| | | // 往前30分钟 |
| | | const before30MinBegin = dayjs(this.abnormalBt) |
| | | // 参数:异常的开始时间,异常的结束时间。 |
| | | // 功能:返回开始时间的前30分钟的时间点,结束时间后40分钟的时间点 |
| | | before30AndAfter40(begin, end) { |
| | | let time = []; |
| | | const before30MinBegin = dayjs(begin) |
| | | .subtract(30, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | // 后一段的开始时间 |
| | | const after10MinBegin = dayjs(this.abnormalEt) |
| | | const after10MinBegin = dayjs(end) |
| | | .add(10, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | // 往后40分钟 |
| | | const after40MinEnd = dayjs(this.abnormalEt) |
| | | const after40MinEnd = dayjs(end) |
| | | .add(40, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | time.push(before30MinBegin); |
| | | time.push(after10MinBegin); |
| | | time.push(after40MinEnd); |
| | | return time; |
| | | }, |
| | | |
| | | let paramsBefore = { |
| | | devId: this.displayData[this.selectedRowIndex].devId, |
| | | beginTime: before30MinBegin, |
| | | endTime: this.displayData[this.selectedRowIndex].beginTime |
| | | // 参数:设备编号, 开始时间, 结束时间 |
| | | // 功能:返回某设备在该时段历史数据的get请求参数。 |
| | | requestGetParms(devnum, begin, end) { |
| | | return { |
| | | devId: devnum, |
| | | beginTime: begin, |
| | | endTime: end |
| | | }; |
| | | let paramsAfter = { |
| | | devId: this.displayData[this.selectedRowIndex].devId, |
| | | beginTime: after10MinBegin, |
| | | endTime: after40MinEnd |
| | | }; |
| | | // 请求前半段 |
| | | axiosInstanceInstance |
| | | .get('/fume/history', { params: paramsBefore }) |
| | | .then((result) => { |
| | | this.beforeData = result.data.data; |
| | | }, |
| | | // 参数:对象数组(该对象中的属性不能是引用类型,否则拷贝的值还是会相互影响) |
| | | // 功能:拷贝该对象数组。 |
| | | shallowCopyList(itemIsObjOfList) { |
| | | let tempList = []; |
| | | itemIsObjOfList.forEach((item) => { |
| | | tempList.push({ ...item }); |
| | | }); |
| | | return tempList; |
| | | }, |
| | | |
| | | // 请求后半段 |
| | | axiosInstanceInstance |
| | | .get('/fume/history', { params: paramsAfter }) |
| | | .then((result) => { |
| | | this.afterData = result.data.data; |
| | | }); |
| | | |
| | | //用null填充中异常无数据的时间 |
| | | //相差几个10分钟 |
| | | const TenMinuteNum = this.diffTenMinutesNum( |
| | | this.abnormalBt, |
| | | this.abnormalEt |
| | | ); |
| | | //保存空值 |
| | | let tempArr = []; |
| | | for (let i = 0; i < TenMinuteNum; i++) { |
| | | tempArr.push(null); |
| | | } |
| | | console.log('填充数组为:', tempArr); |
| | | |
| | | //合并数组 |
| | | setTimeout(() => { |
| | | this.allExceptionTimeData = [ |
| | | ...this.beforeData, |
| | | ...tempArr, |
| | | ...this.afterData |
| | | ]; |
| | | console.log('合并后数组为', this.allExceptionTimeData); |
| | | //展示图形 |
| | | // 参数:添加首尾时间数据的异常数据数组(元素为对象) |
| | | // 功能:对中间异常区间时间和值进行补充,返回处理后的结果 |
| | | // 详细描述:遍历数组,当发现数组元素为空时,设置该元素的时间为上一个元素时间的后10分钟,并把浓度值设置为null(上个元素的时间一定不为空,无需再去判断上个元素为空的情况)。 |
| | | addTenMinutes(exceptionDataArr) { |
| | | // x轴日期时间 |
| | | let dateList = []; |
| | | // y轴 超标油烟浓度 |
| | | let fumeExceeding = []; |
| | | for (let i = 0; i < this.allExceptionTimeData.length; i++) { |
| | | if (this.allExceptionTimeData[i] == null) { |
| | | //x轴日期 |
| | | //无数据时, 为前面时间点增加10分钟 |
| | | let obj = {}; |
| | | for (let i = 0; i < exceptionDataArr.length; i++) { |
| | | if (exceptionDataArr[i] == null) { |
| | | //x轴日期。元素为null时, 设置该元素的时间为前一元素的时间后10分钟 |
| | | dateList.push( |
| | | dayjs(dateList[dateList.length - 1]) |
| | | .add(10, 'minute') |
| | |
| | | fumeExceeding.push(null); |
| | | } else { |
| | | //x轴日期 |
| | | dateList.push(this.allExceptionTimeData[i].mvDataTime); |
| | | dateList.push(exceptionDataArr[i].mvDataTime); |
| | | // 超标油烟浓度 |
| | | fumeExceeding.push( |
| | | this.allExceptionTimeData[i].mvFumeConcentration2 |
| | | ); |
| | | fumeExceeding.push(exceptionDataArr[i].mvFumeConcentration2); |
| | | } |
| | | } |
| | | console.log('x:', dateList); |
| | | console.log('fume:', fumeExceeding); |
| | | |
| | | //展示折线图 |
| | | this.chart = null; |
| | | this.linechart( |
| | | dateList, |
| | | this.abnormalBt, |
| | | this.abnormalEt, |
| | | fumeExceeding |
| | | ); |
| | | }, 500); |
| | | |
| | | // ---------------------------------------- |
| | | } |
| | | // 油烟浓度超标时的折线图 |
| | | else { |
| | | // // 清空,让无数据条数隐藏,使历史数据的标签条数显示出来 |
| | | // this.abnormalTimeTenMinute = [] |
| | | this.isAbnormal = false; |
| | | // x轴日期时间 |
| | | let dateList = []; |
| | | // y轴 超标油烟浓度 |
| | | let fumeExceeding = []; |
| | | this.exceedingData.forEach((item) => { |
| | | //x轴日期 |
| | | dateList.push(item.mvDataTime); |
| | | // 超标油烟浓度 |
| | | fumeExceeding.push(item.mvFumeConcentration2); |
| | | }); |
| | | // // 存放该时间段每隔十分钟一次的时间点 |
| | | // const xAxisData = []; |
| | | // const xAxisData1 = []; |
| | | let beginTime = new Date(dateList[0]); |
| | | const endTime = new Date(dateList[dateList.length - 1]); |
| | | |
| | | // 往前30分钟 |
| | | const before30MinBegin = dayjs(beginTime) |
| | | .subtract(30, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | const before10MinBegin = dayjs(beginTime) |
| | | .subtract(10, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | |
| | | // 往后40分钟 |
| | | const after30MinEnd = dayjs(endTime) |
| | | .add(30, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | const after10MinEnd = dayjs(endTime) |
| | | .add(10, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | console.log('前后时间为', before30MinBegin, after30MinEnd); |
| | | let paramsBefore = { |
| | | devId: this.displayData[this.selectedRowIndex].devId, |
| | | beginTime: before30MinBegin, |
| | | endTime: before10MinBegin |
| | | }; |
| | | let paramsAfter = { |
| | | devId: this.displayData[this.selectedRowIndex].devId, |
| | | beginTime: after10MinEnd, |
| | | endTime: after30MinEnd |
| | | }; |
| | | // 请求前半段 |
| | | axiosInstanceInstance |
| | | .get('/fume/history', { params: paramsBefore }) |
| | | .then((result) => { |
| | | this.beforeData = result.data.data; |
| | | }); |
| | | // 请求后半段 |
| | | axiosInstanceInstance |
| | | .get('/fume/history', { params: paramsAfter }) |
| | | .then((result) => { |
| | | this.afterData = result.data.data; |
| | | }); |
| | | |
| | | setTimeout(() => { |
| | | console.log('请求后的数据为', this.beforeData, this.afterData); |
| | | this.allExceptionTimeData = [ |
| | | ...this.beforeData, |
| | | ...this.exceedingData, |
| | | ...this.afterData |
| | | ]; |
| | | // x轴日期时间 |
| | | let dateList1 = []; |
| | | // y轴 超标油烟浓度 |
| | | let fumeExceeding1 = []; |
| | | console.log('所有数据长度', this.allExceptionTimeData.length); |
| | | console.log('所有数据', this.allExceptionTimeData); |
| | | for (let i = 0; i < this.allExceptionTimeData.length; i++) { |
| | | if (this.allExceptionTimeData[i] == null) { |
| | | //x轴日期 |
| | | //无数据时, 为前面时间点增加10分钟 |
| | | dateList1.push( |
| | | dayjs(dateList1[dateList1.length - 1]) |
| | | .add(10, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss') |
| | | ); |
| | | // 超标油烟浓度 |
| | | fumeExceeding1.push(null); |
| | | } else { |
| | | //x轴日期 |
| | | dateList1.push(this.allExceptionTimeData[i].mvDataTime); |
| | | // 超标油烟浓度 |
| | | fumeExceeding1.push( |
| | | this.allExceptionTimeData[i].mvFumeConcentration2 |
| | | ); |
| | | } |
| | | } |
| | | |
| | | // 提取时间区间内的数据索引 |
| | | var startIndex = dateList1.findIndex((item) => item === dateList[0]); |
| | | var endIndex = dateList1.findIndex( |
| | | (item) => item === dateList[dateList.length - 1] |
| | | ); |
| | | |
| | | this.chart = echarts.init(this.$refs.chart); |
| | | this.chart.setOption({ |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | obj['dateList'] = dateList; |
| | | obj['fumeExceeding'] = fumeExceeding; |
| | | return obj; |
| | | }, |
| | | |
| | | // 参数:加上前后区间的异常数据,时间字符串 |
| | | // 功能:判断data中是否有该日期时间,存在返回该时间对应的浓度值,否则返回-1 |
| | | findTimeInExceptionData(data, time) { |
| | | for (let i = 0; i < data.length; i++) { |
| | | if(data[i]==null){ |
| | | continue |
| | | } |
| | | if (data[i]['mvDataTime'] == time) { |
| | | return data[i]['mvFumeConcentration2']; |
| | | } |
| | | } |
| | | return -1; |
| | | }, |
| | | // 参数:前区间的开始时间, 后区间的结束时间, 加上前后区间的总时间段的异常数据的对象数组 |
| | | // 功能:根据开始和结束时间,返回以10分钟为间隔的时间和对应的值 |
| | | keepContinuousByEachTenMinutes( |
| | | intervalStarTime, |
| | | intervalEndTime, |
| | | headAndTailExceptionData |
| | | ) { |
| | | let xAxis = []; |
| | | let yAxis = []; |
| | | let obj = {}; |
| | | let current = intervalStarTime; |
| | | let tail = dayjs(intervalEndTime) |
| | | .add(10, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | while (current != tail) { |
| | | let value = this.findTimeInExceptionData( |
| | | headAndTailExceptionData, |
| | | current |
| | | ); |
| | | if (value != -1) { |
| | | xAxis.push(current); |
| | | yAxis.push(value); |
| | | } else { |
| | | xAxis.push(current); |
| | | yAxis.push(null); |
| | | } |
| | | current = dayjs(current) |
| | | .add(10, 'minute') |
| | | .format('YYYY-MM-DD HH:mm:ss'); |
| | | |
| | | } |
| | | obj['xAxis'] = xAxis; |
| | | obj['yAxis'] = yAxis; |
| | | return obj; |
| | | }, |
| | | |
| | | // 参数:超标数据前面区间的数据 |
| | | // 功能:返回除去最后一个元素的数组 |
| | | removeLastItemOfBeforeData(beforeDataOfExceeding){ |
| | | let tempList = []; |
| | | if(beforeDataOfExceeding.length ==1){ |
| | | return tempList |
| | | }else{ |
| | | for(let i=0;i<beforeDataOfExceeding.length-1;i++){ |
| | | tempList.push({ ...beforeDataOfExceeding[i]}) |
| | | } |
| | | return tempList; |
| | | } |
| | | }, |
| | | |
| | | |
| | | |
| | | // 设置option |
| | | // 参数:x轴时间, y轴油烟浓度, 异常类别(0代表超标,1代表供电异常和掉线), 异常开始时间,异常结束时间,异常开始时间在整个区间的索引下标,异常结束时间在整个区间的索引下标 |
| | | setOption( |
| | | xData, |
| | | yData, |
| | | exceptionCategory, |
| | | exceptionBeginTime, |
| | | exceptionEndTime, |
| | | beginIndex, |
| | | endIndex |
| | | ) { |
| | | this.option = {} |
| | | // 超标 |
| | | if (exceptionCategory == 0) { |
| | | this.option = { |
| | | tooltip: {}, |
| | | // legend: { |
| | | // data: ['油烟超标数据'] |
| | | // }, |
| | | toolbox: { |
| | | // 工具栏 |
| | | feature: { |
| | | dataZoom: { |
| | | // 区域缩放 |
| | | yAxisIndex: 'none' |
| | | }, |
| | | // dataZoom: { |
| | | // yAxisIndex: 'none' |
| | | // }, |
| | | // 保存为图片 |
| | | saveAsImage: {} |
| | | } |
| | | }, |
| | | xAxis: { |
| | | // type: 'time', |
| | | // 在类目轴(type: 'category')中有效。 |
| | | data: dateList1, |
| | | name: '时间' |
| | | type: 'category', |
| | | data: xData, |
| | | name: '时间', |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | return value.slice(11, -3); |
| | | } |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLabel: { |
| | | show: true, |
| | | interval: 'auto' |
| | | // formatter:'{value} %' |
| | | }, |
| | | name: 'mg/m³' |
| | | }, |
| | | visualMap: { |
| | | show: false, |
| | | dimension: 0, |
| | | pieces: [ |
| | | { |
| | | lte: startIndex, |
| | | color: 'green' |
| | | }, |
| | | { |
| | | gt: startIndex, |
| | | lte: endIndex, |
| | | color: 'red' |
| | | }, |
| | | { |
| | | gt: endIndex, |
| | | lte: dateList1.length - 1, |
| | | color: 'green' |
| | | } |
| | | ] |
| | | name: 'mg/m³', |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '油烟超标数据', |
| | | name: '油烟浓度', |
| | | type: 'line', |
| | | data: fumeExceeding1, |
| | | |
| | | // markArea: { |
| | | // itemStyle: { |
| | | // color: 'rgba(255, 173, 177, 0.4)' |
| | | // }, |
| | | // data: [ |
| | | // [ |
| | | // { |
| | | // name: '浓度超标', |
| | | // xAxis: dateList[0] |
| | | // }, |
| | | // { |
| | | // xAxis: dateList[dateList.length - 1] |
| | | // } |
| | | // ] |
| | | // ] |
| | | // }, |
| | | data: yData.map((item) => { |
| | | if (item >= 1) { |
| | | return { |
| | | value: item, |
| | | itemStyle: { |
| | | color: 'red' |
| | | } |
| | | }; |
| | | } |
| | | return item; |
| | | }), |
| | | // 变换指定时间区间的背景颜色 |
| | | markArea: { |
| | | itemStyle: { |
| | | color: 'rgba(255, 173, 177, 0.4)' |
| | | }, |
| | | data: [ |
| | | [ |
| | | { |
| | | name: '超标时间段', |
| | | xAxis: exceptionBeginTime, |
| | | }, |
| | | { |
| | | xAxis: exceptionEndTime, |
| | | } |
| | | ] |
| | | ] |
| | | }, |
| | | markLine: { |
| | | symbol: 'none', |
| | | itemStyle: { |
| | | // 基线公共样式 |
| | | normal: { |
| | | lineStyle: { |
| | | // show:false, |
| | | // 'solid'实线;'dashed'虚线;'dotted'点线 |
| | | type: 'dashed' |
| | | }, |
| | | label: { |
| | |
| | | }, |
| | | data: [ |
| | | { |
| | | name: '预警', |
| | | name: '超标', |
| | | type: 'average', |
| | | yAxis: 1, |
| | | lineStyle: { |
| | |
| | | ] |
| | | } |
| | | } |
| | | ], |
| | | // 指定时间区间的线段变颜色 |
| | | visualMap: { |
| | | show: false, |
| | | dimension: 0, |
| | | pieces: [ |
| | | { |
| | | lte: beginIndex, |
| | | color: 'green' |
| | | }, |
| | | { |
| | | gt: beginIndex, |
| | | lte: endIndex, |
| | | color: 'red' |
| | | }, |
| | | { |
| | | gt: endIndex, |
| | | lte: xData.length - 1, |
| | | color: 'green' |
| | | } |
| | | ] |
| | | }); |
| | | }, 500); |
| | | } |
| | | }; |
| | | } |
| | | // 供电异常和掉线 |
| | | else if (exceptionCategory == 1) { |
| | | this.option = { |
| | | tooltip: {}, |
| | | toolbox: { |
| | | // 工具栏 |
| | | feature: { |
| | | // dataZoom: { |
| | | // // 区域缩放 |
| | | // yAxisIndex: 'none' |
| | | // }, |
| | | // 保存为图片 |
| | | saveAsImage: {} |
| | | } |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: xData, |
| | | name: '时间', |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | return value.slice(11, -3); |
| | | } |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: 'mg/m³' |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '油烟数据', |
| | | type: 'line', |
| | | data: yData, |
| | | markLine: { |
| | | silent: true, |
| | | data: [ |
| | | // 标注无数据时间段的效果,将这个时间段的数轴部分变为红色 |
| | | { |
| | | name: '无数据', |
| | | xAxis: exceptionBeginTime |
| | | }, |
| | | { |
| | | xAxis: exceptionEndTime |
| | | } |
| | | ], |
| | | lineStyle: { |
| | | color: 'red' |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | } |
| | | }, |
| | | |
| | | |
| | | // 功能:点击 ‘查看详情’, ‘下一条’按钮时会 先逻辑计算。最后展示图形 |
| | | drawChartTest() { |
| | | this.beforeData = [] |
| | | this.afterData= [] |
| | | this.allExceptionTimeData = [] |
| | | //异常的开始时间 结束时间 |
| | | let exceptionBeginTime =this.rowBeginTime |
| | | let exceptionEndTime = this.rowEndTime |
| | | |
| | | // beforeAndAfterTime[0]:前30分钟的时间点 |
| | | // beforeAndAfterTime[1]:后10分钟的时间点 |
| | | // beforeAndAfterTime[2]:后40分钟的时间点 |
| | | let beforeAndAfterTime = this.before30AndAfter40( |
| | | exceptionBeginTime, |
| | | exceptionEndTime |
| | | ); |
| | | |
| | | // 构造异常时间前的区间数据请求参数 |
| | | let paramsBefore = this.requestGetParms( |
| | | this.displayData[this.selectedRowIndex].devId, |
| | | beforeAndAfterTime[0], |
| | | this.displayData[this.selectedRowIndex].beginTime |
| | | ); |
| | | |
| | | // 构造异常时间后的区间数据请求参数 |
| | | let paramsAfter = this.requestGetParms( |
| | | this.displayData[this.selectedRowIndex].devId, |
| | | beforeAndAfterTime[1], |
| | | beforeAndAfterTime[2] |
| | | ); |
| | | |
| | | // 请求前半段 |
| | | axiosInstanceInstance |
| | | .get('/fume/history', { params: paramsBefore }) |
| | | .then((result1) => { |
| | | this.beforeData = result1.data.data; |
| | | console.log('beforeData:',this.beforeData); |
| | | // 请求后半段 |
| | | axiosInstanceInstance |
| | | .get('/fume/history', { params: paramsAfter }) |
| | | .then((result2) => { |
| | | this.afterData = result2.data.data; |
| | | console.log('afterData:',this.afterData); |
| | | //保存异常区间的值 |
| | | let tempArr = []; |
| | | // 保存异常区间前后的值 |
| | | let before = []; |
| | | let after = []; |
| | | |
| | | // 判断是否是供电异常或掉线 |
| | | if ( |
| | | this.rowExceptionType === '1' || |
| | | this.rowExceptionType === '2' |
| | | ) { |
| | | // 重构表格 缺失异常数据自动填充 |
| | | this.setExceptionData(); |
| | | |
| | | //相差几个10分钟 |
| | | const TenMinuteNum = this.diffTenMinutesNum( |
| | | exceptionBeginTime, |
| | | exceptionEndTime |
| | | ); |
| | | //用null填充中异常无数据的时间 |
| | | for (let i = 0; i < TenMinuteNum; i++) { |
| | | tempArr.push(null); |
| | | } |
| | | before = this.shallowCopyList(this.beforeData); |
| | | |
| | | after = this.shallowCopyList(this.afterData); |
| | | // after = this.afterData |
| | | console.log('after:',after); |
| | | } |
| | | // 超标 |
| | | else { |
| | | let beforeTemp = this.removeLastItemOfBeforeData(this.beforeData) |
| | | // 前后区间只显示距离超标区间时间最近的浓度小于1的时间点 |
| | | for (let i = beforeTemp.length - 1; i >= 0; i--) { |
| | | if (beforeTemp[i].mvFumeConcentration2 >= 1) { |
| | | break; |
| | | } |
| | | if (beforeTemp[i].mvFumeConcentration2 < 1) { |
| | | before.unshift(this.beforeData[i]); |
| | | } |
| | | } |
| | | |
| | | for (let i = 0; i<this.afterData.length; i++) { |
| | | if (this.afterData[i].mvFumeConcentration2 >= 1) { |
| | | break; |
| | | } |
| | | if (this.afterData[i].mvFumeConcentration2 < 1) { |
| | | after.unshift(this.afterData[i]); |
| | | } |
| | | } |
| | | tempArr = this.shallowCopyList(this.exceedingData); |
| | | } |
| | | |
| | | // 将前后区间数据 与 异常区间数据 合并 |
| | | this.allExceptionTimeData = [...before, ...tempArr, ...after]; |
| | | console.log('组合数据:',this.allExceptionTimeData); |
| | | // x轴日期时间 |
| | | let dateList = []; |
| | | // y轴 超标油烟浓度 |
| | | let fumeExceeding = []; |
| | | let timeAndValue = {}; |
| | | |
| | | // 从添加了首位区间的开始和结束时间进行遍历 保证时间以10分钟为间隔 |
| | | timeAndValue = this.keepContinuousByEachTenMinutes( |
| | | beforeAndAfterTime[0], |
| | | beforeAndAfterTime[2], |
| | | this.allExceptionTimeData |
| | | ); |
| | | |
| | | dateList = timeAndValue['xAxis']; |
| | | fumeExceeding = timeAndValue['yAxis']; |
| | | |
| | | console.log('dateList:',dateList); |
| | | console.log('fumeExceeding:',fumeExceeding); |
| | | |
| | | // 提取异常起始时间点在整个区间内的数据索引 |
| | | let startIndex = dateList.findIndex( |
| | | (item) => item === exceptionBeginTime |
| | | ); |
| | | let endIndex = dateList.findIndex( |
| | | (item) => item === exceptionEndTime |
| | | ); |
| | | |
| | | // 供电异常和掉线情况 超标情况 |
| | | if ( |
| | | this.rowExceptionType === '1' || |
| | | this.rowExceptionType === '2' |
| | | ) { |
| | | this.setOption( |
| | | dateList, |
| | | fumeExceeding, |
| | | 1, |
| | | exceptionBeginTime, |
| | | exceptionEndTime, |
| | | startIndex, |
| | | endIndex |
| | | ); |
| | | } else { |
| | | // 超标情况 |
| | | this.setOption( |
| | | dateList, |
| | | fumeExceeding, |
| | | 0, |
| | | exceptionBeginTime, |
| | | exceptionEndTime, |
| | | startIndex, |
| | | endIndex |
| | | ); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | getDeviceInfo() { |
| | | // 级联下拉框数据 从接口中动态获取 |
| | | axiosInstanceInstance.get('/fume/device').then((result) => { |
| | |
| | | XLSX.utils.book_append_sheet(wb, xls, 'Sheet1'); |
| | | // 将workbook转为二进制xlsx文件并下载 |
| | | XLSX.writeFile(wb, '分析数据.xlsx'); |
| | | }, |
| | | |
| | | // 查询全部异常表数据 |
| | | getAllData() { |
| | | this.isNoData = false; |
| | | this.loading = true; |
| | | axiosInstanceInstance.get('/fume/abnormal').then((result) => { |
| | | this.abnormalData = result.data.data; |
| | | this.loading = false; |
| | | this.total = this.abnormalData.length; |
| | | if (result.data.data.length == 0) { |
| | | alert('该时段无数据'); |
| | | this.isNoData = true; |
| | | return; |
| | | } |
| | | this.isNoData = false; |
| | | // 默认显示第一页 |
| | | this.handleCurrentChange(1); |
| | | }); |
| | | |
| | | // 得到异常表的最早和最晚时间 |
| | | setTimeout(() => { |
| | | axiosInstanceInstance.get('/fume/time').then((result) => { |
| | | this.beginTime = result.data.data[0].beginTime; |
| | | this.endTime = result.data.data[0].endTime; |
| | | // console.log('be,end',this.beginTime,this.endTime); |
| | | }); |
| | | }, 500); |
| | | }, |
| | | |
| | | getAbnormalDataByClick(val) { |
| | |
| | | getRecentSevenDays() { |
| | | // 给级联选择器设置默认的选择项 |
| | | this.devId = ['付小姐在成都', 'qinshi_31010320210010']; |
| | | // 给时间选择器设置默认时间 |
| | | // this.beginTime = dayjs() |
| | | // .subtract(3, 'week') |
| | | // .format('YYYY-MM-DD HH:mm:ss'); |
| | | // this.endTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); |
| | | |
| | | // this.currentDateTime = dayjs().format('YYYY-MM-DD HH:mm:ss') |
| | | // this.oneWeekAgoDateTime = dayjs().subtract(1,'week').format('YYYY-MM-DD HH:mm:ss') |
| | | console.log(this.currentDateTime, this.oneWeekAgoDateTime); |
| | | let params = {}; |
| | | params['beginTime'] = this.beginTime; |
| | |
| | | .get('/fume/abnormalone', { params: params }) |
| | | .then((response) => { |
| | | if (response.data.data.length == 0) { |
| | | alert('该时段无数据'); |
| | | ElMessage('该时段无数据'); |
| | | return; |
| | | } |
| | | // 保存返回的 |
| | |
| | | this.loading = false; |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | .exception-root-container { |
| | | /* .exception-root-container { |
| | | margin: 20px; |
| | | padding: 10px; |
| | | border: 1px; |
| | | height: 615px; |
| | | /* min-height: 80vh; |
| | | min-width: 100vh; */ |
| | | } |
| | | |
| | | } */ |
| | | .header-container { |
| | | display: flex; |
| | | margin-left: 20px; |
| | | /* flex-wrap: wrap; |
| | | align-items: center; */ |
| | | } |
| | |
| | | color: var(--el-color-primary); |
| | | } |
| | | .collapse-header { |
| | | margin-left: 5px; |
| | | font-size: 18px; |
| | | } |
| | | .collapse-header-text { |
| | |
| | | .box-card-label { |
| | | font-size: 14px; |
| | | white-space: nowrap; |
| | | overflow-x: auto; |
| | | /* overflow-x: auto; */ |
| | | } |
| | | :deep().el-card { |
| | | border-radius: 9px; |
| | | |
| | | } |
| | | /* ‘查看详情’ 的弹出框高度调整 */ |
| | | :deep().el-dialog { |
| | |
| | | overflow-y: hidden; |
| | | border-radius: 9px; |
| | | } |
| | | .table-page { |
| | | margin-left: 20px; |
| | | } |
| | | :deep().table-page .el-card__body { |
| | | padding: 0px; |
| | | /* padding: 0px; */ |
| | | } |
| | | .table-text { |
| | | font-size: 18px; |
| | | margin-bottom: 10px; |
| | | margin: 5px 0px 10px 20px; |
| | | } |
| | | .text-blank { |
| | | margin-left: 10px; |
| | | margin-right: 10px; |
| | | } |
| | | /* 店铺名选择文本 */ |
| | | .describe-info { |
| | |
| | | font-weight: bold; |
| | | } |
| | | |
| | | |
| | | /* 异常表格下标签中的数组 */ |
| | | .table-line-num { |
| | | font-weight: bold; |
| | |
| | | .button_info.el-button_inner { |
| | | text-align: left; |
| | | } |
| | | .el-collapse { |
| | | margin-left: 20px; |
| | | } |
| | | :deep().el-collapse .el-collapse-item__content{ |
| | | padding-bottom: 0px; |
| | | } |
| | |
| | | height: 190px; |
| | | } |
| | | :deep().box-card .el-card__body { |
| | | padding: 5px; |
| | | /* padding: 5px; */ |
| | | } |
| | | .sub-box-card { |
| | | height: 100px; |
| | | overflow-y: auto; |
| | | border: 0px; |
| | | } |
| | | :deep().sub-box-card .el-card__body { |
| | | padding: 0px; |
| | | /* padding: 0px; */ |
| | | } |
| | | .mx-1 { |
| | | margin-bottom: 0px; |