96 lines
4.4 KiB
Vue
96 lines
4.4 KiB
Vue
<script setup lang="ts">
|
||
import { NAlert, NButton, NCheckbox, NInput, NInputNumber } from 'naive-ui'
|
||
import { computed, ref, watch } from 'vue'
|
||
import { AppDialog } from '../../../components/ui'
|
||
import { validImageSize } from '../../subject-images/model'
|
||
import type { GenerateCastingCandidateInput } from '../types'
|
||
|
||
/** Character 选角候选表单固定使用 primary,每次独立生成且不会自动选择演员。 */
|
||
const props = defineProps<{ subjectId: string; subjectName: string; disabled: boolean }>()
|
||
const open = defineModel<boolean>('open', { default: false })
|
||
const emit = defineEmits<{ generate: [input: GenerateCastingCandidateInput] }>()
|
||
const prompt = ref('')
|
||
const width = ref<number | ''>('')
|
||
const height = ref<number | ''>('')
|
||
const acknowledged = ref(false)
|
||
const valid = computed(() => validImageSize(width.value, height.value))
|
||
|
||
/** 每次切换角色或重新打开都清空自定义覆盖与费用确认。 */
|
||
function reset() {
|
||
prompt.value = ''
|
||
width.value = ''
|
||
height.value = ''
|
||
acknowledged.value = false
|
||
}
|
||
watch([() => props.subjectId, open], reset)
|
||
|
||
/** 只发送选角候选接口接受的字段,不携带普通身份图视角参数。 */
|
||
function submit() {
|
||
if (props.disabled || !valid.value || !acknowledged.value) return
|
||
emit('generate', {
|
||
provider: 'seedream',
|
||
...(prompt.value.trim() ? { prompt: prompt.value.trim() } : {}),
|
||
...(width.value !== '' && height.value !== '' ? { width: width.value, height: height.value } : {})
|
||
})
|
||
open.value = false
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<AppDialog v-model:open="open" title="生成角色选角候选" :description="`${subjectName} · 候选不会自动成为身份母版`">
|
||
<form class="mt-5 space-y-4" @submit.prevent="submit">
|
||
<NAlert type="info" :show-icon="false" class="text-xs">
|
||
后端会依据角色 Identity、项目视觉风格和默认选角约束独立生成一张 primary
|
||
候选,不会复用当前身份母版。生成完成后仍需人工点击“确认选角”。
|
||
</NAlert>
|
||
<label class="block">
|
||
<span class="field-label">覆盖本次完整提示词(可选)</span>
|
||
<NInput
|
||
placeholder="建议留空,使用后端编译的稳定身份和选角约束;未明确人物背景时默认中国人物"
|
||
:input-props="{ id: 'casting-candidate-prompt' }"
|
||
class="min-h-24"
|
||
v-model:value="prompt"
|
||
type="textarea"
|
||
:autosize="{ minRows: 3, maxRows: 12 }"
|
||
></NInput>
|
||
</label>
|
||
<p v-if="prompt.trim()" class="text-xs text-danger">
|
||
自定义文本会替换后端完整提示词,请自行包含人物身份、基础服装和中性参考图要求。
|
||
</p>
|
||
<div class="grid grid-cols-2 gap-4">
|
||
<label
|
||
><span class="field-label">宽度(px)</span
|
||
><NInputNumber
|
||
placeholder="后端默认"
|
||
:value="typeof width === 'number' ? width : null"
|
||
@update:value="width = $event ?? ''"
|
||
:min="1"
|
||
></NInputNumber
|
||
></label>
|
||
<label
|
||
><span class="field-label">高度(px)</span
|
||
><NInputNumber
|
||
placeholder="后端默认"
|
||
:value="typeof height === 'number' ? height : null"
|
||
@update:value="height = $event ?? ''"
|
||
:min="1"
|
||
></NInputNumber
|
||
></label>
|
||
</div>
|
||
<p v-if="!valid" class="text-xs text-danger">宽高需要同时留空,或同时填写正整数。</p>
|
||
<NCheckbox
|
||
id="casting-candidate-cost"
|
||
v-model:checked="acknowledged"
|
||
class="flex items-start gap-2 text-xs leading-6"
|
||
>我已确认调用 Seedream 可能产生费用,且当前没有同项目生成任务。
|
||
</NCheckbox>
|
||
<div class="dialog-footer">
|
||
<NButton @click="open = false">取消</NButton>
|
||
<NButton :disabled="disabled || !valid || !acknowledged" type="primary" attr-type="submit">
|
||
确认生成候选
|
||
</NButton>
|
||
</div>
|
||
</form>
|
||
</AppDialog>
|
||
</template>
|