Files
happy-life-star/docs/superpowers/specs/2026-06-29-scriptview-dialog-flow-only-design.md

222 lines
8.9 KiB
Markdown
Raw Permalink 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: Peanut
created_at: 2026-06-29
purpose: ScriptView 简化为纯对话流模式:删除 read/chat 二段切换 + 按旧版布局统一 AI 消息按钮组
---
# ScriptView 简化为纯对话流模式
## 背景
`bf6f279 feat: ScriptView 改造为对话中心查看/修改模式` 引入了 read/chat 二段切换,但偏离了原始设计。用户的原始设计意图:
- **从剧本库点卡片进入**:直接以对话形式查看完整的从创建剧本开始的对话(用户心愿 → AI 剧本 → 改写对话 → 续写对话 → ...)
- **AI 消息卡片**:按旧版布局展示按钮组
- **不要二段切换**:不要先 read 再点按钮进 chat
## 旧版布局参考(来自 commit `cbf5157` 和 `0db434c`
```
MessageCard 顶部(story-head-actions):
┌──────────────────────────────────┐
│ [剧本标题] [收起/展开] [复制] │
└──────────────────────────────────┘
MessageCard 底部(result-actions):
┌──────────────────────────────────┐
│ [换个方向] [不像我] [继续生成] [▶ 播放] │
└──────────────────────────────────┘
```
## 设计
### 1. 入口流程简化
| 入口 | 改动 |
|---|---|
| 剧本库点卡片 | `openScriptChat` → 直接设 `viewState='result'``viewMode='chat'` |
| 首页心愿输入生成新剧本 | 保持现状(home → generating → result |
| read 模式 | **整个删除** |
### 2. 删除 read 模式相关代码
**删除的位置**
| 文件 | 位置 | 内容 |
|---|---|---|
| `mini-program/src/pages/main/ScriptView.vue` | template `view v-if="viewMode === 'read'"` | 整个版本切换器 + 章节展示 + read-action-bar |
| `mini-program/src/pages/main/ScriptView.vue` | `selectedVersionMessageId` ref | 只被 read 模式用 |
| `mini-program/src/pages/main/ScriptView.vue` | `onSelectVersion` | 版本切换(read 模式用) |
| `mini-program/src/pages/main/ScriptView.vue` | `setAsCurrentVersion` | 设为当前版本(read 模式用) |
| `mini-program/src/pages/main/ScriptView.vue` | `enterChatMode` | read → chat 切换(不再需要) |
| `mini-program/src/pages/main/ScriptView.vue` | `rewriteCurrentVersion` | read 模式改写入口 |
| `mini-program/src/pages/main/ScriptView.vue` | `continueCurrentVersion` | read 模式续写入口 |
`currentVersionMessageId` 保留:chat 模式下 AI 消息的"删除版本"按钮需要它来判断 `canDelete`
### 3. 按旧版布局统一 AI 消息按钮组
**MessageCard 改造**
```vue
<template>
<!-- 短消息气泡保持现状 -->
<view v-if="isShortMessage && messageType !== 'script'" class="chat-bubble system">
<text>{{ content }}</text>
</view>
<!-- 长文本卡片story-card -->
<view v-else class="story-card" :class="{ collapsed }">
<!-- 顶部 story-head-actions收起/展开 + 复制 + 版本号 -->
<view class="story-head">
<view class="story-title-wrap">
<text v-if="versionLabel" class="version-label">{{ versionLabel }}</text>
<text class="story-title">{{ title || '我的人生剧本' }}</text>
<view v-if="tags?.length" class="tag-row">
<text v-for="tag in tags" :key="tag" class="tag">{{ tag }}</text>
</view>
</view>
<view class="story-head-actions">
<button class="collapse-icon" @click="$emit('toggle-collapse')">
<text class="collapse-icon-text">{{ collapsed ? '展开' : '收起' }}</text>
<view class="collapse-chevron" :class="{ down: collapsed }">
<view></view><view></view>
</view>
</button>
<button class="copy-card-btn" @click="$emit('copy')">复制</button>
</view>
</view>
<!-- 正文 -->
<scroll-view v-if="collapsed" class="story-body-scroll" scroll-y>
<text class="story-body" :selectable="true" :user-select="true">{{ content }}</text>
</scroll-view>
<text v-else class="story-body" :selectable="true" :user-select="true">{{ content }}</text>
<!-- 底部收起/展开行 -->
<view class="collapse-row" @click="$emit('toggle-collapse')">
<text class="collapse-row-text">{{ collapsed ? '展开全文' : '收起全文' }}</text>
<view class="collapse-chevron" :class="{ down: collapsed }">
<view></view><view></view>
</view>
</view>
<!-- 底部 result-actions按旧版布局 + 加上 script 专属按钮 -->
<view class="result-actions">
<!-- 旧版基础按钮 -->
<button class="action-btn" @click="$emit('change-direction')">换个方向</button>
<button class="action-btn" @click="$emit('not-like-me')">不像我</button>
<button v-if="canContinue" class="action-btn" @click="$emit('continue-script')">续写</button>
<!-- script 专属功能按钮 -->
<button v-if="canRewrite" class="action-btn" @click="$emit('rewrite')">改写</button>
<button v-if="hasChildren" class="action-btn" @click="$emit('view-versions')">查看历史版本</button>
<button v-if="canDelete" class="action-btn danger" @click="$emit('delete-version')">删除版本</button>
<!-- TTS 播放 -->
<button class="action-btn primary" @click="$emit('play-tts')">
<text class="action-icon">{{ ttsIcon || '▶' }}</text>
<text>{{ ttsText || '播放' }}</text>
</button>
</view>
</view>
</template>
```
**关键变化**
- `messageType === 'script'` 分支去掉(长文本统一渲染)
- `result-actions` 在 script 类型下按旧版布局 + 加 script 专属按钮
- 短消息气泡(chat/system)保持不变
### 4. ScriptView template 简化
**简化前的 read 模式 section**
```vue
<view v-if="viewMode === 'read'">
<view class="version-bar">...</view>
<view class="script-read-content">...</view>
<view class="read-action-bar">...</view>
</view>
```
**删除**
**简化后的 chat 模式 section**
```vue
<view class="result-chat-view">
<view class="conversation compact">
<!-- 用户心愿气泡 -->
<view class="chat-bubble user">
<text>{{ wishText }}</text>
<text class="bubble-time">{{ currentMessageTime }}</text>
</view>
<!-- 系统提示 -->
<view class="chat-bubble system done">
<text>心愿已实现故事已为你展开</text>
<text class="bubble-time">{{ currentResultTime }}</text>
</view>
</view>
<!-- 对话消息列表 -->
<view v-if="displayMessages.length" class="result-chat-list">
<view v-for="message in displayMessages" :key="message.id">
<MessageCard
v-if="message.sender === 'assistant' || message.type === 'script'"
message-type="script"
:version-label="formatVersionLabel(message)"
:has-children="messageHasChildren(message)"
:can-delete="message.id !== currentVersionMessageId && message.parentMessageId !== null"
:can-rewrite="true"
:can-continue="true"
:content="message.content"
:collapsed="isMessageCollapsed(message)"
:content-length="message.content.length"
:is-short-message="false"
:tts-icon="..."
:tts-text="..."
@toggle-collapse="..."
@copy="..."
@rewrite="..."
@continue-script="..."
@view-versions="..."
@delete-version="..."
@play-tts="..."
@change-direction="..."
@not-like-me="..."
/>
<view v-else class="chat-bubble user">
<text>{{ message.content }}</text>
<text class="bubble-time">{{ message.time || formatMessageTime() }}</text>
</view>
</view>
</view>
<!-- 输入栏 -->
<view class="result-chat-bar">...</view>
</view>
```
### 5. ScriptView 的 `continue` / `change-direction` / `not-like-me` emits
旧版 emit 在 script-actions 下不存在,需要保留以兼容旧版按钮。
- `continue`(旧版 "继续生成"按钮)→ 触发 `continueMessage``continueInChat`
- `change-direction`"换个方向")→ 触发 `changeDirection`
- `not-like-me`"不像我")→ 触发 `notLikeMe`
**这些函数已经存在于 ScriptView.vue 中**(来自旧版代码)。直接绑定。
## 验收标准
- [ ] 从剧本库点卡片 → 直接进入对话流(无需点"进入对话修改")
- [ ] 对话流完整显示:用户心愿 + AI 剧本 + 改写/续写对话
- [ ] AI 消息卡片顶部:收起/展开、复制、版本号标签
- [ ] AI 消息卡片底部:换个方向、不像我、续写、改写、查看历史版本、删除版本、TTS 播放
- [ ] read 模式相关代码完全删除(不再有任何切换按钮)
- [ ] Console 无报错
## 风险与回退
- **风险低**:只删除 read 模式 + 调整 MessageCard 按钮布局,不影响后端
- **回退**`git revert` 单个 commit 即可恢复