生成帧完成后自动刷新项目封面

- 项目库生成帧任务入队后继续轮询任务进度,解析成功后重新拉取项目列表和当前项目对象。

- 成功后显示视频帧生成完成提示,并让后端写入的 thumbnail_url 立即刷新到项目卡片封面。

- 补充 ProjectLibrary 回归测试,覆盖生成帧完成后自动显示新封面。

- 更新前端审计、设计冻结、测试计划、状态机和项目指南文档。
This commit is contained in:
2026-05-04 05:07:22 +08:00
parent 85de1ffbb2
commit 02635abab1
7 changed files with 92 additions and 12 deletions

View File

@@ -134,8 +134,10 @@ describe('ProjectLibrary', () => {
it('generates frames from an imported video with the selected FPS', async () => {
apiMock.getProjects
.mockResolvedValueOnce([{ id: 'p4', name: 'clip.mp4', status: 'pending', frames: 0, video_path: 'uploads/clip.mp4', parse_fps: 30 }])
.mockResolvedValueOnce([{ id: 'p4', name: 'clip.mp4', status: 'parsing', frames: 0, video_path: 'uploads/clip.mp4', parse_fps: 12 }]);
.mockResolvedValueOnce([{ id: 'p4', name: 'clip.mp4', status: 'parsing', frames: 0, video_path: 'uploads/clip.mp4', parse_fps: 12 }])
.mockResolvedValueOnce([{ id: 'p4', name: 'clip.mp4', status: 'ready', frames: 24, video_path: 'uploads/clip.mp4', parse_fps: 12, thumbnail_url: 'http://thumb/frame.jpg' }]);
apiMock.parseMedia.mockResolvedValueOnce({ id: 22, status: 'queued', progress: 0 });
apiMock.getTask.mockResolvedValueOnce({ id: 22, status: 'success', progress: 100, message: '解析完成' });
const { container } = render(<ProjectLibrary onProjectSelect={vi.fn()} />);
@@ -146,6 +148,11 @@ describe('ProjectLibrary', () => {
await waitFor(() => expect(apiMock.parseMedia).toHaveBeenCalledWith('p4', { parseFps: 12 }));
expect(await screen.findByRole('status')).toHaveTextContent('生成帧任务已入队 #22');
expect(await screen.findByText('12FPS')).toBeInTheDocument();
expect(screen.getByText('正在生成视频帧')).toBeInTheDocument();
await waitFor(() => expect(apiMock.getTask).toHaveBeenCalledWith(22), { timeout: 2500 });
expect(await screen.findByAltText('clip.mp4')).toHaveAttribute('src', 'http://thumb/frame.jpg');
expect(await screen.findByRole('status')).toHaveTextContent('视频帧生成完成,项目封面已自动更新');
});
it('hides frame generation while editing a project name', async () => {