feat: ScriptView 复用 MessageCard 组件

- story-card 使用 MessageCard
- result-chat-list 中的 assistant 消息按内容长度自动切换短消息/完整卡片模式

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 09:16:37 +08:00
parent cbf5157dcf
commit c2ed051de0
+34 -73
View File
@@ -169,87 +169,47 @@
</view>
</view>
<view class="story-card" :class="{ collapsed: storyCollapsed, dialogMode: resultHasScriptReplies }">
<view class="story-head">
<view class="story-title-wrap">
<text class="story-title">{{ currentResult?.title || '我的人生剧本' }}</text>
<view class="tag-row">
<text v-for="tag in resultTags" :key="tag" class="tag">{{ tag }}</text>
</view>
</view>
<view class="story-head-actions">
<button class="collapse-icon" @click="toggleStoryCollapse">
<text class="collapse-icon-text">{{ storyCollapsed ? '展开' : '收起' }}</text>
<view class="collapse-chevron" :class="{ down: storyCollapsed }">
<view></view>
<view></view>
</view>
</button>
<button class="copy-card-btn" @click="copyResultContent">复制</button>
</view>
</view>
<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>
<view class="result-actions">
<button class="action-btn" @click="changeDirection">换个方向</button>
<button class="action-btn" @click="notLikeMe">不像我</button>
<button class="action-btn" @click="continueInChat">继续生成</button>
<button class="action-btn primary" @click="trackTtsClick">
<text class="action-icon">{{ ttsActionIcon }}</text>
<text>{{ ttsActionText }}</text>
</button>
</view>
</view>
<MessageCard
:content="displayedResultContent"
:title="currentResult?.title"
:tags="resultTags"
:collapsed="storyCollapsed"
:content-length="displayedResultContent.length"
:is-short-message="false"
:tts-icon="ttsActionIcon"
:tts-text="ttsActionText"
@toggle-collapse="toggleStoryCollapse"
@copy="copyResultContent"
@change-direction="changeDirection"
@not-like-me="notLikeMe"
@continue="continueInChat"
@play-tts="trackTtsClick"
/>
<view v-if="resultMessages.length" class="result-chat-list">
<view
v-for="message in resultMessages"
:key="message.id"
class="chat-bubble"
:class="{ user: message.role === 'user', system: message.role === 'assistant', pending: message.pending }"
>
<text selectable user-select>{{ getMessageDisplayContent(message) }}</text>
<view v-if="message.pending" class="thinking-dots">
<view></view>
<view></view>
<view></view>
</view>
<view
<MessageCard
v-if="isAssistantMessage(message)"
class="message-toggle"
@click.stop="toggleMessageCollapse(message)"
>
<text>{{ isMessageCollapsed(message) ? '展开' : '收起' }}</text>
<text class="message-toggle-icon" :class="{ open: !isMessageCollapsed(message) }"></text>
:content="message.content"
:collapsed="isMessageCollapsed(message)"
:content-length="message.content.length"
:is-short-message="message.content.length < 100"
:tts-icon="ttsPlayer.playing.value ? '' : ''"
:tts-text="ttsPlayer.playing.value ? '暂停' : '播放'"
@toggle-collapse="toggleMessageCollapse(message)"
@copy="copyMessageContent(message)"
@change-direction="changeDirection"
@not-like-me="notLikeMe"
@continue="continueInChat"
@play-tts="playMessageTts(message)"
/>
<view v-else class="chat-bubble user">
<text>{{ message.content }}</text>
<text class="bubble-time">{{ message.time }}</text>
</view>
<view v-if="isAssistantMessage(message)" class="message-actions">
<button class="action-btn" @click="copyMessageContent(message)">复制</button>
<button class="action-btn" @click="changeDirection">换个方向</button>
<button class="action-btn" @click="notLikeMe">不像我</button>
<button class="action-btn" @click="continueInChat">继续生成</button>
<button class="action-btn primary" @click="playMessageTts(message)">
<text class="action-icon">{{ ttsPlayer.playing.value ? 'Ⅱ' : '▶' }}</text>
<text>{{ ttsPlayer.playing.value ? '暂停' : '播放' }}</text>
</button>
</view>
<text class="bubble-time">{{ message.time }}</text>
</view>
</view>
@@ -312,6 +272,7 @@ import { useTtsPlayer } from '../../composables/useTtsPlayer.js'
import { useTypewriterStream } from '../../composables/useTypewriterStream.js'
import { transcribeAudio } from '../../services/asr.js'
import { streamAiScene } from '../../services/aiRuntime.js'
import MessageCard from '../../components/MessageCard.vue'
const store = useAppStore()
const pagePath = '/pages/main/ScriptView'