feat: 添加批量导出录像诊断并优化导出体验

This commit is contained in:
yangsy
2026-01-28 14:31:37 +08:00
parent 36e839142a
commit aa4684273b
3 changed files with 66 additions and 6 deletions

View File

@@ -48,3 +48,13 @@ export const reloadAllRecordCheckApi = async (dayOffset: number, options?: { sta
if (!data) throw new Error(`${data}`); if (!data) throw new Error(`${data}`);
return data; return data;
}; };
export const batchExportRecordCheckApi = async (params: { checkDuration: number; gapSeconds: number; stationCode: Station['code'][] }, options?: { signal?: AbortSignal }) => {
const { signal } = options ?? {};
const { checkDuration, gapSeconds, stationCode } = params;
const client = userClient;
const endpoint = `/api/ndm/ndmRecordCheck/batchExportByTemplate`;
const resp = await client.post<Blob>(endpoint, { checkDuration, gapSeconds, stationCode }, { responseType: 'blob', retRaw: true, signal });
const data = unwrapResponse(resp);
return data;
};

View File

@@ -1,11 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { getRecordCheckApi, type NdmNvrResultVO, type Station } from '@/apis'; import { batchExportRecordCheckApi, getRecordCheckApi, pageDefParameterApi, type NdmNvrResultVO, type Station } from '@/apis';
import { exportRecordDiagCsv, isNvrCluster, transformRecordChecks } from '@/helpers'; import { exportRecordDiagCsv, isNvrCluster, transformRecordChecks } from '@/helpers';
import { useDeviceStore } from '@/stores'; import { useDeviceStore } from '@/stores';
import { 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 { NButton, NGrid, NGridItem, NModal, NScrollbar, NSpin } from 'naive-ui'; import dayjs from 'dayjs';
import { NButton, NFlex, NGrid, NGridItem, NModal, NScrollbar, NSpin } from 'naive-ui';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, ref, toRefs } from 'vue'; import { computed, ref, toRefs } from 'vue';
@@ -60,7 +61,10 @@ const { mutate: exportRecordDiags, isPending: exporting } = useMutation({
return checks; return checks;
}, },
onSuccess: (checks, { stationCode }) => { onSuccess: (checks, { stationCode }) => {
if (!checks || checks.length === 0) return; if (!checks || checks.length === 0) {
window.$message.info(`没有录像诊断数据`);
return;
}
const recordDiags = transformRecordChecks(checks); const recordDiags = transformRecordChecks(checks);
exportRecordDiagCsv(recordDiags, nvrClusterRecord.value[stationCode]?.stationName ?? ''); exportRecordDiagCsv(recordDiags, nvrClusterRecord.value[stationCode]?.stationName ?? '');
}, },
@@ -72,7 +76,48 @@ const { mutate: exportRecordDiags, isPending: exporting } = useMutation({
}, },
}); });
const { mutate: batchExportRecordCheck, isPending: batchExporting } = useMutation({
mutationFn: async () => {
const { records = [] } = await pageDefParameterApi({
model: {
key: 'NVR_GAP_SECONDS',
},
extra: {},
current: 1,
size: 1,
sort: 'id',
order: 'descending',
});
const gapSeconds = parseInt(records.at(0)?.value ?? '5');
window.$message.info('导出耗时较长,请耐心等待...');
const data = await batchExportRecordCheckApi(
{
checkDuration: 90,
gapSeconds,
stationCode: stations.value.map((station) => station.code),
},
{
signal: abortController.value.signal,
},
);
return data;
},
onSuccess: (data) => {
const time = dayjs().format('YYYY-MM-DD_HH-mm-ss');
downloadByData(data, `录像缺失记录_${time}.xlsx`);
},
onError: (error) => {
if (isCancel(error)) return;
console.error(error);
const errorFeedback = parseErrorFeedback(error);
window.$message.error(errorFeedback);
},
});
const onAfterLeave = () => { const onAfterLeave = () => {
abortController.value.abort();
emit('afterLeave'); emit('afterLeave');
}; };
</script> </script>
@@ -92,6 +137,11 @@ const onAfterLeave = () => {
</NSpin> </NSpin>
</NScrollbar> </NScrollbar>
</template> </template>
<template #action>
<NFlex justify="flex-end" align="center">
<NButton secondary :loading="batchExporting" @click="() => batchExportRecordCheck()">导出全部</NButton>
</NFlex>
</template>
</NModal> </NModal>
</template> </template>

View File

@@ -81,7 +81,7 @@ const { mutate: syncCamera, isPending: cameraSyncing } = useMutation({
window.$notification.info({ window.$notification.info({
title: '摄像机同步结果', title: '摄像机同步结果',
content: notices.join(''), content: notices.join(''),
duration: 3000, duration: 10000,
}); });
if (successRequests.length > 0) { if (successRequests.length > 0) {
// 摄像机同步后,需要重新查询一次设备 // 摄像机同步后,需要重新查询一次设备
@@ -123,7 +123,7 @@ const { mutate: syncNvrChannels, isPending: nvrChannelsSyncing } = useMutation({
window.$notification.info({ window.$notification.info({
title: '录像机通道同步结果', title: '录像机通道同步结果',
content: notices.join(''), content: notices.join(''),
duration: 3000, duration: 10000,
}); });
cancelAction(); cancelAction();
}, },