feat: improve voice studio alpha recovery flow

This commit is contained in:
2026-04-19 23:25:41 +08:00
parent 46d6201529
commit 4ecf0c09c0
9 changed files with 657 additions and 14 deletions

View File

@@ -8,6 +8,7 @@ import BaseCard from '../components/ui/BaseCard.vue'
import EmptyState from '../components/ui/EmptyState.vue'
import LoadingSpinner from '../components/ui/LoadingSpinner.vue'
import type { GenerationOpsSummary, GenerationProviderAnalytics } from '../types/generation'
import type { VoiceSessionSummary } from '../types/voiceSession'
import {
getAssetStatusMeta,
getGenerationStatusMeta,
@@ -40,6 +41,7 @@ const router = useRouter()
const stories = ref<StoryItem[]>([])
const providerAnalytics = ref<GenerationProviderAnalytics | null>(null)
const opsSummary = ref<GenerationOpsSummary | null>(null)
const activeVoiceSession = ref<VoiceSessionSummary | null>(null)
const loading = ref(true)
const error = ref('')
const showCreateModal = ref(false)
@@ -76,14 +78,16 @@ function buildProviderAnalyticsPath() {
async function fetchStories() {
try {
const [storyList, analytics, ops] = await Promise.all([
const [storyList, analytics, ops, activeSession] = await Promise.all([
api.get<StoryItem[]>('/api/stories'),
api.get<GenerationProviderAnalytics>(buildProviderAnalyticsPath()),
api.get<GenerationOpsSummary>('/api/generations/ops-summary'),
api.get<VoiceSessionSummary | null>('/api/voice-sessions/active').catch(() => null),
])
stories.value = storyList
providerAnalytics.value = analytics
opsSummary.value = ops
activeVoiceSession.value = activeSession
} catch (e) {
error.value = e instanceof Error ? e.message : '加载失败'
} finally {
@@ -112,6 +116,10 @@ function goToCreate() {
showCreateModal.value = true
}
function goToVoiceStudio() {
router.push('/voice-studio')
}
function getStoryLink(story: StoryItem) {
return story.mode === 'storybook' ? `/storybook/view/${story.id}` : `/story/${story.id}`
}
@@ -200,6 +208,27 @@ watch([selectedWindow, selectedCapability], () => {
</div>
<template v-else>
<BaseCard
v-if="activeVoiceSession"
class="mb-8 border border-purple-100 bg-purple-50/60"
padding="lg"
>
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-xl font-bold text-gray-800">语音共创正在进行中</h2>
<p class="mt-2 text-sm leading-6 text-gray-600">
最近的语音共创会话仍可继续
{{ activeVoiceSession.working_title || '未命名语音会话' }}
当前状态 {{ activeVoiceSession.status }}已完成 {{ activeVoiceSession.total_turns }}
</p>
</div>
<BaseButton @click="goToVoiceStudio">
<SparklesIcon class="h-5 w-5 mr-2" />
继续语音共创
</BaseButton>
</div>
</BaseCard>
<BaseCard class="mb-8" padding="lg">
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4">
<div class="text-center px-4 py-2">