---
author: claude
created_at: 2026-06-27
purpose: 提取 MessageCard 组件,统一所有 AI 消息卡片样式,按内容长度阈值(100 字)决定是否显示完整功能按钮
---
# MessageCard 组件统一设计
## 背景
在上一轮实现中,result-chat-list 中的 assistant 消息使用了 `.chat-bubble.system` 气泡样式,与 `story-card` 的卡片样式不一致。用户要求:
1. 所有 AI 回复消息卡片的样式、功能、布局、按钮等,都与第一次生成剧本的 `story-card` 完全一致
2. 内容 < 100 字的 assistant 消息:只显示消息内容,无功能按钮
3. 内容 ≥ 100 字的 assistant 消息:必须与 `story-card` 完全一致
## 目标
- 提取独立的 `MessageCard.vue` 组件
- story-card 和 result-chat-list 都复用该组件
- 按 100 字阈值自动切换显示模式
## 方案选择
采用 **方案 B:提取独立 MessageCard.vue 组件**
- 代码复用,维护性好
- 改动范围:新建 1 个组件 + 修改 ScriptView.vue
## 详细设计
### 1. 组件接口
**文件**:`mini-program/src/components/MessageCard.vue`
**Props:**
| Prop | 类型 | 必填 | 说明 |
|---|---|---|---|
| `content` | String | 是 | 消息/故事正文内容 |
| `title` | String | 否 | 卡片标题,默认 `'我的人生剧本'` |
| `tags` | Array | 否 | 标签列表 |
| `collapsed` | Boolean | 是 | 当前折叠状态 |
| `contentLength` | Number | 是 | 内容字数(用于阈值判断) |
| `isShortMessage` | Boolean | 是 | `contentLength < 100` 时为 true |
| `ttsIcon` | String | 否 | TTS 按钮图标(`▶` 或 `Ⅱ`) |
| `ttsText` | String | 否 | TTS 按钮文字(`播放` 或 `暂停`) |
**Events:**
| 事件 | 说明 |
|---|---|
| `toggle-collapse` | 展开/收起 |
| `copy` | 复制内容 |
| `change-direction` | 换个方向 |
| `not-like-me` | 不像我 |
| `continue` | 继续生成 |
| `play-tts` | 播放 TTS |
### 2. 组件内部结构
**短消息(`isShortMessage = true`)**:
```vue
{{ content }}
```
只显示纯文本气泡,无标题、无标签、无按钮。
**长消息(`isShortMessage = false`)**:
完整复用现有 `story-card` 的 HTML 结构:
- 标题(`.story-title`)+ 标签(`.tag-row`)
- 头部操作区:展开/收起按钮 + 复制按钮
- 正文:展开时用 scroll-view,收起时用 text
- 底部:展开全文/收起全文按钮
- 功能按钮组(2 列网格):换个方向、不像我、继续生成、播放
### 3. ScriptView.vue 中的使用
**替换现有 story-card**:
```vue
```
**替换 result-chat-list 中的 assistant 消息**:
```vue
{{ message.content }}
{{ message.time }}
```
### 4. 样式迁移
将以下 CSS 类从 `ScriptView.vue` 迁移到 `MessageCard.vue` 的 `