Files
happy-life-star/docs/superpowers/plans/2026-06-27-ai-message-card-buttons.md
T

468 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 消息添加完整功能按钮组
- 添加相应的样式和埋点
- 所有功能已通过测试