feat: 主体目录增加母版缩略图与紧凑图文布局

This commit is contained in:
GouJ
2026-09-01 19:34:59 +08:00
parent ad37c8ab7c
commit 9e3bff7997
8 changed files with 470 additions and 8 deletions
+68
View File
@@ -220,6 +220,74 @@ describe('内容级滚动下的生产反馈', () => {
})
describe('视觉风格与主体身份工作区', () => {
it('主体目录显示已确认母版和默认占位,点缩略图只切换主体,不重复读取所有角色图库', async () => {
const first = formFixture()
const forms = [
first,
...[2, 3].map(index => ({
...first,
id: `form-${index}`,
subjectId: `subject-${index}`,
images: [],
subject: { ...first.subject, id: `subject-${index}`, ref: `@CH000${index}`, name: `角色${index}` }
}))
]
const fetcher = vi.fn<typeof fetch>().mockImplementation(async url => {
const path = String(url)
if (path.endsWith('/subject-forms')) return jsonResponse(forms)
if (path.endsWith('/visual-style')) return jsonResponse(styleFixture())
if (path.endsWith('/character-casting/readiness'))
return jsonResponse({
total: 3,
ready: 2,
missingIdentity: 0,
missingAnchor: 1,
candidatePending: 0,
unlocked: 0,
locked: 2,
items: forms.map((form, index) => ({
subjectId: form.subjectId,
subjectRef: form.subject.ref,
subjectName: form.subject.name,
status: index === 2 ? 'missing_anchor' : 'ready',
isLocked: index !== 2,
anchorImageId: index === 2 ? undefined : `anchor-${index}`,
anchorImageUrl: index === 2 ? undefined : `/storage/anchor-${index}.png`,
candidateImages: [{ id: 'candidate', imageUrl: '/storage/candidate.png' }]
}))
})
const second = path.includes('/subject-2/')
if (path.endsWith('/identity/images'))
return jsonResponse([
identityImageFixture({
identityId: second ? 'identity-2' : 'identity-db-1',
imageUrl: `/storage/anchor-${second ? 1 : 0}.png`
})
])
return jsonResponse(
identityFixture({
subjectId: second ? 'subject-2' : first.subjectId,
id: second ? 'identity-2' : 'identity-db-1'
})
)
})
vi.stubGlobal('fetch', fetcher)
await mountAssets('identity')
await wrapper!.get('[aria-label="关闭操作面板"]').trigger('click')
await flushPromises()
const items = wrapper!.findAll('.identity-subject-item')
expect(items).toHaveLength(3)
expect(items[0]!.get('.identity-thumbnail img').attributes('src')).toContain('/storage/anchor-0.png')
expect(items[1]!.get('.identity-thumbnail img').attributes('src')).toContain('/storage/anchor-1.png')
expect(items[2]!.get('.identity-thumbnail [role="img"]').attributes('aria-label')).toContain('暂无母版')
expect(fetcher.mock.calls.filter(([url]) => String(url).endsWith('/identity/images'))).toHaveLength(1)
await items[1]!.get('.identity-thumbnail img').trigger('click')
await flushPromises()
expect(items[1]!.attributes('aria-pressed')).toBe('true')
expect(document.querySelector('.n-image-preview-container')).toBeNull()
expect(fetcher.mock.calls.every(([, init]) => init?.method === 'GET')).toBe(true)
})
it('从形态深链接进入后,手动切换主体不会被目录刷新切回', async () => {
const form = formFixture()
const second = {