修复分离传播结果联动高亮

- 将 propagation_seed_signature 纳入传播链选择 token
- 修复合并后的分离 mask 传播到同一帧后点击一个片段另一个不联动高亮的问题
- 同步 VideoWorkspace 的传播链 token 逻辑,保持删除和清空链路一致
- 补充 CanvasArea 回归测试,覆盖同 seed signature 的分离传播片段联动选中
- 更新项目指南和设计冻结文档中的联动规则
This commit is contained in:
2026-05-04 01:32:18 +08:00
parent 45839a2e4c
commit a680510db8
5 changed files with 50 additions and 2 deletions

View File

@@ -466,6 +466,48 @@ describe('CanvasArea', () => {
expect(screen.getByText('当前图层: 胆囊 #21')).toBeInTheDocument();
});
it('selects all separated propagated pieces with the same seed signature on the frame', () => {
useStore.setState({
maskPreviewOpacity: 35,
masks: [
{
id: 'annotation-20',
annotationId: '20',
frameId: 'frame-1',
pathData: 'M 10 10 L 30 10 L 30 30 Z',
label: 'Merged object',
color: '#facc15',
segmentation: [[10, 10, 30, 10, 30, 30]],
metadata: {
source: 'sam2.1_hiera_tiny_propagation',
propagated_from_frame_id: 'seed-frame',
propagation_seed_signature: 'merged-seed-signature',
},
},
{
id: 'annotation-21',
annotationId: '21',
frameId: 'frame-1',
pathData: 'M 80 80 L 100 80 L 100 100 Z',
label: 'Merged object',
color: '#facc15',
segmentation: [[80, 80, 100, 80, 100, 100]],
metadata: {
source: 'sam2.1_hiera_tiny_propagation',
propagated_from_frame_id: 'seed-frame',
propagation_seed_signature: 'merged-seed-signature',
},
},
],
});
render(<CanvasArea activeTool="edit_polygon" frame={frame} />);
fireEvent.click(screen.getAllByTestId('konva-path')[0]);
expect(useStore.getState().selectedMaskIds).toEqual(['annotation-20', 'annotation-21']);
expect(screen.getAllByTestId('konva-group').map((group) => group.getAttribute('data-opacity'))).toEqual(['0.5', '0.5']);
});
it('does not render stored GT seed points as visible editable handles', () => {
useStore.setState({
masks: [

View File

@@ -89,6 +89,9 @@ function propagationLineageTokens(mask: Mask): Set<string> {
if (typeof metadata.propagation_seed_key === 'string' && metadata.propagation_seed_key.length > 0) {
tokens.add(`seed-key:${metadata.propagation_seed_key}`);
}
if (typeof metadata.propagation_seed_signature === 'string' && metadata.propagation_seed_signature.length > 0) {
tokens.add(`seed-signature:${metadata.propagation_seed_signature}`);
}
return tokens;
}

View File

@@ -292,6 +292,9 @@ const propagationLineageTokens = (mask: Mask): Set<string> => {
if (typeof metadata.propagation_seed_key === 'string' && metadata.propagation_seed_key.length > 0) {
tokens.add(`seed-key:${metadata.propagation_seed_key}`);
}
if (typeof metadata.propagation_seed_signature === 'string' && metadata.propagation_seed_signature.length > 0) {
tokens.add(`seed-signature:${metadata.propagation_seed_signature}`);
}
return tokens;
};