docs:新增 AI 消息卡片功能按钮统一设计文档
- 修复 story-card 展开失效 bug - 为每条 AI 消息添加完整功能按钮组 - 采用方案 A:在现有单文件组件内修复 + 扩展
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
---
|
||||
author: claude
|
||||
created_at: 2026-06-27
|
||||
purpose: 统一小程序实现心愿页面中所有 AI 消息卡片的功能按钮,并修复 story-card 展开失效 bug
|
||||
---
|
||||
|
||||
# AI 消息卡片功能按钮统一设计
|
||||
|
||||
## 背景
|
||||
|
||||
在小程序「实现心愿」页面(`mini-program/src/pages/main/ScriptView.vue`)中:
|
||||
|
||||
1. **第一个 AI 回复卡片**(`story-card`)拥有完整的功能按钮:展开/收起、复制、换个方向、不像我、继续生成、播放。
|
||||
2. **后续 AI 消息**(`result-chat-list`)只有基础的展开/收起,缺少复制、换个方向、不像我、继续生成、播放。
|
||||
3. **story-card 展开失效**:当用户触发过重新生成(`resultHasScriptReplies` 为 `true`)后,`<template v-if="!resultHasScriptReplies">` 会隐藏整个故事正文和底部展开按钮,导致点击展开无效果。
|
||||
|
||||
## 目标
|
||||
|
||||
- 每条 AI 回复消息卡片都拥有完整的功能按钮(展开/收起、复制、换个方向、不像我、继续生成、播放)
|
||||
- 修复 story-card 展开失效的 bug
|
||||
- 所有按钮功能正常可用
|
||||
|
||||
## 方案选择
|
||||
|
||||
采用 **方案 A:在现有单文件组件内修复 + 扩展**
|
||||
|
||||
- 不提取独立组件,保持现有文件结构
|
||||
- 改动最小、风险低、不引入新文件
|
||||
- 后续如有更复杂的差异化需求再升级
|
||||
|
||||
## 详细设计
|
||||
|
||||
### 1. 修复 story-card 展开失效
|
||||
|
||||
**根因**:`ScriptView.vue` 第 192 行的条件包裹
|
||||
|
||||
```vue
|
||||
<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. 新增/修改的事件处理器
|
||||
|
||||
1. **`copyMessageContent(message)`**(新增):
|
||||
- 复制 `message.content` 到剪贴板
|
||||
- 空内容时 `showToast` 提示「暂无可复制内容」
|
||||
- 埋点 `script_message_copy_click`
|
||||
|
||||
2. **`playMessageTts(message)`**(新增):
|
||||
- 调用 `ttsPlayer.playSource(currentResult.value?.id || '')`
|
||||
- 所有消息都播放同一个故事的 TTS(TTS 基于 `currentResult` 生成)
|
||||
- 埋点 `script_message_tts_click`
|
||||
|
||||
3. **`toggleMessageCollapse(message)`**(修改):
|
||||
- 补充埋点 `script_message_collapse_toggle`(与 `toggleStoryCollapse` 对齐)
|
||||
|
||||
### 4. 样式
|
||||
|
||||
为消息卡片内的按钮组新建 `.message-actions` 样式,复用 `.result-actions` 和 `.action-btn` 的视觉风格:
|
||||
|
||||
```css
|
||||
.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`
|
||||
|
||||
### 模板修改
|
||||
1. 去掉第 192 行 `<template v-if="!resultHasScriptReplies">` 条件包裹
|
||||
2. 在 `result-chat-list` 的 assistant 消息中添加功能按钮组
|
||||
|
||||
### 脚本修改
|
||||
1. 新增 `copyMessageContent(message)` 方法
|
||||
2. 新增 `playMessageTts(message)` 方法
|
||||
3. 修改 `toggleMessageCollapse(message)` 补充埋点
|
||||
|
||||
### 样式修改
|
||||
1. 新增 `.message-actions` 样式
|
||||
Reference in New Issue
Block a user