import { ndmClient, type Station, type StationDevices } from '@/apis'; import { LINE_DEVICES_QUERY_KEY } from '@/constants'; import { DeviceType } from '@/enums'; import { useDeviceStore, usePollingStore, useStationStore } from '@/stores'; import { runTask } from '@/utils'; import { isCancelledError, useMutation, useQuery } from '@tanstack/vue-query'; import { storeToRefs } from 'pinia'; import { computed } from 'vue'; const createEmptyStationDevices = (): StationDevices => { return { [DeviceType.Camera]: [], [DeviceType.Decoder]: [], [DeviceType.Keyboard]: [], [DeviceType.MediaServer]: [], [DeviceType.Nvr]: [], [DeviceType.SecurityBox]: [], [DeviceType.Switch]: [], [DeviceType.VideoServer]: [], }; }; const getNdmDevicesAll = async (stationCode: string, signal?: AbortSignal) => { const resp = await ndmClient.get(`/${stationCode}/api/ndm/ndmDevices/all`, { retRaw: true, signal }); const [err, data] = resp; if (err || !data) { throw err; } return data; }; export function useLineDevicesQuery() { const stationStore = useStationStore(); const { stationList } = storeToRefs(stationStore); const pollingStore = usePollingStore(); const { deviceQueryStamp } = storeToRefs(pollingStore); const { mutateAsync: getStationDevices } = useStationDevicesMutation(); return useQuery({ queryKey: computed(() => [LINE_DEVICES_QUERY_KEY, deviceQueryStamp.value]), enabled: computed(() => deviceQueryStamp.value > 0), staleTime: Infinity, refetchOnMount: false, refetchOnReconnect: false, refetchOnWindowFocus: false, queryFn: async ({ signal }) => { console.time('useLineDevicesQuery'); for (const station of stationList.value) { await getStationDevices({ station, signal }); } console.timeEnd('useLineDevicesQuery'); // pollingStore.updateDeviceQueryUpdatedAt(); return null; }, }); } interface StationDevicesMutationParams { station: Station; signal?: AbortSignal; } function useStationDevicesMutation() { const lineDevicesStore = useDeviceStore(); const { lineDevices } = storeToRefs(lineDevicesStore); return useMutation({ mutationFn: async ({ station, signal }) => { if (!station.online) { return createEmptyStationDevices(); } return await getNdmDevicesAll(station.code, signal); }, onSuccess: (stationDevices, { station }) => { runTask(() => { lineDevices.value[station.code] = stationDevices; }); }, onError: (error, { station }) => { if (!isCancelledError(error)) { console.error(`获取车站 ${station.name} 设备数据失败:`, error); lineDevices.value[station.code] = createEmptyStationDevices(); throw error; } }, }); }