feat: 同步精简接口并统一表单校验

This commit is contained in:
GJ
2026-09-10 22:34:47 +08:00
parent 82d7bde631
commit 2eea0ea72e
66 changed files with 1611 additions and 1100 deletions
@@ -11,8 +11,7 @@ import {
castingStatusLabel,
currentAnchor,
groupIdentitySubjects,
mergeCastingSubjects,
readImageProvenance
mergeCastingSubjects
} from '@/features/subject-identity/model'
import { identityImageFixture } from '@/features/subject-identity/testing/fixtures'
import { formFixture } from '@/features/subject-images/testing/fixtures'
@@ -83,21 +82,19 @@ describe('身份图与母版契约', () => {
expect(wrapper.emitted('anchor')).toBeUndefined()
})
it('实际提示词默认展开,可手动收起,轮询更新不强行重新展开', async () => {
const image = identityImageFixture({ prompt: '本次实际生成提示词' })
it('身份图库使用精简资产,不展示已移除的提示词和启停状态', () => {
wrapper = mount(IdentityGallery, {
props: { subjectName: '林夏', module: 'character', identityLocked: true, disabled: false, images: [image] }
props: {
subjectName: '林夏',
module: 'character',
identityLocked: true,
disabled: false,
images: [identityImageFixture()]
}
})
const panel = wrapper.get('.n-collapse-item')
expect(panel.classes()).toContain('n-collapse-item--active')
expect(panel.text()).toContain('本次实际生成提示词')
await panel.get('.n-collapse-item__header-main').trigger('click')
expect(panel.classes()).not.toContain('n-collapse-item--active')
await wrapper.setProps({ images: [{ ...image, prompt: '更新后的实际提示词' }] })
expect(panel.classes()).not.toContain('n-collapse-item--active')
await panel.get('.n-collapse-item__header-main').trigger('click')
expect(panel.classes()).toContain('n-collapse-item--active')
expect(panel.text()).toContain('更新后的实际提示词')
expect(wrapper.text()).toContain('当前身份母版')
expect(wrapper.text()).not.toContain('本次实际提示词')
expect(wrapper.text()).not.toContain('停用')
})
it('全部历史记录显示在预览下方,候选、辅助、失败和进行中图片均可切换查看', async () => {
@@ -105,26 +102,24 @@ describe('身份图与母版契约', () => {
identityImageFixture({
id: 'candidate',
imageUrl: '/storage/candidate.png',
isAnchor: false,
enabled: false
isAnchor: false
}),
identityImageFixture({
id: 'failed',
status: 'failed',
imageUrl: null,
isAnchor: false,
enabled: false,
error: '图片模型超时'
}),
identityImageFixture({ id: 'anchor', imageUrl: '/storage/anchor.png', width: 4096, height: 4096 }),
identityImageFixture({ id: 'front', imageUrl: '/storage/front.png', viewType: 'front', isAnchor: false }),
identityImageFixture({ id: 'pending', status: 'pending', imageUrl: null, isAnchor: false, enabled: false }),
identityImageFixture({ id: 'pending', status: 'pending', imageUrl: null, isAnchor: false }),
identityImageFixture({
id: 'generating',
status: 'generating',
imageUrl: null,
isAnchor: false,
enabled: false
isAnchor: false
})
]
wrapper = mount(IdentityGallery, {
@@ -196,9 +191,7 @@ describe('身份图与母版契约', () => {
module: 'character',
identityLocked: false,
disabled: false,
images: ['candidate-a', 'candidate-b'].map(id =>
identityImageFixture({ id, isAnchor: false, enabled: false })
)
images: ['candidate-a', 'candidate-b'].map(id => identityImageFixture({ id, isAnchor: false }))
}
})
button('确认选角并锁定').click()
@@ -225,7 +218,7 @@ describe('身份图与母版契约', () => {
it('启用的辅助视角不是母版,primary 候选停用时仍可选为母版', () => {
const front = identityImageFixture({ id: 'front', viewType: 'front', isAnchor: false })
const candidate = identityImageFixture({ id: 'candidate', enabled: false, isAnchor: false })
const candidate = identityImageFixture({ id: 'candidate', isAnchor: false })
expect(canBeAnchor(front)).toBe(false)
expect(canBeAnchor(candidate)).toBe(true)
expect(currentAnchor([front, candidate])).toBeUndefined()
@@ -233,14 +226,8 @@ describe('身份图与母版契约', () => {
expect(canBeAnchor(identityImageFixture({ imageUrl: null }))).toBe(false)
})
it('正式主体关联校验不接受不同主体的 form,追溯 JSON 兼容旧数据', () => {
it('正式主体关联校验不接受不同主体的 form', () => {
expect(() => groupIdentitySubjects([{ ...formFixture(), subjectId: 'wrong' }])).toThrow('不匹配')
expect(readImageProvenance('{bad')).toEqual({})
expect(readImageProvenance(null)).toEqual({})
expect(readImageProvenance('{"identityAnchorImageId":"anchor","referenceImageId":7}')).toMatchObject({
identityAnchorImageId: 'anchor',
referenceImageId: undefined
})
})
it('选角就绪结果可以补入尚无形态的角色目录', () => {
@@ -342,7 +329,7 @@ describe('身份图与母版契约', () => {
expect(select.props('value')).toBe('front')
})
it('辅助图不能切换母版,提示词按纯文本展示', async () => {
it('辅助图不能切换母版,精简资产不展示内部提示词', async () => {
wrapper = mount(IdentityGallery, {
attachTo: document.body,
props: {
@@ -355,7 +342,7 @@ describe('身份图与母版契约', () => {
})
expect(button('确认选角并锁定').disabled).toBe(true)
await expandSections()
expect(wrapper.text()).toContain('<script>不执行</script>')
expect(wrapper.text()).not.toContain('本次实际提示词')
expect(wrapper.find('script').exists()).toBe(false)
expect(wrapper.emitted('anchor')).toBeUndefined()
})
@@ -388,6 +375,7 @@ describe('身份图与母版契约', () => {
document.querySelector<HTMLInputElement>('#casting-candidate-cost')!.click()
await flushPromises()
button('确认生成候选').click()
await flushPromises()
expect(wrapper.emitted('generate')).toEqual([[{}]])
})
@@ -93,7 +93,7 @@ describe('主体目录母版缩略图', () => {
identityImageFixture({
id: 'candidate',
isAnchor: false,
enabled: false,
imageUrl: '/storage/candidate.png'
}),
identityImageFixture({