feat: 补齐前端主流程并收紧工作台布局
统一工作台紧凑头部与形态图库间距,修复主体身份布局,并接入正式严格视频质量流水线。
This commit is contained in:
@@ -99,12 +99,19 @@ describe('镜头生产数据契约', () => {
|
||||
})
|
||||
vi.stubGlobal('fetch', fetcher)
|
||||
await productionApi.videoReadiness('project/1', true)
|
||||
await productionApi.generateVideos('project/1', { concurrency: 3, force: true })
|
||||
await productionApi.generateQualityVideos('project/1', {
|
||||
concurrency: 3,
|
||||
force: true,
|
||||
limit: 2,
|
||||
maxRepairAttempts: 2
|
||||
})
|
||||
expect(fetcher.mock.calls[0]?.[0]).toBe('/api/projects/project%2F1/videos/readiness?force=true')
|
||||
expect(fetcher.mock.calls[1]?.[0]).toBe('/api/projects/project%2F1/videos/generate')
|
||||
expect(fetcher.mock.calls[1]?.[0]).toBe('/api/projects/project%2F1/videos/generate-quality')
|
||||
expect(JSON.parse(String(fetcher.mock.calls[1]?.[1]?.body))).toEqual({
|
||||
concurrency: 3,
|
||||
force: true
|
||||
force: true,
|
||||
limit: 2,
|
||||
maxRepairAttempts: 2
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ describe('过期首帧到具体素材定位', () => {
|
||||
|
||||
it('切换镜头时筛选、关联说明和图片共用稳定纵向容器,长关联列表单独横向滚动', async () => {
|
||||
const { keyframes, videos, references, fetcher } = await gallery('?sourceShotId=shot-target')
|
||||
expect(wrapper!.find('.workspace-heading-scroll').exists()).toBe(false)
|
||||
expect(wrapper!.find('.workspace-heading-scroll').exists()).toBe(true)
|
||||
const scroll = wrapper!.get<HTMLElement>('.workspace-scroll > .n-scrollbar-container').element
|
||||
const content = wrapper!.get('.workspace-scroll-content').element
|
||||
const sticky = wrapper!.get('.gallery-sticky-controls').element
|
||||
|
||||
@@ -1111,7 +1111,7 @@ describe('工作台页面交互', () => {
|
||||
vi.stubGlobal('fetch', fetcher)
|
||||
await mountStoryboard()
|
||||
await flushPromises()
|
||||
await confirmGeneration('生成本集导演设计')
|
||||
await confirmGeneration('补齐项目导演设计')
|
||||
expect(button('补齐项目导演设计').disabled).toBe(true)
|
||||
await drawerPanel().get('[aria-label="关闭操作面板"]').trigger('click')
|
||||
await flushPromises()
|
||||
@@ -1123,61 +1123,69 @@ describe('工作台页面交互', () => {
|
||||
wrapper = undefined
|
||||
finish(
|
||||
new Response(
|
||||
'{"data":{"episodeNo":1,"direction":{"episodeNo":1,"beatDirections":[]},"validation":{"valid":true,"issues":[]}}}'
|
||||
`{"data":{"projectId":"${fixture.id}","episodeCount":2,"completedEpisodes":1,"skippedEpisodes":1,"failedEpisodes":0,"shotCount":4,"directionCount":4,"coverage":1,"episodes":[]}}`
|
||||
)
|
||||
)
|
||||
await flushPromises()
|
||||
expect(getStoryboardSession(fixture.id).receipt).toMatchObject({
|
||||
kind: 'direction',
|
||||
episodeNo: 1,
|
||||
title: '第 1 集导演设计'
|
||||
kind: 'batch',
|
||||
title: '项目导演设计'
|
||||
})
|
||||
expect(getOperation(fixture.id).pending).toBe(false)
|
||||
const posts = fetcher.mock.calls.filter(([, init]) => init?.method === 'POST')
|
||||
expect(posts).toHaveLength(1)
|
||||
expect(JSON.parse(posts[0]![1]!.body as string)).toEqual({ episodeNo: 1, persist: true })
|
||||
expect(JSON.parse(posts[0]![1]!.body as string)).toEqual({ concurrency: 2, force: false })
|
||||
})
|
||||
|
||||
it('分镜必须先补齐导演设计,校验失败显示未保存,修复次数 0 不被默认值覆盖', async () => {
|
||||
let complete = false
|
||||
it('分镜只提供正式项目生成,逐集失败回执保留零次修复参数', async () => {
|
||||
const fetcher = vi.fn<typeof fetch>().mockImplementation(async (url, init) => {
|
||||
if (init?.method === 'POST')
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
data: {
|
||||
episodeNo: 1,
|
||||
visualState: {},
|
||||
validation: {
|
||||
valid: false,
|
||||
issues: [{ episodeNo: 1, beatNo: 1, shotNo: 1, message: '缺少主体状态' }]
|
||||
},
|
||||
repaired: false,
|
||||
repairAttempts: 0,
|
||||
remainingIssues: [],
|
||||
persisted: false
|
||||
projectId: fixture.id,
|
||||
episodeCount: 1,
|
||||
completedEpisodes: 0,
|
||||
skippedEpisodes: 0,
|
||||
failedEpisodes: 1,
|
||||
shotCount: 2,
|
||||
visualStateCount: 0,
|
||||
coverage: 0,
|
||||
episodes: [
|
||||
{
|
||||
episodeNo: 1,
|
||||
status: 'failed',
|
||||
shotCount: 2,
|
||||
visualStateCount: 0,
|
||||
repairAttempts: 0,
|
||||
error: '缺少主体状态'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
)
|
||||
const result = String(url).includes('storyboard-directions')
|
||||
? directionsResult(fixture.id, 1, complete)
|
||||
? directionsResult(fixture.id, 1, true)
|
||||
: visualStatesResult(fixture.id)
|
||||
return new Response(JSON.stringify({ data: result }))
|
||||
})
|
||||
vi.stubGlobal('fetch', fetcher)
|
||||
await mountStoryboard()
|
||||
await flushPromises()
|
||||
expect(button('生成本集导演设计').disabled).toBe(false)
|
||||
expect(button('生成本集即时状态').disabled).toBe(true)
|
||||
expect(wrapper!.text()).not.toContain('生成本集导演设计')
|
||||
expect(wrapper!.text()).not.toContain('生成本集即时状态')
|
||||
expect(button('补齐项目导演设计').disabled).toBe(false)
|
||||
expect(button('补齐项目即时状态').disabled).toBe(false)
|
||||
expect(fetcher.mock.calls.every(([, init]) => init?.method !== 'POST')).toBe(true)
|
||||
complete = true
|
||||
button('刷新分镜').click()
|
||||
await flushPromises()
|
||||
expect(button('生成本集即时状态').disabled).toBe(false)
|
||||
await drawerPanel().get('#storyboard-repairs').setValue('0')
|
||||
await confirmGeneration('生成本集即时状态')
|
||||
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(drawerPanel().text()).toContain('校验失败,未保存本次生成结果')
|
||||
expect(JSON.parse(post[1]!.body as string)).toEqual({
|
||||
concurrency: 2,
|
||||
force: false,
|
||||
maxRepairAttempts: 0
|
||||
})
|
||||
expect(drawerPanel().text()).toContain('本次存在失败')
|
||||
expect(drawerPanel().text()).toContain('缺少主体状态')
|
||||
})
|
||||
|
||||
@@ -1291,11 +1299,11 @@ describe('工作台页面交互', () => {
|
||||
await flushPromises()
|
||||
expect(wrapper!.text()).toContain('shot-db-1-1')
|
||||
expect(wrapper!.text()).toContain('数据库暂不可用')
|
||||
expect(button('生成本集导演设计').disabled).toBe(true)
|
||||
expect(button('补齐项目导演设计').disabled).toBe(true)
|
||||
fail = false
|
||||
button('重试查询').click()
|
||||
await flushPromises()
|
||||
expect(button('生成本集导演设计').disabled).toBe(false)
|
||||
expect(button('补齐项目导演设计').disabled).toBe(false)
|
||||
})
|
||||
|
||||
it('镜头工具按需 GET,切换镜头会废弃旧参考图,未完成设计不能编译规格', async () => {
|
||||
|
||||
Reference in New Issue
Block a user