fix: 将全部业务抽屉提升为全局全高侧栏

This commit is contained in:
GouJ
2026-09-04 10:23:00 +08:00
parent 13bb6dc83b
commit f3657ea0a6
8 changed files with 68 additions and 54 deletions
+9 -9
View File
@@ -8,7 +8,7 @@ import { projectContextKey, type useProjectData } from '../projects/context'
import type { ProjectDetail } from '../projects/types'
import type { Checkpoint } from '../workflows/types'
import type { BreakdownModule, EpisodePlan } from './types'
import { selectMenu } from '../../testing/naive'
import { drawerPanel, selectMenu } from '../../testing/naive'
let wrapper: VueWrapper | undefined
afterEach(() => {
@@ -147,7 +147,7 @@ describe('拆解页内容滚动', () => {
const provided = mountPage()
await wrapper!.get('[data-workspace-tools]').trigger('click')
await flushPromises()
const config = wrapper!.get('.breakdown-config')
const config = drawerPanel().get('.breakdown-config')
expect(config.get('label[for="group-size"]').text()).toBe('每组集数')
expect(config.get<HTMLInputElement>('#group-size').element.value).toBe('3')
expect(config.get('.breakdown-group-unit').text()).toBe('集 / 组')
@@ -165,7 +165,7 @@ describe('拆解页内容滚动', () => {
await checkbox.trigger('click')
}
expect(preview.element.disabled).toBe(true)
expect(wrapper!.text()).toContain('至少选择一个抽取模块')
expect(drawerPanel().text()).toContain('至少选择一个抽取模块')
await options[1]!.get('[role="checkbox"]').trigger('click')
expect(preview.element.disabled).toBe(false)
provided.data.value!.project.status = 'generating'
@@ -389,9 +389,9 @@ describe('拆解页内容滚动', () => {
history.scrollTop = 120
await wrapper!.get('[data-workspace-tools]').trigger('click')
await flushPromises()
expect(wrapper!.get('.workspace-tools-drawer').element.closest('.workspace-split')).toBeNull()
await wrapper!.get('#group-size').setValue('2')
await wrapper!.get('[aria-label="关闭操作面板"]').trigger('click')
expect(drawerPanel().element.closest('.workspace-split')).toBeNull()
await drawerPanel().get('#group-size').setValue('2')
await drawerPanel().get('[aria-label="关闭操作面板"]').trigger('click')
provided.data.value!.checkpoints = [checkpoint()]
await flushPromises()
expect(wrapper!.get('.breakdown-results-scroll .n-scrollbar-container').element).toBe(results)
@@ -404,7 +404,7 @@ describe('拆解页内容滚动', () => {
expect(history.scrollTop).toBe(120)
await wrapper!.get('[data-workspace-tools]').trigger('click')
await flushPromises()
expect(wrapper!.get<HTMLInputElement>('#group-size').element.value).toBe('2')
expect(drawerPanel().get<HTMLInputElement>('#group-size').element.value).toBe('2')
expect(fetcher).not.toHaveBeenCalled()
})
@@ -423,8 +423,8 @@ describe('拆解页内容滚动', () => {
expect(feedback.find('.breakdown-results-section').exists()).toBe(false)
await feedback.get('button').trigger('click')
await flushPromises()
expect(wrapper!.get('.workspace-tools-drawer').text()).toContain('缺少形态绑定')
expect(wrapper!.get('.workspace-tools-drawer').text()).toContain('重试失败抽取')
expect(drawerPanel().text()).toContain('缺少形态绑定')
expect(drawerPanel().text()).toContain('重试失败抽取')
})
it('没有正式剧集时保留可滚动的空状态,不显示拆解设置与结果', () => {
+21 -21
View File
@@ -28,7 +28,7 @@ import SubjectIdentityPage from '../subject-identity/SubjectIdentityPage.vue'
import { styleFixture, styleImageFixture } from '../visual-style/testing/fixtures'
import { identityFixture, identityImageFixture } from '../subject-identity/testing/fixtures'
import { getIdentitySession } from '../subject-identity/model'
import { expandSections, selectControl, selectMenu } from '../../testing/naive'
import { drawerPanel, expandSections, selectControl, selectMenu } from '../../testing/naive'
import ProductionPage from '../production/ProductionPage.vue'
import { getProductionSession } from '../production/model'
@@ -221,8 +221,8 @@ describe('内容级滚动下的生产反馈', () => {
}
await flushPromises()
expect(wrapper.get('[data-workspace-tools]').attributes('aria-expanded')).toBe('true')
expect(wrapper.find('.workspace-tools-drawer .n-collapse-item--active').exists()).toBe(true)
expect(wrapper.text()).toContain('供应商不可用')
expect(drawerPanel().find('.n-collapse-item--active').exists()).toBe(true)
expect(drawerPanel().text()).toContain('供应商不可用')
})
})
@@ -302,7 +302,7 @@ describe('视觉风格与主体身份工作区', () => {
})
vi.stubGlobal('fetch', fetcher)
await mountAssets('identity')
await wrapper!.get('[aria-label="关闭操作面板"]').trigger('click')
await drawerPanel().get('[aria-label="关闭操作面板"]').trigger('click')
await flushPromises()
const items = wrapper!.findAll('.identity-subject-item')
expect(items).toHaveLength(3)
@@ -592,9 +592,9 @@ describe('视觉风格与主体身份工作区', () => {
const post = fetcher.mock.calls.find(([, init]) => init?.method === 'POST')!
expect(post[0]).toBe('/api/projects/page-test-project/subject-identities/generate')
expect(JSON.parse(post[1]!.body as string)).toEqual({ force: false, concurrency: 3 })
expect(wrapper!.text()).toContain('本次存在部分失败')
expect(wrapper!.text()).toContain('含锁定 1')
expect(wrapper!.text()).toContain('文本模型超时')
expect(drawerPanel().text()).toContain('本次存在部分失败')
expect(drawerPanel().text()).toContain('含锁定 1')
expect(drawerPanel().text()).toContain('文本模型超时')
})
it('身份候选母版切换需确认,只发送正确 Subject ID 的 anchor PUT', async () => {
@@ -673,8 +673,8 @@ describe('视觉风格与主体身份工作区', () => {
})
vi.stubGlobal('fetch', fetcher)
await mountAssets('identity')
expect(wrapper!.get('.identity-tools-intro').text()).toContain('为同一个人物、场景或道具固定稳定特征')
const cards = wrapper!.get('[aria-label="角色选角进度"]').findAll('.casting-item')
expect(drawerPanel().get('.identity-tools-intro').text()).toContain('为同一个人物、场景或道具固定稳定特征')
const cards = drawerPanel().get('[aria-label="角色选角进度"]').findAll('.casting-item')
expect(cards).toHaveLength(2)
expect(cards[0]!.get('.casting-item-name').text()).toBe(longName)
expect(cards[0]!.get('.casting-item-ref').text()).toBe('@CH0001')
@@ -883,7 +883,7 @@ describe('工作台页面交互', () => {
)
vi.stubGlobal('fetch', fetcher)
await mountSubjectImages()
await wrapper!.get('[aria-label="关闭操作面板"]').trigger('click')
await drawerPanel().get('[aria-label="关闭操作面板"]').trigger('click')
const card = wrapper!.get('.form-image-card')
expect(card.getComponent(NImage).props()).toMatchObject({ objectFit: 'cover', previewDisabled: false })
await card.get('img').trigger('click')
@@ -951,11 +951,11 @@ describe('工作台页面交互', () => {
await mountSubjectImages()
await wrapper!.get('[aria-label="搜索形态图片"]').setValue('@CH0001')
await confirmGeneration('补齐项目主参考图')
expect(wrapper!.get('[aria-label="生图批量回执"]').text()).toContain('部分形态生图失败')
expect(wrapper!.text()).toContain('服务暂不可用')
expect(drawerPanel().get('[aria-label="生图批量回执"]').text()).toContain('部分形态生图失败')
expect(drawerPanel().text()).toContain('服务暂不可用')
const post = fetcher.mock.calls.find(([, init]) => init?.method === 'POST')!
expect(JSON.parse(post[1]!.body as string)).toEqual({ concurrency: 2, force: false })
await wrapper!.get('.n-collapse [role="checkbox"]').trigger('click')
await drawerPanel().get('.n-collapse [role="checkbox"]').trigger('click')
await confirmGeneration('为全项目新增候选图')
const lastPost = fetcher.mock.calls.filter(([, init]) => init?.method === 'POST').at(-1)!
expect(JSON.parse(lastPost[1]!.body as string).force).toBe(true)
@@ -1109,7 +1109,7 @@ describe('工作台页面交互', () => {
await flushPromises()
await confirmGeneration('生成本集导演设计')
expect(button('补齐项目导演设计').disabled).toBe(true)
await wrapper!.get('[aria-label="关闭操作面板"]').trigger('click')
await drawerPanel().get('[aria-label="关闭操作面板"]').trigger('click')
await flushPromises()
expect(wrapper!.get('[data-workspace-tools]').attributes('aria-expanded')).toBe('false')
expect(getOperation(fixture.id).pending).toBe(true)
@@ -1169,12 +1169,12 @@ describe('工作台页面交互', () => {
button('刷新分镜').click()
await flushPromises()
expect(button('生成本集即时状态').disabled).toBe(false)
await wrapper!.get('#storyboard-repairs').setValue('0')
await drawerPanel().get('#storyboard-repairs').setValue('0')
await confirmGeneration('生成本集即时状态')
const post = fetcher.mock.calls.find(([, init]) => init?.method === 'POST')!
expect(JSON.parse(post[1]!.body as string)).toEqual({ episodeNo: 1, persist: true, maxRepairAttempts: 0 })
expect(wrapper!.text()).toContain('校验失败,未保存本次生成结果')
expect(wrapper!.text()).toContain('缺少主体状态')
expect(drawerPanel().text()).toContain('校验失败,未保存本次生成结果')
expect(drawerPanel().text()).toContain('缺少主体状态')
})
it('批量 200 部分失败不显示全成功,默认补齐与显式覆盖参数独立', async () => {
@@ -1216,9 +1216,9 @@ describe('工作台页面交互', () => {
await mountStoryboard()
await flushPromises()
await confirmGeneration('补齐项目导演设计')
expect(wrapper!.get('[aria-label="生成回执"] [role="alert"]').text()).toContain('存在失败')
expect(wrapper!.text()).toContain('模型校验失败')
await wrapper!.get('[role="checkbox"]').trigger('click')
expect(drawerPanel().get('[aria-label="生成回执"] [role="alert"]').text()).toContain('存在失败')
expect(drawerPanel().text()).toContain('模型校验失败')
await drawerPanel().get('[role="checkbox"]').trigger('click')
await confirmGeneration('重生成全部导演设计')
const posts = fetcher.mock.calls.filter(([, init]) => init?.method === 'POST')
expect(posts.map(([, init]) => JSON.parse(init!.body as string))).toEqual([
@@ -1415,7 +1415,7 @@ describe('工作台页面交互', () => {
button('预览分组').click()
await flushPromises()
expect(button('开始拆解').disabled).toBe(false)
await wrapper.get('#group-size').setValue('2')
await drawerPanel().get('#group-size').setValue('2')
expect(document.body.textContent).not.toContain('开始拆解')
button('预览分组').click()
await flushPromises()