docs:补充前端代码完整示例,移除占位符
This commit is contained in:
@@ -133,10 +133,16 @@ log.info("[ShortNovel SSE] 完成读取上游响应");
|
||||
```
|
||||
|
||||
**关键点**:
|
||||
- 使用 `readUtf8LineStrict()` 确保严格的行读取
|
||||
- 添加毫秒级时间戳日志,便于诊断
|
||||
- 在 `emitter.send()` 后发送空注释事件,触发 SseEmitter 的 flush
|
||||
- 增加 `originalQuery.trim().isEmpty()` 检查,避免空字符串
|
||||
- 使用 `readUtf8LineStrict()` 替代 `readUtf8Line()`:
|
||||
- `readUtf8Line()` 在遇到 EOF 时可能返回不完整的数据
|
||||
- `readUtf8LineStrict()` 严格遵循 SSE 规范,遇到 `\n` 或 `\r\n` 才返回一行
|
||||
- 这确保每行数据都是完整的 SSE 事件,避免缓冲导致的数据堆积
|
||||
- 添加毫秒级时间戳日志,便于诊断事件到达的时间间隔
|
||||
- 在 `emitter.send()` 后发送空注释事件,触发 SseEmitter 的 flush:
|
||||
- Spring 的 `SseEmitter` 默认会缓冲事件,直到缓冲区满或连接关闭
|
||||
- 发送空注释 `comment("")` 会强制刷新缓冲区,确保事件立即发送到前端
|
||||
- 这是实现真正流式传输的关键步骤
|
||||
- 增加 `originalQuery.trim().isEmpty()` 检查,避免空字符串被误判为有效值
|
||||
|
||||
#### 2. nginx 配置优化
|
||||
|
||||
@@ -206,7 +212,20 @@ const handleShortNovelEvent = (event) => {
|
||||
hasFullText: !!payload.full_text,
|
||||
timestamp
|
||||
})
|
||||
// ... 其余逻辑
|
||||
// 标记最后一条 novel 消息完成
|
||||
const lastNovel = [...resultMessages.value].reverse().find(m => m.kind === 'novel')
|
||||
if (lastNovel) {
|
||||
if (payload.full_text) lastNovel.content = payload.full_text
|
||||
lastNovel.pending = false
|
||||
}
|
||||
scriptId.value = payload.scriptId || ''
|
||||
conversationId.value = payload.conversationId || ''
|
||||
currentVersionMessageId.value = payload.currentVersionMessageId || ''
|
||||
generationPhase.value = 'done'
|
||||
generationStatus.value = 'idle'
|
||||
pendingNextResponse.value = false
|
||||
persistResultMessages()
|
||||
store.fetchScripts()
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -217,17 +236,26 @@ const startNovelGeneration = async (source = 'home') => {
|
||||
const text = wishText.value.trim()
|
||||
if (!text) return
|
||||
|
||||
// ... 其他代码
|
||||
// ... 前面的验证代码 ...
|
||||
|
||||
firstQuery.value = text // 确认设置首次心愿文本
|
||||
console.log('[ScriptView] 设置 firstQuery:', { text, length: text.length })
|
||||
|
||||
// ... 其余代码
|
||||
// ... 后面的初始化代码 ...
|
||||
}
|
||||
|
||||
// 在所有 followupStream 调用中确认 originalQuery 传递
|
||||
// 在 submitClarification 中添加日志确认 originalQuery 传递
|
||||
const submitClarification = (answer) => {
|
||||
// ... 其他代码
|
||||
if (answeringClarification.value) return
|
||||
const card = [...resultMessages.value].reverse().find(m => m.kind === 'card' && !m.submitted)
|
||||
const option = card?.card?.options?.find(opt => opt.value === answer)
|
||||
const label = option?.label || answer
|
||||
if (card) {
|
||||
card.submitted = true
|
||||
card.answer = label
|
||||
}
|
||||
pendingNextResponse.value = true
|
||||
answeringClarification.value = true
|
||||
console.log('[ScriptView] submitClarification:', {
|
||||
sessionId: novelSessionId.value,
|
||||
originalQuery: firstQuery.value,
|
||||
@@ -241,9 +269,93 @@ const submitClarification = (answer) => {
|
||||
onEvent: handleShortNovelEvent,
|
||||
onError: (errMsg) => markGenerationFailed(errMsg)
|
||||
})
|
||||
setTimeout(() => { answeringClarification.value = false }, 200)
|
||||
}
|
||||
|
||||
// 类似地更新 confirmOutline, modifyOutline, resumeSession
|
||||
// 在 confirmOutline 中添加日志和确认 originalQuery 传递
|
||||
const confirmOutline = (msg) => {
|
||||
if (msg) msg.confirmed = true
|
||||
pendingNextResponse.value = true
|
||||
addResultMessage({ role: 'user', kind: 'text', content: '确认大纲,开始生成小说' })
|
||||
console.log('[ScriptView] confirmOutline:', {
|
||||
sessionId: novelSessionId.value,
|
||||
originalQuery: firstQuery.value,
|
||||
originalQueryLength: firstQuery.value?.length
|
||||
})
|
||||
currentStreamTask.value = followupStream({
|
||||
sessionId: novelSessionId.value,
|
||||
action: 'confirm_outline',
|
||||
payload: null,
|
||||
originalQuery: firstQuery.value,
|
||||
onEvent: handleShortNovelEvent,
|
||||
onError: (errMsg) => markGenerationFailed(errMsg)
|
||||
})
|
||||
}
|
||||
|
||||
// 在 modifyOutline 中添加日志和确认 originalQuery 传递
|
||||
const modifyOutline = (msg, feedback) => {
|
||||
if (!feedback.trim()) {
|
||||
uni.showToast({ title: '请先填写修改意见', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (msg) msg.confirmed = true
|
||||
pendingNextResponse.value = true
|
||||
addResultMessage({ role: 'user', kind: 'text', content: feedback })
|
||||
console.log('[ScriptView] modifyOutline:', {
|
||||
sessionId: novelSessionId.value,
|
||||
originalQuery: firstQuery.value,
|
||||
originalQueryLength: firstQuery.value?.length
|
||||
})
|
||||
currentStreamTask.value = followupStream({
|
||||
sessionId: novelSessionId.value,
|
||||
action: 'modify_outline',
|
||||
payload: { feedback },
|
||||
originalQuery: firstQuery.value,
|
||||
onEvent: handleShortNovelEvent,
|
||||
onError: (errMsg) => markGenerationFailed(errMsg)
|
||||
})
|
||||
}
|
||||
|
||||
// 在 resumeSession 中添加日志和确认 originalQuery 传递
|
||||
const resumeSession = () => {
|
||||
if (!resumeableSessionId.value || generating.value) return
|
||||
novelSessionId.value = resumeableSessionId.value
|
||||
resumeableSessionId.value = ''
|
||||
generating.value = true
|
||||
generationPhase.value = 'generating'
|
||||
generationStatus.value = 'waiting'
|
||||
generationError.value = ''
|
||||
addResultMessage({ role: 'user', kind: 'text', content: '继续之前的创作' })
|
||||
streamWriter.reset()
|
||||
startGenerationFeedback()
|
||||
keepResultAtBottom()
|
||||
console.log('[ScriptView] resumeSession:', {
|
||||
sessionId: novelSessionId.value,
|
||||
originalQuery: firstQuery.value,
|
||||
originalQueryLength: firstQuery.value?.length
|
||||
})
|
||||
|
||||
try {
|
||||
currentStreamTask.value = followupStream({
|
||||
sessionId: novelSessionId.value,
|
||||
action: 'retry',
|
||||
payload: null,
|
||||
originalQuery: firstQuery.value,
|
||||
onEvent: handleShortNovelEvent,
|
||||
onError: (errMsg) => {
|
||||
markGenerationFailed(errMsg)
|
||||
analytics.track('script_generate_fail', {
|
||||
source: 'resume',
|
||||
error: errMsg
|
||||
}, { eventType: 'script', pagePath })
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
markGenerationFailed(error.message || '恢复失败')
|
||||
} finally {
|
||||
generating.value = false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**关键点**:
|
||||
|
||||
Reference in New Issue
Block a user