From 44fe10950daeb0bd74ed47d62a0eebeb4c9816d5 Mon Sep 17 00:00:00 2001 From: Peanut Date: Tue, 28 Jul 2026 21:53:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(mini-program):=20ScriptDetailView=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=B0=8F=E8=AF=B4=E6=B6=88=E6=81=AF=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=8C=89=E9=92=AE=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 collapsedMessageIds ref + 5 个函数(isMessageCollapsed、getMessageDisplayContent、toggleMessageCollapse、copyMessageContent、playMessageTts) - 为 kind === 'novel' 的消息添加折叠/展开、复制、播放按钮 - 添加 .collapse-toggle-row、.message-actions、.action-btn 样式 - H5 验收通过:复制按钮触发 Toast、播放按钮切换 TTS 状态(▶播放 ↔ Ⅱ暂停)、折叠按钮切换文案 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/pages/main/ScriptDetailView.vue | 194 +++++++++++++++++- 1 file changed, 193 insertions(+), 1 deletion(-) diff --git a/mini-program/src/pages/main/ScriptDetailView.vue b/mini-program/src/pages/main/ScriptDetailView.vue index 0a230ad..2fe03b3 100644 --- a/mini-program/src/pages/main/ScriptDetailView.vue +++ b/mini-program/src/pages/main/ScriptDetailView.vue @@ -72,7 +72,27 @@ - + + + + + {{ isMessageCollapsed(msg) ? '展开全文' : '收起全文' }} + + + + + + + + + + + @@ -106,10 +126,14 @@ const store = useAppStore() const scriptId = ref('') const script = ref(null) const resultMessages = ref([]) +const collapsedMessageIds = ref({}) const pagePath = '/pages/main/ScriptDetailView' const ttsPlayer = useTtsPlayer({ pagePath }) const { capsuleTopReservePx, topbarStyle } = useMenuButtonSafeArea({ extraTopPx: 10 }) +// 小说正文折叠时的预览长度(字符) +const ASSISTANT_MESSAGE_PREVIEW_LENGTH = 120 + const lengthText = computed(() => { const map = { short: '短篇', medium: '中篇', long: '长篇' } return map[script.value?.length] || script.value?.length || '中篇' @@ -125,6 +149,70 @@ const detailTtsIcon = computed(() => { return ttsPlayer.playing.value ? 'Ⅱ' : '▶' }) +/** + * 判断消息是否处于折叠状态 + */ +const isMessageCollapsed = (message) => { + return Boolean(collapsedMessageIds.value[message.id]) +} + +/** + * 获取消息显示内容(折叠时截断到预览长度) + */ +const getMessageDisplayContent = (message) => { + const content = String(message?.content || '') + if (!isMessageCollapsed(message)) return content + if (content.length <= ASSISTANT_MESSAGE_PREVIEW_LENGTH) return content + return `${content.slice(0, ASSISTANT_MESSAGE_PREVIEW_LENGTH)}...` +} + +/** + * 切换消息折叠/展开状态 + */ +const toggleMessageCollapse = (message) => { + collapsedMessageIds.value = { + ...collapsedMessageIds.value, + [message.id]: !isMessageCollapsed(message) + } + analytics.track('script_message_collapse_toggle', { + message_id: message?.id || '', + collapsed: collapsedMessageIds.value[message.id] + }, { eventType: 'script', pagePath }) +} + +/** + * 复制消息内容到剪贴板 + */ +const copyMessageContent = (message) => { + const content = String(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 }) +} + +/** + * 播放消息 TTS 音频(播放整个剧本的音频) + */ +const playMessageTts = (message) => { + const scriptIdValue = script.value?.id || '' + ttsPlayer.playSource(scriptIdValue) + analytics.track('script_message_tts_click', { + message_id: message?.id || '', + script_id: scriptIdValue + }, { eventType: 'script', pagePath }) +} + /** * 从后端 message 列表重建统一对话消息流 * 复刻 ScriptView 生成时的 chat-bubble 展示结构 @@ -522,6 +610,110 @@ onUnmounted(() => { .novel-bubble { padding: 32rpx; } + +/* 折叠/展开按钮行 */ +.collapse-toggle-row { + display: flex; + align-items: center; + justify-content: center; + gap: 12rpx; + margin-top: 20rpx; + padding: 16rpx 0; + border-radius: 999rpx; + background: rgba(88, 28, 135, 0.12); + border: 1rpx solid rgba(192, 132, 252, 0.28); + color: rgba(246, 230, 255, 0.96); + font-size: 26rpx; + font-weight: 700; +} + +.collapse-toggle-row:active { + transform: scale(0.98); + opacity: 0.92; +} + +.collapse-toggle-text { + line-height: 1; +} + +/* 折叠箭头图标 */ +.collapse-chevron { + position: relative; + width: 20rpx; + height: 16rpx; + flex-shrink: 0; + transition: transform 0.18s ease; +} + +.collapse-chevron.down { + transform: rotate(180deg); +} + +.collapse-chevron view { + position: absolute; + top: 7rpx; + width: 12rpx; + height: 4rpx; + border-radius: 999rpx; + background: linear-gradient(90deg, #fff3b0, #ffd86b); + box-shadow: 0 0 12rpx rgba(255, 216, 107, 0.5); +} + +.collapse-chevron view:first-child { + left: 0; + transform: rotate(-38deg); + transform-origin: right center; +} + +.collapse-chevron view:last-child { + right: 0; + transform: rotate(38deg); + transform-origin: left center; +} + +/* 操作按钮组 */ +.message-actions { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14rpx; + margin-top: 20rpx; +} + +.action-btn { + height: 72rpx; + min-height: 72rpx; + padding: 0 8rpx; + border-radius: 28rpx; + display: flex; + align-items: center; + justify-content: center; + color: #e8ccff; + font-size: 26rpx; + font-weight: 700; + line-height: 1.15; + text-align: center; + white-space: normal; + box-sizing: border-box; + background: rgba(88, 28, 135, 0.18); + border: 1rpx solid rgba(192, 132, 252, 0.35); +} + +.action-btn.primary { + color: #fff; + background: linear-gradient(145deg, #8c44f2, #5f1db8); +} + +.action-icon { + margin-right: 8rpx; + font-size: 24rpx; + font-weight: 900; + line-height: 1; +} + +.action-btn::after { + border: 0; +} + .empty-flow { padding: 80rpx 0; text-align: center;