444 lines
12 KiB
Vue
444 lines
12 KiB
Vue
<template>
|
||
<div class="bigdata-alarm-info">
|
||
<BCard title="报警信息" @edit="handleEdit" style="height: 100%">
|
||
<div class="info-content" :style="{ maxHeight: contentMaxHeight }">
|
||
<a-scrollbar :maxHeight="contentMaxHeight">
|
||
<div class="info-list">
|
||
<div class="info-list-item" v-for="item in alarmInfo" :key="item.title">
|
||
<div class="info-list-item-title">
|
||
{{ item.title }}
|
||
</div>
|
||
<div class="info-list-item-content">
|
||
<div class="info-list-item-text">
|
||
<span class="value">{{ item.value }}</span>
|
||
<span class="label">设备数量</span>
|
||
</div>
|
||
<div class="info-list-item-text">
|
||
<span class="value">{{ item.num }}</span>
|
||
<span class="label">离线</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="alarm-list">
|
||
<div
|
||
class="alarm-list-item"
|
||
v-for="item in alarmTabList"
|
||
:key="item.name"
|
||
:class="{ active: item.value === alarmTabValue }"
|
||
@click="handleAlarmTabClick(item.value)"
|
||
>
|
||
{{ item.name }}({{ item.num }})
|
||
</div>
|
||
</div>
|
||
<a-table
|
||
v-if="alarmTabValue === 1"
|
||
size="small"
|
||
:dataSource="alarmInfoList"
|
||
:columns="columns"
|
||
rowKey="id"
|
||
:pagination="false"
|
||
:showSorterTooltip="false"
|
||
>
|
||
<template #bodyCell="{ column, record }">
|
||
<span v-if="column.dataIndex === 'type'" :style="record[column.dataIndex] === 1 ? { color: '#EDA200' } : { color: '#ff0000' }">
|
||
{{ record[column.dataIndex] === 1 ? '预警' : '报警' }}
|
||
</span>
|
||
</template>
|
||
</a-table>
|
||
|
||
<a-table
|
||
v-if="alarmTabValue === 2"
|
||
size="small"
|
||
:dataSource="eventAlarmInfoList"
|
||
:columns="eventColumns"
|
||
rowKey="id"
|
||
:pagination="false"
|
||
:showSorterTooltip="false"
|
||
>
|
||
<template #bodyCell="{ column, record, text }">
|
||
<template v-if="column.dataIndex === 'state'">
|
||
<a-tag :bordered="false" :color="stateMap[text].color">{{ stateMap[text].label }}</a-tag>
|
||
</template>
|
||
<template v-if="column.dataIndex === 'image'">
|
||
<template v-if="JSON.parse(record.image).length > 0">
|
||
<a-image :width="40" :src="JSON.parse(record.image)[0].fileUrl" />
|
||
</template>
|
||
<template v-else>
|
||
<span>无</span>
|
||
</template>
|
||
</template>
|
||
</template>
|
||
</a-table>
|
||
|
||
<a-table
|
||
v-if="alarmTabValue === 3"
|
||
size="small"
|
||
:dataSource="aiAlarmInfoList"
|
||
:columns="aiColumns"
|
||
rowKey="id"
|
||
:pagination="false"
|
||
:showSorterTooltip="false"
|
||
>
|
||
<template #bodyCell="{ column, record }">
|
||
<span v-if="column.dataIndex === 'imageUrl'">
|
||
<a-image :src="record[column.dataIndex]" :width="40" :height="24" />
|
||
</span>
|
||
</template>
|
||
</a-table>
|
||
</a-scrollbar>
|
||
</div>
|
||
</BCard>
|
||
<AlarmInfoDialog ref="alarmInfoDialogRef" @refresh="queryConfigPage" />
|
||
</div>
|
||
</template>
|
||
<script setup>
|
||
import BCard from './b-card.vue';
|
||
import AlarmInfoDialog from './alarm-info-dialog.vue';
|
||
import { ref, onMounted, nextTick, watch } from 'vue';
|
||
import { bigdataApi } from '/@/api/business/bigdata/bigdata-api';
|
||
import { monitorApi } from '/@/api/business/monitor/monitor-api';
|
||
import { eventApi } from '/@/api/business/event/event-api';
|
||
import { weatherStationApi } from '/@/api/business/weather-station/weather-station-api';
|
||
import { useUserStore } from '/@/store/modules/system/user';
|
||
|
||
watch(
|
||
() => useUserStore().getCurrentVillageId,
|
||
(value) => {
|
||
getTableList();
|
||
queryConfigPage();
|
||
},
|
||
);
|
||
|
||
const alarmInfo = ref([]);
|
||
const alarmInfoList = ref([]);
|
||
const aiAlarmInfoList = ref([]);
|
||
const eventAlarmInfoList = ref([]);
|
||
const alarmInfoDialogRef = ref();
|
||
const contentMaxHeight = ref(0);
|
||
const isEdit = ref(false);
|
||
const isCustom = ref(false);
|
||
const alarmInfoData = ref({});
|
||
|
||
const alarmTabList = ref([
|
||
{
|
||
name: '设备预警',
|
||
value: 1,
|
||
num: 0,
|
||
},
|
||
{
|
||
name: '事件预警',
|
||
value: 2,
|
||
num: 0,
|
||
},
|
||
{
|
||
name: 'AI预警',
|
||
value: 3,
|
||
num: 0,
|
||
},
|
||
]);
|
||
const alarmTabValue = ref(1);
|
||
|
||
const columns = ref([
|
||
{
|
||
title: '名称',
|
||
dataIndex: 'deviceName',
|
||
},
|
||
{
|
||
title: '报警类型',
|
||
dataIndex: 'type',
|
||
},
|
||
{
|
||
title: '报警项',
|
||
dataIndex: 'alarmTypeName',
|
||
},
|
||
{
|
||
title: '报警值',
|
||
dataIndex: 'alarmValue',
|
||
},
|
||
{
|
||
title: '阈值',
|
||
dataIndex: 'exceed',
|
||
},
|
||
{
|
||
title: '推送人',
|
||
dataIndex: 'pushUser',
|
||
},
|
||
]);
|
||
|
||
const aiColumns = ref([
|
||
{
|
||
title: '名称',
|
||
dataIndex: 'hardwareName',
|
||
},
|
||
{
|
||
title: '编号',
|
||
dataIndex: 'hardwareId',
|
||
ellipsis: true,
|
||
},
|
||
{
|
||
title: '预警类型',
|
||
dataIndex: 'alarmTypeName',
|
||
},
|
||
{
|
||
title: '图片',
|
||
dataIndex: 'imageUrl',
|
||
},
|
||
]);
|
||
|
||
const eventColumns = ref([
|
||
{
|
||
title: '事件名称',
|
||
dataIndex: 'eventDesc',
|
||
},
|
||
{
|
||
title: '图片',
|
||
dataIndex: 'image',
|
||
},
|
||
{
|
||
title: '上报人',
|
||
dataIndex: 'createByName',
|
||
},
|
||
{
|
||
title: '处理人',
|
||
dataIndex: 'solveUserName',
|
||
},
|
||
{
|
||
title: '状态',
|
||
dataIndex: 'state',
|
||
},
|
||
]);
|
||
|
||
// 状态(0:已发起待处理;1:已处理;2:已驳回)
|
||
const stateMap = [
|
||
{
|
||
label: '待处理',
|
||
value: 0,
|
||
color: 'blue',
|
||
},
|
||
{
|
||
label: '待审核',
|
||
value: 1,
|
||
color: 'orange',
|
||
},
|
||
{
|
||
label: '驳回',
|
||
value: 2,
|
||
color: 'red',
|
||
},
|
||
{
|
||
label: '通过',
|
||
value: 3,
|
||
color: 'green',
|
||
},
|
||
];
|
||
|
||
const getAlarmInfo = async () => {
|
||
const res = await bigdataApi.getDeviceOnline();
|
||
const { environmentOffLine, environmentTotal, insectPestSituationOffLine, insectPestSituationTotal, videoOffLine, videoTotal } = res.data;
|
||
alarmInfo.value = [
|
||
{
|
||
title: '监控摄像',
|
||
value: videoTotal,
|
||
num: videoOffLine,
|
||
},
|
||
{
|
||
title: '虫情灯',
|
||
value: insectPestSituationTotal,
|
||
num: insectPestSituationOffLine,
|
||
},
|
||
{
|
||
title: '气象站',
|
||
value: environmentTotal,
|
||
num: environmentOffLine,
|
||
},
|
||
];
|
||
};
|
||
|
||
const queryConfigPage = async () => {
|
||
const res = await bigdataApi.queryLargeScreenConfigPage({
|
||
configKey: 'alarmInfo',
|
||
pageNum: 1,
|
||
pageSize: 1,
|
||
});
|
||
isEdit.value = res.data.list.length > 0 ? true : false;
|
||
if (res.ok && res.data.list.length > 0) {
|
||
alarmInfoData.value = res.data.list[0];
|
||
const { configValue } = alarmInfoData.value;
|
||
const { isCustom: isCustom1, list } = JSON.parse(configValue);
|
||
isCustom.value = isCustom1;
|
||
if (isCustom.value) {
|
||
alarmInfo.value = list;
|
||
} else {
|
||
await getAlarmInfo();
|
||
}
|
||
} else {
|
||
await getAlarmInfo();
|
||
}
|
||
};
|
||
|
||
const getTableList = async () => {
|
||
// 设备预警
|
||
const deviceListRes = await weatherStationApi.queryAlarmWarningPage({ pageNum: 1, pageSize: 500 });
|
||
const deviceList = deviceListRes.data.list || [];
|
||
alarmTabList.value[0].num = deviceListRes.data.total;
|
||
alarmInfoList.value = deviceList;
|
||
// AI预警
|
||
const aiListRes = await monitorApi.queryAiAlarmRecordPage({ pageNum: 1, pageSize: 500 });
|
||
const aiList = aiListRes.data.list || [];
|
||
alarmTabList.value[2].num = aiListRes.data.total;
|
||
aiAlarmInfoList.value = aiList;
|
||
|
||
// 事件预警
|
||
const eventListRes = await eventApi.queryPage({ pageNum: 1, pageSize: 500 });
|
||
const eventList = eventListRes.data.list || [];
|
||
alarmTabList.value[1].num = eventListRes.data.total;
|
||
eventAlarmInfoList.value = eventList;
|
||
};
|
||
|
||
const handleAlarmTabClick = (value) => {
|
||
alarmTabValue.value = value;
|
||
};
|
||
|
||
const initHeight = () => {
|
||
let height = document.querySelector('.bigdata-right').clientHeight;
|
||
let height1 = document.querySelector('.bigdata-right-1').clientHeight;
|
||
let height3 = document.querySelector('.bigdata-right-3').clientHeight;
|
||
let otherHeight = 76;
|
||
let gapHeight = 40;
|
||
contentMaxHeight.value = `${height - otherHeight - gapHeight - height1 - height3}px`;
|
||
};
|
||
|
||
onMounted(async () => {
|
||
await getTableList();
|
||
await queryConfigPage();
|
||
initHeight();
|
||
|
||
window.addEventListener('resize', initHeight);
|
||
});
|
||
const handleEdit = () => {
|
||
alarmInfoDialogRef.value.showModal(isEdit.value ? alarmInfoData.value : null);
|
||
};
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.bigdata-alarm-info {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 100%;
|
||
// overflow: hidden;
|
||
.info-content {
|
||
width: 100%;
|
||
height: 100%;
|
||
.info-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 14px;
|
||
position: relative;
|
||
.info-list-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
// align-items: center;
|
||
// justify-content: space-between;
|
||
width: calc(33.33% - 9.33px);
|
||
height: 86px;
|
||
gap: 6px;
|
||
background-image: url('/@/assets/images/bigdata/alarm-bg.png');
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
// padding: 10px;
|
||
.info-list-item-title {
|
||
padding: 8px 28px;
|
||
font-family:
|
||
Alibaba PuHuiTi,
|
||
Alibaba PuHuiTi;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
color: #ffffff;
|
||
line-height: 20px;
|
||
}
|
||
.info-list-item-content {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 100%;
|
||
gap: 12px;
|
||
.info-list-item-text {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
.label {
|
||
font-weight: 500;
|
||
font-size: 14px;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
line-height: 18px;
|
||
}
|
||
.value {
|
||
font-family:
|
||
PingFang SC,
|
||
PingFang SC;
|
||
font-weight: 800;
|
||
font-size: 18px;
|
||
color: #ffffff;
|
||
line-height: 22px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
:deep(.ant-table) {
|
||
background: transparent;
|
||
color: #fff;
|
||
border: none;
|
||
|
||
.ant-table-thead > tr > th {
|
||
background: transparent;
|
||
color: #fff;
|
||
border: none;
|
||
|
||
&::before {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.ant-table-tbody > tr {
|
||
background: rgba(124, 222, 135, 0.05);
|
||
|
||
& > td {
|
||
background: transparent;
|
||
color: #fff;
|
||
border: none;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.alarm-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 20px;
|
||
margin: 10px;
|
||
.alarm-list-item {
|
||
font-family:
|
||
PingFang SC,
|
||
PingFang SC;
|
||
font-weight: 500;
|
||
font-size: 12px;
|
||
height: 20px;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
background: linear-gradient(360deg, #19926c 0%, rgba(25, 146, 108, 0) 100%);
|
||
border-radius: 20px;
|
||
padding: 0px 10px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
&.active {
|
||
background: linear-gradient(360deg, #4fe87d 0%, rgba(80, 237, 114, 0) 100%);
|
||
}
|
||
}
|
||
}
|
||
</style>
|