docs:新增 AI 消息卡片功能按钮实现计划

This commit is contained in:
2026-06-27 22:29:27 +08:00
parent d724cab581
commit 847e80aa0e
@@ -0,0 +1,467 @@
---
author: claude
created_at: 2026-06-27
purpose: AI 消息卡片功能按钮统一实现计划
---
# AI 消息卡片功能按钮统一实现计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 统一小程序实现心愿页面中所有 AI 消息卡片的功能按钮,并修复 story-card 展开失效 bug
**Architecture:** 在现有单文件组件 `ScriptView.vue` 内修复 + 扩展,不提取独立组件,保持现有文件结构
**Tech Stack:** Vue 3, UniApp, 微信小程序
---
## 文件结构
**修改:**
- `mini-program/src/pages/main/ScriptView.vue` - 主页面组件(模板 + 脚本 + 样式)
---
### Task 1: 修复 story-card 展开失效 bug
**Files:**
- Modify: `mini-program/src/pages/main/ScriptView.vue:192-210`
- [ ] **Step 1: 移除 resultHasScriptReplies 条件包裹**
打开 `mini-program/src/pages/main/ScriptView.vue`,找到第 192 行的 `<template v-if="!resultHasScriptReplies">`,删除这个条件包裹标签和对应的 `</template>` 闭合标签(第 210 行)。
修改前:
```vue
<template v-if="!resultHasScriptReplies">
<scroll-view
v-if="storyCollapsed"
class="story-body-scroll"
scroll-y
:enhanced="true"
:show-scrollbar="true"
>
<text class="story-body" :selectable="true" :user-select="true">{{ displayedResultContent }}</text>
</scroll-view>
<text v-else class="story-body" :selectable="true" :user-select="true">{{ displayedResultContent }}</text>
<view class="collapse-row" @click="toggleStoryCollapse">
<text class="collapse-row-text">{{ storyCollapsed ? '展开全文' : '收起全文' }}</text>
<view class="collapse-chevron" :class="{ down: storyCollapsed }">
<view></view>
<view></view>
</view>
</view>
</template>
```
修改后:
```vue
<scroll-view
v-if="storyCollapsed"
class="story-body-scroll"
scroll-y
:enhanced="true"
:show-scrollbar="true"
>
<text class="story-body" :selectable="true" :user-select="true">{{ displayedResultContent }}</text>
</scroll-view>
<text v-else class="story-body" :selectable="true" :user-select="true">{{ displayedResultContent }}</text>
<view class="collapse-row" @click="toggleStoryCollapse">
<text class="collapse-row-text">{{ storyCollapsed ? '展开全文' : '收起全文' }}</text>
<view class="collapse-chevron" :class="{ down: storyCollapsed }">
<view></view>
<view></view>
</view>
</view>
```
- [ ] **Step 2: 验证修复**
在微信开发者工具中编译运行,进入「实现心愿」页面:
1. 输入心愿并生成故事
2. 点击「继续生成」创建 script 类型消息
3. 点击 story-card 的展开/收起按钮,验证故事正文能正确展开和收起
4. 确认控制台无报错
- [ ] **Step 3: 提交代码**
```bash
git add mini-program/src/pages/main/ScriptView.vue
git commit -m "fix: 修复 story-card 展开失效 bug
移除 resultHasScriptReplies 条件包裹,让故事正文始终由 storyCollapsed 控制展开/收起"
```
---
### Task 2: 添加新方法支持消息卡片功能
**Files:**
- Modify: `mini-program/src/pages/main/ScriptView.vue` (script 部分)
- [ ] **Step 1: 添加 copyMessageContent 方法**
`toggleMessageCollapse` 方法之后(约第 450 行),添加复制消息内容的方法:
```javascript
const copyMessageContent = (message) => {
const content = message?.content || ''
if (!content.trim()) {
uni.showToast({ title: '暂无可复制内容', icon: 'none' })
return
}
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({ title: '已复制', icon: 'success' })
}
})
analytics.track('script_message_copy_click', {
message_id: message?.id || '',
content_length: content.length
}, { eventType: 'script', pagePath })
}
```
- [ ] **Step 2: 添加 playMessageTts 方法**
`copyMessageContent` 方法之后,添加播放 TTS 的方法:
```javascript
const playMessageTts = (message) => {
const scriptId = currentResult.value?.id || ''
ttsPlayer.playSource(scriptId)
analytics.track('script_message_tts_click', {
message_id: message?.id || '',
script_id: scriptId
}, { eventType: 'script', pagePath })
}
```
- [ ] **Step 3: 修改 toggleMessageCollapse 方法添加埋点**
找到 `toggleMessageCollapse` 方法(约第 442-450 行),在方法开头添加埋点代码:
修改前:
```javascript
const toggleMessageCollapse = (message) => {
collapsedMessageIds.value[message.id] = !isMessageCollapsed(message)
}
```
修改后:
```javascript
const toggleMessageCollapse = (message) => {
collapsedMessageIds.value[message.id] = !isMessageCollapsed(message)
analytics.track('script_message_collapse_toggle', {
message_id: message?.id || '',
collapsed: collapsedMessageIds.value[message.id]
}, { eventType: 'script', pagePath })
}
```
- [ ] **Step 4: 验证方法添加**
在微信开发者工具中编译运行,确认控制台无语法错误。新方法暂时不会被调用,后续任务会在模板中使用。
- [ ] **Step 5: 提交代码**
```bash
git add mini-program/src/pages/main/ScriptView.vue
git commit -m "feat: 添加消息卡片功能方法
- copyMessageContent: 复制消息内容到剪贴板
- playMessageTts: 播放故事 TTS 音频
- toggleMessageCollapse: 添加展开/收起埋点"
```
---
### Task 3: 在 result-chat-list 中添加功能按钮组
**Files:**
- Modify: `mini-program/src/pages/main/ScriptView.vue:245-270`
- [ ] **Step 1: 在 assistant 消息中添加功能按钮组**
找到 `result-chat-list` 部分(约第 245-270 行),在消息内容和展开/收起按钮之后、时间戳之前,添加功能按钮组。
修改前:
```vue
<view
v-for="(message, index) in resultMessages"
:key="message.id"
class="result-chat-list"
>
<view
v-if="isAssistantMessage(message)"
class="chat-bubble assistant"
>
<text class="message-content">{{ getMessageContent(message) }}</text>
<view class="message-toggle" @click="toggleMessageCollapse(message)">
<text>{{ isMessageCollapsed(message) ? '展开全文' : '收起全文' }}</text>
<view class="collapse-chevron" :class="{ down: isMessageCollapsed(message) }">
<view></view>
<view></view>
</view>
</view>
<text class="message-time">{{ formatMessageTime(message.createdAt) }}</text>
</view>
<!-- user message -->
</view>
```
修改后:
```vue
<view
v-for="(message, index) in resultMessages"
:key="message.id"
class="result-chat-list"
>
<view
v-if="isAssistantMessage(message)"
class="chat-bubble assistant"
>
<text class="message-content">{{ getMessageContent(message) }}</text>
<view class="message-toggle" @click="toggleMessageCollapse(message)">
<text>{{ isMessageCollapsed(message) ? '展开全文' : '收起全文' }}</text>
<view class="collapse-chevron" :class="{ down: isMessageCollapsed(message) }">
<view></view>
<view></view>
</view>
</view>
<view class="message-actions">
<view class="action-btn" @click="copyMessageContent(message)">
<text>复制</text>
</view>
<view class="action-btn" @click="changeDirection">
<text>换个方向</text>
</view>
<view class="action-btn" @click="notLikeMe">
<text>不像我</text>
</view>
<view class="action-btn" @click="continueInChat">
<text>继续生成</text>
</view>
<view class="action-btn primary" @click="playMessageTts(message)">
<text> 播放</text>
</view>
</view>
<text class="message-time">{{ formatMessageTime(message.createdAt) }}</text>
</view>
<!-- user message -->
</view>
```
**说明:**
- 按钮组使用 `.message-actions` 容器,2 列网格布局
- 复制、换个方向、不像我、继续生成使用 `.action-btn` 样式
- 播放按钮使用 `.action-btn.primary` 样式(主色调突出)
- 所有按钮都调用 Task 2 中定义的方法或复用现有方法
- [ ] **Step 2: 验证按钮组显示**
在微信开发者工具中编译运行:
1. 进入「实现心愿」页面,生成故事
2. 点击「继续生成」创建 assistant 消息
3. 验证每条 assistant 消息下方显示 5 个功能按钮(复制、换个方向、不像我、继续生成、播放)
4. 验证按钮布局为 2 列网格
- [ ] **Step 3: 验证按钮功能**
逐个测试按钮功能:
1. **复制**:点击后应复制消息内容,显示「已复制」提示
2. **换个方向**:点击后应进入「换方向」修订确认流程
3. **不像我**:点击后应进入「不像我」修订确认流程
4. **继续生成**:点击后应收起故事并聚焦输入框
5. **播放**:点击后应播放故事 TTS 音频
确认控制台无报错,所有功能正常。
- [ ] **Step 4: 提交代码**
```bash
git add mini-program/src/pages/main/ScriptView.vue
git commit -m "feat: 在 result-chat-list 中添加功能按钮组
为每条 assistant 消息添加完整功能按钮:
- 复制:复制消息内容到剪贴板
- 换个方向:进入换方向修订确认
- 不像我:进入不像我修订确认
- 继续生成:收起故事并聚焦输入框
- 播放:播放故事 TTS 音频"
```
---
### Task 4: 添加消息按钮组样式
**Files:**
- Modify: `mini-program/src/pages/main/ScriptView.vue` (style 部分)
- [ ] **Step 1: 添加 .message-actions 样式**
`<style scoped>` 部分(约第 1500 行之后),找到 `.message-toggle` 样式附近,添加按钮组样式:
```css
.message-actions {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16rpx;
margin-top: 24rpx;
}
.message-actions .action-btn {
padding: 16rpx 24rpx;
background: rgba(255, 255, 255, 0.08);
border: 2rpx solid rgba(255, 255, 255, 0.15);
border-radius: 16rpx;
color: #e0e0e0;
font-size: 24rpx;
text-align: center;
transition: all 0.2s;
}
.message-actions .action-btn:active {
background: rgba(255, 255, 255, 0.12);
transform: scale(0.98);
}
.message-actions .action-btn.primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-color: transparent;
color: #ffffff;
font-weight: 500;
}
.message-actions .action-btn.primary:active {
opacity: 0.85;
}
```
- [ ] **Step 2: 验证样式效果**
在微信开发者工具中编译运行:
1. 进入「实现心愿」页面,生成故事
2. 点击「继续生成」创建 assistant 消息
3. 验证按钮样式:
- 按钮组为 2 列网格布局
- 普通按钮为半透明白色背景,圆角边框
- 播放按钮为主色调渐变(紫色)
- 点击时有缩放反馈效果
4. 验证按钮在不同屏幕尺寸下的响应式表现
- [ ] **Step 3: 提交代码**
```bash
git add mini-program/src/pages/main/ScriptView.vue
git commit -m "style: 添加消息按钮组样式
- .message-actions: 2 列网格布局,间距 16rpx
- .action-btn: 半透明白色背景,圆角边框,点击反馈
- .action-btn.primary: 主色调渐变(紫色),白色文字"
```
---
### Task 5: 最终验证和边界情况测试
**Files:**
- 无需修改文件,仅做验证
- [ ] **Step 1: 测试 story-card 展开/收起**
在微信开发者工具中编译运行:
1. 进入「实现心愿」页面
2. 输入心愿并生成故事
3. 点击 story-card 的「展开全文」按钮,验证故事正文展开
4. 点击「收起全文」按钮,验证故事正文收起
5. 点击「继续生成」创建 script 类型消息
6. 再次点击 story-card 的展开/收起按钮,验证功能正常(之前会失效)
**预期结果:** 所有展开/收起操作正常工作
- [ ] **Step 2: 测试 assistant 消息功能按钮**
继续在上一步的基础上:
1. 验证每条 assistant 消息下方显示 5 个功能按钮
2. 点击「复制」按钮,验证复制成功提示
3. 点击「换个方向」按钮,验证进入修订确认流程
4. 点击「不像我」按钮,验证进入修订确认流程
5. 点击「继续生成」按钮,验证故事收起且输入框获得焦点
6. 点击「播放」按钮,验证 TTS 音频播放
**预期结果:** 所有按钮功能正常
- [ ] **Step 3: 测试边界情况**
测试以下边界场景:
**场景 1:空内容的 assistant 消息**
- 手动构造一条空内容的 assistant 消息(或等待 AI 返回空内容)
- 点击「复制」按钮
- **预期:** 显示「暂无可复制内容」提示
**场景 2pending 状态的 assistant 消息**
- 生成故事后,快速点击「继续生成」
- 观察正在加载的 assistant 消息(pending 状态)
- **预期:** pending 消息不显示功能按钮组
**场景 3user 消息**
- 查看用户发送的消息
- **预期:** user 消息不显示功能按钮组
**场景 4:无 currentResult 时的播放**
- 如果可能,测试在未生成故事时点击播放按钮
- **预期:** 按钮仍可点击,TTS 播放器内部处理空 id
- [ ] **Step 4: 验证埋点**
打开微信开发者工具的控制台,查看埋点日志:
1. 点击 assistant 消息的展开/收起按钮,验证 `script_message_collapse_toggle` 埋点
2. 点击「复制」按钮,验证 `script_message_copy_click` 埋点
3. 点击「播放」按钮,验证 `script_message_tts_click` 埋点
**预期结果:** 所有埋点正确触发,包含正确的参数
- [ ] **Step 5: 检查控制台错误**
在整个测试过程中,持续关注微信开发者工具的控制台:
- 确认无 Vue 警告
- 确认无 JavaScript 错误
- 确认无网络请求错误
**预期结果:** 控制台干净,无任何错误
- [ ] **Step 6: 最终提交(如有修改)**
如果在前面的测试中发现了需要修复的问题,修复后提交:
```bash
git add mini-program/src/pages/main/ScriptView.vue
git commit -m "fix: 修复最终验证中发现的问题
[描述修复的具体问题]"
```
如果测试全部通过,无需额外提交。
- [ ] **Step 7: 创建 Pull Request(可选)**
如果项目使用 PR 流程,创建 PR 合并这些更改:
```bash
git push origin HEAD
```
然后在代码托管平台创建 PR,标题:
```
feat: 统一 AI 消息卡片功能按钮并修复 story-card 展开失效
```
PR 描述包含:
- 修复 story-card 展开失效 bug
- 为每条 assistant 消息添加完整功能按钮组
- 添加相应的样式和埋点
- 所有功能已通过测试