refactor: 录像诊断导出面板统一使用批量接口

This commit is contained in:
yangsy
2026-01-30 14:14:53 +08:00
parent b020226538
commit cf3d19d89d

View File

@@ -1,14 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { batchExportRecordCheckApi, getRecordCheckApi, pageDefParameterApi, type NdmNvrResultVO, type Station } from '@/apis'; import { batchExportRecordCheckApi, pageDefParameterApi, type Station } from '@/apis';
import { exportRecordDiagCsv, isNvrCluster, transformRecordChecks } from '@/helpers';
import { useDeviceStore } from '@/stores';
import { downloadByData, parseErrorFeedback } from '@/utils'; import { downloadByData, parseErrorFeedback } from '@/utils';
import { useMutation } from '@tanstack/vue-query'; import { useMutation } from '@tanstack/vue-query';
import { isCancel } from 'axios'; import { isCancel } from 'axios';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { NButton, NFlex, NGrid, NGridItem, NModal, NScrollbar, NSpin } from 'naive-ui'; import { NButton, NFlex, NGrid, NGridItem, NModal, NScrollbar, NSpin } from 'naive-ui';
import { storeToRefs } from 'pinia'; import { ref, toRefs } from 'vue';
import { computed, ref, toRefs } from 'vue';
const props = defineProps<{ const props = defineProps<{
stations: Station[]; stations: Station[];
@@ -20,93 +17,66 @@ const emit = defineEmits<{
const show = defineModel<boolean>('show'); const show = defineModel<boolean>('show');
const deviceStore = useDeviceStore();
const { lineDevices } = storeToRefs(deviceStore);
const { stations } = toRefs(props); const { stations } = toRefs(props);
const nvrClusterRecord = computed(() => {
const clusterMap: Record<Station['code'], { stationName: Station['name']; clusters: NdmNvrResultVO[] }> = {};
stations.value.forEach((station) => {
clusterMap[station.code] = {
stationName: station.name,
clusters: [],
};
const stationDevices = lineDevices.value[station.code];
const nvrs = stationDevices?.['ndmNvr'] ?? [];
nvrs.forEach((nvr) => {
if (isNvrCluster(nvr)) {
clusterMap[station.code]?.clusters?.push(nvr);
}
});
});
return clusterMap;
});
const abortController = ref<AbortController>(new AbortController()); const abortController = ref<AbortController>(new AbortController());
const { mutate: exportRecordDiags, isPending: exporting } = useMutation({
mutationFn: async (params: { clusters: NdmNvrResultVO[]; stationCode: Station['code'] }) => {
const { clusters, stationCode } = params;
if (clusters.length === 0) {
const stationName = nvrClusterRecord.value[stationCode]?.stationName ?? '';
window.$message.info(`${stationName} 没有录像诊断数据`);
return;
}
const cluster = clusters.at(0);
if (!cluster) return;
abortController.value.abort();
abortController.value = new AbortController();
const checks = await getRecordCheckApi(cluster, 90, [], { stationCode: stationCode, signal: abortController.value.signal });
return checks;
},
onSuccess: (checks, { stationCode }) => {
if (!checks || checks.length === 0) {
window.$message.info(`没有录像诊断数据`);
return;
}
const recordDiags = transformRecordChecks(checks);
exportRecordDiagCsv(recordDiags, nvrClusterRecord.value[stationCode]?.stationName ?? '');
},
onError: (error) => {
if (isCancel(error)) return;
console.error(error);
const errorFeedback = parseErrorFeedback(error);
window.$message.error(errorFeedback);
},
});
const { mutate: batchExportRecordCheck, isPending: batchExporting } = useMutation({ const { mutate: batchExportRecordCheck, isPending: batchExporting } = useMutation({
mutationFn: async () => { mutationFn: async (params: { stations: Station[] }) => {
const { records = [] } = await pageDefParameterApi({ const timer = setTimeout(() => {
model: { if (!batchExporting.value) return;
key: 'NVR_GAP_SECONDS', window.$message.info('导出耗时较长,请耐心等待...', { duration: 0 });
}, }, 3000);
extra: {},
current: 1,
size: 1,
sort: 'id',
order: 'descending',
});
const gapSeconds = parseInt(records.at(0)?.value ?? '5');
window.$message.info('导出耗时较长,请耐心等待...'); try {
abortController.value.abort();
abortController.value = new AbortController();
const { records = [] } = await pageDefParameterApi(
{
model: {
key: 'NVR_GAP_SECONDS',
},
extra: {},
current: 1,
size: 1,
sort: 'id',
order: 'descending',
},
{
signal: abortController.value.signal,
},
);
const gapSeconds = parseInt(records.at(0)?.value ?? '5');
const data = await batchExportRecordCheckApi( abortController.value.abort();
{ abortController.value = new AbortController();
checkDuration: 90, const data = await batchExportRecordCheckApi(
gapSeconds, {
stationCode: stations.value.map((station) => station.code), checkDuration: 90,
}, gapSeconds,
{ stationCode: params.stations.map((station) => station.code),
signal: abortController.value.signal, },
}, {
); signal: abortController.value.signal,
return data; },
);
return data;
} finally {
window.$message.destroyAll();
clearTimeout(timer);
}
}, },
onSuccess: (data) => { onSuccess: (data, { stations }) => {
const time = dayjs().format('YYYY-MM-DD_HH-mm-ss'); const time = dayjs().format('YYYY-MM-DD_HH-mm-ss');
downloadByData(data, `录像缺失记录_${time}.xlsx`); let stationName = '';
if (stations.length === 1) {
const name = stations.at(0)?.name;
if (!!name) {
stationName = `${name}_`;
}
}
downloadByData(data, `${stationName}录像缺失记录_${time}.xlsx`);
}, },
onError: (error) => { onError: (error) => {
if (isCancel(error)) return; if (isCancel(error)) return;
@@ -126,11 +96,11 @@ const onAfterLeave = () => {
<NModal v-model:show="show" preset="card" title="导出录像诊断" @after-leave="onAfterLeave" style="width: 800px"> <NModal v-model:show="show" preset="card" title="导出录像诊断" @after-leave="onAfterLeave" style="width: 800px">
<template #default> <template #default>
<NScrollbar style="height: 300px"> <NScrollbar style="height: 300px">
<NSpin size="small" :show="exporting"> <NSpin size="small" :show="batchExporting">
<NGrid :cols="6"> <NGrid :cols="6">
<template v-for="({ stationName, clusters }, code) in nvrClusterRecord" :key="code"> <template v-for="station in stations" :key="station.code">
<NGridItem> <NGridItem>
<NButton text type="info" style="height: 30px" @click="() => exportRecordDiags({ clusters, stationCode: code })">{{ stationName }}</NButton> <NButton text type="info" style="height: 30px" @click="() => batchExportRecordCheck({ stations: [station] })">{{ station.name }}</NButton>
</NGridItem> </NGridItem>
</template> </template>
</NGrid> </NGrid>
@@ -139,7 +109,7 @@ const onAfterLeave = () => {
</template> </template>
<template #action> <template #action>
<NFlex justify="flex-end" align="center"> <NFlex justify="flex-end" align="center">
<NButton secondary :loading="batchExporting" @click="() => batchExportRecordCheck()">导出全部</NButton> <NButton secondary :loading="batchExporting" @click="() => batchExportRecordCheck({ stations })">导出全部</NButton>
</NFlex> </NFlex>
</template> </template>
</NModal> </NModal>