Browse Source

站点报警

master
xuhuajiao 1 month ago
parent
commit
b71e210a9f
  1. 26
      src/api/assetDevice/index.js
  2. 637
      src/views/assetManage/monitor/index.vue
  3. 46
      src/views/home.vue

26
src/api/assetDevice/index.js

@ -27,9 +27,18 @@ export function FetchInitDeviceInfo(params) {
}
// 根据仓库iD获取全部设备
export function FetchDeviceAlllByWarehouseId(params) {
export function FetchDeviceAllByWarehouseId(params) {
return request({
url: 'api/device/getDeviceAlllByWarehouseId',
url: 'api/device/getDeviceAllByWarehouseId',
method: 'get',
params
})
}
// 站点监控
export function FetchWarehouseMonitoring(params) {
return request({
url: 'api/warehouse/warehouseMonitoring',
method: 'get',
params
})
@ -78,6 +87,15 @@ export function FetchDevicePasswordById(params) {
})
}
// 获取实时报警信息
export function FetchRealtimeAlarms(params) {
return request({
url: 'api/warehouse/getRealtimeAlarms',
method: 'get',
params
})
}
export default {
FetchFondsWarehouseTree,
FetchWarehouseTree,
@ -88,5 +106,7 @@ export default {
FetchDeviceTypeTree,
FetchDeviceDetailsById,
FetchDevicePasswordById,
FetchDeviceAlllByWarehouseId
FetchDeviceAllByWarehouseId,
FetchWarehouseMonitoring,
FetchRealtimeAlarms
}

637
src/views/assetManage/monitor/index.vue

@ -16,12 +16,12 @@
/>
</el-scrollbar>
</div>
<!--用户数据-->
<div class="elect-cont-right" style="background-color: transparent; padding: 0 !important;">
<div class="container-right" style="height: calc(100vh - 158px) !important;background-color: transparent !important; ">
<div class="container-right" style="height: calc(100vh - 158px) !important;background-color: transparent !important;">
<span class="right-top-line" />
<span class="left-bottom-line" />
<div class="monitor-list" style="height: calc(100%); overflow: hidden; overflow-y: scroll;">
<div class="monitor-list" style="height: 100%; overflow-y: auto;">
<el-card
v-for="(item, index) in warehouseCardList"
:key="index"
@ -32,21 +32,20 @@
<img src="@/assets/images/tab_archives_logo.png" alt="" style="display: block; width: 50px; margin-right: 10px;">
<div style="flex: 1;">
<div class="store-info-item store-top">
<p style="width:62%;">{{ item.warehouseName || '仓库' }} </p>
<p style="flex:1;">面积{{ item.warehouseArea || '0' }} </p>
<p style="width:62%;">{{ item.warehouse.warehouseName || '仓库' }}</p>
<p style="flex:1;">面积{{ item.warehouse.warehouseArea || '0' }} </p>
<i
style="width:6%; text-align: center; cursor: pointer;"
class="iconfont icon-wangluoshexiangtou"
@click.stop="openWarehouseCamera(item)"
@click.stop="openWarehouseCamera(item.warehouse)"
/>
</div>
<div class="store-info-item" style="font-size: 12px; color: #909399; margin-top: 10px;">
<!-- <i class="iconfont icon-yonghuguanli" /> -->
<div style="display: flex; justify-content: flex-start;">
<p v-if="item.administrator">{{ item.administrator }}</p>
<p v-if="item.contactPhone">{{ item.contactPhone }}</p>
<p v-if="item.warehouse.administrator">{{ item.warehouse.administrator }}</p>
<p v-if="item.warehouse.contactPhone">&nbsp;{{ item.warehouse.contactPhone }}</p>
</div>
<p v-if="item.lastSyncTime">最后同步时间: {{ item.lastSyncTime | parseTime }}</p>
<p v-if="item.warehouse.lastTime">最后同步时间: {{ item.warehouse.lastTime | parseTime }}</p>
</div>
</div>
</div>
@ -54,48 +53,64 @@
<ul class="store-monitor">
<li>
<span>当日进出</span>
<p>{{ item.todayInCount || '0' }}</p>
<p>{{ item.todayInCount || 0 }}</p>
</li>
<li>
<span>本月进出</span>
<p>{{ item.todayInCount || '0' }}</p>
<p>{{ item.monthlyInCount || 0 }}</p>
</li>
<li>
<span>本月入库</span>
<p>{{ item.todayInCount || '0' }}</p>
<p>{{ item.monthlyInboundCount || 0 }}</p>
</li>
<li>
<span>本月出库</span>
<p>{{ item.todayInCount || '0' }}</p>
<p>{{ item.monthlyOutboundCount || 0 }}</p>
</li>
<li>
<span>本月出入库异动</span>
<p>{{ item.todayInCount || '0' }}</p>
<p>{{ item.fluctuationCount || 0 }}</p>
</li>
<li>
<span>本月重点资产异动</span>
<p>{{ item.todayInCount || '0' }}</p>
<p>{{ item.fluctuationImportantCount || 0 }}</p>
</li>
</ul>
<div class="warning-text">
<i v-if="item.isWarningActive" class="iconfont icon-baojingjilu" />
<div v-if="item.isWarningActive" class="warning-text-scroll" :class="{ scroll: item.warningNeedScroll }">
<span :ref="el => setWarningRef(el, index)" class="scroll-text">{{ item.warningText }}</span>
<div v-if="item.isWarningActive" :ref="el => setWarningRef(el, index)" class="warning-text-scroll">
<div class="scroll-wrap">
<div v-for="(warn, warnIdx) in item.warnList" :key="warnIdx" class="scroll-item">
{{ warn.warnValue }}
</div>
<!-- 复制一份用于无缝循环 -->
<div v-for="(warn, warnIdx) in item.warnList" :key="'copy_'+warnIdx" class="scroll-item">
{{ warn.warnValue }}
</div>
</div>
</div>
</div>
</el-card>
<!-- 只有一个仓库都没有时才显示 -->
<div v-if="warehouseCardList.length === 0 && !crud.loading" class="no-device" style="width: 100%; height: 100%;">
<el-empty style="display: flex; flex-direction: column; align-items: center; padding: 0 !important; height: 100%;" :image-size="60" description="暂无仓库信息" />
<div v-if="warehouseCardList.length === 0 && !crud.loading" class="no-device">
<el-empty style="padding:80px 0;" :image-size="60" description="暂无仓库信息" />
</div>
</div>
</div>
</div>
</div>
<!-- 查看监控视频 -->
<el-dialog class="view-video" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :visible="hkVideoVisible" title="查看监控视频" :before-close="handleClose">
<!-- 监控视频弹窗 -->
<el-dialog
class="view-video"
append-to-body
:close-on-click-modal="false"
:modal-append-to-body="false"
:visible="hkVideoVisible"
title="查看监控视频"
:before-close="handleClose"
>
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog">
@ -106,24 +121,20 @@
</template>
<script>
import crudDevice, { FetchFondsWarehouseTree, FetchWarehouseTree } from '@/api/assetDevice/index'
import crudDevice, { FetchFondsWarehouseTree, FetchDeviceAllByWarehouseId } from '@/api/assetDevice/index'
import CRUD, { presenter, header, crud } from '@crud/crud'
import hkVideo from '@/views/components/hkVideo.vue'
// import { swiper, swiperSlide } from 'vue-awesome-swiper'
// import 'swiper/dist/css/swiper.css'
export default {
name: 'Monitor',
components: {
hkVideo
// swiper,
// swiperSlide
},
cruds() {
return CRUD({
title: '设备监控',
url: 'api/device/getDeviceAllByWarehouseId',
idField: 'id || deviceId',
title: '站点监控',
url: 'api/warehouse/warehouseMonitoring',
idField: 'warehouse.id',
sort: [],
crudMethod: { ...crudDevice },
optShow: {
@ -148,35 +159,20 @@ export default {
},
defaultCheckedKeys: [],
selectedTreeKey: null,
storeData: [],
//
warehouseCardList: [],
warningRefs: [], //
warningRefs: [],
warningIntervals: [],
warningScrollTasks: [],
hkVideoVisible: false,
hkConfig: {
username: null,
password: null,
ip: null,
port: null
},
swiperOptionContent: {
slidesPerView: 1, // 1
slidesPerColumn: 1, //
allowTouchMove: true, //
loop: false, //
autoplay: {
delay: 6000, // 3
disableOnInteraction: false //
},
pagination: { //
el: '.swiper-pagination',
clickable: true
}
}
}
},
created() {
//
FetchFondsWarehouseTree().then(res => {
const filteredData = this.filterTreeData(res)
const topParent = {
@ -189,203 +185,156 @@ export default {
this.selectFirstWarehouseNode()
})
}).catch(() => {})
//
this.getWarehouseTree()
},
mounted() {},
beforeDestroy() {
this.clearAllWarningScroll()
},
methods: {
[CRUD.HOOK.beforeRefresh](crud) {
[CRUD.HOOK.beforeRefresh]() {
this.crud.params.page = null
this.crud.params.size = null
},
[CRUD.HOOK.afterRefresh](crud) {
// + +
this.buildWarehouseCardList(crud.data || [])
},
// 6 23
getDeviceSlides(deviceList) {
const pageSize = 6
const slides = []
for (let i = 0; i < deviceList.length; i += pageSize) {
slides.push(deviceList.slice(i, i + pageSize))
}
return slides
},
getDeviceListBg(typeName) {
const styleMap = {
'RFID吸顶式安全门': { borderLeft: '2px solid rgba(3, 72, 243, 1)' },
'RFID固定式读写器': { borderLeft: '2px solid rgba(20, 201, 201, 1)' },
'RFID手持盘点终端': { borderLeft: '2px solid rgba(248, 183, 34, 1)' },
'网络高清球机': { borderLeft: '2px solid rgba(114, 46, 209, 1)' },
'智能一体机': { borderLeft: '2px solid rgba(244, 100, 123, 1)' },
'人脸识别门禁一体机': { borderLeft: '2px solid rgba(46, 125, 50, 1)' }
// 'RFID': { borderLeft: '2px solid rgba(3, 72, 243, 1)' },
// 'RFID': { borderLeft: '2px solid rgba(3, 72, 243, 1)' },
// 'RFID': { borderLeft: '2px solid rgba(3, 72, 243, 1)' },
// '': { borderLeft: '2px solid rgba(3, 72, 243, 1)' },
// '': { borderLeft: '2px solid rgba(3, 72, 243, 1)' },
// '': { borderLeft: '2px solid rgba(3, 72, 243, 1)' }
}
return styleMap[typeName] || { borderLeft: '2px solid rgba(20, 201, 201, 1)' }
},
getDeviceIconBg(typeName) {
const styleMap = {
'RFID吸顶式安全门': { backgroundColor: 'rgba(3, 72, 243, 0.1)' },
'RFID固定式读写器': { backgroundColor: 'rgba(20, 201, 201, 0.1)' },
'RFID手持盘点终端': { backgroundColor: 'rgba(248, 183, 34, 0.1)' },
'网络高清球机': { backgroundColor: 'rgba(114, 46, 209, 0.1)' },
'智能一体机': { backgroundColor: 'rgba(244, 100, 123, 0.1)' },
'人脸识别门禁一体机': { backgroundColor: 'rgba(46, 125, 50, 0.1)' }
}
return styleMap[typeName] || { backgroundColor: 'rgba(3, 72, 243, 0.1)' }
},
//
getDeviceIcon(typeName) {
const iconMap = {
'RFID吸顶式安全门': 'iconfont icon-saomiao',
'RFID固定式读写器': 'iconfont icon-rfidduxieqi',
'RFID手持盘点终端': 'iconfont icon-shouchipandianyi',
'网络高清球机': 'iconfont icon-wangluoshexiangtou',
'智能一体机': 'iconfont icon-yitiji',
'人脸识别门禁一体机': 'iconfont icon-renlianshibiejiqi'
}
return iconMap[typeName] || 'iconfont icon-default'
},
//
getDeviceIconStyle(typeName) {
const styleMap = {
'RFID吸顶式安全门': { fontSize: '12px' },
'RFID固定式读写器': { fontSize: '18px' },
'RFID手持盘点终端': { fontSize: '16px' },
'网络高清球机': { fontSize: '16px' },
'智能一体机': { fontSize: '14px' },
'人脸识别门禁一体机': { fontSize: '14px' }
}
return styleMap[typeName] || { fontSize: '12px' }
},
getWarehouseTree() {
FetchWarehouseTree().then(res => {
this.storeData = res || []
// 使
// this.storeData = []
this.storeData[0].lastSyncTime = '2026-04-03T08:33:19.014+00:00'
this.storeData[0].syncExplanation = '报警文案报警文案报警文案报警文案报警文案报警文案报警文案报警文案报警文案报警文案'
// this.storeData[2].lastSyncTime = '2026-04-03T08:33:19.014+00:00'
// this.storeData[2].syncExplanation = 'ddd'
// console.log('storeData', this.storeData)
}).catch(() => {})
[CRUD.HOOK.afterRefresh]() {
const apiList = this.crud.data || []
this.buildWarehouseCardList(apiList)
},
//
buildWarehouseCardList(deviceList) {
// 1.
if (!this.storeData.length) {
buildWarehouseCardList(apiResult) {
// ========== 使mock apiList ==========
// const apiList = [
// {
// warehouse: {
// id: 1,
// warehouseNo: 'S00101',
// warehouseName: '',
// warehouseArea: '1200',
// administrator: '',
// contactPhone: '13800138000',
// fondsNo: 'S001',
// lastTime: '2026-08-07 10:20:30'
// },
// todayInCount: 0,
// monthlyInCount: 11,
// monthlyInboundCount: 99,
// monthlyOutboundCount: 0,
// fluctuationCount: 0,
// fluctuationImportantCount: 0,
// warnList: []
// },
// {
// warehouse: {
// id: 2,
// warehouseNo: 'S00201',
// warehouseName: '',
// warehouseArea: '800',
// administrator: '',
// contactPhone: '13900139000',
// fondsNo: 'S002',
// lastTime: '2026-08-07 09:10:20'
// },
// todayInCount: 0,
// monthlyInCount: 0,
// monthlyInboundCount: 0,
// monthlyOutboundCount: 0,
// fluctuationCount: 0,
// fluctuationImportantCount: 0,
// warnList: [
// { warnValue: 'A001' },
// { warnValue: '11111' }
// ]
// }
// ]
// ========== mock ==========
const apiList = this.crud.data || []
if (!Array.isArray(apiList) || apiList.length === 0) {
this.warehouseCardList = []
return
}
// 2.
const currentFondsNo = this.selectedTreeKey?.fondsNo
// 3.
let allWarehousesInCurrentFonds = []
if (this.selectedTreeKey.id === 0) {
//
allWarehousesInCurrentFonds = this.storeData
let filterList = []
if (this.selectedTreeKey?.id === 0) {
filterList = apiList
} else {
//
allWarehousesInCurrentFonds = this.storeData.filter(
s => s.fondsNo === currentFondsNo
)
const selectFondsNo = this.selectedTreeKey?.fondsNo
filterList = apiList.filter(item => item.warehouse.fondsNo === selectFondsNo)
}
// 4.
const deviceGroup = {}
deviceList.forEach(item => {
const key = item.fondsNo + '_' + item.warehouseNo
if (!deviceGroup[key]) deviceGroup[key] = []
deviceGroup[key].push(item)
})
// 5.
const cardList = []
allWarehousesInCurrentFonds.forEach(warehouse => {
const key = warehouse.fondsNo + '_' + warehouse.warehouseNo
const deviceListOfWarehouse = deviceGroup[key] || [] //
let isWarningActive = false
let warningText = ''
const lastSyncTime = warehouse.lastSyncTime
const syncExplanation = warehouse.syncExplanation
if (lastSyncTime) {
try {
const now = new Date().getTime()
const syncTime = new Date(lastSyncTime).getTime()
if (!isNaN(syncTime)) {
const diffMinutes = (now - syncTime) / (1000 * 60)
if (diffMinutes > 10) {
isWarningActive = true
warningText = syncExplanation || '同步超时超过10分钟'
}
}
} catch (e) {
console.log(e)
}
const cardList = filterList.map(item => {
return {
...item,
isWarningActive: Array.isArray(item.warnList) && item.warnList.length > 0
}
cardList.push({
...warehouse,
deviceList: deviceListOfWarehouse,
isWarningActive,
warningText,
warningNeedScroll: false
})
})
this.warehouseCardList = cardList
// 6.
console.log('cardList', cardList)
this.$nextTick(() => {
this.startAllTextScroll()
})
},
// DOM
setWarningRef(el, index) {
if (el) this.warningRefs[index] = el
},
//
clearAllWarningScroll() {
this.warningScrollTasks.forEach(task => {
if (task && typeof task.stop === 'function') task.stop()
})
this.warningScrollTasks = []
},
startAllTextScroll() {
this.warehouseCardList.forEach((item, idx) => {
if (!item.isWarningActive) return
const scrollText = this.warningRefs[idx]
if (!scrollText) return
const scrollBox = scrollText.parentElement
if (!scrollBox) return
const textWidth = scrollText.scrollWidth
const boxWidth = scrollBox.clientWidth
this.warehouseCardList[idx].warningNeedScroll = textWidth > boxWidth
if (textWidth <= boxWidth) return
let pos = 0
const speed = 1
setInterval(() => {
pos -= speed
if (pos < -textWidth) pos = boxWidth
scrollText.style.transform = `translateX(${pos}px)`
}, 30)
this.clearAllWarningScroll()
this.warningRefs.forEach(el => {
if (!el) return
const wrapDom = el.querySelector('.scroll-wrap')
if (wrapDom) {
wrapDom.style.transform = `translateY(0px)`
wrapDom.style.transition = ''
}
})
this.warehouseCardList.forEach((card, idx) => {
if (!card.isWarningActive || !card.warnList || card.warnList.length <= 0) return
const boxDom = this.warningRefs[idx]
if (!boxDom) return
const wrapDom = boxDom.querySelector('.scroll-wrap')
if (!wrapDom) return
const itemHeight = 44
const originLen = card.warnList.length
const totalOriginHeight = originLen * itemHeight
let offset = 0
let timer = null
const scrollStep = () => {
//
wrapDom.style.transition = 'transform 0.6s ease-in-out'
offset += itemHeight
wrapDom.style.transform = `translateY(-${offset}px)`
timer = setTimeout(() => {
//
if (offset >= totalOriginHeight) {
wrapDom.style.transition = 'none'
offset = 0
wrapDom.style.transform = `translateY(0px)`
//
wrapDom.offsetHeight
}
scrollStep()
}, 3000) // 3s
}
const stop = () => {
clearTimeout(timer)
}
this.warningScrollTasks.push({ stop })
scrollStep()
})
},
//
filterTreeData(tree) {
return tree.map(node => {
if (node.type === 'warehouse') return null
@ -397,28 +346,15 @@ export default {
}).filter(item => item)
},
// //
// selectFirstWarehouseNode() {
// const root = this.warehouseTreeData[0]
// if (root && root.children && root.children.length) {
// const firstFonds = root.children[0]
// this.defaultCheckedKeys = [firstFonds.id]
// this.$refs.tree.setCurrentKey(firstFonds.id)
// this.handleNodeClick(firstFonds)
// }
// },
//
selectFirstWarehouseNode() {
const root = this.warehouseTreeData[0]
if (root) {
// id = 0
this.defaultCheckedKeys = [root.id]
this.$refs.tree.setCurrentKey(root.id)
this.handleNodeClick(root)
}
},
//
handleNodeClick(data) {
this.selectedTreeKey = data
if (this.selectedTreeKey.id === 0) {
@ -431,89 +367,114 @@ export default {
this.crud.toQuery()
},
//
handleClose() {
this.hkVideoVisible = false
},
openWarehouseCamera(warehouse) {
// warehouse.deviceList
const cameraList = warehouse.deviceList || []
//
const camera = cameraList.find(item => item.deviceTypeName === '网络高清球机')
if (!camera) {
this.$message.warning('该仓库暂无监控设备')
return
// async openWarehouseCamera(cardItem) {
// const warehouseNo = cardItem.warehouseNo
// try {
// //
// const res = await FetchDeviceAllByWarehouseId()
// const allDevices = res || []
// // 1.
// // 2.warehouseNo === warehouseNo
// const ballDevices = allDevices.filter(d => {
// return d.deviceTypeName === '' && d.warehouseNo === warehouseNo
// })
// if (ballDevices.length === 0) {
// this.$message.info('')
// return
// }
// console.log('', ballDevices)
// // id
// this.handleViewVideo(ballDevices[0].id)
// } catch (err) {
// console.error('', err)
// this.$message.error('')
// }
// },
async openWarehouseCamera(cardItem) {
const warehouseId = cardItem.id
try {
// warehouseId
const res = await FetchDeviceAllByWarehouseId({ warehouseId })
const allDevices = res || []
// allDevices
const ballDevices = allDevices.filter(d => d.deviceTypeName === '网络高清球机')
if (ballDevices.length === 0) {
this.$message.info('该仓库暂无网络高清球机设备')
return
}
console.log('当前仓库匹配的球机', ballDevices)
this.handleViewVideo(ballDevices[0].id)
} catch (err) {
console.error('获取仓库设备异常:', err)
this.$message.error('获取仓库设备失败')
}
// IDhandleViewVideo
this.handleViewVideo(camera.id)
},
handleViewVideo(data) {
const deviceId = data
Promise.all([
crudDevice.FetchDeviceDetailsById({ deviceId }),
crudDevice.FetchDevicePasswordById({ deviceId })
]).then(([detailRes, pwdRes]) => {
if (detailRes) {
const finalPassword = pwdRes || detailRes.devicePassword
this.hkConfig = {
username: detailRes.deviceAccount,
devicePassword: finalPassword,
ip: detailRes.deviceIp,
port: detailRes.devicePort
}
this.hkVideoVisible = true
this.$nextTick(() => {
this.$refs.hkVideoRef.initVideo()
})
async handleViewVideo(deviceId) {
try {
const [detailRes, pwdRes] = await Promise.all([
crudDevice.FetchDeviceDetailsById({ deviceId }),
crudDevice.FetchDevicePasswordById({ deviceId })
])
if (!detailRes) return
const finalPassword = pwdRes || detailRes.devicePassword
this.hkConfig = {
username: detailRes.deviceAccount,
password: finalPassword,
ip: detailRes.deviceIp,
port: detailRes.devicePort
}
}).catch(err => {
console.log('获取设备视频信息失败', err)
})
this.hkVideoVisible = true
this.$nextTick(() => {
this.$refs.hkVideoRef.initVideo()
})
} catch (err) {
console.error('打开视频失败:', err)
this.$message.error('获取监控设备信息失败')
}
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-tree{
.el-tree-node__content{
::v-deep .el-tree {
.el-tree-node__content {
font-size: 14px;
color: #545B65;
.tree-text{
font-size: 16px;
font-weight: 600;
color: #0C0E1E;
}
}
.el-tree-node__children{
.tree-text {
font-size: 14px !important;
font-weight: normal;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
display: inline-block;
min-width: 170px;
color: #545B65;
}
.el-tree-node__children {
.el-tree-node__content {
font-size: 14px;
color: #545B65;
}
}
}
.monitor-list{
.monitor-list {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
padding-top: 15px;
.list-card{
.list-card {
width: calc(100% / 3 - 20px);
margin: 0 10px 20px 10px;
}
}
::v-deep .el-card {
border-radius: 10px;
.el-card__header{
.el-card__header {
height: 66px;
padding: 12px 10px !important;
border-radius: 10px 10px 0 0;
@ -522,30 +483,27 @@ export default {
font-weight: 600;
background-color: #fff !important;
border-bottom: 1px solid #ebeef5 !important;
.store-info{
.store-info {
display: flex;
justify-content: flex-start;
align-items: center;
.store-info-item{
.store-info-item {
display: flex;
justify-content: space-between;
align-items: center;
p{
p {
margin-right: 6px;
}
&.store-top{
&.store-top {
justify-content: space-between;
.iconfont::before{
margin: 0 !important;
}
}
}
}
}
.el-card__body{
.el-card__body {
padding: 5px 10px;
border-radius: 0 0 10px 10px;
.store-monitor{
.store-monitor {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
@ -553,119 +511,78 @@ export default {
padding: 5px 5px 10px 5px;
line-height: 35px;
font-size: 14px;
li{
li {
width: calc(50% - 10px);
display: flex;
justify-content: space-between;
align-items: center;
&:nth-child(even){
&:nth-child(even) {
margin-left: 15px;
}
span{
span {
display: block;
width: 120px;
// color: #0348f3;
}
p{
p {
flex: 1;
text-align: right;
font-weight: bold;
color: #0C0E1E;
}
}
}
}
.warning-text{
.warning-text {
color: #F65163;
font-size: 14px;
font-weight: 600;
border-top: 1px solid #ebeef5 !important;
border-top: 1px solid #ebeef5;
display: flex;
align-items: center;
gap: 6px;
height: 44px;
overflow: hidden;
padding: 0 10px !important;
padding: 0 10px;
.iconfont{
.iconfont {
flex-shrink: 0;
}
.warning-text-scroll {
flex: 1;
height: 100%;
height: 44px;
overflow: hidden;
line-height: 44px;
position: relative;
}
.scroll-text {
display: inline-block;
white-space: nowrap;
.scroll-wrap {
position: absolute;
left: 0;
top: 0;
width: 100%;
}
.scroll-item {
height: 44px;
line-height: 44px;
white-space: nowrap;
}
}
&.warning-active{
.el-card__header{
&.warning-active {
.el-card__header {
background-color: rgba(85, 85, 85, 0.2) !important;
border-bottom: 1px solid #fff !important;
}
.el-card__body{
background-color: rgba(85, 85, 85, 0.2) !important;
.el-card__body {
background-color: rgba(85, 85, 85, 0.2) !important;
}
.warning-text{
border-top: 1px solid #fff !important;
.warning-text {
border-top: 1px solid #fff;
}
}
}
.view-video{
::v-deep .el-dialog{
width: 1000px !important;
}
}
.swiper-content{
height: 210px;
.device-grid {
display: grid;
grid-template-columns: repeat(1, 1fr); // 3
grid-template-rows: repeat(6, 30px); // 2
gap: 4px;
height: 100%;
}
.device-item {
display: flex;
justify-content: flex-start;
align-items: center;
// border-radius: 4px;
padding: 0 6px;
p{
flex: 1;
font-size: 14px;
margin-left: 10px;
text-align: left;
}
&:hover{
background-color: rgba(245, 249, 252, 1);
}
}
.swiper-slide-content{
height: 100%;
}
.iconfont::before{
margin-right: 0 !important;
.view-video {
::v-deep .el-dialog {
width: 1000px !important;
}
}
//
::v-deep .swiper-pagination {
bottom: 0 !important;
}
</style>

46
src/views/home.vue

@ -145,7 +145,7 @@
<span class="right-top-line" />
<span class="left-bottom-line" />
<h3 class="home-item-title">
报警设备
报警信息
</h3>
<div class="home-flowable-list" style="height: calc(100% - 45px); overflow-x: hidden;">
<el-table
@ -157,10 +157,10 @@
style="width: 100%"
>
<el-table-column prop="warehouseName" label="仓库名称" />
<el-table-column prop="syncExplanation" label="报警说明" />
<el-table-column prop="checkStartTime" label="最后同步时间" width="150px">
<el-table-column prop="warnValue" label="报警信息" />
<el-table-column prop="warnTime" label="报警时间" width="150px">
<template slot-scope="scope">
<div>{{ scope.row.checkStartTime | parseTime }}</div>
<div>{{ scope.row.warnTime | parseTime }}</div>
</template>
</el-table-column>
</el-table>
@ -182,6 +182,7 @@ import serverProgress from '@/views/components/echarts/serverProgress.vue'
import { FetchInitBaseInfo } from '@/api/stockTask/index'
import { FetchSystemInfo } from '@/api/home/cpu/index'
import { FetchInitStockTakeBill, FetchInitInOutBill } from '@/api/asset/index'
import { FetchRealtimeAlarms } from '@/api/assetDevice/index'
import { mapGetters } from 'vuex'
import { swiper, swiperSlide } from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'
@ -251,7 +252,9 @@ export default {
},
slidesPerView: 'auto'
},
alarmData: []
alarmData: [],
//
alarmTimer: null
}
},
computed: {
@ -267,8 +270,12 @@ export default {
this.getInitStockTakeBill(true)
this.getInitInOutBill(true) //
this.getSystemInfo()
this.getRealtimeAlarms()
},
mounted() {
// 30
this.startAlarmPoll()
//
this.$nextTick(() => {
if (this.$refs.stockTableRef) {
@ -298,7 +305,26 @@ export default {
}
})
},
beforeDestroy() {
//
this.clearAlarmPoll()
},
methods: {
// 30s
startAlarmPoll() {
this.clearAlarmPoll()
this.alarmTimer = setInterval(() => {
this.getRealtimeAlarms()
}, 30000)
},
//
clearAlarmPoll() {
if (this.alarmTimer) {
clearInterval(this.alarmTimer)
this.alarmTimer = null
}
},
handleMainData() {
const param = {
'userId': this.user.id
@ -466,6 +492,16 @@ export default {
sysFilesPercentage: 0
}
this.getSystemInfo()
},
//
getRealtimeAlarms() {
FetchRealtimeAlarms().then(res => {
if (res.code !== 500) {
this.alarmData = res
} else {
this.alarmData = []
}
})
}
}
}

Loading…
Cancel
Save