1
This commit is contained in:
parent
55e133852e
commit
5a11b7431f
@ -479,6 +479,7 @@ const reportExportToastOpen = ref(false)
|
||||
const reportExportProgress = ref(0)
|
||||
const reportExportStatus = ref<'running' | 'success' | 'error'>('running')
|
||||
const reportExportText = ref('')
|
||||
const reportExportBlobUrl = ref<string | null>(null)
|
||||
let reportExportToastTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const clearReportExportToastTimer = () => {
|
||||
@ -495,15 +496,32 @@ const showReportExportProgress = (progress: number, text: string) => {
|
||||
reportExportToastOpen.value = true
|
||||
}
|
||||
|
||||
const finishReportExportProgress = (success: boolean, text: string) => {
|
||||
const finishReportExportProgress = (success: boolean, text: string, blobUrl?: string | null) => {
|
||||
clearReportExportToastTimer()
|
||||
reportExportStatus.value = success ? 'success' : 'error'
|
||||
reportExportProgress.value = 100
|
||||
reportExportText.value = text
|
||||
reportExportBlobUrl.value = success && blobUrl ? blobUrl : null
|
||||
reportExportToastOpen.value = true
|
||||
reportExportToastTimer = setTimeout(() => {
|
||||
reportExportToastOpen.value = false
|
||||
}, success ? 1200 : 1800)
|
||||
if (!success || !blobUrl) {
|
||||
reportExportToastTimer = setTimeout(() => {
|
||||
reportExportToastOpen.value = false
|
||||
}, success ? 1200 : 1800)
|
||||
}
|
||||
}
|
||||
|
||||
const openExportedReport = () => {
|
||||
if (!reportExportBlobUrl.value) return
|
||||
window.open(reportExportBlobUrl.value, '_blank')
|
||||
reportExportToastOpen.value = false
|
||||
}
|
||||
|
||||
const dismissReportToast = () => {
|
||||
if (reportExportBlobUrl.value) {
|
||||
URL.revokeObjectURL(reportExportBlobUrl.value)
|
||||
reportExportBlobUrl.value = null
|
||||
}
|
||||
reportExportToastOpen.value = false
|
||||
}
|
||||
|
||||
const tabsModel = computed({
|
||||
@ -1609,12 +1627,13 @@ const exportData = async () => {
|
||||
const exportReport = async () => {
|
||||
try {
|
||||
const now = new Date()
|
||||
const payload = await buildExportReportPayload()
|
||||
const fileName = `${sanitizeFileNamePart(payload.name)}-报表-${formatExportTimestamp(now)}`
|
||||
await exportFile(fileName, payload, () => {
|
||||
const projectInfoRaw = await kvStore.getItem<XmInfoLike>(PROJECT_INFO_DB_KEY)
|
||||
const projectName = isNonEmptyString(projectInfoRaw?.projectName) ? sanitizeFileNamePart(projectInfoRaw.projectName) : '造价项目'
|
||||
const fileName = `${projectName}-报表-${formatExportTimestamp(now)}`
|
||||
const blobUrl = await exportFile(fileName, () => buildExportReportPayload(), () => {
|
||||
showReportExportProgress(30, '正在生成报表文件...')
|
||||
})
|
||||
finishReportExportProgress(true, '报表导出完成')
|
||||
finishReportExportProgress(true, '报表导出完成', blobUrl)
|
||||
} catch (error) {
|
||||
console.error('export report failed:', error)
|
||||
if (reportExportToastOpen.value) {
|
||||
@ -2012,12 +2031,21 @@ watch(
|
||||
v-model:open="reportExportToastOpen"
|
||||
:duration="0"
|
||||
class="pointer-events-auto rounded-xl border border-border bg-card px-4 py-3 text-foreground shadow-lg"
|
||||
@update:open="(val) => { if (!val) dismissReportToast() }"
|
||||
>
|
||||
<ToastTitle class="text-sm font-semibold text-foreground">
|
||||
{{ reportExportStatus === 'running' ? '导出报表' : (reportExportStatus === 'success' ? '导出成功' : '导出失败') }}
|
||||
</ToastTitle>
|
||||
<ToastDescription class="mt-1 text-xs text-muted-foreground">{{ reportExportText }}</ToastDescription>
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<div v-if="reportExportStatus === 'success' && reportExportBlobUrl" class="mt-2 flex items-center gap-2">
|
||||
<Button size="sm" class="h-7 rounded-md px-3 text-xs" @click="openExportedReport">
|
||||
打开文件
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" class="h-7 rounded-md px-2 text-xs text-muted-foreground" @click="dismissReportToast">
|
||||
关闭
|
||||
</Button>
|
||||
</div>
|
||||
<div v-else class="mt-2 flex items-center gap-2">
|
||||
<div class="h-1.5 flex-1 overflow-hidden rounded-full bg-muted">
|
||||
<div
|
||||
class="h-full transition-all duration-300"
|
||||
|
||||
18
src/sql.ts
18
src/sql.ts
@ -688,7 +688,7 @@ export function getBasicFeeFromScale(
|
||||
* 导出入口:生成 Excel 并触发保存(优先使用 File System Access API)。
|
||||
* @returns 导出流程完成后的 Promise
|
||||
*/
|
||||
export async function exportFile(fileName: string, data: any, onSaveConfirmed?: () => void): Promise<void> {
|
||||
export async function exportFile(fileName: string, data: any | (() => Promise<any>), onSaveConfirmed?: () => void): Promise<string | null> {
|
||||
if (window.showSaveFilePicker) {
|
||||
const handle = await window.showSaveFilePicker({
|
||||
suggestedName: fileName,
|
||||
@ -699,25 +699,26 @@ export async function exportFile(fileName: string, data: any, onSaveConfirmed?:
|
||||
});
|
||||
try {
|
||||
onSaveConfirmed?.()
|
||||
|
||||
const workbook = await generateTemplate(data);
|
||||
const resolvedData = typeof data === 'function' ? await data() : data
|
||||
const workbook = await generateTemplate(resolvedData);
|
||||
const buffer = await workbook.xlsx.writeBuffer();
|
||||
const writable = await handle.createWritable();
|
||||
await writable.write(buffer);
|
||||
await writable.close();
|
||||
// 返回 blob URL 供打开文件使用
|
||||
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||
return URL.createObjectURL(blob);
|
||||
// ecCom.WeaLoadingGlobal.destroy();
|
||||
// antd.notification['success']({
|
||||
// message: '下载成功!',
|
||||
// });
|
||||
} catch (err) {
|
||||
console.log('err:' + err);
|
||||
// ecCom.WeaLoadingGlobal.destroy();
|
||||
// antd.notification['error']({
|
||||
// message: '下载失败!',
|
||||
// });
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
const workbook = await generateTemplate(data);
|
||||
const resolvedData = typeof data === 'function' ? await data() : data
|
||||
const workbook = await generateTemplate(resolvedData);
|
||||
const buffer = await workbook.xlsx.writeBuffer();
|
||||
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||
const url1 = window.URL.createObjectURL(blob);
|
||||
@ -726,6 +727,7 @@ export async function exportFile(fileName: string, data: any, onSaveConfirmed?:
|
||||
a.download = `${fileName}.xlsx`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url1);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user