feat: track generation jobs

This commit is contained in:
2026-04-18 16:29:22 +08:00
parent 16fafe0fe0
commit 96dfc677e2
18 changed files with 709 additions and 71 deletions

View File

@@ -21,6 +21,7 @@ export interface Storybook {
image_status?: string
audio_status?: string
last_error?: string | null
retryable_assets?: Array<'image' | 'audio'>
}
export const useStorybookStore = defineStore('storybook', () => {

View File

@@ -26,6 +26,7 @@ interface Story {
image_status: string
audio_status: string
last_error: string | null
retryable_assets: Array<'image' | 'audio'>
pages?: Array<{
page_number: number
text: string
@@ -53,16 +54,8 @@ const storyParagraphs = computed(() => story.value?.story_text?.split('\n\n') ??
const generationMeta = computed(() => getGenerationStatusMeta(story.value?.generation_status))
const imageMeta = computed(() => getAssetStatusMeta(story.value?.image_status))
const audioMeta = computed(() => getAssetStatusMeta(story.value?.audio_status))
const canRetryImage = computed(() =>
Boolean(story.value?.cover_prompt)
&& story.value?.image_status !== 'ready'
&& story.value?.image_status !== 'generating',
)
const canRetryAudio = computed(() =>
Boolean(story.value?.story_text)
&& story.value?.audio_status !== 'ready'
&& story.value?.audio_status !== 'generating',
)
const canRetryImage = computed(() => story.value?.retryable_assets.includes('image') ?? false)
const canRetryAudio = computed(() => story.value?.retryable_assets.includes('audio') ?? false)
const isAudioGenerating = computed(() => story.value?.audio_status === 'generating')
const assetGuidance = computed(() => {
if (story.value?.generation_status === 'degraded_completed') {

View File

@@ -33,6 +33,7 @@ interface StoryDetailResponse {
image_status: string
audio_status: string
last_error: string | null
retryable_assets: Array<'image' | 'audio'>
}
const route = useRoute()
@@ -51,11 +52,7 @@ const isLastPage = computed(() => currentPageIndex.value === totalPages.value -
const generationMeta = computed(() => getGenerationStatusMeta(storybook.value?.generation_status))
const imageMeta = computed(() => getAssetStatusMeta(storybook.value?.image_status))
const audioMeta = computed(() => getAssetStatusMeta(storybook.value?.audio_status))
const canRetryImages = computed(() =>
Boolean(storybook.value?.id)
&& storybook.value?.image_status !== 'ready'
&& storybook.value?.image_status !== 'generating',
)
const canRetryImages = computed(() => storybook.value?.retryable_assets?.includes('image') ?? false)
const currentPage = computed(() => {
if (!storybook.value || isCover.value) return null
return storybook.value.pages[currentPageIndex.value]
@@ -151,6 +148,7 @@ async function loadStorybook() {
image_status: detail.image_status,
audio_status: detail.audio_status,
last_error: detail.last_error,
retryable_assets: detail.retryable_assets,
})
} catch (e) {
error.value = e instanceof Error ? e.message : '绘本加载失败'
@@ -186,6 +184,7 @@ async function retryStorybookImages() {
image_status: detail.image_status,
audio_status: detail.audio_status,
last_error: detail.last_error,
retryable_assets: detail.retryable_assets,
})
} catch (e) {
error.value = e instanceof Error ? e.message : '插图补全失败'