fix:修复 ScriptView 详情面板重复展示及列表预览行数据路径

- ScriptView.openScriptChat 移除重复 push wishTheme/novelContent,改为从 messages 真实数据按 type 映射为 chat-bubble(与 ScriptDetailView.rebuildResultMessages 一致)
- ScriptLibraryView.getOutlinePreview 增加多路径探测(plotJson.stages.outline.beats / fullPayload.outline.beats / plotJson.outline.beats),兼容老剧本数据
This commit is contained in:
2026-07-26 16:30:33 +08:00
parent d220b01ba4
commit 50fb2404fd
2 changed files with 75 additions and 41 deletions
@@ -255,10 +255,15 @@ const getInitial = (script) => (script.title || '剧').slice(0, 1)
/** /**
* 获取大纲预览文本(前 2 章标题) * 获取大纲预览文本(前 2 章标题)
* 数据来源script.plotJson.stages.outline.beats * 数据来源按优先级探测:
* 1. plotJson.stages.outline.beatsTask 1-5 部署后新生成的小说)
* 2. plotJson.fullPayload.outline.beats(兼容老剧本可能的 fullPayload 结构)
* 3. 直接 plotJson.outline.beats(兜底)
*/ */
const getOutlinePreview = (script) => { const getOutlinePreview = (script) => {
const beats = script?.plotJson?.stages?.outline?.beats const beats = script?.plotJson?.stages?.outline?.beats
|| script?.plotJson?.fullPayload?.outline?.beats
|| script?.plotJson?.outline?.beats
if (!Array.isArray(beats) || beats.length === 0) return '' if (!Array.isArray(beats) || beats.length === 0) return ''
const parts = beats.slice(0, 2).map((beat, i) => { const parts = beats.slice(0, 2).map((beat, i) => {
const title = beat.title || '' const title = beat.title || ''
+69 -40
View File
@@ -1455,45 +1455,73 @@ const openScriptChat = async (payload = {}) => {
await loadMessages() await loadMessages()
} }
// 将历史剧本数据转换为统一对话消息格式,填充 resultMessages // 从后端 messages 重建统一对话消息流,复刻生成时的 chat-bubble 展示
const novelContent = currentResult.value?.content || currentResult.value?.plotJson?.fullContent || '' // 不再重复 push wishTheme/novelContentmessages 中已包含)
const wishTheme = currentResult.value?.theme || currentResult.value?.title || '' const messagesList = messages.value || []
messagesList.forEach(m => {
// 1. 用户心愿作为首条 user 消息 if (m.type === 'clarification_question') {
if (wishTheme) { let card = {}
resultMessages.value.push({ try { card = JSON.parse(m.content || '{}') } catch (e) { card = {} }
id: `loaded-wish-${Date.now()}`,
role: 'user',
kind: 'text',
content: wishTheme,
pending: false,
time: formatMessageTime(),
submitted: false,
confirmed: false
})
}
// 2. 当前小说正文作为 AI novel 消息(已完成态)
if (novelContent) {
resultMessages.value.push({
id: `loaded-novel-${Date.now()}`,
role: 'assistant',
kind: 'novel',
content: novelContent,
pending: false,
time: formatMessageTime(),
submitted: false,
confirmed: false
})
}
// 3. 对话历史中除首条外的其他消息追加到对话流
// (首条通常是与 wishTheme 重复的用户消息,跳过避免重复)
if (messages.value.length > 0) {
messages.value.slice(1).forEach(m => {
resultMessages.value.push({ resultMessages.value.push({
id: m.id || createMessageId(), id: m.id || createMessageId(),
role: m.sender === 'user' ? 'user' : 'assistant', role: 'assistant',
kind: 'card',
content: '',
card,
answer: '',
pending: false,
time: formatMessageTime(),
submitted: true,
confirmed: true
})
} else if (m.type === 'clarification_answer') {
// 把答案合并到上一条 card 消息的 answer 字段
const lastCard = [...resultMessages.value].reverse().find(x => x.kind === 'card')
if (lastCard) {
lastCard.answer = m.content || '未回答'
lastCard.submitted = true
} else {
// 无对应 question,作为独立 user 消息
resultMessages.value.push({
id: m.id || createMessageId(),
role: 'user',
kind: 'text',
content: m.content || '',
pending: false,
time: formatMessageTime(),
submitted: false,
confirmed: false
})
}
} else if (m.type === 'outline') {
let outline = {}
try { outline = JSON.parse(m.content || '{}') } catch (e) { outline = {} }
resultMessages.value.push({
id: m.id || createMessageId(),
role: 'assistant',
kind: 'outline',
content: '',
outline,
pending: false,
time: formatMessageTime(),
submitted: false,
confirmed: true
})
} else if (m.type === 'script') {
resultMessages.value.push({
id: m.id || createMessageId(),
role: 'assistant',
kind: 'novel',
content: m.content || '',
pending: false,
time: formatMessageTime(),
submitted: false,
confirmed: true
})
} else if (m.type === 'chat' && m.sender === 'user') {
resultMessages.value.push({
id: m.id || createMessageId(),
role: 'user',
kind: 'text', kind: 'text',
content: m.content || '', content: m.content || '',
pending: false, pending: false,
@@ -1501,12 +1529,13 @@ const openScriptChat = async (payload = {}) => {
submitted: false, submitted: false,
confirmed: false confirmed: false
}) })
}) }
} // 跳过 system 类型(不展示)
})
analytics.track('script_chat_open_from_library', { analytics.track('script_chat_open_from_library', {
script_id: script.id, script_id: script.id,
has_history: messages.value.length > 0 has_history: messagesList.length > 0
}, { eventType: 'script', pagePath }) }, { eventType: 'script', pagePath })
scrollResultToLatest() scrollResultToLatest()
} }