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;