feat: 对齐后端能力并补齐形态提示词与生产诊断
This commit is contained in:
@@ -13,6 +13,8 @@ import { coverImage, hasRunningImages, isPrimaryIdentityStale, primaryImage } fr
|
||||
import type { GenerateFormImageInput, SubjectFormAsset } from './types'
|
||||
import GenerateImageDialog from './components/GenerateImageDialog.vue'
|
||||
import ImageGalleryDialog from './components/ImageGalleryDialog.vue'
|
||||
import FormPromptDialog from './components/FormPromptDialog.vue'
|
||||
import FormPromptBatch from './components/FormPromptBatch.vue'
|
||||
|
||||
/** 形态图库以正式数据库为准,自动显示已在后端生成的图片。 */
|
||||
const route = useRoute()
|
||||
@@ -25,6 +27,12 @@ const {
|
||||
session,
|
||||
concurrency,
|
||||
force,
|
||||
limit,
|
||||
promptConcurrency,
|
||||
promptForce,
|
||||
concurrencyValid,
|
||||
generatePrompt,
|
||||
generatePrompts,
|
||||
blocked,
|
||||
running,
|
||||
batchValid,
|
||||
@@ -40,6 +48,12 @@ watch(
|
||||
if (receipt) toolsOpen.value = true
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => session.value.promptReceipt,
|
||||
receipt => {
|
||||
if (receipt) toolsOpen.value = true
|
||||
}
|
||||
)
|
||||
const search = ref('')
|
||||
const module = ref('all')
|
||||
const onlyMissing = ref(false)
|
||||
@@ -48,6 +62,9 @@ const generateOpen = ref(false)
|
||||
const galleryOpen = ref(false)
|
||||
const generateId = ref('')
|
||||
const galleryId = ref('')
|
||||
const promptOpen = ref(false)
|
||||
const promptId = ref('')
|
||||
const promptForm = computed(() => forms.value.find(form => form.id === promptId.value) ?? null)
|
||||
const generateForm = computed(() => forms.value.find(form => form.id === generateId.value) ?? null)
|
||||
const galleryForm = computed(() => forms.value.find(form => form.id === galleryId.value) ?? null)
|
||||
const completeCount = computed(() => forms.value.filter(form => primaryImage(form.images)).length)
|
||||
@@ -70,6 +87,12 @@ watch(
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
/** 打开指定正式形态的提示词管理。 */
|
||||
function openPrompt(form: SubjectFormAsset) {
|
||||
promptId.value = form.id
|
||||
promptOpen.value = true
|
||||
}
|
||||
|
||||
/** 打开指定正式形态的生图表单。 */
|
||||
function openGenerate(form: SubjectFormAsset) {
|
||||
generateId.value = form.id
|
||||
@@ -111,7 +134,7 @@ function resetFilters() {
|
||||
><WorkspaceTools
|
||||
v-model:open="toolsOpen"
|
||||
title="形态生图配置与回执"
|
||||
:has-receipt="!!session.receipt"
|
||||
:has-receipt="!!session.receipt || !!session.promptReceipt"
|
||||
><div class="flex flex-wrap items-end justify-between gap-4">
|
||||
<div>
|
||||
<h2 class="text-lg font-semibold">形态图片</h2>
|
||||
@@ -124,18 +147,27 @@ function resetFilters() {
|
||||
/></RouterLink>
|
||||
</div>
|
||||
<NAlert type="info" :show-icon="false" class="mt-5 text-xs">
|
||||
Character 形态图会记录生成时使用的 Identity
|
||||
Anchor。更换演员母版后,旧主图会标记为“身份母版已变更”,且后端会阻止它继续进入分镜首帧;请基于当前母版重新生成候选并确认新的主参考图。
|
||||
人物、场景、道具形态图均可继承已锁定 Identity
|
||||
的母版,并记录本次引用来源。母版变化后可筛选过期图,重新生成候选并人工确认新的主参考图;不要直接沿用旧资产进入下游。
|
||||
<RouterLink :to="`/projects/${id}/subject-identity`" class="text-button ml-2"
|
||||
>管理主体身份 →</RouterLink
|
||||
></NAlert
|
||||
>
|
||||
<FormPromptBatch
|
||||
:forms="forms"
|
||||
:disabled="blocked"
|
||||
:pending="operation.pending"
|
||||
:receipt="session.promptReceipt"
|
||||
v-model:concurrency="promptConcurrency"
|
||||
v-model:force="promptForce"
|
||||
@generate="generatePrompts"
|
||||
/>
|
||||
<div class="panel mt-5 p-5">
|
||||
<div class="flex flex-wrap items-center justify-between gap-4">
|
||||
<p class="text-sm">
|
||||
<strong>{{ completeCount }}</strong> / {{ forms.length }} 个形态已有主图
|
||||
<span v-if="staleForms.length" class="ml-3 text-xs text-danger">
|
||||
{{ staleForms.length }} 个人物形态主图已过期
|
||||
{{ staleForms.length }} 个形态主图已过期
|
||||
</span>
|
||||
<span class="ml-3 text-xs text-muted">Seedream · 后端配置</span>
|
||||
</p>
|
||||
@@ -147,14 +179,14 @@ function resetFilters() {
|
||||
<NAlert v-if="staleForms.length" type="error" :show-icon="false" class="mt-4"
|
||||
><div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<span class="flex items-center gap-2 text-xs">
|
||||
<AlertTriangle :size="14" />检测到 {{ staleForms.length }} 个 Character Form
|
||||
仍在使用旧 Identity Anchor。
|
||||
<AlertTriangle :size="14" />检测到 {{ staleForms.length }} 个形态 仍在使用旧
|
||||
Identity Anchor。
|
||||
</span>
|
||||
<ConfirmAction
|
||||
label="重新生成过期形态"
|
||||
:disabled="blocked || !batchValid || !staleForms.length"
|
||||
:disabled="blocked || !concurrencyValid || !staleForms.length"
|
||||
acknowledgement
|
||||
description="只为身份母版已经变化的 Character Form 调用 Seedream,各新增一张基于当前 Anchor 的候选图;不会自动替换旧主图,生成后请人工确认并设置新的主参考图。"
|
||||
description="只为身份母版已经变化的形态调用 Seedream,各新增一张基于当前已锁定母版的候选图;不会自动替换旧主图,生成后请人工确认并设置新的主参考图。"
|
||||
@confirm="generateStale"
|
||||
/></div
|
||||
></NAlert>
|
||||
@@ -173,6 +205,17 @@ function resetFilters() {
|
||||
:step="1"
|
||||
></NInputNumber>
|
||||
</label>
|
||||
<label class="w-36"
|
||||
><span class="field-label">本批上限(可选)</span
|
||||
><NInputNumber
|
||||
:disabled="operation.pending"
|
||||
:value="typeof limit === 'number' ? limit : null"
|
||||
@update:value="limit = $event ?? ''"
|
||||
:min="1"
|
||||
:step="1"
|
||||
placeholder="不限制"
|
||||
:input-props="{ 'aria-label': '生图本批上限' }"
|
||||
/></label>
|
||||
<NCheckbox
|
||||
v-model:checked="force"
|
||||
:disabled="operation.pending"
|
||||
@@ -191,9 +234,11 @@ function resetFilters() {
|
||||
@confirm="generateProject"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="!batchValid" class="mt-2 text-xs text-danger">并发必须是正整数。</p>
|
||||
<p v-if="!batchValid" class="mt-2 text-xs text-danger">
|
||||
并发和填写的数量上限必须是正整数。
|
||||
</p>
|
||||
<p class="mt-3 text-xs leading-6 text-muted">
|
||||
作用于整个项目,不受下方筛选影响。批量使用后端默认尺寸与形态提示词,不会启动视频生成。
|
||||
作用于整个项目,不受下方筛选影响。上限只限制本次真正生图数量,其余显示为“待后续处理”,不计入跳过。默认使用后端尺寸与正式提示词,不会启动视频生成。
|
||||
</p></NCollapseItem
|
||||
></NCollapse
|
||||
>
|
||||
@@ -210,6 +255,9 @@ function resetFilters() {
|
||||
{{ session.receipt.result.targetCount }} · 生成 {{ session.receipt.result.generated }} ·
|
||||
跳过 {{ session.receipt.result.skipped }} · 失败
|
||||
{{ session.receipt.result.failed }}
|
||||
<span v-if="session.receipt.result.remaining !== undefined">
|
||||
· 待后续处理 {{ session.receipt.result.remaining }}</span
|
||||
>
|
||||
</p>
|
||||
<NAlert
|
||||
v-if="session.receipt.result.failed"
|
||||
@@ -221,7 +269,7 @@ function resetFilters() {
|
||||
部分形态生图失败。已生成的图片保留;先查看失败原因,再按形态重新生图。
|
||||
</NAlert>
|
||||
<NAlert
|
||||
v-else-if="session.receipt.title === '刷新过期人物形态图'"
|
||||
v-else-if="session.receipt.title === '刷新过期形态图'"
|
||||
type="info"
|
||||
:show-icon="false"
|
||||
class="mt-3 text-xs"
|
||||
@@ -322,13 +370,14 @@ function resetFilters() {
|
||||
:show-icon="false"
|
||||
class="mt-3 text-xs leading-6"
|
||||
>
|
||||
当前主图由旧演员母版生成,后续分镜已禁止继续引用。请基于当前 Identity Anchor
|
||||
当前主图未能匹配最新已锁定母版。请基于当前 Identity Anchor
|
||||
重新生成候选图,并在确认后设置为新的主参考图。
|
||||
</NAlert>
|
||||
<p v-if="form.images[0]?.status === 'failed'" class="mt-2 line-clamp-2 text-xs text-danger">
|
||||
{{ form.images[0].error }}
|
||||
</p>
|
||||
<div class="mt-4 flex flex-wrap items-center justify-between gap-2">
|
||||
<NButton text size="small" @click="openPrompt(form)">提示词与生成</NButton>
|
||||
<NButton @click="openGallery(form)" text size="small">查看图片与记录</NButton>
|
||||
<NButton :disabled="blocked" @click="openGenerate(form)"
|
||||
><ImagePlus :size="14" />
|
||||
@@ -357,7 +406,11 @@ function resetFilters() {
|
||||
<RouterLink v-else :to="`/projects/${id}/breakdown`" class="button button-secondary"
|
||||
>前往剧本拆解</RouterLink
|
||||
> </EmptyState
|
||||
><GenerateImageDialog
|
||||
><FormPromptDialog
|
||||
v-model:open="promptOpen"
|
||||
:form="promptForm"
|
||||
:disabled="blocked || !promptForm"
|
||||
@generate="generatePrompt" /><GenerateImageDialog
|
||||
v-model:open="generateOpen"
|
||||
:form="generateForm"
|
||||
:disabled="blocked || !generateForm"
|
||||
|
||||
Reference in New Issue
Block a user