feat: 优化生产面板并增加图片网格加载
This commit is contained in:
@@ -227,8 +227,9 @@ const videoRules = { videoLimit: integerRule('本批镜头上限'), videoRepairA
|
||||
label="批量生产"
|
||||
:has-receipt="!!session.receipt || !!session.pipelineReceipt"
|
||||
>
|
||||
<div class="flex flex-wrap items-end justify-between gap-4">
|
||||
<div class="production-tools-intro">
|
||||
<div>
|
||||
<p class="eyebrow">PRODUCTION</p>
|
||||
<h2 class="text-lg font-semibold">镜头生产</h2>
|
||||
<p class="mt-2 text-sm text-muted">
|
||||
从可生成的提示词和首帧,到异步视频任务与最终成片。
|
||||
@@ -238,8 +239,13 @@ const videoRules = { videoLimit: integerRule('本批镜头上限'), videoRepairA
|
||||
<ArrowLeft :size="14" />回到分镜设计
|
||||
</RouterLink>
|
||||
</div>
|
||||
<CreativeProfileSettings :project-id="id" />
|
||||
<section class="mt-3" aria-label="项目生产配置">
|
||||
<section class="production-batch-config" aria-label="项目生产配置">
|
||||
<div class="production-section-heading">
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold">批量执行设置</h3>
|
||||
<p class="mt-1 text-xs text-muted">控制本次手动批处理的并发与覆盖方式。</p>
|
||||
</div>
|
||||
</div>
|
||||
<AppForm
|
||||
:model="batchModel"
|
||||
:rules="batchRules"
|
||||
@@ -265,273 +271,285 @@ const videoRules = { videoLimit: integerRule('本批镜头上限'), videoRepairA
|
||||
</NCheckbox>
|
||||
</div>
|
||||
</AppForm>
|
||||
<DetailDisclosure title="处理范围与覆盖规则" class="mt-3"
|
||||
</section>
|
||||
<div class="production-tool-stack">
|
||||
<CreativeProfileSettings :project-id="id" />
|
||||
<DetailDisclosure title="处理范围与覆盖规则" class="production-tool-section"
|
||||
><p class="text-xs leading-6 text-muted">
|
||||
提示词与视频就绪检查面向全项目;视频实际提交受本批镜头上限控制,并使用严格质量流水线。首帧默认补当前剧集,存在过期主首帧时优先更新全项目过期项,覆盖模式处理全项目;过期首帧成功后会自动接替旧主图,其余新增候选。图片模型、视频模型与视觉校验均可能产生费用。
|
||||
</p></DetailDisclosure
|
||||
>
|
||||
</section>
|
||||
<div class="workspace-overview-panel">
|
||||
<NCollapse v-model:expanded-names="overview"
|
||||
><NCollapseItem name="overview" title="项目生产总览与批量操作"
|
||||
><div class="overview-content">
|
||||
<NAlert
|
||||
v-if="videoRunning"
|
||||
role="status"
|
||||
type="info"
|
||||
:show-icon="false"
|
||||
class="mt-4"
|
||||
>
|
||||
当前有 {{ videoRunning }} 个视频任务等待或生成中。后端正在轮询
|
||||
Provider;同一镜头不会重复提交活动任务。
|
||||
</NAlert>
|
||||
<NAlert v-if="identityBlocked" type="info" :show-icon="false" class="mt-4">
|
||||
当前有 {{ identityBlocked }} 项角色身份前置问题。Character 必须生成
|
||||
Identity、确认演员母版并锁定后,首帧才能就绪。
|
||||
<RouterLink
|
||||
:to="`/projects/${id}/subject-identity`"
|
||||
class="text-button ml-2"
|
||||
>前往角色选角 →</RouterLink
|
||||
></NAlert
|
||||
>
|
||||
<NAlert
|
||||
v-if="staleKeyframes"
|
||||
role="status"
|
||||
type="info"
|
||||
:show-icon="false"
|
||||
class="mt-4"
|
||||
>
|
||||
当前有
|
||||
{{ staleKeyframes }}
|
||||
个主首帧已过期。它们使用的主体参考资产已经变化,视频阶段会被阻止;可在下方逐镜重新生成,或使用“补齐
|
||||
/ 更新主首帧”批量处理。
|
||||
</NAlert>
|
||||
<NAlert
|
||||
v-if="staleVideos"
|
||||
role="status"
|
||||
type="info"
|
||||
:show-icon="false"
|
||||
class="mt-4"
|
||||
>
|
||||
当前有
|
||||
{{ staleVideos }}
|
||||
个主视频已过期。它们使用的主首帧或主体参考图已经变化;非覆盖模式批量生成时会只重建这些过期主视频。
|
||||
</NAlert>
|
||||
<ProductionReceipt v-if="session.receipt" :receipt="session.receipt" />
|
||||
<div v-if="query.data.value" class="production-pipeline mt-5">
|
||||
<article
|
||||
v-for="stage in stages"
|
||||
:key="stage.key"
|
||||
class="panel production-pipeline-card"
|
||||
<div class="workspace-overview-panel">
|
||||
<NCollapse v-model:expanded-names="overview" class="production-tool-section"
|
||||
><NCollapseItem name="overview" title="项目生产总览与批量操作"
|
||||
><div class="overview-content">
|
||||
<NAlert
|
||||
v-if="videoRunning"
|
||||
role="status"
|
||||
type="info"
|
||||
:show-icon="false"
|
||||
class="mt-4"
|
||||
>
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="flex items-start gap-3">
|
||||
<span class="production-step"
|
||||
><component :is="stage.icon" :size="17"
|
||||
/></span>
|
||||
<div>
|
||||
<p class="eyebrow">STEP {{ stage.code }}</p>
|
||||
<h3 class="mt-2 text-sm font-semibold">
|
||||
{{ stage.title }}
|
||||
</h3>
|
||||
当前有 {{ videoRunning }} 个视频任务等待或生成中。后端正在轮询
|
||||
Provider;同一镜头不会重复提交活动任务。
|
||||
</NAlert>
|
||||
<NAlert v-if="identityBlocked" type="info" :show-icon="false" class="mt-4">
|
||||
当前有 {{ identityBlocked }} 项角色身份前置问题。Character 必须生成
|
||||
Identity、确认演员母版并锁定后,首帧才能就绪。
|
||||
<RouterLink
|
||||
:to="`/projects/${id}/subject-identity`"
|
||||
class="text-button ml-2"
|
||||
>前往角色选角 →</RouterLink
|
||||
></NAlert
|
||||
>
|
||||
<NAlert
|
||||
v-if="staleKeyframes"
|
||||
role="status"
|
||||
type="info"
|
||||
:show-icon="false"
|
||||
class="mt-4"
|
||||
>
|
||||
当前有
|
||||
{{ staleKeyframes }}
|
||||
个主首帧已过期。它们使用的主体参考资产已经变化,视频阶段会被阻止;可在下方逐镜重新生成,或使用“补齐
|
||||
/ 更新主首帧”批量处理。
|
||||
</NAlert>
|
||||
<NAlert
|
||||
v-if="staleVideos"
|
||||
role="status"
|
||||
type="info"
|
||||
:show-icon="false"
|
||||
class="mt-4"
|
||||
>
|
||||
当前有
|
||||
{{ staleVideos }}
|
||||
个主视频已过期。它们使用的主首帧或主体参考图已经变化;非覆盖模式批量生成时会只重建这些过期主视频。
|
||||
</NAlert>
|
||||
<ProductionReceipt v-if="session.receipt" :receipt="session.receipt" />
|
||||
<div v-if="query.data.value" class="production-pipeline mt-5">
|
||||
<article
|
||||
v-for="stage in stages"
|
||||
:key="stage.key"
|
||||
class="panel production-pipeline-card"
|
||||
>
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="flex items-start gap-3">
|
||||
<span class="production-step"
|
||||
><component :is="stage.icon" :size="17"
|
||||
/></span>
|
||||
<div>
|
||||
<p class="eyebrow">STEP {{ stage.code }}</p>
|
||||
<h3 class="mt-2 text-sm font-semibold">
|
||||
{{ stage.title }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<span class="font-mono text-xs text-muted"
|
||||
>{{ stage.done }} / {{ stage.data?.total ?? 0 }}</span
|
||||
>
|
||||
</div>
|
||||
<span class="font-mono text-xs text-muted"
|
||||
>{{ stage.done }} / {{ stage.data?.total ?? 0 }}</span
|
||||
>
|
||||
</div>
|
||||
<p class="mt-4 min-h-10 text-xs leading-5 text-muted">
|
||||
{{ stage.description }}
|
||||
</p>
|
||||
<NProgress
|
||||
:aria-label="`${stage.title}完成数量`"
|
||||
type="line"
|
||||
:show-indicator="false"
|
||||
:height="4"
|
||||
:percentage="
|
||||
Math.min(
|
||||
100,
|
||||
Math.max(
|
||||
0,
|
||||
(stage.done /
|
||||
Math.max(1, Math.max(stage.data?.total ?? 0, 1))) *
|
||||
100
|
||||
<p class="mt-4 min-h-10 text-xs leading-5 text-muted">
|
||||
{{ stage.description }}
|
||||
</p>
|
||||
<NProgress
|
||||
:aria-label="`${stage.title}完成数量`"
|
||||
type="line"
|
||||
:show-indicator="false"
|
||||
:height="4"
|
||||
:percentage="
|
||||
Math.min(
|
||||
100,
|
||||
Math.max(
|
||||
0,
|
||||
(stage.done /
|
||||
Math.max(
|
||||
1,
|
||||
Math.max(stage.data?.total ?? 0, 1)
|
||||
)) *
|
||||
100
|
||||
)
|
||||
)
|
||||
)
|
||||
"
|
||||
class="mt-4"
|
||||
></NProgress>
|
||||
<dl class="production-stats mt-4">
|
||||
"
|
||||
class="mt-4"
|
||||
></NProgress>
|
||||
<dl class="production-stats mt-4">
|
||||
<div>
|
||||
<dt>可执行</dt>
|
||||
<dd>{{ stage.data?.ready ?? 0 }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>已有结果</dt>
|
||||
<dd>{{ stage.data?.skipped ?? 0 }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>阻塞</dt>
|
||||
<dd>{{ stage.data?.blocked ?? 0 }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p
|
||||
v-if="stage.key === 'keyframes' && staleKeyframes"
|
||||
class="mt-3 text-[11px] leading-5"
|
||||
>
|
||||
已过期 {{ staleKeyframes }} · 会按当前主体参考资产重新生成
|
||||
</p>
|
||||
<p
|
||||
v-if="stage.key === 'videos' && staleVideos"
|
||||
class="mt-3 text-[11px] leading-5"
|
||||
>
|
||||
主视频已过期 {{ staleVideos }} ·
|
||||
会按当前主首帧与参考资产重新生成
|
||||
</p>
|
||||
<p
|
||||
v-if="stage.key === 'keyframes' && identityBlocked"
|
||||
class="mt-3 text-[11px] leading-5 text-danger"
|
||||
>
|
||||
身份缺失
|
||||
{{ query.data.value?.keyframes.missingIdentity ?? 0 }} ·
|
||||
母版缺失
|
||||
{{ query.data.value?.keyframes.missingIdentityAnchor ?? 0 }} ·
|
||||
未锁定
|
||||
{{ query.data.value?.keyframes.identityUnlocked ?? 0 }}
|
||||
</p>
|
||||
<ConfirmAction
|
||||
class="mt-4"
|
||||
:label="stage.action"
|
||||
:disabled="
|
||||
blocked ||
|
||||
!batchValid ||
|
||||
(stage.key === 'keyframes' && !keyframeValid) ||
|
||||
(stage.key === 'videos' && !videoQualityValid) ||
|
||||
!(stage.data?.ready ?? 0)
|
||||
"
|
||||
acknowledgement
|
||||
:description="
|
||||
stage.key === 'videos'
|
||||
? staleVideos && !force
|
||||
? `当前存在过期主视频,非覆盖模式只会为其中至多 ${videoLimit || '—'} 个镜头启动严格质量流水线;候选自动校验并有限修复,通过后才接替旧主视频。`
|
||||
: `只为至多 ${videoLimit || '—'} 个就绪镜头启动严格质量流水线。任务创建后由后端自动校验,最多修复 ${videoRepairAttempts || '—'} 次,通过后才晋升主视频。`
|
||||
: stage.key === 'keyframes'
|
||||
? `处理缺失或过期主首帧。过期首帧成功后自动接替旧主图(覆盖模式也如此),其余已有主图只新增候选。本批上限:${keyframeLimit || '不限制'};尺寸:${keyframeWidth && keyframeHeight ? `${keyframeWidth} × ${keyframeHeight}` : '后端默认'}。`
|
||||
: '只处理通过视频提示词就绪检查的镜头;覆盖模式会重写已有提示词。'
|
||||
"
|
||||
:primary="stage.key === 'videos'"
|
||||
@confirm="run(stage.key)"
|
||||
/>
|
||||
<AppForm
|
||||
v-if="stage.key === 'keyframes'"
|
||||
:model="keyframeModel"
|
||||
:rules="keyframeRules"
|
||||
:disabled="operation.pending"
|
||||
validate-on-change
|
||||
class="mt-4 grid gap-3"
|
||||
>
|
||||
<NFormItem path="keyframeLimit" label="本批上限(可选)"
|
||||
><NInputNumber
|
||||
:input-props="{ 'aria-label': '本批上限(可选)' }"
|
||||
:value="keyframeLimit === '' ? null : keyframeLimit"
|
||||
@update:value="keyframeLimit = $event ?? ''"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
:disabled="operation.pending"
|
||||
placeholder="留空不限制"
|
||||
/></NFormItem>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<NFormItem path="keyframeWidth" label="宽度(像素)"
|
||||
><NInputNumber
|
||||
:input-props="{ 'aria-label': '宽度(像素)' }"
|
||||
:value="keyframeWidth === '' ? null : keyframeWidth"
|
||||
@update:value="keyframeWidth = $event ?? ''"
|
||||
:min="1"
|
||||
:disabled="operation.pending"
|
||||
placeholder="默认" /></NFormItem
|
||||
><NFormItem path="keyframeHeight" label="高度(像素)"
|
||||
><NInputNumber
|
||||
:input-props="{ 'aria-label': '高度(像素)' }"
|
||||
:value="
|
||||
keyframeHeight === '' ? null : keyframeHeight
|
||||
"
|
||||
@update:value="keyframeHeight = $event ?? ''"
|
||||
:min="1"
|
||||
:disabled="operation.pending"
|
||||
placeholder="默认"
|
||||
/></NFormItem>
|
||||
</div>
|
||||
</AppForm>
|
||||
<AppForm
|
||||
v-if="stage.key === 'videos'"
|
||||
:model="videoModel"
|
||||
:rules="videoRules"
|
||||
:disabled="operation.pending"
|
||||
validate-on-change
|
||||
class="mt-4 grid gap-3"
|
||||
>
|
||||
<NFormItem path="videoLimit" label="本批镜头上限"
|
||||
><NInputNumber
|
||||
v-model:value="videoLimit"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
:disabled="operation.pending"
|
||||
:input-props="{ 'aria-label': '视频质量任务镜头上限' }"
|
||||
/></NFormItem>
|
||||
<NFormItem path="videoRepairAttempts" label="每镜最多自动修复"
|
||||
><NInputNumber
|
||||
v-model:value="videoRepairAttempts"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
:disabled="operation.pending"
|
||||
:input-props="{ 'aria-label': '视频自动修复次数' }"
|
||||
/></NFormItem>
|
||||
</AppForm>
|
||||
</article>
|
||||
</div>
|
||||
<div v-if="query.data.value" class="panel mt-4 p-5">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<dt>可执行</dt>
|
||||
<dd>{{ stage.data?.ready ?? 0 }}</dd>
|
||||
<h3 class="text-sm font-semibold">视频任务状态</h3>
|
||||
<p class="mt-2 text-xs text-muted">
|
||||
状态统计取每个镜头最近一次任务,不等同于主视频数量。
|
||||
</p>
|
||||
</div>
|
||||
<ConfirmAction
|
||||
label="重试失败视频"
|
||||
:disabled="
|
||||
blocked ||
|
||||
!batchValid ||
|
||||
!query.data.value.videoStatus.failed
|
||||
"
|
||||
acknowledgement
|
||||
description="仅重新提交后端判定可重试的失败视频;不可重试项会跳过,并在回执中显示数量。"
|
||||
@confirm="run('retry-videos')"
|
||||
/>
|
||||
</div>
|
||||
<dl class="production-status-grid mt-4">
|
||||
<div>
|
||||
<dt>完成</dt>
|
||||
<dd>{{ query.data.value.videoStatus.completed }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>已有结果</dt>
|
||||
<dd>{{ stage.data?.skipped ?? 0 }}</dd>
|
||||
<dt>排队/生成</dt>
|
||||
<dd>{{ videoRunning }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>阻塞</dt>
|
||||
<dd>{{ stage.data?.blocked ?? 0 }}</dd>
|
||||
<dt>失败</dt>
|
||||
<dd>{{ query.data.value.videoStatus.failed }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>取消</dt>
|
||||
<dd>{{ query.data.value.videoStatus.cancelled }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>未开始</dt>
|
||||
<dd>{{ query.data.value.videoStatus.notStarted }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p
|
||||
v-if="stage.key === 'keyframes' && staleKeyframes"
|
||||
class="mt-3 text-[11px] leading-5"
|
||||
>
|
||||
已过期 {{ staleKeyframes }} · 会按当前主体参考资产重新生成
|
||||
</p>
|
||||
<p
|
||||
v-if="stage.key === 'videos' && staleVideos"
|
||||
class="mt-3 text-[11px] leading-5"
|
||||
>
|
||||
主视频已过期 {{ staleVideos }} · 会按当前主首帧与参考资产重新生成
|
||||
</p>
|
||||
<p
|
||||
v-if="stage.key === 'keyframes' && identityBlocked"
|
||||
class="mt-3 text-[11px] leading-5 text-danger"
|
||||
>
|
||||
身份缺失 {{ query.data.value?.keyframes.missingIdentity ?? 0 }} ·
|
||||
母版缺失
|
||||
{{ query.data.value?.keyframes.missingIdentityAnchor ?? 0 }} ·
|
||||
未锁定
|
||||
{{ query.data.value?.keyframes.identityUnlocked ?? 0 }}
|
||||
</p>
|
||||
<ConfirmAction
|
||||
class="mt-4"
|
||||
:label="stage.action"
|
||||
:disabled="
|
||||
blocked ||
|
||||
!batchValid ||
|
||||
(stage.key === 'keyframes' && !keyframeValid) ||
|
||||
(stage.key === 'videos' && !videoQualityValid) ||
|
||||
!(stage.data?.ready ?? 0)
|
||||
"
|
||||
acknowledgement
|
||||
:description="
|
||||
stage.key === 'videos'
|
||||
? staleVideos && !force
|
||||
? `当前存在过期主视频,非覆盖模式只会为其中至多 ${videoLimit || '—'} 个镜头启动严格质量流水线;候选自动校验并有限修复,通过后才接替旧主视频。`
|
||||
: `只为至多 ${videoLimit || '—'} 个就绪镜头启动严格质量流水线。任务创建后由后端自动校验,最多修复 ${videoRepairAttempts || '—'} 次,通过后才晋升主视频。`
|
||||
: stage.key === 'keyframes'
|
||||
? `处理缺失或过期主首帧。过期首帧成功后自动接替旧主图(覆盖模式也如此),其余已有主图只新增候选。本批上限:${keyframeLimit || '不限制'};尺寸:${keyframeWidth && keyframeHeight ? `${keyframeWidth} × ${keyframeHeight}` : '后端默认'}。`
|
||||
: '只处理通过视频提示词就绪检查的镜头;覆盖模式会重写已有提示词。'
|
||||
"
|
||||
:primary="stage.key === 'videos'"
|
||||
@confirm="run(stage.key)"
|
||||
/>
|
||||
<AppForm
|
||||
v-if="stage.key === 'keyframes'"
|
||||
:model="keyframeModel"
|
||||
:rules="keyframeRules"
|
||||
:disabled="operation.pending"
|
||||
validate-on-change
|
||||
class="mt-4 grid gap-3"
|
||||
>
|
||||
<NFormItem path="keyframeLimit" label="本批上限(可选)"
|
||||
><NInputNumber
|
||||
:input-props="{ 'aria-label': '本批上限(可选)' }"
|
||||
:value="keyframeLimit === '' ? null : keyframeLimit"
|
||||
@update:value="keyframeLimit = $event ?? ''"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
:disabled="operation.pending"
|
||||
placeholder="留空不限制"
|
||||
/></NFormItem>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<NFormItem path="keyframeWidth" label="宽度(像素)"
|
||||
><NInputNumber
|
||||
:input-props="{ 'aria-label': '宽度(像素)' }"
|
||||
:value="keyframeWidth === '' ? null : keyframeWidth"
|
||||
@update:value="keyframeWidth = $event ?? ''"
|
||||
:min="1"
|
||||
:disabled="operation.pending"
|
||||
placeholder="默认" /></NFormItem
|
||||
><NFormItem path="keyframeHeight" label="高度(像素)"
|
||||
><NInputNumber
|
||||
:input-props="{ 'aria-label': '高度(像素)' }"
|
||||
:value="keyframeHeight === '' ? null : keyframeHeight"
|
||||
@update:value="keyframeHeight = $event ?? ''"
|
||||
:min="1"
|
||||
:disabled="operation.pending"
|
||||
placeholder="默认"
|
||||
/></NFormItem>
|
||||
</div>
|
||||
</AppForm>
|
||||
<AppForm
|
||||
v-if="stage.key === 'videos'"
|
||||
:model="videoModel"
|
||||
:rules="videoRules"
|
||||
:disabled="operation.pending"
|
||||
validate-on-change
|
||||
class="mt-4 grid gap-3"
|
||||
>
|
||||
<NFormItem path="videoLimit" label="本批镜头上限"
|
||||
><NInputNumber
|
||||
v-model:value="videoLimit"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
:disabled="operation.pending"
|
||||
:input-props="{ 'aria-label': '视频质量任务镜头上限' }"
|
||||
/></NFormItem>
|
||||
<NFormItem path="videoRepairAttempts" label="每镜最多自动修复"
|
||||
><NInputNumber
|
||||
v-model:value="videoRepairAttempts"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
:disabled="operation.pending"
|
||||
:input-props="{ 'aria-label': '视频自动修复次数' }"
|
||||
/></NFormItem>
|
||||
</AppForm>
|
||||
</article>
|
||||
</div>
|
||||
<div v-if="query.data.value" class="panel mt-4 p-5">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold">视频任务状态</h3>
|
||||
<p class="mt-2 text-xs text-muted">
|
||||
状态统计取每个镜头最近一次任务,不等同于主视频数量。
|
||||
</p>
|
||||
</div>
|
||||
<ConfirmAction
|
||||
label="重试失败视频"
|
||||
:disabled="
|
||||
blocked || !batchValid || !query.data.value.videoStatus.failed
|
||||
"
|
||||
acknowledgement
|
||||
description="仅重新提交后端判定可重试的失败视频;不可重试项会跳过,并在回执中显示数量。"
|
||||
@confirm="run('retry-videos')"
|
||||
/>
|
||||
</div>
|
||||
<dl class="production-status-grid mt-4">
|
||||
<div>
|
||||
<dt>完成</dt>
|
||||
<dd>{{ query.data.value.videoStatus.completed }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>排队/生成</dt>
|
||||
<dd>{{ videoRunning }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>失败</dt>
|
||||
<dd>{{ query.data.value.videoStatus.failed }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>取消</dt>
|
||||
<dd>{{ query.data.value.videoStatus.cancelled }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>未开始</dt>
|
||||
<dd>{{ query.data.value.videoStatus.notStarted }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div></NCollapseItem
|
||||
></NCollapse
|
||||
>
|
||||
</div></NCollapseItem
|
||||
></NCollapse
|
||||
>
|
||||
</div>
|
||||
<EpisodeAssemblyPanel :project-id="id" />
|
||||
<AdvancedProduction />
|
||||
</div>
|
||||
<EpisodeAssemblyPanel :project-id="id" />
|
||||
<AdvancedProduction />
|
||||
</WorkspaceTools>
|
||||
</div></div
|
||||
></template>
|
||||
@@ -695,6 +713,46 @@ const videoRules = { videoLimit: integerRule('本批镜头上限'), videoRepairA
|
||||
<style>
|
||||
/* 本组件专属布局与 Naive 内部结构覆盖。 */
|
||||
@reference "../../styles/styles.css";
|
||||
.production-tools-intro {
|
||||
@apply flex flex-wrap items-end justify-between gap-4 p-[18px] bg-(--app-surface);
|
||||
}
|
||||
.production-tools-intro .eyebrow {
|
||||
@apply mb-2;
|
||||
}
|
||||
.production-batch-config {
|
||||
@apply mt-3 p-4 bg-(--app-surface);
|
||||
}
|
||||
.production-section-heading {
|
||||
@apply flex items-start justify-between gap-4;
|
||||
}
|
||||
.workspace-tools-body .production-batch-config .production-controls {
|
||||
@apply mt-4 mb-0;
|
||||
}
|
||||
.production-tool-stack {
|
||||
@apply mt-3 px-4 bg-(--app-surface);
|
||||
}
|
||||
.production-tool-stack .production-tool-section.n-collapse {
|
||||
@apply m-0;
|
||||
box-shadow: inset 0 1px var(--app-border);
|
||||
}
|
||||
.production-tool-stack > :first-child.production-tool-section.n-collapse {
|
||||
box-shadow: none;
|
||||
}
|
||||
.production-tool-stack .production-tool-section .n-collapse-item__header {
|
||||
@apply min-h-12 py-0;
|
||||
}
|
||||
.production-tool-stack .production-tool-section .n-collapse-item__header-main {
|
||||
@apply text-[13px] font-medium;
|
||||
}
|
||||
.production-tool-stack .production-tool-section .n-collapse-item__content-inner {
|
||||
@apply pt-1 pb-4 pl-6;
|
||||
}
|
||||
.production-tool-stack .detail-disclosure-content {
|
||||
@apply py-3 px-4 bg-(--app-subtle);
|
||||
}
|
||||
.production-tool-stack .workspace-overview-panel {
|
||||
@apply m-0;
|
||||
}
|
||||
.production-controls {
|
||||
@apply grid grid-cols-[minmax(220px,_1.6fr)_minmax(110px,_0.5fr)_minmax(230px,_1fr)_auto] items-end gap-[18px];
|
||||
}
|
||||
@@ -737,6 +795,16 @@ const videoRules = { videoLimit: integerRule('本批镜头上限'), videoRepairA
|
||||
}
|
||||
}
|
||||
@media (max-width: 760px) {
|
||||
.production-tools-intro,
|
||||
.production-section-heading {
|
||||
@apply items-start;
|
||||
}
|
||||
.production-tool-stack {
|
||||
@apply px-3;
|
||||
}
|
||||
.production-tool-stack .production-tool-section .n-collapse-item__content-inner {
|
||||
@apply pl-4;
|
||||
}
|
||||
.production-controls,
|
||||
.production-workspace {
|
||||
@apply grid-cols-[minmax(0,_1fr)];
|
||||
|
||||
Reference in New Issue
Block a user