diff --git a/mini-program/src/pages/main/ScriptDetailView.vue b/mini-program/src/pages/main/ScriptDetailView.vue index 6bc51d0..c4a83cf 100644 --- a/mini-program/src/pages/main/ScriptDetailView.vue +++ b/mini-program/src/pages/main/ScriptDetailView.vue @@ -24,7 +24,24 @@ {{ msg.card.question }} - 已回答:{{ msg.answer || '未回答' }} + + + 已回答: + {{ getAnswerLabel(msg) }} + + + + + {{ opt.label || opt.value }} + {{ opt.description }} + + + @@ -135,7 +152,9 @@ const rebuildResultMessages = (scriptData, messages) => { } else if (m.type === 'clarification_answer') { const lastCard = [...result].reverse().find(x => x.kind === 'card') if (lastCard) { - lastCard.answer = m.content || '未回答' + // answer 存用户提交的 value,渲染时通过 card.options 映射成中文 label + lastCard.answer = m.content || '' + lastCard.selectedValue = m.content || '' } else { // 无对应 question,作为独立 user 消息 result.push({ id: m.id, role: 'user', kind: 'text', content: m.content || '' }) @@ -167,6 +186,20 @@ const rebuildResultMessages = (scriptData, messages) => { return result } +/** + * 把已回答卡片的 value(如 "family")映射为对应的中文 label(如 "家人") + * 若选项中找不到匹配的 value,则原样返回 answer(兜底) + * 若 msg.card 不存在则返回 "未回答" + */ +const getAnswerLabel = (msg) => { + if (!msg || !msg.card) return '未回答' + const raw = msg.selectedValue || msg.answer || '' + if (!raw) return '未回答' + const options = Array.isArray(msg.card.options) ? msg.card.options : [] + const match = options.find(opt => opt && opt.value === raw) + return match?.label || raw +} + const continueCurrent = () => { if (!script.value?.id) return uni.setStorageSync('pending_open_script_chat', { @@ -332,9 +365,62 @@ onUnmounted(() => { color: rgba(255, 255, 255, 0.9); font-weight: 500; } -.card-answer-text { +.card-answer-row { + display: flex; + align-items: baseline; + gap: 8rpx; + margin-bottom: 4rpx; +} +.card-answer-prefix { font-size: 26rpx; - color: rgba(193, 134, 255, 0.88); + color: rgba(255, 255, 255, 0.6); +} +.card-answer-label { + font-size: 28rpx; + color: rgba(193, 134, 255, 0.95); + font-weight: 600; +} +.card-options-list { + display: flex; + flex-direction: column; + gap: 10rpx; + margin-top: 8rpx; +} +.card-option-item { + position: relative; + display: flex; + flex-direction: column; + gap: 4rpx; + padding: 14rpx 18rpx; + border-radius: 14rpx; + background: rgba(255, 255, 255, 0.04); + border: 1rpx solid rgba(255, 255, 255, 0.08); +} +.card-option-item.selected { + background: rgba(168, 85, 247, 0.16); + border-color: rgba(168, 85, 247, 0.45); +} +.card-option-label { + font-size: 26rpx; + color: rgba(255, 255, 255, 0.92); + font-weight: 500; +} +.card-option-item.selected .card-option-label { + color: rgba(220, 195, 255, 1); +} +.card-option-desc { + font-size: 22rpx; + color: rgba(255, 255, 255, 0.55); + line-height: 1.5; +} +.card-option-mark { + position: absolute; + right: 14rpx; + top: 50%; + transform: translateY(-50%); + font-size: 30rpx; + color: rgba(220, 195, 255, 1); + font-weight: 700; } .outline-title { font-size: 32rpx; diff --git a/mini-program/src/pages/main/ScriptView.vue b/mini-program/src/pages/main/ScriptView.vue index 8f58be3..2941906 100644 --- a/mini-program/src/pages/main/ScriptView.vue +++ b/mini-program/src/pages/main/ScriptView.vue @@ -130,7 +130,24 @@ /> {{ msg.card.question }} - 已回答:{{ msg.answer }} + + + 已回答: + {{ getAnswerLabel(msg) }} + + + + + {{ opt.label || opt.value }} + {{ opt.description }} + + + @@ -1189,6 +1206,20 @@ const PENDING_SCRIPT_CHAT_KEY = 'pending_open_script_chat' const createMessageId = () => `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` const createConversationId = () => `conv-${Date.now()}-${Math.random().toString(36).slice(2, 8)}` +/** + * 把已回答卡片的 value(如 "family")映射为对应的中文 label(如 "家人") + * 若选项中找不到匹配的 value,则原样返回 answer(兜底) + * 若 msg.card 不存在则返回 "未回答" + */ +const getAnswerLabel = (msg) => { + if (!msg || !msg.card) return '未回答' + const raw = msg.selectedValue || msg.answer || '' + if (!raw) return '未回答' + const options = Array.isArray(msg.card.options) ? msg.card.options : [] + const match = options.find(opt => opt && opt.value === raw) + return match?.label || raw +} + const getCurrentScriptId = () => String(currentResult.value?.id || '') const getCurrentConversationId = () => String(currentConversationId.value || currentResult.value?.conversationId || '') @@ -1475,10 +1506,12 @@ const openScriptChat = async (payload = {}) => { confirmed: true }) } else if (m.type === 'clarification_answer') { - // 把答案合并到上一条 card 消息的 answer 字段 + // 把答案合并到上一条 card 消息:answer 存用户原始 value,selectedValue 也存 value 用于渲染时映射 label const lastCard = [...resultMessages.value].reverse().find(x => x.kind === 'card') if (lastCard) { - lastCard.answer = m.content || '未回答' + const rawValue = m.content || '' + lastCard.answer = rawValue // 原始 value(用于查找 label) + lastCard.selectedValue = rawValue // 选中的 value(渲染时通过 options 映射成 label) lastCard.submitted = true } else { // 无对应 question,作为独立 user 消息 @@ -1841,12 +1874,11 @@ const submitClarification = (answer) => { if (answeringClarification.value) return // 找最后一张未提交的卡片消息(mp-weixin 模板不支持内联箭头函数传 msg,改为自己查找) const card = [...resultMessages.value].reverse().find(m => m.kind === 'card' && !m.submitted) - // 通过 value 查找选项的 label,用于前端显示;后端 payload 仍用 value(语义化) - const option = card?.card?.options?.find(opt => opt.value === answer) - const label = option?.label || answer if (card) { card.submitted = true - card.answer = label // 显示用 label(中文);答案已在卡片中显示,无需额外用户气泡 + // answer 存用户提交的 value,渲染时通过 card.options 映射成中文 label(与历史回放逻辑一致) + card.answer = answer + card.selectedValue = answer } pendingNextResponse.value = true // 标记等待下一个 assistant 响应 answeringClarification.value = true @@ -3775,6 +3807,63 @@ onUnmounted(() => { font-size: 26rpx; padding: 16rpx 0; } +.card-answer-row { + display: flex; + align-items: baseline; + gap: 8rpx; + margin-bottom: 12rpx; +} +.card-answer-prefix { + font-size: 26rpx; + color: rgba(255, 255, 255, 0.6); +} +.card-answer-label { + font-size: 28rpx; + color: rgba(193, 134, 255, 0.95); + font-weight: 600; +} +.card-options-list { + display: flex; + flex-direction: column; + gap: 10rpx; + margin-top: 8rpx; +} +.card-option-item { + position: relative; + display: flex; + flex-direction: column; + gap: 4rpx; + padding: 14rpx 18rpx; + border-radius: 14rpx; + background: rgba(255, 255, 255, 0.04); + border: 1rpx solid rgba(255, 255, 255, 0.08); +} +.card-option-item.selected { + background: rgba(168, 85, 247, 0.16); + border-color: rgba(168, 85, 247, 0.45); +} +.card-option-label { + font-size: 26rpx; + color: rgba(255, 255, 255, 0.92); + font-weight: 500; +} +.card-option-item.selected .card-option-label { + color: rgba(220, 195, 255, 1); +} +.card-option-desc { + font-size: 22rpx; + color: rgba(255, 255, 255, 0.55); + line-height: 1.5; +} +.card-option-mark { + position: absolute; + right: 14rpx; + top: 50%; + transform: translateY(-50%); + font-size: 30rpx; + color: rgba(220, 195, 255, 1); + font-weight: 700; +} .outline-title { color: #ffffff;