|
@@ -1,9 +1,9 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div
|
|
<div
|
|
|
- class="device-page grid grid-cols-[auto_1fr] grid-rows-[auto_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
|
|
|
|
|
|
|
+ class="device-page grid grid-cols-[auto_1fr] grid-rows-[auto_auto_minmax(0,1fr)] gap-3 gap-x-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
|
|
|
<!-- 左侧部门树 -->
|
|
<!-- 左侧部门树 -->
|
|
|
<DeptTreeSelect
|
|
<DeptTreeSelect
|
|
|
- class="row-span-2"
|
|
|
|
|
|
|
+ class="row-span-3"
|
|
|
:top-id="rootDeptId"
|
|
:top-id="rootDeptId"
|
|
|
:deptId="deptId"
|
|
:deptId="deptId"
|
|
|
v-model="queryParams.deptId"
|
|
v-model="queryParams.deptId"
|
|
@@ -18,7 +18,7 @@
|
|
|
:model="queryParams"
|
|
:model="queryParams"
|
|
|
size="default"
|
|
size="default"
|
|
|
label-width="68px"
|
|
label-width="68px"
|
|
|
- class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 py-3 flex items-center flex-wrap min-w-0">
|
|
|
|
|
|
|
+ class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 py-2 flex items-center flex-wrap min-w-0">
|
|
|
<div class="flex items-center gap-4 flex-wrap">
|
|
<div class="flex items-center gap-4 flex-wrap">
|
|
|
<el-form-item :label="t('iotDevice.yfCode')" prop="yfDeviceCode">
|
|
<el-form-item :label="t('iotDevice.yfCode')" prop="yfDeviceCode">
|
|
|
<el-input
|
|
<el-input
|
|
@@ -145,8 +145,14 @@
|
|
|
</div>
|
|
</div>
|
|
|
</el-form>
|
|
</el-form>
|
|
|
|
|
|
|
|
|
|
+ <div class="device-dashboard-grid min-w-0">
|
|
|
|
|
+ <DeviceTotalCard :total="dashboardTotal" :loading="dashboardLoading" />
|
|
|
|
|
+ <DeviceStatusCard :data="dashboardStatus" :loading="dashboardLoading" />
|
|
|
|
|
+ <DeviceClassifyTopCard :data="dashboardClassify" :loading="dashboardLoading" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- 列表 -->
|
|
<!-- 列表 -->
|
|
|
- <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg flex flex-col p-4 min-w-0">
|
|
|
|
|
|
|
+ <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg flex flex-col p-2 pt-3 min-w-0">
|
|
|
<div class="flex-1 relative min-h-0">
|
|
<div class="flex-1 relative min-h-0">
|
|
|
<el-auto-resizer class="absolute">
|
|
<el-auto-resizer class="absolute">
|
|
|
<template #default="{ width, height }">
|
|
<template #default="{ width, height }">
|
|
@@ -791,6 +797,9 @@ import { useRefreshStore } from '@/store/modules/pms/refreshStore'
|
|
|
import { Search } from '@element-plus/icons-vue'
|
|
import { Search } from '@element-plus/icons-vue'
|
|
|
import * as DeptApi from '@/api/system/dept'
|
|
import * as DeptApi from '@/api/system/dept'
|
|
|
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
|
|
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
|
|
|
|
|
+import DeviceTotalCard from './components/dashboard/DeviceTotalCard.vue'
|
|
|
|
|
+import DeviceStatusCard from './components/dashboard/DeviceStatusCard.vue'
|
|
|
|
|
+import DeviceClassifyTopCard from './components/dashboard/DeviceClassifyTopCard.vue'
|
|
|
const { ZmTable, ZmTableColumn } = useTableComponents()
|
|
const { ZmTable, ZmTableColumn } = useTableComponents()
|
|
|
|
|
|
|
|
/** 设备台账 列表 */
|
|
/** 设备台账 列表 */
|
|
@@ -855,6 +864,23 @@ const queryParams = reactive<any>({
|
|
|
const queryFormRef = ref() // 搜索的表单
|
|
const queryFormRef = ref() // 搜索的表单
|
|
|
const exportLoading = ref(false) // 导出的加载中
|
|
const exportLoading = ref(false) // 导出的加载中
|
|
|
const brandList = ref<any[]>([])
|
|
const brandList = ref<any[]>([])
|
|
|
|
|
+const dashboardLoading = ref(false)
|
|
|
|
|
+const dashboardTotal = ref(0)
|
|
|
|
|
+const dashboardStatus = ref<any[]>([])
|
|
|
|
|
+const dashboardClassify = ref<any[]>([])
|
|
|
|
|
+
|
|
|
|
|
+const dashboardQueryParams = reactive({
|
|
|
|
|
+ deptId: undefined as number | undefined,
|
|
|
|
|
+ yfDeviceCode: undefined as string | undefined,
|
|
|
|
|
+ deviceCode: undefined as string | undefined,
|
|
|
|
|
+ deviceName: undefined as string | undefined,
|
|
|
|
|
+ carNo: undefined as string | undefined,
|
|
|
|
|
+ deviceNo: undefined as string | undefined,
|
|
|
|
|
+ brandName: undefined as string | undefined,
|
|
|
|
|
+ deviceStatus: undefined as string | undefined,
|
|
|
|
|
+ assetProperty: undefined as string | undefined,
|
|
|
|
|
+ assetClass: undefined as number | string | undefined
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
const handleZmSortChange = (prop: string, order: 'asc' | 'desc' | null) => {
|
|
const handleZmSortChange = (prop: string, order: 'asc' | 'desc' | null) => {
|
|
|
queryParams.sortingFields = order ? [{ field: prop, order }] : []
|
|
queryParams.sortingFields = order ? [{ field: prop, order }] : []
|
|
@@ -883,10 +909,40 @@ const getList = async () => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const syncDashboardQuery = () => {
|
|
|
|
|
+ dashboardQueryParams.deptId = queryParams.deptId
|
|
|
|
|
+ dashboardQueryParams.yfDeviceCode = queryParams.yfDeviceCode
|
|
|
|
|
+ dashboardQueryParams.deviceCode = queryParams.deviceCode
|
|
|
|
|
+ dashboardQueryParams.deviceName = queryParams.deviceName
|
|
|
|
|
+ dashboardQueryParams.carNo = queryParams.carNo
|
|
|
|
|
+ dashboardQueryParams.deviceNo = queryParams.deviceNo
|
|
|
|
|
+ dashboardQueryParams.brandName = queryParams.brandName
|
|
|
|
|
+ dashboardQueryParams.deviceStatus = queryParams.deviceStatus
|
|
|
|
|
+ dashboardQueryParams.assetProperty = queryParams.assetProperty
|
|
|
|
|
+ dashboardQueryParams.assetClass = queryParams.assetClass
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const getDashboardData = async () => {
|
|
|
|
|
+ dashboardLoading.value = true
|
|
|
|
|
+ syncDashboardQuery()
|
|
|
|
|
+ try {
|
|
|
|
|
+ const [count, status, classify] = await Promise.all([
|
|
|
|
|
+ IotDeviceApi.getIotDeviceCount(dashboardQueryParams),
|
|
|
|
|
+ IotDeviceApi.getIotDeviceStatus(dashboardQueryParams),
|
|
|
|
|
+ IotDeviceApi.getIotDeviceClassify(dashboardQueryParams)
|
|
|
|
|
+ ])
|
|
|
|
|
+ dashboardTotal.value = Number(count ?? 0)
|
|
|
|
|
+ dashboardStatus.value = Array.isArray(status) ? status : []
|
|
|
|
|
+ dashboardClassify.value = Array.isArray(classify) ? classify : []
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ dashboardLoading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/** 处理部门被点击 */
|
|
/** 处理部门被点击 */
|
|
|
const handleDeptNodeClick = async (row) => {
|
|
const handleDeptNodeClick = async (row) => {
|
|
|
queryParams.deptId = row.id
|
|
queryParams.deptId = row.id
|
|
|
- await getList()
|
|
|
|
|
|
|
+ await Promise.all([getList(), getDashboardData()])
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 搜索按钮操作 */
|
|
/** 搜索按钮操作 */
|
|
@@ -975,17 +1031,32 @@ onMounted(async () => {
|
|
|
order: 'asc'
|
|
order: 'asc'
|
|
|
}
|
|
}
|
|
|
queryParams.sortingFields.push(sort)
|
|
queryParams.sortingFields.push(sort)
|
|
|
- await getList()
|
|
|
|
|
- refreshStore.registerCallback('devicerouter', getList)
|
|
|
|
|
|
|
+ await Promise.all([getList(), getDashboardData()])
|
|
|
|
|
+ refreshStore.registerCallback('devicerouter', () => {
|
|
|
|
|
+ Promise.all([getList(), getDashboardData()])
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
deptList.value = handleTree(await DeptApi.getSimpleDeptList())
|
|
deptList.value = handleTree(await DeptApi.getSimpleDeptList())
|
|
|
})
|
|
})
|
|
|
</script>
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
|
|
|
+@media (width <= 1440px) {
|
|
|
|
|
+ .device-dashboard-grid {
|
|
|
|
|
+ grid-template-columns: minmax(180px, 0.7fr) minmax(390px, 1fr) minmax(360px, 1.35fr);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
:deep(.el-form-item) {
|
|
:deep(.el-form-item) {
|
|
|
margin-bottom: 0;
|
|
margin-bottom: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.device-dashboard-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: minmax(190px, 0.55fr) minmax(430px, 1.18fr) minmax(420px, 1.42fr);
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+ min-height: 164px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
::v-deep .el-table__header-wrapper {
|
|
::v-deep .el-table__header-wrapper {
|
|
|
position: sticky !important;
|
|
position: sticky !important;
|
|
|
top: 0;
|
|
top: 0;
|