fix toast Style issue
This commit is contained in:
parent
083c8f1886
commit
55e133852e
@ -11,7 +11,10 @@
|
|||||||
"Bash(bun run:*)",
|
"Bash(bun run:*)",
|
||||||
"Bash(grep:*)",
|
"Bash(grep:*)",
|
||||||
"mcp__context7__resolve-library-id",
|
"mcp__context7__resolve-library-id",
|
||||||
"mcp__context7__query-docs"
|
"mcp__context7__query-docs",
|
||||||
|
"mcp__ag-mcp__detect_version",
|
||||||
|
"WebSearch",
|
||||||
|
"WebFetch(domain:reka-ui.com)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1756,21 +1756,21 @@ watch(budgetRefreshSignature, (next, prev) => {
|
|||||||
<ToastRoot
|
<ToastRoot
|
||||||
v-model:open="toastOpen"
|
v-model:open="toastOpen"
|
||||||
:duration="1800"
|
:duration="1800"
|
||||||
class="group pointer-events-auto flex items-center gap-3 rounded-xl border border-slate-800/90 bg-slate-900 px-4 py-3 text-white shadow-xl"
|
class="group pointer-events-auto flex items-center gap-3 rounded-xl border border-border bg-card px-4 py-3 text-foreground shadow-lg"
|
||||||
>
|
>
|
||||||
<div class="grid gap-1">
|
<div class="grid gap-1">
|
||||||
<ToastTitle class="text-sm font-semibold text-white">{{ toastTitle }}</ToastTitle>
|
<ToastTitle class="text-sm font-semibold text-foreground">{{ toastTitle }}</ToastTitle>
|
||||||
<ToastDescription class="text-xs text-slate-100">{{ toastText }}</ToastDescription>
|
<ToastDescription class="text-xs text-muted-foreground">{{ toastText }}</ToastDescription>
|
||||||
</div>
|
</div>
|
||||||
<ToastAction
|
<ToastAction
|
||||||
alt-text="知道了"
|
alt-text="知道了"
|
||||||
class="ml-auto inline-flex h-7 items-center rounded-md border border-white/30 bg-white/10 px-2 text-xs text-white hover:bg-white/20"
|
class="ml-auto cursor-pointer inline-flex h-7 items-center rounded-md border border-border bg-muted px-2 text-xs text-foreground hover:bg-muted/80"
|
||||||
@click="toastOpen = false"
|
@click="toastOpen = false"
|
||||||
>
|
>
|
||||||
知道了
|
知道了
|
||||||
</ToastAction>
|
</ToastAction>
|
||||||
</ToastRoot>
|
</ToastRoot>
|
||||||
<ToastViewport class="fixed bottom-5 right-5 z-[80] flex w-[380px] max-w-[92vw] flex-col gap-2 outline-none" />
|
<ToastViewport class="fixed bottom-5 right-5 z-[85] flex w-[380px] max-w-[92vw] flex-col gap-2 outline-none" />
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -20,6 +20,11 @@ import {
|
|||||||
AlertDialogRoot,
|
AlertDialogRoot,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
|
ToastDescription,
|
||||||
|
ToastProvider,
|
||||||
|
ToastRoot,
|
||||||
|
ToastTitle,
|
||||||
|
ToastViewport
|
||||||
} from 'reka-ui'
|
} from 'reka-ui'
|
||||||
import { decodeZwArchive, encodeZwArchive, ZW_FILE_EXTENSION } from '@/lib/zwArchive'
|
import { decodeZwArchive, encodeZwArchive, ZW_FILE_EXTENSION } from '@/lib/zwArchive'
|
||||||
import { PROJECT_TAB_ID, QUICK_TAB_ID, readWorkspaceMode } from '@/lib/workspace'
|
import { PROJECT_TAB_ID, QUICK_TAB_ID, readWorkspaceMode } from '@/lib/workspace'
|
||||||
@ -470,6 +475,37 @@ const tabTitleOverflowMap = ref<Record<string, boolean>>({})
|
|||||||
let tabStripViewportEl: HTMLElement | null = null
|
let tabStripViewportEl: HTMLElement | null = null
|
||||||
let tabTitleOverflowRafId: number | null = null
|
let tabTitleOverflowRafId: number | null = null
|
||||||
|
|
||||||
|
const reportExportToastOpen = ref(false)
|
||||||
|
const reportExportProgress = ref(0)
|
||||||
|
const reportExportStatus = ref<'running' | 'success' | 'error'>('running')
|
||||||
|
const reportExportText = ref('')
|
||||||
|
let reportExportToastTimer: ReturnType<typeof setTimeout> | null = null
|
||||||
|
|
||||||
|
const clearReportExportToastTimer = () => {
|
||||||
|
if (!reportExportToastTimer) return
|
||||||
|
clearTimeout(reportExportToastTimer)
|
||||||
|
reportExportToastTimer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const showReportExportProgress = (progress: number, text: string) => {
|
||||||
|
clearReportExportToastTimer()
|
||||||
|
reportExportStatus.value = 'running'
|
||||||
|
reportExportProgress.value = Math.max(0, Math.min(100, progress))
|
||||||
|
reportExportText.value = text
|
||||||
|
reportExportToastOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const finishReportExportProgress = (success: boolean, text: string) => {
|
||||||
|
clearReportExportToastTimer()
|
||||||
|
reportExportStatus.value = success ? 'success' : 'error'
|
||||||
|
reportExportProgress.value = 100
|
||||||
|
reportExportText.value = text
|
||||||
|
reportExportToastOpen.value = true
|
||||||
|
reportExportToastTimer = setTimeout(() => {
|
||||||
|
reportExportToastOpen.value = false
|
||||||
|
}, success ? 1200 : 1800)
|
||||||
|
}
|
||||||
|
|
||||||
const tabsModel = computed({
|
const tabsModel = computed({
|
||||||
get: () => tabStore.tabs,
|
get: () => tabStore.tabs,
|
||||||
set: (value) => {
|
set: (value) => {
|
||||||
@ -1575,11 +1611,15 @@ const exportReport = async () => {
|
|||||||
const now = new Date()
|
const now = new Date()
|
||||||
const payload = await buildExportReportPayload()
|
const payload = await buildExportReportPayload()
|
||||||
const fileName = `${sanitizeFileNamePart(payload.name)}-报表-${formatExportTimestamp(now)}`
|
const fileName = `${sanitizeFileNamePart(payload.name)}-报表-${formatExportTimestamp(now)}`
|
||||||
console.log(payload)
|
await exportFile(fileName, payload, () => {
|
||||||
await exportFile(fileName, payload)
|
showReportExportProgress(30, '正在生成报表文件...')
|
||||||
|
})
|
||||||
|
finishReportExportProgress(true, '报表导出完成')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('export report failed:', error)
|
console.error('export report failed:', error)
|
||||||
// window.alert('导出报表失败,请重试。')
|
if (reportExportToastOpen.value) {
|
||||||
|
finishReportExportProgress(false, '报表导出失败,请重试')
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
dataMenuOpen.value = false
|
dataMenuOpen.value = false
|
||||||
}
|
}
|
||||||
@ -1760,6 +1800,7 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<ToastProvider>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<div class="flex flex-col w-full h-screen bg-background overflow-hidden">
|
<div class="flex flex-col w-full h-screen bg-background overflow-hidden">
|
||||||
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-start gap-2 border-b bg-muted/30 px-2 pt-1 h-15 flex-none">
|
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-start gap-2 border-b bg-muted/30 px-2 pt-1 h-15 flex-none">
|
||||||
@ -1967,7 +2008,31 @@ watch(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ToastRoot
|
||||||
|
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"
|
||||||
|
>
|
||||||
|
<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 class="h-1.5 flex-1 overflow-hidden rounded-full bg-muted">
|
||||||
|
<div
|
||||||
|
class="h-full transition-all duration-300"
|
||||||
|
:class="reportExportStatus === 'error'
|
||||||
|
? 'bg-red-500'
|
||||||
|
: (reportExportStatus === 'success' ? 'bg-foreground/70' : 'bg-foreground')"
|
||||||
|
:style="{ width: `${reportExportProgress}%` }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span class="shrink-0 text-[11px] tabular-nums text-muted-foreground">{{ reportExportProgress }}%</span>
|
||||||
|
</div>
|
||||||
|
</ToastRoot>
|
||||||
|
<ToastViewport class="fixed bottom-5 right-5 z-[85] flex w-[380px] max-w-[92vw] flex-col gap-2 outline-none" />
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
</ToastProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@ -688,7 +688,7 @@ export function getBasicFeeFromScale(
|
|||||||
* 导出入口:生成 Excel 并触发保存(优先使用 File System Access API)。
|
* 导出入口:生成 Excel 并触发保存(优先使用 File System Access API)。
|
||||||
* @returns 导出流程完成后的 Promise
|
* @returns 导出流程完成后的 Promise
|
||||||
*/
|
*/
|
||||||
export async function exportFile(fileName: string, data: any): Promise<void> {
|
export async function exportFile(fileName: string, data: any, onSaveConfirmed?: () => void): Promise<void> {
|
||||||
if (window.showSaveFilePicker) {
|
if (window.showSaveFilePicker) {
|
||||||
const handle = await window.showSaveFilePicker({
|
const handle = await window.showSaveFilePicker({
|
||||||
suggestedName: fileName,
|
suggestedName: fileName,
|
||||||
@ -697,10 +697,9 @@ export async function exportFile(fileName: string, data: any): Promise<void> {
|
|||||||
accept: { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [".xlsx"] }
|
accept: { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [".xlsx"] }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
// ecCom.WeaLoadingGlobal.start({
|
|
||||||
// tip: "下载中,结束前请勿打开文件...",
|
|
||||||
// });
|
|
||||||
try {
|
try {
|
||||||
|
onSaveConfirmed?.()
|
||||||
|
|
||||||
const workbook = await generateTemplate(data);
|
const workbook = await generateTemplate(data);
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
const buffer = await workbook.xlsx.writeBuffer();
|
||||||
const writable = await handle.createWritable();
|
const writable = await handle.createWritable();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user