From c2ebe34a05efde7cb48b8685d25d9d7d86efc837 Mon Sep 17 00:00:00 2001 From: yangsy Date: Tue, 26 Aug 2025 03:27:06 +0800 Subject: [PATCH] refactor: add store to save data from queries progressively --- .../query/alarm/use-line-alarms-query.ts | 22 ++-- .../query/alarm/use-station-alarms-query.ts | 8 +- .../query/device/use-line-devices-query.ts | 122 ++++++++++++------ .../query/device/use-station-devices-query.ts | 8 +- .../query/station/use-station-list-query.ts | 10 +- src/stores/line-alarms.ts | 11 ++ src/stores/line-devices.ts | 11 ++ src/stores/station.ts | 3 - 8 files changed, 141 insertions(+), 54 deletions(-) create mode 100644 src/stores/line-alarms.ts create mode 100644 src/stores/line-devices.ts diff --git a/src/composables/query/alarm/use-line-alarms-query.ts b/src/composables/query/alarm/use-line-alarms-query.ts index 4de48b4..fe8d4ad 100644 --- a/src/composables/query/alarm/use-line-alarms-query.ts +++ b/src/composables/query/alarm/use-line-alarms-query.ts @@ -8,6 +8,7 @@ import dayjs from 'dayjs'; import { storeToRefs } from 'pinia'; import { computed } from 'vue'; import type { StationAlarms } from './domains'; +import { useLineAlarmsStore } from '@/stores/line-alarms'; export interface LineAlarms { [stationCode: Station['code']]: StationAlarms; @@ -15,24 +16,29 @@ export interface LineAlarms { export function useLineAlarmsQuery() { const stationStore = useStationStore(); - const { updatedTime, stationList, onlineStationList } = storeToRefs(stationStore); + const { stationList, onlineStationList } = storeToRefs(stationStore); const queryControlStore = useQueryControlStore(); const { pollingEnabled } = storeToRefs(queryControlStore); + const lineAlarmsStore = useLineAlarmsStore(); + const { lineAlarms } = storeToRefs(lineAlarmsStore); return useQuery({ - queryKey: ['line-alarms', updatedTime], + queryKey: ['line-alarms'], enabled: computed(() => onlineStationList.value.length > 0 && pollingEnabled.value), + staleTime: Infinity, + refetchOnMount: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, queryFn: async ({ signal }): Promise => { // console.time('useLineAlarmsQuery'); - const lineAlarms: LineAlarms = {}; - if (!stationList?.value) { - return lineAlarms; + lineAlarms.value = {}; + return lineAlarms.value; } for (const station of stationList.value) { - lineAlarms[station.code] = { + lineAlarms.value[station.code] = { [DeviceType.Camera]: [], [DeviceType.Decoder]: [], [DeviceType.Keyboard]: [], @@ -71,7 +77,7 @@ export function useLineAlarmsQuery() { const securityBoxAlarms = alarmList.filter((device) => device.deviceType === DeviceType.SecurityBox); const switchAlarms = alarmList.filter((device) => device.deviceType === DeviceType.Switch); const videoServerAlarms = alarmList.filter((device) => device.deviceType === DeviceType.VideoServer); - lineAlarms[station.code] = { + lineAlarms.value[station.code] = { [DeviceType.Camera]: cameraAlarms, [DeviceType.Decoder]: decoderAlarms, [DeviceType.Keyboard]: keyboardAlarms, @@ -89,7 +95,7 @@ export function useLineAlarmsQuery() { // console.timeEnd('useLineAlarmsQuery'); - return lineAlarms; + return lineAlarms.value; }, placeholderData: (prev) => prev, }); diff --git a/src/composables/query/alarm/use-station-alarms-query.ts b/src/composables/query/alarm/use-station-alarms-query.ts index 11936e2..6c022e1 100644 --- a/src/composables/query/alarm/use-station-alarms-query.ts +++ b/src/composables/query/alarm/use-station-alarms-query.ts @@ -23,7 +23,7 @@ const createEmptyStationAlarms = (): StationAlarms => ({ export function useStationAlarmsQuery(stationCode: Station['code']) { const stationStore = useStationStore(); - const { updatedTime, onlineStationList } = storeToRefs(stationStore); + const { onlineStationList } = storeToRefs(stationStore); const queryControlStore = useQueryControlStore(); const { pollingEnabled } = storeToRefs(queryControlStore); @@ -31,8 +31,12 @@ export function useStationAlarmsQuery(stationCode: Station['code']) { const isOnline = computed(() => onlineStationList.value.some((stn) => stn.code === stationCode)); return useQuery({ - queryKey: ['station-alarms', stationCode, updatedTime], + queryKey: ['station-alarms', stationCode], enabled: computed(() => isOnline.value && pollingEnabled.value), + staleTime: Infinity, + refetchOnMount: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, queryFn: async ({ signal }): Promise => { // 如果车站离线,返回空数据 if (!isOnline.value) { diff --git a/src/composables/query/device/use-line-devices-query.ts b/src/composables/query/device/use-line-devices-query.ts index 9e0f5fb..969e584 100644 --- a/src/composables/query/device/use-line-devices-query.ts +++ b/src/composables/query/device/use-line-devices-query.ts @@ -8,6 +8,7 @@ import { useQuery } from '@tanstack/vue-query'; import { storeToRefs } from 'pinia'; import { computed } from 'vue'; import type { StationDevices } from './domains'; +import { useLineDevicesStore } from '@/stores/line-devices'; export interface LineDevices { [stationCode: Station['code']]: StationDevices; @@ -28,67 +29,116 @@ const createEmptyStationDevices = (): StationDevices => { export function useLineDevicesQuery() { const stationStore = useStationStore(); - const { updatedTime, stationList, onlineStationList } = storeToRefs(stationStore); + const { stationList, onlineStationList } = storeToRefs(stationStore); const queryControlStore = useQueryControlStore(); const { pollingEnabled } = storeToRefs(queryControlStore); + const lineDevicesStore = useLineDevicesStore(); + const { lineDevices } = storeToRefs(lineDevicesStore); return useQuery({ - queryKey: ['line-devices', updatedTime], + queryKey: ['line-devices'], enabled: computed(() => onlineStationList.value.length > 0 && pollingEnabled.value), + staleTime: Infinity, + refetchOnMount: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, queryFn: async ({ signal }): Promise => { // console.time('useLineDevicesQuery'); const pageQuery: PageParams<{}> = { model: {}, extra: {}, size: 5000, current: 1, sort: 'id', order: 'ascending' }; - const lineDevices: LineDevices = {}; + // const lineDevices: LineDevices = {}; - // 如果没有车站列表,返回空对象 + // 如果没有车站列表,返回空数据 if (!stationList?.value) { - return lineDevices; + lineDevices.value = {}; + return lineDevices.value; } // 遍历所有车站 for (const station of stationList.value) { - // 如果车站离线,设置空数组 + // 如果车站离线,设置空数据 if (!station.online) { - lineDevices[station.code] = createEmptyStationDevices(); + lineDevices.value[station.code] = createEmptyStationDevices(); continue; } - try { - // 并行获取该车站的所有设备类型数据 - const [cameraData, decoderData, keyboardData, mediaServerData, nvrData, securityBoxData, switchData, videoServerData] = await Promise.all([ - postNdmCameraPage(station.code, pageQuery, signal), - postNdmDecoderPage(station.code, pageQuery, signal), - postNdmKeyboardPage(station.code, pageQuery, signal), - postNdmMediaServerPage(station.code, pageQuery, signal), - postNdmNvrPage(station.code, pageQuery, signal), - postNdmSecurityBoxPage(station.code, pageQuery, signal), - postNdmSwitchPage(station.code, pageQuery, signal), - postNdmVideoServerPage(station.code, pageQuery, signal), - ]); - - // 存储该车站的设备数据 - lineDevices[station.code] = { - [DeviceType.Camera]: cameraData.records ?? [], - [DeviceType.Decoder]: decoderData.records ?? [], - [DeviceType.Keyboard]: keyboardData.records ?? [], - [DeviceType.MediaServer]: mediaServerData.records ?? [], - [DeviceType.Nvr]: nvrData.records ?? [], - [DeviceType.SecurityBox]: securityBoxData.records ?? [], - [DeviceType.Switch]: switchData.records ?? [], - [DeviceType.VideoServer]: videoServerData.records ?? [], - }; - } catch (error) { - console.error(`获取车站 ${station.name} 设备数据失败:`, error); - // 如果获取失败,设置空数组 - lineDevices[station.code] = createEmptyStationDevices(); + if (!lineDevices.value[station.code]) { + lineDevices.value[station.code] = createEmptyStationDevices(); } + const stationDevices = lineDevices.value[station.code]; + + await Promise.allSettled([ + postNdmCameraPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.Camera] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 摄像机数据失败:`, error); + stationDevices[DeviceType.Camera] = []; + }), + postNdmDecoderPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.Decoder] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 解码器数据失败:`, error); + stationDevices[DeviceType.Decoder] = []; + }), + postNdmKeyboardPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.Keyboard] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 网络键盘数据失败:`, error); + stationDevices[DeviceType.Keyboard] = []; + }), + postNdmMediaServerPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.MediaServer] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 媒体服务器数据失败:`, error); + stationDevices[DeviceType.MediaServer] = []; + }), + postNdmNvrPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.Nvr] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 录像机数据失败:`, error); + stationDevices[DeviceType.Nvr] = []; + }), + postNdmSecurityBoxPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.SecurityBox] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 安防箱数据失败:`, error); + stationDevices[DeviceType.SecurityBox] = []; + }), + postNdmSwitchPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.Switch] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 交换机数据失败:`, error); + stationDevices[DeviceType.Switch] = []; + }), + postNdmVideoServerPage(station.code, pageQuery, signal) + .then(({ records }) => { + stationDevices[DeviceType.VideoServer] = records; + }) + .catch((error) => { + console.error(`获取车站 ${station.name} 视频服务器数据失败:`, error); + stationDevices[DeviceType.VideoServer] = []; + }), + ]); } // console.timeEnd('useLineDevicesQuery'); - return lineDevices; + return lineDevices.value; }, placeholderData: (prev) => prev, }); diff --git a/src/composables/query/device/use-station-devices-query.ts b/src/composables/query/device/use-station-devices-query.ts index c448c36..c1e7867 100644 --- a/src/composables/query/device/use-station-devices-query.ts +++ b/src/composables/query/device/use-station-devices-query.ts @@ -24,7 +24,7 @@ const createEmptyStationDevices = (): StationDevices => { export function useStationDevicesQuery(stationCode: Station['code']) { const stationStore = useStationStore(); - const { updatedTime, onlineStationList } = storeToRefs(stationStore); + const { onlineStationList } = storeToRefs(stationStore); const queryControlStore = useQueryControlStore(); const { pollingEnabled } = storeToRefs(queryControlStore); @@ -32,8 +32,12 @@ export function useStationDevicesQuery(stationCode: Station['code']) { const isOnline = computed(() => onlineStationList.value.some((s) => s.code === stationCode)); return useQuery({ - queryKey: ['station-devices', stationCode, updatedTime], + queryKey: ['station-devices', stationCode], enabled: computed(() => isOnline.value && pollingEnabled.value), + staleTime: Infinity, + refetchOnMount: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, queryFn: async ({ signal }): Promise => { const pageQuery: PageParams<{}> = { model: {}, extra: {}, size: 5000, current: 1, sort: 'id', order: 'ascending' }; diff --git a/src/composables/query/station/use-station-list-query.ts b/src/composables/query/station/use-station-list-query.ts index 8b03011..fbe30d4 100644 --- a/src/composables/query/station/use-station-list-query.ts +++ b/src/composables/query/station/use-station-list-query.ts @@ -3,7 +3,7 @@ import { ndmVerify } from '@/apis/requests'; import { useQueryControlStore } from '@/stores/query-control'; import { useStationStore } from '@/stores/station'; import { getAppEnvConfig } from '@/utils/env'; -import { useQuery } from '@tanstack/vue-query'; +import { useQuery, useQueryClient } from '@tanstack/vue-query'; import axios from 'axios'; import dayjs from 'dayjs'; import { storeToRefs } from 'pinia'; @@ -11,7 +11,7 @@ import { computed } from 'vue'; export function useStationListQuery() { const stationStore = useStationStore(); - const { updatedTime, stationList } = storeToRefs(stationStore); + const { stationList } = storeToRefs(stationStore); const queryControlStore = useQueryControlStore(); const { pollingEnabled } = storeToRefs(queryControlStore); @@ -45,7 +45,11 @@ export function useStationListQuery() { stationList.value.splice(0, stationList.value.length, ...stations); } - updatedTime.value = dayjs().toJSON(); + const queryClient = useQueryClient(); + queryClient.invalidateQueries({ queryKey: ['station-devices'] }); + queryClient.invalidateQueries({ queryKey: ['station-alarms'] }); + // queryClient.invalidateQueries({ queryKey: ['line-devices'] }); + // queryClient.invalidateQueries({ queryKey: ['line-alarms'] }); return stations; }, diff --git a/src/stores/line-alarms.ts b/src/stores/line-alarms.ts new file mode 100644 index 0000000..f06d5f4 --- /dev/null +++ b/src/stores/line-alarms.ts @@ -0,0 +1,11 @@ +import type { LineAlarms } from '@/composables/query'; +import { defineStore } from 'pinia'; +import { ref } from 'vue'; + +export const useLineAlarmsStore = defineStore('line-alarms', () => { + const lineAlarms = ref({}); + + return { + lineAlarms, + }; +}); diff --git a/src/stores/line-devices.ts b/src/stores/line-devices.ts new file mode 100644 index 0000000..dc0ddf7 --- /dev/null +++ b/src/stores/line-devices.ts @@ -0,0 +1,11 @@ +import type { LineDevices } from '@/composables/query'; +import { defineStore } from 'pinia'; +import { ref } from 'vue'; + +export const useLineDevicesStore = defineStore('ndm-line-devices-store', () => { + const lineDevices = ref({}); + + return { + lineDevices, + }; +}); diff --git a/src/stores/station.ts b/src/stores/station.ts index c5a159e..7d1c1cd 100644 --- a/src/stores/station.ts +++ b/src/stores/station.ts @@ -3,14 +3,11 @@ import { defineStore } from 'pinia'; import { computed, ref } from 'vue'; export const useStationStore = defineStore('ndm-station-store', () => { - const updatedTime = ref(''); - const stationList = ref([]); const onlineStationList = computed(() => stationList.value.filter((station) => station.online)); return { - updatedTime, stationList, onlineStationList, };