diff --git a/mini-program/src/pages/main/ScriptView.vue b/mini-program/src/pages/main/ScriptView.vue index c90e9ba..4c65ff0 100644 --- a/mini-program/src/pages/main/ScriptView.vue +++ b/mini-program/src/pages/main/ScriptView.vue @@ -173,7 +173,8 @@ {{ generationCopy }} {{ generationSubcopy }} - + + @@ -346,6 +347,7 @@ const generationScrollTarget = ref('') const generationScrollTop = ref(0) const generationAutoFollow = ref(true) const generationDisplayText = ref('') +const resumeableSessionId = ref('') const lastGenerationPrompt = ref('') const lastSubmitSource = ref('text') const lastGenerationRevision = ref(false) @@ -1641,7 +1643,9 @@ const runGeneration = async ({ prompt, displayText, source = 'text', saveTheme } novelOutline.value = null clarificationCard.value = null novelSessionId.value = '' + resumeableSessionId.value = '' outlineFeedback.value = '' + generationDisplayText.value = display generationScrollTarget.value = '' generationScrollTop.value = 0 generationScrollAnchor.value = 'generation-stream-anchor-a' @@ -1709,7 +1713,13 @@ const handleShortNovelEvent = (event) => { viewMode.value = 'chat' break case 'error': - markGenerationFailed(payload.message || '生成失败') + // 识别每日限制错误,保存 session_id 供"继续创作"使用 + if (payload.code === 'DAILY_GENERATION_IN_PROGRESS' && session_id) { + resumeableSessionId.value = session_id + markGenerationFailed(payload.message || '今天已有未完成的创作,可点击继续创作恢复') + } else { + markGenerationFailed(payload.message || '生成失败') + } break } } @@ -1748,6 +1758,42 @@ const modifyOutline = (feedback) => { }) } +const resumeSession = () => { + if (!resumeableSessionId.value || generating.value) return + novelSessionId.value = resumeableSessionId.value + resumeableSessionId.value = '' + generating.value = true + streamContent.value = '' + novelFullText.value = '' + generationStatus.value = 'waiting' + generationError.value = '' + generationDisplayText.value = '继续之前的创作' + streamWriter.reset() + startGenerationFeedback() + viewState.value = 'generating' + keepGenerationAtBottom() + + try { + currentStreamTask.value = followupStream({ + sessionId: novelSessionId.value, + action: 'retry', + payload: null, + onEvent: handleShortNovelEvent, + onError: (msg) => { + markGenerationFailed(msg) + analytics.track('script_generate_fail', { + source: 'resume', + error: msg + }, { eventType: 'script', pagePath }) + } + }) + } catch (error) { + markGenerationFailed(error.message || '恢复失败') + } finally { + generating.value = false + } +} + const submitWish = async (source = 'text') => { const text = wishText.value.trim() if (!text || generating.value) return