gangkou/ruoyi-ui/src/views/dataAnalysis/bound/index.vue

382 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-row :gutter="10">
<el-col :span="6">
<dept-tree @deptChange="handleDeptChange" :showQuickGroup="true" />
</el-col>
<el-col :span="6">
<el-date-picker
v-model="dateList"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
:picker-options="pickerOptions"
@change="dateChange"
>
</el-date-picker>
</el-col>
<el-col :span="6">
<device-select
v-model="queryDeviceSn"
:deptId="dept ? dept.deptId : ''"
placeholder="请选择设备"
@change="handleDeviceSelectChange"
/>
</el-col>
</el-row>
<div style="display: flex; height: 700px; margin-top: 10px;">
<div style="width: 50%; background: #e0e1e2; padding: 10px">
<div class="title">厂界在线监测设备报警情况分析</div>
<div style="width: 100%; height: 650px" ref="qdCityMap1"></div>
</div>
<div style="width: 50%; background: #e0e1e2; padding: 10px">
结合{{days}}天的数据分析,报警最多的监测设备列表如下,请在未来加强管控!
<el-table v-loading="loading" :data="alarmCountDesc" max-height="650">
<el-table-column label="企业名称" align="center" prop="p" />
<el-table-column label="设备编号" align="center" prop="sn" />
<el-table-column label="放置区域" align="center" prop="address" />
<el-table-column label="报警次数" align="center" prop="count">
<template slot-scope="scope">
<el-tag type="danger" class="count-tag" @click="clickAlarmTag(scope.row)">{{ scope.row.count }}</el-tag>
</template>
</el-table-column>
<el-table-column
v-if="checkRole(['admin', 'notice'])"
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>下发通知</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-dialog title="报警管理" :visible.sync="dialogAlarmVisible">
<alarm-monitor :queryParamsName="queryParamsName" :queryParamsDate="queryParamsDate"/>
</el-dialog>
<!--发送通知-->
<send-msg
:deviceInfo="deviceInfo"
v-if="isOpenMsg"
:isOpenMsg="isOpenMsg"
@closeMsg="closeMsg"
></send-msg>
</div>
</template>
<script>
import { queryAlarmChart } from "@/api/demostrate/monitor";
import { queryMonitorPrediction } from "@/api/demostrate/monitor";
import sendMsg from "@/views/demostrate/alarm/sendMsg.vue";
import DeviceSelect from '@/components/DeviceSelect/index.vue';
const echarts = require("echarts");
import { factoryBoundaryOnline } from "@/api/analysis"
import to from '@/utils/await-to.js';
import moment from 'moment';
import { debounce } from '@/utils';
import { checkRole } from "@/utils/permission";
import AlarmMonitor from '@/views/alarmMonitor/bound/index.vue';
export default {
name: "alarm",
components: { sendMsg, DeviceSelect, AlarmMonitor },
dicts: [],
data() {
return {
dept: null,
queryDebounce: null,
alarmCount: [],
alarmCountDesc: [],
days: 0,
loading: false,
pickerOptions: {
// disabledDate(time) {
// // 计算选择的时间跨度
// const diff = Math.abs(time.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24);
// // 如果时间跨度超过30天则禁用该日期
// return diff > 30;
// },
shortcuts: [
{
text: "最近30天",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setDate(start.getDate() - 29); // 30天前
picker.$emit("pick", [start, end]);
},
},
],
},
dateList: [], //日期
total: 0,
isOpenMsg: false,
deviceInfo: {},
queryDeviceSn: "",
// 查询参数
queryParams: {
deptId: null,
beginDate: null,
endDate: null,
deviceSn: null,
},
dialogAlarmVisible: false,
queryParamsName: null,
queryParamsDate: null,
};
},
mounted() {
this.queryDebounce = debounce(this.query, 100);
setTimeout(() => {
let dsiab_com = this.$refs.qdCityMap1;
dsiab_com.removeAttribute("_echarts_instance_");
this.getDefaultDateRange();
});
},
watch: {
dateList: {
handler: function () {
// 计算选择的时间天数
const diff = Math.abs(
new Date(this.dateList[1]).getTime() -
new Date(this.dateList[0]).getTime()
);
this.days = diff / (1000 * 60 * 60 * 24);
},
deep: true,
},
},
methods: {
checkRole,
clickAlarmTag(row) {
this.dialogAlarmVisible = true;
this.queryParamsName = row.name;
// 日期加上00:00:00
this.queryParamsDate = [
moment(this.dateList[0]).format("YYYY-MM-DD 00:00:00"),
moment(this.dateList[1]).format("YYYY-MM-DD 23:59:59"),
];
},
dateChange() {
this.queryDebounce();
},
handleDeptChange(dept) {
this.dept = dept;
this.queryDeviceSn = "";
this.queryDebounce();
},
async query() {
if (this.dept && this.dateList.length > 0) {
this.queryParams.deptId = this.dept.deptId;
this.queryParams.beginDate = this.dateList[0];
this.queryParams.endDate = this.dateList[1];
this.queryParams.deviceSn = this.queryDeviceSn || '';
const [err, res] = await to(factoryBoundaryOnline(this.queryParams));
if (err) {
console.error(err);
this.$message.error("查询失败");
return;
}
if (res.code !== 200) {
this.$message.error(res.msg);
return;
}
this.alarmCount = res.data.alarmCount;
this.alarmCountDesc = res.data.alarmCountDesc;
this.queryChart();
}
},
//发送通知
handleUpdate(row) {
this.deviceInfo = row;
this.isOpenMsg = true;
},
queryChart() {
const xData = [];
const yData1 = [];
const yData2 = [];
const yData3 = [];
this.alarmCount.forEach((item) => {
xData.push(item.day);
yData1.push(item.alarmCount);
yData3.push(((item.alarmCount / item.count) * 100).toFixed(2));
});
this.init(xData, yData1, yData2, yData3);
},
getDefaultDateRange() {
const endDate = new Date(); // 当前时间
const startDate = new Date();
startDate.setDate(startDate.getDate() - 7); // 当前时间之前的7天
// 格式化为YYYY-MM-DD
this.dateList = [
moment(startDate).format("YYYY-MM-DD"),
moment(endDate).format("YYYY-MM-DD"),
];
this.queryChart();
},
init(xData, yData1, yData2, yData3) {
const yData2GradientColor = [
{
offset: 0,
color: "#0058e1",
},
{
offset: 1,
color: "#3BA1E3",
},
];
const yData3GradientColor = [
{
offset: 0,
color: "#32E8D4",
},
{
offset: 1,
color: "#4BA1E3",
},
];
const option = {
tooltip: {
trigger: "axis", // x轴触发
formatter: function (params) {
let list = [];
let listItem = "";
params.forEach((item) => {
// 柱状图加单位 局,折线图加单位 %
let unitValue =
item.seriesType == "bar" ? item.value + "个" : item.value + "%";
list.push(item.marker + "" + item.seriesName + ": " + unitValue);
});
listItem = list.join("<br/>");
return "<div>" + listItem + "</div>";
},
},
legend: {
orient: "horizontal", // 水平排列
x: "center", //可设定图例在左、右、居中
y: "top", //可设定图例在上、下、居中
padding: 6, //位置也可为数组 [距上方距离,距右方距离,距下方距离,距左方距离]
},
xAxis: {
type: "category",
data: xData,
},
yAxis: [
{
type: "value",
name: "报警数",
yAxisIndex: 0,
axisLabel: {
//y轴每个刻度都加单位
formatter: "{value}个",
},
},
{
type: "value",
name: "报警率(%)",
min: 0, // 最小为0
max: 100, // 最大为100
interval: 25, // 间隔25
axisLabel: {
//y轴每个刻度都加单位
formatter: "{value}%",
},
},
],
series: [
{
type: "bar",
stack: "x",
name: "报警数",
data: yData1,
label: {
show: true,
color: "#eee",
},
barGap: "-100%", // 平移自身一个身位,使之与前一个柱状图重叠
// stack:'重叠',
itemStyle: {
// borderRadius: [20, 20, 6, 6],
color: "#15C1AF",
},
},
// {
// type: 'bar',
// stack: 'x',
// name: "二级报警数",
// data: yData2,
// label: {
// show: true,
// color: '#eee'
// },
// barGap: "-100%", // 平移自身一个身位,使之与前一个柱状图重叠
// // stack:'重叠',
// itemStyle: {
// // borderRadius: [20, 20, 6, 6],
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, yData3GradientColor),
// }
// },
{
type: "line",
name: "报警率(%)",
data: yData3,
yAxisIndex: 1, // 1表示以右侧Y轴为基准 0表示以左侧Y轴为基准
symbolSize: 10, // 圆点大小
// itemStyle: {
// color: '#74DER1', // 折线图小圆点颜色
// },
lineStyle: {
color: "#DE390F",
},
label: {
show: true,
color: "#ddd",
formatter: "{c}%", // {c}数据值
},
},
],
};
this.myChart = echarts.init(this.$refs.qdCityMap1);
this.myChart.setOption(option);
},
handleDeviceSelectChange() {
this.queryDebounce();
},
},
};
</script>
<style>
.title {
padding-left: 10px;
color: #212121;
font-size: 20px;
margin-bottom: 10px;
margin-top: 10px;
background-position-y: 7px;
}
.count-tag {
cursor: pointer;
}
</style>