Browse Source

大屏环控优化

master
xuhuajiao 2 months ago
parent
commit
d7eb4cb036
  1. 2
      public/web3D/index.js
  2. 10
      src/api/home/device/index.js
  3. 2
      src/main.js
  4. 4
      src/views/components/AccessDoor.vue
  5. 4
      src/views/components/WarehouseWarning.vue
  6. 1304
      src/views/environmentalScreen/index copy 2.vue
  7. 1149
      src/views/environmentalScreen/index-1216-1.vue
  8. 874
      src/views/environmentalScreen/index.vue
  9. 152
      src/views/environmentalScreen/module/catePie.vue
  10. 135
      src/views/home copy.vue
  11. 826
      src/views/home.vue
  12. 210
      src/views/storeManage/warehouse3D/archivesStorage/index.js
  13. 365
      src/views/storeManage/warehouse3D/archivesStorage/index.vue
  14. 127
      src/views/system/logManage/warnLog/index.vue

2
public/web3D/index.js

@ -277,7 +277,7 @@ var createScene = function() {
var scene = new BABYLON.Scene(engine)
camera = new BABYLON.ArcRotateCamera(
'Camera', 4.02, 0.98, 2.6,
'Camera', 4.02, 0.98, 3.4,
new BABYLON.Vector3(1.2, 0.08, 0.03),
scene
)

10
src/api/home/device/index.js

@ -13,4 +13,12 @@ export function getDeviceOnoff() {
method: 'get'
})
}
export default { getOnlineDevice, getDeviceOnoff }
export function getTodayHikAlarmLog() {
return request({
url: 'api/device/todayHikAlarmLog',
method: 'get'
})
}
export default { getOnlineDevice, getDeviceOnoff, getTodayHikAlarmLog }

2
src/main.js

@ -51,7 +51,7 @@ Vue.filter('formatTs', (tsStr) => {
// 处理日期部分:yyyy/MM/dd
const [year, month, day] = datePart.split('/')
const formattedDate = `${year}/${padZero(month)}/${padZero(day)}`
const formattedDate = `${year}-${padZero(month)}-${padZero(day)}`
// 处理时间部分:HH:mm:ss
const [hour, minute, second] = timePart.split(':')

4
src/views/components/AccessDoor.vue

@ -8,7 +8,7 @@
</p>
</h3>
<el-table ref="table" style="min-width: 100%;" :height="height" :data="tableData" class="warehose-el-table" stripe @row-click="toPage">
<el-table-column prop="time" label="时间" min-width="65">
<el-table-column prop="time" label="时间" min-width="70">
<template slot-scope="scope">
<div>{{ scope.row.time | parseTime }}</div>
</template>
@ -18,7 +18,7 @@
<div>{{ scope.row.name }}</div>
</template>
</el-table-column>
<el-table-column prop="minorName" label="警情" align="center" :show-overflow-tooltip="true" min-width="65" />
<el-table-column prop="minorName" label="说明" align="center" :show-overflow-tooltip="true" min-width="65" />
</el-table>
</div>
</template>

4
src/views/components/WarehouseWarning.vue

@ -9,13 +9,13 @@
</h3>
<!--表格渲染-->
<el-table ref="table" style="min-width: 100%;" :width="width" :height="height" :data="tableData" class="warehose-el-table" :row-class-name="rowBgColor" @row-click="toPage">
<el-table-column prop="TS" label="时间" min-width="65">
<el-table-column prop="TS" label="时间" min-width="70">
<template slot-scope="scope">
<span v-if="scope.row.TS">{{ scope.row.TS | formatTs }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="设备" :show-overflow-tooltip="true" min-width="60" />
<el-table-column prop="value" label="警情" align="center" :show-overflow-tooltip="true" min-width="65" />
<el-table-column prop="value" label="警情" align="center" :show-overflow-tooltip="true" min-width="60" />
</el-table>
</div>
</template>

1304
src/views/environmentalScreen/index copy 2.vue
File diff suppressed because it is too large
View File

1149
src/views/environmentalScreen/index-1216-1.vue
File diff suppressed because it is too large
View File

874
src/views/environmentalScreen/index.vue
File diff suppressed because it is too large
View File

152
src/views/environmentalScreen/module/catePie.vue

@ -0,0 +1,152 @@
<template>
<div ref="chartRef" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
export default {
name: 'CatePie',
mixins: [resize],
props: {
cateData: {
type: Array,
required: true,
default: () => []
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
}
},
data() {
return {
chart: null
}
},
watch: {
cateData: {
handler() {
this.$nextTick(() => {
this.drawChart()
})
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
this.chart = null
}
},
methods: {
initChart() {
if (this.chart) return
const chartDom = this.$refs.chartRef
if (!chartDom) return
this.chart = echarts.init(chartDom)
this.drawChart()
},
drawChart() {
if (!this.chart) this.initChart()
if (!this.chart) return
//
const chartData = this.cateData.length
? this.cateData
: [{ name: '无告警数据', value: 1, itemStyle: { color: '#666666' }}]
const option = {
backgroundColor: 'transparent',
tooltip: {
trigger: 'item',
textStyle: { fontSize: 12 },
formatter: '{b}: {c} 次 ({d}%)'
},
legend: {
bottom: 10,
left: 'center',
icon: 'circle',
itemHeight: 8,
itemWidth: 8,
itemGap: 15,
textStyle: {
color: '#ffffff',
fontSize: 11
},
formatter: function(name) {
if (name.length > 6) {
return name.substring(0, 6) + '\n' + name.substring(6)
}
return name
}
},
series: [
{
name: '当日告警统计',
type: 'pie',
radius: ['30%', '60%'],
center: ['50%', '40%'],
avoidLabelOverlap: false,
labelLine: {
show: true,
length: 10,
length2: 20
},
label: {
show: true,
fontSize: 11,
formatter: '{d}%',
color: '#ffffff' //
},
emphasis: {
label: {
show: true,
fontSize: 12,
fontWeight: 'bold'
},
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
data: chartData, // 使
animationDuration: 1000,
animationEasing: 'cubicOut'
}
]
}
this.chart.setOption(option, true)
},
resize() {
if (this.chart) {
this.chart.resize()
}
}
}
}
</script>
<style lang="scss" scoped>
:deep(.ec-legend) {
padding-bottom: 5px !important;
}
:deep(.ec-tooltip) {
background: rgba(0, 20, 53, 0.9) !important;
border: 1px solid #339cff !important;
border-radius: 4px !important;
}
</style>

135
src/views/home111.vue → src/views/home copy.vue

@ -32,34 +32,6 @@
<el-carousel-item>
<div class="warehouse-tab" style="display: flex; justify-content: center; align-items: center; height: calc(100%); ">
<div class="five-bottom">
<!-- <p class="env-title">档案库</p> -->
<!-- <ul class="leakage-list">
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_001.curstatus > 0 }">
<p>温度</p>
<span>{{ topDisplayData.DAK_DIV_TOP_001.curValue }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_002.curstatus > 0 }">
<p>湿度</p>
<span>{{ topDisplayData.DAK_DIV_TOP_002.curValue }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_003.curstatus > 0 }">
<p>CO2</p>
<span>{{ topDisplayData.DAK_DIV_TOP_003.curValue }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_005.curstatus > 0 }">
<p>PM2.5</p>
<span>{{ topDisplayData.DAK_DIV_TOP_005.curValue }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_006.curstatus > 0 }">
<p>PM10</p>
<span>{{ topDisplayData.DAK_DIV_TOP_006.curValue }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_004.curstatus > 0 }">
<p>TVOC</p>
<span>{{ topDisplayData.DAK_DIV_TOP_004.curValue }}</span>
</li>
</ul> -->
<ul v-if="newAlarm && newAlarm.length !== 0" class="leakage-list">
<li v-for="item in newAlarm" :key="item.SUBID">
<div class="msg-txt">
@ -68,7 +40,6 @@
</div>
</li>
</ul>
</div>
</div>
</el-carousel-item>
@ -203,9 +174,9 @@ import { FetchWaitBorrower } from '@/api/archivesManage/lendManage'
// import displayConfigApi from '@/api/storeManage/displayConfig'
// import thirdApi from '@/api/thirdApi'
import alarmApi from '@/api/home/alarm'
import { allDeviceData, mockIpData } from '@/views/environmentalScreen/index.js'
// import { allDeviceData, mockIpData } from '@/views/environmentalScreen/index.js'
// // mock
// mock
// const mockFetchDataForIP = (params) => {
// return new Promise((resolve) => {
// setTimeout(() => {
@ -241,58 +212,6 @@ export default {
displayConfigData: [],
url: '',
allDeviceIds: [],
oaoMessage: {
ZLS_MO_OAO_001: {
show: false,
wendu: '',
sidu: '',
alarmState: 0
},
YLS_MO_OAO_001: {
show: false,
wendu: '',
sidu: '',
alarmState: 0
}
},
topDisplayData: {
DAK_DIV_TOP_001: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_002: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_003: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_004: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_005: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_006: {
show: false,
curValue: '',
unit: '',
curstatus: 0
}
},
// FullView
newAlarm: [],
aqiValue: 45,
@ -310,7 +229,8 @@ export default {
ipToNameMap: {}, // IP
currentDeviceName: '', //
currentIpIndex: 0, // IP
excludeIpList: ['192.168.99.101:6003'] // IP
excludeIpList: ['192.168.99.101:6003'], // IP
dataTimer: null //
}
},
computed: {
@ -318,45 +238,48 @@ export default {
'roles'
])
},
beforeDestroy() {
if (this.dataTimer) {
clearInterval(this.dataTimer)
this.dataTimer = null
console.log('轮询定时器已清除')
}
},
async created() {
this.getWaitBorrower()
// console.log('allDeviceData:', allDeviceData)
// this.allDisplayConfigData = allDeviceData
// this.handleDeviceIpList()
//
await alarmApi.FetchYpGetSite().then((data) => {
// if (data && data.length > 0) {
// this.allDisplayConfigData = data
// // IP
// this.handleDeviceIpList()
// } else {
// this.allDisplayConfigData = []
// }
this.allDisplayConfigData = allDeviceData
this.handleDeviceIpList()
if (data && data.length > 0) {
this.allDisplayConfigData = data
// IP
this.handleDeviceIpList()
} else {
this.allDisplayConfigData = []
}
// this.allDisplayConfigData = allDeviceData
// this.handleDeviceIpList()
})
//
// +
if (this.allDeviceIds.length > 0) {
this.currentDeviceName = this.ipToNameMap[this.allDeviceIds[0]] || ''
await this.getRealTimeData(this.allDeviceIds[0])
console.log('初始加载IP数据:', this.allDeviceIds[0])
} else {
console.warn('无有效设备IP,停止轮询')
this.newAlarm = []
}
},
mounted() {
if (this.allDeviceIds.length > 0) {
//
this.dataTimer = setInterval(async() => {
const currentIp = this.getNextIp()
this.currentDeviceName = this.ipToNameMap[currentIp] || ''
await this.getRealTimeData(currentIp)
}, 10000)
console.log(`启动IP轮询,共${this.allDeviceIds.length}个有效IP:`, this.allDeviceIds)
} else {
console.warn('无有效设备IP,停止轮询')
this.newAlarm = []
}
},
mounted() {
},
methods: {
/**
* 处理设备IP列表去重+排除+名称映射
@ -385,6 +308,8 @@ export default {
*/
getNextIp() {
if (this.allDeviceIds.length === 0) return ''
//
this.currentIpIndex = this.currentIpIndex % this.allDeviceIds.length
const ip = this.allDeviceIds[this.currentIpIndex]
this.currentIpIndex = (this.currentIpIndex + 1) % this.allDeviceIds.length
console.log(`轮询切换 - 当前IP:${ip},下一个索引:${this.currentIpIndex}`)

826
src/views/home.vue

@ -8,7 +8,7 @@
<div class="container-left" style="height: 100%;margin: 0; position: relative;">
<span class="right-top-line" />
<span class="left-bottom-line" />
<h3 class=" table-title" style="margin-bottom: 26px;">
<h3 class=" table-title" style="margin-bottom:26px;">
<p class="title-arrow">
档案检索
</p>
@ -26,49 +26,87 @@
</p>
</h3>
<div class="home-floor-tab">
<p :class="{ 'active-floor': floorEnvIndex == 0 }" @click="changeFloorEnvTab(0)">3楼</p>
<!-- :class="{ 'active-floor': floorEnvIndex == 0 }" @click="changeFloorEnvTab(0)" -->
<p :class="{ 'active-floor': floorEnvIndex == 0 || floorEnvIndex == 1 }">3</p>
</div>
<el-carousel ref="carouselEnvRef" trigger="click" :interval="10000" indicator-position="none" height="110px" arrow="never" @change="handleEnvChange">
<!-- 环境数据轮播容器隐藏指示器分屏展示温湿度 + 其他指标 -->
<el-carousel
ref="carouselEnvRef"
trigger="click"
:interval="5000"
indicator-position="none"
height="110px"
arrow="hover"
@change="handleEnvChange"
>
<!-- 第一屏温湿度 -->
<el-carousel-item>
<div class="warehouse-tab" style="display: flex; justify-content: center; align-items: center; height: calc(100%); ">
<div class="five-bottom">
<!-- <p class="env-title">档案库</p> -->
<!-- <ul class="leakage-list">
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_001.curstatus > 0 }">
<p>温度</p>
<span>{{ topDisplayData.DAK_DIV_TOP_001.curValue }}</span>
<div class="warehouse-tab" style="display: flex; justify-content: center; align-items: center; height: 100%;">
<div v-if="hasValidData" class="env-alarm-container env-humiture-container">
<ul class="env-alarm-list env-humiture-list">
<li>
<svg-icon icon-class="temperature" class-name="msg-list-svg" />
<div>
<span>{{ avgData.temperature }} </span>
<p>温度 {{ avgData.temperatureUnit }}</p>
</div>
</li>
<li>
<svg-icon icon-class="shidu" class-name="msg-list-svg" />
<div>
<span>{{ avgData.humidity }}</span>
<p>湿度 {{ avgData.humidityUnit }}</p>
</div>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_002.curstatus > 0 }">
<p>湿度</p>
<span>{{ topDisplayData.DAK_DIV_TOP_002.curValue }}</span>
</ul>
</div>
<div v-else class="empty-main" style="height: 100%; display: flex; align-items: center; justify-content: center;">
<svg-icon icon-class="empty" class-name="empty-img" />
</div>
</div>
</el-carousel-item>
<!-- 第二屏env-alarm-list-second 内容 -->
<el-carousel-item>
<div class="warehouse-tab" style="display: flex; justify-content: center; align-items: center; height: 100%;">
<div v-if="hasValidData" class="env-alarm-container">
<ul class="leakage-list env-alarm-list-second">
<li :class="alarmStatus.infrared === '告警' ? 'leakage-warn' : ''">
<p>红外</p>
<span>{{ alarmStatus.infrared }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_003.curstatus > 0 }">
<p>CO2</p>
<span>{{ topDisplayData.DAK_DIV_TOP_003.curValue }}</span>
<li :class="alarmStatus.fire === '告警' ? 'leakage-warn' : ''">
<p>消防</p>
<span>{{ alarmStatus.fire }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_005.curstatus > 0 }">
<p>PM2.5</p>
<span>{{ topDisplayData.DAK_DIV_TOP_005.curValue }}</span>
<li :class="alarmStatus.waterLeak === '告警' ? 'leakage-warn' : ''">
<p>漏水</p>
<span>{{ alarmStatus.waterLeak }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_006.curstatus > 0 }">
<p>PM10</p>
<span>{{ topDisplayData.DAK_DIV_TOP_006.curValue }}</span>
<li>
<p>PM2.5浓度</p>
<span>{{ avgData.pm25 }}{{ avgData.pm25Unit }}</span>
</li>
<li :class="{ 'leakage-warn': topDisplayData.DAK_DIV_TOP_004.curstatus > 0 }">
<li>
<p>TVOC</p>
<span>{{ topDisplayData.DAK_DIV_TOP_004.curValue }}</span>
<span>{{ avgData.tvoc }}{{ avgData.tvocUnit }}</span>
</li>
</ul> -->
<ul v-if="newAlarm && newAlarm.length !== 0" class="leakage-list">
<li v-for="item in newAlarm" :key="item.SUBID">
<div class="msg-txt">
<p>{{ item.subName }}</p>
<span>{{ item.value }}</span>
</div>
<li>
<p>PM10浓度</p>
<span>{{ avgData.pm10 }}{{ avgData.pm10Unit }}</span>
</li>
<li>
<p>二氧化碳</p>
<span>{{ avgData.co2 }}{{ avgData.co2Unit }}</span>
</li>
<li>
<p>甲醛</p>
<span>{{ avgData.formaldehyde }}{{ avgData.formaldehydeUnit }}</span>
</li>
</ul>
</div>
<div v-else class="empty-main" style="height: 100%; display: flex; align-items: center; justify-content: center;">
<svg-icon icon-class="empty" class-name="empty-img" />
</div>
</div>
</el-carousel-item>
@ -86,7 +124,6 @@
</h3>
<div class="home-floor-tab">
<p :class="{ 'active-floor': floorIndex == 0 }" @click="changeFloorTab(0)">3楼</p>
<!-- <p :class="{ 'active-floor': floorIndex == 1 }" @click="changeFloorTab(1)">7楼</p> -->
</div>
<el-carousel ref="carouselRef" trigger="click" :interval="4000" indicator-position="none" height="110px" arrow="never" @change="handleChange">
<el-carousel-item>
@ -132,8 +169,7 @@
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<!-- 门禁记录 -->
<!-- <security-door :height="'calc(100% - 40px)'" /> -->
<AccessDoor :height="'calc(100% - 40px)'" />
<AccessDoor :height="'calc(100% - 40px)'" size="5" />
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<!-- 报警记录 -->
@ -195,17 +231,15 @@ import lendAcross from '@/views/components/echarts/lendAcross.vue'
import catePie from '@/views/components/echarts/catePie.vue'
import typePie from '@/views/components/echarts/typePie.vue'
import WarehouseWarning from '@/views/components/WarehouseWarning'
// import SecurityDoor from '@/views/components/SecurityDoor'
import AccessDoor from '@/views/components/AccessDoor'
import SearchAcrives from '@/views/archivesManage/archivesSearch/index'
import { statisticsCrud } from '@/views/system/archiveStatistics/mixins/statistics'
import { FetchWaitBorrower } from '@/api/archivesManage/lendManage'
// import displayConfigApi from '@/api/storeManage/displayConfig'
// import thirdApi from '@/api/thirdApi'
import alarmApi from '@/api/home/alarm'
import { mapGetters } from 'vuex'
// import { allDeviceData, mockIpData } from '@/views/environmentalScreen/index.js'
// mock
// const mockFetchDataForIP = (params) => {
// return new Promise((resolve) => {
// setTimeout(() => {
@ -215,13 +249,11 @@ import alarmApi from '@/api/home/alarm'
// }, 500)
// })
// }
import { mapGetters } from 'vuex'
export default {
name: 'Dashboard',
components: {
WarehouseWarning,
// SecurityDoor,
AccessDoor,
PanelGroup,
lendAcross,
@ -240,78 +272,58 @@ export default {
allDisplayConfigData: [],
displayConfigData: [],
url: '',
allDeviceIds: [],
oaoMessage: {
ZLS_MO_OAO_001: {
show: false,
wendu: '',
sidu: '',
alarmState: 0
},
YLS_MO_OAO_001: {
show: false,
wendu: '',
sidu: '',
alarmState: 0
}
},
topDisplayData: {
DAK_DIV_TOP_001: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_002: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_003: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_004: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_005: {
show: false,
curValue: '',
unit: '',
curstatus: 0
},
DAK_DIV_TOP_006: {
show: false,
curValue: '',
unit: '',
curstatus: 0
}
},
// FullView
newAlarm: [],
allDeviceIds: [], // IPIP
//
newAlarm: [], //
aqiValue: 45,
aqiStatus: '健康',
aqiStatus: '优',
keepIndicators: [
'二氧化碳',
'CO2浓度',
'甲醛',
'综合气体',
'PM2.5浓度',
'PM10浓度',
'温度',
'湿度',
'空气质量'
'空气质量',
'TVOC',
'红外',
'消防',
'漏水'
],
ipToNameMap: {}, // IP
currentDeviceName: '', //
currentIpIndex: 0, // IP
excludeIpList: ['192.168.99.101:6003'], // IP
dataTimer: null //
//
avgData: {
temperature: '0.00',
temperatureUnit: '',
humidity: '0.00',
humidityUnit: '',
pm25: '0.00',
pm25Unit: '',
tvoc: '0.00',
tvocUnit: '',
pm10: '0.00',
pm10Unit: '',
co2: '0.00',
co2Unit: '',
formaldehyde: '0.00',
formaldehydeUnit: ''
},
//
alarmStatus: {
infrared: '正常',
fire: '正常',
waterLeak: '正常'
},
aqiGradeStandard: [
{ aqiMin: 0, aqiMax: 50, level: '优', colorKey: 'excellent' },
{ aqiMin: 51, aqiMax: 100, level: '良', colorKey: 'good' },
{ aqiMin: 101, aqiMax: 150, level: '轻度污染', colorKey: 'lightPollution' },
{ aqiMin: 151, aqiMax: 200, level: '中度污染', colorKey: 'mediumPollution' },
{ aqiMin: 201, aqiMax: 300, level: '重度污染', colorKey: 'heavyPollution' },
{ aqiMin: 301, aqiMax: 500, level: '严重污染', colorKey: 'severePollution' }
],
hasValidData: false //
}
},
computed: {
@ -320,130 +332,302 @@ export default {
])
},
beforeDestroy() {
if (this.dataTimer) {
clearInterval(this.dataTimer)
this.dataTimer = null
console.log('轮询定时器已清除')
}
//
},
async created() {
//
this.getWaitBorrower()
//
await alarmApi.FetchYpGetSite().then((data) => {
if (data && data.length > 0) {
this.allDisplayConfigData = data
// IP
this.handleDeviceIpList()
} else {
this.allDisplayConfigData = []
}
// this.allDisplayConfigData = allDeviceData
// this.handleDeviceIpList()
})
//
await this.loadAllDeviceConfig()
// +
//
if (this.allDeviceIds.length > 0) {
this.currentDeviceName = this.ipToNameMap[this.allDeviceIds[0]] || ''
await this.getRealTimeData(this.allDeviceIds[0])
//
this.dataTimer = setInterval(async() => {
const currentIp = this.getNextIp()
this.currentDeviceName = this.ipToNameMap[currentIp] || ''
await this.getRealTimeData(currentIp)
}, 10000)
console.log(`启动IP轮询,共${this.allDeviceIds.length}个有效IP:`, this.allDeviceIds)
await this.getAllDevicesData()
// AQI
this.calcAllAvgData()
this.calcAQIByAvg()
} else {
console.warn('无有效设备IP,停止轮询')
this.newAlarm = []
console.warn('无有效设备IP数据')
this.hasValidData = false
}
},
mounted() {
// if (this.allDeviceIds.length > 0) {
// this.dataTimer = setInterval(async() => {
// const currentIp = this.getNextIp()
// this.currentDeviceName = this.ipToNameMap[currentIp] || ''
// await this.getRealTimeData(currentIp)
// }, 10000)
// console.log(`IP${this.allDeviceIds.length}IP`, this.allDeviceIds)
// }
},
methods: {
/**
* 处理设备IP列表去重+排除+名称映射
* 加载所有设备配置数据
*/
async loadAllDeviceConfig() {
// this.allDisplayConfigData = allDeviceData
// this.handleDeviceIpList()
try {
const data = await alarmApi.FetchYpGetSite()
if (data && data.length > 0) {
this.allDisplayConfigData = data
// IPIP
this.handleDeviceIpList()
} else {
this.allDisplayConfigData = []
this.allDeviceIds = []
}
} catch (error) {
console.error('加载设备配置失败:', error)
this.allDisplayConfigData = []
this.allDeviceIds = []
}
},
/**
* 处理设备IP列表仅过滤空IP无其他排除逻辑
*/
handleDeviceIpList() {
const ipSet = new Set()
this.ipToNameMap = {}
this.allDisplayConfigData.forEach(element => {
const ip = (element.IP || '').trim()
if (ip && !this.excludeIpList.includes(ip)) {
if (ip) { // IPIP
ipSet.add(ip)
this.ipToNameMap[ip] = element.Name || `未知设备(${ip})`
console.log('有效设备IP:', ip, '设备名称:', element.Name)
} else if (this.excludeIpList.includes(ip)) {
console.log('排除指定IP:', ip, '设备名称:', element.Name)
} else if (!ip) {
console.log('过滤空IP:', element.Name)
} else {
console.log('过滤空IP设备:', element.Name)
}
})
this.allDeviceIds = Array.from(ipSet)
},
/**
* 获取下一个轮询IP循环切换
* 获取所有设备的实时环境数据
*/
getNextIp() {
if (this.allDeviceIds.length === 0) return ''
//
this.currentIpIndex = this.currentIpIndex % this.allDeviceIds.length
const ip = this.allDeviceIds[this.currentIpIndex]
this.currentIpIndex = (this.currentIpIndex + 1) % this.allDeviceIds.length
console.log(`轮询切换 - 当前IP:${ip},下一个索引:${this.currentIpIndex}`)
return ip
async getAllDevicesData() {
const allData = []
for (const ip of this.allDeviceIds) {
try {
console.log(`请求IP【${ip}】的环境数据`)
//
const data = await alarmApi.FetchDataForIP({ ip })
// const data = await mockFetchDataForIP({ ip })
// CO2
const filteredData = data.filter(item =>
this.keepIndicators.includes(item.subName)
).map(item => {
// CO2
if (item.subName === 'CO2浓度') {
return { ...item, subName: '二氧化碳' }
}
return item
})
if (filteredData.length > 0) {
allData.push(...filteredData)
}
} catch (error) {
console.error(`获取IP【${ip}】数据失败:`, error)
}
}
this.newAlarm = allData
this.hasValidData = allData.length > 0
console.log('所有设备环境数据汇总:', allData)
},
/**
* 请求指定IP的实时数据过滤+AQI计算
* 计算所有设备指标的平均值包含单位处理
*/
async getRealTimeData(targetIp) {
if (!targetIp) {
this.newAlarm = []
this.currentDeviceName = ''
return
calcAllAvgData() {
if (!this.hasValidData) return
const sumMap = {
temperature: { sum: 0, count: 0, unit: '' }, //
humidity: { sum: 0, count: 0, unit: '' }, // 湿
pm25: { sum: 0, count: 0, unit: '' }, // PM2.5
tvoc: { sum: 0, count: 0, unit: '' }, // TVOC
pm10: { sum: 0, count: 0, unit: '' }, // PM10
co2: { sum: 0, count: 0, unit: '' }, //
formaldehyde: { sum: 0, count: 0, unit: '' }, //
infrared: [], //
fire: [], //
waterLeak: [] //
}
try {
console.log(`开始请求IP【${targetIp}】的实时数据(模拟)`)
//
// const data = await mockFetchDataForIP({ ip: targetIp })
//
const data = await alarmApi.FetchDataForIP({ ip: targetIp })
//
const filteredData = data.filter(item =>
this.keepIndicators.includes(item.subName)
)
if (filteredData.length > 0) {
this.newAlarm = filteredData
console.log(`IP【${targetIp}】(${this.currentDeviceName}) 过滤后的数据:`, filteredData)
} else {
this.newAlarm = []
this.aqiValue = 45
this.aqiStatus = '健康'
console.log(`IP【${targetIp}】(${this.currentDeviceName}) 无需要的指标数据`)
//
this.newAlarm.forEach(item => {
const value = parseFloat(item.value) || 0
// 使dw
const unit = item.dw || this.getDefaultUnit(item.subName)
switch (item.subName) {
case '温度':
sumMap.temperature.sum += value
sumMap.temperature.count++
if (!sumMap.temperature.unit && unit) sumMap.temperature.unit = unit
break
case '湿度':
sumMap.humidity.sum += value
sumMap.humidity.count++
if (!sumMap.humidity.unit && unit) sumMap.humidity.unit = unit
break
case '二氧化碳':
sumMap.co2.sum += value
sumMap.co2.count++
if (!sumMap.co2.unit && unit) sumMap.co2.unit = unit
break
case 'PM2.5浓度':
sumMap.pm25.sum += value
sumMap.pm25.count++
if (!sumMap.pm25.unit && unit) sumMap.pm25.unit = unit
break
case 'TVOC':
sumMap.tvoc.sum += value
sumMap.tvoc.count++
if (!sumMap.tvoc.unit && unit) sumMap.tvoc.unit = unit
break
case 'PM10浓度':
sumMap.pm10.sum += value
sumMap.pm10.count++
if (!sumMap.pm10.unit && unit) sumMap.pm10.unit = unit
break
case '甲醛':
sumMap.formaldehyde.sum += value
sumMap.formaldehyde.count++
if (!sumMap.formaldehyde.unit && unit) sumMap.formaldehyde.unit = unit
break
//
case '红外':
sumMap.infrared.push(item.value)
break
case '消防':
sumMap.fire.push(item.value)
break
case '漏水':
sumMap.waterLeak.push(item.value)
break
}
} catch (error) {
this.newAlarm = []
})
//
this.avgData = {
temperature: sumMap.temperature.count ? (sumMap.temperature.sum / sumMap.temperature.count).toFixed(2) : '0.00',
temperatureUnit: sumMap.temperature.unit || '℃',
humidity: sumMap.humidity.count ? (sumMap.humidity.sum / sumMap.humidity.count).toFixed(2) : '0.00',
humidityUnit: sumMap.humidity.unit || '%',
pm25: sumMap.pm25.count ? (sumMap.pm25.sum / sumMap.pm25.count).toFixed(2) : '0.00',
pm25Unit: sumMap.pm25.unit || 'ug/立方米',
tvoc: sumMap.tvoc.count ? (sumMap.tvoc.sum / sumMap.tvoc.count).toFixed(2) : '0.00',
tvocUnit: sumMap.tvoc.unit || 'LuK',
pm10: sumMap.pm10.count ? (sumMap.pm10.sum / sumMap.pm10.count).toFixed(2) : '0.00',
pm10Unit: sumMap.pm10.unit || 'ug/立方米',
co2: sumMap.co2.count ? (sumMap.co2.sum / sumMap.co2.count).toFixed(2) : '0.00',
co2Unit: sumMap.co2.unit || 'ppm',
formaldehyde: sumMap.formaldehyde.count ? (sumMap.formaldehyde.sum / sumMap.formaldehyde.count).toFixed(2) : '0.00',
formaldehydeUnit: sumMap.formaldehyde.unit || 'ppm'
}
// ON
this.alarmStatus = {
infrared: sumMap.infrared.some(s => s === 'ON') ? '告警' : '正常',
fire: sumMap.fire.some(s => s === 'ON') ? '告警' : '正常',
waterLeak: sumMap.waterLeak.some(s => s === 'ON') ? '告警' : '正常'
}
//
if (sumMap.infrared.length === 0) this.alarmStatus.infrared = '正常'
if (sumMap.fire.length === 0) this.alarmStatus.fire = '正常'
if (sumMap.waterLeak.length === 0) this.alarmStatus.waterLeak = '正常'
},
/**
* 获取指标默认单位兜底用
*/
getDefaultUnit(subName) {
const unitMap = {
'温度': '℃',
'湿度': '%',
'PM2.5浓度': 'ug/立方米',
'TVOC': 'LuK',
'PM10浓度': 'ug/立方米',
'二氧化碳': 'ppm',
'CO2浓度': 'ppm',
'甲醛': 'ppm',
'综合气体': '无量纲'
}
return unitMap[subName] || ''
},
/**
* 根据所有设备的平均值计算AQI空气质量指数
*/
calcAQIByAvg() {
if (!this.hasValidData) {
this.aqiValue = 45
this.aqiStatus = '健康'
this.currentDeviceName = ''
console.error(`IP【${targetIp}】数据请求失败:`, error)
this.aqiStatus = '优'
return
}
// PM2.5PM100
const pm25 = parseFloat(this.avgData.pm25) || 0
const pm10 = parseFloat(this.avgData.pm10) || 0
// AQI24μg/m³
const aqiBpTable = {
pm25: [
{ iaqiLo: 0, iaqiHi: 50, bpLo: 0, bpHi: 35 }, //
{ iaqiLo: 50, iaqiHi: 100, bpLo: 35, bpHi: 75 }, //
{ iaqiLo: 100, iaqiHi: 150, bpLo: 75, bpHi: 115 }, //
{ iaqiLo: 150, iaqiHi: 200, bpLo: 115, bpHi: 150 }, //
{ iaqiLo: 200, iaqiHi: 300, bpLo: 150, bpHi: 250 }, //
{ iaqiLo: 300, iaqiHi: 500, bpLo: 250, bpHi: 500 } //
],
pm10: [
{ iaqiLo: 0, iaqiHi: 50, bpLo: 0, bpHi: 50 }, //
{ iaqiLo: 50, iaqiHi: 100, bpLo: 50, bpHi: 150 }, //
{ iaqiLo: 100, iaqiHi: 150, bpLo: 150, bpHi: 250 }, //
{ iaqiLo: 150, iaqiHi: 200, bpLo: 250, bpHi: 350 }, //
{ iaqiLo: 200, iaqiHi: 300, bpLo: 350, bpHi: 420 }, //
{ iaqiLo: 300, iaqiHi: 500, bpLo: 420, bpHi: 500 } //
]
}
// IAQI
const calculateIAQI = (conc, pollutantType) => {
const bpTable = aqiBpTable[pollutantType]
// 500
if (conc > bpTable[bpTable.length - 1].bpHi) {
return 500
}
//
const matchedBp = bpTable.find(item => conc >= item.bpLo && conc <= item.bpHi) || bpTable[0]
// IAQI
const iaqi = ((matchedBp.iaqiHi - matchedBp.iaqiLo) / (matchedBp.bpHi - matchedBp.bpLo)) * (conc - matchedBp.bpLo) + matchedBp.iaqiLo
// 500
return Math.min(Math.round(iaqi), 500)
}
// PM2.5PM10
const iaqiPm25 = calculateIAQI(pm25, 'pm25')
const iaqiPm10 = calculateIAQI(pm10, 'pm10')
// AQI
const finalAQI = Math.max(iaqiPm25, iaqiPm10)
this.aqiValue = finalAQI
// AQI
const matchedGrade = this.aqiGradeStandard.find(grade =>
finalAQI >= grade.aqiMin && finalAQI <= grade.aqiMax
)
this.aqiStatus = matchedGrade ? matchedGrade.level : '严重污染'
console.log('AQI计算结果:', {
pm25,
pm10,
iaqiPm25,
iaqiPm10,
finalAQI,
aqiStatus: this.aqiStatus
})
},
//
handleChange(index) {
this.floorIndex = index
},
@ -460,9 +644,6 @@ export default {
const carousel = this.$refs.carouselEnvRef
carousel.setActiveItem(index)
},
// handleSetLineChartData(type) {
// this.lineChartData = lineChartData[type]
// },
getWaitBorrower() {
FetchWaitBorrower().then(data => {
if (data) {
@ -488,10 +669,6 @@ export default {
},
handleToWaiting(item) {
if (this.roles.includes('admin') || this.roles.includes('lendManage:list')) {
// 0
// 1
// 2
// 3
let locationIndex = 0
if (item.title.includes('待借档案')) {
locationIndex = 0
@ -599,7 +776,6 @@ export default {
.container-wrap {
min-height: auto;
height: 100%;
// overflow: hidden;
}
.todo-list {
padding: 0 20px;
@ -631,7 +807,6 @@ export default {
float: right;
padding-right: 10px;
}
}
}
::v-deep
@ -697,27 +872,257 @@ export default {
font-size: 12px;
margin: 10px 10px 0 0;
}
//
.env-alarm-container {
position: relative;
width: 100%;
padding: 0 10px;
box-sizing: border-box;
}
// 湿
.env-humiture-container {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.env-humiture-list {
width: 80% !important;
justify-content: space-around !important;
li {
width: 45% !important;
height: 66px !important;
flex-direction: row !important;
.msg-list-svg {
font-size: 24px !important;
margin-right: 10px !important;
}
div {
span {
font-size: 20px !important;
font-weight: bold;
margin-top: 0 !important;
}
p {
font-size: 12px !important;
color: #339CFF;
margin-top: 4px;
}
}
}
}
.env-alarm-list{
display: flex;
justify-content: flex-start;
width: 100%;
padding: 0;
margin: 0;
list-style: none;
li{
display: flex;
flex-direction: column;
align-items: center;
align-content: center;
justify-content: center;
height: 70px;
margin-right: 10px;
background: url('~@/assets/images/data_border_default.png') no-repeat;
background-size: 100% 100%;
position: relative;
color: #fff;
font-size: 14px;
&.li-warn{
background: url('~@/assets/images/data_border_warn.png') no-repeat;
background-size: 100% 100%;
}
p{
color: #339CFF;
margin: 0;
}
span{
display: block;
margin-top: 12px;
font-weight: bold;
}
}
}
.env-alarm-list-second {
flex-wrap: wrap !important;
align-items: center;
justify-content: center;
li {
width: calc(100% / 4 - 20px) !important;
height: 40px !important;
font-size: 10px !important;
margin-bottom: 6px;
p {
font-size: 10px !important;
}
span {
margin-top: 6px !important;
font-size: 12px !important;
}
}
}
//
::v-deep .el-carousel__arrow {
width: 24px;
height: 24px;
background-color: rgba(51, 156, 255, 0.3);
&:hover {
background-color: rgba(51, 156, 255, 0.6);
}
}
.air-quality{
position: absolute;
bottom: 0;
right: 10px;
color: #fff;
padding: 10px;
background-image: linear-gradient(to top, rgba(24, 176, 143, .5), rgba(24, 176, 143, 0));
border-radius: 5px;
z-index: 9999;
width: 200px;
h3{
padding: 5px 0;
font-size: 12px;
margin: 0;
text-align: center;
}
.air-params{
display: flex;
justify-content: space-between;
align-items: last baseline;
flex-wrap: wrap;
.air-left{
width: 100%;
.air-title{
position: relative;
padding-left: 8px;
font-size: 10px;
&::before{
content: "";
position: absolute;
left: 0;
top: 50%;
width: 4px;
height: 4px;
background-color: #18B08F;
border-radius: 50%;
transform: translateY(-50%);
}
}
.air-result{
display: flex;
justify-content: flex-start;
align-items: last baseline;
padding-top: 5px;
p{
font-size: 18px;
font-weight: 600;
padding: 0 4px 0 8px;
margin: 0;
}
span{
display: block;
font-size: 8px;
opacity: .6;
}
}
}
.air-right{
width: 100%;
text-align: center;
margin-top: 5px;
span{
display: block;
font-size: 10px;
}
p{
font-size: 12px;
font-weight: 600;
padding: 5px 10px;
margin: 5px 0 0 0;
background-color: rgba(24, 176, 143, .2);
border-radius: 3px;
}
}
}
&.air-excellent {
background-image: linear-gradient(to top, rgba(40, 180, 40, .5), rgba(40, 180, 40, 0));
.air-params .air-right p {
background-color: rgba(40, 180, 40, .2);
}
}
&.air-good {
background-image: linear-gradient(to top, rgba(255, 200, 0, .5), rgba(255, 200, 0, 0));
.air-params .air-right p {
background-color: rgba(255, 200, 0, .2);
}
}
&.air-lightPollution {
background-image: linear-gradient(to top, rgba(255, 140, 0, .5), rgba(255, 140, 0, 0));
.air-params .air-right p {
background-color: rgba(255, 140, 0, .2);
}
}
&.air-mediumPollution {
background-image: linear-gradient(to top, rgba(255, 0, 0, .5), rgba(255, 0, 0, 0));
.air-params .air-right p {
background-color: rgba(255, 0, 0, .2);
}
}
&.air-heavyPollution {
background-image: linear-gradient(to top, rgba(150, 0, 200, .5), rgba(150, 0, 200, 0));
.air-params .air-right p {
background-color: rgba(150, 0, 200, .2);
}
}
&.air-severePollution {
background-image: linear-gradient(to top, rgba(120, 0, 0, .5), rgba(120, 0, 0, 0));
.air-params .air-right p {
background-color: rgba(120, 0, 0, .2);
}
}
}
.empty-main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
.empty-img {
width: 40px;
height: 40px;
margin-bottom: 10px;
}
p {
font-size: 12px;
margin: 0;
}
}
.leakage-list {
display: flex;
justify-content:flex-start;
flex-wrap: wrap;
justify-content: center;
align-items: center;
flex: 1;
text-align: left;
font-size: 10px;
padding-left: 10px;
li {
position: relative;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
align-items: center;
width: 72px;
width: 60px;
height: 40px;
border: 1px solid #3581cc;
background-color: #02255f;
border-radius: 2px;
padding: 4px;
margin: 6px 10px 0 0;
padding: 4px 6px;
margin: 0 10px 10px 0;
font-size: 12px;
&::before {
content: "";
@ -751,13 +1156,4 @@ export default {
}
}
}
.five-bottom{
display: flex;
justify-content: flex-start;
align-items: center;
.env-title{
line-height: 40px;
}
}
</style>

210
src/views/storeManage/warehouse3D/archivesStorage/index.js

@ -1,131 +1,4 @@
export const allDeviceData = [
{
'id': 1,
'ParentID': 0,
'SubClass': 0,
'IP': '',
'Name': '环境监控',
'NetStatus': 1,
'SUBTYPE': '1'
},
{
'id': 11303,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.101:5005',
'Name': '温湿度',
'NetStatus': 1,
'SUBTYPE': '17'
},
{
'id': 11519,
'ParentID': 1,
'SubClass': 0,
'IP': '',
'Name': '空调红外控制',
'NetStatus': 1,
'SUBTYPE': '1'
},
{
'id': 11520,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.101:6003',
'Name': '开关量',
'NetStatus': 1,
'SUBTYPE': '11'
},
{
'id': 11605,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.000',
'Name': 'PM2.5 浓度',
'NetStatus': 1,
'SUBTYPE': '101'
},
{
'id': 11606,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.001',
'Name': 'PM10浓度',
'NetStatus': 1,
'SUBTYPE': '101'
},
{
'id': 11607,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.002',
'Name': 'TWOC',
'NetStatus': 1,
'SUBTYPE': '101'
},
{
'id': 11608,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.003',
'Name': '二氧化碳',
'NetStatus': 1,
'SUBTYPE': '101'
},
{
'id': 11609,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.004',
'Name': '甲醛',
'NetStatus': 1,
'SUBTYPE': '101'
},
{
'id': 11682,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.101:5004',
'Name': '壁挂升降空气净化机',
'NetStatus': 1,
'SUBTYPE': '11'
},
{
'id': 11695,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.101:5003',
'Name': '恒湿净化一体机',
'NetStatus': 1,
'SUBTYPE': '11'
},
{
'id': 11728,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.102:5005',
'Name': '环境监测1',
'NetStatus': 1,
'SUBTYPE': '25'
},
{
'id': 11800,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.102:5003.3',
'Name': '环境监测3_3',
'NetStatus': 1,
'SUBTYPE': '25'
},
{
'id': 11824,
'ParentID': 1,
'SubClass': 0,
'IP': '192.168.99.102:5004.2',
'Name': '环境监测2_2',
'NetStatus': 1,
'SUBTYPE': '25'
}
]
export const allDeviceData = [{ 'id': 1, 'ParentID': 0, 'SubClass': 0, 'IP': '', 'Name': '环境监控', 'NetStatus': 1, 'SUBTYPE': '1' }, { 'id': 11303, 'ParentID': 1, 'SubClass': 0, 'IP': '192.168.99.101:5005', 'Name': '温湿度', 'NetStatus': 1, 'SUBTYPE': '17' }, { 'id': 11355, 'ParentID': 1, 'SubClass': 0, 'IP': '192.168.99.102:5003:3', 'Name': '环境监测3_3', 'NetStatus': 1, 'SUBTYPE': '25' }, { 'id': 11379, 'ParentID': 1, 'SubClass': 0, 'IP': '192.168.99.102:5004:2', 'Name': '环境监测2_2', 'NetStatus': 1, 'SUBTYPE': '25' }, { 'id': 11403, 'ParentID': 1, 'SubClass': 0, 'IP': '192.168.99.102:5005', 'Name': '环境监测1', 'NetStatus': 1, 'SUBTYPE': '25' }, { 'id': 11440, 'ParentID': 1, 'SubClass': 0, 'IP': '192.168.99.101:5004', 'Name': '壁挂升降空气净化机', 'NetStatus': 1, 'SUBTYPE': '11' }, { 'id': 11486, 'ParentID': 1, 'SubClass': 0, 'IP': '192.168.99.101:5003', 'Name': '恒湿净化一体机', 'NetStatus': 1, 'SUBTYPE': '11' }, { 'id': 11519, 'ParentID': 1, 'SubClass': 0, 'IP': '', 'Name': '空调红外控制', 'NetStatus': 1, 'SUBTYPE': '1' }, { 'id': 11520, 'ParentID': 1, 'SubClass': 0, 'IP': '192.168.99.101:6003', 'Name': '开关量', 'NetStatus': 0, 'SUBTYPE': '11' }]
export const mockIpData = {
// 温湿度
@ -150,7 +23,88 @@ export const mockIpData = {
'dw': '℃',
'SUBID': 2,
'TIME': '2025-12-11 13:22:31'
},
{
'IP': '192.168.99.101:6003',
'subName': '红外',
'WYID': '192.168.99.101:6003_9',
'value': 'ON',
'dw': '',
'SUBID': 9,
'TIME': '2025-12-11 13:25:55'
},
{
'IP': '192.168.99.101:6003',
'subName': '消防',
'WYID': '192.168.99.101:6003_10',
'value': 'OFF',
'dw': '',
'SUBID': 10,
'TIME': '2025-12-11 13:25:55'
},
{
'IP': '192.168.99.101:6003',
'subName': '漏水',
'WYID': '192.168.99.101:6003_11',
'value': 'OFF',
'dw': '',
'SUBID': 11,
'TIME': '2025-12-11 13:25:55'
}
// {
// 'IP': '192.168.99.101:5003',
// 'subName': '二氧化碳',
// 'WYID': '192.168.99.101:5003_1',
// 'value': '593.00',
// 'dw': 'ppm',
// 'SUBID': 1,
// 'TIME': '2025-12-11 13:25:09'
// },
// {
// 'IP': '192.168.99.101:5003',
// 'subName': '甲醛',
// 'WYID': '192.168.99.101:5003_2',
// 'value': '20.00',
// 'dw': 'mg/m3',
// 'SUBID': 2,
// 'TIME': '2025-12-11 13:25:09'
// },
// {
// 'IP': '192.168.99.101:5003',
// 'subName': '综合气体',
// 'WYID': '192.168.99.101:5003_3',
// 'value': '140.00',
// 'dw': 'ppm',
// 'SUBID': 3,
// 'TIME': '2025-12-11 13:25:09'
// },
// {
// 'IP': '192.168.99.101:5003',
// 'subName': 'PM2.5浓度',
// 'WYID': '192.168.99.101:5003_4',
// 'value': '82.00',
// 'dw': 'ppm',
// 'SUBID': 4,
// 'TIME': '2025-12-11 13:25:09'
// },
// {
// 'IP': '192.168.99.101:5003',
// 'subName': 'PM10浓度',
// 'WYID': '192.168.99.101:5003_5',
// 'value': '101.00',
// 'dw': 'ppm',
// 'SUBID': 5,
// 'TIME': '2025-12-11 13:25:09'
// },
// {
// 'IP': '192.168.99.101:5003',
// 'subName': 'PM10浓度',
// 'WYID': '192.168.99.101:5003_5',
// 'value': '101.00',
// 'dw': 'ppm',
// 'SUBID': 5,
// 'TIME': '2025-12-11 13:25:09'
// }
],
'timestamp': 1765430551410
},

365
src/views/storeManage/warehouse3D/archivesStorage/index.vue

@ -4,29 +4,43 @@
<div class="left-3d">
<iframe id="myIframe" ref="myIframe" name="iframeMap" class="iframe_box" src="/web3D/index.html" frameborder="0" scrolling="no" />
<ul v-if="newAlarm && newAlarm.length !== 0" class="msg-list">
<li v-for="item in newAlarm" :key="item.SUBID">
<svg-icon v-if="item.subName === '温度'" icon-class="temperature" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '湿度'" icon-class="shidu" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === 'PM2.5浓度'" icon-class="pm25" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === 'PM10浓度'" icon-class="pm10" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === 'TVOC'" icon-class="voc" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '二氧化碳'" icon-class="co2" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '甲醛'" icon-class="jiaquan" class-name="msg-list-svg" style="width: 2em; margin-left: 20px;" />
<svg-icon v-if="item.subName === '综合气体'" icon-class="comprehensive-gas" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '空气质量'" icon-class="kongqi" class-name="msg-list-svg" />
<div class="msg-txt">
<span class="msg-list-num">{{ item.value }}</span>
<p class="msg-list-unit">{{ item.subName }} {{ item.dw }}</p>
</div>
</li>
</ul>
<div v-if="newAlarm && newAlarm.length !== 0" class="air-quality" :class="{'air-warn': aqiStatus === '污染'}">
<div style="position: absolute; top: 0; left: 0;">
<p style="font-size: 12px; margin-bottom: 10px;">{{ currentDeviceName }}</p>
<ul v-if="newAlarm && newAlarm.length !== 0" class="msg-list">
<li v-for="item in newAlarm" :key="item.SUBID">
<svg-icon v-if="item.subName === '温度'" icon-class="temperature" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '湿度'" icon-class="shidu" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === 'PM2.5浓度'" icon-class="pm25" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === 'PM10浓度'" icon-class="pm10" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === 'TVOC'" icon-class="voc" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '二氧化碳'" icon-class="co2" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '甲醛'" icon-class="jiaquan" class-name="msg-list-svg" style="width: 2em; margin-left: 20px;" />
<svg-icon v-if="item.subName === '综合气体'" icon-class="comprehensive-gas" class-name="msg-list-svg" />
<svg-icon v-if="item.subName === '空气质量'" icon-class="kongqi" class-name="msg-list-svg" />
<div class="msg-txt">
<span class="msg-list-num">{{ item.value }}</span>
<p class="msg-list-unit">{{ item.subName }} {{ item.dw }}</p>
</div>
</li>
</ul>
</div>
<div
v-if="hasValidData"
class="air-quality"
:class="[
aqiStatus === '优' ? 'air-excellent' : '',
aqiStatus === '良' ? 'air-good' : '',
aqiStatus === '轻度污染' ? 'air-lightPollution' : '',
aqiStatus === '中度污染' ? 'air-mediumPollution' : '',
aqiStatus === '重度污染' ? 'air-heavyPollution' : '',
aqiStatus === '严重污染' ? 'air-severePollution' : ''
]"
>
<h3>实时空气质量指数AQI</h3>
<div class="air-params">
<div class="air-left">
<span class="air-title">实时AQI</span>
<div class="air-result"><p>{{ aqiValue }}</p><span>(AQI-US)</span></div>
<div class="air-result"><p>{{ aqiValue }}</p><span>(AQI-中国标准)</span></div>
</div>
<div class="air-right">
<span>空气质量为</span>
@ -34,6 +48,7 @@
</div>
</div>
</div>
</div>
</div>
<div class="warehouse-right">
@ -69,25 +84,17 @@ export default {
roomId: '01A1DC2123C2B75E1A579D',
allDisplayConfigData: [],
displayConfigData: [],
originalAllDeviceIds: [],
allDeviceIds: [],
currentIpIndex: 0,
excludeIpList: [
'192.168.99.101:6003'
],
oaoMessage: [],
timer: '',
topDisplayData: {
DAK_DIV_TOP_001: { show: true, curValue: '23.10', unit: '℃', curstatus: 0 },
DAK_DIV_TOP_002: { show: true, curValue: '48.90', unit: '%', curstatus: 0 },
DAK_DIV_TOP_003: { show: true, curValue: '619', unit: 'ppm', curstatus: 0 },
DAK_DIV_TOP_004: { show: true, curValue: '0.21', unit: 'mg/m³', curstatus: 0 },
DAK_DIV_TOP_005: { show: true, curValue: '26.00', unit: 'ug/m³', curstatus: 0 },
DAK_DIV_TOP_006: { show: true, curValue: '38.00', unit: 'ug/m³', curstatus: 0 }
},
open: false,
newAlarm: [],
aqiValue: 45,
aqiStatus: '健康',
aqiStatus: '优',
keepIndicators: [
'二氧化碳',
'甲醛',
@ -98,17 +105,47 @@ export default {
'湿度',
'空气质量'
],
aqiGradeStandard: [
{ aqiMin: 0, aqiMax: 50, level: '优', colorKey: 'excellent' },
{ aqiMin: 51, aqiMax: 100, level: '良', colorKey: 'good' },
{ aqiMin: 101, aqiMax: 150, level: '轻度污染', colorKey: 'lightPollution' },
{ aqiMin: 151, aqiMax: 200, level: '中度污染', colorKey: 'mediumPollution' },
{ aqiMin: 201, aqiMax: 300, level: '重度污染', colorKey: 'heavyPollution' },
{ aqiMin: 301, aqiMax: 500, level: '严重污染', colorKey: 'severePollution' }
],
aqiBpTable: {
pm25: [
{ iaqiLo: 0, iaqiHi: 50, bpLo: 0, bpHi: 35 }, //
{ iaqiLo: 50, iaqiHi: 100, bpLo: 35, bpHi: 75 }, //
{ iaqiLo: 100, iaqiHi: 150, bpLo: 75, bpHi: 115 }, //
{ iaqiLo: 150, iaqiHi: 200, bpLo: 115, bpHi: 150 }, //
{ iaqiLo: 200, iaqiHi: 300, bpLo: 150, bpHi: 250 }, //
{ iaqiLo: 300, iaqiHi: 500, bpLo: 250, bpHi: 500 } //
],
pm10: [
{ iaqiLo: 0, iaqiHi: 50, bpLo: 0, bpHi: 50 }, //
{ iaqiLo: 50, iaqiHi: 100, bpLo: 50, bpHi: 150 }, //
{ iaqiLo: 100, iaqiHi: 150, bpLo: 150, bpHi: 250 }, //
{ iaqiLo: 150, iaqiHi: 200, bpLo: 250, bpHi: 350 }, //
{ iaqiLo: 200, iaqiHi: 300, bpLo: 350, bpHi: 420 }, //
{ iaqiLo: 300, iaqiHi: 500, bpLo: 420, bpHi: 500 } //
]
},
// IP
ipToNameMap: {},
//
currentDeviceName: ''
currentDeviceName: '',
aqiTimer: null,
// PM2.5/PM10
allDevicesPollutantData: [],
hasValidData: false
}
},
async created() {
window.getIframeLoading = this.getIframeLoading
//
// this.allDisplayConfigData = allDeviceData
//
// this.handleDeviceIpList()
await alarmApi.FetchYpGetSite().then((data) => {
if (data && data.length > 0) {
this.allDisplayConfigData = data
@ -117,15 +154,15 @@ export default {
this.allDisplayConfigData = []
}
})
// this.allDisplayConfigData = allDeviceData
// this.handleDeviceIpList()
// +
await this.getAllDevicesPollutantData()
this.calcGlobalAQI()
if (this.allDeviceIds.length > 0) {
this.currentDeviceName = this.ipToNameMap[this.allDeviceIds[0]] || ''
await this.getRealTimeData(this.allDeviceIds[0])
//
// msg-listAQI
this.timer = setInterval(async() => {
const currentIp = this.getNextIp()
this.currentDeviceName = this.ipToNameMap[currentIp] || ''
@ -136,47 +173,63 @@ export default {
console.warn('无有效设备IP,停止轮询')
this.newAlarm = []
}
// AQIAQI
// if (this.allDeviceIds.length > 0) {
// this.aqiTimer = setInterval(async() => {
// await this.getAllDevicesPollutantData()
// this.calcGlobalAQI()
// }, 30000)
// console.log('AQI30/')
// }
},
mounted() {
const _this = this
_this.iframeWin = this.$refs.myIframe.contentWindow
window.addEventListener('message', this.handleMessageEvent)
// if (this.allDeviceIds.length > 0) {
// this.timer = setInterval(async() => {
// const currentIp = _this.getNextIp()
// //
// _this.currentDeviceName = _this.ipToNameMap[currentIp] || ''
// await _this.getRealTimeData(currentIp)
// }, 10000)
// console.log(`IP${this.allDeviceIds.length}IP`, this.allDeviceIds)
// }
},
beforeDestroy() {
//
if (this.timer) {
clearInterval(this.timer)
console.log('停止IP轮询')
}
// AQI
if (this.aqiTimer) {
clearInterval(this.aqiTimer)
console.log('停止全量AQI计算定时器')
}
window.removeEventListener('message', this.handleMessageEvent)
},
methods: {
handleDeviceIpList() {
const ipSet = new Set()
const filteredIpSet = new Set() // IP
const originalIpSet = new Set() // IPAQI
this.ipToNameMap = {}
this.allDisplayConfigData.forEach(element => {
const ip = (element.IP || '').trim()
if (ip && !this.excludeIpList.includes(ip)) {
ipSet.add(ip)
if (ip) {
// 1. IPIPAQI
originalIpSet.add(ip)
// 2. IPIP
if (!this.excludeIpList.includes(ip)) {
filteredIpSet.add(ip)
} else {
console.log('轮询排除IP:', ip, '设备名称:', element.Name)
}
// IPIP
this.ipToNameMap[ip] = element.Name || `未知设备(${ip})`
console.log('有效设备IP:', ip, '设备名称:', element.Name)
} else if (this.excludeIpList.includes(ip)) {
console.log('排除指定IP:', ip, '设备名称:', element.Name)
} else if (!ip) {
console.log('有效设备IP(AQI计算包含):', ip, '设备名称:', element.Name)
} else {
console.log('过滤空IP:', element.Name)
}
})
this.allDeviceIds = Array.from(ipSet)
// IPIPAQI
this.allDeviceIds = Array.from(filteredIpSet) //
this.originalAllDeviceIds = Array.from(originalIpSet) // AQI
console.log(`轮询IP列表(过滤后):`, this.allDeviceIds)
console.log(`AQI计算IP列表(原始):`, this.originalAllDeviceIds)
},
/**
@ -246,7 +299,6 @@ export default {
try {
console.log(`开始请求IP【${targetIp}】的实时数据(模拟)`)
//
// const data = await mockFetchDataForIP({ ip: targetIp })
//
const data = await alarmApi.FetchDataForIP({ ip: targetIp })
@ -258,43 +310,137 @@ export default {
if (filteredData.length > 0) {
this.newAlarm = filteredData
console.log(`IP【${targetIp}】(${this.currentDeviceName}) 过滤后的数据:`, filteredData)
this.calcAQI(filteredData)
} else {
this.newAlarm = []
this.aqiValue = 45
this.aqiStatus = '健康'
console.log(`IP【${targetIp}】(${this.currentDeviceName}) 无需要的指标数据`)
}
} catch (error) {
this.newAlarm = []
this.aqiValue = 45
this.aqiStatus = '健康'
// AQI
this.currentDeviceName = ''
console.error(`IP【${targetIp}】模拟数据请求失败:`, error)
}
},
calcAQI() {},
/**
* 获取所有设备的PM2.5/PM10数据用于计算全局AQI
*/
async getAllDevicesPollutantData() {
if (this.originalAllDeviceIds.length === 0) {
this.allDevicesPollutantData = []
return
}
const allPollutantData = []
// IPEnvironmentalScreenallDeviceIds
for (const ip of this.originalAllDeviceIds) {
try {
// const data = await mockFetchDataForIP({ ip })
//
const data = await alarmApi.FetchDataForIP({ ip })
// PM2.5/PM10
const pm25Item = data.find(item => item.subName === 'PM2.5浓度')
const pm10Item = data.find(item => item.subName === 'PM10浓度')
if (pm25Item) {
allPollutantData.push({
...pm25Item,
value: parseFloat(pm25Item.value) || 0, //
dw: pm25Item.dw || 'ug/立方米' //
})
}
if (pm10Item) {
allPollutantData.push({
...pm10Item,
value: parseFloat(pm10Item.value) || 0,
dw: pm10Item.dw || 'ug/立方米'
})
}
} catch (error) {
console.error(`获取IP【${ip}】污染物数据失败:`, error)
}
}
this.allDevicesPollutantData = allPollutantData
},
/**
* 计算AQI
* 计算全局AQI所有设备PM2.5/PM10平均值
*/
calcAQI(filteredData) {
const pm25 = parseFloat(filteredData.find(item => item.subName === 'PM2.5浓度')?.value || 0)
const pm10 = parseFloat(filteredData.find(item => item.subName === 'PM10浓度')?.value || 0)
const formaldehyde = parseFloat(filteredData.find(item => item.subName === '甲醛')?.value || 0)
const co2 = parseFloat(filteredData.find(item => item.subName === '二氧化碳')?.value || 0)
let aqi = 0
if (pm25 > 50 || pm10 > 100 || formaldehyde > 30 || co2 > 1000) {
aqi = Math.floor(Math.random() * 50) + 100
this.aqiStatus = '污染'
} else if (pm25 > 25 || pm10 > 50 || formaldehyde > 10 || co2 > 800) {
aqi = Math.floor(Math.random() * 50) + 50
this.aqiStatus = '一般'
} else {
aqi = Math.floor(Math.random() * 50) + 1
this.aqiStatus = '健康'
calcGlobalAQI() {
this.hasValidData = this.allDevicesPollutantData.length > 0
// EnvironmentalScreenAQI=45=
if (!this.hasValidData) {
this.aqiValue = 45
this.aqiStatus = '优'
return
}
this.aqiValue = aqi
// 2. PM2.5/PM100
const pm25List = this.allDevicesPollutantData
.filter(item => item.subName === 'PM2.5浓度')
.map(item => parseFloat(item.value) || 0)
const pm10List = this.allDevicesPollutantData
.filter(item => item.subName === 'PM10浓度')
.map(item => parseFloat(item.value) || 0)
// 3. EnvironmentalScreen
const avgPm25 = pm25List.length > 0
? (pm25List.reduce((sum, val) => sum + val, 0) / pm25List.length)
: 0
const avgPm10 = pm10List.length > 0
? (pm10List.reduce((sum, val) => sum + val, 0) / pm10List.length)
: 0
// 4. EnvironmentalScreenAQI
const aqiBpTable = {
pm25: [
{ iaqiLo: 0, iaqiHi: 50, bpLo: 0, bpHi: 35 }, //
{ iaqiLo: 50, iaqiHi: 100, bpLo: 35, bpHi: 75 }, //
{ iaqiLo: 100, iaqiHi: 150, bpLo: 75, bpHi: 115 }, //
{ iaqiLo: 150, iaqiHi: 200, bpLo: 115, bpHi: 150 }, //
{ iaqiLo: 200, iaqiHi: 300, bpLo: 150, bpHi: 250 }, //
{ iaqiLo: 300, iaqiHi: 500, bpLo: 250, bpHi: 500 } //
],
pm10: [
{ iaqiLo: 0, iaqiHi: 50, bpLo: 0, bpHi: 50 }, //
{ iaqiLo: 50, iaqiHi: 100, bpLo: 50, bpHi: 150 }, //
{ iaqiLo: 100, iaqiHi: 150, bpLo: 150, bpHi: 250 }, //
{ iaqiLo: 150, iaqiHi: 200, bpLo: 250, bpHi: 350 }, //
{ iaqiLo: 200, iaqiHi: 300, bpLo: 350, bpHi: 420 }, //
{ iaqiLo: 300, iaqiHi: 500, bpLo: 420, bpHi: 500 } //
]
}
// IAQI
const calculateIAQI = (conc, pollutantType) => {
const bpTable = aqiBpTable[pollutantType]
if (conc > bpTable[bpTable.length - 1].bpHi) return 500
const matchedBp = bpTable.find(item => conc >= item.bpLo && conc <= item.bpHi) || bpTable[0]
const iaqi = ((matchedBp.iaqiHi - matchedBp.iaqiLo) / (matchedBp.bpHi - matchedBp.bpLo)) * (conc - matchedBp.bpLo) + matchedBp.iaqiLo
return Math.min(Math.round(iaqi), 500)
}
// PM2.5PM10AQI
const iaqiPm25 = calculateIAQI(avgPm25, 'pm25')
const iaqiPm10 = calculateIAQI(avgPm10, 'pm10')
const finalAQI = Math.max(iaqiPm25, iaqiPm10)
// 5. AQI
this.aqiValue = finalAQI
const matchedGrade = this.aqiGradeStandard.find(grade =>
finalAQI >= grade.aqiMin && finalAQI <= grade.aqiMax
)
this.aqiStatus = matchedGrade ? matchedGrade.level : '严重污染'
// 便EnvironmentalScreen
console.log('FullView AQI计算(对齐EnvironmentalScreen):', {
avgPm25: avgPm25.toFixed(2),
avgPm10: avgPm10.toFixed(2),
iaqiPm25,
iaqiPm10,
finalAQI,
aqiStatus: this.aqiStatus
})
},
getIframeLoading(value) {},
@ -348,8 +494,8 @@ export default {
right: 20px;
color: #fff;
padding: 20px 20px 10px 20px;
background-image: linear-gradient(to top, rgba(24, 176, 143, .5), rgba(24, 176, 143, 0));
border-radius: 5px;
z-index: 999;
h3{
padding: 30px 0;
}
@ -401,12 +547,68 @@ export default {
font-weight: 600;
padding: 10px 30px;
margin-top: 10px;
background-color: rgba(24, 176, 143, .2);
border-radius: 5px;
}
}
}
&.air-excellent { // - 绿
background-image: linear-gradient(to top, rgba(40, 180, 40, .5), rgba(40, 180, 40, 0));
.air-params .air-right p {
background-color: rgba(40, 180, 40, .2);
}
.air-title::before {
background-color: #28B428;
}
}
&.air-good { // -
background-image: linear-gradient(to top, rgba(255, 200, 0, .5), rgba(255, 200, 0, 0));
.air-params .air-right p {
background-color: rgba(255, 200, 0, .2);
}
.air-title::before {
background-color: #FFC800;
}
}
&.air-lightPollution { // -
background-image: linear-gradient(to top, rgba(255, 140, 0, .5), rgba(255, 140, 0, 0));
.air-params .air-right p {
background-color: rgba(255, 140, 0, .2);
}
.air-title::before {
background-color: #FF8C00;
}
}
&.air-mediumPollution { // -
background-image: linear-gradient(to top, rgba(255, 0, 0, .5), rgba(255, 0, 0, 0));
.air-params .air-right p {
background-color: rgba(255, 0, 0, .2);
}
.air-title::before {
background-color: #FF0000;
}
}
&.air-heavyPollution { // -
background-image: linear-gradient(to top, rgba(150, 0, 200, .5), rgba(150, 0, 200, 0));
.air-params .air-right p {
background-color: rgba(150, 0, 200, .2);
}
.air-title::before {
background-color: #9600C8;
}
}
&.air-severePollution { // -
background-image: linear-gradient(to top, rgba(120, 0, 0, .5), rgba(120, 0, 0, 0));
.air-params .air-right p {
background-color: rgba(120, 0, 0, .2);
}
.air-title::before {
background-color: #780000;
}
}
}
// air-warn
.air-warn{
background-image: linear-gradient(to top, rgba(246, 81, 99, .5), rgba(24, 176, 143, 0));
.air-params{
@ -417,8 +619,9 @@ export default {
}
}
}
.msg-list{
// top: 40px;
position: static;
flex-wrap: wrap !important;
li{
margin-bottom: 20px;

127
src/views/system/logManage/warnLog/index.vue

@ -2,18 +2,19 @@
<div style="height: calc(100vh - 234px);">
<div class="head-container">
<el-button :loading="crud.downloadLoading" size="mini" icon="el-icon-download" @click="handleDownload">导出</el-button>
<el-button size="mini" icon="el-icon-download" :disabled="!(selections.length===1)" @click="handleHand">手动处理</el-button>
<el-select v-model="oprType" class="filter-item" style="width: 100px; height: 30px;margin:0 0 0 10px" @change="crud.toQuery">
<!-- <el-button size="mini" icon="el-icon-download" :disabled="!(selections.length===1)" @click="handleHand">手动处理</el-button> -->
<!-- <el-select v-model="oprType" class="filter-item" style="width: 100px; height: 30px;margin:0 0 0 10px" @change="crud.toQuery" @clear="handleOprTypeClear">
<el-option v-for="item in oprTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input
v-model="query.blurry"
v-model="query.search"
size="small"
clearable
placeholder="请输入关键词"
style="width: 300px;margin-right:10px;padding-left:10px"
class="input-prepend filter-item"
@keyup.enter.native="crud.toQuery"
@clear="crud.toQuery"
>
<el-select slot="prepend" v-model="optionVal" style="width: 80px">
<el-option
@ -23,8 +24,26 @@
:value="item.value"
/>
</el-select>
</el-input>
<date-range-picker v-model="query.createTime" class="date-item" />
</el-input> -->
<!-- 原有输入框添加clear事件 -->
<el-input
v-model="query.search"
size="small"
clearable
placeholder="请输入关键词"
style="width: 200px; margin-right:10px; padding-left:10px"
class="filter-item"
@keyup.enter.native="crud.toQuery"
@clear="crud.toQuery"
/>
<DateRangePicker
v-model="queryTime"
class="date-item"
style="margin-right: 10px;"
@change="handleDateChange"
@clear="handleDateClear"
/>
<rrOperation />
</div>
<el-table
@ -38,24 +57,20 @@
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column prop="state" label="状态" min-width="100" align="center">
<template slot-scope="scope">
<span v-if="scope.row.state" class="clear">已处理</span>
<span v-if="!scope.row.state" class="clear">未处理</span>
</template>
</el-table-column>
<el-table-column prop="storeroomName" label="库房" align="center" min-width="150" />
<el-table-column prop="deviceName" label="设备" align="center" min-width="200" />
<el-table-column prop="content" label="警情描述" align="center" min-width="240" />
<!-- <el-table-column prop="remark" label="说明" align="center" min-width="180" /> -->
<el-table-column prop="create_time" label="报警时间" align="center" min-width="180">
<el-table-column prop="siteName" label="设备名称" align="center" min-width="200" />
<el-table-column prop="name" label="监测点名称" align="center" min-width="200" />
<el-table-column prop="ip" label="IP" min-width="130" align="center" />
<el-table-column prop="value" label="警告" align="center" min-width="240" />
<el-table-column prop="dw" label="单位" align="center" />
<el-table-column prop="itemLevels" label="报警等级" align="center">
<template slot-scope="scope">
<div>{{ scope.row.create_time | parseTime }}</div>
<!-- 1.紧急 2.重大 3.严重 4.紧要 5.重要 6.次要 7.一般 8.警告 9.提示 10.忽略 -->
<div>{{ formatAlarmLevel(scope.row.itemLevels) }}</div>
</template>
</el-table-column>
<el-table-column prop="update_time" label="处理时间" align="center" min-width="180">
<el-table-column prop="ts" label="报警时间" align="center" min-width="180">
<template slot-scope="scope">
<div>{{ scope.row.update_time | parseTime }}</div>
<div>{{ scope.row.ts | parseTime }}</div>
</template>
</el-table-column>
</el-table>
@ -93,8 +108,8 @@ export default {
mixins: [presenter(), crud(), header()],
cruds() {
return CRUD({
url: 'api/alarmlog/',
sort: ['state'],
url: 'api/device/hikAlarmLog',
sort: [],
optShow: {
add: false,
edit: false,
@ -120,7 +135,7 @@ export default {
{ value: 1, label: '设备' },
{ value: 2, label: '库房' }
],
queryTime: null,
queryTime: [],
form: {
description: ''
},
@ -128,6 +143,18 @@ export default {
description: [
{ required: true, message: '说明不能为空', trigger: 'blur' }
]
},
alarmLevelMap: {
1: '紧急',
2: '重大',
3: '严重',
4: '紧要',
5: '重要',
6: '次要',
7: '一般',
8: '警告',
9: '提示',
10: '忽略'
}
}
},
@ -137,22 +164,32 @@ export default {
])
},
methods: {
formatAlarmLevel(level) {
//
const numLevel = Number(level)
// ""
return this.alarmLevelMap[numLevel] || this.alarmLevelMap['']
},
//
[CRUD.HOOK.beforeRefresh]() {
this.crud.downloadLoading = true
this.crud.query.state = null
// this.crud.query.blurry = this.keyWord
if (this.oprType > -1) {
this.crud.query.state = this.oprType
if (this.queryTime && this.queryTime.length > 0) {
this.crud.query.startTime = this.queryTime[0]
this.crud.query.endTime = this.queryTime[1]
} else {
this.crud.query.startTime = null
this.crud.query.endTime = null
}
this.crud.downloadLoading = false
},
//
handleDownload() {
this.crud.downloadLoading = true
const fileName = parseTime(new Date()) + '-报警日志'
getBlob(this.baseApi + '/api/alarmlog/download' + '?' + qs.stringify(this.crud.query, { indices: false }), function(blob) {
getBlob(this.baseApi + '/api/device/downloadHikAlarmLog' + '?' + qs.stringify(this.crud.query, { indices: false }), function(blob) {
saveAs(blob, fileName)
}, (err) => {
console.error('导出失败:', err)
this.$message.error('导出失败')
this.crud.downloadLoading = false
})
this.crud.downloadLoading = false
},
@ -164,25 +201,23 @@ export default {
},
//
handleHand() {
this.form.description = this.selections[0].remark
this.form.description = this.selections[0]?.remark || ''
this.handleVisible = true
},
handleSave() {
const row = this.selections[0]
if (!row) {
this.$message.warning('请选择要处理的记录')
return
}
const params = {
'id': row.id,
// 'storeroom_name': row.storeroomName,
'state': true,
// 'device_id': row.deviceId,
// 'device_name': row.deviceName,
// 'content': row.content,
'remark': this.form.description
}
console.log(params)
this.$refs.formDom.validate((valid) => {
if (valid) {
warnRemark(params).then(res => {
// console.log(res, '')
if (res === 'SUCCESS') {
this.crud.refresh()
this.$message({
@ -195,6 +230,8 @@ export default {
} else {
this.$message.error('处理失败')
}
}).catch(() => {
this.$message.error('处理失败')
})
} else {
return false
@ -207,6 +244,24 @@ export default {
} else if (row.state === false && columnIndex === 2) {
return 'fail-clear'
}
},
//
handleOprTypeClear() {
this.oprType = -1
this.crud.toQuery()
},
handleDateChange() {
this.crud.toQuery()
},
//
handleDateClear() {
//
this.queryTime = []
//
this.crud.query.startTime = null
this.crud.query.endTime = null
//
this.crud.toQuery()
}
}
}

Loading…
Cancel
Save