feat(securitySurveillance): 实现首页大屏数据展示和设备状态动态更新
- 新增获取首页大屏数据的API接口 - 在安全监控页面添加数据获取逻辑并传递给子组件 - 更新设备状态组件显示实时在线/离线数据 - 优化视频监控组件播放器初始化和销毁逻辑 - 调整API接口路径和参数格式 - 移除无用代码和注释
This commit is contained in:
		| @ -55,6 +55,8 @@ | ||||
| import { ref, onBeforeUnmount, getCurrentInstance, nextTick } from 'vue'; | ||||
| import { ElMessageBox, ElMessage } from 'element-plus'; | ||||
| import { listDevicePreset, addDevicePreset, updateDevicePreset, delDevicePreset, callDevicePreset } from '@/api/devicePreset'; | ||||
| import { getToken } from '@/api/securitySurveillance/index.js'; | ||||
|  | ||||
| import EZUIKit from 'ezuikit-js'; | ||||
|  | ||||
| const emit = defineEmits(['update']); | ||||
| @ -127,8 +129,8 @@ function addPre() { | ||||
| function videoPlay(obj: any) { | ||||
|     console.log('objobjobj', obj); | ||||
|  | ||||
|     getAccessToken().then((res: any) => { | ||||
|         if (res.code == 200 && obj.deviceSerial) { | ||||
|     getToken().then((res: any) => { | ||||
|         if (res.msg == "ok" && obj.deviceSerial) { | ||||
|             flvPlayer.value = new EZUIKit.EZUIKitPlayer({ | ||||
|                 audio: '0', | ||||
|                 id: 'video-container', | ||||
| @ -211,7 +213,12 @@ function handleDelete(row: any) { | ||||
|  | ||||
| // 调用 | ||||
| function handleDebug(row: any) { | ||||
|     callDevicePreset(row.id).then((res: any) => { | ||||
|     callDevicePreset([{ | ||||
|         deviceSerial: row.deviceSerial, | ||||
|         presetIndex: row.presetIndex, | ||||
|         channelNo: "1", | ||||
|         id: row.id | ||||
|     }]).then((res: any) => { | ||||
|         if (res.code === 200) { | ||||
|             ElMessage.success('调用成功'); | ||||
|         } | ||||
|  | ||||
| @ -137,7 +137,7 @@ | ||||
|                         {{ scope.row.projectName ? scope.row.projectName : '未分配' }} | ||||
|                     </template> | ||||
|                 </el-table-column> --> | ||||
|                 <el-table-column label="备注" align="center" prop="remark" min-width="100px" /> | ||||
|                 <!-- <el-table-column label="备注" align="center" prop="remark" min-width="100px" /> --> | ||||
|                 <!-- <el-table-column label="创建时间" align="center" prop="deviceCreateTime" min-width="100px"> | ||||
|                     <template #default="scope"> | ||||
|                         <span>{{ proxy.parseTime(scope.row.deviceCreateTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> | ||||
| @ -145,7 +145,7 @@ | ||||
|                 </el-table-column> --> | ||||
|                 <el-table-column label="操作" align="center" class-name="small-padding" min-width="160px" fixed="right"> | ||||
|                     <template #default="scope"> | ||||
|                         <el-button type="primary" link @click="handleUpdate(scope.row)" | ||||
|                         <!-- <el-button type="primary" link @click="handleUpdate(scope.row)" | ||||
|                             v-auth="'api/v1/system/ys7Devices/edit'"><el-icon> | ||||
|                                 <EditPen /> | ||||
|                             </el-icon>修改</el-button> | ||||
| @ -156,7 +156,7 @@ | ||||
|                         <el-button type="primary" link @click="onLinkProject(scope.row)" | ||||
|                             v-auth="'api/v1/system/ys7Devices/delete'"><el-icon> | ||||
|                                 <Link /> | ||||
|                             </el-icon>设备分配</el-button> | ||||
|                             </el-icon>设备分配</el-button> --> | ||||
|                         <el-button type="primary" link @click="addPreset(scope.row)"><el-icon> | ||||
|                                 <Plus /> | ||||
|                             </el-icon>添加预置位</el-button> | ||||
| @ -243,15 +243,17 @@ const resetQuery = (formEl: FormInstance | undefined) => { | ||||
| const ys7DevicesList = () => { | ||||
|     loading.value = true; | ||||
|     getMonitoringList({ | ||||
|         pageStart: 1, | ||||
|         pageSize: 10 | ||||
|         pageStart: state.tableData.param.pageNum, | ||||
|         pageSize: state.tableData.param.pageSize, | ||||
|     }).then((res: any) => { | ||||
|         let list = res.data ?? []; | ||||
|         let list = res.data.object ?? []; | ||||
|         state.tableData.data = list.map((item) => { | ||||
|             item.enctyptLoading = false; | ||||
|             return item; | ||||
|         }); | ||||
|         state.tableData.total = res.total; | ||||
|         state.tableData.total = Number(res.data.sum); | ||||
|         console.log(state.tableData); | ||||
|  | ||||
|         loading.value = false; | ||||
|     }); | ||||
| }; | ||||
| @ -270,17 +272,17 @@ const handleSelectionChange = (selection: any[]) => { | ||||
| }; | ||||
|  | ||||
| // 新增 | ||||
| const handleAdd = () => { | ||||
|     addRef.value.openDialog(); | ||||
| }; | ||||
| // const handleAdd = () => { | ||||
| //     addRef.value.openDialog(); | ||||
| // }; | ||||
|  | ||||
| // 编辑 | ||||
| const handleUpdate = (row?: Ys7DeviceVO) => { | ||||
|     if (!row) { | ||||
|         row = state.tableData.data.find((item) => item.id === state.ids[0])!; | ||||
|     } | ||||
|     editRef.value.openDialog(toRaw(row)); | ||||
| }; | ||||
| // // 编辑 | ||||
| // const handleUpdate = (row?: Ys7DeviceVO) => { | ||||
| //     if (!row) { | ||||
| //         row = state.tableData.data.find((item) => item.id === state.ids[0])!; | ||||
| //     } | ||||
| //     editRef.value.openDialog(toRaw(row)); | ||||
| // }; | ||||
|  | ||||
| // 删除 | ||||
| const handleDelete = (row?: Ys7DeviceVO) => { | ||||
| @ -340,22 +342,22 @@ const encryptChange = (row: Ys7DeviceVO | any) => { | ||||
| }; | ||||
|  | ||||
| //监听项目id刷新数据 | ||||
| const listeningProject = watch( | ||||
|     () => currentProject.value?.id, | ||||
|     (nid, oid) => { | ||||
|         tableData.value.param.projectId = nid; | ||||
|         initTableData(); | ||||
|     } | ||||
| ); | ||||
| // const listeningProject = watch( | ||||
| //     () => currentProject.value?.id, | ||||
| //     (nid, oid) => { | ||||
| //         tableData.value.param.projectId = nid; | ||||
| //         initTableData(); | ||||
| //     } | ||||
| // ); | ||||
|  | ||||
| // 页面加载 | ||||
| onMounted(() => { | ||||
|     initTableData(); | ||||
| }); | ||||
|  | ||||
| onUnmounted(() => { | ||||
|     listeningProject(); | ||||
| }); | ||||
| // onUnmounted(() => { | ||||
| //     listeningProject(); | ||||
| // }); | ||||
|  | ||||
| // 暴露变量 | ||||
| const { tableData, projectList } = toRefs(state); | ||||
|  | ||||
| @ -9,13 +9,13 @@ | ||||
|                     <el-col :span="12"> | ||||
|                         <div class="item"> | ||||
|                             <div class="status">在线</div> | ||||
|                             <div class="count" style="color: rgba(0, 184, 122, 1);">56</div> | ||||
|                             <div class="count" style="color: rgba(0, 184, 122, 1);">{{ data?.sumOnLine || 0 }}</div> | ||||
|                         </div> | ||||
|                     </el-col> | ||||
|                     <el-col :span="12"> | ||||
|                         <div class="item"> | ||||
|                             <div class="status">离线</div> | ||||
|                             <div class="count" style="color: rgba(102, 102, 102, 1);">10</div> | ||||
|                             <div class="count" style="color: rgba(102, 102, 102, 1);">{{ data?.sumOffLine || 0 }}</div> | ||||
|                         </div> | ||||
|                     </el-col> | ||||
|                     <el-col :span="12"> | ||||
| @ -146,4 +146,11 @@ | ||||
|     } | ||||
| } | ||||
| </style> | ||||
| <script setup></script> | ||||
| <script setup> | ||||
| const props = defineProps({ | ||||
|     data: { | ||||
|         type: Object, | ||||
|         default: () => ({}) | ||||
|     } | ||||
| }) | ||||
| </script> | ||||
| @ -70,7 +70,7 @@ | ||||
|                     <template v-else> | ||||
|                         <el-col :span="8" v-for="(item, index) in videoList" :key="index" class="video-wrapper"> | ||||
|                             <!-- 视频容器 --> | ||||
|                             <div class="item" :id="`smallVideo-${index + 1}`" ref="smallVideoRef"> | ||||
|                             <div class="item" :id="`smallVideo-${index + 1}`" :ref="el => smallVideoRefs[index] = el"> | ||||
|                                 <!-- <div class="title">{{ item.name }}</div> --> | ||||
|                             </div> | ||||
|                             <!-- 按钮放在最外层,与视频容器同级 --> | ||||
| @ -85,7 +85,7 @@ | ||||
|                 </el-row> | ||||
|                 <el-row v-if="!isExpanded"> | ||||
|                     <div class="pagination" v-if="activeTab !== 'record'"> | ||||
|                         <el-pagination layout="prev, pager, next, jumper, sizes" :total="totalRecords" | ||||
|                         <el-pagination layout="prev, pager, next, jumper" :total="totalRecords" | ||||
|                             v-model:current-page="pageStart" v-model:page-size="pageSize" :page-sizes="[20, 50, 100]" | ||||
|                             @current-change="handlePageChange" @size-change="handleSizeChange"></el-pagination> | ||||
|                     </div> | ||||
| @ -110,7 +110,7 @@ const pageSize = ref(4); // 默认请求4个视频(扩展布局) | ||||
| const totalRecords = ref(0); | ||||
| const activeTab = ref('live'); | ||||
| const bigVideoRef = ref<HTMLDivElement>(null); | ||||
| const smallVideoRef = ref<HTMLDivElement>(null); | ||||
| const smallVideoRefs = ref<Array<HTMLDivElement | null>>([]); // 使用数组存储多个视频容器引用 | ||||
|  | ||||
| const videoList = ref([]); | ||||
| // 存储第二页的数据,用于处理扩展视图右边视频不足的情况 | ||||
| @ -119,13 +119,26 @@ const nextPageVideoList = ref([]); | ||||
| const hasUsedNextPageData = ref(false); | ||||
|  | ||||
| const StructureEZUIKitPlayer = (item: any, index: number, isBig = false) => { | ||||
|     // 添加输入参数的安全检查 | ||||
|     if (!item || typeof item !== 'object') { | ||||
|         console.error('无效的视频项数据:', item); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     const containerId = isBig ? 'bigVideo' : isExpanded.value ? `smallVideo-expanded-${index + 1}` : `smallVideo-${index + 1}`; | ||||
|     const container = document.getElementById(containerId); | ||||
|  | ||||
|     // 先销毁旧的播放器实例(如果存在) | ||||
|     if (item.player) { | ||||
|         try { | ||||
|             item.player.destroy(); | ||||
|             // 添加安全检查,确保destroy方法存在 | ||||
|             if (typeof item.player.destroy === 'function') { | ||||
|                 // 尝试移除所有事件监听器 | ||||
|                 if (item.player.off) { | ||||
|                     item.player.off('*'); | ||||
|                 } | ||||
|                 item.player.destroy(); | ||||
|             } | ||||
|         } | ||||
|         catch (error) { | ||||
|             console.error('销毁播放器失败:', error); | ||||
| @ -133,18 +146,24 @@ const StructureEZUIKitPlayer = (item: any, index: number, isBig = false) => { | ||||
|         item.player = null; | ||||
|     } | ||||
|  | ||||
|     if (container) { | ||||
|         item.player = new EZUIKit.EZUIKitPlayer({ | ||||
|             audio: '0', | ||||
|             id: containerId, | ||||
|             accessToken: accessToken.value, | ||||
|             url: `ezopen://open.ys7.com/${item.deviceSerial}/1.hd.live`, | ||||
|             template: "pcLive", | ||||
|             width: container.clientWidth, | ||||
|             height: container.clientHeight, | ||||
|             plugin: ['talk'] | ||||
|         }); | ||||
|  | ||||
|     if (container && accessToken.value && item.deviceSerial) { | ||||
|         try { | ||||
|             item.player = new EZUIKit.EZUIKitPlayer({ | ||||
|                 audio: '0', | ||||
|                 id: containerId, | ||||
|                 accessToken: accessToken.value, | ||||
|                 url: `ezopen://open.ys7.com/${item.deviceSerial}/1.hd.live`, | ||||
|                 template: "pcLive", | ||||
|                 width: container.clientWidth, | ||||
|                 height: container.clientHeight, | ||||
|                 plugin: ['talk'] | ||||
|             }); | ||||
|         } catch (error) { | ||||
|             console.error('创建播放器失败:', error); | ||||
|             item.player = null; | ||||
|         } | ||||
|     } else { | ||||
|         console.error(`创建播放器失败,缺少必要条件: container=${!!container}, accessToken=${!!accessToken.value}, deviceSerial=${!!item.deviceSerial}`); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @ -157,21 +176,23 @@ const getTokenData = async () => { | ||||
| const getMonitoringListData = async () => { | ||||
|     // 根据当前视图类型设置请求数量 | ||||
|     const currentPageSize = isExpanded.value ? 4 : 9; | ||||
|     const { data } = await getMonitoringList({ | ||||
|     const { data: { object, sum }, } = await getMonitoringList({ | ||||
|         pageStart: pageStart.value, | ||||
|         pageSize: currentPageSize | ||||
|     }) | ||||
|     // totalRecords.value = data.total | ||||
|     videoList.value = data | ||||
|     totalRecords.value = Number(sum) | ||||
|     // 确保object是数组,如果不是则使用空数组 | ||||
|     videoList.value = Array.isArray(object) ? object : [] | ||||
| } | ||||
|  | ||||
| // 获取下一页视频数据 | ||||
| const getNextPageData = async () => { | ||||
|     const { data } = await getMonitoringList({ | ||||
|     const { data: { object, sum } } = await getMonitoringList({ | ||||
|         pageStart: pageStart.value + 1, | ||||
|         pageSize: 3 // 只需要3个视频 | ||||
|     }) | ||||
|     nextPageVideoList.value = data; | ||||
|     // 确保object是数组,如果不是则使用空数组 | ||||
|     nextPageVideoList.value = Array.isArray(object) ? object : []; | ||||
|     // 标记已经使用了下一页的数据 | ||||
|     hasUsedNextPageData.value = true; | ||||
| } | ||||
| @ -193,37 +214,62 @@ const initVideo = async () => { | ||||
|         bigVideoRef.value.innerHTML = ''; | ||||
|     } | ||||
|  | ||||
|     // 清理所有小视频容器的内容 | ||||
|     smallVideoRefs.value.forEach(ref => { | ||||
|         if (ref) { | ||||
|             ref.innerHTML = ''; | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     // 确保videoList是数组,如果不是则使用空数组 | ||||
|     const safeVideoList = Array.isArray(videoList.value) ? videoList.value : []; | ||||
|     // 确保nextPageVideoList是数组,如果不是则使用空数组 | ||||
|     const safeNextPageVideoList = Array.isArray(nextPageVideoList.value) ? nextPageVideoList.value : []; | ||||
|  | ||||
|     if (isExpanded.value) { | ||||
|         // 扩展布局:初始化大视频和右侧3个小视频 | ||||
|         StructureEZUIKitPlayer(videoList.value[activeIndex.value], 0, true); | ||||
|         // 安全检查:确保activeIndex在有效范围内 | ||||
|         const safeActiveIndex = Math.min(Math.max(activeIndex.value, 0), safeVideoList.length - 1); | ||||
|         if (safeVideoList.length > 0 && safeVideoList[safeActiveIndex] && typeof safeVideoList[safeActiveIndex] === 'object') { | ||||
|             StructureEZUIKitPlayer(safeVideoList[safeActiveIndex], 0, true); | ||||
|         } | ||||
|  | ||||
|         // 检查当前视频后面是否有足够的视频 | ||||
|         const remainingVideos = videoList.value.length - activeIndex.value - 1; | ||||
|         const remainingVideos = safeVideoList.length - safeActiveIndex - 1; | ||||
|  | ||||
|         if (remainingVideos >= 3) { | ||||
|             // 当前页后面有足够的视频,直接使用当前页的数据 | ||||
|             for (let i = 0; i < 3; i++) { | ||||
|                 const displayIndex = activeIndex.value + i + 1; | ||||
|                 StructureEZUIKitPlayer(videoList.value[displayIndex], i); | ||||
|                 const videoIndex = safeActiveIndex + 1 + i; | ||||
|                 if (safeVideoList[videoIndex] && typeof safeVideoList[videoIndex] === 'object') { | ||||
|                     // 修复索引:使用i而不是i+1,确保正确对应smallVideo-expanded-1, 2, 3 | ||||
|                     StructureEZUIKitPlayer(safeVideoList[videoIndex], i); | ||||
|                 } | ||||
|             } | ||||
|             // 重置已使用下一页数据的标记 | ||||
|             hasUsedNextPageData.value = false; | ||||
|         } else { | ||||
|             // 当前页后面视频不足3个,需要获取下一页的数据 | ||||
|             await getNextPageData(); | ||||
|             // 重新获取安全的视频列表 | ||||
|             const updatedSafeNextPageVideoList = Array.isArray(nextPageVideoList.value) ? nextPageVideoList.value : []; | ||||
|             // 使用当前页后面的视频和下一页的前几个视频 | ||||
|             let displayCount = 0; | ||||
|  | ||||
|             // 先显示当前页后面的视频 | ||||
|             for (let i = activeIndex.value + 1; i < videoList.value.length && displayCount < 3; i++) { | ||||
|                 StructureEZUIKitPlayer(videoList.value[i], displayCount); | ||||
|                 displayCount++; | ||||
|             for (let i = safeActiveIndex + 1; i < safeVideoList.length && displayCount < 3; i++) { | ||||
|                 if (safeVideoList[i] && typeof safeVideoList[i] === 'object') { | ||||
|                     // 修复索引:使用displayCount而不是displayCount+1 | ||||
|                     StructureEZUIKitPlayer(safeVideoList[i], displayCount); | ||||
|                     displayCount++; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // 再显示下一页的视频补充到3个 | ||||
|             for (let i = 0; i < nextPageVideoList.value.length && displayCount < 3; i++) { | ||||
|                 StructureEZUIKitPlayer(nextPageVideoList.value[i], displayCount); | ||||
|                 displayCount++; | ||||
|             for (let i = 0; i < updatedSafeNextPageVideoList.length && displayCount < 3; i++) { | ||||
|                 if (updatedSafeNextPageVideoList[i] && typeof updatedSafeNextPageVideoList[i] === 'object') { | ||||
|                     // 修复索引:使用displayCount而不是displayCount+1 | ||||
|                     StructureEZUIKitPlayer(updatedSafeNextPageVideoList[i], displayCount); | ||||
|                     displayCount++; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
| @ -234,9 +280,13 @@ const initVideo = async () => { | ||||
|             await getMonitoringListData(); | ||||
|             hasUsedNextPageData.value = false; | ||||
|         } | ||||
|         // 初始化所有视频 | ||||
|         videoList.value.forEach((item, index) => { | ||||
|             StructureEZUIKitPlayer(item, index); | ||||
|         // 初始化所有视频,添加更严格的类型检查 | ||||
|         safeVideoList.forEach((item, index) => { | ||||
|             if (item && typeof item === 'object') { | ||||
|                 StructureEZUIKitPlayer(item, index); | ||||
|             } else { | ||||
|                 console.warn(`跳过无效的视频项: ${index}`); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -244,37 +294,53 @@ const initVideo = async () => { | ||||
| const handlePageChange = (page: number) => { | ||||
|     pageStart.value = page; | ||||
|     // 这里可以添加分页逻辑 | ||||
|     getData() | ||||
| } | ||||
|  | ||||
| const handleSizeChange = (size: number) => { | ||||
|     pageSize.value = size; | ||||
|     // 根据当前视图类型设置合适的页面大小 | ||||
|     // 扩展视图固定为4,普通视图固定为9 | ||||
|     pageSize.value = isExpanded.value ? 4 : 9; | ||||
|     pageStart.value = 1; | ||||
|     // 这里可以添加分页逻辑 | ||||
|     getData() | ||||
| } | ||||
|  | ||||
| // 清理所有播放器实例 | ||||
| const cleanupPlayers = () => { | ||||
|     // 清理当前页视频的播放器 | ||||
|     videoList.value.forEach(item => { | ||||
|         if (item.player) { | ||||
|         if (item && item.player && typeof item.player.destroy === 'function') { | ||||
|             try { | ||||
|                 // 尝试移除所有事件监听器 | ||||
|                 if (item.player.off) { | ||||
|                     item.player.off('*'); | ||||
|                 } | ||||
|                 // 销毁播放器实例 | ||||
|                 item.player.destroy(); | ||||
|             } | ||||
|             catch (error) { | ||||
|                 console.error('销毁播放器失败:', error); | ||||
|             } | ||||
|             // 确保播放器引用被清除 | ||||
|             item.player = null; | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     // 清理下一页视频的播放器 | ||||
|     nextPageVideoList.value.forEach(item => { | ||||
|         if (item.player) { | ||||
|         if (item && item.player && typeof item.player.destroy === 'function') { | ||||
|             try { | ||||
|                 // 尝试移除所有事件监听器 | ||||
|                 if (item.player.off) { | ||||
|                     item.player.off('*'); | ||||
|                 } | ||||
|                 // 销毁播放器实例 | ||||
|                 item.player.destroy(); | ||||
|             } | ||||
|             catch (error) { | ||||
|                 console.error('销毁下一页视频播放器失败:', error); | ||||
|             } | ||||
|             // 确保播放器引用被清除 | ||||
|             item.player = null; | ||||
|         } | ||||
|     }); | ||||
| @ -287,15 +353,32 @@ watch(isExpanded, async (newValue, oldValue) => { | ||||
|  | ||||
|     // 从扩展视图切换到普通视图,需要重新请求9个视频 | ||||
|     if (newValue === false && oldValue === true) { | ||||
|         // 同步更新页面大小为9 | ||||
|         pageSize.value = 9; | ||||
|         // 清理所有播放器实例 | ||||
|         cleanupPlayers(); | ||||
|         // 等待DOM更新 | ||||
|         await nextTick(); | ||||
|         // 重新请求9个视频数据 | ||||
|         await getData(); | ||||
|         await getMonitoringListData(); | ||||
|         // 再次等待DOM更新 | ||||
|         await nextTick(); | ||||
|         // 初始化视频 | ||||
|         initVideo(); | ||||
|         // 恢复保存的activeIndex值 | ||||
|         activeIndex.value = currentActiveIndex; | ||||
|     } | ||||
|     // 从普通视图切换到扩展视图,不需要重新请求数据 | ||||
|     else if (newValue === true && oldValue === false) { | ||||
|         // 但是需要重新初始化视频布局 | ||||
|         // 同步更新页面大小为4 | ||||
|         pageSize.value = 4; | ||||
|         // 清理所有播放器实例 | ||||
|         cleanupPlayers(); | ||||
|         // 等待DOM更新完成后再初始化视频 | ||||
|         await nextTick(); | ||||
|         // 再次等待,确保DOM完全渲染 | ||||
|         await new Promise(resolve => setTimeout(resolve, 100)); | ||||
|         // 初始化视频 | ||||
|         initVideo(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @ -35,9 +35,11 @@ | ||||
|             <div class="box" style="height: 100%;display: flex;"> | ||||
|                 <div class="left" | ||||
|                     style="display: flex;flex-direction: column;height: 100%;justify-content: space-around;padding: 15px;"> | ||||
|                     <div style="color: rgba(102, 102, 102, 1);">今日录像时长</div> | ||||
|                     <div style="color: rgba(102, 102, 102, 1);">今日设备情况</div> | ||||
|                     <div><span | ||||
|                             style="font-size: 30px;font-weight: 400;letter-spacing: 0px;line-height: 36px;color: rgba(0, 0, 0, 1);font-weight: bold;">54</span> | ||||
|                             style="font-size: 30px;font-weight: 400;letter-spacing: 0px;line-height: 36px;color: rgba(0, 0, 0, 1);font-weight: bold;">{{ | ||||
|                                 data?.sumMon | ||||
|                             || 0}}</span> | ||||
|                         <span | ||||
|                             style="font-size: 12px;font-weight: 400;letter-spacing: 0px;line-height: 17.38px;color: rgba(154, 154, 154, 1);"> | ||||
|                             台 | ||||
| @ -48,14 +50,14 @@ | ||||
|                             style="width: 63px;height: 18px;border-radius: 16px;background: rgba(0, 184, 122, .3);text-align: center;"> | ||||
|                             <span | ||||
|                                 style="font-size: 12px;font-weight: 400;letter-spacing: 0;line-height: 17.38px;color: rgba(0, 184, 122, 1);"> | ||||
|                                 正常:<span>53</span> | ||||
|                                 正常:<span>{{ data?.sumOnLine || 0 }}</span> | ||||
|                             </span> | ||||
|                         </div> | ||||
|                         <div | ||||
|                             style="width: 63px;height: 18px;border-radius: 16px;background: rgba(227, 39, 39, .3);text-align: center;margin-left: 10px;"> | ||||
|                             <span | ||||
|                                 style="font-size: 12px;font-weight: 400;letter-spacing: 0;line-height: 17.38px;color: rgba(0, 184, 122, 1);color: red;"> | ||||
|                                 异常<span>53</span> | ||||
|                                 异常<span>{{ data?.sumOffLine || 0 }}</span> | ||||
|                             </span> | ||||
|                         </div> | ||||
|                         <!-- <div>异常:<span>1</span></div> --> | ||||
| @ -153,4 +155,11 @@ | ||||
|     margin-right: 30px; | ||||
| } | ||||
| </style> | ||||
| <script setup></script> | ||||
| <script setup> | ||||
| const props = defineProps({ | ||||
|     data: { | ||||
|         type: Object, | ||||
|         default: () => ({}) | ||||
|     } | ||||
| }) | ||||
| </script> | ||||
| @ -25,7 +25,7 @@ | ||||
|             </el-col> | ||||
|         </el-row> | ||||
|         <el-row style="margin-top: 20px;"> | ||||
|             <Top /> | ||||
|             <Top :data="data" /> | ||||
|         </el-row> | ||||
|         <el-row style="margin-top: 20px;" :gutter="25"> | ||||
|             <el-col :span="18"> | ||||
| @ -37,7 +37,7 @@ | ||||
|         </el-row> | ||||
|         <el-row style="margin-top: 20px;"> | ||||
|             <el-col> | ||||
|                 <Sbzt /> | ||||
|                 <Sbzt :data="data" /> | ||||
|             </el-col> | ||||
|         </el-row> | ||||
|     </div> | ||||
| @ -55,4 +55,11 @@ import Top from "./components/top" | ||||
| import Spjk from "./components/spjk" | ||||
| import Spgl from "./components/spgl"; | ||||
| import Sbzt from "./components/sbzt"; | ||||
| import { getHomeScreenData } from "@/api/securitySurveillance"; | ||||
| const data = ref(null) | ||||
| onMounted(() => { | ||||
|     getHomeScreenData().then(res => { | ||||
|         data.value = res.data | ||||
|     }) | ||||
| }) | ||||
| </script> | ||||
		Reference in New Issue
	
	Block a user