e014450aa3
- 修复 story-card 展开失效 bug - 为每条 AI 消息添加完整功能按钮组 - 采用方案 A:在现有单文件组件内修复 + 扩展
5.1 KiB
5.1 KiB
author, created_at, purpose
| author | created_at | purpose |
|---|---|---|
| claude | 2026-06-27 | 统一小程序实现心愿页面中所有 AI 消息卡片的功能按钮,并修复 story-card 展开失效 bug |
AI 消息卡片功能按钮统一设计
背景
在小程序「实现心愿」页面(mini-program/src/pages/main/ScriptView.vue)中:
- 第一个 AI 回复卡片(
story-card)拥有完整的功能按钮:展开/收起、复制、换个方向、不像我、继续生成、播放。 - 后续 AI 消息(
result-chat-list)只有基础的展开/收起,缺少复制、换个方向、不像我、继续生成、播放。 - story-card 展开失效:当用户触发过重新生成(
resultHasScriptReplies为true)后,<template v-if="!resultHasScriptReplies">会隐藏整个故事正文和底部展开按钮,导致点击展开无效果。
目标
- 每条 AI 回复消息卡片都拥有完整的功能按钮(展开/收起、复制、换个方向、不像我、继续生成、播放)
- 修复 story-card 展开失效的 bug
- 所有按钮功能正常可用
方案选择
采用 方案 A:在现有单文件组件内修复 + 扩展
- 不提取独立组件,保持现有文件结构
- 改动最小、风险低、不引入新文件
- 后续如有更复杂的差异化需求再升级
详细设计
1. 修复 story-card 展开失效
根因:ScriptView.vue 第 192 行的条件包裹
<template v-if="!resultHasScriptReplies">
<scroll-view v-if="storyCollapsed" ...>
<text class="story-body">{{ displayedResultContent }}</text>
</scroll-view>
<text v-else class="story-body">{{ displayedResultContent }}</text>
<view class="collapse-row" @click="toggleStoryCollapse">...</view>
</template>
当 resultHasScriptReplies 为 true(有 kind: 'script' 的消息)时,整个故事正文和底部展开按钮被隐藏。
修复:去掉 <template v-if="!resultHasScriptReplies"> 条件包裹,让故事正文始终由 storyCollapsed 控制展开/收起。
副作用:story-card 始终显示完整故事正文,与 result-chat-list 中的 script 消息内容重复。这是预期行为——两个卡片独立操作各自内容。
2. 给每条 assistant 消息加功能按钮组
布局:在每条 assistant 消息的内容 + 展开/收起按钮之后,追加一行网格按钮组,2 列布局(与 story-card 的 .result-actions 一致)。
按钮清单(按顺序):
| 按钮 | 作用 | 实现方式 |
|---|---|---|
| 复制 | 复制该消息正文到剪贴板 | uni.setClipboardData |
| 换个方向 | 进入「换方向」修订确认 | 复用现有 changeDirection() |
| 不像我 | 进入「不像我」修订确认 | 复用现有 notLikeMe() |
| 继续生成 | 收起故事 + 聚焦输入框 | 复用现有 continueInChat() |
| 播放 | 播放 TTS 音频 | 复用 ttsPlayer.playSource,传 currentResult.id |
按钮条件:
- 展开/收起、复制:所有 assistant 消息都有
- 换个方向、不像我、继续生成、播放:所有 assistant 消息都有(本质上是全局操作,作用在
currentResult上) - 正在
pending的 assistant 消息不显示按钮组(保持现有逻辑,isAssistantMessage已排除pending)
3. 新增/修改的事件处理器
-
copyMessageContent(message)(新增):- 复制
message.content到剪贴板 - 空内容时
showToast提示「暂无可复制内容」 - 埋点
script_message_copy_click
- 复制
-
playMessageTts(message)(新增):- 调用
ttsPlayer.playSource(currentResult.value?.id || '') - 所有消息都播放同一个故事的 TTS(TTS 基于
currentResult生成) - 埋点
script_message_tts_click
- 调用
-
toggleMessageCollapse(message)(修改):- 补充埋点
script_message_collapse_toggle(与toggleStoryCollapse对齐)
- 补充埋点
4. 样式
为消息卡片内的按钮组新建 .message-actions 样式,复用 .result-actions 和 .action-btn 的视觉风格:
.message-actions {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14rpx;
margin-top: 16rpx;
}
按钮直接复用 .action-btn 类名,确保视觉与主卡片一致。展开/收起按钮(.message-toggle)保留现有金色调样式,与功能按钮组做视觉区分。
5. 边界情况
| 场景 | 行为 |
|---|---|
| 空内容的 assistant 消息 | 复制按钮 showToast 提示「暂无可复制内容」;其他按钮正常可用 |
| pending 中的消息 | 不显示按钮组(现有逻辑) |
| user 消息 | 不显示按钮组 |
无 currentResult 时的播放 |
按钮仍可点击,playSource 会走内部兜底(传空 id) |
修改范围
仅修改一个文件:mini-program/src/pages/main/ScriptView.vue
模板修改
- 去掉第 192 行
<template v-if="!resultHasScriptReplies">条件包裹 - 在
result-chat-list的 assistant 消息中添加功能按钮组
脚本修改
- 新增
copyMessageContent(message)方法 - 新增
playMessageTts(message)方法 - 修改
toggleMessageCollapse(message)补充埋点
样式修改
- 新增
.message-actions样式