From a9a5fba92bd82d0a7233c9946116ccf85ea8769c Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Sat, 12 Sep 2026 20:49:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20PR=20#316=20review?= =?UTF-8?q?=EF=BC=88=E5=89=8D=E7=AB=AF=20TS/TSX=EF=BC=89=EF=BC=9A=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=BC=96=E8=BE=91=E5=99=A8=E7=B4=A0=E6=9D=90=E5=BC=B9?= =?UTF-8?q?=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ImageCanvasProjectAssetPickerDialog.tsx:打开时的重置 effect 只依赖 `open`,父级每次渲染重建 `selectedAssetIds` 不再清空进行中的搜索 / 筛选 / 选择 - ImageCanvasProjectAssetPickerDialog.tsx:素材卡媒体渲染抽成 `AssetCardMedia`,顺带去掉该处嵌套三元 - projectAssetReferencePickerModel.ts:`image-sequence` 单列一类(新增「序列帧」页签),不再混进「图片」——参考图链路只接受 `mediaType === 'image'`,混进去就是「按图片选中、按图片文案拒掉」;缩略图口径由 `projectAssetPickerUsesThumbnail` 收口 - 用例:父级重渲染不清空在选状态;序列帧分类归属与其被参考图链路过滤掉的事实 --- ...ageCanvasProjectAssetPickerDialog.test.tsx | 53 ++++++++++++++++++ .../ImageCanvasProjectAssetPickerDialog.tsx | 56 ++++++++++++++----- .../projectAssetReferencePickerModel.test.ts | 53 +++++++++++++++++- .../projectAssetReferencePickerModel.ts | 26 ++++++++- 4 files changed, 170 insertions(+), 18 deletions(-) diff --git a/src/components/image-editor/ImageCanvasProjectAssetPickerDialog.test.tsx b/src/components/image-editor/ImageCanvasProjectAssetPickerDialog.test.tsx index 5d588db1b..cde2b12c7 100644 --- a/src/components/image-editor/ImageCanvasProjectAssetPickerDialog.test.tsx +++ b/src/components/image-editor/ImageCanvasProjectAssetPickerDialog.test.tsx @@ -173,6 +173,59 @@ describe('ImageCanvasProjectAssetPickerDialog', () => { expect(screen.getByText('已选 1 个')).toBeTruthy(); }); + /** + * 弹窗里的搜索 / 分类 / 在选中的选择是用户正在做的工作,不能被父级的一次普通重渲染清掉。 + * + * 调用方(`useImageCanvasGenerationSurface`)每次渲染都会重算 `selectedAssetIds`, + * 把它的身份放进重置 effect 的依赖里,就等于「父级一渲染就清空」。 + * + * 变异验证:把 `selectedAssetIds` 加回 effect 依赖,本用例必须失败。 + */ + it('keeps the in-progress search and selection across parent re-renders', () => { + const { rerender } = render( + {}} + onConfirm={() => {}} + />, + ); + + fireEvent.change(screen.getByLabelText('搜索参考图素材'), { + target: { value: '主角' }, + }); + fireEvent.click(screen.getByRole('option', { name: '选择参考图主角立绘' })); + expect(screen.getByText('已选 1 个')).toBeTruthy(); + expect( + screen.queryByRole('option', { name: '选择参考图小镇背景' }), + ).toBeNull(); + + // 父级重渲染:`selectedAssetIds` 换了一个新数组身份,内容不变。 + rerender( + {}} + onConfirm={() => {}} + />, + ); + + expect( + (screen.getByLabelText('搜索参考图素材') as HTMLInputElement).value, + ).toBe('主角'); + expect(screen.getByText('已选 1 个')).toBeTruthy(); + expect( + screen + .getByRole('option', { name: '选择参考图主角立绘' }) + .getAttribute('aria-selected'), + ).toBe('true'); + expect( + screen.queryByRole('option', { name: '选择参考图小镇背景' }), + ).toBeNull(); + }); + it('shows an empty state when the project has no registered assets', () => { render(