feat: 主体目录增加母版缩略图与紧凑图文布局
This commit is contained in:
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user