87 lines
3.8 KiB
Vue
87 lines
3.8 KiB
Vue
<script setup lang="ts">
|
||
import { computed, provide } from 'vue'
|
||
import { useRoute, useRouter } from 'vue-router'
|
||
import { NScrollbar, NAlert, NButton, NPageHeader, NSpin, NTab, NTabs, NEllipsis } from 'naive-ui'
|
||
import { RefreshCw } from '@lucide/vue'
|
||
import { StatusBadge } from '../../components/ui'
|
||
import { projectContextKey, useProjectData } from './context'
|
||
import { getOperation } from '../workflows/operations'
|
||
|
||
/** 项目共享查询保持不变,标题与导航固定,子工作区负责内容滚动。 */
|
||
const route = useRoute()
|
||
const router = useRouter()
|
||
const id = computed(() => String(route.params.projectId))
|
||
const context = useProjectData(id)
|
||
provide(projectContextKey, context)
|
||
const operation = computed(() => getOperation(id.value))
|
||
const tabs = [
|
||
['create-drama', '剧本创作'],
|
||
['breakdown', '剧本拆解'],
|
||
['visual-style', '视觉风格'],
|
||
['subject-identity', '主体身份'],
|
||
['subject-images', '形态图片'],
|
||
['storyboard', '分镜设计'],
|
||
['production', '镜头生产']
|
||
] as const
|
||
/** 路由控制当前工作流,不额外缓存一份可能失步的标签状态。 */
|
||
function switchWorkflow(path: string) {
|
||
void router.push('/projects/' + id.value + '/' + path)
|
||
}
|
||
</script>
|
||
<template>
|
||
<section class="project-frame">
|
||
<header class="project-header">
|
||
<NPageHeader @back="router.push('/projects')">
|
||
<template #title
|
||
><NEllipsis class="project-title">{{
|
||
context.project.value?.title || context.project.value?.topic || '读取项目'
|
||
}}</NEllipsis></template
|
||
>
|
||
<template #extra
|
||
><div class="flex items-center gap-3">
|
||
<StatusBadge v-if="context.project.value" :status="context.project.value.status" /><NButton
|
||
size="small"
|
||
:loading="context.loading.value"
|
||
@click="context.refresh"
|
||
><template #icon><RefreshCw :size="14" /></template>刷新</NButton
|
||
>
|
||
</div></template
|
||
>
|
||
</NPageHeader>
|
||
<NTabs
|
||
:value="String(route.path.split('/').at(-1))"
|
||
type="line"
|
||
size="small"
|
||
class="project-tabs"
|
||
aria-label="项目工作流"
|
||
@update:value="switchWorkflow"
|
||
>
|
||
<NTab v-for="[path, label] in tabs" :key="path" :name="path">{{ label }}</NTab>
|
||
</NTabs>
|
||
</header>
|
||
<NScrollbar
|
||
v-if="context.error.value || operation.pending || operation.error || operation.notice"
|
||
class="project-notices"
|
||
content-class="project-notices-content"
|
||
>
|
||
<NAlert v-if="context.error.value" type="error" :show-icon="false"
|
||
>{{ context.error.value
|
||
}}<span v-if="context.project.value"> 当前保留上次成功读取的数据。</span></NAlert
|
||
>
|
||
<NAlert v-if="operation.pending" :show-icon="false" role="status"
|
||
>{{ operation.label }}。可切换页面查看结果,请勿重复提交;关闭页面不会取消后端任务。</NAlert
|
||
>
|
||
<NAlert v-if="operation.error" type="error" :show-icon="false">{{ operation.error }}</NAlert>
|
||
<NAlert v-if="operation.notice" :show-icon="false" role="status">{{ operation.notice }}</NAlert>
|
||
</NScrollbar>
|
||
<div class="project-view">
|
||
<RouterView v-if="context.project.value" :key="id" />
|
||
<NSpin
|
||
v-else-if="context.loading.value"
|
||
class="workspace-loading"
|
||
description="正在读取项目和工作流记录…"
|
||
/>
|
||
</div>
|
||
</section>
|
||
</template>
|