Files
app-govern/pages/message1/comp/alarmDetails.vue
2026-06-01 20:36:04 +08:00

286 lines
9.0 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
<Cn-page :loading="loading">
<view class="detail" slot="body">
<view class="detail-content" style="font-size: 32rpx">
<!-- <view class="detail-content-title mb20">发生时间</view> -->
<view>{{ detail.date }}</view>
</view>
<view class="detail-content" style="padding-top: 0px;padding-bottom: 0px">
<view class="detail-content-title pb20 pt20 pl20">终端告警列表</view>
</view>
<view class="event-list">
<uni-card class="event-item" :class="item.type" v-for="(item, index) in list" :key="index">
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon"
:class="item.devType == 'Direct_Connected_Device' ? 'zl-bgc' : 'jc-bgc'">
<Cn-icon-transient :name="item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备'" />
<view class="badge1" v-if="item.status == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.devName }}</text>
<text class="event-tag"
:class="item.devType == 'Direct_Connected_Device' ? 'zl-tag' : 'jc-tag'">{{
item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}</text>
</view>
<view class="event-desc">
<text>工程{{ item.engineeringName }}</text>
<text>项目{{ item.projectName }}</text>
<!-- <text v-if="item.dataDetails.onlineRate.isAbnormal">在线率{{
item.dataDetails.onlineRate.value }}% 限值{{ item.dataDetails.onlineRate.threshold
}}% </text> -->
<!-- <text>事件时间{{ item.startTime }}</text> -->
</view>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<view v-if="item.dataDetails.onlineRate.isAbnormal">
<text>在线率
<text class="integrity-value">{{ item.dataDetails.onlineRate.value }}%</text> 
</text>
</view>
<view v-if="hasIntegrityAbnormal(item)" class="mt10">
数据完整性
<view class="integrity-grid">
<view
v-for="(rowItems, rowIdx) in chunkedPoints(getAbnormalPoints(item))"
:key="rowIdx"
class="grid-row">
<view
v-for="(point, pIdx) in rowItems"
:key="pIdx"
class="param-group">
<view class="param-title">
<text>{{ point.monitorName }}</text>
</view>
<view class="integrity-value-row">
<text class="integrity-value">{{ point.value }}%</text>
</view>
</view>
</view>
</view>
</view>
<view v-if="item.warnCounts" class="mt10 ">
终端告警 {{ item.warnCounts }} 详情如下
<view class="textBox mt10">
<view v-for="val in item.warnDetails" class="textBox mb5" style=" font-size: 26rpx;">
{{ val.warnEventTime + '发生' + val.warnEventDesc }}
</view>
</view>
</view>
</view>
</uni-card>
</view>
</view>
</Cn-page>
</template>
<script>
import { updateStatus, queryAlarmDetail } from '@/common/api/message'
export default {
data() {
return {
loading: true,
detail: {},
limit: '',
collapseValue: '0',
list: [],
}
},
onLoad(options) {
this.loading = true
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.init()
if (this.detail.isRead != 1) {
updateStatus({
eventIds: [this.detail.eventId],
})
}
},
methods: {
hasIntegrityAbnormal(item) {
const points = item?.dataDetails?.integrity?.monitorPoints
if (!Array.isArray(points) || !points.length) return false
return points.some((p) => p.isAbnormal === true)
},
getAbnormalPoints(item) {
return item?.dataDetails?.integrity?.monitorPoints?.filter((p) => p.isAbnormal === true) || []
},
chunkedPoints(points) {
const result = []
for (let i = 0; i < points.length; i += 3) {
result.push(points.slice(i, i + 3))
}
return result
},
init() {
queryAlarmDetail({
devList: this.detail.devIds,
time: this.detail.date,
})
.then((res) => {
this.list = res.data
this.loading = false
})
.catch(() => {
this.loading = false
})
},
},
}
</script>
<style lang="scss" scoped>
@import '../index.scss';
.detail {
padding: 20rpx 0;
.detail-content {
padding: 20rpx;
background: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
.detail-content-title {
display: inline-flex;
align-items: center;
position: relative;
padding-left: 20rpx;
font-size: 30rpx;
color: #111;
font-weight: 700;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 8rpx;
height: 28rpx;
background: $uni-theme-color;
border-radius: 3rpx;
}
}
}
.collapseTop {
padding: 10rpx 0;
margin-left: 15px;
.name {
font-size: 28rpx;
font-weight: 700;
color: #333333;
}
}
.frequency {
display: flex;
font-size: 28rpx;
// color: #666666;
}
}
.textBox {
// border-bottom: 1px solid #eee;
font-size: 28rpx;
color: #666666;
text-indent: 2em;
}
.event-list {
// background: #fff;
padding-bottom: 10rpx;
// .event-icon {
// background-color: #376cf320;
// }
.zl-bgc {
background-color: #376cf320;
}
.jc-bgc {
background-color: #376cf320;
}
.zl-tag {
background-color: #007aff20;
color: #007aff;
}
.jc-tag {
background-color: #007aff20;
color: #007aff;
}
}
/deep/ .uni-collapse-item__title-box {
padding: 0 15px 0 0;
height: 56rpx;
line-height: 56rpx;
font-size: 26rpx !important;
color: #666666;
span {
font-size: 26rpx !important;
}
}
.textBox {
max-height: 150rpx;
overflow-y: auto;
}
.integrity-grid {
margin-top: 16rpx;
}
.grid-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16rpx;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
}
.param-group {
min-width: 0;
background: #f3f3f3;
border-radius: 16rpx;
padding: 16rpx 8rpx 12rpx;
text-align: center;
}
.param-title {
font-size: 24rpx;
color: #666666;
// margin-bottom: 8rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.integrity-value-row {
display: flex;
justify-content: center;
align-items: center;
padding: 2rpx;
}
.integrity-value {
font-size: 26rpx;
font-weight: 700;
color: #333333;
}
</style>