<script lang="ts" setup>
|
import type { QrExportTask } from '#/api/mes/pro/qrExport';
|
|
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { Button, message, Modal, Progress } from 'ant-design-vue';
|
|
import {
|
cancelQrExportTask,
|
downloadQrExportTask,
|
getQrExportTask,
|
} from '#/api/mes/pro/qrExport';
|
|
const storageKey = 'mes-pro-last-qr-export-task-id';
|
const visible = ref(false);
|
const task = ref<QrExportTask>();
|
const downloading = ref(false);
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
function stopPolling() {
|
if (timer) clearTimeout(timer);
|
timer = undefined;
|
}
|
|
async function refresh() {
|
if (!task.value) return;
|
stopPolling();
|
try {
|
task.value = await getQrExportTask(task.value.id);
|
if (task.value.status === 10 || task.value.status === 20) {
|
timer = setTimeout(refresh, 2000);
|
}
|
} catch {
|
message.error('获取导出进度失败,请点击刷新重试');
|
}
|
}
|
|
function show(value: QrExportTask) {
|
task.value = value;
|
localStorage.setItem(storageKey, String(value.id));
|
visible.value = true;
|
void refresh();
|
}
|
|
function showLast() {
|
if (task.value) visible.value = true;
|
else message.info('暂无后台导出任务');
|
}
|
|
async function cancel() {
|
if (!task.value) return;
|
await cancelQrExportTask(task.value.id);
|
message.success('已申请取消导出任务');
|
await refresh();
|
}
|
|
async function download() {
|
if (!task.value?.downloadable || downloading.value) return;
|
downloading.value = true;
|
try {
|
const data = await downloadQrExportTask(task.value.id);
|
downloadFileFromBlobPart({ fileName: `${task.value.taskName}.zip`, source: data });
|
localStorage.removeItem(storageKey);
|
await refresh();
|
} finally {
|
downloading.value = false;
|
}
|
}
|
|
onMounted(async () => {
|
const id = Number(localStorage.getItem(storageKey));
|
if (!Number.isSafeInteger(id) || id <= 0) return;
|
try {
|
const previous = await getQrExportTask(id);
|
task.value = previous;
|
if (previous.status === 10 || previous.status === 20 || previous.downloadable) {
|
visible.value = true;
|
}
|
if (previous.status === 10 || previous.status === 20) timer = setTimeout(refresh, 2000);
|
} catch {
|
localStorage.removeItem(storageKey);
|
}
|
});
|
onBeforeUnmount(stopPolling);
|
|
defineExpose({ show, showLast });
|
</script>
|
|
<template>
|
<Modal v-model:open="visible" title="二维码后台导出" :footer="null" :mask-closable="false">
|
<template v-if="task">
|
<p>任务 #{{ task.id }} · {{ task.taskName }}</p>
|
<p>已生成 {{ task.finishedCount }} / {{ task.totalCount }} 张,{{ task.statusName }}</p>
|
<Progress :percent="task.progress" :status="task.status === 50 ? 'exception' : task.downloadable ? 'success' : 'active'" />
|
<p v-if="task.errorMsg" class="text-red-600">{{ task.errorMsg }}</p>
|
<div class="mt-4 flex justify-end gap-2">
|
<Button @click="refresh">刷新</Button>
|
<Button v-if="task.status === 10 || task.status === 20" danger @click="cancel">取消任务</Button>
|
<Button v-if="task.downloadable" type="primary" :loading="downloading" @click="download">下载 ZIP</Button>
|
</div>
|
</template>
|
</Modal>
|
</template>
|