--- 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` 的 `