update at 2026-02-11 19:31:11

This commit is contained in:
douboer
2026-02-11 19:31:11 +08:00
parent b0c7ea4cba
commit cc6c9c8a99
4 changed files with 47 additions and 10 deletions

View File

@@ -32,6 +32,7 @@ const activePreviewFonts = ref<FontInfo[]>([])
const processedFontCount = ref(0)
const renderedPreviewCount = ref(0)
const previewTriggerItemEl = ref<HTMLElement | null>(null)
const previewErrorMessage = ref('')
const previewFonts = computed(() => fontStore.previewFonts)
const inputText = computed(() => uiStore.inputText)
@@ -302,17 +303,18 @@ async function generatePreviewBatch(
startIndex: number,
batchSize: number,
generationToken: number,
): Promise<PreviewRenderItem[]> {
): Promise<{ items: PreviewRenderItem[]; errors: string[] }> {
const endIndex = Math.min(startIndex + batchSize, fonts.length)
const batchFonts = fonts.slice(startIndex, endIndex)
if (batchFonts.length === 0) {
return []
return { items: [], errors: [] }
}
const selectedFontIdSet = new Set(uiStore.selectedExportItems.map(item => item.fontInfo.id))
const items = new Array<PreviewRenderItem | null>(batchFonts.length).fill(null)
const workerCount = Math.min(PREVIEW_CONCURRENCY, batchFonts.length)
let nextIndex = 0
const errors: string[] = []
const worker = async () => {
while (true) {
@@ -353,7 +355,9 @@ async function generatePreviewBatch(
}
items[localIndex] = applyLocalStyleToPreviewItem(item)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
console.error(`Failed to render preview for ${fontInfo.name}:`, error)
errors.push(`${fontInfo.name}: ${message}`)
}
}
}
@@ -361,10 +365,13 @@ async function generatePreviewBatch(
await Promise.all(Array.from({ length: workerCount }, () => worker()))
if (isStaleGeneration(generationToken)) {
return []
return { items: [], errors: [] }
}
return items.filter((item): item is PreviewRenderItem => item !== null)
return {
items: items.filter((item): item is PreviewRenderItem => item !== null),
errors,
}
}
async function loadNextPreviewBatch(generationToken: number) {
@@ -396,13 +403,20 @@ async function loadNextPreviewBatch(generationToken: number) {
activePreviewFonts.value.length,
)
previewItems.value = [...previewItems.value, ...batchItems]
previewItems.value = [...previewItems.value, ...batchItems.items]
renderedPreviewCount.value = Math.min(
renderedPreviewCount.value + PREVIEW_BATCH_SIZE,
previewItems.value.length,
)
if (batchItems.errors.length > 0 && previewItems.value.length === 0) {
previewErrorMessage.value = `预览生成失败:${batchItems.errors[0]}`
} else if (previewItems.value.length > 0) {
previewErrorMessage.value = ''
}
} catch (error) {
console.error('Failed to load preview batch:', error)
previewErrorMessage.value = `预览生成失败:${error instanceof Error ? error.message : String(error)}`
} finally {
if (!isStaleGeneration(generationToken)) {
isBatchGenerating.value = false
@@ -440,6 +454,7 @@ async function regeneratePreviews() {
processedFontCount.value = 0
previewItems.value = []
renderedPreviewCount.value = 0
previewErrorMessage.value = ''
if (!inputText.value || inputText.value.trim() === '' || nextPreviewFonts.length === 0) {
isGenerating.value = false
@@ -450,8 +465,18 @@ async function regeneratePreviews() {
try {
await loadNextPreviewBatch(generationToken)
if (
!isStaleGeneration(generationToken) &&
previewItems.value.length === 0 &&
nextPreviewFonts.length > 0 &&
inputText.value.trim() !== '' &&
!previewErrorMessage.value
) {
previewErrorMessage.value = '预览生成失败:服务未返回可用结果'
}
} catch (error) {
console.error('Failed to regenerate previews:', error)
previewErrorMessage.value = `预览生成失败:${error instanceof Error ? error.message : String(error)}`
} finally {
if (!isStaleGeneration(generationToken)) {
isGenerating.value = false
@@ -526,7 +551,19 @@ defineExpose({
<template>
<div class="flex flex-col gap-2">
<div v-if="previewItems.length === 0" class="text-[#86909c] text-center py-20">
{{ isGenerating ? '生成预览中...' : '请选择字体并输入内容' }}
{{
isGenerating
? '生成预览中...'
: (
previewErrorMessage
? previewErrorMessage
: (
inputText.trim() === '' || previewFonts.length === 0
? '请选择字体并输入内容'
: '暂无可显示预览'
)
)
}}
</div>
<div v-else class="flex flex-col gap-2">