<script lang="ts" setup name="Statistics"> import { getCurrentInstance, ref } from 'vue' import type { Ref } from 'vue' import { ElMessage, type DateModelType } from 'element-plus' import groupPng from '@/assets/images/dashboard/group.png' import devicePng from '@/assets/images/dashboard/device.png' import productPng from '@/assets/images/dashboard/product.png' import dataPng from '@/assets/images/dashboard/data.png' import { getDictByCode } from '@/api/system/dict' import { getGroupListPage } from '@/api/basic/group' import { getDeviceListPage } from '@/api/basic/device' const router = useRouter() // 每个展示块高度 const blockHeight = ref(300) // 上面概览数据 const overview = ref({ groupCount: '****', deviceCount: '****', productCount: '****', dataCount: '****', }) // ---------------------------------分组管理----------------------------------------------- // 默认查询条件 const groupListQuery = ref({ groupName: '', // 分组名 beginTime: '', // 创建时间-起始 endTime: '', // 创建时间-结束 offset: 1, limit: 20, }) const groupList: any = ref([]) const groupColumn: any = [ { text: '分组名称', value: 'groupName', align: 'center'}, { text: '分组内设备数量', value: 'deviceCount', align: 'center' }, { text: '订阅数量', value: 'subscribeCount', align: 'center' }, ] const groupTotal = ref(0) const groupLoadingTable = ref(false) // 获取分组数据 function fetchGroupList(isNowPage = false) { groupLoadingTable.value = true if (!isNowPage) { // 是否显示当前页,否则跳转第一页 groupListQuery.value.offset = 1 } getGroupListPage(groupListQuery.value).then((response) => { if (response.code === 200) { groupList.value = response.data.rows groupTotal.value = parseInt(response.data.total) // overview.value.groupCount = groupTotal.value + '' } groupLoadingTable.value = false }).catch(() => { groupLoadingTable.value = false }) } // ---------------------------------离线设备----------------------------------------------- // 默认查询条件 const offlineListQuery = ref({ groupId: '', // 分组 productId: '', devcode: '', imei: '', deviceType: '', status: '', endCell: '', offset: 1, limit: 20, }) const offlineList: any = ref([]) const offlineColumn: any = [ { text: '分组名称', value: 'groupName', align: 'center'}, { text: '设备编号', value: 'devcode', align: 'center' }, { text: '最后上传时间', value: 'logtime', align: 'center' }, { text: '无数据天数', value: 'count', align: 'center', width: '100' }, ] const offlineTotal = ref(0) const offlineLoadingTable = ref(false) // 获取离线设备 function fetchOfflineList(isNowPage = false) { offlineLoadingTable.value = true if (!isNowPage) { // 是否显示当前页,否则跳转第一页 offlineListQuery.value.offset = 1 } getDeviceListPage(offlineListQuery.value).then((response) => { if (response.code === 200) { offlineList.value = response.data.rows.map((item: any) => { return { ...item, } }) offlineTotal.value = parseInt(response.data.total) } offlineLoadingTable.value = false }).catch(() => { offlineLoadingTable.value = false }) } // ---------------------------------低电量设备----------------------------------------------- // 默认查询条件 const lowBatteryListQuery = ref({ groupId: '', // 分组 productId: '', devcode: '', imei: '', deviceType: '', status: '', endCell: '10', beginCell: '0', offset: 1, limit: 20, }) const lowBatteryList: any = ref([]) const lowBatteryColumn: any = [ { text: '分组名称', value: 'groupName', align: 'center'}, { text: '设备编号', value: 'devcode', align: 'center' }, { text: '最后上传时间', value: 'logtime', align: 'center' }, { text: '电量(%)', value: 'cell', align: 'center', width: '80', styleFilter: (row: any) => { return 'color: red' } }, ] const lowBatteryTotal = ref(0) const lowBatteryLoadingTable = ref(false) // 获取低电量数据 function fetchLowBatteryList(isNowPage = false) { lowBatteryLoadingTable.value = true if (!isNowPage) { // 是否显示当前页,否则跳转第一页 lowBatteryListQuery.value.offset = 1 } getDeviceListPage(lowBatteryListQuery.value).then((response) => { if (response.code === 200) { lowBatteryList.value = response.data.rows.map((item: any) => { return { ...item, } }) lowBatteryTotal.value = parseInt(response.data.total) } lowBatteryLoadingTable.value = false }).catch(() => { lowBatteryLoadingTable.value = false }) } // ---------------------------------异常设备----------------------------------------------- // 默认查询条件 const errorListQuery = ref({ groupId: '', // 分组 productId: '', devcode: '', imei: '', deviceType: '', status: '', endCell: '', offset: 1, limit: 20, }) const errorList: any = ref([]) const errorColumn: any = [ { text: '分组名称', value: 'groupName', align: 'center'}, { text: '设备编号', value: 'devcode', align: 'center' }, { text: '报警类型', value: 'count', align: 'center', width: '100' }, { text: '报警时间', value: 'count', align: 'center' }, ] const errorTotal = ref(0) const errorLoadingTable = ref(false) // 获取异常设备 function fetchErrorList(isNowPage = false) { errorLoadingTable.value = true if (!isNowPage) { // 是否显示当前页,否则跳转第一页 errorListQuery.value.offset = 1 } getDeviceListPage(errorListQuery.value).then((response) => { if (response.code === 200) { errorList.value = response.data.rows.map((item: any) => { return { ...item, } }) errorTotal.value = parseInt(response.data.total) } errorLoadingTable.value = false }).catch(() => { errorLoadingTable.value = false }) } // ---------------------------------异常设备----------------------------------------------- // 页数发生变化后的操作,可能是页码变化,可能是每页容量变化,此函数必写 const changePage = (val: { size?: number; page?: number }, type = '') => { switch(type) { case 'group': if (val && val.size) { groupListQuery.value.limit = val.size } if (val && val.page) { groupListQuery.value.offset = val.page } fetchGroupList(true) break; case 'offline': ElMessage.info('敬请期待') return if (val && val.size) { offlineListQuery.value.limit = val.size } if (val && val.page) { offlineListQuery.value.offset = val.page } fetchOfflineList(true) break; case 'lowBattery': if (val && val.size) { lowBatteryListQuery.value.limit = val.size } if (val && val.page) { lowBatteryListQuery.value.offset = val.page } fetchLowBatteryList(true) break; case 'error': ElMessage.info('敬请期待') return if (val && val.size) { errorListQuery.value.limit = val.size } if (val && val.page) { errorListQuery.value.offset = val.page } fetchErrorList(true) break; } } // 处理操作中的按钮 const handleOperateButton = (type = '', row: any) => { switch(type) { case 'group': router.push({ query: { type: 'detail', // id: row.id, id: '1922544288985513986' }, path: '/basic/group/detail', }) break default: // 离线设备、低电量设备、异常设备 router.push({ query: { type: 'detail', id: row.id, }, path: '/basic/device/detail?', }) break } } // 点击标题跳转页面 const handleClickTitle = (title = '') => { console.log('点击的title', title); switch(title) { case '分组管理': router.push('/basic/group/list') break; case '低电量设备(低于10%)': router.push({ path: '/basic/device/list', query: { fromPage: 'dashboard', queryType: 'lowBattery' } }) break; } } function calcBlockSize() { // 计算工作台区域高度 - 顶部-面包屑-边距 const bodyHeight = document.body.clientHeight - 50 - 20 blockHeight.value = (bodyHeight - 100) / 2 // 左侧菜单使用 } window.addEventListener('resize', () => { calcBlockSize() }) onBeforeMount(() => { calcBlockSize() }) onMounted(() => { fetchGroupList() // 获取分组表格 fetchLowBatteryList() // 获取低电量设备 // fetchOfflineList() // 获取离线设备 // fetchErrorList() // 获取异常设备 }) </script> <template> <app-container style="overflow: hidden;padding-top: 10px;"> <div style="display: flex;height: 90px;text-align: center;width: 100%;justify-content: space-evenly;"> <div class="item"> <el-image :src="groupPng" class="base-map-image" mode="fill" /> <div class="item-text"> <div style="color: #0f67e7;"> 分组数量 </div> <div class="num"> {{ overview.groupCount }} <!-- <span class="unit">台</span> --> </div> </div> </div> <div class="item"> <el-image :src="devicePng" class="base-map-image" mode="fill" /> <div class="item-text"> <div style="color: #0f67e7;"> 设备数量 </div> <div class="num"> {{ overview.deviceCount }} <!-- <span class="unit">台</span> --> </div> </div> </div> <div class="item"> <el-image :src="productPng" class="base-map-image" mode="fill" /> <div class="item-text"> <div style="color: #0f67e7;"> 产品数量 </div> <div class="num"> {{ overview.productCount }} <!-- <span class="unit">%</span> --> </div> </div> </div> <div class="item"> <el-image :src="dataPng" class="base-map-image" mode="fill" /> <div class="item-text"> <div style="color: #0f67e7;"> 今日收到数据 </div> <div class="num"> {{ overview.dataCount }} <!-- <span class="unit">%</span> --> </div> </div> </div> </div> <div class="device-bench"> <el-row :gutter="10"> <el-col :span="12"> <bench-col icon="icon-group1" title="分组管理" :height="blockHeight" @handleClickTitle="handleClickTitle"> <normal-table :data="groupList" :height="blockHeight - 94" :columns="groupColumn" :total="groupTotal" :query="groupListQuery" :list-loading="groupLoadingTable" @change="(val) => changePage(val, 'group')"> <template #preColumns> <el-table-column label="序号" width="55" align="center"> <template #default="scope"> {{ (groupListQuery.offset! - 1) * groupListQuery.limit! + scope.$index + 1 }} </template> </el-table-column> </template> <template #columns> <el-table-column fixed="right" label="操作" align="center" width="80"> <template #default="{ row }"> <el-button size="small" type="primary" link @click="handleOperateButton('group', row)"> 进入分组 </el-button> </template> </el-table-column> </template> </normal-table> </bench-col> </el-col> <el-col :span="12"> <bench-col icon="icon-offline" title="离线设备" :height="blockHeight" @handleClickTitle="handleClickTitle"> <normal-table :data="offlineList" :height="blockHeight - 94" :columns="offlineColumn" :total="offlineTotal" :query="offlineListQuery" :list-loading="offlineLoadingTable" @change="(val) => changePage(val, 'offline')"> <template #preColumns> <el-table-column label="序号" width="55" align="center"> <template #default="scope"> {{ (offlineListQuery.offset! - 1) * offlineListQuery.limit! + scope.$index + 1 }} </template> </el-table-column> </template> <template #columns> <el-table-column fixed="right" label="操作" align="center" width="80"> <template #default="{ row }"> <el-button size="small" type="primary" link @click="handleOperateButton('offline', row)"> 详情 </el-button> </template> </el-table-column> </template> </normal-table> </bench-col> </el-col> </el-row> </div> <div class="device-bench" style="margin-top: 10px;"> <el-row :gutter="10"> <el-col :span="12"> <bench-col icon="icon-lowBattery" title="低电量设备(低于10%)" :height="blockHeight" @handleClickTitle="handleClickTitle"> <normal-table :data="lowBatteryList" :height="blockHeight - 94" :columns="lowBatteryColumn" :total="lowBatteryTotal" :query="lowBatteryListQuery" :list-loading="lowBatteryLoadingTable" @change="(val) => changePage(val, 'lowBattery')"> <template #preColumns> <el-table-column label="序号" width="55" align="center"> <template #default="scope"> {{ (lowBatteryListQuery.offset! - 1) * lowBatteryListQuery.limit! + scope.$index + 1 }} </template> </el-table-column> </template> <template #columns> <el-table-column fixed="right" label="操作" align="center" width="80"> <template #default="{ row }"> <el-button size="small" type="primary" link @click="handleOperateButton('lowBattery', row)"> 详情 </el-button> </template> </el-table-column> </template> </normal-table> </bench-col> </el-col> <el-col :span="12"> <bench-col icon="icon-error" title="异常设备" :height="blockHeight" @handleClickTitle="handleClickTitle"> <normal-table :data="errorList" :height="blockHeight - 94" :columns="errorColumn" :total="errorTotal" :query="errorListQuery" :list-loading="errorLoadingTable" @change="(val) => changePage(val, 'error')"> <template #preColumns> <el-table-column label="序号" width="55" align="center"> <template #default="scope"> {{ (errorListQuery.offset! - 1) * errorListQuery.limit! + scope.$index + 1 }} </template> </el-table-column> </template> <template #columns> <el-table-column fixed="right" label="操作" align="center" width="80"> <template #default="{ row }"> <el-button size="small" type="primary" link @click="handleOperateButton('error', row)"> 详情 </el-button> </template> </el-table-column> </template> </normal-table> </bench-col> </el-col> </el-row> </div> </app-container> </template> <style lang="scss" scoped> .device-bench { width: 100%; height: 100%; box-sizing: border-box; .the-month-total-Data { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: space-around; padding: 0 20px; .title { display: flex; justify-content: space-between; font-weight: 500; margin-bottom: 3px; } .content { width: 100%; .item { display: flex; flex-direction: column; flex: 1; margin-right: 10px; padding: 3px 0; justify-content: center; align-items: center; background-image: linear-gradient(to bottom, #e9f5ff, #3d7eff); border-radius: 8px; &:last-child { margin-right: 0; } } } } .my-equipment { height: 100%; display: flex; flex-direction: column; justify-content: space-around; padding: 20px; .item { height: 40%; display: flex; flex-direction: column; justify-content: center; align-items: center; background-image: linear-gradient(to right, #caddff, #3d7eff); border-radius: 16px; } } } .item { width: 300px; display: flex; justify-content: left; align-items: center; height: 80px; border-radius: 10px; border: 2px solid #398bff; &:hover { background-color: #e7f1fd; cursor: pointer; color: #398bff; } } </style> <style lang="scss"> .bench-table { .el-table__header-wrapper { border-radius: 8px; } } .bench-table-header { th { font-weight: normal; font-size: 14px; } } .bench-table-row { border-radius: 8px; } .num { text-shadow: 0 0 5px #0f67e7; color: #0f67e7; font-size: 30px; padding-top: 2px; font-weight: bold; } .unit { color: #0f67e7; font-size: 14px; margin-left: 3px; } .item-text { text-shadow: 0 0 2px #0f67e7; flex: 1; text-align: center; font-size: 18px; } .base-map-image { width: 60px; height: 60px; margin-left: 20px; } </style>