docs:新增 AI 消息卡片功能按钮实现计划
This commit is contained in:
@@ -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 返回空内容)
|
||||
- 点击「复制」按钮
|
||||
- **预期:** 显示「暂无可复制内容」提示
|
||||
|
||||
**场景 2:pending 状态的 assistant 消息**
|
||||
- 生成故事后,快速点击「继续生成」
|
||||
- 观察正在加载的 assistant 消息(pending 状态)
|
||||
- **预期:** pending 消息不显示功能按钮组
|
||||
|
||||
**场景 3:user 消息**
|
||||
- 查看用户发送的消息
|
||||
- **预期:** 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 消息添加完整功能按钮组
|
||||
- 添加相应的样式和埋点
|
||||
- 所有功能已通过测试
|
||||
Reference in New Issue
Block a user