From 3b645d270daa8deeef22f66985eec89bdc79fa31 Mon Sep 17 00:00:00 2001 From: "lihao.ylh" Date: Fri, 17 Sep 2021 20:48:01 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=88=9B=E5=BB=BA=20doc=20=E6=97=B6=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E5=BC=8F=E8=8E=B7=E5=8F=96=20schema=20?= =?UTF-8?q?=E7=9A=84=E6=AC=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/designer/jest.config.js | 2 +- packages/designer/src/document/history.ts | 17 +-- .../src/document/node/modal-nodes-manager.ts | 2 +- packages/designer/src/document/node/node.ts | 14 ++ .../tests/designer/builtin-hotkey.test.ts | 6 + .../__snapshots__/document-model.test.ts.snap | 134 ++++++++++++++++++ .../document-model/document-model.test.ts | 6 + .../designer/tests/document/node/node.test.ts | 2 +- packages/vision-polyfill/src/pages.ts | 6 +- 9 files changed, 172 insertions(+), 17 deletions(-) diff --git a/packages/designer/jest.config.js b/packages/designer/jest.config.js index 6e872af60..553eeb33f 100644 --- a/packages/designer/jest.config.js +++ b/packages/designer/jest.config.js @@ -6,7 +6,7 @@ module.exports = { // // '^.+\\.(ts|tsx)$': 'ts-jest', // // '^.+\\.(js|jsx)$': 'babel-jest', // }, - // testMatch: ['**/prop.test.ts'], + // testMatch: ['**/builtin-hotkey.test.ts'], // testMatch: ['(/tests?/.*(test))\\.[jt]s$'], transformIgnorePatterns: [ `/node_modules/(?!${esModules})/`, diff --git a/packages/designer/src/document/history.ts b/packages/designer/src/document/history.ts index 401075a63..ef25dfb92 100644 --- a/packages/designer/src/document/history.ts +++ b/packages/designer/src/document/history.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'events'; -import { autorun, Reaction, untracked, globalContext, Editor } from '@ali/lowcode-editor-core'; +import { autorun, reaction, mobx, untracked, globalContext, Editor } from '@ali/lowcode-editor-core'; import { NodeSchema } from '@ali/lowcode-types'; // TODO: cache to localStorage @@ -37,17 +37,12 @@ export class History { this.session = new Session(0, null, this.timeGap); this.records = [this.session]; - autorun(() => { + reaction(() => { + return logger(); + }, (data) => { if (this.asleep) return; - const data = logger(); - untracked(() => { const log = currentSerialization.serialize(data); - if (this.session.cursor === 0 && this.session.isActive()) { - // first log - this.session.log(log); - this.session.end(); - } else if (this.session) { if (this.session.isActive()) { this.session.log(log); } else { @@ -62,9 +57,9 @@ export class History { this.emitter.emit('statechange', currentState); } } - } + // } }); - }); + }, { fireImmediately: true }); } get hotData() { diff --git a/packages/designer/src/document/node/modal-nodes-manager.ts b/packages/designer/src/document/node/modal-nodes-manager.ts index e2c459521..584b72237 100644 --- a/packages/designer/src/document/node/modal-nodes-manager.ts +++ b/packages/designer/src/document/node/modal-nodes-manager.ts @@ -122,7 +122,7 @@ export class ModalNodesManager { } private setNodes() { - const nodes = getModalNodes(this.page.getRoot()); + const nodes = getModalNodes(this.page.getRoot()!); this.modalNodes = nodes; this.modalNodes.forEach((node: Node) => { this.addNodeEvent(node); diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 08d59ae51..dbcb1b335 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -179,6 +179,8 @@ export class Node { this.setupAutoruns(); } + this.initBuiltinProps(); + this.isInited = true; this.emitter = new EventEmitter(); } @@ -191,6 +193,18 @@ export class Node { return this._settingEntry; } + /** + * 节点初始化期间就把内置的一些 prop 初始化好,避免后续不断构造实例导致 reaction 执行多次 + */ + private initBuiltinProps() { + this.props.has(getConvertedExtraKey('hidden')) || this.props.add(false, getConvertedExtraKey('hidden')); + this.props.has(getConvertedExtraKey('title')) || this.props.add('', getConvertedExtraKey('title')); + this.props.has(getConvertedExtraKey('isLocked')) || this.props.add(false, getConvertedExtraKey('isLocked')); + this.props.has(getConvertedExtraKey('condition')) || this.props.add(true, getConvertedExtraKey('condition')); + this.props.has(getConvertedExtraKey('conditionGroup')) || this.props.add('', getConvertedExtraKey('conditionGroup')); + this.props.has(getConvertedExtraKey('loop')) || this.props.add(undefined, getConvertedExtraKey('loop')); + } + private initProps(props: any): any { return this.document.designer.transformProps(props, this, TransformStage.Init); } diff --git a/packages/designer/tests/designer/builtin-hotkey.test.ts b/packages/designer/tests/designer/builtin-hotkey.test.ts index 493aa5546..ce89af276 100644 --- a/packages/designer/tests/designer/builtin-hotkey.test.ts +++ b/packages/designer/tests/designer/builtin-hotkey.test.ts @@ -102,6 +102,9 @@ describe('快捷键测试', () => { const firstButtonNode = designer.currentDocument?.getNode('node_k1ow3cbn')!; let secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!; + // 等待第一个 session 结束 + await new Promise(resolve => setTimeout(resolve, 1000)); + firstButtonNode.remove(); expect(secondButtonNode.getParent()?.children.size).toBe(1); @@ -119,6 +122,9 @@ describe('快捷键测试', () => { const firstButtonNode = designer.currentDocument?.getNode('node_k1ow3cbn')!; let secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!; + // 等待第一个 session 结束 + await new Promise(resolve => setTimeout(resolve, 1000)); + firstButtonNode.remove(); expect(secondButtonNode.getParent()?.children.size).toBe(1); diff --git a/packages/designer/tests/document/document-model/__snapshots__/document-model.test.ts.snap b/packages/designer/tests/document/document-model/__snapshots__/document-model.test.ts.snap index 49bcbba08..dd31db7de 100644 --- a/packages/designer/tests/document/document-model/__snapshots__/document-model.test.ts.snap +++ b/packages/designer/tests/document/document-model/__snapshots__/document-model.test.ts.snap @@ -68,7 +68,11 @@ Object { Object { "componentName": "PageHeader", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbd", + "isLocked": false, + "loop": undefined, "props": Object { "__slot__action": false, "__slot__content": false, @@ -108,12 +112,18 @@ Object { ], }, }, + "title": "", }, ], "componentName": "RootHeader", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cba", + "isLocked": false, + "loop": undefined, "props": Object {}, + "title": "", }, Object { "children": Array [ @@ -130,7 +140,11 @@ Object { Object { "componentName": "TextField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbz", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -200,11 +214,16 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, Object { "componentName": "TextField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc1", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -270,11 +289,16 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, Object { "componentName": "TextField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc3", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -340,23 +364,33 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, ], "componentName": "Column", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbx", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": Object {}, "colSpan": "", "fieldId": "column_k1p1bnjm", }, + "title": "", }, Object { "children": Array [ Object { "componentName": "TextField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc2", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -422,11 +456,16 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, Object { "componentName": "SelectField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc0", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -512,21 +551,31 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, ], "componentName": "Column", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cby", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": Object {}, "colSpan": "", "fieldId": "column_k1p1bnjn", }, + "title": "", }, ], "componentName": "ColumnsLayout", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbw", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": Object {}, "columnGap": "20", @@ -534,17 +583,27 @@ Object { "layout": "6:6", "rowGap": 0, }, + "title": "", }, ], "componentName": "CardContent", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbk", + "isLocked": false, + "loop": undefined, "props": Object {}, + "title": "", }, ], "componentName": "Card", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbj", + "isLocked": false, + "loop": undefined, "props": Object { "__slot__extra": false, "__slot__subTitle": false, @@ -576,6 +635,7 @@ Object { "zh_CN": "基本信息", }, }, + "title": "", }, Object { "children": Array [ @@ -584,7 +644,11 @@ Object { Object { "componentName": "TextField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc4", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -650,6 +714,7 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, Object { "children": Array [ @@ -658,7 +723,11 @@ Object { Object { "componentName": "TextField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc8", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -724,23 +793,33 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, ], "componentName": "Column", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc6", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": Object {}, "colSpan": "", "fieldId": "column_k1p1bnjo", }, + "title": "", }, Object { "children": Array [ Object { "componentName": "TextField", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc9", + "isLocked": false, + "loop": undefined, "props": Object { "__category__": "form", "__style__": Object {}, @@ -806,21 +885,31 @@ Object { "wrapperColOffset": 0, "wrapperColSpan": 0, }, + "title": "", }, ], "componentName": "Column", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc7", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": Object {}, "colSpan": "", "fieldId": "column_k1p1bnjp", }, + "title": "", }, ], "componentName": "ColumnsLayout", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cc5", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": Object {}, "columnGap": "20", @@ -828,17 +917,27 @@ Object { "layout": "6:6", "rowGap": 0, }, + "title": "", }, ], "componentName": "CardContent", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbm", + "isLocked": false, + "loop": undefined, "props": Object {}, + "title": "", }, ], "componentName": "Card", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbl", + "isLocked": false, + "loop": undefined, "props": Object { "__slot__extra": false, "__slot__subTitle": false, @@ -870,13 +969,18 @@ Object { "zh_CN": "部门信息", }, }, + "title": "", }, Object { "children": Array [ Object { "componentName": "Button", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbn", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": ":root { margin-right: 16px; @@ -912,11 +1016,16 @@ Object { "triggerEventsWhenLoading": false, "type": "primary", }, + "title": "", }, Object { "componentName": "Button", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbp", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": ":root { width: 80px; @@ -945,11 +1054,16 @@ Object { "triggerEventsWhenLoading": false, "type": "normal", }, + "title": "", }, ], "componentName": "Div", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbo", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": ":root { display: flex; @@ -965,12 +1079,17 @@ Object { "fieldId": "div_k1ow3h1o", "useFieldIdAsDomId": false, }, + "title": "", }, ], "componentName": "Form", "condition": true, + "conditionGroup": "", "extraPropA": "extraPropA", + "hidden": false, "id": "form", + "isLocked": false, + "loop": undefined, "props": Object { "__style__": Object {}, "autoUnmount": true, @@ -992,26 +1111,38 @@ Object { "size": "medium", "slotA": "", }, + "title": "", }, ], "componentName": "RootContent", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbb", + "isLocked": false, + "loop": undefined, "props": Object { "contentBgColor": "transparent", "contentMargin": "20", "contentPadding": "0", }, + "title": "", }, Object { "componentName": "RootFooter", "condition": true, + "conditionGroup": "", + "hidden": false, "id": "node_k1ow3cbc", + "isLocked": false, + "loop": undefined, "props": Object {}, + "title": "", }, ], "componentName": "Page", "condition": true, + "conditionGroup": "", "css": "body{background-color:#f2f3f5}.card_kgaqfbm5 { margin-bottom: 12px; }.card_kgaqfbm6 { @@ -1042,7 +1173,9 @@ Object { "online": Array [], "sync": true, }, + "hidden": false, "id": "page", + "isLocked": false, "lifeCycles": Object { "constructor": Object { "compiled": "function constructor() { @@ -1070,6 +1203,7 @@ Object.keys(module.exports).forEach(function(item) { "type": "js", }, }, + "loop": undefined, "methods": Object { "__initMethods__": Object { "compiled": "function (exports, module) { /*set actions code here*/ }", diff --git a/packages/designer/tests/document/document-model/document-model.test.ts b/packages/designer/tests/document/document-model/document-model.test.ts index d4515aa2d..9f895c87a 100644 --- a/packages/designer/tests/document/document-model/document-model.test.ts +++ b/packages/designer/tests/document/document-model/document-model.test.ts @@ -32,6 +32,12 @@ describe('document-model 测试', () => { expect(doc.isBlank()).toBeFalsy(); expect(doc.schema).toEqual({ componentName: 'Page', + condition: true, + conditionGroup: '', + hidden: false, + isLocked: false, + loop: undefined, + title: '', id: 'root', fileName: '', props: {}, diff --git a/packages/designer/tests/document/node/node.test.ts b/packages/designer/tests/document/node/node.test.ts index ae6d61f46..18f40e215 100644 --- a/packages/designer/tests/document/node/node.test.ts +++ b/packages/designer/tests/document/node/node.test.ts @@ -249,7 +249,7 @@ describe('Node 方法测试', () => { // getComponentName btnParent.insertAfter({ getComponentName: () => 'Button' }, firstBtn); - expect(btnParent.children.get(1)?.getProps().export().props).toBeUndefined(); + expect(btnParent.children.get(1)?.getProps().export().props).toEqual({}); expect(mockFn).toHaveBeenCalledTimes(3); }); }); diff --git a/packages/vision-polyfill/src/pages.ts b/packages/vision-polyfill/src/pages.ts index ab11bb916..997560376 100644 --- a/packages/vision-polyfill/src/pages.ts +++ b/packages/vision-polyfill/src/pages.ts @@ -71,14 +71,14 @@ const pages = Object.assign(project, { componentsTree, id: pages[0].id, config: project.config, - }, + }, true, ); - // FIXME: 根本原因是 PropStash 导致的,在页面节点初始化结束后,hideModalNodes 导致了第一次变化 + // FIXME: 在页面节点初始化结束后,还有响应式变量变化导致了多次变化 // 这样可以避免页面加载之后就被标记为 isModified setTimeout(() => { project.currentDocument?.history.savePoint(); - }, 0); + }, 1000); }, addPage(data: OldPageData | RootSchema) { if (isPageDataV1(data)) {