diff --git a/packages/designer/jest.config.js b/packages/designer/jest.config.js index 82c76fad8..1ecebd938 100644 --- a/packages/designer/jest.config.js +++ b/packages/designer/jest.config.js @@ -19,6 +19,7 @@ const jestConfig = { // testMatch: ['**/setting-field.test.ts'], // testMatch: ['**/node.test.ts'], // testMatch: ['**/builtin-hotkey.test.ts'], + // testMatch: ['**/selection.test.ts'], transformIgnorePatterns: [ `/node_modules/(?!${esModules})/`, ], diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 456595b04..b0e509bce 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -159,6 +159,9 @@ export interface IBaseNode return !!this.getExtraProp('isLocked')?.getValue(); } + canSelect(): boolean { + const onSelectHook = this.componentMeta?.advanced?.callbacks?.onSelectHook; + const canSelect = typeof onSelectHook === 'function' ? onSelectHook(this.internalToShellNode()!) : true; + return canSelect; + } + /** * 选择当前节点 */ diff --git a/packages/designer/src/document/selection.ts b/packages/designer/src/document/selection.ts index 93ec04ffe..6147e188d 100644 --- a/packages/designer/src/document/selection.ts +++ b/packages/designer/src/document/selection.ts @@ -32,6 +32,12 @@ export class Selection implements ISelection { return; } + const node = this.doc.getNode(id); + + if (!node?.canSelect()) { + return; + } + this._selected = [id]; this.emitter.emit('selectionchange', this._selected); } @@ -40,7 +46,18 @@ export class Selection implements ISelection { * 批量选中 */ selectAll(ids: string[]) { - this._selected = ids; + const selectIds: string[] = []; + + ids.forEach(d => { + const node = this.doc.getNode(d); + + if (node?.canSelect()) { + selectIds.push(d); + } + }); + + this._selected = selectIds; + this.emitter.emit('selectionchange', this._selected); } diff --git a/packages/designer/tests/document/selection.test.ts b/packages/designer/tests/document/selection.test.ts index b8b5ad434..0af22b5ce 100644 --- a/packages/designer/tests/document/selection.test.ts +++ b/packages/designer/tests/document/selection.test.ts @@ -122,7 +122,7 @@ describe('选择区测试', () => { selectionChangeHandler.mockClear(); }); - it('dispose 方法', () => { + it('selectAll 包含不存在的 id', () => { const project = new Project(designer, { componentsTree: [ formSchema, @@ -135,14 +135,7 @@ describe('选择区测试', () => { selection.selectAll(['form', 'node_k1ow3cbj', 'form2']); - const selectionChangeHandler = jest.fn(); - selection.onSelectionChange(selectionChangeHandler); - selection.dispose(); - - expect(selectionChangeHandler).toHaveBeenCalledTimes(1); - expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form', 'node_k1ow3cbj']); expect(selection.selected).toEqual(['form', 'node_k1ow3cbj']); - selectionChangeHandler.mockClear(); }); it('dispose 方法 - 选中的节点没有被删除的', () => { diff --git a/packages/types/src/shell/type/metadata.ts b/packages/types/src/shell/type/metadata.ts index 3122ab7d7..573be1689 100644 --- a/packages/types/src/shell/type/metadata.ts +++ b/packages/types/src/shell/type/metadata.ts @@ -195,6 +195,9 @@ export interface IPublicTypeCallbacks { onMoveHook?: (currentNode: IPublicModelNode) => boolean; // thinkof 限制性拖拽 onHoverHook?: (currentNode: IPublicModelNode) => boolean; + + /** 选中 hook,如果返回值是 false,可以控制组件不可被选中 */ + onSelectHook?: (currentNode: IPublicModelNode) => boolean; onChildMoveHook?: (childNode: IPublicModelNode, currentNode: IPublicModelNode) => boolean; // events