feat: ScriptDetailView 增强展示用户心愿和大纲元数据
This commit is contained in:
@@ -14,6 +14,10 @@
|
||||
<text class="eyebrow">PARALLEL LIFE</text>
|
||||
<text class="script-title">{{ script?.title || '未命名剧本' }}</text>
|
||||
<text class="script-summary">{{ script?.summary || '命运正在整理章节。' }}</text>
|
||||
<view v-if="userWish" class="wish-block">
|
||||
<text class="wish-label">💭 用户心愿</text>
|
||||
<text class="wish-text">{{ userWish }}</text>
|
||||
</view>
|
||||
<view class="stats">
|
||||
<view class="stat">
|
||||
<text class="stat-value">{{ script?.style || '爽文' }}</text>
|
||||
@@ -39,8 +43,17 @@
|
||||
<Markdown :content="fullContent" />
|
||||
</view>
|
||||
|
||||
<view v-else class="outline-list">
|
||||
<view v-for="(item, index) in outline" :key="index" class="outline-card kos-card">
|
||||
<view v-else-if="activeTab === 'outline'" class="outline-list">
|
||||
<!-- 优先展示从后端保存的真实大纲(来自 conversation.message.metadata) -->
|
||||
<view v-if="outlineFromMeta && outlineFromMeta.length" v-for="(item, index) in outlineFromMeta" :key="'meta-' + index" class="outline-card kos-card">
|
||||
<view class="outline-node">{{ index + 1 }}</view>
|
||||
<view class="outline-body">
|
||||
<text class="outline-title">{{ item.title }}</text>
|
||||
<text class="outline-text">{{ item.text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- fallback 到本地解析 -->
|
||||
<view v-else v-for="(item, index) in outline" :key="'local-' + index" class="outline-card kos-card">
|
||||
<view class="outline-node">{{ index + 1 }}</view>
|
||||
<view class="outline-body">
|
||||
<text class="outline-title">{{ item.title }}</text>
|
||||
@@ -83,6 +96,34 @@ const lengthText = computed(() => {
|
||||
return map[script.value?.length] || script.value?.length || '中篇'
|
||||
})
|
||||
|
||||
/**
|
||||
* 用户心愿原文(从 EpicScript.theme 字段读取)
|
||||
*/
|
||||
const userWish = computed(() => script.value?.theme || '')
|
||||
|
||||
/**
|
||||
* 大纲(从 plotJson.stages.outline 读取后端真实保存的 outline JSON)
|
||||
* 后端 ShortNovelServiceImpl 在 novel_done 时会把 outline_created 事件累积到 metadata.stages.outline
|
||||
*/
|
||||
const outlineFromMeta = computed(() => {
|
||||
const stages = script.value?.plotJson?.stages
|
||||
if (!stages || !stages.outline) return []
|
||||
const outline = stages.outline
|
||||
const items = []
|
||||
if (outline.title) items.push({ title: '标题', text: outline.title })
|
||||
if (outline.logline) items.push({ title: '简介', text: outline.logline })
|
||||
if (Array.isArray(outline.beats)) {
|
||||
outline.beats.forEach((beat, i) => {
|
||||
items.push({
|
||||
title: beat.title || `章节 ${i + 1}`,
|
||||
text: beat.text || beat.description || JSON.stringify(beat)
|
||||
})
|
||||
})
|
||||
}
|
||||
if (outline.ending) items.push({ title: '结局', text: outline.ending })
|
||||
return items
|
||||
})
|
||||
|
||||
const detailTtsActionText = computed(() => {
|
||||
if (!script.value?.id) return '播放'
|
||||
if (ttsPlayer.loading.value) return '生成中'
|
||||
@@ -271,6 +312,30 @@ onUnmounted(() => {
|
||||
line-height: 1.62;
|
||||
}
|
||||
|
||||
.wish-block {
|
||||
margin-top: 24rpx;
|
||||
padding: 20rpx 22rpx;
|
||||
border-radius: 22rpx;
|
||||
background: linear-gradient(135deg, rgba(168, 85, 247, 0.16), rgba(232, 121, 249, 0.08));
|
||||
border: 1rpx solid rgba(168, 85, 247, 0.24);
|
||||
}
|
||||
|
||||
.wish-label {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #c186ff;
|
||||
font-weight: 700;
|
||||
letter-spacing: 2rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.wish-text {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.62;
|
||||
color: rgba(255, 255, 255, 0.92);
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
|
||||
Reference in New Issue
Block a user