fix(APP功能调整): 文档中的第7、8、10没有做;第4点需要再核查下ITIC、F47曲线中的可容忍事件、不可容忍事件的显示是否正确。

This commit is contained in:
dk
2026-05-15 11:16:00 +08:00
parent eb72146e0d
commit 17e47c1f07
17 changed files with 1800 additions and 1664 deletions

View File

@@ -37,21 +37,22 @@
{{ device.equipmentName }}
</text>
<text class="uni-card__header-content-subtitle uni-ellipsis">
{{ device.mac }}
<!-- {{ device.mac }}-->
</text>
<view class="tagBox">
<text class="event-tag" :class="device.runStatus == 1 ? 'lx-tag' : 'zx-tag'">{{
device.runStatus == 1 ? '离线' : '在线'
}}</text>
<text class="event-tag" :class="device.runStatus == 1 ? 'lx-tag' : 'zx-tag'">
{{ device.runStatus == 1 ? '离线' : '在线' }}
</text>
<text
class="event-tag"
:class="device.devType == 'Direct_Connected_Device' ? 'zl-tag' : 'jc-tag'"
>
{{ device.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}
</text>
<text class="event-tag" :class="device.isPrimaryUser == 1 ? 'z-tag' : 'fx-tag'">{{
device.isPrimaryUser == 1 ? '设备' : '分享设备'
}}</text></view
<text class="event-tag" :class="device.isPrimaryUser == 1 ? 'z-tag' : 'fx-tag'">
{{ device.isPrimaryUser == 1 ? '我的设备' : '他人设备' }}
</text>
</view
>
</view>
</view>
@@ -76,7 +77,7 @@
<text>{{ device.process == 2 ? '功能调试' : '出厂调试' }}</text>
</view>
</view>
<view class="pinToTop" v-if="device.isTop == 1"> 置顶 </view>
<view class="pinToTop" v-if="device.isTop == 1"> 置顶</view>
</uni-card>
</template>
<script>
@@ -87,7 +88,8 @@ export default {
props: {
device: {
type: Object,
default: () => {},
default: () => {
},
},
},
methods: {
@@ -152,6 +154,7 @@ export default {
line-height: 1.2;
}
}
.uni-card {
/deep/ .uni-card__header-box {
display: flex;
@@ -160,6 +163,7 @@ export default {
align-items: center;
overflow: hidden;
}
/deep/ .uni-card__header {
display: flex;
border-bottom: 2rpx #ebeef5 solid;
@@ -169,16 +173,20 @@ export default {
overflow: hidden;
}
}
.uni-card .uni-card__header .uni-card__header-content .uni-card__header-content-title {
font-size: 30rpx;
color: #3a3a3a;
font-weight: 700;
}
.uni-card .uni-card__header .uni-card__header-content .uni-card__header-content-subtitle {
margin-top: 15rpx;
font-size: 24rpx;
// margin-top: 5px;
color: #666666;
}
.uni-card .uni-card__header .uni-card__header-avatar .uni-card__header-avatar-image {
width: 40px;
height: 40px;
@@ -186,6 +194,7 @@ export default {
border-radius: 5px;
margin-right: 10px;
}
.uni-card .uni-card__header .uni-card__header-content {
display: flex;
flex-direction: column;
@@ -193,10 +202,12 @@ export default {
flex: 1;
overflow: hidden;
}
.tagBox {
display: flex;
gap: 15rpx;
}
.event-icon {
position: relative;
width: 100rpx;
@@ -207,6 +218,7 @@ export default {
align-items: center;
margin-right: 20rpx;
}
.event-tag {
font-size: 22rpx;
padding: 2rpx 10rpx;
@@ -220,28 +232,34 @@ export default {
background-color: #10b98120;
color: #10b981;
}
.lx-tag {
background-color: #ff3b3020;
color: #ff3b30;
}
.z-tag {
background-color: #2563eb20;
color: #2563eb;
}
.fx-tag {
background-color: #90939920;
color: #909399;
}
.zl-tag {
// background-color: #007aff20;
// color: #007aff;
background-color: #007aff20;
color: #007aff;
}
.jc-tag {
background-color: #007aff20;
color: #007aff;
}
.pinToTop {
background-color: $uni-theme-color;
width: 100rpx;

View File

@@ -588,7 +588,7 @@ export default {
})
}
}
if (this.userInfo.authorities !== 'tourist') {
if (this.userInfo.authorities !== 'tourist' && this.device.isPrimaryUser === '1') {
this.content.splice(0, 0, {
iconPath: '/static/subordinate.png',
text: '用户',

View File

@@ -4,7 +4,7 @@
<view class="device">
<view class="nav" :style="{ top: navTabHeight + 'px' }">
<view class="nav-menu" @click="selectEngineering"
>{{
>{{
select.engineeringName
? select.engineeringName.length > 6
? select.engineeringName.substring(0, 6) + '...'
@@ -35,12 +35,12 @@
</picker>
<picker
@change="runStatusChange"
:value="select.runStatusIndex"
:range="projectType"
range-key="text"
>
<view class="nav-menu" >
<view class="nav-menu">
{{
select.runStatusName
? select.runStatusName.length > 12
@@ -67,13 +67,13 @@
v-if="
userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user'
"
>移交
>移交
</view>
<view
class="nav-menu nav-menu-btn"
@click="selectDevice('share')"
v-if="userInfo.authorities === 'app_vip_user'"
>分享
>分享
</view>
</template>
</view>
@@ -89,7 +89,6 @@
<Cn-device-card :device="item" :key="index">
<template v-slot:title>
<!-- 卡片标题 -->
<switch
v-if="transfer || share"
:checked="checkList.indexOf(item.equipmentId) > -1"
@@ -97,8 +96,7 @@
@change="switchChange(item)"
/>
<view class="star-icon" v-else>
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
<uni-icons type="search" size="25" color="#376cf3"></uni-icons>
</view>
</template>
</Cn-device-card>
@@ -119,6 +117,7 @@ import { getProjectList } from '@/common/api/project'
import { queryDictData } from '@/common/api/dictionary'
import list from '@/common/js/list'
import { engineeringPinToTop } from '@/common/api/device'
export default {
mixins: [list],
data() {
@@ -458,15 +457,7 @@ export default {
} else {
this[type] = true
}
},
switchChange(e) {
let index = this.checkList.indexOf(e.equipmentId)
if (index > -1) {
this.checkList.splice(index, 1)
} else {
this.checkList.push(e.equipmentId)
}
},
}
},
}
</script>

View File

@@ -238,7 +238,7 @@ export default {
})
}
}
if (this.userInfo.authorities !== 'tourist') {
if (this.userInfo.authorities !== 'tourist' && this.device.isPrimaryUser === '1') {
this.content.splice(0, 0, {
iconPath: '/static/subordinate.png',
text: '用户',

View File

@@ -44,13 +44,13 @@
class="nav-menu nav-menu-btn"
@click="selectDevice('transfer')"
v-if="userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user'"
>移交
>移交
</view>
<view
class="nav-menu nav-menu-btn"
@click="selectDevice('share')"
v-if="userInfo.authorities === 'app_vip_user'"
>分享
>分享
</view>
</template>
<!-- <picker @change="projectTypeChange" :value="select.projectTypeIndex" :range="projectType" range-key="text">
@@ -70,7 +70,6 @@
<Cn-device-card :device="item" :key="index">
<template v-slot:title>
<!-- 卡片标题 -->
<switch
v-if="transfer || share"
:checked="checkList.indexOf(item.equipmentId) > -1"
@@ -78,8 +77,7 @@
@change="switchChange(item)"
/>
<view class="star-icon" v-else>
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
<uni-icons type="search" size="25" color="#376cf3"></uni-icons>
</view>
</template>
</Cn-device-card>
@@ -97,6 +95,7 @@
import { getProjectList } from '@/common/api/project'
import { queryDictData } from '@/common/api/dictionary'
import { engineeringPinToTop } from '@/common/api/device'
export default {
props: {
store: {
@@ -167,7 +166,8 @@ export default {
created() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
},
mounted() {},
mounted() {
},
methods: {
bindClick(e, item) {
engineeringPinToTop({
@@ -373,9 +373,11 @@ export default {
.nav-menu {
}
}
/deep/ .button-group--right {
padding: 0 0 20rpx;
}
.star-icon {
font-size: 40rpx;
}

View File

@@ -1,324 +1,342 @@
<template>
<Cn-page :loading="loading" class="messageBox" style="padding-top: 10px">
<view slot="body" class="message">
<view class="tabsBox">
<uni-segmented-control
:current="current"
:values="items"
style-type="text"
active-color="#376cf3"
@clickItem="onClickItem"
/>
<!-- 角标 -->
<view class="badge-container">
<span v-for="(item, index) in items" :key="index" class="badge">
<uni-badge :text="badgeCounts[index] > 99 ? '99+' : badgeCounts[index]" />
<!-- {{ badgeCounts[index] > 99 ? '99+' : badgeCounts[index] }} -->
</span>
</view>
<!-- 筛选条件 -->
<Cn-filterCriteria
ref="cnFilterCriteria"
:level="current === 0 ? 3 : current === 1 ? 3 : 2"
@select="select"
>
</Cn-filterCriteria>
</view>
<view class="content">
<Transient
ref="TransientRef"
v-if="current === 0"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<SteadyState
ref="SteadyStateRef"
v-if="current === 1"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<Alarm
ref="AlarmRef"
v-if="current === 2"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<Run
ref="RunRef"
v-if="current === 3"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
</view>
</view>
</Cn-page>
</template>
<script>
import Transient from '@/pages/message1/transient.vue'
import SteadyState from '@/pages/message1/steadyState.vue'
import Alarm from '@/pages/message1/alarm.vue'
import Run from '@/pages/message1/run.vue'
import { getDevCount } from '../../common/api/device.js'
import { updateStatus } from '@/common/api/message'
export default {
components: { Transient, SteadyState, Alarm, Run },
props: {},
data() {
return {
items: ['暂态事件', '稳态事件'], //'运行告警', '运行事件'
badgeCounts: [0, 0, 0, 0],
current: 0,
colorIndex: 0,
item: '',
loading: false,
width: 0,
navHeight: 0,
selectValue: {},
devCount: [],
// 筛选数据
}
},
onLoad() {},
mounted() {
this.setHeight()
},
onPullDownRefresh() {
this.refresh()
},
onNavigationBarButtonTap(e) {
uni.showModal({
title: '提示',
content: '确定要全部标记为已读吗?',
success: (res) => {
if (res.confirm) {
updateStatus({
// '暂态事件', 0
// '稳态事件', 1
// '运行告警', 3
// '运行事件' 2
type: this.current == 2 ? 3 : this.current == 3 ? 2 : this.current,
eventIds: [],
}).then(() => {
this.refresh()
this.getDevCount()
})
}
},
})
},
onShow() {
if (uni.getStorageSync(this.$cacheKey.userInfo).authorities === 'operation_manager') {
this.items = ['暂态事件', '稳态事件', '运行告警', '运行事件']
}
const params = uni.getStorageSync('messageParams')
this.getDevCount()
this.$nextTick(() => {
if (params.type !== '') {
this.current = params.type - 0
}
if (params.engineeringName != '') {
this.$refs.cnFilterCriteria && this.$refs.cnFilterCriteria.external(params)
}
// this.refresh()
this.$refs.TransientRef && this.$refs.TransientRef.getConfig()
})
},
// 页面销毁
onHide() {
uni.setStorageSync('messageParams', {
engineeringName: '',
engineeringId: '', //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
type: '',
})
},
methods: {
setHeight() {
uni.createSelectorQuery()
.select('.tabsBox')
.boundingClientRect((rect) => {
this.width = rect.width
//
// #ifdef H5
this.navHeight = rect.height + 75
// #endif
// #ifdef APP-PLUS
this.navHeight = rect.height + 20
// #endif
})
.exec()
},
refresh() {
switch (this.current) {
case 0:
this.$refs.TransientRef.store.reload()
break
case 1:
this.$refs.SteadyStateRef.store.reload()
break
case 2:
this.$refs.AlarmRef.store.reload()
break
case 3:
this.$refs.RunRef.store.reload()
break
}
},
onClickItem(e) {
if (this.current !== e.currentIndex) {
this.current = e.currentIndex
}
},
select(value) {
this.selectValue = value
setTimeout(() => {
this.setHeight()
}, 100)
},
// 设置角标
getDevCount() {
if (uni.getStorageSync('projectList')[1] != undefined) {
getDevCount(uni.getStorageSync('projectList')[1].engineeringId).then((res) => {
this.devCount = res.data
this.badgeCounts = [
this.devCount.eventCount,
this.devCount.harmonicCount,
this.devCount.alarmCount,
this.devCount.runCount,
]
uni.setStorage({
key: this.$cacheKey.messageCount,
data: this.devCount,
})
let messagePage =
this.devCount.eventCount +
this.devCount.harmonicCount +
(uni.getStorageSync(this.$cacheKey.userInfo).authorities == 'operation_manager'
? this.devCount.alarmCount + this.devCount.runCount
: 0)
let minePage = this.devCount.feedBackCount
if (messagePage) {
uni.setTabBarBadge({
index: 1,
text: messagePage ? (messagePage > 99 ? '99+' : messagePage + '') : '',
})
} else {
uni.removeTabBarBadge({
index: 1,
})
}
if (minePage) {
uni.setTabBarBadge({
index: 2,
text: minePage + '',
})
} else {
uni.removeTabBarBadge({
index: 2,
})
}
// #ifdef APP-PLUS
plus.runtime.setBadgeNumber(messagePage + minePage)
// #endif
})
}
},
// 根据索引动态计算右侧偏移位置,使徽章对准每个标签的右上角
getBadgeRightPosition(index) {
if (this.items == 4) {
return (index + 1) * (this.width / 4) + 'px'
} else {
return (index + 0) * (this.width / 2) + 'px'
}
},
},
computed: {},
}
</script>
<style lang="scss">
.messageBox {
overflow: hidden;
/deep/.tabsBox {
position: relative;
background-color: #fff;
.segmented-control {
// height: 40px;
background-color: #fff;
border-bottom: 1px solid #cccccc70;
.segmented-control__item {
align-items: baseline;
margin-top: 5px;
}
}
.segmented-control__text {
font-size: 30rpx !important;
color: rgb(96, 98, 102);
}
.segmented-control__item--text {
font-weight: bold;
padding: 0 0 5rpx;
}
.choose {
// padding: 20rpx;
// display: flex;
// justify-content: space-between;
// align-items: center;
background: #fff;
}
}
.subsection {
width: 90%;
margin: 20rpx auto;
}
.badge-container {
position: absolute;
top: -10rpx; /* 徽章向上偏移,与控件重叠 */
display: flex;
justify-content: space-around;
right: 0;
width: 100%;
height: 0;
pointer-events: none; /* 确保徽章不干扰点击事件 */
}
/deep/ .uni-badge--error {
background-color: #ff3b30;
}
.badge {
flex: 1;
// position: absolute;
// min-width: 18px;
// height: 16px;
// padding: 0 4px;
// background-color: #ff3b30; /* 红色徽章 */
// color: white;
// font-size: 22rpx;
// line-height: 16px;
// text-align: center;
// border-radius: 9px;
//
text-align: center;
// transform: translateX(-110%); /* 使徽章中心对齐右上角 */
.uni-badge--x {
left: 70rpx;
}
}
}
</style>
<template>
<Cn-page :loading="loading" class="messageBox" style="padding-top: 10px">
<view slot="body" class="message">
<view class="tabsBox">
<uni-segmented-control
:current="current"
:values="items"
style-type="text"
active-color="#376cf3"
@clickItem="onClickItem"
/>
<!-- 角标 -->
<view class="badge-container">
<span v-for="(item, index) in items" :key="index" class="badge">
<uni-badge :text="badgeCounts[index] > 99 ? '99+' : badgeCounts[index]" />
<!-- {{ badgeCounts[index] > 99 ? '99+' : badgeCounts[index] }} -->
</span>
</view>
<!-- 筛选条件 -->
<Cn-filterCriteria
ref="cnFilterCriteria"
:level="current === 0 ? 3 : current === 1 ? 3 : 2"
@select="select"
>
<picker
v-if="current === 0"
@change="bindPickerChange"
:value="sortIndex"
:range="sortOptions"
style="margin-left: auto"
>
<view class="sort-picker">
{{ sortOptions[sortIndex] }}排序
<uni-icons
custom-prefix="iconfont"
type="icon-paixu1"
size="10"
color="#2563EB"
></uni-icons>
</view>
</picker>
</Cn-filterCriteria>
</view>
<view class="content">
<Transient
ref="TransientRef"
v-if="current === 0"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<SteadyState
ref="SteadyStateRef"
v-if="current === 1"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<Alarm
ref="AlarmRef"
v-if="current === 2"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<Run
ref="RunRef"
v-if="current === 3"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
</view>
</view>
</Cn-page>
</template>
<script>
import Transient from '@/pages/message1/transient.vue'
import SteadyState from '@/pages/message1/steadyState.vue'
import Alarm from '@/pages/message1/alarm.vue'
import Run from '@/pages/message1/run.vue'
import { getDevCount } from '../../common/api/device.js'
import { updateStatus } from '@/common/api/message'
export default {
components: { Transient, SteadyState, Alarm, Run },
props: {},
data() {
return {
items: ['暂态事件', '稳态事件'], //'运行告警', '运行事件'
badgeCounts: [0, 0, 0, 0],
current: 0,
colorIndex: 0,
item: '',
loading: false,
width: 0,
navHeight: 0,
selectValue: {},
devCount: [],
sortIndex: 0,
sortOptions: ['发生时间', '暂降深度', '持续时间'],
}
},
onLoad() {},
mounted() {
this.setHeight()
},
onPullDownRefresh() {
this.refresh()
},
onNavigationBarButtonTap(e) {
uni.showModal({
title: '提示',
content: '确定要全部标记为已读吗?',
success: (res) => {
if (res.confirm) {
updateStatus({
// '暂态事件', 0
// '稳态事件', 1
// '运行告警', 3
// '运行事件' 2
type: this.current == 2 ? 3 : this.current == 3 ? 2 : this.current,
eventIds: [],
}).then(() => {
this.refresh()
this.getDevCount()
})
}
},
})
},
onShow() {
if (uni.getStorageSync(this.$cacheKey.userInfo).authorities === 'operation_manager') {
this.items = ['暂态事件', '稳态事件', '运行告警', '运行事件']
}
const params = uni.getStorageSync('messageParams')
this.getDevCount()
this.$nextTick(() => {
if (params.type !== '') {
this.current = params.type - 0
}
if (params.engineeringName != '') {
this.$refs.cnFilterCriteria && this.$refs.cnFilterCriteria.external(params)
}
})
},
// 页面销毁
onHide() {
uni.setStorageSync('messageParams', {
engineeringName: '',
engineeringId: '', //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
type: '',
})
},
methods: {
setHeight() {
uni.createSelectorQuery()
.select('.tabsBox')
.boundingClientRect((rect) => {
this.width = rect.width
//
// #ifdef H5
this.navHeight = rect.height + 75
// #endif
// #ifdef APP-PLUS
this.navHeight = rect.height + 20
// #endif
})
.exec()
},
refresh() {
switch (this.current) {
case 0:
this.$refs.TransientRef.store.reload()
break
case 1:
this.$refs.SteadyStateRef.store.reload()
break
case 2:
this.$refs.AlarmRef.store.reload()
break
case 3:
this.$refs.RunRef.store.reload()
break
}
},
onClickItem(e) {
if (this.current !== e.currentIndex) {
this.current = e.currentIndex
}
},
select(value) {
this.selectValue = value
setTimeout(() => {
this.setHeight()
}, 100)
},
bindPickerChange(e) {
this.sortIndex = e.detail.value
if (this.$refs.TransientRef) {
this.$refs.TransientRef.setSort(this.sortIndex)
}
},
// 设置角标
getDevCount() {
if (uni.getStorageSync('projectList')[1] != undefined) {
getDevCount(uni.getStorageSync('projectList')[1].engineeringId).then((res) => {
this.devCount = res.data
this.badgeCounts = [
this.devCount.eventCount,
this.devCount.harmonicCount,
this.devCount.alarmCount,
this.devCount.runCount,
]
uni.setStorage({
key: this.$cacheKey.messageCount,
data: this.devCount,
})
let messagePage =
this.devCount.eventCount +
this.devCount.harmonicCount +
(uni.getStorageSync(this.$cacheKey.userInfo).authorities == 'operation_manager'
? this.devCount.alarmCount + this.devCount.runCount
: 0)
let minePage = this.devCount.feedBackCount
if (messagePage) {
uni.setTabBarBadge({
index: 1,
text: messagePage ? (messagePage > 99 ? '99+' : messagePage + '') : '',
})
} else {
uni.removeTabBarBadge({
index: 1,
})
}
if (minePage) {
uni.setTabBarBadge({
index: 2,
text: minePage + '',
})
} else {
uni.removeTabBarBadge({
index: 2,
})
}
// #ifdef APP-PLUS
plus.runtime.setBadgeNumber(messagePage + minePage)
// #endif
})
}
},
// 根据索引动态计算右侧偏移位置,使徽章对准每个标签的右上角
getBadgeRightPosition(index) {
if (this.items == 4) {
return (index + 1) * (this.width / 4) + 'px'
} else {
return (index + 0) * (this.width / 2) + 'px'
}
},
},
computed: {},
}
</script>
<style lang="scss">
.messageBox {
overflow: hidden;
/deep/.tabsBox {
position: relative;
background-color: #fff;
.segmented-control {
// height: 40px;
background-color: #fff;
border-bottom: 1px solid #cccccc70;
.segmented-control__item {
align-items: baseline;
margin-top: 5px;
}
}
.segmented-control__text {
font-size: 30rpx !important;
color: rgb(96, 98, 102);
}
.segmented-control__item--text {
font-weight: bold;
padding: 0 0 5rpx;
}
.choose {
// padding: 20rpx;
// display: flex;
// justify-content: space-between;
// align-items: center;
background: #fff;
}
}
.subsection {
width: 90%;
margin: 20rpx auto;
}
.badge-container {
position: absolute;
top: -10rpx; /* 徽章向上偏移,与控件重叠 */
display: flex;
justify-content: space-around;
right: 0;
width: 100%;
height: 0;
pointer-events: none; /* 确保徽章不干扰点击事件 */
}
/deep/ .uni-badge--error {
background-color: #ff3b30;
}
.badge {
flex: 1;
text-align: center;
.uni-badge--x {
left: 70rpx;
}
}
.sort-picker {
font-size: 24rpx;
color: #2563eb;
display: flex;
align-items: center;
white-space: nowrap;
}
}
</style>

View File

@@ -21,17 +21,18 @@
<view class="content-item-header-right-des">工程名称{{ item.engineeringName }}</view>
<view class="content-item-header-right-des">项目名称{{ item.projectName }}</view>
<view class="content-item-header-right-des" v-if="type == '0' || type == '1'"
>监测点名称{{ item.lineName }}</view
>监测点名称{{ item.lineName }}
</view
>
<view class="content-item-header-right-des" v-if="type == '0'"
>暂态类型{{ item.showName }}</view
>暂态类型{{ item.showName }}
</view
>
<!-- <view class="content-item-header-right-des">{{ item.subTitle }}</view> -->
</view>
<view class="ml10" v-if="type === '0' || item.status != '1'">
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
</view>
<uni-icons type="search" size="25" color="#376cf3"></uni-icons>
</view>
</view>
<view class="content-item-footer">{{ item.subTitle }}</view>
</view>

View File

@@ -31,26 +31,25 @@
color="#376cf3"
></uni-icons> -->
<Cn-icon-transient :name="`运行告警`" />
<view class="badge1" v-if="item.isRead == 0"> </view>
<view class="badge1" v-if="item.isRead == 0"></view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.date }}</text>
</view>
<view class="event-desc">
<text>告警终端{{ item.warnNums }}</text>
<text>通讯中断{{ item.interruptCounts }}</text>
<text>终端告警{{ item.warnCounts}}</text>
<text>告警终端总数{{ item.warnNums }}</text>
<text>质量指标告警终端数{{ item.interruptCounts }}</text>
<text>事件触发告警终端数{{ item.warnCounts }}</text>
</view>
</view>
<view class="event-action">
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
<uni-icons type="search" size="25" color="#376cf3"></uni-icons>
</view>
</view>
<!-- <view class="event-detail">
<text> 告警终端{{ item.warnNums }} </text>
<text> 告警终端总数{{ item.warnNums }} </text>
</view> -->
</uni-card>
<uni-load-more
@@ -63,6 +62,7 @@
</template>
<script>
import list from '@/common/js/list'
export default {
components: {},
props: {
@@ -82,7 +82,8 @@ export default {
status: 'noMore', //more加载前 loading加载中 noMore加载后
}
},
mounted() {},
mounted() {
},
methods: {
init() {
@@ -160,6 +161,7 @@ export default {
flex: 1;
}
}
/deep/ .uni-scroll-view-refresher {
display: none;
}

View File

@@ -1,249 +1,249 @@
<template>
<!-- ITIC -->
<view>
<l-echart v-if="status != 'loading'" ref="echartRef" @finished="initChart"></l-echart>
<uni-load-more v-else :status="status"></uni-load-more>
</view>
</template>
<script>
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
export default {
components: {},
props: {
store: {
type: [Object],
},
},
data() {
return {
option: {
backgroundColor: '#fff',
grid: {
left: '10px',
right: '40rpx',
bottom: '40rpx',
top: '10px',
containLabel: true,
},
legend: {
data: ['分割线', '可容忍事件', '不可容忍事件'],
right: '10px',
bottom: '10px',
textStyle: {
fontSize: 10,
},
itemWidth: 10,
itemHeight: 10,
itemGap: 8,
padding: [5, 5, 5, 10],
},
yAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
inverse: true,
axisLabel: {
rotate: -90,
},
splitLine: { show: false },
},
xAxis: {
type: 'value',
splitNumber: 10,
minInterval: 20,
position: 'top',
rotate: 90,
max: 140,
axisLabel: {
rotate: -90,
},
name: '%',
},
series: [
{
name: '分割线',
type: 'line',
data: [
[0, 0.05],
[50, 0.05],
[50, 0.2],
[70, 0.2],
[70, 0.5],
[80, 0.5],
[80, 10],
[80, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#DAA520',
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointF,
data: [],
color: 'green',
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointFun,
data: [],
color: 'red',
},
],
},
status: 'loading',
echartRef: null,
pointF: [],
pointFun: [],
data: [],
maxXAxis: 140,
}
},
mounted() {
// this.initChart()
// console.log('🚀 ~ props.data:', this.props.data)
},
methods: {
init() {},
async initChart() {
if (!this.$refs.echartRef) return
try {
this.echartRef = await this.$refs.echartRef.init(echarts)
this.bindChartClickEvent()
this.echartRef.setOption(this.option, true)
} catch (error) {
console.error('图表初始化失败:', error)
}
},
gongfunction() {
var standF = 0
var unstandF = 0
this.pointF = []
this.pointFun = []
var total = 0
let dataList = [0]
total = this.data.length
if (total == 0) {
} else {
for (var i = 0; i < this.data.length; i++) {
var point = []
var xx = this.data[i].evtParamTm.replace(/s/g, '')
var yy = this.data[i].evtParamVVaDepth.replace(/%/g, '')
var time = this.data[i].startTime.replace('T', ' ')
dataList.push(yy)
point = [yy, xx, time, this.data[i]]
if (xx < 0.05) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else if (xx < 0.2) {
if (yy > 50) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
} else if (xx < 0.5) {
if (yy > 70) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
} else {
if (yy > 80) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
}
}
}
this.option.xAxis.max = Math.max(
140,
Math.ceil(
Math.max(
...dataList
.filter((item) => {
return item !== '-' && !isNaN(Number(item))
})
.map((item) => Number(item)),
) / 10,
) * 10,
) //this.maxXAxis
this.option.series[1].data = this.pointF
this.option.series[2].data = this.pointFun
if (this.echartRef) {
this.echartRef.setOption(this.option, true)
} else {
this.initChart()
}
},
bindChartClickEvent() {
if (!this.echartRef) return
this.echartRef.on('click', (params) => {
// 点击查看详情
let item = params.value[3]
let str = JSON.stringify(item).replace(/%/g, '百分比')
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
})
},
},
computed: {},
watch: {
store: {
handler(val, oldVal) {
this.status = val.status
this.data = (val.data || [])
this.gongfunction()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped></style>
<template>
<!-- ITIC -->
<view>
<l-echart v-if="status != 'loading'" ref="echartRef" @finished="initChart"></l-echart>
<uni-load-more v-else :status="status"></uni-load-more>
</view>
</template>
<script>
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
export default {
components: {},
props: {
store: {
type: [Object],
},
},
data() {
return {
option: {
backgroundColor: '#fff',
grid: {
left: '10px',
right: '40rpx',
bottom: '40rpx',
top: '10px',
containLabel: true,
},
legend: {
data: ['分割线', '可容忍事件', '不可容忍事件'],
right: '10px',
bottom: '10px',
textStyle: {
fontSize: 10,
},
itemWidth: 10,
itemHeight: 10,
itemGap: 8,
padding: [5, 5, 5, 10],
},
yAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
inverse: true,
axisLabel: {
rotate: -90,
},
splitLine: { show: false },
},
xAxis: {
type: 'value',
splitNumber: 10,
minInterval: 20,
position: 'top',
rotate: 90,
max: 140,
axisLabel: {
rotate: -90,
},
name: '%',
},
series: [
{
name: '分割线',
type: 'line',
data: [
[0, 0.05],
[50, 0.05],
[50, 0.2],
[70, 0.2],
[70, 0.5],
[80, 0.5],
[80, 10],
[80, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#DAA520',
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointF,
data: [],
color: 'green',
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointFun,
data: [],
color: 'red',
},
],
},
status: 'loading',
echartRef: null,
pointF: [],
pointFun: [],
data: [],
maxXAxis: 140,
}
},
mounted() {
// this.initChart()
// console.log('🚀 ~ props.data:', this.props.data)
},
methods: {
init() {},
async initChart() {
if (!this.$refs.echartRef) return
try {
this.echartRef = await this.$refs.echartRef.init(echarts)
this.bindChartClickEvent()
this.echartRef.setOption(this.option, true)
} catch (error) {
console.error('图表初始化失败:', error)
}
},
gongfunction() {
var standF = 0
var unstandF = 0
this.pointF = []
this.pointFun = []
var total = 0
let dataList = [0]
total = this.data.length
if (total == 0) {
} else {
for (var i = 0; i < this.data.length; i++) {
var point = []
var xx = this.data[i].evtParamTm.replace(/s/g, '')
var yy = this.data[i].evtParamVVaDepth.replace(/%/g, '')
var time = this.data[i].startTime.replace('T', ' ')
dataList.push(yy)
point = [yy, xx, time, this.data[i]]
if (xx < 0.05) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else if (xx < 0.2) {
if (yy > 50) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
} else if (xx < 0.5) {
if (yy > 70) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
} else {
if (yy > 80) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
}
}
}
this.option.xAxis.max = Math.max(
140,
Math.ceil(
Math.max(
...dataList
.filter((item) => {
return item !== '-' && !isNaN(Number(item))
})
.map((item) => Number(item)),
) / 10,
) * 10,
) //this.maxXAxis
this.option.series[1].data = this.pointF
this.option.series[2].data = this.pointFun
if (this.echartRef) {
this.echartRef.setOption(this.option, true)
} else {
this.initChart()
}
},
bindChartClickEvent() {
if (!this.echartRef) return
this.echartRef.on('click', (params) => {
// 点击查看详情
let item = params.value[3]
let str = JSON.stringify(item).replace(/%/g, '百分比')
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
})
},
},
computed: {},
watch: {
store: {
handler(val, oldVal) {
this.status = val.status
this.data = (val.data || [])
this.gongfunction()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped></style>

View File

@@ -1,241 +1,241 @@
<template>
<!-- ITIC -->
<view>
<l-echart v-if="status != 'loading'" ref="echartRef" @finished="initChart"></l-echart>
<uni-load-more v-else :status="status"></uni-load-more>
</view>
</template>
<script>
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
export default {
components: {},
props: {
store: {
type: [Object],
},
},
data() {
return {
option: {
backgroundColor: '#fff',
grid: {
left: '10px',
right: '40rpx',
bottom: '40rpx',
top: '10px',
containLabel: true,
},
legend: {
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
right: '10px',
bottom: '10px',
textStyle: {
fontSize: 10,
},
itemWidth: 10,
itemHeight: 10,
itemGap: 8,
padding: [5, 5, 5, 10],
},
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
yAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
inverse: true,
axisLabel: {
rotate: -90,
},
splitLine: { show: false },
},
xAxis: {
type: 'value',
splitNumber: 10,
minInterval: 3,
position: 'top',
rotate: 90,
axisLabel: {
rotate: 90,
},
name: '%',
},
series: [
{
name: '上限',
type: 'line',
data: [
[200, 0.001],
[140, 0.003],
[120, 0.003],
[120, 0.5],
[110, 0.5],
[110, 10],
[110, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#FF8C00',
},
{
name: '下限',
type: 'line',
data: [
[0, 0.02],
[70, 0.02],
[70, 0.5],
[80, 0.5],
[80, 10],
[90, 10],
[90, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#00BFFF',
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointI,
data: [],
color: 'green',
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointIun,
data: [],
color: 'red',
},
],
},
status: 'loading',
echartRef: null,
pointI: [],
pointIun: [],
data: [],
}
},
mounted() {
// this.initChart()
// console.log('🚀 ~ props.data:', this.props.data)
},
methods: {
init() {},
async initChart() {
if (!this.$refs.echartRef) return
try {
this.echartRef = await this.$refs.echartRef.init(echarts)
this.bindChartClickEvent()
this.echartRef.setOption(this.option, true)
} catch (error) {
console.error('图表初始化失败:', error)
}
},
gongfunction() {
// 初始化计数与数据数组
let normalCount = 0
let abnormalCount = 0
this.normalPoints = []
this.abnormalPoints = []
if (!this.data || this.data.length === 0) {
this.updateChartOption()
return
}
// 缓存长度,遍历数据
const len = this.data.length
for (let i = 0; i < len; i++) {
const item = this.data[i]
// 建议确认正则意图,/s/g 仅移除字母 s若去空格应为 /\s/g
const xx = parseFloat(item.evtParamTm.replace(/s/g, ''))
const yy = parseFloat(item.evtParamVVaDepth.replace(/%/g, ''))
const time = item.startTime.replace('T', ' ')
const pointData = [yy, xx, time, item]
const isNormal = this.checkPointStatus(xx, yy)
const pointObj = {
value: pointData,
itemStyle: { normal: { color: isNormal ? 'green' : 'red' } },
}
if (isNormal) {
normalCount++
this.normalPoints.push(pointObj)
} else {
abnormalCount++
this.abnormalPoints.push(pointObj)
}
}
this.updateChartOption()
},
// 提取判断逻辑为独立方法
checkPointStatus(xx, yy) {
if (xx <= 0.003) {
const line = 230 - 30000 * xx
return yy <= line
} else if (xx <= 0.02) {
return yy <= 120
} else if (xx <= 0.5) {
return yy > 70 && yy < 120
} else if (xx <= 10) {
return yy > 80 && yy < 110
} else {
return yy > 90 && yy < 110
}
},
updateChartOption() {
// 建议避免硬编码 series 索引,可通过 seriesName 查找
this.option.series[2].data = this.normalPoints
this.option.series[3].data = this.abnormalPoints
if (this.echartRef) {
this.echartRef.setOption(this.option, true)
} else {
this.initChart()
}
},
bindChartClickEvent() {
if (!this.echartRef) return
this.echartRef.on('click', (params) => {
console.log('🚀 ~ params:', params.value[3])
// 点击查看详情
let item = params.value[3]
let str = JSON.stringify(item).replace(/%/g, '百分比')
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
})
},
},
computed: {},
watch: {
store: {
handler(val, oldVal) {
this.status = val.status
this.data = (val.data || [])
this.gongfunction()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped></style>
<template>
<!-- ITIC -->
<view>
<l-echart v-if="status != 'loading'" ref="echartRef" @finished="initChart"></l-echart>
<uni-load-more v-else :status="status"></uni-load-more>
</view>
</template>
<script>
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
export default {
components: {},
props: {
store: {
type: [Object],
},
},
data() {
return {
option: {
backgroundColor: '#fff',
grid: {
left: '10px',
right: '40rpx',
bottom: '40rpx',
top: '10px',
containLabel: true,
},
legend: {
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
right: '10px',
bottom: '10px',
textStyle: {
fontSize: 10,
},
itemWidth: 10,
itemHeight: 10,
itemGap: 8,
padding: [5, 5, 5, 10],
},
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
yAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
inverse: true,
axisLabel: {
rotate: -90,
},
splitLine: { show: false },
},
xAxis: {
type: 'value',
splitNumber: 10,
minInterval: 3,
position: 'top',
rotate: 90,
axisLabel: {
rotate: 90,
},
name: '%',
},
series: [
{
name: '上限',
type: 'line',
data: [
[200, 0.001],
[140, 0.003],
[120, 0.003],
[120, 0.5],
[110, 0.5],
[110, 10],
[110, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#FF8C00',
},
{
name: '下限',
type: 'line',
data: [
[0, 0.02],
[70, 0.02],
[70, 0.5],
[80, 0.5],
[80, 10],
[90, 10],
[90, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#00BFFF',
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointI,
data: [],
color: 'green',
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointIun,
data: [],
color: 'red',
},
],
},
status: 'loading',
echartRef: null,
pointI: [],
pointIun: [],
data: [],
}
},
mounted() {
// this.initChart()
// console.log('🚀 ~ props.data:', this.props.data)
},
methods: {
init() {},
async initChart() {
if (!this.$refs.echartRef) return
try {
this.echartRef = await this.$refs.echartRef.init(echarts)
this.bindChartClickEvent()
this.echartRef.setOption(this.option, true)
} catch (error) {
console.error('图表初始化失败:', error)
}
},
gongfunction() {
// 初始化计数与数据数组
let normalCount = 0
let abnormalCount = 0
this.normalPoints = []
this.abnormalPoints = []
if (!this.data || this.data.length === 0) {
this.updateChartOption()
return
}
// 缓存长度,遍历数据
const len = this.data.length
for (let i = 0; i < len; i++) {
const item = this.data[i]
// 建议确认正则意图,/s/g 仅移除字母 s若去空格应为 /\s/g
const xx = parseFloat(item.evtParamTm.replace(/s/g, ''))
const yy = parseFloat(item.evtParamVVaDepth.replace(/%/g, ''))
const time = item.startTime.replace('T', ' ')
const pointData = [yy, xx, time, item]
const isNormal = this.checkPointStatus(xx, yy)
const pointObj = {
value: pointData,
itemStyle: { normal: { color: isNormal ? 'green' : 'red' } },
}
if (isNormal) {
normalCount++
this.normalPoints.push(pointObj)
} else {
abnormalCount++
this.abnormalPoints.push(pointObj)
}
}
this.updateChartOption()
},
// 提取判断逻辑为独立方法
checkPointStatus(xx, yy) {
if (xx <= 0.003) {
const line = 230 - 30000 * xx
return yy <= line
} else if (xx <= 0.02) {
return yy <= 120
} else if (xx <= 0.5) {
return yy > 70 && yy < 120
} else if (xx <= 10) {
return yy > 80 && yy < 110
} else {
return yy > 90 && yy < 110
}
},
updateChartOption() {
// 建议避免硬编码 series 索引,可通过 seriesName 查找
this.option.series[2].data = this.normalPoints
this.option.series[3].data = this.abnormalPoints
if (this.echartRef) {
this.echartRef.setOption(this.option, true)
} else {
this.initChart()
}
},
bindChartClickEvent() {
if (!this.echartRef) return
this.echartRef.on('click', (params) => {
console.log('🚀 ~ params:', params.value[3])
// 点击查看详情
let item = params.value[3]
let str = JSON.stringify(item).replace(/%/g, '百分比')
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
})
},
},
computed: {},
watch: {
store: {
handler(val, oldVal) {
this.status = val.status
this.data = (val.data || [])
this.gongfunction()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped></style>

View File

@@ -1,99 +1,146 @@
<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.startTime }}</view>
</view>
<view class="detail-content">
<view class="detail-content-title mb20">基础信息</view>
<view class="mb5"> 工程名称{{ detail.engineeringName }} </view>
<view class="mb5"> 项目名称{{ detail.projectName }} </view>
<view class="mb5"> 设备名称{{ detail.equipmentName }}</view>
<view class="mb5"> 监测点名称{{ detail.lineName }}</view>
<view class="mb5"> 暂态类型{{ detail.showName }}</view>
<view class="mb5" v-if="detail.evtParamTm"> 持续时间{{ detail.evtParamTm }}s</view>
<view class="mb5" v-if="detail.evtParamVVaDepth"> 幅值{{ detail.evtParamVVaDepth }}%</view>
<view class="mb5" v-if="detail.evtParamPhase"> 相别{{ detail.evtParamPhase }}</view>
<!-- <view class="mb5" v-for="(item, textIndex) in detail.dataSet" :key="textIndex">
{{ item.showName + '' + (item.value == 3.1415926 ? '-' : item.value) + (item.unit || '') }}
</view> -->
</view>
<view class="detail-content">
<view class="detail-content-title mb20">瞬时波形图</view>
<image
style="width: 100%"
:src="detail.instantPics"
mode="widthFix"
v-if="detail.instantPics"
@click="previewImage(detail.instantPics)"
/>
<text v-else>暂无</text>
</view>
<view class="detail-content">
<view class="detail-content-title mb20">RMS波形图</view>
<image
style="width: 100%"
:src="detail.rmsPics"
mode="widthFix"
v-if="detail.rmsPics"
@click="previewImage(detail.rmsPics)"
/>
<text v-else>暂无</text>
</view>
</view>
</Cn-page>
</template>
<script>
import { updateStatus } from '@/common/api/message'
export default {
data() {
return {
loading: true,
detail: {},
}
},
onLoad(options) {
// console.log(options.detail)
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.detail.rmsPics && (this.detail.rmsPics = this.$config.static + this.detail.rmsPics)
this.detail.instantPics && (this.detail.instantPics = this.$config.static + this.detail.instantPics)
this.loading = false
if (this.detail.status != 1) {
updateStatus({
eventIds: [this.detail.id],
})
}
},
methods: {
previewImage(url) {
// uni.previewImage({
// urls: [url],
// })
uni.navigateTo({
url: `/pages/message1/comp/preview?url=${encodeURIComponent(url)}`,
})
},
},
}
</script>
<style lang="scss">
.detail {
padding: 20rpx 0;
.detail-content {
padding: 20rpx;
background: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
.detail-content-title {
font-size: 30rpx;
color: #111;
font-weight: 700;
}
}
}
</style>
<template>
<Cn-page :loading="loading">
<view class="detail" slot="body">
<view class="detail-content" style="font-size: 32rpx">
<view>{{ detail.startTime }}</view>
</view>
<view class="detail-content">
<view class="detail-content-title mb20">基础信息</view>
<view class="mb5"> 工程名称{{ detail.engineeringName }} </view>
<view class="mb5"> 项目名称{{ detail.projectName }} </view>
<view class="mb5"> 设备名称{{ detail.equipmentName }}</view>
<view class="mb5"> 监测点名称{{ detail.lineName }}</view>
<view class="mb5"> 暂态类型{{ detail.showName }}</view>
<view class="mb5" v-if="detail.evtParamTm"> 持续时间{{ detail.evtParamTm }}s</view>
<view class="mb5" v-if="detail.evtParamVVaDepth"> 幅值{{ detail.evtParamVVaDepth }}%</view>
<view class="mb5" v-if="detail.evtParamPhase"> 相别{{ detail.evtParamPhase }}</view>
</view>
<view class="detail-tabs">
<uni-segmented-control
:current="detailTab"
active-color="#376cf3"
:values="['波形图', 'ITIC', 'F47']"
@clickItem="onDetailTabChange"
/>
</view>
<view v-if="detailTab == 0">
<view class="detail-content">
<view class="detail-content-title mb20">瞬时波形图</view>
<image
style="width: 100%"
:src="detail.instantPics"
mode="widthFix"
v-if="detail.instantPics"
@click="previewImage(detail.instantPics)"
/>
<text v-else>暂无</text>
</view>
<view class="detail-content">
<view class="detail-content-title mb20">RMS波形图</view>
<image
style="width: 100%"
:src="detail.rmsPics"
mode="widthFix"
v-if="detail.rmsPics"
@click="previewImage(detail.rmsPics)"
/>
<text v-else>暂无</text>
</view>
</view>
<view v-if="detailTab == 1" class="chart-wrapper">
<ITIC :store="eventStore" style="min-height: 600rpx;" />
</view>
<view v-if="detailTab == 2" class="chart-wrapper">
<F47 :store="eventStore" style="min-height: 600rpx;" />
</view>
</view>
</Cn-page>
</template>
<script>
import { updateStatus } from '@/common/api/message'
import ITIC from './ITIC.vue'
import F47 from './F47.vue'
export default {
components: { ITIC, F47 },
data() {
return {
loading: true,
detail: {},
detailTab: 0,
}
},
computed: {
eventStore() {
const hasData = this.detail && (this.detail.id || this.detail.equipmentId)
if (!hasData) {
return { data: [], status: 'noMore' }
}
const item = {
...this.detail,
evtParamTm: this.detail.evtParamTm || '0s',
evtParamVVaDepth: this.detail.evtParamVVaDepth || '0%',
}
return {
data: [item],
status: 'noMore',
}
},
},
onLoad(options) {
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.detail.rmsPics && (this.detail.rmsPics = this.$config.static + this.detail.rmsPics)
this.detail.instantPics && (this.detail.instantPics = this.$config.static + this.detail.instantPics)
this.loading = false
if (this.detail.status != 1) {
updateStatus({
eventIds: [this.detail.id],
})
}
},
methods: {
onDetailTabChange(e) {
this.detailTab = e.currentIndex
},
previewImage(url) {
uni.navigateTo({
url: `/pages/message1/comp/preview?url=${encodeURIComponent(url)}`,
})
},
},
}
</script>
<style lang="scss">
.detail {
padding: 20rpx 0;
.detail-content {
padding: 20rpx;
background: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
.detail-content-title {
font-size: 30rpx;
color: #111;
font-weight: 700;
}
}
.detail-tabs {
padding: 0 20rpx;
margin-bottom: 20rpx;
}
.chart-container {
min-height: 600rpx;
}
.chart-wrapper {
background: #fff;
margin-bottom: 20rpx;
padding: 20rpx;
}
}
</style>

View File

@@ -27,7 +27,7 @@
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>事件时间{{ item.startTime }}</text>
<text>事件时间{{ item.startTime2 }}</text>
</view>
</view>
</view>

View File

@@ -17,9 +17,9 @@
</view>
</view>
</view>
<!-- 稳态数量 -->
<!-- 越限数量 -->
<scroll-view
v-if="filterValue == '稳态数量'"
v-if="filterValue == '越限数量'"
scroll-y="true"
@refresherrefresh="refresherrefresh"
@scrolltolower="scrolltolower"
@@ -47,7 +47,7 @@
color="#E6A23C"
></uni-icons> -->
<Cn-icon-transient :name="`稳态越限`" />
<view class="badge1" v-if="item.isRead == 0"> </view>
<view class="badge1" v-if="item.isRead == 0"></view>
</view>
<view class="event-info">
<view class="event-title">
@@ -61,13 +61,12 @@
</view>
</view>
<view class="event-action">
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
<uni-icons type="search" size="25" color="#376cf3"></uni-icons>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail textBox" @touchmove.stop>
<text>{{ item.statisticsDate }}发生 {{ item.overLimitDesc }} </text>
<text>{{ item.statisticsDate }}发生 {{ item.overLimitDesc }}</text>
</view>
</uni-card>
@@ -149,6 +148,7 @@
<script>
import list from '@/common/js/list'
import { queryAppHarmonicCounts, queryAppHarmonicLine } from '../../common/api/harmonic.js'
export default {
components: {},
props: {
@@ -165,9 +165,9 @@ export default {
data() {
return {
height: 0,
filterValue: '稳态数量',
filterValue: '越限数量',
list: [
{ value: 0, label: '稳态数量' },
{ value: 0, label: '越限数量' },
{ value: 0, label: '越限天数' },
{ value: 0, label: '越限测点数' },
],
@@ -276,6 +276,7 @@ export default {
.box:first-child {
flex: 1.3 !important;
}
/* 列表容器 */
.event-list {
/* 头部:图标 + 信息 + 操作 */
@@ -294,9 +295,11 @@ export default {
font-size: 24rpx;
}
}
/deep/ .uni-scroll-view-refresher {
display: none;
}
.textBox {
max-height: 110rpx;
overflow-y: auto;
@@ -308,15 +311,18 @@ export default {
// text-overflow: ellipsis;
// word-break: break-all;
}
/deep/ .uni-calendar-item--checked {
background-color: #ffffff00;
color: #000000e6;
opacity: 1;
}
/deep/ .uni-calendar-item--isDay {
background-color: #ffffff00;
color: #000000e6;
opacity: 1;
.uni-calendar-item__weeks-lunar-text {
background-color: #ffffff00;
color: #000000e6;
@@ -327,9 +333,11 @@ export default {
/deep/ .uni-calendar-item__weeks-box-text {
z-index: 1;
}
/deep/ .uni-calendar-item--isDay-text {
color: #333 !important; /* 改成你想要的颜色 */
}
/deep/ .uni-calendar-item__weeks-box-circle {
position: absolute;
top: 7px;
@@ -340,30 +348,38 @@ export default {
z-index: 0;
background-color: #e6a23c;
}
/* 核心:选中圆圈下的 子元素(日期数字) */
/deep/ .uni-calendar-item__weeks-box-circle + .uni-calendar-item__weeks-box-text {
color: #fff !important; /* 改成你想要的颜色 */
}
/deep/ .uni-calendar__backtoday,
/deep/ .uni-calendar__header-btn-box {
display: none;
}
/deep/ .uni-calendar-item__weeks-lunar-text {
display: none;
}
/deep/ .uni-calendar__header {
pointer-events: none !important;
}
.event-detail {
/deep/ .uni-calendar__header {
display: none !important;
}
/deep/ .uni-calendar__weeks-day {
height: 35px;
}
/deep/ .uni-calendar-item__weeks-box-item {
height: 40px;
}
/deep/ .uni-calendar-item__weeks-box-circle {
position: absolute;
top: 3px;

View File

@@ -1,333 +1,266 @@
<template>
<view style="position: relative">
<!-- 暂态 -->
<view class="transientBox">
<view class="statistics pd20">
<view
class="box boxClick"
:class="{ boxClick1: filterValue == index }"
v-for="(item, index) in dataList"
@click="
filterValue = index
init()
"
>
<!-- <text class="num">{{ item.value }}</text> -->
<text class="num">{{ item.value }}</text>
<text class="label">{{ item.label }}</text>
</view>
</view>
<view class="smallLabel">
<uni-segmented-control
:current="curSub"
active-color="#376cf3"
:values="subsectionList"
@clickItem="sectionChange"
v-if="subsectionList.length > 1"
/>
<view style="width: 180rpx">
<picker @change="bindPickerChange" :value="sort" :range="array" v-if="curSub == 0">
<view class="uni-input"
>{{ array[sort] }}排序
<uni-icons
custom-prefix="iconfont"
type="icon-paixu1"
size="10"
color="#2563EB"
></uni-icons>
</view>
</picker>
</view>
</view>
</view>
<!-- 卡片 -->
<scroll-view
scroll-y="true"
@refresherrefresh="refresherrefresh"
@scrolltolower="scrolltolower"
:refresher-triggered="triggered"
refresher-enabled="true"
class="event-list"
v-if="curSub == 0"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card
class="event-item boxClick"
:class="judgment(item.showName).type"
v-for="(item, index) in store.data || []"
:key="index"
@click="jump(item)"
>
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
:custom-prefix="'iconfont'"
:type="judgment(item.showName).icon"
:color="judgment(item.showName).color"
:size="judgment(item.showName).size"
></uni-icons> -->
<Cn-icon-transient :name="item.showName" />
<!-- 0未读 1已读 -->
<view class="badge1" v-if="item.status == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
<text class="event-tag" :class="`${judgment(item.showName).type}-tag`">{{
item.showName
}}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>设备名称{{ item.equipmentName }}</text>
</view>
</view>
<view class="event-action">
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<text>
{{ item.startTime ? '发生时间:' + item.startTime : '' }}
{{
item.evtParamVVaDepth != null && item.evtParamVVaDepth !== ''
? ',幅值:' + item.evtParamVVaDepth + '%'
: ''
}}
{{
item.evtParamTm != null && item.evtParamTm !== ''
? ',持续时间:' + item.evtParamTm + 's'
: ''
}}
{{
item.evtParamPhase != null && item.evtParamPhase !== ''
? ',相别:' + item.evtParamPhase
: ''
}}
</text>
</view>
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
<!-- ITIC 列表 -->
<ITIC
v-if="subsectionList[curSub] == 'ITIC'"
:store="store"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
></ITIC>
<!-- F47 列表 -->
<F47
v-if="subsectionList[curSub] == 'F47'"
:store="store"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
></F47>
</view>
</template>
<script>
import list from '@/common/js/list'
import { queryUserPushConfig } from '@/common/api/mine'
import ITIC from './comp/ITIC.vue'
import F47 from './comp/F47.vue'
import { queryAppEventCounts } from '../../common/api/harmonic.js'
export default {
components: { ITIC, F47 },
props: {
navHeight: {
type: Number,
default: 0,
},
selectValue: {
type: Object,
// default: () => {},
},
},
mixins: [list],
data() {
return {
height: 0,
filterValue: 0,
dataList: [
{ value: 0, label: '暂态数量', key: '' },
{ value: 0, label: '暂降', key: '电压暂降' },
{ value: 0, label: '中断', key: '电压中断' },
{ value: 0, label: '暂升', key: '电压暂升' },
],
curSub: 0,
subsectionList: [], //'列表', 'ITIC', 'F47'
status: 'noMore', //more加载前 loading加载中 noMore加载后
sort: 0,
triggered: true,
// config: {},
array: ['发生时间', '暂降深度', '持续时间'],
}
},
mounted() {
this.getConfig()
},
methods: {
getHeight() {
uni.createSelectorQuery()
.select('.transientBox')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect?.height || 0
// #endif
// #ifdef APP-PLUS
this.height = rect?.height || 0
// #endif
})
.exec()
},
// 查詢
init() {
this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage')
this.store.params.type = 0
// this.store.params.pageSize = 10000
this.store.params.sortField = this.sort
this.store.params.engineeringid = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.deviceId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
this.store.params.target =
this.filterValue == 0
? []
: this.filterValue == 1
? ['Evt_Sys_DipStr']
: this.filterValue == 2
? ['Evt_Sys_IntrStr']
: ['Evt_Sys_SwlStr']
this.store.params.startTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay
this.store.params.endTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay
this.store.loadedCallback = () => {
this.getHeight()
this.loading = false
queryAppEventCounts(this.store.params).then((res) => {
this.dataList[0].value = res.data.allNum
this.dataList[1].value = res.data.eventDown
this.dataList[2].value = res.data.eventOff
this.dataList[3].value = res.data.eventUp
})
}
this.store.reload()
},
getConfig() {
queryUserPushConfig().then((res) => {
// this.config = res.data
let list = [
'列表',
res.data.iticFunction == 1 ? 'ITIC' : '',
res.data.f47Function == 1 ? 'F47' : '',
].filter((item) => item)
this.curSub = !list[this.curSub] ? 0 : this.curSub
this.subsectionList = JSON.parse(JSON.stringify(list))
})
},
judgment(val, key) {
switch (val) {
case '电压暂降':
return {
type: 'sag',
icon: 'icon-a-svg4',
color: '#2563eb',
size: '25',
}
case '电压暂升':
return {
type: 'swell',
icon: 'icon-a-svg5',
color: '#e6a23c',
size: '25',
}
case '电压中断':
return {
type: 'interrupt',
icon: 'icon-zhongduan2',
color: '#6b7280',
size: '35',
}
case '瞬态':
return {
type: 'transient',
icon: 'icon-shuntaishijian',
color: '#8b5cf6',
size: '40',
}
case '未知':
return {
type: 'unknown',
icon: 'icon-wenhao',
color: '#6b7280',
size: '45',
}
}
},
// 点击查看详情
jump(item) {
let str = JSON.stringify(item).replace(/%/g, '百分比')
item.status = '1'
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
},
// 切换排序
bindPickerChange(e) {
this.sort = e.detail.value
this.init()
},
sectionChange(e) {
this.curSub = e.currentIndex
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
onShow() {
this.curSub = 0
},
computed: {},
watch: {
selectValue: {
handler(val, oldVal) {
if (Object.keys(val).length === 0) return
this.init()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped>
@import './index.scss';
/deep/ .uni-scroll-view-refresher {
display: none;
}
</style>
<template>
<view style="position: relative">
<!-- 暂态 -->
<view class="transientBox">
<view class="statistics pd20">
<view
class="box boxClick"
:class="{ boxClick1: filterValue == index }"
v-for="(item, index) in dataList"
@click="
filterValue = index
init()
"
>
<!-- <text class="num">{{ item.value }}</text> -->
<text class="num">{{ item.value }}</text>
<text class="label">{{ item.label }}</text>
</view>
</view>
<view class="smallLabel"> </view>
</view>
<!-- 卡片 -->
<scroll-view
scroll-y="true"
@refresherrefresh="refresherrefresh"
@scrolltolower="scrolltolower"
:refresher-triggered="triggered"
refresher-enabled="true"
class="event-list"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card
class="event-item boxClick"
:class="judgment(item.showName).type"
v-for="(item, index) in store.data || []"
:key="index"
@click="jump(item)"
>
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
:custom-prefix="'iconfont'"
:type="judgment(item.showName).icon"
:color="judgment(item.showName).color"
:size="judgment(item.showName).size"
></uni-icons> -->
<Cn-icon-transient :name="item.showName" />
<!-- 0未读 1已读 -->
<view class="badge1" v-if="item.status == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
<text class="event-tag" :class="`${judgment(item.showName).type}-tag`">{{
item.showName
}}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>设备名称{{ item.equipmentName }}</text>
</view>
</view>
<view class="event-action">
<uni-icons type="search" size="25" color="#376cf3"></uni-icons>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<text>
{{ item.startTime ? '发生时间:' + item.startTime : '' }}
{{
item.evtParamVVaDepth != null && item.evtParamVVaDepth !== ''
? ',幅值:' + item.evtParamVVaDepth + '%'
: ''
}}
{{
item.evtParamTm != null && item.evtParamTm !== ''
? ',持续时间:' + item.evtParamTm + 's'
: ''
}}
{{
item.evtParamPhase != null && item.evtParamPhase !== ''
? ',相别:' + item.evtParamPhase
: ''
}}
</text>
</view>
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
</view>
</template>
<script>
import list from '@/common/js/list'
import { queryAppEventCounts } from '../../common/api/harmonic.js'
export default {
props: {
navHeight: {
type: Number,
default: 0,
},
selectValue: {
type: Object,
// default: () => {},
},
},
mixins: [list],
data() {
return {
height: 0,
filterValue: 0,
dataList: [
{ value: 0, label: '暂态数量', key: '' },
{ value: 0, label: '暂降', key: '电压暂降' },
{ value: 0, label: '中断', key: '电压中断' },
{ value: 0, label: '暂升', key: '电压暂升' },
],
status: 'noMore', //more加载前 loading加载中 noMore加载后
sort: 0,
triggered: true,
}
},
methods: {
getHeight() {
uni.createSelectorQuery()
.select('.transientBox')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect?.height || 0
// #endif
// #ifdef APP-PLUS
this.height = rect?.height || 0
// #endif
})
.exec()
},
// 查詢
init() {
this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage')
this.store.params.type = 0
// this.store.params.pageSize = 10000
this.store.params.sortField = this.sort
this.store.params.engineeringid = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.deviceId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
this.store.params.target =
this.filterValue == 0
? []
: this.filterValue == 1
? ['Evt_Sys_DipStr']
: this.filterValue == 2
? ['Evt_Sys_IntrStr']
: ['Evt_Sys_SwlStr']
this.store.params.startTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay
this.store.params.endTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay
this.store.loadedCallback = () => {
this.getHeight()
this.loading = false
queryAppEventCounts(this.store.params).then((res) => {
this.dataList[0].value = res.data.allNum
this.dataList[1].value = res.data.eventDown
this.dataList[2].value = res.data.eventOff
this.dataList[3].value = res.data.eventUp
})
}
this.store.reload()
},
judgment(val, key) {
switch (val) {
case '电压暂降':
return {
type: 'sag',
icon: 'icon-a-svg4',
color: '#2563eb',
size: '25',
}
case '电压暂升':
return {
type: 'swell',
icon: 'icon-a-svg5',
color: '#e6a23c',
size: '25',
}
case '电压中断':
return {
type: 'interrupt',
icon: 'icon-zhongduan2',
color: '#6b7280',
size: '35',
}
case '瞬态':
return {
type: 'transient',
icon: 'icon-shuntaishijian',
color: '#8b5cf6',
size: '40',
}
case '未知':
return {
type: 'unknown',
icon: 'icon-wenhao',
color: '#6b7280',
size: '45',
}
}
},
// 点击查看详情
jump(item) {
let str = JSON.stringify(item).replace(/%/g, '百分比')
item.status = '1'
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
},
setSort(index) {
this.sort = index
this.init()
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
computed: {},
watch: {
selectValue: {
handler(val, oldVal) {
if (Object.keys(val).length === 0) return
this.init()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped>
@import './index.scss';
/deep/ .uni-scroll-view-refresher {
display: none;
}
</style>

View File

@@ -93,7 +93,7 @@ import { sm3Digest } from '@/common/js/sm3.js'
export default {
data() {
return {
checkbox: false,
checkbox: true,
loading: false,
loginType: 'pwd',
phone: '',

View File

@@ -77,7 +77,7 @@ export default {
name: 'jiaban',
data() {
return {
checkbox: false,
checkbox: true,
step: 1,
loading: false,
waitTime: 0,

826
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff