feat(short-drama-agent-front): 优化项目查询与工作区界面
This commit is contained in:
@@ -99,7 +99,7 @@ const filtered = computed(() =>
|
||||
)
|
||||
)
|
||||
|
||||
/** 深链接仅在目标 ID 变化时选择,不因目录轮询把用户切回原主体。 */
|
||||
/** 深链接仅在目标 ID 变化时选择,不因目录刷新把用户切回原主体。 */
|
||||
const linkedSubjectId = computed(
|
||||
() => subjects.value.find(item => item.id === route.query.subjectId || item.ref === route.query.subjectRef)?.id
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ import { NButton, NCheckbox, NInput } from 'naive-ui'
|
||||
import { computed, reactive, ref, watch } from 'vue'
|
||||
import type { SaveIdentityInput, SubjectIdentity } from '../types'
|
||||
|
||||
/** 身份文本草稿不随轮询覆盖;父页面切换主体或保存成功后重建编辑器。 */
|
||||
/** 身份文本草稿不随查询覆盖;父页面切换主体或保存成功后重建编辑器。 */
|
||||
const props = defineProps<{ identity: SubjectIdentity | null; disabled: boolean; module: string }>()
|
||||
const emit = defineEmits<{ save: [input: SaveIdentityInput]; dirty: [value: boolean] }>()
|
||||
const form = reactive({ description: '', generationPrompt: '', isLocked: false })
|
||||
|
||||
@@ -53,7 +53,7 @@ watch(url, () => {
|
||||
imageFailed.value = false
|
||||
})
|
||||
|
||||
/** 仅读取正式主体的身份图库;切项目、筛选或刷新时中止旧请求,不轮询每个缩略图。 */
|
||||
/** 仅读取正式主体的身份图库;切项目、筛选或刷新时中止旧请求。 */
|
||||
watch(
|
||||
() => [props.projectId, props.subjectId, props.identityId, props.source, props.refreshKey, visible.value],
|
||||
async (_value, _oldValue, onCleanup) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { usePolling } from '../../composables/usePolling'
|
||||
import { useQuery } from '../../composables/useQuery'
|
||||
import { visualStyleApi } from '../visual-style'
|
||||
import { subjectImagesApi } from '../subject-images/api'
|
||||
import { hasRunningImages } from '../subject-images/model'
|
||||
@@ -30,58 +30,42 @@ export function useSubjectIdentity() {
|
||||
const candidateLimit = ref(3)
|
||||
const force = ref(false)
|
||||
/** 目录与身份已有刷新按钮,查询只在进入、切换和手动刷新时读取。 */
|
||||
const catalog = usePolling(
|
||||
projectId,
|
||||
async (id, signal) => {
|
||||
const forms = await subjectImagesApi.listForms(id, signal)
|
||||
if (
|
||||
forms.some(
|
||||
form => form.subject.projectId !== id || form.images.some(image => image.subjectFormId !== form.id)
|
||||
)
|
||||
const catalog = useQuery(projectId, async (id, signal) => {
|
||||
const forms = await subjectImagesApi.listForms(id, signal)
|
||||
if (
|
||||
forms.some(
|
||||
form => form.subject.projectId !== id || form.images.some(image => image.subjectFormId !== form.id)
|
||||
)
|
||||
throw new Error('主体目录与当前项目不匹配,请刷新后重试。')
|
||||
return {
|
||||
subjects: groupIdentitySubjects(forms),
|
||||
running: forms.some(form => hasRunningImages(form.images))
|
||||
}
|
||||
},
|
||||
false
|
||||
)
|
||||
const styleQuery = usePolling(
|
||||
projectId,
|
||||
async (id, signal) => {
|
||||
const style = await visualStyleApi.get(id, signal)
|
||||
if (style && style.projectId !== id) throw new Error('视觉风格与当前项目不匹配。')
|
||||
return { style }
|
||||
},
|
||||
false
|
||||
)
|
||||
const castingQuery = usePolling(
|
||||
projectId,
|
||||
async (id, signal) => {
|
||||
const readiness = await subjectIdentityApi.castingReadiness(id, signal)
|
||||
return readiness
|
||||
},
|
||||
false
|
||||
)
|
||||
)
|
||||
throw new Error('主体目录与当前项目不匹配,请刷新后重试。')
|
||||
return {
|
||||
subjects: groupIdentitySubjects(forms),
|
||||
running: forms.some(form => hasRunningImages(form.images))
|
||||
}
|
||||
})
|
||||
const styleQuery = useQuery(projectId, async (id, signal) => {
|
||||
const style = await visualStyleApi.get(id, signal)
|
||||
if (style && style.projectId !== id) throw new Error('视觉风格与当前项目不匹配。')
|
||||
return { style }
|
||||
})
|
||||
const castingQuery = useQuery(projectId, async (id, signal) => {
|
||||
const readiness = await subjectIdentityApi.castingReadiness(id, signal)
|
||||
return readiness
|
||||
})
|
||||
const subjects = computed(() =>
|
||||
mergeCastingSubjects(catalog.data.value?.subjects ?? [], castingQuery.data.value?.items ?? [], projectId.value)
|
||||
)
|
||||
const subject = computed(() => subjects.value.find(item => item.id === selectedId.value))
|
||||
const selectionKey = computed(() => subject.value?.id ?? '')
|
||||
const detail = usePolling(
|
||||
selectionKey,
|
||||
async (id, signal) => {
|
||||
if (!id) return null
|
||||
const identity = await subjectIdentityApi.get(id, signal)
|
||||
if (!identity) return { identity: null, images: [] as IdentityImage[] }
|
||||
assertIdentity(identity, id)
|
||||
const images = await subjectIdentityApi.listImages(id, signal)
|
||||
if (images.some(image => image.identityId !== identity.id)) throw new Error('身份图片与当前主体不匹配。')
|
||||
return { identity, images }
|
||||
},
|
||||
false
|
||||
)
|
||||
const detail = useQuery(selectionKey, async (id, signal) => {
|
||||
if (!id) return null
|
||||
const identity = await subjectIdentityApi.get(id, signal)
|
||||
if (!identity) return { identity: null, images: [] as IdentityImage[] }
|
||||
assertIdentity(identity, id)
|
||||
const images = await subjectIdentityApi.listImages(id, signal)
|
||||
if (images.some(image => image.identityId !== identity.id)) throw new Error('身份图片与当前主体不匹配。')
|
||||
return { identity, images }
|
||||
})
|
||||
const identity = computed(() => detail.data.value?.identity ?? null)
|
||||
const images = computed(() => detail.data.value?.images ?? [])
|
||||
const castingItem = computed(() =>
|
||||
|
||||
Reference in New Issue
Block a user