ui: 默认展开内容折叠区

This commit is contained in:
GouJ
2026-09-22 18:42:56 +08:00
parent b9db84c261
commit 8e8fab307f
19 changed files with 90 additions and 126 deletions
@@ -6,10 +6,10 @@ import { downloadText, formatDate } from '../../../lib/format'
import { useAdvancedProduction } from '../useAdvancedProduction'
import ProductionPlanPanel from './ProductionPlanPanel.vue'
/** 高级入口明确真实流程边界,默认折叠且不在挂载时触发预检或生成。 */
/** 高级入口默认展示真实流程边界,但不会在挂载时触发预检或生成。 */
const { id, operation, session, checking, error, check, blocked, preflight, start } = useAdvancedProduction()
const receipt = computed(() => session.value.pipelineReceipt)
const expanded = ref<string[]>([])
const expanded = ref<string[]>(['advanced'])
watch(
receipt,
value => {
@@ -60,7 +60,7 @@ onScopeDispose(() => controller?.abort())
</script>
<template>
<NCollapse class="production-tool-section">
<NCollapse class="production-tool-section" :default-expanded-names="['episode-assembly']">
<NCollapseItem name="episode-assembly" title="单集成片拼接">
<NSpin :show="loading">
<div class="flex flex-wrap items-center justify-between gap-3">
@@ -83,7 +83,7 @@ const problems = computed(() => [
{{ plan.manualBlocked }}
项需人工处理同一镜头可能重复计数可先生成就绪的主体参考图成功结果会保留遇到阻塞时后续阶段可能暂停
</NAlert>
<NCollapse v-if="problems.length" class="mt-3">
<NCollapse v-if="problems.length" class="mt-3" :default-expanded-names="['issues']">
<NCollapseItem name="issues" title="查看前置条件与阻塞原因">
<ul class="space-y-3 text-xs">
<li v-for="item in problems" :key="item.key">
@@ -125,7 +125,7 @@ const rules = computed(() => ({
limit: integerRule('本批镜头上限'),
...sizeRules(() => formModel.value)
}))
const optionsExpanded = ref<string[]>([])
const optionsExpanded = ref<string[]>(['options'])
</script>
<template>
@@ -277,7 +277,7 @@ const optionsExpanded = ref<string[]>([])
session.error
}}</NAlert>
<QualityResult v-if="session.receipt" :receipt="session.receipt" @locate="emit('locate', $event)" />
<NCollapse v-else-if="saved" class="mt-4"
<NCollapse v-else-if="saved" class="mt-4" :default-expanded-names="['saved']"
><NCollapseItem name="saved" :title="`本会话最近校验 · ${saved.passed ? '通过' : '未通过'}`"
><p>{{ saved.summary }}</p>
<p v-for="(issue, index) in saved.issues" :key="index" class="mt-2 text-danger">
@@ -4,7 +4,7 @@ import { NAlert, NButton, NCollapse, NCollapseItem } from 'naive-ui'
import { downloadText } from '../../../lib/format'
import type { QualityReceipt } from '../quality.types'
/** 摘要失败直接显示,完整逐轮信息按需展开,不用完成请求冒充质量通过。 */
/** 摘要失败完整逐轮信息默认直接显示,不用完成请求冒充质量通过。 */
const props = defineProps<{ receipt: QualityReceipt }>()
const emit = defineEmits<{ locate: [shotId: string] }>()
const passed = computed(() =>
@@ -113,7 +113,7 @@ function exportResult() {
>
{{ issue.frameLabel ? `${issue.frameLabel} · ` : '' }}{{ issue.description }}
</NAlert>
<NCollapse class="mt-4">
<NCollapse class="mt-4" :default-expanded-names="['details']">
<NCollapseItem name="details" title="主体检查与执行详情">
<template v-if="receipt.kind === 'keyframe' || receipt.kind === 'video'">
<p class="text-xs">
@@ -4,7 +4,7 @@ import { NAlert, NButton, NCollapse, NCollapseItem, NTag } from 'naive-ui'
import { computed, ref, watch } from 'vue'
import { ExternalLink, ImagePlus, RefreshCw } from '@lucide/vue'
import { AssetImage, StatusBadge } from '../../../components/ui'
import { useQuery } from '../../../composables/useQuery'
import { usePolling } from '../../../composables/usePolling'
import { mediaAssetUrl } from '../../../lib/assets'
import { errorMessage } from '../../../lib/http'
import { formatDate } from '../../../lib/format'
@@ -41,16 +41,20 @@ const props = defineProps<{
}>()
const emit = defineEmits<{ changed: [] }>()
const key = computed(() => props.shot.shotId)
/** 单镜头资产仅在进入、切换镜头或显式刷新时读取。 */
const query = useQuery(key, async (shotId, signal) => {
const [keyframes, videos] = await Promise.all([
productionApi.listKeyframes(shotId, signal),
productionApi.listVideos(shotId, signal)
])
if (keyframes.some(item => item.shotId !== shotId) || videos.some(item => item.shotId !== shotId))
throw new Error('资产记录与当前镜头不匹配,请刷新后重试。')
return { keyframes, videos }
})
/** 单镜头资产已有刷新入口,不再定时轮询。 */
const query = usePolling(
key,
async (shotId, signal) => {
const [keyframes, videos] = await Promise.all([
productionApi.listKeyframes(shotId, signal),
productionApi.listVideos(shotId, signal)
])
if (keyframes.some(item => item.shotId !== shotId) || videos.some(item => item.shotId !== shotId))
throw new Error('资产记录与当前镜头不匹配,请刷新后重试。')
return { keyframes, videos }
},
false
)
const keyframes = computed(() => query.data.value?.keyframes ?? [])
const videos = computed(() => query.data.value?.videos ?? [])
const currentKeyframe = computed(() => primaryKeyframe(keyframes.value))
@@ -63,7 +67,7 @@ const qualityOpen = ref(false)
const qualityTarget = ref<QualityTarget | null>(null)
const specsOpen = ref(false)
/** 从实际候选打开质量面板,保留单镜头主操作,不默认展开全部校验参数。 */
/** 从实际候选打开质量面板,保留单镜头主操作。 */
function openQuality(kind: 'keyframe' | 'video', assetId: string) {
qualityTarget.value = {
kind,