|
|
<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 = [] } })
// 初始加载数据
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>
|