Files
short-drama-agent-front/src/features/breakdown/components/SubjectList.vue
T
GouJ 669f4d9df0 feat: 同步视觉风格与主体身份母版工作区
对齐后端 dev 059e597,新增项目风格编辑锁定、身份文本生成、身份参考图与母版切换。
整理六个工作区入口,接通人物及场景母版继承说明、形态图片来源追溯。
补充草稿保护、正式 ID 校验、费用确认及部分失败回执,67 项测试和静态检查、构建通过。
未修改后端,未调用真实模型;本环境未完成浏览器视觉验收。
2026-08-28 19:28:27 +08:00

80 lines
3.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, ref } from 'vue'
import { Search, ChevronDown } from '@lucide/vue'
import { EmptyState } from '../../../components/ui'
import type { SubjectCandidate, SubjectForm } from '../types'
/** 主体列表按稳定 ref 展示;形态以 profileId 关联。 */
const props = defineProps<{ subjects: SubjectCandidate[]; forms: SubjectForm[]; projectId?: string }>()
const search = ref('')
const filtered = computed(() =>
props.subjects.filter(item =>
`${item.name} ${item.ref} ${item.aliases?.join(' ') ?? ''}`
.toLowerCase()
.includes(search.value.trim().toLowerCase())
)
)
</script>
<template>
<div class="p-5 lg:p-7">
<div class="mb-5 flex items-center justify-between gap-3">
<p class="text-sm text-muted">{{ subjects.length }} 个主体</p>
<div class="search-field">
<Search :size="14" /><input v-model="search" placeholder="搜索名称或引用" aria-label="搜索主体" />
</div>
</div>
<div v-if="filtered.length" class="divide-y divide-line">
<article v-for="subject in filtered" :key="subject.profileId" class="py-5 first:pt-0">
<div class="mb-3 flex flex-wrap items-center gap-3">
<h3 class="font-semibold">{{ subject.name }}</h3>
<code class="subject-ref">{{ subject.ref }}</code
><span v-if="subject.aliases?.length" class="text-xs text-muted"
>别名{{ subject.aliases.join('、') }}</span
>
</div>
<p class="text-sm leading-7">{{ subject.description }}</p>
<RouterLink
v-if="projectId"
:to="{ path: `/projects/${projectId}/subject-identity`, query: { subjectRef: subject.ref } }"
class="text-button mt-3 mr-4"
>管理稳定身份母版</RouterLink
>
<RouterLink
v-if="projectId"
:to="{ path: `/projects/${projectId}/subject-images`, query: { subjectRef: subject.ref } }"
class="text-button mt-3"
>查看形态图片生图</RouterLink
>
<details class="subject-details mt-4">
<summary>
<ChevronDown :size="14" />外观描述与形态
<span class="ml-1 text-muted">{{
forms.filter(form => form.profileId === subject.profileId).length
}}</span>
</summary>
<p class="mt-3 whitespace-pre-wrap text-sm leading-7 text-muted">
{{ subject.appearance_prompt || '暂无外观描述' }}
</p>
<div
v-for="form in forms.filter(item => item.profileId === subject.profileId)"
:key="form.formId"
class="mt-3 border-l-2 border-line pl-4"
>
<p class="text-sm font-medium">
{{ form.formName || form.name }}<span v-if="form.isDefault" class="tag ml-2">默认</span>
</p>
<p class="mt-2 text-sm leading-6 text-muted">{{ form.description }}</p>
<p class="mt-2 text-xs leading-6 text-muted">{{ form.appearancePrompt }}</p>
</div>
</details>
</article>
</div>
<EmptyState
v-else
:title="subjects.length ? '没有匹配的主体' : '尚无主体结果'"
description="主体会在抽取、合并与档案整理完成后出现在这里。若未启用该模块,则不会生成此类主体。"
/>
</div>
</template>