Compare commits

..

10 Commits

Author SHA1 Message Date
yangsy
2abfa8f2f7 format: DataTable funcation 2025-11-14 16:42:30 +08:00
yangsy
686fdc8724 refactor(query): remove unnecessary query calls and optimize global loading 2025-11-14 16:36:07 +08:00
yangsy
1ed091f54d refactor(diag-info): make all fields optional 2025-11-14 16:06:24 +08:00
yangsy
8a38da53d7 style(device-status-history-diag-card): timeline height 2025-11-14 15:48:05 +08:00
yangsy
098a315153 fix(device-common-card): render condition 2025-11-12 15:37:53 +08:00
yangsy
a5a6ff9dbe refactor(ndm-security-box-diag-info): make all fields optional 2025-11-12 15:37:27 +08:00
yangsy
be88c0b31a refactor(device-tree): UX of tree node 2025-11-12 14:22:13 +08:00
yangsy
d2791ad093 feat(device-tree): expand/fold station node when click it 2025-11-11 12:21:12 +08:00
yangsy
a583fa2a4b chore: update dependencies 2025-11-11 10:37:36 +08:00
yangsy
8f3c8b7992 refactor: extract isNvrCluster 2025-11-10 20:38:40 +08:00
34 changed files with 236 additions and 258 deletions

View File

@@ -20,15 +20,15 @@
"@tanstack/vue-query": "^5.83.1",
"@tanstack/vue-query-devtools": "^5.84.0",
"@vueuse/core": "^13.6.0",
"axios": "^1.11.0",
"axios": "^1.13.2",
"compressing": "^2.0.0",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
"dayjs": "^1.11.19",
"destr": "^2.0.5",
"echarts": "^6.0.0",
"es-toolkit": "^1.39.9",
"naive-ui": "^2.42.0",
"nanoid": "^5.1.5",
"es-toolkit": "^1.41.0",
"naive-ui": "^2.43.1",
"nanoid": "^5.1.6",
"pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.5.0",
"sass": "^1.90.0",

60
pnpm-lock.yaml generated
View File

@@ -21,8 +21,8 @@ importers:
specifier: ^13.6.0
version: 13.6.0(vue@3.5.18(typescript@5.8.3))
axios:
specifier: ^1.11.0
version: 1.11.0
specifier: ^1.13.2
version: 1.13.2
compressing:
specifier: ^2.0.0
version: 2.0.0
@@ -30,8 +30,8 @@ importers:
specifier: ^4.2.0
version: 4.2.0
dayjs:
specifier: ^1.11.13
version: 1.11.13
specifier: ^1.11.19
version: 1.11.19
destr:
specifier: ^2.0.5
version: 2.0.5
@@ -39,14 +39,14 @@ importers:
specifier: ^6.0.0
version: 6.0.0
es-toolkit:
specifier: ^1.39.9
version: 1.39.9
specifier: ^1.41.0
version: 1.41.0
naive-ui:
specifier: ^2.42.0
version: 2.42.0(vue@3.5.18(typescript@5.8.3))
specifier: ^2.43.1
version: 2.43.1(vue@3.5.18(typescript@5.8.3))
nanoid:
specifier: ^5.1.5
version: 5.1.5
specifier: ^5.1.6
version: 5.1.6
pinia:
specifier: ^3.0.3
version: 3.0.3(typescript@5.8.3)(vue@3.5.18(typescript@5.8.3))
@@ -1049,8 +1049,8 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
axios@1.11.0:
resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==}
axios@1.13.2:
resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -1179,8 +1179,8 @@ packages:
date-fns@3.6.0:
resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
dayjs@1.11.13:
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
dayjs@1.11.19:
resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==}
de-indent@1.0.2:
resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
@@ -1267,8 +1267,8 @@ packages:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
es-toolkit@1.39.9:
resolution: {integrity: sha512-9OtbkZmTA2Qc9groyA1PUNeb6knVTkvB2RSdr/LcJXDL8IdEakaxwXLHXa7VX/Wj0GmdMJPR3WhnPGhiP3E+qg==}
es-toolkit@1.41.0:
resolution: {integrity: sha512-bDd3oRmbVgqZCJS6WmeQieOrzpl3URcWBUVDXxOELlUW2FuW+0glPOz1n0KnRie+PdyvUZcXz2sOn00c6pPRIA==}
esbuild@0.25.8:
resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==}
@@ -1722,8 +1722,8 @@ packages:
muggle-string@0.4.1:
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
naive-ui@2.42.0:
resolution: {integrity: sha512-c7cXR2YgOjgtBadXHwiWL4Y0tpGLAI5W5QzzHksOi22iuHXoSGMAzdkVTGVPE/PM0MSGQ/JtUIzCx2Y0hU0vTQ==}
naive-ui@2.43.1:
resolution: {integrity: sha512-w52W0mOhdOGt4uucFSZmP0DI44PCsFyuxeLSs9aoUThfIuxms90MYjv46Qrr7xprjyJRw5RU6vYpCx4o9ind3A==}
peerDependencies:
vue: ^3.0.0
@@ -1732,8 +1732,8 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
nanoid@5.1.5:
resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==}
nanoid@5.1.6:
resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==}
engines: {node: ^18 || >=20}
hasBin: true
@@ -2222,8 +2222,8 @@ packages:
typescript:
optional: true
vueuc@0.4.64:
resolution: {integrity: sha512-wlJQj7fIwKK2pOEoOq4Aro8JdPOGpX8aWQhV8YkTW9OgWD2uj2O8ANzvSsIGjx7LTOc7QbS7sXdxHi6XvRnHPA==}
vueuc@0.4.65:
resolution: {integrity: sha512-lXuMl+8gsBmruudfxnMF9HW4be8rFziylXFu1VHVNbLVhRTXXV4njvpRuJapD/8q+oFEMSfQMH16E/85VoWRyQ==}
peerDependencies:
vue: ^3.0.11
@@ -3049,7 +3049,7 @@ snapshots:
'@vue/devtools-kit': 8.0.0
'@vue/devtools-shared': 8.0.0
mitt: 3.0.1
nanoid: 5.1.5
nanoid: 5.1.6
pathe: 2.0.3
vite-hot-client: 2.1.0(vite@7.1.12(@types/node@22.17.1)(jiti@2.5.1)(sass@1.90.0)(tsx@4.20.5))
vue: 3.5.18(typescript@5.8.3)
@@ -3194,7 +3194,7 @@ snapshots:
dependencies:
possible-typed-array-names: 1.1.0
axios@1.11.0:
axios@1.13.2:
dependencies:
follow-redirects: 1.15.11
form-data: 4.0.4
@@ -3333,7 +3333,7 @@ snapshots:
date-fns@3.6.0: {}
dayjs@1.11.13: {}
dayjs@1.11.19: {}
de-indent@1.0.2: {}
@@ -3405,7 +3405,7 @@ snapshots:
has-tostringtag: 1.0.2
hasown: 2.0.2
es-toolkit@1.39.9: {}
es-toolkit@1.41.0: {}
esbuild@0.25.8:
optionalDependencies:
@@ -3839,7 +3839,7 @@ snapshots:
muggle-string@0.4.1: {}
naive-ui@2.42.0(vue@3.5.18(typescript@5.8.3)):
naive-ui@2.43.1(vue@3.5.18(typescript@5.8.3)):
dependencies:
'@css-render/plugin-bem': 0.15.14(css-render@0.15.14)
'@css-render/vue3-ssr': 0.15.14(vue@3.5.18(typescript@5.8.3))
@@ -3860,11 +3860,11 @@ snapshots:
vdirs: 0.1.8(vue@3.5.18(typescript@5.8.3))
vooks: 0.2.12(vue@3.5.18(typescript@5.8.3))
vue: 3.5.18(typescript@5.8.3)
vueuc: 0.4.64(vue@3.5.18(typescript@5.8.3))
vueuc: 0.4.65(vue@3.5.18(typescript@5.8.3))
nanoid@3.3.11: {}
nanoid@5.1.5: {}
nanoid@5.1.6: {}
natural-compare@1.4.0: {}
@@ -4336,7 +4336,7 @@ snapshots:
optionalDependencies:
typescript: 5.8.3
vueuc@0.4.64(vue@3.5.18(typescript@5.8.3)):
vueuc@0.4.65(vue@3.5.18(typescript@5.8.3)):
dependencies:
'@css-render/vue3-ssr': 0.15.14(vue@3.5.18(typescript@5.8.3))
'@juggle/resize-observer': 3.4.0

View File

@@ -1,5 +1,5 @@
export interface NdmCameraDiagInfo {
[key: string]: any;
logTime: string;
info: string;
logTime?: string;
info?: string;
}

View File

@@ -1,14 +1,14 @@
export interface NdmDecoderDiagInfo {
[key: string]: any;
logTime: string;
stCommonInfo: {
设备ID: string;
软件版本: string;
生产厂商: string;
设备别名: string;
设备型号: string;
硬件版本: string;
内存使用率: string;
CPU使用率: string;
logTime?: string;
stCommonInfo?: {
设备ID?: string;
软件版本?: string;
生产厂商?: string;
设备别名?: string;
设备型号?: string;
硬件版本?: string;
内存使用率?: string;
CPU使用率?: string;
};
}

View File

@@ -1,31 +1,31 @@
export interface NdmNvrDiagInfo {
[key: string]: any;
logTime: string;
info: {
diskHealth: number[];
groupInfoList: {
freeSize: number;
state: number;
stateValue: string;
totalSize: number;
logTime?: string;
info?: {
diskHealth?: number[];
groupInfoList?: {
freeSize?: number;
state?: number;
stateValue?: string;
totalSize?: number;
}[];
};
stCommonInfo: {
设备ID: string;
软件版本: string;
生产厂商: string;
设备别名: string;
设备型号: string;
硬件版本: string;
内存使用率: string;
CPU使用率: string;
stCommonInfo?: {
设备ID?: string;
软件版本?: string;
生产厂商?: string;
设备别名?: string;
设备型号?: string;
硬件版本?: string;
内存使用率?: string;
CPU使用率?: string;
};
cdFanInfo: {
索引号: string;
'风扇转速(rpm)': string;
cdFanInfo?: {
索引号?: string;
'风扇转速(rpm)'?: string;
}[];
cdPowerSupplyInfo: {
索引号: string;
电源状态: string;
cdPowerSupplyInfo?: {
索引号?: string;
电源状态?: string;
}[];
}

View File

@@ -1,18 +1,19 @@
export interface NdmSecurityBoxDiagInfo {
[key: string]: any;
info: [
info?: [
{
addrCode: number;
circuits: NdmSecurityBoxCircuit[];
fanSpeeds: number[];
humidity: number;
switches: number[];
temperature: number;
addrCode?: number;
circuits?: NdmSecurityBoxCircuit[];
fanSpeeds?: number[];
humidity?: number;
switches?: number[];
temperature?: number;
},
];
stCommonInfo: {
内存使用率: string;
CPU使用率: string;
stCommonInfo?: {
[key: string]: any;
内存使用率?: string;
CPU使用率?: string;
};
}

View File

@@ -1,9 +1,9 @@
export interface NdmServerDiagInfo {
[key: string]: any;
commInfo: {
CPU使用率: string;
内存使用率: string;
磁盘使用率: string;
系统运行时间: string;
commInfo?: {
CPU使用率?: string;
内存使用率?: string;
磁盘使用率?: string;
系统运行时间?: string;
};
}

View File

@@ -2,10 +2,10 @@ export interface NdmSwitchDiagInfo {
[key: string]: any;
cpuRatio?: string; // 因环境不同可能不存在
memoryRatio?: string; // 因环境不同可能不存在
logTime: string;
info: {
overFlowPorts: string[];
portInfoList: NdmSwitchPortInfo[];
logTime?: string;
info?: {
overFlowPorts?: string[];
portInfoList?: NdmSwitchPortInfo[];
};
}

View File

@@ -155,10 +155,6 @@ const tablePagination = reactive<PaginationProps>({
const tableData = ref<DataTableRowData[]>([]);
const exportTableData = () => {
downloadTableData();
};
const onAfterModalEnter = () => {
getStaionAlarmList();
};
@@ -183,7 +179,7 @@ const onUpdateFilters: DataTableProps['onUpdateFilters'] = (filterState) => {
getStaionAlarmList();
};
const { mutate: getStaionAlarmList, isPending: isTableLoading } = useMutation({
const { mutate: getStaionAlarmList, isPending: tableLoading } = useMutation({
mutationFn: async () => {
const now = dayjs();
const res = await postNdmDeviceAlarmLogPage(station.value?.code ?? '', {
@@ -218,7 +214,7 @@ const { mutate: getStaionAlarmList, isPending: isTableLoading } = useMutation({
},
});
const { mutate: downloadTableData, isPending: isDownloading } = useMutation({
const { mutate: exportTableData, isPending: exporting } = useMutation({
mutationFn: async () => {
const now = dayjs();
const data = await ndmDeviceAlarmLogDefaultExportByTemplate(station.value?.code ?? '', {
@@ -275,12 +271,12 @@ const { mutate: downloadTableData, isPending: isDownloading } = useMutation({
<div style="flex: 0 0 auto; display: flex; align-items: center; padding: 8px 0">
<div style="font-size: medium">今日设备告警列表</div>
<NSpace style="margin-left: auto">
<NButton type="primary" :loading="isDownloading" @click="exportTableData">导出</NButton>
<NButton type="primary" :loading="exporting" @click="() => exportTableData()">导出</NButton>
</NSpace>
</div>
<div style="flex: 1 1 auto; min-height: 0">
<NDataTable
:loading="isTableLoading"
:loading="tableLoading"
:columns="tableColumns"
:data="tableData"
:pagination="tablePagination"

View File

@@ -8,6 +8,7 @@ import { computed, ref, toRefs } from 'vue';
import DeviceHeaderCard from './current-diag-card/device-header-card.vue';
import CameraHistoryDiagCard from './history-diag-card/camera-history-diag-card.vue';
import DeviceCommonCard from './current-diag-card/device-common-card.vue';
import type { NdmCameraDiagInfo } from '@/apis/domains';
const props = defineProps<{
stationCode: string;
@@ -22,7 +23,7 @@ const lastDiagInfo = computed(() => {
const result = destr<any>(ndmCamera.value.lastDiagInfo);
if (!result) return null;
if (typeof result !== 'object') return null;
return result;
return result as NdmCameraDiagInfo;
});
const commonInfo = computed(() => {

View File

@@ -8,11 +8,13 @@ const props = defineProps<{
const { commonInfo } = toRefs(props);
const cardShow = computed(() => !!commonInfo.value && Object.keys(commonInfo.value).length > 0);
const commonInfoEntries = computed(() => Object.entries(commonInfo.value ?? {}));
</script>
<template>
<NCard v-if="commonInfo" size="small" hoverable>
<NCard v-if="cardShow" size="small" hoverable>
<template #header>
<div>设备信息</div>
</template>

View File

@@ -21,10 +21,10 @@ const debugModeStore = useDebugModeStore();
const { stationCode, ndmDecoder } = toRefs(props);
const lastDiagInfo = computed(() => {
const result = destr<NdmDecoderDiagInfo>(ndmDecoder.value.lastDiagInfo);
const result = destr<any>(ndmDecoder.value.lastDiagInfo);
if (!result) return null;
if (typeof result !== 'object') return null;
return result;
return result as NdmDecoderDiagInfo;
});
const commonInfo = computed<Record<string, string> | undefined>(() => {
@@ -37,8 +37,8 @@ const commonInfo = computed<Record<string, string> | undefined>(() => {
return info;
});
const cpuUsage = computed(() => lastDiagInfo.value?.stCommonInfo.CPU使用率);
const memUsage = computed(() => lastDiagInfo.value?.stCommonInfo.内存使用率);
const cpuUsage = computed(() => lastDiagInfo.value?.stCommonInfo?.CPU使用率);
const memUsage = computed(() => lastDiagInfo.value?.stCommonInfo?.内存使用率);
const selectedTab = ref('设备状态');
</script>

View File

@@ -119,6 +119,9 @@ defineExpose({
<div v-if="timelineItems.length === 0" style="width: 100%; display: flex; color: #666">
<div style="margin: auto">暂无记录</div>
</div>
<NTimeline v-else-if="timelineItems.length <= DEFAULT_PAGE_SIZE">
<NTimelineItem v-for="{ type, title, content, time } in timelineItems" :key="time" :type="type" :title="title" :content="content" :time="time"></NTimelineItem>
</NTimeline>
<NScrollbar v-else x-scrollable style="height: 500px">
<NTimeline>
<NTimelineItem v-for="{ type, title, content, time } in timelineItems" :key="time" :type="type" :title="title" :content="content" :time="time"></NTimelineItem>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import type { NdmNvrResultVO } from '@/apis/models';
import { isNvrCluster } from '@/components/helper';
import dayjs from 'dayjs';
import { NButton, NCard, NDatePicker, NFlex, NGi, NGrid, NSelect, type DatePickerProps, type SelectOption } from 'naive-ui';
import { computed, onMounted, reactive, ref, toRefs, useTemplateRef } from 'vue';
@@ -66,12 +67,11 @@ onMounted(() => {
});
const diagCards = computed<SelectOption[]>(() => {
const isCluster = (maybeNvrCluster: NdmNvrResultVO) => !!maybeNvrCluster.clusterList?.trim() && maybeNvrCluster.clusterList !== maybeNvrCluster.ipAddress;
const baseOptions: SelectOption[] = [
{ label: '设备状态', value: 'status' },
{ label: '设备告警', value: 'alarm' },
];
if (!isCluster(ndmNvr.value)) {
if (!isNvrCluster(ndmNvr.value)) {
baseOptions.push({ label: '硬件使用率', value: 'usage' }, { label: '硬盘健康', value: 'health' });
}
return baseOptions;

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import type { NdmNvrDiagInfo } from '@/apis/domains';
import type { NdmNvrResultVO } from '@/apis/models';
import { isNvrCluster } from '@/components/helper';
import { useDebugModeStore } from '@/stores/debug-mode';
import { destr } from 'destr';
import { NCard, NFlex, NTabPane, NTabs } from 'naive-ui';
@@ -23,14 +24,14 @@ const debugModeStore = useDebugModeStore();
const { stationCode, ndmNvr } = toRefs(props);
const lastDiagInfo = computed(() => {
const result = destr<NdmNvrDiagInfo>(ndmNvr.value.lastDiagInfo);
const result = destr<any>(ndmNvr.value.lastDiagInfo);
if (!result) return null;
if (typeof result !== 'object') return null;
return result;
return result as NdmNvrDiagInfo;
});
const cpuUsage = computed(() => lastDiagInfo.value?.stCommonInfo.CPU使用率);
const memUsage = computed(() => lastDiagInfo.value?.stCommonInfo.内存使用率);
const cpuUsage = computed(() => lastDiagInfo.value?.stCommonInfo?.['CPU使用率']);
const memUsage = computed(() => lastDiagInfo.value?.stCommonInfo?.['内存使用率']);
const commonInfo = computed<Record<string, string> | undefined>(() => {
const info = lastDiagInfo.value?.stCommonInfo;
@@ -42,14 +43,11 @@ const commonInfo = computed<Record<string, string> | undefined>(() => {
return info;
});
const diskHealth = computed(() => lastDiagInfo.value?.info.diskHealth);
const groupInfoList = computed(() => lastDiagInfo.value?.info.groupInfoList);
const diskHealth = computed(() => lastDiagInfo.value?.info?.diskHealth);
const groupInfoList = computed(() => lastDiagInfo.value?.info?.groupInfoList);
const isCluster = computed(() => {
const { ipAddress, clusterList } = ndmNvr.value;
if (!clusterList?.trim()) return false;
if (clusterList === ipAddress) return false;
return true;
return isNvrCluster(ndmNvr.value);
});
const selectedTab = ref('设备状态');

View File

@@ -23,10 +23,10 @@ const debugModeStore = useDebugModeStore();
const { stationCode, ndmSecurityBox } = toRefs(props);
const lastDiagInfo = computed(() => {
const result = destr<NdmSecurityBoxDiagInfo>(ndmSecurityBox.value.lastDiagInfo);
const result = destr<any>(ndmSecurityBox.value.lastDiagInfo);
if (!result) return null;
if (typeof result !== 'object') return null;
return result;
return result as NdmSecurityBoxDiagInfo;
});
const commonInfo = computed<Record<string, string> | undefined>(() => {
@@ -39,15 +39,15 @@ const commonInfo = computed<Record<string, string> | undefined>(() => {
return info;
});
const cpuUsage = computed(() => lastDiagInfo.value?.stCommonInfo.CPU使用率);
const memUsage = computed(() => lastDiagInfo.value?.stCommonInfo.内存使用率);
const cpuUsage = computed(() => lastDiagInfo.value?.stCommonInfo?.['CPU使用率']);
const memUsage = computed(() => lastDiagInfo.value?.stCommonInfo?.['内存使用率']);
const fanSpeeds = computed(() => lastDiagInfo.value?.info.at(0)?.fanSpeeds);
const temperature = computed(() => lastDiagInfo.value?.info.at(0)?.temperature);
const humidity = computed(() => lastDiagInfo.value?.info.at(0)?.humidity);
const switches = computed(() => lastDiagInfo.value?.info.at(0)?.switches);
const fanSpeeds = computed(() => lastDiagInfo.value?.info?.at(0)?.fanSpeeds);
const temperature = computed(() => lastDiagInfo.value?.info?.at(0)?.temperature);
const humidity = computed(() => lastDiagInfo.value?.info?.at(0)?.humidity);
const switches = computed(() => lastDiagInfo.value?.info?.at(0)?.switches);
const circuits = computed(() => lastDiagInfo.value?.info.at(0)?.circuits);
const circuits = computed(() => lastDiagInfo.value?.info?.at(0)?.circuits);
const selectedTab = ref('设备状态');
</script>

View File

@@ -20,16 +20,16 @@ const debugModeStore = useDebugModeStore();
const { stationCode, ndmServer } = toRefs(props);
const lastDiagInfo = computed(() => {
const result = destr<NdmServerDiagInfo>(ndmServer.value.lastDiagInfo);
const result = destr<any>(ndmServer.value.lastDiagInfo);
if (!result) return null;
if (typeof result !== 'object') return null;
return result;
return result as NdmServerDiagInfo;
});
const cpuUsage = computed(() => lastDiagInfo.value?.commInfo.CPU使用率);
const memUsage = computed(() => lastDiagInfo.value?.commInfo.内存使用率);
const diskUsage = computed(() => lastDiagInfo.value?.commInfo.磁盘使用率);
const runningTime = computed(() => lastDiagInfo.value?.commInfo.系统运行时间);
const cpuUsage = computed(() => lastDiagInfo.value?.commInfo?.['CPU使用率']);
const memUsage = computed(() => lastDiagInfo.value?.commInfo?.['内存使用率']);
const diskUsage = computed(() => lastDiagInfo.value?.commInfo?.['磁盘使用率']);
const runningTime = computed(() => lastDiagInfo.value?.commInfo?.['系统运行时间']);
const selectedTab = ref('设备状态');
</script>

View File

@@ -21,16 +21,16 @@ const debugModeStore = useDebugModeStore();
const { stationCode, ndmSwitch } = toRefs(props);
const lastDiagInfo = computed(() => {
const result = destr<NdmSwitchDiagInfo>(ndmSwitch.value.lastDiagInfo);
const result = destr<any>(ndmSwitch.value.lastDiagInfo);
if (!result) return null;
if (typeof result !== 'object') return null;
return result;
return result as NdmSwitchDiagInfo;
});
const cpuUsage = computed(() => lastDiagInfo.value?.cpuRatio);
const memUsage = computed(() => lastDiagInfo.value?.memoryRatio);
const portInfoList = computed(() => lastDiagInfo.value?.info.portInfoList ?? []);
const portInfoList = computed(() => lastDiagInfo.value?.info?.portInfoList ?? []);
const selectedTab = ref('设备状态');
</script>

View File

@@ -11,6 +11,7 @@ const deviceTabPanes = Object.keys(DeviceType).map((key) => {
<script setup lang="ts">
import type { Station } from '@/apis/domains';
import type { NdmDeviceResultVO, NdmNvrResultVO } from '@/apis/models';
import { isNvrCluster } from '@/components/helper';
import type { LineDevices } from '@/composables/query';
import { DeviceType, DeviceTypeName, tryGetDeviceTypeVal, type DeviceTypeKey, type DeviceTypeVal } from '@/enums/device-type';
import { destr } from 'destr';
@@ -57,11 +58,19 @@ watch(
);
const selectedKeys = computed(() => (selectedDevice.value?.id ? [selectedDevice.value.id] : undefined));
// 选择设备
// 树节点交互
const onSelectDevice = (device: NdmDeviceResultVO, stationCode: string) => {
emit('select-device', device, stationCode);
};
const override: TreeOverrideNodeClickBehavior = () => 'none';
const override: TreeOverrideNodeClickBehavior = ({ option }) => {
const hasChildren = (option.children?.length ?? 0) > 0;
const isDeviceNode = !!option['device'];
if (hasChildren || !isDeviceNode) {
return 'toggleExpand';
} else {
return 'none';
}
};
const nodeProps: TreeProps['nodeProps'] = ({ option }) => {
return {
onDblclick: (payload: MouseEvent) => {
@@ -85,13 +94,12 @@ const lineDeviceTreeData = computed<Record<string, TreeOption[]>>(() => {
const onlineDevices = devices?.filter((device) => device.deviceStatus === '10');
const offlineDevices = devices?.filter((device) => device.deviceStatus === '20');
// 对于录像机需要根据clusterList字段以分号分隔设备IP进一步形成子树结构
const isCluster = (maybeNvrCluster: NdmNvrResultVO) => !!maybeNvrCluster.clusterList?.trim() && maybeNvrCluster.clusterList !== maybeNvrCluster.ipAddress;
if (paneName === DeviceType.Nvr) {
const nvrs = devices as NdmNvrResultVO[];
const nvrClusters: NdmNvrResultVO[] = [];
const nvrSingletons: NdmNvrResultVO[] = [];
for (const device of nvrs) {
if (isCluster(device)) {
if (isNvrCluster(device)) {
nvrClusters.push(device);
} else {
nvrSingletons.push(device);
@@ -194,7 +202,7 @@ const renderDeviceNodePrefix = (device: NdmDeviceResultVO, stationCode: string)
() => '查看',
);
};
return h('div', [/* renderViewDeviceButton(device, stationCode), */ renderDeviceStatusTag(device)]);
return h(NFlex, { size: 'small' }, { default: () => [renderViewDeviceButton(device, stationCode), renderDeviceStatusTag(device)] });
};
// ========== 设备树搜索 ==========
@@ -257,7 +265,7 @@ const scrollDeviceTreeToSelectedDevice = () => {
<template>
<div style="height: 100%; display: flex; flex-direction: column">
<div style="flex-shrink: 0; padding: 12px">
<NInput v-model:value="searchInput" placeholder="搜索设备、设备ID或IP地址" clearable />
<NInput v-model:value="searchInput" placeholder="搜索设备名称、设备ID或IP地址" clearable />
<NFlex justify="space-between" align="center">
<NRadioGroup v-model:value="statusInput">
<NRadio value="">全部</NRadio>

View File

@@ -1,2 +1,3 @@
export * from './device-alarm';
export * from './nvr-cluster';
export * from './switch-port';

View File

@@ -0,0 +1,8 @@
import type { NdmNvrResultVO } from '@/apis/models';
export const isNvrCluster = (maybeNvrCluster: NdmNvrResultVO) => {
const { ipAddress, clusterList } = maybeNvrCluster;
if (!clusterList?.trim()) return false;
if (clusterList === ipAddress) return false;
return true;
};

View File

@@ -1,3 +1,3 @@
export * from './domains';
export * from './use-line-alarm-counts-query';
export * from './use-line-alarms-query';

View File

@@ -1,16 +1,16 @@
import { LINE_ALARM_COUNTS_QUERY_KEY } from '@/constants';
import { useLineAlarmCountsStore } from '@/stores/line-alarm-counts';
import type { StationAlarmCounts } from './domains';
import type { Station } from '@/apis/domains';
import { postNdmDeviceAlarmLogPage } from '@/apis/requests';
import { LINE_ALARMS_QUERY_KEY } from '@/constants';
import { DeviceType, tryGetDeviceTypeVal } from '@/enums/device-type';
import { useLineAlarmsStore } from '@/stores/line-alarms';
import { useQueryControlStore } from '@/stores/query-control';
import { useStationStore } from '@/stores/station';
import { isCancelledError, useMutation, useQuery } from '@tanstack/vue-query';
import { runTask } from '@/utils/run-task';
import { storeToRefs } from 'pinia';
import { computed } from 'vue';
import dayjs from 'dayjs';
import { postNdmDeviceAlarmLogPage } from '@/apis/requests';
import type { Station } from '@/apis/domains';
import { DeviceType, tryGetDeviceTypeVal } from '@/enums/device-type';
import type { StationAlarmCounts } from './domains';
import { runTask } from '@/utils/run-task';
const createEmptyStationAlarmCounts = () => {
return {
@@ -26,7 +26,7 @@ const createEmptyStationAlarmCounts = () => {
};
};
export function useLineAlarmCountsQuery() {
export function useLineAlarmsQuery() {
const stationStore = useStationStore();
const { stationList } = storeToRefs(stationStore);
const queryControlStore = useQueryControlStore();
@@ -34,7 +34,7 @@ export function useLineAlarmCountsQuery() {
const { mutateAsync: getStationAlarmCounts } = useStationAlarmCountsMutation();
return useQuery({
queryKey: [LINE_ALARM_COUNTS_QUERY_KEY, alarmQueryStamp],
queryKey: [LINE_ALARMS_QUERY_KEY, alarmQueryStamp],
enabled: computed(() => alarmQueryStamp.value > 0),
staleTime: Infinity,
refetchOnMount: false,
@@ -58,8 +58,8 @@ interface StationAlarmCountsMutationParams {
}
function useStationAlarmCountsMutation() {
const lineAlarmCountsStore = useLineAlarmCountsStore();
const { lineAlarmCounts } = storeToRefs(lineAlarmCountsStore);
const lineAlarmsStore = useLineAlarmsStore();
const { lineAlarmCounts } = storeToRefs(lineAlarmsStore);
return useMutation<StationAlarmCounts, Error, StationAlarmCountsMutationParams>({
mutationFn: async ({ station, signal }) => {

View File

@@ -1,15 +1,15 @@
import type { StationDevices } from './domains';
import { ndmClient } from '@/apis/client';
import type { Station } from '@/apis/domains';
import { LINE_DEVICES_QUERY_KEY } from '@/constants';
import { DeviceType } from '@/enums/device-type';
import { useLineDevicesStore } from '@/stores/line-devices';
import { useQueryControlStore } from '@/stores/query-control';
import { useStationStore } from '@/stores/station';
import { isCancelledError, useMutation, useQuery } from '@tanstack/vue-query';
import { runTask } from '@/utils/run-task';
import { storeToRefs } from 'pinia';
import { computed } from 'vue';
import type { StationDevices } from './domains';
import { useLineDevicesStore } from '@/stores/line-devices';
import { LINE_DEVICES_QUERY_KEY } from '@/constants';
import { ndmClient } from '@/apis/client';
import type { Station } from '@/apis/domains';
import { runTask } from '@/utils/run-task';
const createEmptyStationDevices = (): StationDevices => {
return {

View File

@@ -1,4 +1,4 @@
export const STATION_LIST_QUERY_KEY = 'station-list';
export const LINE_DEVICES_QUERY_KEY = 'line-devices';
export const LINE_ALARM_COUNTS_QUERY_KEY = 'line-alarm-counts';
export const LINE_ALARMS_QUERY_KEY = 'line-alarms';
export const DEVICE_SNMP_LOGS_QUERY_KEY = 'device-snmp-logs';

View File

@@ -10,16 +10,18 @@ function renderIcon(icon: Component): () => VNode {
import type { NdmDeviceAlarmLogResultVO } from '@/apis/models';
import SettingsDrawer from '@/components/global/settings-drawer.vue';
import { useStationListQuery } from '@/composables/query';
import { STATION_LIST_QUERY_KEY, LINE_DEVICES_QUERY_KEY, LINE_ALARMS_QUERY_KEY } from '@/constants';
import { useCurrentAlarmsStore } from '@/stores/current-alarms';
import { useUserStore } from '@/stores/user';
import { Client as StompClient } from '@stomp/stompjs';
import { useIsFetching } from '@tanstack/vue-query';
import { AlertFilled, /* AreaChartOutlined, */ FileTextFilled, HomeFilled, LogoutOutlined, SettingOutlined, VideoCameraFilled } from '@vicons/antd';
import { ChevronDown, Debug } from '@vicons/carbon';
import type { AxiosError } from 'axios';
import { destr } from 'destr';
import { NBadge, NButton, NDropdown, NFlex, NIcon, NLayout, NLayoutContent, NLayoutFooter, NLayoutHeader, NLayoutSider, NMenu, NScrollbar, type DropdownOption, type MenuOption } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { h, onBeforeMount, onBeforeUnmount, onMounted, ref, watch, type Component, type VNode } from 'vue';
import { computed, h, onBeforeMount, onBeforeUnmount, onMounted, ref, watch, type Component, type VNode } from 'vue';
import { RouterLink, useRoute, useRouter } from 'vue-router';
const userStore = useUserStore();
@@ -38,6 +40,13 @@ watch(stationListQueryError, (newStationListQueryError) => {
}
});
const stationListFetchingCount = useIsFetching({ queryKey: [STATION_LIST_QUERY_KEY] });
const lineDevicesFetchingCount = useIsFetching({ queryKey: [LINE_DEVICES_QUERY_KEY] });
const lineAlarmsFetchingCount = useIsFetching({ queryKey: [LINE_ALARMS_QUERY_KEY] });
const fetchingCount = computed(() => {
return stationListFetchingCount.value + lineDevicesFetchingCount.value + lineAlarmsFetchingCount.value;
});
onBeforeMount(() => {
userStore.userGetInfo().catch((err) => window.$message.error((err as AxiosError).message));
});
@@ -104,7 +113,7 @@ const menuOptions = ref<MenuOption[]>([
icon: renderIcon(AlertFilled),
},
// {
// label: () => h(RouterLink, { to: '/statistics' }, { default: () => '设备性能统计' }),
// label: () => h(RouterLink, { to: '/statistics' }, { default: () => '设备数据统计' }),
// key: '/statistics',
// icon: renderIcon(AreaChartOutlined),
// },
@@ -133,13 +142,12 @@ const dropdownOptions = ref<DropdownOption[]>([
key: 'logout',
icon: renderIcon(LogoutOutlined),
onClick: async () => {
await userStore
.userLogout()
.then(() => {
window.$loadingBar.finish();
router.push('/login');
})
.catch(() => window.$message.error('退出登录失败'));
try {
await userStore.userLogout();
router.push('/login');
} catch (_) {
window.$message.error('退出登录失败');
}
},
},
]);
@@ -175,7 +183,10 @@ const openSettingsDrawer = () => {
<NLayout :native-scrollbar="false">
<NLayoutHeader bordered class="app-layout-header">
<NFlex justify="space-between" align="center" :size="8" style="width: 100%; height: 100%">
<span style="font-size: 16px; font-weight: 500; margin-left: 16px; cursor: pointer" @click="toDashboardPage">网络设备管理平台</span>
<NFlex>
<div style="font-size: 16px; font-weight: 500; margin-left: 16px; cursor: pointer" @click="toDashboardPage">网络设备管理平台</div>
<NButton text size="tiny" :loading="fetchingCount > 0" />
</NFlex>
<NFlex align="center" :size="0" style="height: 100%">
<!-- <ThemeSwitch /> -->
<NDropdown trigger="hover" show-arrow :options="dropdownOptions" @select="selectDropdownOption">

View File

@@ -2,9 +2,9 @@
import type { NdmDeviceAlarmLogResultVO } from '@/apis/models';
import { ndmDeviceAlarmLogDefaultExportByTemplate, postNdmDeviceAlarmLogPage, putNdmDeviceAlarmLog } from '@/apis/requests';
import { renderAlarmDateCell, renderAlarmTypeCell, renderDeviceTypeCell, renderFaultLevelCell } from '@/components/helper';
import { FaultLevel } from '@/enums/fault-level';
import { AlarmType } from '@/enums/alarm-type';
import { DeviceType, DeviceTypeCode, DeviceTypeName, type DeviceTypeVal } from '@/enums/device-type';
import { FaultLevel } from '@/enums/fault-level';
import { useCurrentAlarmsStore } from '@/stores/current-alarms';
import { useStationStore } from '@/stores/station';
import { downloadByData } from '@/utils/download';
@@ -192,7 +192,7 @@ const tablePagination = reactive<PaginationProps>({
},
});
const { mutate: getAlarmList, isPending: isTableLoading } = useMutation({
const { mutate: getAlarmList, isPending: tableLoading } = useMutation({
mutationFn: async () => {
const res = await postNdmDeviceAlarmLogPage('', {
model: {},
@@ -252,7 +252,7 @@ const { mutate: confirmAlarm } = useMutation({
},
});
const { mutate: downloadTableData, isPending: isDownloading } = useMutation({
const { mutate: exportTableData, isPending: exporting } = useMutation({
mutationFn: async () => {
const data = await ndmDeviceAlarmLogDefaultExportByTemplate('', {
model: {},
@@ -274,8 +274,6 @@ const { mutate: downloadTableData, isPending: isDownloading } = useMutation({
},
});
const exportTableData = () => downloadTableData();
onBeforeMount(() => getAlarmList());
</script>
@@ -349,7 +347,7 @@ onBeforeMount(() => getAlarmList());
<NGridItem>
<NSpace>
<NButton @click="onClickReset">重置</NButton>
<NButton type="primary" :loading="isTableLoading" @click="onClickQuery">查询</NButton>
<NButton type="primary" :loading="tableLoading" @click="onClickQuery">查询</NButton>
</NSpace>
</NGridItem>
</NGrid>
@@ -360,13 +358,13 @@ onBeforeMount(() => getAlarmList());
<div style="flex: 0 0 auto; display: flex; align-items: center; padding: 8px">
<div style="font-size: medium">设备告警列表</div>
<NSpace style="margin-left: auto">
<NButton type="primary" :loading="isDownloading" @click="exportTableData">导出</NButton>
<NButton type="primary" :loading="exporting" @click="() => exportTableData()">导出</NButton>
</NSpace>
</div>
<!-- 表格区域填满剩余空间 -->
<div style="flex: 1 1 auto; min-height: 0; padding: 8px">
<NDataTable :loading="isTableLoading" :columns="tableColumns" :data="tableData" :pagination="tablePagination" :single-line="false" remote flex-height style="height: 100%" />
<NDataTable :loading="tableLoading" :columns="tableColumns" :data="tableData" :pagination="tablePagination" :single-line="false" remote flex-height style="height: 100%" />
</div>
</div>
</template>

View File

@@ -1,56 +1,42 @@
<script setup lang="ts">
import type { Station } from '@/apis/domains';
import DeviceAlarmDetailModal from '@/components/dashboard-page/device-alarm-detail-modal.vue';
import DeviceParamsConfigModal from '@/components/dashboard-page/device-params-config-modal.vue';
import OfflineDeviceDetailModal from '@/components/dashboard-page/offline-device-detail-modal.vue';
import StationCard from '@/components/dashboard-page/station-card.vue';
import { useLineAlarmCountsQuery, useLineDevicesQuery } from '@/composables/query';
import { useStationStore } from '@/stores/station';
import { ndmExportDevices } from '@/apis/requests';
import { useLineAlarmsQuery, useLineDevicesQuery } from '@/composables/query';
import { useLayoutStore } from '@/stores/layout';
import { useLineAlarmsStore } from '@/stores/line-alarms';
import { useLineDevicesStore } from '@/stores/line-devices';
import { useStationStore } from '@/stores/station';
import { downloadByData } from '@/utils/download';
import { useMutation } from '@tanstack/vue-query';
import { NGrid, NGi } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { ref, watch } from 'vue';
import { useLineAlarmCountsStore } from '@/stores/line-alarm-counts';
import { useLayoutStore } from '@/stores/layout';
import DeviceStatistic from '@/components/dashboard-page/device-statistic.vue';
import { useMutation } from '@tanstack/vue-query';
import { ndmExportDevices } from '@/apis/requests';
import { downloadByData } from '@/utils/download';
import dayjs from 'dayjs';
import DeviceAlarmDetailModal from '@/components/dashboard-page/device-alarm-detail-modal.vue';
import DeviceParamsConfigModal from '@/components/dashboard-page/device-params-config-modal.vue';
import DeviceStatisticCard from '@/components/dashboard-page/device-statistic-card.vue';
import OfflineDeviceDetailModal from '@/components/dashboard-page/offline-device-detail-modal.vue';
import StationCard from '@/components/dashboard-page/station-card.vue';
const stationStore = useStationStore();
const { stationList } = storeToRefs(stationStore);
const lineDevicesStore = useLineDevicesStore();
const { lineDevices } = storeToRefs(lineDevicesStore);
const lineAlarmCountsStore = useLineAlarmCountsStore();
const { lineAlarmCounts } = storeToRefs(lineAlarmCountsStore);
const lineAlarmsStore = useLineAlarmsStore();
const { lineAlarmCounts } = storeToRefs(lineAlarmsStore);
const { isFetching: lineDevicesFetching, error: lineDevicesQueryError } = useLineDevicesQuery();
const { isFetching: lineAlarmCountsFetching, error: lineAlarmCountsQueryError } = useLineAlarmCountsQuery();
const { error: lineDevicesQueryError } = useLineDevicesQuery();
const { error: lineAlarmsQueryError } = useLineAlarmsQuery();
const layoutStore = useLayoutStore();
const { stationLayoutGridCols } = storeToRefs(layoutStore);
// 当设备查询或告警查询正在进行时,显示加载条
watch(
[lineDevicesFetching, lineAlarmCountsFetching],
([devicesFetching, alarmCountsFetching]) => {
if (devicesFetching || alarmCountsFetching) {
window.$loadingBar.start();
} else {
window.$loadingBar.finish();
}
},
{
immediate: true,
},
);
watch([lineDevicesQueryError, lineAlarmCountsQueryError], ([newLineDevicesQueryError, newLineAlarmCountsQueryError]) => {
watch([lineDevicesQueryError, lineAlarmsQueryError], ([newLineDevicesQueryError, newLineAlarmsQueryError]) => {
if (newLineDevicesQueryError) {
window.$message.error(newLineDevicesQueryError.message);
}
if (newLineAlarmCountsQueryError) {
window.$message.error(newLineAlarmCountsQueryError.message);
if (newLineAlarmsQueryError) {
window.$message.error(newLineAlarmsQueryError.message);
}
});
@@ -95,7 +81,7 @@ const openDeviceParamsConfigModal = (station: Station) => {
</script>
<template>
<DeviceStatistic
<DeviceStatisticCard
:station-list="stationList"
:line-devices="lineDevices"
:button-loading="exporting"

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { useQueryControlStore } from '@/stores/query-control';
import { NLayout, NLayoutContent } from 'naive-ui';
import { onBeforeUnmount } from 'vue';
import { useQueryControlStore } from '@/stores/query-control';
const queryControlStore = useQueryControlStore();
queryControlStore.disablePolling();

View File

@@ -1,20 +1,20 @@
<script setup lang="ts">
import { useDeviceSelection } from '@/composables/device';
import { useLineDevicesQuery, type LineDevices } from '@/composables/query';
import { useLineDevicesQuery } from '@/composables/query';
import { useLineDevicesStore } from '@/stores/line-devices';
import { useStationStore } from '@/stores/station';
import { ChevronBack } from '@vicons/ionicons5';
import { watchDebounced } from '@vueuse/core';
import { NEmpty, NIcon, NLayout, NLayoutContent, NLayoutSider, NPageHeader, NScrollbar, NSpin } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { onMounted, ref, watch } from 'vue';
import { onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import DeviceTree from '@/components/device-page/device-tree.vue';
import DeviceRenderer from '@/components/device-page/device-renderer.vue';
// 数据获取
const { isFetching: lineDevicesFetching, error: lineDevicesQueryError } = useLineDevicesQuery();
const { error: lineDevicesQueryError } = useLineDevicesQuery();
const stationStore = useStationStore();
const { stationList } = storeToRefs(stationStore);
const lineDevicesStore = useLineDevicesStore();
@@ -32,21 +32,6 @@ onMounted(() => {
initFromRoute(lineDevices.value);
});
// 加载条控制
watch(
lineDevicesFetching,
(fetching) => {
if (fetching) {
window.$loadingBar.start();
} else {
window.$loadingBar.finish();
}
},
{
immediate: true,
},
);
// 当设备数据更新时,需要重新配置设备树
watchDebounced(
lineDevices,
@@ -98,11 +83,6 @@ watch(lineDevicesQueryError, (newLineDevicesQueryError) => {
<DeviceRenderer :station-code="selectedStationCode" :device="selectedDevice" />
</NScrollbar>
</template>
<template v-else-if="lineDevicesFetching">
<div style="width: 100%; height: 100%; display: flex">
<NSpin style="margin: auto" />
</div>
</template>
<template v-else>
<div style="width: 100%; height: 100%; display: flex">
<NEmpty description="选择设备查看诊断数据" style="margin: auto" />

View File

@@ -30,7 +30,6 @@ const vimpOperationTypeOptions: SelectOption[] = [
<script setup lang="ts">
import type { NdmVimpLogResultVO } from '@/apis/models/device';
import { ndmVimpLogDefaultExportByTemplate, postNdmVimpLogPage } from '@/apis/requests';
import { useStationListQuery } from '@/composables/query';
import { useStationStore } from '@/stores/station';
import { downloadByData } from '@/utils/download';
import { useMutation } from '@tanstack/vue-query';
@@ -57,7 +56,6 @@ import {
import { storeToRefs } from 'pinia';
import { computed, h, onMounted, reactive, ref, watch, watchEffect } from 'vue';
useStationListQuery();
const stationStore = useStationStore();
const { stationList, onlineStationList } = storeToRefs(stationStore);
@@ -187,7 +185,7 @@ const tablePagination = reactive<PaginationProps>({
},
});
const { mutate: getVimpLogList, isPending: isTableLoading } = useMutation({
const { mutate: getVimpLogList, isPending: tableLoading } = useMutation({
mutationFn: async () => {
if (!searchFields.stationCode) throw Error('请选择车站');
const res = await postNdmVimpLogPage(searchFields.stationCode, {
@@ -228,7 +226,7 @@ const onClickQuery = () => {
getVimpLogList();
};
const { mutate: downloadTableData, isPending: isDownloading } = useMutation({
const { mutate: exportTableData, isPending: exporting } = useMutation({
mutationFn: async () => {
if (!searchFields.stationCode) throw Error('请选择车站');
const data = await ndmVimpLogDefaultExportByTemplate(searchFields.stationCode, {
@@ -251,8 +249,6 @@ const { mutate: downloadTableData, isPending: isDownloading } = useMutation({
},
});
const exportTableData = () => downloadTableData();
// 进入页面时选择首个在线的车站
onMounted(() => {
// if (onlineStationList.value.length > 0) {
@@ -316,7 +312,7 @@ watchEffect(() => {
<NGridItem>
<NSpace>
<NButton @click="onClickReset">重置</NButton>
<NButton type="primary" :loading="isTableLoading" @click="onClickQuery">查询</NButton>
<NButton type="primary" :loading="tableLoading" @click="onClickQuery">查询</NButton>
</NSpace>
</NGridItem>
</NGrid>
@@ -327,13 +323,13 @@ watchEffect(() => {
<div style="flex: 0 0 auto; display: flex; align-items: center; padding: 8px">
<div style="font-size: medium">视频平台日志</div>
<NSpace style="margin-left: auto">
<NButton type="primary" :loading="isDownloading" @click="exportTableData">导出</NButton>
<NButton type="primary" :loading="exporting" @click="() => exportTableData()">导出</NButton>
</NSpace>
</div>
<!-- 表格区域:填满剩余空间 -->
<div style="flex: 1 1 auto; min-height: 0; padding: 8px">
<NDataTable remote :columns="tableColumns" :data="tableData" :pagination="tablePagination" :loading="isTableLoading" :single-line="false" flex-height style="height: 100%" />
<NDataTable remote :columns="tableColumns" :data="tableData" :pagination="tablePagination" :loading="tableLoading" :single-line="false" flex-height style="height: 100%" />
</div>
</div>
</template>

View File

@@ -1,11 +0,0 @@
import type { LineAlarmCounts } from '@/composables/query';
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useLineAlarmCountsStore = defineStore('ndm-line-alarm-counts-store', () => {
const lineAlarmCounts = ref<LineAlarmCounts>({});
return {
lineAlarmCounts,
};
});

View File

@@ -1,11 +1,11 @@
import type { LineAlarms } from '@/composables/query';
import type { LineAlarmCounts } from '@/composables/query';
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useLineAlarmsStore = defineStore('ndm-line-alarms-store', () => {
const lineAlarms = ref<LineAlarms>({});
const lineAlarmCounts = ref<LineAlarmCounts>({});
return {
lineAlarms,
lineAlarmCounts,
};
});