7 changed files with 2040 additions and 348 deletions
-
31public/web3D/index.js
-
8src/assets/icons/svg/jiankong.svg
-
4src/views/components/AccessDoor.vue
-
787src/views/environmentalScreen/index copy.vue
-
27src/views/environmentalScreen/index.js
-
782src/views/environmentalScreen/index.vue
-
749src/views/home111.vue
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" standalone="no"?> |
|||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> |
|||
<svg t="1765795623113" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9168" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="256"> |
|||
<style type="text/css"> |
|||
.st0{fill:#F65163;} /* 和上一个图标一致的红色 */ |
|||
</style> |
|||
<path d="M637.44 816.64C716.8 846.08 766.72 898.56 766.72 960H247.04c0-61.44 53.76-115.2 135.68-143.36C232.96 762.88 125.44 619.52 125.44 450.56 125.44 235.52 296.96 64 512 64s386.56 171.52 386.56 386.56c0 168.96-107.52 312.32-261.12 366.08zM519.68 332.8c-111.36 0-204.8 93.44-204.8 204.8s93.44 204.8 204.8 204.8c115.2 0 204.8-93.44 204.8-204.8s-90.88-204.8-204.8-204.8z m0 314.88c-53.76 0-99.84-43.52-99.84-99.84 0-53.76 46.08-99.84 99.84-99.84s99.84 43.52 99.84 99.84c0 53.76-43.52 99.84-99.84 99.84z" class="st0" p-id="9169"></path> |
|||
</svg> |
|||
@ -0,0 +1,787 @@ |
|||
<template> |
|||
<div class="env-container"> |
|||
<div class="env-top-title" /> |
|||
<div class="current-date">{{ nowDate }}</div> |
|||
<div class="env-main"> |
|||
<div class="env-main-left"> |
|||
<div class="env-item container-wrap"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<h3> |
|||
<svg-icon icon-class="danganjieyue" style="margin-right:10px" />档案借阅 |
|||
</h3> |
|||
<div class="chart-wrapper" style="height: calc(100% - 40px);"> |
|||
<lend-across :lend-data="lendData" :refreshtime="refreshtime" /> |
|||
</div> |
|||
</div> |
|||
<div class="env-item container-wrap" style="height: calc(100% - 170px) !important;"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<h3> |
|||
<i class="iconfont icon-kongqizhiliangshuju" />档案库空气质量数据 |
|||
</h3> |
|||
<span style="display:block; text-align: center; font-size: 12px; margin-left: 10px; color: #3a99fd;"> |
|||
{{ currentDeviceName || '' }} |
|||
</span> |
|||
<ul v-if="newAlarm && newAlarm.length !== 0" class="screen-env-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="font-size: 64px; margin-left: 10px;" /> |
|||
<!-- <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-else class="empty-tip" style="display:flex; justify-content: center; height: calc(100% - 80px); color: #909399; align-items: center; font-size: 12px;"> |
|||
暂无数据 |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="env-main-middle" :style="{ height: allDisplayConfigData?.length ? 'calc(100vh - 138px)' : 'calc(100vh - 138px)', overflow: 'hidden' }"> |
|||
<div class="env-3d" :style="{ height: allDisplayConfigData?.length ? 'calc(100% - 80px)' : 'calc(100% + 80px)'}"> |
|||
<div class="banner-top-name">{{ bannerRoomName }}</div> |
|||
<iframe id="myIframe" ref="myIframe" name="iframeMap" class="iframe_box" src="/web3D/index.html" frameborder="0" scrolling="no" /> |
|||
</div> |
|||
<div v-if="newAlarm && newAlarm.length !== 0" class="air-quality" :class="{'air-warn': aqiStatus === '污染'}"> |
|||
<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> |
|||
<div class="air-right"> |
|||
<span>空气质量为</span> |
|||
<p>{{ aqiStatus }}</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- <div v-if="allDisplayConfigData && allDisplayConfigData.length !==0 " class="middle-bottom"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<ul class="leakage-list"> |
|||
<li v-for="item in allDisplayConfigData" :key="item.id" :class="{ 'leakage-warn': item.NetStatus === 0 }"> |
|||
<p><i class="iconfont icon-weihubaojing" />{{ item.Name }}</p> |
|||
<span class="leakage-state-tip" /> |
|||
</li> |
|||
</ul> |
|||
</div> --> |
|||
<div v-if="validDisplayConfigData.length" class="middle-bottom"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<ul |
|||
class="leakage-list" |
|||
:style="{ |
|||
height: showScroll ? '147px' : 'auto', // 数量>6时固定高度,否则自适应 |
|||
overflow: showScroll ? 'auto' : 'hidden' // 数量>6时显示滚动 |
|||
}" |
|||
> |
|||
<li |
|||
v-for="item in validDisplayConfigData" |
|||
:key="item.id" |
|||
:class="{ 'leakage-warn': item.NetStatus === 0 }" |
|||
:style="{ |
|||
width: liWidth, |
|||
height: liHeight, |
|||
marginRight: '14px', |
|||
marginBottom: '14px' |
|||
}" |
|||
> |
|||
<p><i class="iconfont icon-shebei" />{{ item.Name }}</p> |
|||
<span class="leakage-state-tip" /> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
<div class="env-main-right"> |
|||
<!-- 门禁记录 --> |
|||
<!-- <security-door :height="'calc(100% - 38px)'" style="margin-bottom: 15px;" /> --> |
|||
<AccessDoor :height="'calc(100% - 40px)'" style="margin-bottom: 15px;" /> |
|||
<!-- 报警记录 --> |
|||
<warehouse-warning :height="'calc(100% - 38px)'" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { getCurrentTime } from '@/utils/index' |
|||
import lendAcross from '@/views/components/echarts/lendAcross.vue' |
|||
import WarehouseWarning from '@/views/components/WarehouseWarning' |
|||
// import SecurityDoor from '@/views/components/SecurityDoor' |
|||
import AccessDoor from '@/views/components/AccessDoor' |
|||
import displayConfigApi from '@/api/storeManage/displayConfig' |
|||
// import thirdApi from '@/api/thirdApi' |
|||
import { statisticsCrud } from '@/views/system/archiveStatistics/mixins/statistics' |
|||
import alarmApi from '@/api/home/alarm' |
|||
// import { allDeviceData, mockIpData } from './index.js' |
|||
|
|||
// // 同步mock方法 |
|||
// const mockFetchDataForIP = (params) => { |
|||
// return new Promise((resolve) => { |
|||
// setTimeout(() => { |
|||
// const ip = params.ip |
|||
// const result = mockIpData[ip] || { code: 200, message: '操作成功', data: [], timestamp: Date.now() } |
|||
// resolve(result.data) |
|||
// }, 500) |
|||
// }) |
|||
// } |
|||
|
|||
export default { |
|||
name: 'EnvironmentalScreen', |
|||
components: { |
|||
WarehouseWarning, |
|||
// SecurityDoor, |
|||
AccessDoor, |
|||
lendAcross |
|||
}, |
|||
mixins: [statisticsCrud], |
|||
data() { |
|||
return { |
|||
bannerRoomName: '3F 全景图', |
|||
nowDate: '', |
|||
timer: null, |
|||
echartsTimer: null, |
|||
roomId: 'D6490DA3D4261E8C26D0E3', |
|||
allDisplayConfigData: [], |
|||
displayConfigData: [], |
|||
url: '', |
|||
allDeviceIds: [], |
|||
oaoMessage: [], |
|||
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 } |
|||
}, |
|||
refreshtime: 60000, |
|||
lendData: [], |
|||
typeData: [], |
|||
// 同步FullView的核心数据 |
|||
newAlarm: [], |
|||
aqiValue: 45, |
|||
aqiStatus: '健康', |
|||
keepIndicators: [ |
|||
'二氧化碳', |
|||
'甲醛', |
|||
'综合气体', |
|||
'PM2.5浓度', |
|||
'PM10浓度', |
|||
'温度', |
|||
'湿度', |
|||
'空气质量' |
|||
], |
|||
ipToNameMap: {}, // IP到设备名称映射 |
|||
currentDeviceName: '', // 当前显示设备名称 |
|||
currentIpIndex: 0, // IP轮询索引 |
|||
excludeIpList: ['192.168.99.101:6003'], // 排除IP列表 |
|||
dataTimer: null, // 数据轮询定时器 |
|||
iframeWin: null // iframe窗口对象 |
|||
} |
|||
}, |
|||
computed: { |
|||
// 过滤有效数据(排除空值/无效项) |
|||
validDisplayConfigData() { |
|||
return this.allDisplayConfigData.filter(item => item && item.Name) |
|||
}, |
|||
// 每行显示数量(优先3个,数量不足时自动调整) |
|||
itemsPerRow() { |
|||
const len = this.validDisplayConfigData.length |
|||
if (len === 0) return 0 |
|||
// 规则:总数<=3 → 每行显示总数;3<总数<=6 → 每行3个;总数>6 → 每行3个(最多显示2行,超出滚动) |
|||
return len <= 3 ? len : 3 |
|||
}, |
|||
// li的宽度(百分比,预留间距) |
|||
liWidth() { |
|||
if (this.itemsPerRow === 0) return '0' |
|||
// 每行n个 → 宽度 = 100%/n - 间距(14px) |
|||
return `calc(100% / ${this.itemsPerRow} - 14px)` |
|||
}, |
|||
// li的高度(百分比,根据总行数均分) |
|||
liHeight() { |
|||
const len = this.validDisplayConfigData.length |
|||
if (len === 0) return '0' |
|||
// 总行数 = 向上取整(总数/每行数量) |
|||
const rows = Math.ceil(len / this.itemsPerRow) |
|||
// 高度 = 100%/总行数 - 间距(14px) |
|||
return `calc(100% / ${rows} - 14px)` |
|||
}, |
|||
// 是否显示滚动(数量>6时,限制高度并显示滚动) |
|||
showScroll() { |
|||
return this.validDisplayConfigData.length > 6 |
|||
} |
|||
}, |
|||
async created() { |
|||
// 时间更新 |
|||
this.timer = setInterval(() => { |
|||
this.nowDate = getCurrentTime() |
|||
}, 1000) |
|||
|
|||
// 同步FullView的初始化逻辑 |
|||
window.getIframeLoading = this.getIframeLoading |
|||
// 真实请求请替换: |
|||
await alarmApi.FetchYpGetSite().then((data) => { |
|||
if (data && data.length > 0) { |
|||
this.allDisplayConfigData = data |
|||
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]) |
|||
|
|||
// 移到这里创建定时器 |
|||
this.dataTimer = setInterval(async() => { |
|||
const currentIp = this.getNextIp() |
|||
this.currentDeviceName = this.ipToNameMap[currentIp] || '' |
|||
await this.getRealTimeData(currentIp) |
|||
}, 10000) |
|||
// 10000 |
|||
console.log(`启动IP轮询,共${this.allDeviceIds.length}个有效IP:`, this.allDeviceIds) |
|||
} else { |
|||
console.warn('无有效设备IP,停止轮询') |
|||
this.newAlarm = [] |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.iframeWin = this.$refs.myIframe?.contentWindow |
|||
|
|||
// 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) |
|||
// } |
|||
|
|||
// 原有echarts刷新逻辑 |
|||
this.echartsTimer = setInterval(() => { |
|||
this.lendData = [] |
|||
this.typeData = [] |
|||
this.getBorrowerNumSta() |
|||
}, this.refreshtime) |
|||
}, |
|||
beforeDestroy() { |
|||
// 清理所有定时器 |
|||
if (this.timer) clearInterval(this.timer) |
|||
if (this.echartsTimer) clearInterval(this.echartsTimer) |
|||
if (this.dataTimer) { |
|||
clearInterval(this.dataTimer) |
|||
console.log('停止IP轮询') |
|||
} |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 处理设备IP列表(去重+排除+名称映射) |
|||
*/ |
|||
handleDeviceIpList() { |
|||
const ipSet = new Set() |
|||
this.ipToNameMap = {} |
|||
|
|||
this.allDisplayConfigData.forEach(element => { |
|||
const ip = (element.IP || '').trim() |
|||
if (ip && !this.excludeIpList.includes(ip)) { |
|||
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) |
|||
} |
|||
}) |
|||
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 |
|||
}, |
|||
/** |
|||
* 请求指定IP的实时数据(过滤+AQI计算) |
|||
*/ |
|||
async getRealTimeData(targetIp) { |
|||
if (!targetIp) { |
|||
this.newAlarm = [] |
|||
this.currentDeviceName = '' |
|||
return |
|||
} |
|||
|
|||
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) |
|||
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 = '健康' |
|||
this.currentDeviceName = '' |
|||
console.error(`IP【${targetIp}】数据请求失败:`, error) |
|||
} |
|||
}, |
|||
|
|||
getIframeLoading(value) {}, |
|||
// 原有切换房间方法(同步更新数据) |
|||
async changeRoomGetDeivce() { |
|||
this.allDeviceIds = [] |
|||
this.allDisplayConfigData = await displayConfigApi.list({ storeroomId: this.roomId }) |
|||
this.handleDeviceIpList() // 重新处理IP列表 |
|||
console.log('allDeviceIds2', this.allDeviceIds) |
|||
this.displayConfigData = this.allDisplayConfigData.filter((item) => { |
|||
return item.isDisplay && item.bindState && item.deviceInfo && (item.divPosition.includes('OAO') || item.divPosition.includes('TOP') || item.divPosition.includes('LS')) |
|||
}) |
|||
console.log('displayConfigData2', this.displayConfigData) |
|||
|
|||
// 重新加载数据 |
|||
if (this.allDeviceIds.length > 0) { |
|||
this.currentDeviceName = this.ipToNameMap[this.allDeviceIds[0]] || '' |
|||
await this.getRealTimeData(this.allDeviceIds[0]) |
|||
} else { |
|||
this.newAlarm = [] |
|||
this.currentDeviceName = '' |
|||
} |
|||
this.handleAQI() |
|||
}, |
|||
/** |
|||
* 计算AQI |
|||
*/ |
|||
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 = '健康' |
|||
} |
|||
this.aqiValue = aqi |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style rel="stylesheet/scss" lang="scss" scoped> |
|||
@import "~@/assets/styles/lend-manage.scss"; |
|||
|
|||
.env-container { |
|||
width: 100%; |
|||
height: calc(100vh); |
|||
background-color: #031435; |
|||
.env-top-title { |
|||
width: calc(100vw); |
|||
height: 130px; |
|||
background: url("~@/assets/images/largeScreen/top-title.png") no-repeat 0 -14px; |
|||
background-size: contain; |
|||
} |
|||
.current-date { |
|||
position: fixed; |
|||
top: 25px; |
|||
right: 150px; |
|||
font-size: 16px; |
|||
color: #3a99fd; |
|||
} |
|||
.env-main { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 0 25px; |
|||
// margin-top: -12px; |
|||
.env-main-left, |
|||
.env-main-right { |
|||
max-width: 24%; |
|||
flex: 1; |
|||
height: calc(100vh - 138px); |
|||
overflow: hidden; |
|||
} |
|||
.env-main-middle { |
|||
position: relative; |
|||
flex: 1; |
|||
margin: 0 20px; |
|||
height: calc(100vh - 138px); |
|||
overflow: hidden; |
|||
} |
|||
.env-main-left .container-wrap { |
|||
min-height: auto; |
|||
} |
|||
.env-main-right .container-wrap { |
|||
height: calc(100% / 2 - 14px); |
|||
min-height: auto; |
|||
} |
|||
.env-item { |
|||
margin-bottom: 20px; |
|||
text-align: center; |
|||
h3 { |
|||
position: relative; |
|||
display: inline-block; |
|||
padding: 10px 70px; |
|||
font-size: 16px; |
|||
color: #fff; |
|||
.iconfont { |
|||
margin-right: 10px; |
|||
font-size: 14px; |
|||
color: #f65163; |
|||
} |
|||
&::before { |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 50%; |
|||
width: 36px; |
|||
height: 12px; |
|||
margin-top: -6px; |
|||
background: url("~@/assets/images/largeScreen/item-left.png") no-repeat; |
|||
background-size: cover; |
|||
} |
|||
&::after { |
|||
content: ""; |
|||
position: absolute; |
|||
top: 50%; |
|||
right: 0; |
|||
width: 36px; |
|||
height: 12px; |
|||
margin-top: -6px; |
|||
background: url("~@/assets/images/largeScreen/item-right.png") no-repeat; |
|||
background-size: cover; |
|||
} |
|||
} |
|||
.msg-list { |
|||
flex-wrap: wrap !important; |
|||
padding: 0 20px; |
|||
li { |
|||
margin-bottom: 20px; |
|||
display: flex; |
|||
align-items: center; |
|||
.msg-list-svg { |
|||
font-size: 40px; |
|||
margin-left: 20px; |
|||
} |
|||
.msg-txt { |
|||
margin-left: 15px; |
|||
text-align: left; |
|||
.msg-list-num { |
|||
font-size: 24px; |
|||
color: #fff; |
|||
font-weight: 600; |
|||
} |
|||
.msg-list-unit { |
|||
font-size: 14px; |
|||
color: #ccc; |
|||
margin: 5px 0 0 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.empty-tip { |
|||
font-size: 14px; |
|||
color: #999; |
|||
padding: 40px 0; |
|||
} |
|||
} |
|||
.screen-env-list { |
|||
flex-wrap: wrap; |
|||
// justify-content: space-between; |
|||
justify-content: flex-start; |
|||
height: calc(100% - 54px); |
|||
padding: 0 10px; |
|||
li { |
|||
flex: none; |
|||
width: calc(100% / 2 - 22px); |
|||
margin: 20px 10px; |
|||
height: calc(100% / 4 - 40px); |
|||
.msg-list-svg { |
|||
font-size: 40px; |
|||
margin-left: 20px; |
|||
} |
|||
&.msg-pm { |
|||
.msg-list-svg { |
|||
font-size: 46px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.env-3d { |
|||
position: relative; |
|||
width: 100%; |
|||
// height: calc(100% + 80px); |
|||
height: calc(100% - 80px); |
|||
background: url("~@/assets/images/largeScreen/bg.png") no-repeat center -130px; |
|||
overflow: hidden; |
|||
margin-top: -80px; |
|||
.iframe_box { |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
.screen-env-list { |
|||
position: absolute; |
|||
right: 0; |
|||
bottom: 0; |
|||
flex-wrap: wrap; |
|||
justify-content: space-between; |
|||
padding: 0; |
|||
width: 165px; |
|||
height: 200px; |
|||
z-index: 99999; |
|||
li { |
|||
width: 100%; |
|||
margin: 20px 0 0 0; |
|||
height: calc(100% / 2 - 20px); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.banner-top-name{ |
|||
position: absolute; |
|||
left: 0; |
|||
top: 80px; |
|||
padding: 0 15px; |
|||
height: 34px; |
|||
line-height: 32px; |
|||
font-size: 18px; |
|||
color: #fff; |
|||
background-color: #113d72; |
|||
border: 1px solid #339cff; |
|||
border-radius: 4px; |
|||
} |
|||
.air-quality{ |
|||
position: absolute; |
|||
top: 10px; |
|||
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: 9999; |
|||
h3{ |
|||
padding: 30px 0; |
|||
} |
|||
.air-params{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: last baseline; |
|||
.air-left{ |
|||
.air-title{ |
|||
position: relative; |
|||
padding-left: 12px; |
|||
font-size: 14px; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 50%; |
|||
width: 6px; |
|||
height: 6px; |
|||
background-color: #18B08F; |
|||
border-radius: 50%; |
|||
} |
|||
} |
|||
.air-result{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: last baseline; |
|||
padding-top: 10px; |
|||
p{ |
|||
font-size: 30px; |
|||
font-weight: 600; |
|||
padding: 0 6px 0 10px; |
|||
} |
|||
span{ |
|||
display: block; |
|||
font-size: 12px; |
|||
opacity: .6; |
|||
} |
|||
} |
|||
} |
|||
.air-right{ |
|||
text-align: center; |
|||
span{ |
|||
display: block; |
|||
font-size: 12px; |
|||
} |
|||
p{ |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
padding: 10px 30px; |
|||
margin-top: 10px; |
|||
background-color: rgba(24, 176, 143, .2); |
|||
border-radius: 5px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.air-warn{ |
|||
background-image: linear-gradient(to top, rgba(246, 81, 99, .5), rgba(24, 176, 143, 0)); |
|||
.air-params{ |
|||
.air-right{ |
|||
p{ |
|||
background-color: rgba(246, 81, 99, .2); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.middle-bottom { |
|||
width: 100%; |
|||
position: relative; |
|||
padding: 0 !important; |
|||
background-color: #021941; |
|||
border: 1px solid #113d72; |
|||
color: #339cff; |
|||
font-size: 14px; |
|||
&::before, |
|||
&::after{ |
|||
content: ""; |
|||
position: absolute; |
|||
width: 17px; |
|||
height: 17px; |
|||
z-index: 99; |
|||
} |
|||
&::before{ |
|||
top: -1px; |
|||
left: -1px; |
|||
border-top: 1px solid #339CFF; |
|||
border-left: 1px solid #339CFF; |
|||
} |
|||
&::after{ |
|||
right: -1px; |
|||
bottom: -1px; |
|||
border-right: 1px solid #339CFF; |
|||
border-bottom: 1px solid #339CFF; |
|||
} |
|||
} |
|||
|
|||
.leakage-list { |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
flex-wrap: wrap; |
|||
padding: 14px 0 0 14px; |
|||
height: auto; |
|||
text-align: left; |
|||
&::-webkit-scrollbar { |
|||
width: 4px; |
|||
height: 4px; |
|||
} |
|||
&::-webkit-scrollbar-thumb { |
|||
background-color: #339cff; |
|||
border-radius: 2px; |
|||
} |
|||
&::-webkit-scrollbar-track { |
|||
background-color: #021941; |
|||
} |
|||
li { |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
// width: calc( 100% / 3 - 14px); |
|||
// height: calc(100% / 3 - 14px); |
|||
width: auto; |
|||
height: auto; |
|||
// margin: 0 14px 14px 0; |
|||
padding: 0 30px; |
|||
border: 1px solid #3581cc; |
|||
background-color: #02255f; |
|||
border-radius: 2px; |
|||
&::before { |
|||
content: ""; |
|||
position: absolute; |
|||
top: 4px; |
|||
left: 4px; |
|||
width: 0; |
|||
height: 0; |
|||
border-color: transparent #339cff; |
|||
border-width: 0 0 6px 6px; |
|||
border-style: solid; |
|||
} |
|||
p { |
|||
i { |
|||
margin-right: 8px; |
|||
font-size: 20px; |
|||
} |
|||
} |
|||
span.leakage-state-tip { |
|||
position: relative; |
|||
display: block; |
|||
width: 6px; |
|||
height: 6px; |
|||
border-radius: 50%; |
|||
background-color: #18b08f; |
|||
&::before { |
|||
content: ""; |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
width: 14px; |
|||
height: 14px; |
|||
border-radius: 50%; |
|||
box-shadow: inset 0px 0px 10px 1px #18b08f; |
|||
transform: translate(-50%, -50%); |
|||
} |
|||
} |
|||
&.leakage-warn { |
|||
border-color: #f65164; |
|||
box-shadow: inset 0px 0px 15px 1px #f65164; |
|||
color: #f65164; |
|||
&::before { |
|||
border-color: transparent #f65164; |
|||
} |
|||
span.leakage-state-tip { |
|||
background-color: #f65164; |
|||
&::before { |
|||
box-shadow: inset 0px 0px 10px 1px #f65164; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
782
src/views/environmentalScreen/index.vue
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,749 @@ |
|||
<template> |
|||
<div class="dashboard-container"> |
|||
<div class="dashboard-editor-container"> |
|||
<panel-group /> |
|||
<el-row :gutter="20" style="margin-bottom:20px;height: 152px;"> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<!-- search-area --> |
|||
<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;"> |
|||
<p class="title-arrow"> |
|||
档案检索 |
|||
</p> |
|||
</h3> |
|||
<SearchAcrives :is-home-search="isHomeSearch" /> |
|||
</div> |
|||
</el-col> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<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"> |
|||
<p class="title-arrow"> |
|||
<i class="iconfont icon-kongqizhiliangshuju" />环境数据 |
|||
</p> |
|||
</h3> |
|||
<div class="home-floor-tab"> |
|||
<p :class="{ 'active-floor': floorEnvIndex == 0 }" @click="changeFloorEnvTab(0)">3楼</p> |
|||
</div> |
|||
<el-carousel ref="carouselEnvRef" trigger="click" :interval="10000" indicator-position="none" height="110px" arrow="never" @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> |
|||
</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"> |
|||
<p>{{ item.subName }}</p> |
|||
<span>{{ item.value }}</span> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
|
|||
</div> |
|||
</div> |
|||
</el-carousel-item> |
|||
</el-carousel> |
|||
</div> |
|||
</el-col> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<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"> |
|||
<p class="title-arrow"> |
|||
<svg-icon icon-class="a-3Dkufang" class-name="warehouse-svg" />3D库房 |
|||
</p> |
|||
</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> |
|||
<div class="warehouse-tab"> |
|||
<ul class="warehouse-nav"> |
|||
<li @click="changeActiveTab(1,0)"> |
|||
<span /> |
|||
<p>全景图</p> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</el-carousel-item> |
|||
</el-carousel> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
<el-row :gutter="20" style="margin-bottom:20px;height: calc(50vh - 251px);"> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<!-- 待办事项 --> |
|||
<div class="container-wrap"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<h3 class="table-title"> |
|||
<p class="title-arrow"> |
|||
<svg-icon icon-class="tongzhigonggao" class-name="warehouse-svg" />待办事项 |
|||
</p> |
|||
</h3> |
|||
<div style="height: calc(100% - 40px);overflow-y: auto;overflow-x: hidden;"> |
|||
<ul v-if="waitBorrowerData.length !== 0" class="todo-list"> |
|||
<li v-for="(item,index) in waitBorrowerData" :key="index" :class="item.title.includes('警告') || item.title.includes('逾期') ? 'warn-info' :''" @click="handleToWaiting(item)"> |
|||
<el-tooltip class="item" effect="dark" :content="item.title" :enterable="false" placement="top"> |
|||
<p>{{ item.title }}</p> |
|||
</el-tooltip> |
|||
<span>{{ item.update_time | parseTime }}</span> |
|||
</li> |
|||
</ul> |
|||
<div v-else class="empty-main" style="height: 100%;"> |
|||
<svg-icon icon-class="empty" class-name="empty-img" /> |
|||
<p>暂无数据</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</el-col> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<!-- 门禁记录 --> |
|||
<!-- <security-door :height="'calc(100% - 40px)'" /> --> |
|||
<AccessDoor :height="'calc(100% - 40px)'" /> |
|||
</el-col> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<!-- 报警记录 --> |
|||
<warehouse-warning :height="'calc(100% - 40px)'" /> |
|||
</el-col> |
|||
</el-row> |
|||
<el-row :gutter="20" style="height: calc(50vh - 251px);"> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<!-- 档案借阅 --> |
|||
<div class="container-wrap"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<h3 class="table-title"> |
|||
<p class="title-arrow">档案借阅</p> |
|||
</h3> |
|||
<div class="chart-wrapper"> |
|||
<lend-across :lend-data="lendData" /> |
|||
</div> |
|||
</div> |
|||
</el-col> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<!-- 档案类别 --> |
|||
<div class="container-wrap"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<h3 class="table-title"> |
|||
<p class="title-arrow">档案类别</p> |
|||
</h3> |
|||
<div class="chart-wrapper"> |
|||
<cate-pie :cate-data="cateData" /> |
|||
</div> |
|||
</div> |
|||
</el-col> |
|||
<el-col :xs="24" :sm="24" :lg="8"> |
|||
<!-- 档案类型 --> |
|||
<div class="container-wrap"> |
|||
<span class="right-top-line" /> |
|||
<span class="left-bottom-line" /> |
|||
<h3 class="table-title"> |
|||
<p class="title-arrow">档案类型</p> |
|||
</h3> |
|||
<div v-if="typeData.length !== 0" class="chart-wrapper"> |
|||
<type-pie :type-data="typeData" /> |
|||
</div> |
|||
<div v-else class="empty-main"> |
|||
<svg-icon icon-class="empty" class-name="empty-img" /> |
|||
<p>暂无数据</p> |
|||
</div> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import PanelGroup from './dashboard/PanelGroup' |
|||
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 { allDeviceData, mockIpData } from '@/views/environmentalScreen/index.js' |
|||
|
|||
// // 同步mock方法 |
|||
// const mockFetchDataForIP = (params) => { |
|||
// return new Promise((resolve) => { |
|||
// setTimeout(() => { |
|||
// const ip = params.ip |
|||
// const result = mockIpData[ip] || { code: 200, message: '操作成功', data: [], timestamp: Date.now() } |
|||
// resolve(result.data) |
|||
// }, 500) |
|||
// }) |
|||
// } |
|||
import { mapGetters } from 'vuex' |
|||
|
|||
export default { |
|||
name: 'Dashboard', |
|||
components: { |
|||
WarehouseWarning, |
|||
// SecurityDoor, |
|||
AccessDoor, |
|||
PanelGroup, |
|||
lendAcross, |
|||
catePie, |
|||
typePie, |
|||
SearchAcrives |
|||
}, |
|||
mixins: [statisticsCrud], |
|||
data() { |
|||
return { |
|||
waitBorrowerData: [], |
|||
floorIndex: 0, |
|||
floorEnvIndex: 0, |
|||
isHomeSearch: false, |
|||
roomId: null, |
|||
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: [], |
|||
aqiValue: 45, |
|||
aqiStatus: '健康', |
|||
keepIndicators: [ |
|||
'二氧化碳', |
|||
'甲醛', |
|||
'综合气体', |
|||
'PM2.5浓度', |
|||
'PM10浓度', |
|||
'温度', |
|||
'湿度', |
|||
'空气质量' |
|||
], |
|||
ipToNameMap: {}, // IP到设备名称映射 |
|||
currentDeviceName: '', // 当前显示设备名称 |
|||
currentIpIndex: 0, // IP轮询索引 |
|||
excludeIpList: ['192.168.99.101:6003'] // 排除IP列表 |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapGetters([ |
|||
'roles' |
|||
]) |
|||
}, |
|||
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 (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) |
|||
} |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 处理设备IP列表(去重+排除+名称映射) |
|||
*/ |
|||
handleDeviceIpList() { |
|||
const ipSet = new Set() |
|||
this.ipToNameMap = {} |
|||
|
|||
this.allDisplayConfigData.forEach(element => { |
|||
const ip = (element.IP || '').trim() |
|||
if (ip && !this.excludeIpList.includes(ip)) { |
|||
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) |
|||
} |
|||
}) |
|||
this.allDeviceIds = Array.from(ipSet) |
|||
}, |
|||
|
|||
/** |
|||
* 获取下一个轮询IP(循环切换) |
|||
*/ |
|||
getNextIp() { |
|||
if (this.allDeviceIds.length === 0) return '' |
|||
const ip = this.allDeviceIds[this.currentIpIndex] |
|||
this.currentIpIndex = (this.currentIpIndex + 1) % this.allDeviceIds.length |
|||
console.log(`轮询切换 - 当前IP:${ip},下一个索引:${this.currentIpIndex}`) |
|||
return ip |
|||
}, |
|||
/** |
|||
* 请求指定IP的实时数据(过滤+AQI计算) |
|||
*/ |
|||
async getRealTimeData(targetIp) { |
|||
if (!targetIp) { |
|||
this.newAlarm = [] |
|||
this.currentDeviceName = '' |
|||
return |
|||
} |
|||
|
|||
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}) 无需要的指标数据`) |
|||
} |
|||
} catch (error) { |
|||
this.newAlarm = [] |
|||
this.aqiValue = 45 |
|||
this.aqiStatus = '健康' |
|||
this.currentDeviceName = '' |
|||
console.error(`IP【${targetIp}】数据请求失败:`, error) |
|||
} |
|||
}, |
|||
|
|||
handleChange(index) { |
|||
this.floorIndex = index |
|||
}, |
|||
handleEnvChange(index) { |
|||
this.floorEnvIndex = index |
|||
}, |
|||
changeFloorTab(index) { |
|||
this.floorIndex = index |
|||
const carousel = this.$refs.carouselRef |
|||
carousel.setActiveItem(index) |
|||
}, |
|||
changeFloorEnvTab(index) { |
|||
this.floorEnvIndex = index |
|||
const carousel = this.$refs.carouselEnvRef |
|||
carousel.setActiveItem(index) |
|||
}, |
|||
// handleSetLineChartData(type) { |
|||
// this.lineChartData = lineChartData[type] |
|||
// }, |
|||
getWaitBorrower() { |
|||
FetchWaitBorrower().then(data => { |
|||
if (data) { |
|||
this.waitBorrowerData = data |
|||
} |
|||
}) |
|||
}, |
|||
changeActiveTab(floorId, roomId) { |
|||
if (this.roles.includes('admin') || this.roles.includes('warehouse3D')) { |
|||
this.$router.push({ |
|||
name: 'warehouse3D', |
|||
params: { |
|||
floorId: floorId, |
|||
roomId: roomId |
|||
} |
|||
}) |
|||
} else { |
|||
this.$message({ |
|||
message: '当前账号没有权限', |
|||
type: 'warning' |
|||
}) |
|||
} |
|||
}, |
|||
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 |
|||
} else if (item.title.includes('借出确认')) { |
|||
locationIndex = 1 |
|||
} else if (item.title.includes('逾期警告')) { |
|||
locationIndex = 2 |
|||
} else if (item.title.includes('即将到期')) { |
|||
locationIndex = 2 |
|||
} |
|||
this.$router.push({ |
|||
name: 'lendManage', |
|||
params: { |
|||
locationIndex: locationIndex |
|||
} |
|||
}) |
|||
} else { |
|||
this.$message({ |
|||
message: '当前账号没有权限', |
|||
type: 'warning' |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style rel="stylesheet/scss" lang="scss" scoped> |
|||
@import "~@/assets/styles/lend-manage.scss"; |
|||
.dashboard-editor-container { |
|||
padding: 20px; |
|||
background-color: #031435; |
|||
position: relative; |
|||
|
|||
.chart-wrapper { |
|||
height: calc(100% - 40px); |
|||
} |
|||
} |
|||
@media (max-width: 1024px) { |
|||
.chart-wrapper { |
|||
padding: 8px; |
|||
} |
|||
} |
|||
.warehouse-tab { |
|||
color: #fff; |
|||
.warehouse-nav { |
|||
display: flex; |
|||
justify-content: space-around; |
|||
position: absolute; |
|||
bottom: 15px; |
|||
z-index: 11; |
|||
width: 100%; |
|||
padding: 0; |
|||
li { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
flex-wrap: nowrap; |
|||
align-content: center; |
|||
justify-content: center; |
|||
height: 90px; |
|||
text-align: right; |
|||
font-size: 14px; |
|||
position: relative; |
|||
&:hover { |
|||
cursor: pointer; |
|||
} |
|||
span { |
|||
width: 72px; |
|||
height: 52px; |
|||
margin-bottom: 7px; |
|||
} |
|||
p { |
|||
text-align: left; |
|||
} |
|||
&:first-child span { |
|||
background: url("~@/assets/images/tab_fullview_logo.png") no-repeat; |
|||
} |
|||
&:nth-child(2) span { |
|||
background: url("~@/assets/images/tab_archives_logo.png") no-repeat; |
|||
} |
|||
&:nth-child(3) span { |
|||
background: url("~@/assets/images/tab_collate_logo.png") no-repeat; |
|||
} |
|||
&:nth-child(4) span { |
|||
background: url("~@/assets/images/tab_read_logo.png") no-repeat; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.el-col { |
|||
height: 100%; |
|||
} |
|||
.container-left, |
|||
.container-right, |
|||
.container-wrap, |
|||
.el-card, |
|||
.header-container-wrap { |
|||
min-height: 100%; |
|||
} |
|||
.warehose-el-table ::v-deep .el-table__header-wrapper { |
|||
box-shadow: inset 0px 0px 6px 1px #339cff; |
|||
background: none !important; |
|||
} |
|||
.container-wrap { |
|||
min-height: auto; |
|||
height: 100%; |
|||
// overflow: hidden; |
|||
} |
|||
.todo-list { |
|||
padding: 0 20px; |
|||
& li { |
|||
height: 42px; |
|||
line-height: 42px; |
|||
margin-bottom: 10px; |
|||
font-size: 13px; |
|||
color: #ffffff; |
|||
background: #02255f; |
|||
box-shadow: inset 0px 0px 6px 1px #339cff; |
|||
border-radius: 26px; |
|||
opacity: 1; |
|||
cursor: pointer; |
|||
&.warn-info{ |
|||
color: #F65163; |
|||
box-shadow: inset 0px 0px 15px 1px #f65164; |
|||
} |
|||
& p { |
|||
display: inline-block; |
|||
width: calc(100% - 140px); |
|||
padding-left: 10px; |
|||
text-overflow: ellipsis; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
word-break: break-all; |
|||
} |
|||
& span { |
|||
float: right; |
|||
padding-right: 10px; |
|||
} |
|||
|
|||
} |
|||
} |
|||
::v-deep |
|||
.el-table--striped |
|||
.el-table__body |
|||
tr.el-table__row--striped |
|||
td.el-table__cell { |
|||
background: #02255f; |
|||
} |
|||
.search-area { |
|||
width: 100%; |
|||
height: 100%; |
|||
margin: 0; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
::v-deep .search-main{ |
|||
padding: 0 0 0 20px; |
|||
.head-container{ |
|||
padding: 0; |
|||
width: 100% !important; |
|||
.search-input { |
|||
width: 100% !important; |
|||
} |
|||
.input-with-select{ |
|||
width: 100% !important; |
|||
} |
|||
} |
|||
} |
|||
.home-floor-tab{ |
|||
position: absolute; |
|||
right: 14px; |
|||
top: 10px; |
|||
color: #fff; |
|||
display: flex; |
|||
justify-self: flex-start; |
|||
p{ |
|||
font-size: 14px; |
|||
padding:2px 6px; |
|||
margin-right: 6px; |
|||
color: #339cff; |
|||
border: 1px solid #339cff; |
|||
border-radius: 4px; |
|||
cursor: pointer; |
|||
&.active-floor, |
|||
&:hover{ |
|||
color: #fff; |
|||
background-color: #113d72; |
|||
} |
|||
} |
|||
} |
|||
.icon-kongqizhiliangshuju{ |
|||
font-size: 14px; |
|||
color: #F65163; |
|||
margin-right: 6px |
|||
} |
|||
.env-title{ |
|||
width: 50px; |
|||
height: 40px; |
|||
line-height: 20px; |
|||
text-align: center; |
|||
font-size: 12px; |
|||
margin: 10px 10px 0 0; |
|||
} |
|||
.leakage-list { |
|||
display: flex; |
|||
justify-content:flex-start; |
|||
flex-wrap: wrap; |
|||
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; |
|||
height: 40px; |
|||
border: 1px solid #3581cc; |
|||
background-color: #02255f; |
|||
border-radius: 2px; |
|||
padding: 4px; |
|||
margin: 6px 10px 0 0; |
|||
font-size: 12px; |
|||
&::before { |
|||
content: ""; |
|||
position: absolute; |
|||
top: 2px; |
|||
right: 2px; |
|||
width: 0; |
|||
height: 0; |
|||
border-color: transparent #339cff; |
|||
border-width: 0 4px 4px 0; |
|||
border-style: solid; |
|||
} |
|||
p { |
|||
width: 100%; |
|||
} |
|||
span{ |
|||
width: 100%; |
|||
color: #18B08F; |
|||
text-align: right; |
|||
} |
|||
&.leakage-warn { |
|||
border-color: #f65164; |
|||
box-shadow: inset 0px 0px 15px 1px #f65164; |
|||
color: #f65164; |
|||
&::before { |
|||
border-color: transparent #f65164; |
|||
} |
|||
span { |
|||
color: #f65164; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.five-bottom{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
.env-title{ |
|||
line-height: 40px; |
|||
} |
|||
} |
|||
</style> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue