From cbbe6d315262405ecf1167144fbff1d0997a3784 Mon Sep 17 00:00:00 2001 From: JackLian Date: Sat, 10 Dec 2022 11:55:33 +0800 Subject: [PATCH] fix: merge from develop --- .github/CODEOWNERS | 10 +- .../workflows/insufficient information.yml | 2 +- docs/community/issue.md | 24 +- docs/docs/api/common.md | 2 +- docs/docs/api/datasource.md | 4 +- docs/docs/api/event.md | 2 +- docs/docs/api/index.md | 2 +- docs/docs/api/init.md | 4 +- docs/docs/api/logger.md | 2 +- docs/docs/api/material.md | 4 +- docs/docs/api/plugins.md | 19 +- docs/docs/api/project.md | 4 +- docs/docs/api/setters.md | 4 +- docs/docs/api/skeleton.md | 97 +++-- docs/docs/article/index.md | 24 +- docs/docs/demoUsage/appendix/loop.md | 8 +- docs/docs/demoUsage/intro.md | 36 +- docs/docs/demoUsage/makeStuff/dialog.md | 22 +- docs/docs/demoUsage/makeStuff/table.md | 104 +++-- docs/docs/demoUsage/panels/canvas.md | 16 +- docs/docs/demoUsage/panels/code.md | 36 +- docs/docs/demoUsage/panels/component.md | 7 +- docs/docs/demoUsage/panels/datasource.md | 36 +- docs/docs/demoUsage/panels/settings.md | 28 +- docs/docs/faq/faq002.md | 10 +- docs/docs/faq/faq003.md | 10 +- docs/docs/faq/faq005.md | 10 +- docs/docs/faq/faq006.md | 2 +- docs/docs/faq/faq007.md | 8 +- docs/docs/faq/faq008.md | 4 +- docs/docs/faq/faq009.md | 4 +- docs/docs/faq/faq010.md | 2 +- docs/docs/faq/faq011.md | 8 +- docs/docs/faq/faq012.md | 4 +- docs/docs/faq/faq013.md | 2 +- docs/docs/faq/faq014.md | 2 +- docs/docs/faq/faq015.md | 4 +- docs/docs/faq/faq016.md | 2 +- docs/docs/faq/faq018.md | 6 +- docs/docs/faq/faq020.md | 2 +- docs/docs/faq/faq021.md | 18 + docs/docs/faq/faq022.md | 18 + docs/docs/guide/appendix/glossary.md | 2 +- docs/docs/guide/appendix/metaSpec.md | 4 +- docs/docs/guide/appendix/npms.md | 2 +- docs/docs/guide/appendix/repos.md | 16 +- .../guide/appendix/setterDetails/array.md | 39 +- .../docs/guide/appendix/setterDetails/bool.md | 13 +- .../guide/appendix/setterDetails/color.md | 12 +- .../guide/appendix/setterDetails/event.md | 69 ++-- .../docs/guide/appendix/setterDetails/icon.md | 25 +- .../guide/appendix/setterDetails/mixed.md | 12 +- .../guide/appendix/setterDetails/number.md | 17 +- .../appendix/setterDetails/radioGroup.md | 24 +- .../guide/appendix/setterDetails/select.md | 26 +- .../docs/guide/appendix/setterDetails/slot.md | 100 ++--- .../guide/appendix/setterDetails/string.md | 14 +- .../guide/appendix/setterDetails/style.md | 47 +-- .../guide/appendix/setterDetails/textArea.md | 14 +- .../guide/appendix/setterDetails/variable.md | 18 +- docs/docs/guide/appendix/setters.md | 58 ++- docs/docs/guide/create/_category_.json | 2 +- docs/docs/guide/create/useEditor.md | 125 +++--- docs/docs/guide/create/useRenderer.md | 34 +- docs/docs/guide/design/datasourceEngine.md | 29 +- docs/docs/guide/design/editor.md | 227 +++++++---- docs/docs/guide/design/generator.md | 78 ++-- docs/docs/guide/design/materialParser.md | 32 +- docs/docs/guide/design/renderer.md | 50 +-- docs/docs/guide/design/setter.md | 22 +- docs/docs/guide/design/specs.md | 109 ++++-- docs/docs/guide/design/summary.md | 52 ++- docs/docs/guide/expand/_category_.json | 2 +- docs/docs/guide/expand/editor/cli.md | 252 ++++++------ docs/docs/guide/expand/editor/material.md | 108 +++--- docs/docs/guide/expand/editor/metaSpec.md | 175 +++++---- docs/docs/guide/expand/editor/partsIntro.md | 126 +++--- .../guide/expand/editor/pluginContextMenu.md | 38 +- docs/docs/guide/expand/editor/pluginWidget.md | 125 ++++-- docs/docs/guide/expand/editor/setter.md | 83 ++-- docs/docs/guide/expand/editor/summary.md | 30 +- .../guide/expand/runtime/codeGeneration.md | 26 +- docs/docs/guide/expand/runtime/renderer.md | 6 +- docs/docs/guide/quickStart/demo.md | 67 ++-- docs/docs/guide/quickStart/intro.md | 6 +- docs/docs/guide/quickStart/start.md | 228 +++++++---- .../participate}/code-specification.md | 3 +- docs/docs/participate/config.md | 2 +- docs/docs/participate/doc.md | 20 +- docs/docs/participate/flow.md | 17 +- docs/docs/participate/index.md | 3 +- docs/docs/participate/prepare.md | 2 +- docs/docs/specs/assets-spec.md | 16 +- docs/docs/specs/lowcode-spec.md | 50 +-- docs/docs/specs/material-spec.md | 98 +++-- docs/docusaurus.config.js | 4 + docs/package.json | 2 +- .../src/plugins/component/rax/jsx.ts | 2 +- .../test-cases/rax-app/demo01/schema.json5 | 1 - .../test-cases/rax-app/demo02/schema.json5 | 1 - .../test-cases/rax-app/demo03/schema.json5 | 1 - .../test-cases/rax-app/demo05/schema.json5 | 1 - .../rax-app/demo12-refs/schema.json5 | 1 - modules/material-parser/README.md | 2 +- .../test/fixtures/ts-component2/package.json | 2 +- package.json | 6 +- packages/designer/jest.config.js | 4 +- packages/designer/package.json | 12 +- .../bem-tools/border-container.tsx | 3 +- .../bem-tools/border-selecting.tsx | 6 +- .../designer/src/builtin-simulator/host.ts | 27 +- .../builtin-simulator/utils/parse-metadata.ts | 2 +- packages/designer/src/component-meta.ts | 26 +- packages/designer/src/designer/designer.ts | 63 +-- packages/designer/src/designer/dragon.ts | 32 +- .../src/designer/setting/setting-field.ts | 5 +- .../designer/setting/setting-prop-entry.ts | 8 +- .../src/designer/setting/setting-top-entry.ts | 3 +- .../designer/src/designer/setting/utils.ts | 3 +- .../designer/src/document/document-model.ts | 6 +- packages/designer/src/document/history.ts | 11 +- .../src/document/node/node-children.ts | 10 +- packages/designer/src/document/node/node.ts | 12 +- .../designer/src/document/node/props/prop.ts | 4 +- .../designer/src/plugin/plugin-context.ts | 71 ++-- .../designer/src/plugin/plugin-manager.ts | 17 +- packages/designer/src/plugin/plugin-types.ts | 44 ++- packages/designer/src/project/project.ts | 3 +- packages/designer/src/types/index.ts | 22 +- .../tests/bugs/prop-variable-jse.test.ts | 8 +- .../bem-tools/drag-resize-engine.test.ts | 9 +- .../bem-tools/manager.test.tsx | 17 +- .../builtin-simulator/host-view.test.tsx | 32 -- .../tests/builtin-simulator/host.test.ts | 22 +- .../utils/parse-metadata.test.ts | 4 + .../tests/builtin-simulator/viewport.test.ts | 6 +- .../tests/designer/builtin-hotkey.test.ts | 3 +- .../designer/tests/designer/designer.test.ts | 32 +- .../designer/tests/designer/dragon.test.ts | 6 +- .../designer/tests/designer/scroller.test.ts | 25 +- .../designer/setting/setting-field.test.ts | 4 +- .../setting/setting-prop-entry.test.ts | 9 +- .../setting/setting-top-entry.test.ts | 9 +- .../document-model/document-model.test.ts | 6 +- .../tests/document/history/history.test.ts | 14 - .../document/node/modal-nodes-manager.test.ts | 3 +- .../tests/document/node/node-children.test.ts | 3 +- .../designer/tests/document/node/node.test.ts | 8 +- .../tests/document/node/props/prop.test.ts | 5 +- .../tests/plugin/plugin-manager.test.ts | 9 +- .../tests/project/project-methods.test.ts | 7 +- packages/designer/tsconfig.json | 12 + packages/editor-core/package.json | 2 +- packages/editor-core/src/config.ts | 172 ++------ packages/editor-core/src/di/setter.ts | 54 ++- packages/editor-core/src/editor.ts | 10 +- packages/editor-core/src/hotkey.ts | 3 +- packages/editor-core/src/intl/index.ts | 2 +- .../editor-core/src/widgets/title/index.tsx | 4 +- packages/editor-skeleton/package.json | 2 +- .../src/components/settings/settings-pane.tsx | 5 +- .../src/components/stage-box/stage.tsx | 2 +- packages/editor-skeleton/src/skeleton.ts | 9 +- .../src/transducers/addon-combine.ts | 2 +- .../src/transducers/parse-func.ts | 8 +- packages/editor-skeleton/src/types.ts | 37 +- packages/editor-skeleton/src/widget/utils.ts | 3 +- packages/editor-view/package.json | 4 +- packages/editor-window/package.json | 4 +- packages/engine/README-zh_CN.md | 16 +- packages/engine/README.md | 14 +- packages/engine/src/engine-core.ts | 30 +- packages/engine/src/modules/designer-types.ts | 5 +- packages/engine/src/modules/editor-types.ts | 3 - packages/engine/src/modules/live-editing.ts | 5 +- .../engine/src/modules/shell-model-factory.ts | 18 + packages/ignitor/public/index.html | 4 +- packages/plugin-designer/package.json | 2 +- packages/plugin-outline-pane/package.json | 2 +- packages/plugin-outline-pane/src/tree-node.ts | 3 +- .../plugin-outline-pane/src/views/tree.tsx | 3 +- packages/rax-simulator-renderer/package.json | 2 +- .../rax-simulator-renderer/src/renderer.ts | 4 +- packages/react-renderer/package.json | 2 +- .../react-simulator-renderer/package.json | 2 +- packages/renderer-core/package.json | 2 +- packages/renderer-core/src/renderer/base.tsx | 5 +- packages/renderer-core/src/utils/common.ts | 3 +- .../renderer-core/src/utils/data-helper.ts | 2 +- .../renderer-core/src/utils/is-use-loop.ts | 3 +- packages/shell/package.json | 4 +- packages/shell/src/canvas.ts | 9 +- packages/shell/src/common.tsx | 367 +++++++++++++----- packages/shell/src/component-meta.ts | 38 +- packages/shell/src/detecting.ts | 3 +- packages/shell/src/document-model.ts | 131 ++++--- packages/shell/src/drag-object.ts | 20 +- packages/shell/src/dragon.ts | 36 +- packages/shell/src/drop-location.ts | 9 +- packages/shell/src/event.ts | 4 +- packages/shell/src/history.ts | 21 +- packages/shell/src/hotkey.ts | 6 +- packages/shell/src/locate-event.ts | 25 +- packages/shell/src/material.ts | 21 +- packages/shell/src/modal-nodes-manager.ts | 24 +- packages/shell/src/node-children.ts | 64 +-- packages/shell/src/node.ts | 164 +++++--- packages/shell/src/project.ts | 46 ++- packages/shell/src/prop.ts | 30 +- packages/shell/src/props.ts | 32 +- packages/shell/src/selection.ts | 28 +- packages/shell/src/setting-prop-entry.ts | 84 ++-- packages/shell/src/setting-top-entry.ts | 13 +- packages/shell/src/simulator-host.ts | 21 +- packages/shell/src/skeleton.ts | 14 +- packages/types/package.json | 2 +- packages/types/src/assets.ts | 2 +- packages/types/src/deprecated/index.ts | 18 + .../src/deprecated/isActionContentObject.ts | 8 + packages/types/src/deprecated/isCustomView.ts | 10 + packages/types/src/deprecated/isDOMText.ts | 8 + .../types/src/deprecated/isDynamicSetter.ts | 9 + packages/types/src/deprecated/isI18nData.ts | 8 + packages/types/src/deprecated/isJSBlock.ts | 8 + .../types/src/deprecated/isJSExpression.ts | 8 + packages/types/src/deprecated/isJSFunction.ts | 8 + packages/types/src/deprecated/isJSSlot.ts | 8 + .../src/deprecated/isLowCodeComponentType.ts | 9 + packages/types/src/deprecated/isNodeSchema.ts | 8 + .../types/src/deprecated/isPlainObject.ts | 10 + .../src/deprecated/isProCodeComponentType.ts | 8 + .../types/src/deprecated/isProjectSchema.ts | 8 + packages/types/src/deprecated/isReactClass.ts | 8 + .../types/src/deprecated/isReactComponent.ts | 9 + .../types/src/deprecated/isSetterConfig.ts | 9 + .../types/src/deprecated/isTitleConfig.ts | 10 + packages/types/src/designer.ts | 23 ++ packages/types/src/dragon.ts | 29 ++ packages/types/src/editor-skeleton.ts | 27 ++ packages/types/src/editor.ts | 21 + packages/types/src/engine-config.ts | 181 +++++++++ packages/types/src/i18n.ts | 5 - packages/types/src/index.ts | 9 + packages/types/src/metadata.ts | 18 +- packages/types/src/npm.ts | 10 +- packages/types/src/props-transducer.ts | 12 + packages/types/src/schema.ts | 15 +- packages/types/src/setter-config.ts | 27 +- packages/types/src/shell-model-factory.ts | 8 + packages/types/src/shell/api/common.ts | 50 +++ packages/types/src/shell/api/event.ts | 26 ++ packages/types/src/shell/api/hotkey.ts | 16 + packages/types/src/shell/api/index.ts | 8 + packages/types/src/shell/api/material.ts | 90 +++++ packages/types/src/shell/api/project.ts | 115 ++++++ packages/types/src/shell/api/setters.ts | 31 ++ .../types/src/shell/api/simulator-host.ts | 41 ++ packages/types/src/shell/api/skeleton.ts | 95 +++++ packages/types/src/shell/index.ts | 15 + packages/types/src/shell/model/canvas.ts | 4 + .../types/src/shell/model/component-meta.ts | 85 ++++ packages/types/src/shell/model/detecting.ts | 23 ++ .../types/src/shell/model/document-model.ts | 155 ++++++++ packages/types/src/shell/model/drag-object.ts | 8 + packages/types/src/shell/model/dragon.ts | 39 ++ .../types/src/shell/model/drop-location.ts | 3 + packages/types/src/shell/model/history.ts | 49 +++ packages/types/src/shell/model/index.ts | 17 + .../types/src/shell/model/locate-event.ts | 20 + .../src/shell/model/modal-nodes-manager.ts | 37 ++ .../types/src/shell/model/node-children.ts | 128 ++++++ packages/types/src/shell/model/node.ts | 316 +++++++++++++++ packages/types/src/shell/model/prop.ts | 59 +++ packages/types/src/shell/model/props.ts | 82 ++++ packages/types/src/shell/model/selection.ts | 65 ++++ .../src/shell/model/setting-prop-entry.ts | 188 +++++++++ .../src/shell/model/setting-top-entry.ts | 30 ++ packages/types/src/title.ts | 16 +- packages/types/src/value-type.ts | 28 +- packages/utils/package.json | 2 +- packages/utils/src/check-types/index.ts | 16 + .../check-types/is-action-content-object.ts | 6 + .../utils/src/check-types/is-custom-view.ts | 8 + packages/utils/src/check-types/is-dom-text.ts | 5 + .../src/check-types/is-dynamic-setter.ts | 7 + .../utils/src/check-types/is-i18n-data.ts | 7 + .../utils/src/check-types/is-isfunction.ts | 5 + packages/utils/src/check-types/is-jsblock.ts | 5 + .../utils/src/check-types/is-jsexpression.ts | 15 + packages/utils/src/check-types/is-jsslot.ts | 5 + .../check-types/is-lowcode-component-type.ts | 7 + .../utils/src/check-types/is-node-schema.ts | 5 + .../check-types/is-procode-component-type.ts | 6 + .../src/check-types/is-project-schema.ts | 5 + .../utils/src/check-types/is-setter-config.ts | 7 + .../utils/src/check-types/is-title-config.ts | 8 + packages/utils/src/index.ts | 1 + packages/utils/src/schema.ts | 3 +- packages/workspace/package.json | 4 +- 299 files changed, 5577 insertions(+), 2655 deletions(-) create mode 100644 docs/docs/faq/faq021.md create mode 100644 docs/docs/faq/faq022.md rename docs/{community => docs/participate}/code-specification.md (93%) delete mode 100644 packages/designer/tests/builtin-simulator/host-view.test.tsx create mode 100644 packages/designer/tsconfig.json delete mode 100644 packages/engine/src/modules/editor-types.ts create mode 100644 packages/engine/src/modules/shell-model-factory.ts create mode 100644 packages/types/src/deprecated/index.ts create mode 100644 packages/types/src/deprecated/isActionContentObject.ts create mode 100644 packages/types/src/deprecated/isCustomView.ts create mode 100644 packages/types/src/deprecated/isDOMText.ts create mode 100644 packages/types/src/deprecated/isDynamicSetter.ts create mode 100644 packages/types/src/deprecated/isI18nData.ts create mode 100644 packages/types/src/deprecated/isJSBlock.ts create mode 100644 packages/types/src/deprecated/isJSExpression.ts create mode 100644 packages/types/src/deprecated/isJSFunction.ts create mode 100644 packages/types/src/deprecated/isJSSlot.ts create mode 100644 packages/types/src/deprecated/isLowCodeComponentType.ts create mode 100644 packages/types/src/deprecated/isNodeSchema.ts create mode 100644 packages/types/src/deprecated/isPlainObject.ts create mode 100644 packages/types/src/deprecated/isProCodeComponentType.ts create mode 100644 packages/types/src/deprecated/isProjectSchema.ts create mode 100644 packages/types/src/deprecated/isReactClass.ts create mode 100644 packages/types/src/deprecated/isReactComponent.ts create mode 100644 packages/types/src/deprecated/isSetterConfig.ts create mode 100644 packages/types/src/deprecated/isTitleConfig.ts create mode 100644 packages/types/src/designer.ts create mode 100644 packages/types/src/dragon.ts create mode 100644 packages/types/src/editor-skeleton.ts create mode 100644 packages/types/src/engine-config.ts create mode 100644 packages/types/src/props-transducer.ts create mode 100644 packages/types/src/shell-model-factory.ts create mode 100644 packages/types/src/shell/api/common.ts create mode 100644 packages/types/src/shell/api/event.ts create mode 100644 packages/types/src/shell/api/hotkey.ts create mode 100644 packages/types/src/shell/api/index.ts create mode 100644 packages/types/src/shell/api/material.ts create mode 100644 packages/types/src/shell/api/project.ts create mode 100644 packages/types/src/shell/api/setters.ts create mode 100644 packages/types/src/shell/api/simulator-host.ts create mode 100644 packages/types/src/shell/api/skeleton.ts create mode 100644 packages/types/src/shell/index.ts create mode 100644 packages/types/src/shell/model/canvas.ts create mode 100644 packages/types/src/shell/model/component-meta.ts create mode 100644 packages/types/src/shell/model/detecting.ts create mode 100644 packages/types/src/shell/model/document-model.ts create mode 100644 packages/types/src/shell/model/drag-object.ts create mode 100644 packages/types/src/shell/model/dragon.ts create mode 100644 packages/types/src/shell/model/drop-location.ts create mode 100644 packages/types/src/shell/model/history.ts create mode 100644 packages/types/src/shell/model/index.ts create mode 100644 packages/types/src/shell/model/locate-event.ts create mode 100644 packages/types/src/shell/model/modal-nodes-manager.ts create mode 100644 packages/types/src/shell/model/node-children.ts create mode 100644 packages/types/src/shell/model/node.ts create mode 100644 packages/types/src/shell/model/prop.ts create mode 100644 packages/types/src/shell/model/props.ts create mode 100644 packages/types/src/shell/model/selection.ts create mode 100644 packages/types/src/shell/model/setting-prop-entry.ts create mode 100644 packages/types/src/shell/model/setting-top-entry.ts create mode 100644 packages/utils/src/check-types/index.ts create mode 100644 packages/utils/src/check-types/is-action-content-object.ts create mode 100644 packages/utils/src/check-types/is-custom-view.ts create mode 100644 packages/utils/src/check-types/is-dom-text.ts create mode 100644 packages/utils/src/check-types/is-dynamic-setter.ts create mode 100644 packages/utils/src/check-types/is-i18n-data.ts create mode 100644 packages/utils/src/check-types/is-isfunction.ts create mode 100644 packages/utils/src/check-types/is-jsblock.ts create mode 100644 packages/utils/src/check-types/is-jsexpression.ts create mode 100644 packages/utils/src/check-types/is-jsslot.ts create mode 100644 packages/utils/src/check-types/is-lowcode-component-type.ts create mode 100644 packages/utils/src/check-types/is-node-schema.ts create mode 100644 packages/utils/src/check-types/is-procode-component-type.ts create mode 100644 packages/utils/src/check-types/is-project-schema.ts create mode 100644 packages/utils/src/check-types/is-setter-config.ts create mode 100644 packages/utils/src/check-types/is-title-config.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bc889c307..c2e49b783 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,13 +2,7 @@ # These owners will be the default owners for everything in # the repo. Unless a later match takes precedence -* @leoyuan @JackLian +* @liujuping @JackLian /modules/material-parser @akirakai -/modules/code-generator @Clarence-pan - -/packages/renderer-core/ @liujuping -/packages/react-renderer/ @liujuping -/packages/react-simulator-renderer/ @liujuping -/packages/rax-renderer/ @liujuping -/packages/rax-simulator-renderer/ @liujuping \ No newline at end of file +/modules/code-generator @leoyuan diff --git a/.github/workflows/insufficient information.yml b/.github/workflows/insufficient information.yml index 2b699860d..15885043a 100644 --- a/.github/workflows/insufficient information.yml +++ b/.github/workflows/insufficient information.yml @@ -16,4 +16,4 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} body: | - 你好 @${{ github.event.issue.user.login }},由于缺乏必要的信息(如 bug 重现步骤、引擎版本信息 等),无法定位问题,请按照 [issue bug 模板](https://github.com/alibaba/lowcode-engine/blob/main/.github/ISSUE_TEMPLATE/bug-report.md) 补全信息,也可以通过阅读[引擎的 issue 说明](https://www.yuque.com/lce/doc/yvlxhs) 了解什么类型的 issue 可以获得更好、更快的支持。 + 你好 @${{ github.event.issue.user.login }},由于缺乏必要的信息(如 bug 重现步骤、引擎版本信息 等),无法定位问题,请按照 [issue bug 模板](https://github.com/alibaba/lowcode-engine/blob/main/.github/ISSUE_TEMPLATE/bug-report.md) 补全信息,也可以通过阅读 [引擎的 issue 说明](https://lowcode-engine.cn/site/community/issue) 了解什么类型的 issue 可以获得更好、更快的支持。 diff --git a/docs/community/issue.md b/docs/community/issue.md index f0afc90d2..2b6bd0f96 100644 --- a/docs/community/issue.md +++ b/docs/community/issue.md @@ -33,7 +33,7 @@ sidebar_position: 2 ### 不同优先级的示例 #### 【支持快】通过线上 Demo 地址 + 控制台输入 API 可复现。 **示例** -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656387671833-cd44507b-af59-45ec-b0da-f4f0ef61e92e.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=295&id=ub61f0ab8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1862&originWidth=3322&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5033674&status=done&style=none&taskId=u3646a3b6-4b22-48e7-94e3-564a09cfa24&title=&width=527) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01np6ARb1KnJFOELjXg_!!6000000001208-2-tps-3322-1862.png) 复现步骤: - 打开线上 demo @@ -65,18 +65,18 @@ window.AliLowCodeEngine.project.openDocument('docl4xkca5b') 期望: -- 页面中的xxx部分和预期不符合,期望的效果是 xxx +- 页面中的 xxx 部分和预期不符合,期望的效果是 xxx #### 【支持稍慢】通过线上 demo + 完整操作步骤可复现 **示例** 1.使用 antd 组件 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656387998779-9f621c7f-82cb-48ad-94fc-84c2cd46065c.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=906&id=u0ad0726a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1812&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=838860&status=done&style=none&taskId=u0a0a9e20-f79e-4c8c-8c82-b304f7b7583&title=&width=1792) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN019dFe4Y24SDKbmpbdw_!!6000000007389-2-tps-3584-1812.png) 2.拖拽这个组件 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656388046560-e07680ee-809a-4ad1-bc47-47c2c00fdd40.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=901&id=u23c8416a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1802&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=890196&status=done&style=none&taskId=u7ac32b55-f32c-4215-ac1d-f81f5e986ac&title=&width=1792) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN0109SdxO1OtxSbpLn4Q_!!6000000001764-2-tps-3584-1802.png) 3.配置该属性值为 100 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656388075312-7c06f15a-464a-49f0-beb5-19320ea0e454.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=900&id=ua91e7f85&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1800&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=882142&status=done&style=none&taskId=u61082c8a-1092-4b5b-a2ea-00486cadb71&title=&width=1792) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01WeVXpW1HBny0VmQcS_!!6000000000720-2-tps-3584-1800.png) 期望效果: @@ -84,26 +84,26 @@ window.AliLowCodeEngine.project.openDocument('docl4xkca5b') #### 【支持稍慢】通过线上 demo + 变更代码可复现,并清楚的说明变更代码的位置和内容 **示例** -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656387894830-6850815f-e2ee-46bf-a2bf-fdda4d166691.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u87419dd1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=754&originWidth=1892&originalType=binary&ratio=1&rotation=0&showTitle=false&size=226627&status=done&style=none&taskId=u88b2bbb8-869c-482c-9510-9d513f6e191&title=&width=946) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01FL0Urq1tl1pLcYhJH_!!6000000005941-2-tps-1892-754.png) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656387911054-771dd7fc-db90-46ae-b1db-f5f9f7537ed4.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=389&id=u0a370108&margin=%5Bobject%20Object%5D&name=image.png&originHeight=778&originWidth=1917&originalType=binary&ratio=1&rotation=0&showTitle=false&size=229881&status=done&style=none&taskId=ucbc7af71-f0e1-4319-9097-8ad6b936c5e&title=&width=958.5) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01WIpR9V1i363wzyFzi_!!6000000004356-2-tps-1917-778.png) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656387922644-de3f1d64-0206-407d-82ad-2d1155374e37.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=127&id=u9c5921eb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=253&originWidth=1836&originalType=binary&ratio=1&rotation=0&showTitle=false&size=58615&status=done&style=none&taskId=u5c8af90a-0d20-40c8-a1f2-e387f037d85&title=&width=918) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01ZDkR3n1MNmP2uk15t_!!6000000001423-2-tps-1836-253.png) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656387931330-a5453ba1-264b-4325-b3a8-7cb6e22633ee.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=457&id=u687acf85&margin=%5Bobject%20Object%5D&name=image.png&originHeight=914&originWidth=1912&originalType=binary&ratio=1&rotation=0&showTitle=false&size=129980&status=done&style=none&taskId=u3a706b70-0da6-484d-857d-1d086f7a4e5&title=&width=956) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01OKzt1Z28b9WZIbM6B_!!6000000007950-2-tps-1912-914.png) #### 【支持慢】有完整的项目地址,下载下来可直接安装依赖并启动复现的 由于完整的项目中有很多冗余的信息,这部分排查起来十分耗时且困难。不推荐使用改方式。 #### 【不保证提供支持】其他 ##### 只有标题没有复现步骤 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656388351815-e086b980-0828-4c49-ba72-142446313d2d.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=510&id=u79a38c3b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1020&originWidth=2520&originalType=binary&ratio=1&rotation=0&showTitle=false&size=529258&status=done&style=none&taskId=u3540b08e-9dff-4c72-8ee5-123912439b0&title=&width=1260) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN017rO2gR1YKpEgIMBjh_!!6000000003041-2-tps-2520-1020.png) ##### 复现步骤不清晰 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656388451393-2168e5ca-20de-4781-9e51-20e282dbc0ca.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=833&id=ubaf001f6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1666&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1228630&status=done&style=none&taskId=ub26ed4ff-e0cf-4644-9a65-00ddee4b9e5&title=&width=1792) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01vtHi5z225CC7aFVS2_!!6000000007068-2-tps-3584-1666.png) ##### 和引擎无关的 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1656388376995-0ab5d7c0-8ff9-49cf-8854-70e9bb3ff87a.png#clientId=uaa040ac3-dccc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=715&id=uffc59321&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1430&originWidth=2548&originalType=binary&ratio=1&rotation=0&showTitle=false&size=747119&status=done&style=none&taskId=u861d5fa6-f673-4091-8635-ff45adf680e&title=&width=1274) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01KxqT9M1vcu25xJHFP_!!6000000006194-2-tps-2548-1430.png) diff --git a/docs/docs/api/common.md b/docs/docs/api/common.md index 46b4d7f03..c16d22043 100644 --- a/docs/docs/api/common.md +++ b/docs/docs/api/common.md @@ -43,7 +43,7 @@ common.utils.startTransaction(() => { ``` ### createIntl -i18n相关工具 +i18n 相关工具 *引擎版本 >= 1.0.17 ```typescript import { common } from '@alilc/lowcode-engine'; diff --git a/docs/docs/api/datasource.md b/docs/docs/api/datasource.md index cadf9cb58..994e1ee18 100644 --- a/docs/docs/api/datasource.md +++ b/docs/docs/api/datasource.md @@ -4,7 +4,7 @@ sidebar_position: 12 --- ### 请求数据源 ```javascript -// 请求userList (userList在数据源面板中定义) +// 请求 userList(userList 在数据源面板中定义) this.dataSourceMap['userList'].load({ data: {} @@ -22,7 +22,7 @@ const { userList } = this.state; // 获取数据源面板中定义的值 const { user } = this.state; -// 修改state值 +// 修改 state 值 this.setState({ user: {} }); diff --git a/docs/docs/api/event.md b/docs/docs/api/event.md index 26232b7c1..b24c91054 100644 --- a/docs/docs/api/event.md +++ b/docs/docs/api/event.md @@ -74,7 +74,7 @@ import { event } from '@alilc/lowcode-engine'; class SetterB extends React.Component { bindFunction = () => { const { field, value } = this.props; - // 这里展示的和插件进行通信, 事件规则是插件名 + 方法 + // 这里展示的和插件进行通信,事件规则是插件名 + 方法 event.emit('eventBindDialog.openDialog', field.name, this.emitEventName); } } diff --git a/docs/docs/api/index.md b/docs/docs/api/index.md index 1afccce18..b888bad0b 100644 --- a/docs/docs/api/index.md +++ b/docs/docs/api/index.md @@ -5,7 +5,7 @@ sidebar_position: 0 引擎直接提供 9 大类 API,以及若干间接的 API,具体如下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1645445575048-cc511d60-3b84-411d-a70e-21b7a596d09c.png#clientId=uaab5e9c4-fa7b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=695&id=u8e1d0318&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1390&originWidth=1278&originalType=binary&ratio=1&rotation=0&showTitle=false&size=410614&status=done&style=none&taskId=u9fdcdcfb-4e8b-4e22-8865-94181f458d0&title=&width=639) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01ZA2RMv1nYlWf6ThGf_!!6000000005102-2-tps-1278-1390.png) ### API 设计约定 一些 API 设计约定: diff --git a/docs/docs/api/init.md b/docs/docs/api/init.md index 50c5cf701..93ad133d3 100644 --- a/docs/docs/api/init.md +++ b/docs/docs/api/init.md @@ -41,7 +41,7 @@ interface EngineOptions { */ enableCanvasLock?: boolean; /** - * 容器锁定后,容器本身是否可以设置属性,仅当画布锁定特性开启时生效, 默认值为:false + * 容器锁定后,容器本身是否可以设置属性,仅当画布锁定特性开启时生效,默认值为:false */ enableLockedNodeSetting?: boolean; /** @@ -135,4 +135,4 @@ init({ ``` 在引擎中即可这样使用。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1657272220368-9ee4430e-9e42-4746-9de8-a233840b0950.png#clientId=u951c1fcc-9dab-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=292&id=uacb8d50d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1796&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1641368&status=error&style=none&taskId=u559fb5cd-4a48-4732-b169-c9868a6d7b7&title=&width=582) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01FWvu051OxAEYrHBy5_!!6000000001771-2-tps-3584-1796.png) diff --git a/docs/docs/api/logger.md b/docs/docs/api/logger.md index 3fbb7b7fc..d523622d8 100644 --- a/docs/docs/api/logger.md +++ b/docs/docs/api/logger.md @@ -35,7 +35,7 @@ import { logger } from '@alilc/lowcode-engine'; // 内部实现:logger = getLogger({ level: 'warn', bizName: 'designer:pluginManager' }) -// 若在url query中增加 `__logConf__` 可改变打印日志级别和限定业务类型日志 +// 若在 url query 中增加 `__logConf__` 可改变打印日志级别和限定业务类型日志 // 默认:__logConf__=warn:* logger.log('log'); // 不输出 logger.warn('warn'); // 输出 diff --git a/docs/docs/api/material.md b/docs/docs/api/material.md index 852287f64..4cf1948cf 100644 --- a/docs/docs/api/material.md +++ b/docs/docs/api/material.md @@ -12,7 +12,7 @@ sidebar_position: 2 # 方法签名(functions) ## 资产包 ### setAssets -设置「[资产包](https://www.yuque.com/lce/doc/vgcyf1)」结构 +设置「[资产包](/site/docs/specs/lowcode-spec#2-协议结构)」结构 **类型定义** ```typescript @@ -151,7 +151,7 @@ material.addBuiltinComponentAction({ condition: true, }); ``` -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1645446545381-aa6f4543-5f6e-4a03-91c1-e88817823153.png#clientId=u51926daa-3723-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=198&id=u34e8d0d9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=198&originWidth=230&originalType=binary&ratio=1&rotation=0&showTitle=false&size=16907&status=done&style=none&taskId=u27bac39f-a38f-43bf-a0e5-157118e3aa6&title=&width=230) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01jDbN7B1KfWVzJ16tw_!!6000000001191-2-tps-230-198.png) ### removeBuiltinComponentAction 移除设计器辅助层的指定 action diff --git a/docs/docs/api/plugins.md b/docs/docs/api/plugins.md index 8762dbacd..f225386fc 100644 --- a/docs/docs/api/plugins.md +++ b/docs/docs/api/plugins.md @@ -223,15 +223,16 @@ plugins.delete('builtinPluginRegistry'); **类型定义** ```typescript export interface ILowCodePluginContext { - skeleton: Skeleton; // 参考面板 API - hotkey: Hotkey; // 参考快捷键 API - logger: Logger; // 参考日志 API - plugins: ILowCodePluginManager; // 参考插件 API - setters: Setters; // 参考设置器 API - config: EngineConfig; // 参考配置 API - material: Material; // 参考物料 API - event: Event; // 参考事件 API - project: Project; // 参考模型 API + skeleton: Skeleton; // 参考面板 API + hotkey: Hotkey; // 参考快捷键 API + setters: Setters; // 参考设置器 API + config: EngineConfig; // 参考配置 API + material: Material; // 参考物料 API + event: Event; // 参考事件 API + project: Project; // 参考模型 API + common: Common; // 参考模型 API + logger: Logger; // 参考日志 API + plugins: ILowCodePluginManager; // 即本文档描述内容 preference: IPluginPreferenceMananger; } ``` diff --git a/docs/docs/api/project.md b/docs/docs/api/project.md index 269184b53..7c5896852 100644 --- a/docs/docs/api/project.md +++ b/docs/docs/api/project.md @@ -5,7 +5,7 @@ sidebar_position: 3 # 模块简介 引擎编排模块中包含多种模型,包括[项目模型(project)](#DADnF)、[文档模型(document-model)](#lp7xO)、[节点模型(node)](#m0cJS)、[节点孩子模型(node-children)](#W8seq)、[属性集模型(props)](#IJeRY)以及[属性模型(prop)](#w1diM)。 他们的依赖关系如下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1645510146964-62f26151-e624-48f6-a422-dacdcb60dbea.png#averageHue=%23fefefe&clientId=ue969b413-090d-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=676&id=ucd07aeff&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1352&originWidth=1650&originalType=binary&ratio=1&rotation=0&showTitle=false&size=282048&status=error&style=none&taskId=u8ec0cad1-ed80-46f5-8b6b-b7278b4bb7d&title=&width=825) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01B1bAZi1asNU3KaSUJ_!!6000000003385-2-tps-1650-1352.png) 在文档模型内部,又有一些引申模型,比如[历史操作(history)](#xvIKj)、[画布节点选中(selection)](#GtFkP)、[画布节点悬停(detecting)](#Tjt05)等。 整个模型系统,以项目模型为最顶层的模型,其他模型实例均需要通过 project 来获得,比如 project.currentDocument 来获取当前的文档模型,project.currentDocument.nodesMap 来获取当前文档模型里所有的节点列表。 @@ -248,7 +248,7 @@ onChangeNodeVisible(fn: (node: Node, visible: boolean) => void) ### onChangeNodeChildren -onChangeNodeChildren(fn: (info?: IOnChangeOptions) => void) +onChangeNodeChildren(fn: (info?: IPublicOnChangeOptions) => void) 当前 document 的节点 children 变更事件 diff --git a/docs/docs/api/setters.md b/docs/docs/api/setters.md index ac45831be..41c992e16 100644 --- a/docs/docs/api/setters.md +++ b/docs/docs/api/setters.md @@ -83,7 +83,7 @@ interface AltStringSetterProps { value: string; // 默认值 initialValue: string; - // setter唯一输出 + // setter 唯一输出 onChange: (val: string) => void; // AltStringSetter 特殊配置 placeholder: string; @@ -254,7 +254,7 @@ interface AltStringSetterProps { value: string; // 默认值 initialValue: string; - // setter唯一输出 + // setter 唯一输出 onChange: (val: string) => void; // AltStringSetter 特殊配置 placeholder: string; diff --git a/docs/docs/api/skeleton.md b/docs/docs/api/skeleton.md index 80e3220f6..1ae573e7e 100644 --- a/docs/docs/api/skeleton.md +++ b/docs/docs/api/skeleton.md @@ -3,23 +3,57 @@ title: skeleton - 面板 API sidebar_position: 1 --- ## 模块简介 -面板 API 提供了面板扩展和管理的能力,如下图蓝色内容都是扩展出来的。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1645442085447-d1822e7f-9e5a-4e06-a770-04b1023d5daf.png#clientId=u9aca70b6-1a98-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=498&id=u2dd3deb2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=996&originWidth=1780&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1549904&status=done&style=none&taskId=u28659b69-981c-416e-bed6-b2f06b8e6fc&title=&width=890)
页面上可以扩展的区域共 5 个,具体如下:
![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1645431386085-2710d33d-0652-450a-a993-c804368da1ce.png#clientId=u1724eb73-4c0c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=487&id=ud138f866&margin=%5Bobject%20Object%5D&name=image.png&originHeight=974&originWidth=1892&originalType=binary&ratio=1&rotation=0&showTitle=false&size=228235&status=done&style=none&taskId=u265d50a5-3700-406e-84b2-0158ebadaae&title=&width=946) +面板 API 提供了面板扩展和管理的能力,如下图蓝色内容都是扩展出来的。 + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01eVA0U41xYRP3e5zo0_!!6000000006455-2-tps-1780-996.png) + +页面上可以扩展的区域共 5 个,具体如下: +![image.png](https://img.alicdn.com/imgextra/i3/O1CN014d2AcS1D5c9TshEiQ_!!6000000000165-2-tps-1892-974.png) ### 基本概念 -#### 扩展区域位置(area) +#### 扩展区域位置 (area) ##### topArea -展示在设计器的顶部区域,常见的相关区域的插件主要是:
1)注册设计器 Logo;
2)设计器操作回退和撤销按钮;
3)全局操作按钮,例如:保存、预览等; + +展示在设计器的顶部区域,常见的相关区域的插件主要是: +1. 注册设计器 Logo; +2. 设计器操作回退和撤销按钮; +3. 全局操作按钮,例如:保存、预览等; ##### leftArea -左侧区域的展示形式大多数是 Icon 和对应的面板,通过点击 Icon 可以展示对应的面板并隐藏其他的面板。
该区域相关插件的主要有:
1)大纲树展示,展示该设计器设计页面的大纲。
2)组件库,展示注册到设计器中的组件,点击之后,可以从组件库面板中拖拽到设计器的画布中。
3)数据源面板
4)JS 等代码面板。
可以发现,这个区域的面板大多数操作时是不需要同时并存的,且交互比较复杂的,需要一个更整块的区域来进行操作。 + +左侧区域的展示形式大多数是 Icon 和对应的面板,通过点击 Icon 可以展示对应的面板并隐藏其他的面板。 + +该区域相关插件的主要有: +1. 大纲树展示,展示该设计器设计页面的大纲。 +2. 组件库,展示注册到设计器中的组件,点击之后,可以从组件库面板中拖拽到设计器的画布中。 +3. 数据源面板 +4. JS 等代码面板。 + +可以发现,这个区域的面板大多数操作时是不需要同时并存的,且交互比较复杂的,需要一个更整块的区域来进行操作。 + ##### centerArea -画布区域,由于画布大多数是展示作用,所以一般扩展的种类比较少。常见的扩展有:
1)画布大小修改
2)物料选中扩展区域修改 + +画布区域,由于画布大多数是展示作用,所以一般扩展的种类比较少。常见的扩展有: +1. 画布大小修改 +2. 物料选中扩展区域修改 ##### rightArea + 右侧区域,常用于组件的配置。常见的扩展有:统一处理组件的配置项,例如统一删除某一个配置项,统一添加某一个配置项的。 ##### toolbar + 跟 topArea 类似,按需放置面板插件~ -#### 展示类型(type) -展示类型用于区分插件在设计器内可操作的几种不同界面类型。主要的几种类型为PanelDock、Widget、Dock,另有Panel类型目前不推荐使用。 +#### 展示类型 (type) + +展示类型用于区分插件在设计器内可操作的几种不同界面类型。主要的几种类型为 PanelDock、Widget、Dock,另有 Panel 类型目前不推荐使用。 ##### PanelDock -PanelDock 是以面板的形式展示在设计器的左侧区域的。其中主要有两个部分组成,一个是图标,一个是面板。当点击图标时可以控制面板的显示和隐藏。
下图是组件库插件的展示效果。
![Feb-08-2022 19-44-15.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644320663827-ee9c54a1-f684-40e2-8a6b-875103d04b31.gif#clientId=u221f0bd4-c19e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=555&id=u5292d9cc&margin=%5Bobject%20Object%5D&name=Feb-08-2022%2019-44-15.gif&originHeight=790&originWidth=1536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1381641&status=done&style=stroke&taskId=ub28a13a4-3d80-4a02-bcaa-cc9d6127243&title=&width=1080)
其中右上角可以进行固定,可以对弹出的宽度做设定
接入可以参考代码 + +PanelDock 是以面板的形式展示在设计器的左侧区域的。其中主要有两个部分组成,一个是图标,一个是面板。当点击图标时可以控制面板的显示和隐藏。 + +下图是组件库插件的展示效果。 + +![Feb-08-2022 19-44-15.gif](https://img.alicdn.com/imgextra/i2/O1CN01i66G5O27bK37nlpxV_!!6000000007815-1-tps-1536-790.gif) + +其中右上角可以进行固定,可以对弹出的宽度做设定 + +接入可以参考代码 ```javascript import { skeleton } from "@alilc/lowcode-engine"; @@ -31,7 +65,7 @@ skeleton.add({ props: { align: "left", icon: "wenjian", - description: "JS面板", + description: "JS 面板", }, panelProps: { floatable: true, // 是否可浮动 @@ -39,13 +73,18 @@ skeleton.add({ hideTitleBar: false, maxHeight: 800, maxWidth: 1200, - title: "JS面板", + title: "JS 面板", width: 600, }, }); ``` ##### Widget -Widget 形式是直接渲染在当前编辑器的对应位置上。如 demo 中在设计器顶部的所有组件都是这种展现形式。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644320068765-47efc836-30c2-452f-8104-b98b1ea3533d.png#clientId=u221f0bd4-c19e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=51&id=P60UE&margin=%5Bobject%20Object%5D&name=image.png&originHeight=94&originWidth=1988&originalType=binary&ratio=1&rotation=0&showTitle=false&size=58410&status=done&style=stroke&taskId=u4eadd643-2e63-4be7-8736-b27b9c82b81&title=&width=1080)
接入可以参考代码: +Widget 形式是直接渲染在当前编辑器的对应位置上。如 demo 中在设计器顶部的所有组件都是这种展现形式。 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01IRQIZp1m5AJPwBKDv_!!6000000004902-2-tps-1988-94.png) + +接入可以参考代码: + ```javascript import {skeleton} from "@alilc/lowcode-engine"; // 注册 logo 面板 @@ -53,8 +92,8 @@ skeleton.add({ area: "topArea", type: "Widget", name: "logo", - content: Logo, // Widget 组件实例 - contentProps: { // Widget 插件props + content: Logo, // Widget 组件实例 + contentProps: { // Widget 插件 props logo: "https://img.alicdn.com/tfs/TB1_SocGkT2gK0jSZFkXXcIQFXa-66-66.png", href: "/", @@ -66,7 +105,9 @@ skeleton.add({ }); ``` ##### Dock -一个图标的表现形式,可以用于语言切换、跳转到外部链接、打开一个 widget 等场景 + +一个图标的表现形式,可以用于语言切换、跳转到外部链接、打开一个 widget 等场景。 + ```javascript import { skeleton } from "@alilc/lowcode-engine"; @@ -75,7 +116,7 @@ skeleton.add({ type: "Dock", name: "opener", content: Opener, // Widget 组件实例 - contentProps: { // Widget 插件props + contentProps: { // Widget 插件 props xxx: "1", }, props: { @@ -89,11 +130,14 @@ skeleton.add({ } }); ``` -####
+ ## 变量(variables) + 无 ## 方法签名(functions) + ### 1. add + ```tsx add(config: IWidgetBaseConfig & { area?: string; @@ -116,8 +160,6 @@ IWidgetBaseConfig 定义如下: | index | 面板的位置,不传默认按插件注册顺序 | | - - ### 2. remove remove(config: IWidgetBaseConfig) @@ -150,13 +192,17 @@ hideWidget(name: string) enableWidget(name: string) -将 widget 启用。
注:该函数将会触发全局事件 'skeleton.widget.enable' +将 widget 启用。 + +注:该函数将会触发全局事件 'skeleton.widget.enable' ### 8. disableWidget disableWidget(name: string) -将 widget 禁用掉,禁用后,所有鼠标事件都会被禁止掉。
适用场景:在该面板还在进行初始化构造时,可以先禁止掉,防止用户点击报错,待初始化完成,重新启用。 +将 widget 禁用掉,禁用后,所有鼠标事件都会被禁止掉。 + +适用场景:在该面板还在进行初始化构造时,可以先禁止掉,防止用户点击报错,待初始化完成,重新启用。 ## 事件(events) ### 1. onShowPanel @@ -166,7 +212,8 @@ onShowPanel(listener: (...args: unknown[]) => void) 监听 Panel 实例显示事件 ### 2. onHidePanel -
onHidePanel(listener: (...args: unknown[]) => void) + +onHidePanel(listener: (...args: unknown[]) => void) 监听 Panel 实例隐藏事件 @@ -177,10 +224,12 @@ onShowWidget(listener: (...args: unknown[]) => void) 监听 Widget 实例显示事件 ### 4. onHideWidget -
onHideWidget(listener: (...args: unknown[]) => void) + +onHideWidget(listener: (...args: unknown[]) => void) 监听 Widget 实例隐藏事件 ## 使用示例 + ```typescript import { skeleton } from '@alilc/lowcode-engine'; @@ -199,7 +248,7 @@ skeleton.add({ props: { align: 'top', icon: 'wenjian', - description: 'JS面板', + description: 'JS 面板', }, panelProps: { floatable: true, @@ -208,7 +257,7 @@ skeleton.add({ hideTitleBar: false, maxHeight: 800, maxWidth: 1200, - title: 'JS面板', + title: 'JS 面板', width: 600, }, content: SourceEditor, diff --git a/docs/docs/article/index.md b/docs/docs/article/index.md index d0a65524c..fd09a59a3 100644 --- a/docs/docs/article/index.md +++ b/docs/docs/article/index.md @@ -13,13 +13,13 @@ title: 低代码引擎相关文章资料 - [2B 领域下的低代码探索之路](https://mp.weixin.qq.com/s/HAxrMHLT43dPH488RiEIdw) - [阿里低代码引擎 LowCodeEngine 正式开源!](https://mp.weixin.qq.com/s/T66LghtWLz2Oh048XqaniA) -## Portal设计项目实战 +## Portal 设计项目实战 #### 直播回放 [https://www.bilibili.com/video/BV1AS4y1K7DP/](https://www.bilibili.com/video/BV1AS4y1K7DP/) #### 示例项目 -- 前端: [https://github.com/mark-ck/lowcode-portal](https://github.com/mark-ck/lowcode-portal) -- 后端: [https://github.com/mark-ck/document-solution-site](https://github.com/mark-ck/document-solution-site) +- 前端: [https://github.com/mark-ck/lowcode-portal](https://github.com/mark-ck/lowcode-portal) +- 后端: [https://github.com/mark-ck/document-solution-site](https://github.com/mark-ck/document-solution-site) - 组件库:[https://github.com/mark-ck/portal-components](https://github.com/mark-ck/portal-components) **注意** @@ -27,12 +27,12 @@ title: 低代码引擎相关文章资料 2. 后端项目要把 config.default.js 里的 yuque 和 oss 配置补全; #### 视频链接 -- [阿里低代码引擎项目实战(1)-引擎 demo 部署到 faas 服务](https://www.bilibili.com/video/BV1B44y1P7GM/) -- [【有翻车】阿里低代码引擎项目实战(2)-保存页面到远端存储](https://www.bilibili.com/video/BV1AS4y1K7DP/) -- [阿里巴巴低代码引擎项目实战(3)-自定义组件接入](https://www.bilibili.com/video/BV1dZ4y1m76S/) -- [阿里低代码引擎项目实战(4)-自定义插件-页面管理](https://www.bilibili.com/video/BV17a411i73f/) -- [阿里低代码引擎项目实战(4)-用户登录](https://www.bilibili.com/video/BV1Wu411e7EQ/) -- [【有翻车】阿里低代码引擎项目实战(5)-表单回显](https://www.bilibili.com/video/BV1UY4y1v7D7/) -- [阿里低代码引擎项目实战(6)-自定义插件-页面管理-后端](https://www.bilibili.com/video/BV1uZ4y1U7Ly/) -- [阿里低代码引擎项目实战(6)-自定义插件-页面管理-前端](https://www.bilibili.com/video/BV1Yq4y1a74P/) -- [阿里低代码引擎项目实战(7)-自定义插件-页面管理(完结)](https://www.bilibili.com/video/BV13Y4y1e7EV/) \ No newline at end of file +- [阿里低代码引擎项目实战 (1)-引擎 demo 部署到 faas 服务](https://www.bilibili.com/video/BV1B44y1P7GM/) +- [【有翻车】阿里低代码引擎项目实战 (2)-保存页面到远端存储](https://www.bilibili.com/video/BV1AS4y1K7DP/) +- [阿里巴巴低代码引擎项目实战 (3)-自定义组件接入](https://www.bilibili.com/video/BV1dZ4y1m76S/) +- [阿里低代码引擎项目实战 (4)-自定义插件 - 页面管理](https://www.bilibili.com/video/BV17a411i73f/) +- [阿里低代码引擎项目实战 (4)-用户登录](https://www.bilibili.com/video/BV1Wu411e7EQ/) +- [【有翻车】阿里低代码引擎项目实战 (5)-表单回显](https://www.bilibili.com/video/BV1UY4y1v7D7/) +- [阿里低代码引擎项目实战 (6)-自定义插件 - 页面管理 - 后端](https://www.bilibili.com/video/BV1uZ4y1U7Ly/) +- [阿里低代码引擎项目实战 (6)-自定义插件 - 页面管理 - 前端](https://www.bilibili.com/video/BV1Yq4y1a74P/) +- [阿里低代码引擎项目实战 (7)-自定义插件 - 页面管理 (完结)](https://www.bilibili.com/video/BV13Y4y1e7EV/) \ No newline at end of file diff --git a/docs/docs/demoUsage/appendix/loop.md b/docs/docs/demoUsage/appendix/loop.md index 0afb5c931..8b364ecf4 100644 --- a/docs/docs/demoUsage/appendix/loop.md +++ b/docs/docs/demoUsage/appendix/loop.md @@ -3,15 +3,15 @@ title: 如何使用循环值 sidebar_position: 0 --- 1.设置循环数据 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1655975447215-026bd3ae-ae2a-4f90-805e-df0d5c4bb7d2.png#clientId=ubd100ffc-952a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=950&id=u6413eee5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1900&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=339030&status=done&style=none&taskId=ued46d732-83a2-441f-a80f-23061587689&title=&width=1920) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01Gw1kXO1qaXulQCWap_!!6000000005512-2-tps-3840-1900.png) 2.给需要的变量绑定 this.item -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1655975499246-f9d14ef4-6736-46a5-8b24-8eedd4477617.png#clientId=ubd100ffc-952a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=946&id=u0b50f02a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1892&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=451804&status=done&style=none&taskId=uf4916102-2e3d-4277-ac81-604c6761615&title=&width=1920) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01RpP2Ev24lRxjqpHdY_!!6000000007431-2-tps-3840-1892.png) 绑定之后的效果如下: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1655975540038-ccf3aabc-3f7c-4e33-a701-a9b005b1cf25.png#clientId=uc887596b-8aed-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=942&id=u32901b3a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1884&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=333998&status=done&style=none&taskId=u2853d459-4432-4d0a-ba12-494e79e892a&title=&width=1920) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN019qa1J31m7ugsXcnaA_!!6000000004908-2-tps-3840-1884.png) 其中 this.item 的 item 是可以配置的。配置不同的 key 可以方便在多层循环中使用不同层级的循环 item 值。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1655975569197-33d90389-7394-4e65-bc6a-582b7ceb9fee.png#clientId=uc887596b-8aed-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=948&id=u6e6741d2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1896&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=311961&status=done&style=none&taskId=u14bbcfbb-e7cf-4307-a58d-3cb58afe8f7&title=&width=1920) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01XQfnYL1P4wxn01oXv_!!6000000001788-2-tps-3840-1896.png) this.index 是当前循环的索引值。 diff --git a/docs/docs/demoUsage/intro.md b/docs/docs/demoUsage/intro.md index 5154f0ea7..8fdc356c4 100644 --- a/docs/docs/demoUsage/intro.md +++ b/docs/docs/demoUsage/intro.md @@ -3,78 +3,78 @@ title: 1. 试用低代码引擎 Demo sidebar_position: 0 --- 低代码编辑器中的区块主要包含这些功能点: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644562161350-50ae7ccd-2e6f-4f50-af56-30e5cc5624dc.png#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=892&id=udd8e7731&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1784&originWidth=3384&originalType=binary&ratio=1&rotation=0&showTitle=false&size=509888&status=done&style=none&taskId=u1621cea1-8e9d-48d0-9273-bf852ef8e82&title=&width=1692) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01aGQull1RVdGs7Pt6x_!!6000000002117-2-tps-3384-1784.png) ## 分区块功能介绍 ### 左侧:面板与操作区 #### 物料面板 可以查找组件,并在此拖动组件到编辑器画布中 -![Dec-17-2021 19-12-46.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562213143-49b9aff8-b538-43f4-a66d-53fac98ce7ae.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u3a98c25c&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-12-46.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u265abeb3-a0b1-4cdf-9291-c5fa865d06c&title=&width=734) +![Dec-17-2021 19-12-46.gif](https://img.alicdn.com/imgextra/i1/O1CN01pEu7811SlwzxraLHG_!!6000000002288-1-tps-1468-754.gif) #### 大纲面板 可以调整页面内的组件树结构: -![Dec-17-2021 19-14-34.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562213701-39f3e2c3-f52c-4be4-bb56-90842daa58ab.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u1d18d088&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-14-34.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u2d6ebf59-3cd5-4e80-8599-a4d594a2cbf&title=&width=734) +![Dec-17-2021 19-14-34.gif](https://img.alicdn.com/imgextra/i1/O1CN013DDLqt1GH0rAlajqi_!!6000000000596-1-tps-1468-754.gif) 可以在这里打开或者关闭模态浮层的展现: -![Dec-17-2021 19-19-18.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562213674-44d91956-ac82-4909-98b5-e0bd4fcbe12d.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u7d3beb31&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-19-18.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u6adfe95e-0c27-4c03-8e3c-ca62cb37387&title=&width=734) +![Dec-17-2021 19-19-18.gif](https://img.alicdn.com/imgextra/i2/O1CN01bQfS8W1JitokHRinC_!!6000000001063-1-tps-1468-754.gif) #### 源码面板 可以编辑页面级别的 JavaScript 代码和 CSS 配置 -![Feb-11-2022 14-51-59.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562356337-9e7f7490-396c-4520-b780-4a43a29050ef.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u02b5cb05&margin=%5Bobject%20Object%5D&name=Feb-11-2022%2014-51-59.gif&originHeight=614&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2080513&status=done&style=none&taskId=u2f95447f-b7a6-453d-8a8c-7d1649581d9&title=) +![Feb-11-2022 14-51-59.gif](https://img.alicdn.com/imgextra/i1/O1CN01d11kK71Q223eWvL5F_!!6000000001917-1-tps-1532-614.gif) #### Schema 编辑 【开发者专属】可以编辑页面的底层 Schema 数据。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644562411102-a8596fce-fd77-4f20-bd3c-b52e2a0beb52.png#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=824&id=u3488f050&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1648&originWidth=3070&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1082743&status=done&style=none&taskId=u529bf58c-2203-484f-bf9f-19c2a3fe870&title=&width=1535) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01lcQOER23Q5sjA0Gn5_!!6000000007249-2-tps-3070-1648.png) 搭配顶部操作区的“保存到本地”和“重置页面”功能,可以实验各种 schema 对低代码页面的改变。 它们操作的数据关系是: -- 页面中的 Schema 数据:保存在低代码引擎中的 Schema,点击 Schema 面板中的“保存 Schema” 时将修改引擎中的值,此外低代码引擎中的所有操作都可能修改到 Schema +- 页面中的 Schema 数据:保存在低代码引擎中的 Schema,点击 Schema 面板中的“保存 Schema”时将修改引擎中的值,此外低代码引擎中的所有操作都可能修改到 Schema - localStorage 数据:由“保存到本地”保存到 localStorage 中,页面初始化时将读取,预览页面时也会读取 - 默认 Schema:保存在 Demo 项目中的默认 Schema(`public/schema.json`),初始化页面时如果不存在 localStorage 数据即会读取,点击“重置页面”时,也会读取 #### 中英文切换 可以切换编辑器的语言;注:需要组件配置配合。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644562219182-e4233163-b731-4f09-a442-9d5c0e71e7e8.png#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=756&id=ua3adfd78&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1512&originWidth=3018&originalType=binary&ratio=1&rotation=0&showTitle=false&size=384093&status=done&style=none&taskId=uf546934b-ae91-4e3e-9e21-2447de70ed1&title=&width=1509) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644562219666-1baf7da2-6d70-45fa-8805-b6cc9ac99f3f.png#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=755&id=u34aad08e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1510&originWidth=3016&originalType=binary&ratio=1&rotation=0&showTitle=false&size=380190&status=done&style=none&taskId=ud264115a-ae01-4b65-9ccc-4e6efa37b62&title=&width=1508) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN019ORknX1M5SYg7eSJ3_!!6000000001383-2-tps-3018-1512.png) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01R7g7pW21rSJEHd2AI_!!6000000007038-2-tps-3016-1510.png) ## 中部:可视化页面编辑画布区域 点击组件在右侧面板中能够显示出对应组件的属性配置选项 -![Dec-17-2021 19-28-28.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562216925-c4bd5f10-2469-452c-8c2d-fe92ba6d03a7.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=uff491710&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-28-28.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u2f775208-8b07-4968-9dd4-420c6e4d3c1&title=&width=734) +![Dec-17-2021 19-28-28.gif](https://img.alicdn.com/imgextra/i1/O1CN01uBU3lR1CuAFTTq4RS_!!6000000000140-1-tps-1468-754.gif) 拖拽修改组件的排列顺序 -![Dec-17-2021 19-29-40.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562219867-61a41b16-4513-4827-80bf-f7e4832bcf3a.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=ueda50ec8&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-29-40.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=ue0ec6bea-81f1-4d04-bf82-acde7c9983a&title=&width=734) +![Dec-17-2021 19-29-40.gif](https://img.alicdn.com/imgextra/i3/O1CN01DAAYKd1bycUq1C4JV_!!6000000003534-1-tps-1468-754.gif) 将组件拖拽到容器类型的组件中,注意拖拽时会在右侧提示当前的组件树。 -![Dec-17-2021 19-31-30.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562220001-4afae72e-f9fd-4564-a904-c87f61ba79b5.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=ucc719a0e&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-31-30.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u2c46a827-8702-471c-a8c1-eb4f069d108&title=&width=734) +![Dec-17-2021 19-31-30.gif](https://img.alicdn.com/imgextra/i2/O1CN01TzJosP1FIYZe6xIQ5_!!6000000000464-1-tps-1468-754.gif) ## 右侧:组件级别配置 ### 选中的组件 从页面开始一直到当前选中的组件位置,点击对应的名称可以切换到对应的组件上。 -![Dec-17-2021 19-35-25.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562220818-c6532319-51df-4698-a3a4-80f3ab70b209.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u648c740b&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-35-25.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u03dd1651-8139-47f1-9cd1-a5089b64bf9&title=&width=734) +![Dec-17-2021 19-35-25.gif](https://img.alicdn.com/imgextra/i4/O1CN01EbImy425R80OeblSD_!!6000000007522-1-tps-1468-754.gif) ### 选中组件的配置 当前组件的大类目选项,根据组件类型不同,包含如下子类目: #### 属性 组件的基础属性值设置 -![Dec-17-2021 19-37-26.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562222884-191c8433-2386-47f4-bab4-d3d1fe534f12.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u43676a31&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-37-26.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u170b8d2a-c1f9-4acf-a0e2-9825c588dcd&title=&width=734) +![Dec-17-2021 19-37-26.gif](https://img.alicdn.com/imgextra/i2/O1CN01ziBI9T1nQynFKqCp2_!!6000000005085-1-tps-1468-754.gif) #### 样式 组件的样式配置,如文字: -![Dec-17-2021 19-38-55.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562224062-86fcf97b-d229-487f-951d-d2070337c058.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u4a9930ae&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-38-55.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u4a81ecb9-5b51-4758-9dd0-eaeb2e1a318&title=&width=734) +![Dec-17-2021 19-38-55.gif](https://img.alicdn.com/imgextra/i4/O1CN017DQv2R1OEjoawXmKJ_!!6000000001674-1-tps-1468-754.gif) #### 事件 绑定组件对外暴露的事件。 -![Dec-17-2021 19-41-17.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562224632-a3ee9b18-97e8-4d31-b4fe-b58720dc6bf5.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u534bb1ea&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-41-17.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u50691375-2514-4a6c-8bec-0be44adf141&title=&width=734) +![Dec-17-2021 19-41-17.gif](https://img.alicdn.com/imgextra/i2/O1CN01mhVutF24I8cLde0zy_!!6000000007367-1-tps-1468-754.gif) #### 高级 循环、条件渲染与 key 设置。 -![Dec-17-2021 19-46-26.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562226094-899cf104-3c60-439f-8b68-83af595ef275.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u9190ed31&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-46-26.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=uf02555c1-cd82-486d-8561-ca97e0ec1cd&title=&width=734) +![Dec-17-2021 19-46-26.gif](https://img.alicdn.com/imgextra/i4/O1CN01xTjXQX1jMcYwuTGKZ_!!6000000004534-1-tps-1468-754.gif) ## 顶部:操作区 ### 撤回和重做 -![Dec-17-2021 19-52-23.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562226083-d7f69bff-42e6-4173-8ac8-6e5a0c0262d6.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u81f5d842&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-52-23.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=ubeb556cd-2349-44d8-b1be-ba6e32bea4e&title=&width=734) +![Dec-17-2021 19-52-23.gif](https://img.alicdn.com/imgextra/i3/O1CN019VWkbr1jsgHoGKf6g_!!6000000004604-1-tps-1468-754.gif) diff --git a/docs/docs/demoUsage/makeStuff/dialog.md b/docs/docs/demoUsage/makeStuff/dialog.md index 772bd5647..56303067c 100644 --- a/docs/docs/demoUsage/makeStuff/dialog.md +++ b/docs/docs/demoUsage/makeStuff/dialog.md @@ -2,28 +2,28 @@ title: 3. 如何通过按钮展示/隐藏弹窗 sidebar_position: 1 --- -### 1.拖拽一个按钮 +## 1.拖拽一个按钮 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652355202273-1a84b1e5-e33c-4686-b92b-633936423141.png#clientId=udd01ff56-e3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=906&id=u81f6abfa&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1812&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=749009&status=done&style=none&taskId=u6f4bf7e1-db67-4fca-8107-04021936c00&title=&width=1792) -### 2.拖拽一个弹窗 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652355233863-6d65ee77-b2fa-4d51-a04c-f0582c99eb72.png#clientId=udd01ff56-e3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=811&id=u848a34e1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1622&originWidth=3578&originalType=binary&ratio=1&rotation=0&showTitle=false&size=774132&status=done&style=none&taskId=ue713e331-7ce0-4bd8-b41d-3ae1e07c69b&title=&width=1789) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01kLaWA31D6WwTui9VW_!!6000000000167-2-tps-3584-1812.png) +## 2.拖拽一个弹窗 +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01rfRzLa1quEwUyulPc_!!6000000005555-2-tps-3578-1622.png) -### 3.查看弹窗 refId -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652355269097-3e5282ed-2fdd-4a3b-b9b8-d78fac69c42e.png#clientId=udd01ff56-e3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=794&id=ufd9346c1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1588&originWidth=3574&originalType=binary&ratio=1&rotation=0&showTitle=false&size=843332&status=done&style=none&taskId=ubc630826-e577-4dee-a2c3-5478bdf266a&title=&width=1787) +## 3.查看弹窗 refId +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01rEgPnW1cSqdWpG0YE_!!6000000003600-2-tps-3574-1588.png) - 点击弹窗 - 点击右侧面板中的高级 - 找到 refId -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652355320821-dd2c85f7-a75e-495d-896a-67e4761561ac.png#clientId=udd01ff56-e3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=898&id=u4bf6b721&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1796&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=993930&status=done&style=none&taskId=u8c648fa2-c660-4979-8991-1cf138d2372&title=&width=1792) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01MXMfqn1rj4uKzlOh2_!!6000000005666-2-tps-3584-1796.png) 这里我们的 refId 是 "pro-dialog-entryl32xgrus" -### 4.隐藏弹窗 +## 4.隐藏弹窗 点击工具栏的隐藏小图标,将弹窗在画布中隐藏 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652355400766-f7bdca37-7ba9-497d-a7e2-ad1d92233a26.png#clientId=udd01ff56-e3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=784&id=ucbbe5086&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1568&originWidth=3578&originalType=binary&ratio=1&rotation=0&showTitle=false&size=774518&status=done&style=none&taskId=u2c8e73cd-10c5-47d3-b96e-30e6840d1af&title=&width=1789) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN017Kamt71HFvWkpeK8j_!!6000000000729-2-tps-3578-1568.png) -### 5.按钮绑定事件 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652355486231-172c5797-c376-4f6f-94f7-8c3c593caa02.png#clientId=udd01ff56-e3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=907&id=ufcf7d50e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1814&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=845218&status=done&style=none&taskId=u7c2c54ce-9c18-4b29-a066-f3024a95443&title=&width=1792) +## 5.按钮绑定事件 +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01SwJ0xx1u3LfX2h8yt_!!6000000005981-2-tps-3584-1814.png) **通过下面的代码即可打开弹窗** diff --git a/docs/docs/demoUsage/makeStuff/table.md b/docs/docs/demoUsage/makeStuff/table.md index 06999010d..173d2e756 100644 --- a/docs/docs/demoUsage/makeStuff/table.md +++ b/docs/docs/demoUsage/makeStuff/table.md @@ -2,30 +2,33 @@ title: 2. 如何制作表格 sidebar_position: 0 --- -# 步骤详解 -## 拖入组件 +## 步骤详解 +### 拖入组件 + 一个常见的表格页面会包含查询框、表格和分页按钮。这些都在 Fusion UI 中进行了相应的封装,我们可以在左侧组件面板处找到他们。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645011856718-ed2aa0b1-0c5c-4ec0-a72b-377bc500faf3.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=824&id=ue90ea461&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1648&originWidth=3032&originalType=binary&ratio=1&rotation=0&showTitle=false&size=963971&status=done&style=stroke&taskId=u3b1dfd98-44b7-4a13-be2a-e0124084288&title=&width=1516) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01UU8pVT26XN1A0ExVG_!!6000000007671-2-tps-3032-1648.png) 将他们拖到画布之中: -![Feb-16-2022 16-58-59.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645002115004-4f01eb8d-cf68-4a7c-b0db-bc5aaf2604a3.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=uf69dc239&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2016-58-59.gif&originHeight=792&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7510570&status=done&style=stroke&taskId=ua6ea2651-6c6c-4762-98cc-cc3ab5734cd&title=&width=767) -## 配置组件 +![Feb-16-2022 16-58-59.gif](https://img.alicdn.com/imgextra/i3/O1CN01UAsQ8124HgDptzPrn_!!6000000007366-1-tps-1534-792.gif) +### 配置组件 选中刚拖入的“查询筛选”组件,您可以配置此组件: -![Feb-14-2022 17-59-47.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644832912542-4b2e66ae-ba15-4e38-ab79-9f83e413a493.gif#clientId=uec0ffd6f-d4e1-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u83c491b2&margin=%5Bobject%20Object%5D&name=Feb-14-2022%2017-59-47.gif&originHeight=792&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2147213&status=done&style=stroke&taskId=uffd7092e-a247-4f48-b831-aaffe3646f7&title=) +![Feb-14-2022 17-59-47.gif](https://img.alicdn.com/imgextra/i2/O1CN01RiDUy31aufSeVk8IN_!!6000000003390-1-tps-1532-792.gif) 对于形如 Array 的配置项目,我们可以增删项目、修改常用项、修改顺序。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645012184644-444d82fa-a226-4784-b0df-92a5a52748bc.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=738&id=uc4ea8ded&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1476&originWidth=3060&originalType=binary&ratio=1&rotation=0&showTitle=false&size=375890&status=done&style=none&taskId=u7a1f43d8-eac4-405e-a3c9-38d3047f452&title=&width=1530) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01eWOK0d1fOfsF9PZu9_!!6000000003997-2-tps-3060-1476.png) 掌握组件配置功能,我们就可以完成一个常用的查询框的配置: -![Feb-21-2022 18-05-52.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645437973453-1fd1dc10-99ad-4c18-af49-2741bd81c4ae.gif#clientId=u022fc577-71a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=395&id=u964ae52f&margin=%5Bobject%20Object%5D&name=Feb-21-2022%2018-05-52.gif&originHeight=790&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7210902&status=done&style=stroke&taskId=u9e39c54a-7467-4a96-b716-681cf598f09&title=&width=766) +![Feb-21-2022 18-05-52.gif](https://img.alicdn.com/imgextra/i1/O1CN0138fb0P1CTbHKWDBeo_!!6000000000082-1-tps-1532-790.gif) -## 绑定数据 +### 绑定数据 低代码场景下,我们需要绑定动态的数据。通过左侧的源码编辑面板,我们可以创建动态数据和它的相关处理函数: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645012532562-596d4a96-908e-4094-836c-974bda61d8a2.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=739&id=ufa7b81f8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1478&originWidth=2976&originalType=binary&ratio=1&rotation=0&showTitle=false&size=816197&status=done&style=none&taskId=u5ab9656e-26b6-427a-a52e-5e11dbc4a7a&title=&width=1488) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN015Bw2aQ1jaMRWoYzv5_!!6000000004564-2-tps-2976-1478.png) + 如图,我们配入如下自定义值进 state 里: ```json "companies": [ @@ -35,18 +38,25 @@ sidebar_position: 0 ] ``` 定义动态数据以后,我们需要绑定它到组件的属性中,我们找到相关属性的配置: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645012714358-f3f39d5f-1790-4196-9f16-b45f51fa8f28.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=896&id=u1126fd65&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1792&originWidth=3546&originalType=binary&ratio=1&rotation=0&showTitle=false&size=413958&status=done&style=none&taskId=u976689ac-18a1-4f15-9fc2-60681670fc7&title=&width=1773) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645012791356-4fed1bea-bec2-4be9-85ea-b366d0acb4ab.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=820&id=ub81b6dc8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1640&originWidth=3428&originalType=binary&ratio=1&rotation=0&showTitle=false&size=354847&status=done&style=none&taskId=uc645e654-b293-4c18-86da-a6637083e55&title=&width=1714) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN013Cu5OE1CXGRhyEmbJ_!!6000000000090-2-tps-3546-1792.png) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01iaK15j1bgIeO65svI_!!6000000003494-2-tps-3428-1640.png) + 如图,输入表达式: -```json + +```javascript this.state.companies ``` -再结合上一节的“配置组件”操作,我们已经可以把表格的主体配置出来了: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645013130950-4219cf27-760c-4749-8d4e-013dd53dbc83.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=820&id=u73c837e3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1640&originWidth=3058&originalType=binary&ratio=1&rotation=0&showTitle=false&size=408420&status=done&style=stroke&taskId=u23f7f045-8077-4e9d-9335-fea3ba54273&title=&width=1529) -## 动态请求 +再结合上一节的“配置组件”操作,我们已经可以把表格的主体配置出来了: + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01p8QJ5C1buxKDTS1cU_!!6000000003526-2-tps-3058-1640.png) + +### 动态请求 我们进入代码区块,使用生命周期方法来完成动态数据的请求。假设提供数据的接口是:[http://rap2api.taobao.org/app/mock/250089/testCompanies](http://rap2api.taobao.org/app/mock/250089/testCompanies),那么,我们可以在源码面板进行如下配置: + ```typescript class LowcodeComponent extends Component { state = { @@ -54,9 +64,9 @@ class LowcodeComponent extends Component { "isShowDialog": false, "loading": false, "companies": [ - { company: '测试公司1', id: 1, createTime: +new Date() }, - { company: '测试公司2', id: 2, createTime: +new Date() }, - { company: '测试公司3', id: 3, createTime: +new Date() }, + { company: '测试公司 1', id: 1, createTime: +new Date() }, + { company: '测试公司 2', id: 2, createTime: +new Date() }, + { company: '测试公司 3', id: 3, createTime: +new Date() }, ] } componentDidMount() { @@ -75,42 +85,52 @@ class LowcodeComponent extends Component { } } ``` -在 `componentDidMount` 生命周期,将请求接口并设置 loading 和数据字段。 -点击保存或叉关闭源码面板后,我们可以看到代码已经生效了: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645013883960-ca217c38-5c40-4ecc-9e05-277098fef16a.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=817&id=u1a3f852b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1634&originWidth=3058&originalType=binary&ratio=1&rotation=0&showTitle=false&size=427572&status=done&style=stroke&taskId=ubd2291b7-36c3-48c1-b489-9c61f0f6230&title=&width=1529) -## 配置插槽 +在 `componentDidMount` 生命周期,将请求接口并设置 loading 和数据字段。 + +点击保存或叉关闭源码面板后,我们可以看到代码已经生效了: + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01lqjW8e1f39G8Zm7hQ_!!6000000003950-2-tps-3058-1634.png) + +### 配置插槽 我们可以用绑定数据的方法把 loading 绑在加载指示上: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645014111323-c45f9b9a-77dd-4724-b6ee-78572863a871.png#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=952&id=u3bdd353b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1904&originWidth=3170&originalType=binary&ratio=1&rotation=0&showTitle=false&size=503197&status=done&style=none&taskId=u1faed9f0-3c68-4385-8d08-e59e2a1600a&title=&width=1585) -![Feb-16-2022 20-24-35.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645014292272-68e07740-47dc-4c94-8437-beded0b07c63.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u4506fc72&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-24-35.gif&originHeight=792&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6960677&status=done&style=stroke&taskId=u9fe02184-e6dc-4886-b371-c48ca1e2832&title=&width=766) -将 Loading 的“是否显示”字段绑定 `this.state.loading` 后,我们可以看到,这里暴露了一个插槽。插槽是可以任意扩展的预设部分,我们可以把其他的部分拖进插槽: -![Feb-16-2022 20-27-03.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645014436894-9b975ae6-76cc-412b-829a-fae3605277dc.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u407467ac&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-27-03.gif&originHeight=792&originWidth=1528&originalType=binary&ratio=1&rotation=0&showTitle=false&size=3443266&status=done&style=stroke&taskId=u0a091444-8b12-49a0-a57a-bfa758d351a&title=&width=764) -点击右上角的预览,我们能够看到完整的动态请求效果了: -![Feb-16-2022 20-28-36.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645014527841-b621f38f-2c03-40f1-aa41-19293f96b08f.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u6ee6beea&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-28-36.gif&originHeight=792&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1968612&status=done&style=stroke&taskId=u2bdcee3f-91c5-4cb3-8405-f44f995cc78&title=&width=767) -## 列挂钩浮层 +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01K3Pwjo1PKWQcoBl5K_!!6000000001822-2-tps-3170-1904.png) + +![Feb-16-2022 20-24-35.gif](https://img.alicdn.com/imgextra/i2/O1CN01VGlZPS1JitoljrFFY_!!6000000001063-1-tps-1532-792.gif) + +将 Loading 的“是否显示”字段绑定 `this.state.loading` 后,我们可以看到,这里暴露了一个插槽。插槽是可以任意扩展的预设部分,我们可以把其他的部分拖进插槽: + +![Feb-16-2022 20-27-03.gif](https://img.alicdn.com/imgextra/i2/O1CN01HSBncU1XWRfPdwlPK_!!6000000002931-1-tps-1528-792.gif) + +点击右上角的预览,我们能够看到完整的动态请求效果了: +![Feb-16-2022 20-28-36.gif](https://img.alicdn.com/imgextra/i3/O1CN01o5THZf1fkesw2nZEC_!!6000000004045-1-tps-1534-792.gif) + +### 列挂钩浮层 为了能够让表格里的操作挂钩浮层,我们先拖入一个浮层: -![Feb-16-2022 20-32-09.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645014772471-0fce9b50-0f70-492e-bb53-5f875c00f5b4.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u4d33cd05&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-32-09.gif&originHeight=792&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7475148&status=done&style=stroke&taskId=u9dc26cba-41eb-4fe8-b96f-fe391968861&title=&width=766) +![Feb-16-2022 20-32-09.gif](https://img.alicdn.com/imgextra/i2/O1CN01bX3SHk21Z8T4O6knp_!!6000000006998-1-tps-1532-792.gif) + 使用大纲树能够临时显示和隐藏此浮层: -![Feb-16-2022 20-32-39.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645014828329-b2de4db6-9032-4280-b886-db17070eea21.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=ue27e6676&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-32-39.gif&originHeight=792&originWidth=1530&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7335022&status=done&style=stroke&taskId=u73554a5d-5ebe-48d1-a861-426ba8501b1&title=&width=765) -我们给表格增加一个数据列: -![Feb-16-2022 20-39-41.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645015242447-3e019714-4b86-4c10-9bf7-01e19201bf0c.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=uc2c35de3&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-39-41.gif&originHeight=792&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=3415710&status=done&style=stroke&taskId=u5aedc5dd-f361-4e45-88b0-be09af09a6a&title=&width=766) +![Feb-16-2022 20-32-39.gif](https://img.alicdn.com/imgextra/i3/O1CN01ZtSp0P1LvNqYPeUHg_!!6000000001361-1-tps-1530-792.gif) + +我们给表格增加一个数据列: +![Feb-16-2022 20-39-41.gif](https://img.alicdn.com/imgextra/i2/O1CN012K6qWI1hgCG6KwRF7_!!6000000004306-1-tps-1532-792.gif) 然后配置它的行为为“弹窗”: -![Feb-16-2022 20-40-05.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645015223838-7f180e28-43e0-442b-a47e-ea5ff69d4900.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u80f44f38&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-40-05.gif&originHeight=792&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7261162&status=done&style=stroke&taskId=u3828503a-ecac-452a-8d20-02e4a46ad02&title=&width=766) +![Feb-16-2022 20-40-05.gif](https://img.alicdn.com/imgextra/i2/O1CN016axZh61uc9ln0L3Rz_!!6000000006057-1-tps-1532-792.gif) 实现的效果如下: -![Feb-16-2022 20-42-51.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645015379808-7d7852b1-5902-42d0-b951-c9c5d8f4c893.gif#clientId=uf61aba9b-3a69-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=ua2e7ceda&margin=%5Bobject%20Object%5D&name=Feb-16-2022%2020-42-51.gif&originHeight=792&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=588625&status=done&style=stroke&taskId=uf0466dde-ca4c-41d9-bf42-1ff443d02c5&title=&width=767) +![Feb-16-2022 20-42-51.gif](https://img.alicdn.com/imgextra/i4/O1CN018iana91j4l71QTmpE_!!6000000004495-1-tps-1534-792.gif) -## 事件回调 +### 事件回调 上述功能点中,我们是把操作行为绑定在数据列上的,这一节我们绑定到操作列中。在操作列按钮处,点击下方的“添加一项”: -![Feb-23-2022 11-58-02.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645588703676-2a36cab4-52f4-4f31-9018-d56b41a55283.gif#clientId=u74bf469f-47f0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=395&id=u18d8ea0b&margin=%5Bobject%20Object%5D&name=Feb-23-2022%2011-58-02.gif&originHeight=790&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8440133&status=done&style=stroke&taskId=u73e25800-c0fa-486b-9b68-4df7db9b9f1&title=&width=767) +![Feb-23-2022 11-58-02.gif](https://img.alicdn.com/imgextra/i4/O1CN01DsBoHQ1tyli2rtoFR_!!6000000005971-1-tps-1534-790.gif) 点击左侧的详情按钮,配置它的事件回调: -![Feb-23-2022 12-00-18.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645588832183-7ed0f06b-731d-4bd8-b934-723de43a8b42.gif#clientId=u74bf469f-47f0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=395&id=u59505da7&margin=%5Bobject%20Object%5D&name=Feb-23-2022%2012-00-18.gif&originHeight=790&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9047220&status=done&style=stroke&taskId=ub8ab1b4e-4195-426f-b792-fc8bf91d142&title=&width=767) +![Feb-23-2022 12-00-18.gif](https://img.alicdn.com/imgextra/i2/O1CN017BuNLP1LPmW8zH7hx_!!6000000001292-1-tps-1534-790.gif) 代码侧,我们配置这个回调函数: ```javascript @@ -119,10 +139,10 @@ onClick_new(e, { rowKey, rowIndex, rowRecord }){ } ``` 保存。预览时我们可以看到效果了: -![Feb-23-2022 12-05-25.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645589138764-d6514256-2a1f-4127-9591-747b4808848e.gif#clientId=u74bf469f-47f0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=395&id=u9f09d078&margin=%5Bobject%20Object%5D&name=Feb-23-2022%2012-05-25.gif&originHeight=790&originWidth=1532&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2238638&status=done&style=stroke&taskId=u460c90f3-d692-45f9-9028-cf45d4cea98&title=&width=766) -# 研究本例的 schema +![Feb-23-2022 12-05-25.gif](https://img.alicdn.com/imgextra/i3/O1CN01CXi1zJ1N302paKUre_!!6000000001513-1-tps-1532-790.gif) +## 研究本例的 schema 我们把本例的 schema 保存在云端,您可以自行下载研究:[https://mo.m.taobao.com/marquex/lowcode-showcase-table](https://mo.m.taobao.com/marquex/lowcode-showcase-table) 您可以通过左下角的 Schema 面板直接导入本例子的 Schema。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645589288482-0ce8ea2f-c4e1-4956-be9c-143c9b71654b.png#clientId=u74bf469f-47f0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=810&id=u713729c6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1620&originWidth=3054&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1074154&status=done&style=stroke&taskId=u783f33a5-241d-43ec-8b46-8385b733810&title=&width=1527) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01z2LXgW1iFSklNRzTN_!!6000000004383-2-tps-3054-1620.png) diff --git a/docs/docs/demoUsage/panels/canvas.md b/docs/docs/demoUsage/panels/canvas.md index 0e4678076..35158d29d 100644 --- a/docs/docs/demoUsage/panels/canvas.md +++ b/docs/docs/demoUsage/panels/canvas.md @@ -5,18 +5,18 @@ sidebar_position: 1 ## 组件操作 ### 画布操作 点击组件在右侧面板中能够显示出对应组件的属性配置选项 -![Dec-17-2021 19-28-28.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562216925-c4bd5f10-2469-452c-8c2d-fe92ba6d03a7.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=uff491710&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-28-28.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u2f775208-8b07-4968-9dd4-420c6e4d3c1&title=&width=734) +![Dec-17-2021 19-28-28.gif](https://img.alicdn.com/imgextra/i1/O1CN01flb5tL1inM47Gdo3a_!!6000000004457-1-tps-1468-754.gif) 拖拽修改组件的排列顺序 -![Dec-17-2021 19-29-40.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562219867-61a41b16-4513-4827-80bf-f7e4832bcf3a.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=ueda50ec8&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-29-40.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=ue0ec6bea-81f1-4d04-bf82-acde7c9983a&title=&width=734) +![Dec-17-2021 19-29-40.gif](https://img.alicdn.com/imgextra/i3/O1CN01UJ1x731NBFB4eELV0_!!6000000001531-1-tps-1468-754.gif) 拖拽时会在右侧提示当前的组件树。 -![Dec-17-2021 19-31-30.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562220001-4afae72e-f9fd-4564-a904-c87f61ba79b5.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=ucc719a0e&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-31-30.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u2c46a827-8702-471c-a8c1-eb4f069d108&title=&width=734) +![Dec-17-2021 19-31-30.gif](https://img.alicdn.com/imgextra/i1/O1CN01jLUYQE1h4dmcfYhZB_!!6000000004224-1-tps-1468-754.gif) ### 组件控制 点击组件右上角的复制按钮,或者按下 `ctrl + c` 再按下 `ctrl + v`,可以将其复制; 点击组件右上角的删除按钮,或者直接使用 `Delete` 键,可以将其删除。 -![Dec-17-2021 19-33-20.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644562220898-a54f0cfa-26bf-461f-a4aa-9708fc367d7c.gif#clientId=u99b5ef7a-7ebb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=377&id=u2bae31a2&margin=%5Bobject%20Object%5D&name=Dec-17-2021%2019-33-20.gif&originHeight=754&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u2c4c7b00-b316-431a-9c54-949ae4ed766&title=&width=734) +![Dec-17-2021 19-33-20.gif](https://img.alicdn.com/imgextra/i2/O1CN01QT1pq621gvCVpoOm6_!!6000000007015-1-tps-1468-754.gif) ### 选择组件切换 @@ -28,7 +28,7 @@ sidebar_position: 1 - `→` 向右选择组件 可以 hover 到组件操作辅助区的第一项来选中组件的父级节点: -![Feb-22-2022 14-42-30.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645512169966-17f26afa-00fc-47a5-86be-08505ab39a4f.gif#clientId=u5c3042e1-7626-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=395&id=uee0cbe0a&margin=%5Bobject%20Object%5D&name=Feb-22-2022%2014-42-30.gif&originHeight=790&originWidth=1536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2913977&status=done&style=stroke&taskId=ud9314fe0-0943-48e5-9f0c-b9b9b4a6b47&title=&width=768) +![Feb-22-2022 14-42-30.gif](https://img.alicdn.com/imgextra/i4/O1CN01RWbgGJ1TM8HoOpQ7V_!!6000000002367-1-tps-1536-790.gif) ### 可扩展项简述 @@ -37,12 +37,12 @@ sidebar_position: 1 ## Slot 区块 React 中,可以定义一个 prop 选项为 `JSXElement` 或 `(...args) => JSXElement` 的形式,这个形式在低代码画布中,被定义为 Slot,允许往其内部拖入组件,进行符合直觉的操作。 -![Feb-22-2022 14-46-02.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645512376500-46baf1b5-2335-4fb5-a430-c2f2245c8439.gif#clientId=u5c3042e1-7626-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=395&id=u8c429d95&margin=%5Bobject%20Object%5D&name=Feb-22-2022%2014-46-02.gif&originHeight=790&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2389349&status=done&style=stroke&taskId=u7462c2e4-64bf-432a-aa2e-2fef526b4d4&title=&width=767) +![Feb-22-2022 14-46-02.gif](https://img.alicdn.com/imgextra/i4/O1CN01geivkn1csUog5gZbm_!!6000000003656-1-tps-1534-790.gif) ### 锁定 Slot 您可以对 Slot 进行锁定操作,锁定后内部内容无法选中; -![Feb-22-2022 14-50-03.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1645512638545-ae46bcd2-883b-4229-9f78-d59087d03d28.gif#clientId=u5c3042e1-7626-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=395&id=u87ff9fe3&margin=%5Bobject%20Object%5D&name=Feb-22-2022%2014-50-03.gif&originHeight=790&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9318074&status=done&style=none&taskId=ua4e1f652-2e72-4dcf-ad78-19b42e179c3&title=&width=767) +![Feb-22-2022 14-50-03.gif](https://img.alicdn.com/imgextra/i3/O1CN01eBD3WY1rPNsZt8UVL_!!6000000005623-1-tps-1534-790.gif) 在组件树可以解除操作。 @@ -54,7 +54,7 @@ React 中,可以定义一个 prop 选项为 `JSXElement` 或 `(...args) => JSX - 侵入型:组件编辑态下,会往组件内传入 `__designMode: 'design'`,可以在组件中进行相应处理; -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645512859914-b51c23b9-50d9-4962-a6f7-96dbdcef6cef.png#clientId=u5c3042e1-7626-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=821&id=uf96a3071&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1642&originWidth=3066&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1024714&status=done&style=none&taskId=u7838e6c7-2349-4224-94ed-4e0e972b2a2&title=&width=1533) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01Xh3o891gvTrNBMMy2_!!6000000004204-2-tps-3066-1642.png) - 双入口型:通过配置物料的 editUrls,加载专属于编辑态组件的物料。pro-layout 使用的是这种方式 ```json diff --git a/docs/docs/demoUsage/panels/code.md b/docs/docs/demoUsage/panels/code.md index 717c2353a..929c9bcb0 100644 --- a/docs/docs/demoUsage/panels/code.md +++ b/docs/docs/demoUsage/panels/code.md @@ -6,7 +6,7 @@ sidebar_position: 3 ## 面板功能拆解 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644897390779-cefb2c31-82fc-44f4-b824-adc32569ac6f.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=870&id=u23446c19&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1740&originWidth=2502&originalType=binary&ratio=1&rotation=0&showTitle=false&size=865371&status=done&style=none&taskId=u44e2b188-c268-4a30-a628-76a046be9d4&title=&width=1251) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01pRxmmD1agTBVwCO5x_!!6000000003359-2-tps-2502-1740.png) ### 代码编辑面板 @@ -15,8 +15,8 @@ sidebar_position: 3 | 编译前 | 编译后 | | --- | --- | -| ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644897774925-b54126e0-ff6b-445e-bc68-569731aef8c3.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=95&id=nhuiT&margin=%5Bobject%20Object%5D&name=image.png&originHeight=190&originWidth=670&originalType=binary&ratio=1&rotation=0&showTitle=false&size=25045&status=done&style=none&taskId=u323192f6-7cfa-4d73-a184-2699f648c6f&title=&width=335) | ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644897840129-83fe9a81-d8b2-4873-8764-904f531ec959.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=55&id=u3ba8300e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=110&originWidth=2094&originalType=binary&ratio=1&rotation=0&showTitle=false&size=44006&status=done&style=none&taskId=uef1552e3-ccdb-45dd-95d5-187a6c6b7df&title=&width=1047) | -| ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644897884917-641b1547-7b90-4f78-86c1-0cc51996623d.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=60&id=u5fa00781&margin=%5Bobject%20Object%5D&name=image.png&originHeight=120&originWidth=434&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17421&status=done&style=none&taskId=uecee8fbf-a786-4f89-ac9c-f2f8d059fe0&title=&width=217) | ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644897915892-a1784bc2-693b-4cf6-a082-3c8e0368a987.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=60&id=ubcca6a46&margin=%5Bobject%20Object%5D&name=image.png&originHeight=120&originWidth=2536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=50743&status=done&style=none&taskId=ue0f418e0-4192-4bfd-8912-9b64faedb66&title=&width=1268) | +| ![image.png](https://img.alicdn.com/imgextra/i4/O1CN01xI9RVX1yV46HbW02H_!!6000000006583-2-tps-670-190.png) | ![image.png](https://img.alicdn.com/imgextra/i1/O1CN012exYQL1y37wKM7VFT_!!6000000006522-2-tps-2094-110.png) | +| ![image.png](https://img.alicdn.com/imgextra/i4/O1CN01pK2rPi1lhLij4m3o7_!!6000000004850-2-tps-434-120.png) | ![image.png](https://img.alicdn.com/imgextra/i2/O1CN01ti4n9m1ihOupktQow_!!6000000004444-2-tps-2536-120.png) | > 注:因为编译结果会被 `@babel/runtime` 干扰,目前面板不支持 `async await`或 `{ ...arr }` 形态的语法编译。如果您需要此类编译,您可以考虑在读取 schema 中的 `originCode` 之后自己手动通过 babel 编译。 @@ -28,7 +28,7 @@ sidebar_position: 3 ```typescript window.Next.Message.success('成功') ``` -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644898647058-9a5d6800-31fd-4c62-a577-850b90fc5d21.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=57&id=ue6231d61&margin=%5Bobject%20Object%5D&name=image.png&originHeight=114&originWidth=238&originalType=binary&ratio=1&rotation=0&showTitle=false&size=11360&status=done&style=none&taskId=u869f3709-a599-4ead-a80f-fa3b49c9836&title=&width=119) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01Fxjd801p4eigEBpb6_!!6000000005307-2-tps-238-114.png) #### 局部变量引用 @@ -48,18 +48,18 @@ window.Next.Message.success('成功') | 源码面板中 | schema 中 | | --- | --- | | 本地数据初始值设置: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899552013-3de394fd-f530-4b4f-8258-8b9c64f11c11.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=73&id=u291f7733&margin=%5Bobject%20Object%5D&name=image.png&originHeight=146&originWidth=370&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17505&status=done&style=none&taskId=u55496884-bc04-4867-9295-c71f44b77ef&title=&width=185) | ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899587782-0ceea074-07bb-4260-a580-7f49a82740ed.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=413&id=u01ae12cb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=826&originWidth=2098&originalType=binary&ratio=1&rotation=0&showTitle=false&size=776122&status=done&style=none&taskId=ube04795b-6244-4aac-9ebc-f4624e605db&title=&width=1049) | +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01V6iaTY1gVNHi7gQfK_!!6000000004147-2-tps-370-146.png) | ![image.png](https://img.alicdn.com/imgextra/i2/O1CN010rhIPa268BEfGmzO6_!!6000000007616-2-tps-2098-826.png) | | 生命周期方法: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899759963-d198edc4-a8c7-4a3f-90ee-b42244398958.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=130&id=uafcbf72e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=260&originWidth=478&originalType=binary&ratio=1&rotation=0&showTitle=false&size=37208&status=done&style=none&taskId=u19b58f72-7058-4a22-9a8e-334a9a541bd&title=&width=239) | ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899791416-a7969846-8d7d-4c51-9c55-6b1c65faf07b.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=418&id=uc6edd06d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=836&originWidth=2010&originalType=binary&ratio=1&rotation=0&showTitle=false&size=806116&status=done&style=none&taskId=uacb7cf67-ee4b-45ba-962a-24f43b525bc&title=&width=1005) | +![image.png](https://img.alicdn.com/imgextra/i4/O1CN010Y1TxV1QOvrVLRUjD_!!6000000001967-2-tps-478-260.png) | ![image.png](https://img.alicdn.com/imgextra/i3/O1CN01pbJzVQ1VSfAL7Lh8G_!!6000000002652-2-tps-2010-836.png) | | 自定义函数: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899808831-538e59a7-6d40-4e1a-bd72-bd2332bb9d7c.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=321&id=u2ea3e043&margin=%5Bobject%20Object%5D&name=image.png&originHeight=642&originWidth=660&originalType=binary&ratio=1&rotation=0&showTitle=false&size=72124&status=done&style=none&taskId=uc6ec76e1-89a0-4dad-a0ab-053730e2b4d&title=&width=330) | ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899830711-e262e41e-8332-4810-9293-bd4ef540c919.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=411&id=ueb7c1ad8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=822&originWidth=1862&originalType=binary&ratio=1&rotation=0&showTitle=false&size=815729&status=done&style=none&taskId=u3aae2a2e-4de4-468a-bd5a-5bec53b908a&title=&width=931) | +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01S2gjFk1CU3fm61eiD_!!6000000000083-2-tps-660-642.png) | ![image.png](https://img.alicdn.com/imgextra/i2/O1CN01X35YxU1GUkjj1YWVj_!!6000000000626-2-tps-1862-822.png) | | 编译前全量代码: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899850193-0b1990ea-e494-4c5f-94ef-9a1fdbde0a98.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=561&id=u92136fdf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1122&originWidth=762&originalType=binary&ratio=1&rotation=0&showTitle=false&size=165346&status=done&style=none&taskId=u727c08ae-f56f-4632-acc0-837fa220681&title=&width=381) | ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899882162-648366a3-5b0b-4cf3-b103-bf3812f6e807.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=398&id=ub882b04a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=796&originWidth=1906&originalType=binary&ratio=1&rotation=0&showTitle=false&size=716114&status=done&style=none&taskId=u94d53b7d-5ea9-471a-b82c-3dec1a532b5&title=&width=953) | +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01sbiK9N1kc1Uxp1OHY_!!6000000004703-2-tps-762-1122.png) | ![image.png](https://img.alicdn.com/imgextra/i3/O1CN01adKSg61QXAzRjQ4bm_!!6000000001985-2-tps-1906-796.png) | - 异常处理:如果代码解析失败,它将无法被正常保存到 schema 中,此时编辑器会弹层提示: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899252223-57317fcb-0958-4f38-a37b-00eaa5561512.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=819&id=u2d66f54c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1638&originWidth=3068&originalType=binary&ratio=1&rotation=0&showTitle=false&size=473979&status=done&style=none&taskId=u9e4a4c69-dd56-4265-93d7-9b2e4e8971a&title=&width=1534) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01aSzh8o26rWRu6zXFE_!!6000000007715-2-tps-3068-1638.png) ### 样式编辑面板 @@ -67,7 +67,7 @@ window.Next.Message.success('成功') | 源码面板中 | Schema 中 | | --- | --- | -| ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899312003-76f4c95e-221f-4b5f-92ae-c51e664385e0.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=194&id=u30912dec&margin=%5Bobject%20Object%5D&name=image.png&originHeight=388&originWidth=634&originalType=binary&ratio=1&rotation=0&showTitle=false&size=42979&status=done&style=none&taskId=ue2a18106-55f3-4cff-8f95-904317d0419&title=&width=317) | ![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899355488-aa352d2d-a001-434f-9368-021befea52ed.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=291&id=u60b8f9d4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=582&originWidth=1646&originalType=binary&ratio=1&rotation=0&showTitle=false&size=454443&status=done&style=none&taskId=u236b94fb-6c20-4c6c-9fe3-7cd75eef0c4&title=&width=823) | +| ![image.png](https://img.alicdn.com/imgextra/i2/O1CN01cuWt4L27fRcW5WIP9_!!6000000007824-2-tps-634-388.png) | ![image.png](https://img.alicdn.com/imgextra/i4/O1CN01Edu7Gy1MzKsb2iss8_!!6000000001505-2-tps-1646-582.png) | ## 对接代码 @@ -92,8 +92,8 @@ window.Next.Message.success('成功') 通常书写代码是为了对接低代码配置中的“变量绑定”、“事件回调”、“条件判断”和“循环”部分的。 #### 变量绑定 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644899977727-f4f44171-52e8-4062-b558-436536b84640.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=732&id=ua42e46e3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1464&originWidth=2738&originalType=binary&ratio=1&rotation=0&showTitle=false&size=957243&status=done&style=stroke&taskId=u56f7f36d-535d-48e9-8a0c-e0cb1f9af1d&title=&width=1369) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644900005551-14c356a0-2e51-4b0b-82b5-8a135d1c6c3e.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=583&id=ufcb9db2b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1166&originWidth=1528&originalType=binary&ratio=1&rotation=0&showTitle=false&size=153133&status=done&style=stroke&taskId=u208e369b-f019-4019-8c2e-4c28b6eba91&title=&width=764) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01wcgwOI1wOXDtgfrgD_!!6000000006298-2-tps-2738-1464.png) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01GYVAw41FlrvEyFcCO_!!6000000000528-2-tps-1528-1166.png) ```json { "componentName": "NextBlockCell", @@ -110,8 +110,8 @@ window.Next.Message.success('成功') #### 事件回调 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644900095962-2ec54fb5-e1f8-4d4a-a75e-24e1c685a833.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=726&id=ufed11f2e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1452&originWidth=2734&originalType=binary&ratio=1&rotation=0&showTitle=false&size=749908&status=done&style=stroke&taskId=uc379b8ec-c344-48f8-9b43-8d9be961356&title=&width=1367) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644900119673-f9538274-c896-4951-86f2-54d60ac95316.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=581&id=uffdcbbce&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1162&originWidth=1670&originalType=binary&ratio=1&rotation=0&showTitle=false&size=118712&status=done&style=stroke&taskId=u261a9b7f-9f5a-406a-aa55-8a3f33bdd05&title=&width=835) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01B0tvgw1O6x58dbbIb_!!6000000001657-2-tps-2734-1452.png) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01sD9g2n1tQQ0OjQkcY_!!6000000005896-2-tps-1670-1162.png) ```json { "componentName": "Filter", @@ -135,8 +135,8 @@ window.Next.Message.success('成功') ``` #### 条件判断 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644900186943-de6b33de-adca-4c1b-8f47-f68cf6ce5f77.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=726&id=u23b46226&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1452&originWidth=2738&originalType=binary&ratio=1&rotation=0&showTitle=false&size=789132&status=done&style=stroke&taskId=u6322e6a8-bea3-47d8-a374-b9ec6558bb9&title=&width=1369) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644900005551-14c356a0-2e51-4b0b-82b5-8a135d1c6c3e.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=583&id=G2uKJ&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1166&originWidth=1528&originalType=binary&ratio=1&rotation=0&showTitle=false&size=153133&status=done&style=stroke&taskId=u208e369b-f019-4019-8c2e-4c28b6eba91&title=&width=764) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01zXqec823EBaCutOY2_!!6000000007223-2-tps-2738-1452.png) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01Ze3snL24BGfuRIMCl_!!6000000007352-2-tps-1528-1166.png) ```json { "componentName": "Filter", @@ -150,8 +150,8 @@ window.Next.Message.success('成功') ``` #### 循环 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644900265929-c21c9927-1f34-49b6-9dc6-bcb4357190be.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=730&id=u8f457b1e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1460&originWidth=2746&originalType=binary&ratio=1&rotation=0&showTitle=false&size=781151&status=done&style=stroke&taskId=u92be7d31-2070-4a08-bc1c-6b1a599c682&title=&width=1373) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644900005551-14c356a0-2e51-4b0b-82b5-8a135d1c6c3e.png#clientId=ud3fa1588-e66f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=583&id=ot5cO&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1166&originWidth=1528&originalType=binary&ratio=1&rotation=0&showTitle=false&size=153133&status=done&style=stroke&taskId=u208e369b-f019-4019-8c2e-4c28b6eba91&title=&width=764) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01Kbj6XP297fe0BvhKz_!!6000000008021-2-tps-2746-1460.png) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN018Ogesd1qnN0IOKRDZ_!!6000000005540-2-tps-1528-1166.png) ```json { "componentName": "Filter", diff --git a/docs/docs/demoUsage/panels/component.md b/docs/docs/demoUsage/panels/component.md index 814792741..d1c6b9088 100644 --- a/docs/docs/demoUsage/panels/component.md +++ b/docs/docs/demoUsage/panels/component.md @@ -3,8 +3,9 @@ title: 4. 组件面板详解 sidebar_position: 0 --- ## 概述 -组件面板顾名思义就是承载组件的面板,组件面板会获取并解析传入给低代码引擎的资产包数据(数据结构[点此查看](https://lowcode-engine.cn/assets)),得到需要被展示的组件列表,并根据分类、排序规则对组件进行排列,同时也提供了搜索功能。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647964501932-33676243-c42b-4e7c-8663-77c5898d3343.png#clientId=uf38e3cbf-9388-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=438&id=ubb9e4616&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1672&originWidth=3056&originalType=binary&ratio=1&rotation=0&showTitle=true&size=451947&status=done&style=stroke&taskId=u0fc240e1-a792-4bd1-b84d-5bbc8e8fc8b&title=%E7%BB%84%E4%BB%B6%E9%9D%A2%E6%9D%BF&width=800 "组件面板") +组件面板顾名思义就是承载组件的面板,组件面板会获取并解析传入给低代码引擎的资产包数据 (数据结构[点此查看](https://lowcode-engine.cn/assets)),得到需要被展示的组件列表,并根据分类、排序规则对组件进行排列,同时也提供了搜索功能。 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01a6xgwH1wCAWugmNvU_!!6000000006271-2-tps-3056-1672.png) ## 组件信息 组件面板承载的组件信息有: @@ -18,7 +19,7 @@ sidebar_position: 0 其中标题和截图是我们能够看到的,schema 片段则是拖拽到设计器时会自动插入页面 schema 中,面板会根据分组、分类来对组件进行排列; 这些组件信息均通过资产包数据获取,字段对应关系如下图所示: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647965256061-d15ad119-471f-43c7-8856-2c91bb3670ad.png#clientId=uf38e3cbf-9388-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1012&id=u1b3132db&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1678&originWidth=1326&originalType=binary&ratio=1&rotation=0&showTitle=false&size=996705&status=done&style=stroke&taskId=u6730f591-c7e1-42ba-8cb7-fcc95e76e8c&title=&width=800) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN012ZUg6a289fl4z6WCm_!!6000000007890-2-tps-1326-1678.png) ## 组件分组、分类排序 组件面板会把相同分组的组件放在同一个 tab 下,相同分类的组件放在同一个 collapse 中,同时也支持对 tab 和 collapse 进行排序; 由于是整体性的排序,组件自身的信息无法决定此排序,因此在资产包数据根节点新增了 sort 字段用于指定分组和分类的排序,具体定义在[《低代码引擎资产包协议规范》](https://lowcode-engine.cn/assets)2.4 sort 章节; diff --git a/docs/docs/demoUsage/panels/datasource.md b/docs/docs/demoUsage/panels/datasource.md index 3116f1939..7e9028e5e 100644 --- a/docs/docs/demoUsage/panels/datasource.md +++ b/docs/docs/demoUsage/panels/datasource.md @@ -3,14 +3,16 @@ title: 8. 数据源面板详解 sidebar_position: 4 --- ## 🪚 概述 -数据源面板主要负责管理低代码中远程数据源内容,通过可视化编辑的方式操作低代码协议中的数据源Schema,配合 [数据源引擎](https://www.yuque.com/lce/doc/datasource-engine) 即可实现低代码中数据源的生产和消费; -![image.png](https://cdn.nlark.com/yuque/0/2022/png/84508/1648397674378-aec10892-5ee4-414d-807e-39f55f3a5be5.png#clientId=u38847497-05f3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=821&id=u07e82f8a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1642&originWidth=2878&originalType=binary&ratio=1&rotation=0&showTitle=false&size=246032&status=done&style=none&taskId=uc18acbc5-1404-4266-a499-e952d1084c4&title=&width=1439) +数据源面板主要负责管理低代码中远程数据源内容,通过可视化编辑的方式操作低代码协议中的数据源 Schema,配合 [数据源引擎](/site/docs/guide/design/datasourceEngine) 即可实现低代码中数据源的生产和消费; + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN0170HeBg276B7fM9rqh_!!6000000007747-2-tps-2878-1642.png) + 数据源面板 ## ❓如何使用 > 面板内包含了数据源创建、删除、编辑、排序、导入导出、复制以及搜索等能力,内置支持了 `fecth` & `JSONP`两种常用远程请求类型; ### 三步创建一个数据源 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/84508/1648398269436-bd241801-e617-4640-830f-03b44aca80a1.png#clientId=u38847497-05f3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=819&id=u1ee9fa0d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1638&originWidth=2878&originalType=binary&ratio=1&rotation=0&showTitle=false&size=279302&status=done&style=none&taskId=ue1248934-df36-423c-86f3-160a4e865da&title=&width=1439) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01bkgbqj1cOGfwQtEif_!!6000000003590-2-tps-2878-1638.png) 三步创建数据源 ### 参数详解 @@ -24,11 +26,13 @@ TODO ### 如何定制数据源 #### 定制数据源类型(设计态) #### 定制数据源请求实现(运行态) + > 当出现以下两种情况的时,我们需要定制数据源请求实现, > - 当你默认提供的 `handler`无法满足你的需求 > - 定制了数据源类型,比如 `GraphQL`,需要实现一个对应的 `handler` 接下来我们来看一个例子,如何实现一个 `handler` + ```javascript import { RuntimeOptionsConfig } from '@alilc/lowcode-datasource-types'; @@ -50,9 +54,9 @@ export function createFetchHandler(config?: Record) { }; } ``` -低代码fetch-handler默认实现 +低代码 fetch-handler 默认实现 -以上代码是低代码内置的fetch-handler默认实现,内部使用了 `universal-request`,假如你们内部使用的 `axios`,你完全重新实现一个; +以上代码是低代码内置的 fetch-handler 默认实现,内部使用了 `universal-request`,假如你们内部使用的 `axios`,你完全重新实现一个; ```javascript import axios from 'axios'; export function createAxiosFetchHandler(config?: Record) { @@ -71,10 +75,10 @@ export function createAxiosFetchHandler(config?: Record) { } ``` -##### 注册到render -完成一个Handler后你可以通过以下方式接入到render或者出码中使用 +##### 注册到 render +完成一个 Handler 后你可以通过以下方式接入到 render 或者出码中使用 -###### 渲染Render +###### 渲染 Render ```tsx import React, { memo } from 'react'; import ReactRenderer from '@alilc/lowcode-react-renderer'; @@ -95,11 +99,11 @@ const SamplePreview = memo(() => { }); ``` ###### 出码 -> 目前自定义只能通过重新定义类型来完成,接下来我们会给出码添加requestHandlersMap映射能力;如有需求请联系 荣彬(github-id:xingmolu) +> 目前自定义只能通过重新定义类型来完成,接下来我们会给出码添加 requestHandlersMap 映射能力;如有需求请联系 荣彬 (github-id:xingmolu) ### 设计态启用数据源引擎 -> 默认情况下设计态没有开启数据源引擎,我们可以在设计器init的时候来传递`requstHandlersMap`来开启;具体代码如下: +> 默认情况下设计态没有开启数据源引擎,我们可以在设计器 init 的时候来传递`requstHandlersMap`来开启;具体代码如下: ```javascript import { init, plugins } from '@alilc/lowcode-engine'; @@ -139,12 +143,12 @@ const preference = new Map(); | isInit | 是否为初始数据 | Boolean | ✅ | true | 值为 true 时,将在组件初始化渲染时自动发送当前数据请求 | | isSync | 是否需要串行执行 | Boolean | ✅ | false | 值为 true 时,当前请求将被串行执行 | | type | 数据请求类型 | String | - | fetch | 支持四种类型:fetch/mtop/jsonp/custom | -| shouldFetch | 本次请求是否可以正常请求 | (options: ComponentDataSourceItemOptions) => boolean | - | () => true | function 参数参考 [ComponentDataSourceItemOptions 对象描述](https://lowcode-engine.cn/lowcode#2315-componentdatasourceitemoptions-%E5%AF%B9%E8%B1%A1%E6%8F%8F%E8%BF%B0) | +| shouldFetch | 本次请求是否可以正常请求 | (options: ComponentDataSourceItemOptions) => boolean | - | () => true | function 参数参考 [ComponentDataSourceItemOptions 对象描述](/site/docs/specs/lowcode-spec#2315-componentdatasourceitemoptions-对象描述) | | willFetch | 单个数据结果请求参数处理函数 | Function | - | options => options | 只接受一个参数(options),返回值作为请求的 options,当处理异常时,使用原 options。也可以返回一个 Promise,resolve 的值作为请求的 options,reject 时,使用原 options | -| requestHandler | 自定义扩展的外部请求处理器 | Function | - | - | 仅 type=‘custom’ 时生效 | -| dataHandler | request 成功后的回调函数 | Function | - | response => response.data | 参数: 请求成功后 promise 的 value 值 | -| errorHandler | request 失败后的回调函数 | Function | - | - | 参数: 请求出错 promise 的 error 内容 | -| options {} | 请求参数 | **ComponentDataSourceItemOptions** | - | - | 每种请求类型对应不同参数, 详见 [ComponentDataSourceItemOptions 对象描述](https://lowcode-engine.cn/lowcode#2315-componentdatasourceitemoptions-%E5%AF%B9%E8%B1%A1%E6%8F%8F%E8%BF%B0) | +| requestHandler | 自定义扩展的外部请求处理器 | Function | - | - | 仅 type=‘custom’时生效 | +| dataHandler | request 成功后的回调函数 | Function | - | response => response.data | 参数:请求成功后 promise 的 value 值 | +| errorHandler | request 失败后的回调函数 | Function | - | - | 参数:请求出错 promise 的 error 内容 | +| options {} | 请求参数 | **ComponentDataSourceItemOptions**| - | - | 每种请求类型对应不同参数,详见见 [ComponentDataSourceItemOptions 对象描述](/site/docs/specs/lowcode-spec#2315-componentdatasourceitemoptions-对象描述) | ### 运行时实现层:数据源引擎设计 -[https://www.yuque.com/lce/doc/datasource-engine](https://www.yuque.com/lce/doc/datasource-engine) +[数据源引擎设计](/site/docs/guide/design/datasourceEngine) diff --git a/docs/docs/demoUsage/panels/settings.md b/docs/docs/demoUsage/panels/settings.md index 03c28eabf..9023e587a 100644 --- a/docs/docs/demoUsage/panels/settings.md +++ b/docs/docs/demoUsage/panels/settings.md @@ -5,7 +5,7 @@ sidebar_position: 2 # 设置器介绍 ## 展示区域 设置器,又称为 Setter,主要展示在编辑器的右边区域,如下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1647695118402-ac146307-f6e2-4755-8be3-67278c505283.png#clientId=u547a37e3-c43d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=865&id=u3cac31de&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1730&originWidth=3836&originalType=binary&ratio=1&rotation=0&showTitle=false&size=947162&status=done&style=none&taskId=u35373859-102e-4809-adfd-680b2dd4cda&title=&width=1918) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01jN0toi1OknXWrPuYt_!!6000000001744-2-tps-3836-1730.png) 其中包含 属性、样式、事件、高级 - 属性:展示该物料常规的属性 @@ -18,7 +18,7 @@ sidebar_position: 2 ## 设置器 上述区域中是有多项设置器的,对于一个组件来说,每一项配置都对应一个设置器,比如我们的配置是一个文本,我们需要的是文本设置器,我们需要配置的是数字,我们需要的就是数字设置器。 下图中的标题和按钮类型配置就分别是文本设置器和下拉框设置器。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1647695118227-bf6caf7c-4974-4b35-8d6b-0c4969fc316d.png#clientId=u547a37e3-c43d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=407&id=u51d889e6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1460&originWidth=2120&originalType=binary&ratio=1&rotation=0&showTitle=false&size=489840&status=done&style=none&taskId=u35d4519f-b82d-43c4-9eb4-bd44e6d67b1&title=&width=591) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01Bl2hgm1GiUcXD3TOO_!!6000000000656-2-tps-2120-1460.png) 我们提供了常用的设置器作为内置设置器,也提供了定制能力帮助大家开发特定需求的设置器。 # 内置设置器 | **预置 Setter** | **用途** | @@ -28,23 +28,23 @@ sidebar_position: 2 | BoolSetter | 布尔型数据设置器, | | SelectSetter | 枚举型数据设置器,采用下拉的形式展现 | | VariableSetter | 变量型数据设置器, | -| RadioGroupSetter | 枚举型数据设置器,采用tab选择的形式展现 | +| RadioGroupSetter | 枚举型数据设置器,采用 tab 选择的形式展现 | | TextAreaSetter | 长文本型数据设置器,可换行 | | DateSetter | 日期型数据设置器 | | TimePicker | 时间型数据设置器 | -| DateYearSetter | 日期型-年数据设置器 | -| DateMonthSetter | 日期型-月数据设置器 | +| DateYearSetter | 日期型 - 年数据设置器 | +| DateMonthSetter | 日期型 - 月数据设置器 | | DateRangeSetter | 日期型数据设置器,可选择时间区间 | | EventsSetter | 事件绑定设置器 | | ColorSetter | 颜色设置器 | -| JsonSetter | json型数据设置器 | +| JsonSetter | json 型数据设置器 | | StyleSetter | 样式设置器 | | ClassNameSetter | 样式名设置器 | | FunctionSetter | 函数型数据设置器 | | MixedSetter | 混合型数据设置器 | | SlotSetter | 节点型数据设置器 | | ArraySetter | 列表数组行数据设置器 | -| ObjectSetter | 对象数据设置器,一般内嵌在ArraySetter中 | +| ObjectSetter | 对象数据设置器,一般内嵌在 ArraySetter 中 | # 设置器定制 @@ -60,7 +60,7 @@ interface AltStringSetterProps { value: string; // 默认值 defaultValue: string; - // setter唯一输出 + // setter 唯一输出 onChange: (val: string) => void; // AltStringSetter 特殊配置 placeholder: string; @@ -73,7 +73,7 @@ export default class AltStringSetter extends React.PureComponent { } componentWillUnmount() { - // setter是以实例为单位的,每个setter注销的时候需要把事件也注销掉,避免事件池过多 + // setter 是以实例为单位的,每个 setter 注销的时候需要把事件也注销掉,避免事件池过多 event.off(`${this.emitEventName}.bindEvent`, this.bindEvent) } ``` @@ -115,7 +115,7 @@ import { event } from '@ali/lowcode-engine'; bindFunction = () => { const { field, value } = this.props; - // 这里展示的和插件进行通信,事件规则是插件名+方法 + // 这里展示的和插件进行通信,事件规则是插件名 + 方法 event.emit('eventBindDialog.openDialog', field.name, this.emitEventName); } ``` @@ -125,9 +125,9 @@ setter 本身只影响其中一个 props 的值,如果需要影响其他组件 bindFunction = () => { const { field, value } = this.props; const propsField = field.parent; - // 获取同级其他属性showJump的值 + // 获取同级其他属性 showJump 的值 const otherValue = propsField.getPropValue('showJump'); - // set同级其他属性showJump的值 + // set 同级其他属性 showJump 的值 propsField.setPropValue('showJump', false); } ``` diff --git a/docs/docs/faq/faq002.md b/docs/docs/faq/faq002.md index 45e1c0c50..e1da36b3d 100644 --- a/docs/docs/faq/faq002.md +++ b/docs/docs/faq/faq002.md @@ -6,28 +6,28 @@ tags: [FAQ] 渲染唯一标识(key)和 React 中组件的 key 属性的原理是一致的,都是为了在渲染场景或者组件切换的场景中唯一标识一个组件。 你可以在组件右侧配置面板的「高级」中看到此配置项,该配置项一般配合「是否渲染」和「循环」功能使用。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1659076591507-f37841b4-a3c2-4c87-b875-5f0458b2a3d2.png#clientId=u87aade85-8350-4&crop=0&crop=0&crop=1&crop=1&height=348&id=dbojA&margin=%5Bobject%20Object%5D&name=image.png&originHeight=696&originWidth=560&originalType=binary&ratio=1&rotation=0&showTitle=false&size=102096&status=done&style=none&taskId=ub4a95aaa-8630-47ad-b0e3-881b5d54ac9&title=&width=280) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01wU7y30232jgLlfzRe_!!6000000007198-2-tps-560-696.png) ## 以下场景必需设置「渲染唯一标识」 #### 场景一:同类组件切换 以下场景中,当「爱好」选择「游戏」时显示「最喜欢的游戏」,选择「运动」时显示「最喜欢的运动」 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1659076591520-b2e1121b-3f4e-4c7c-88c8-82a761b85fe0.png#clientId=u87aade85-8350-4&crop=0&crop=0&crop=1&crop=1&height=294&id=Xr3NB&margin=%5Bobject%20Object%5D&name=image.png&originHeight=588&originWidth=1560&originalType=binary&ratio=1&rotation=0&showTitle=false&size=78723&status=done&style=none&taskId=u59b975eb-93a1-4c8a-bb3b-17ef8b7005c&title=&width=780) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN016qHhJB1XWRfUJsml7_!!6000000002931-2-tps-1560-588.png) 配置方式如下: 1. 增加变量数据源:hobby 2. 「最喜欢的游戏」表单标识设置为 game,「是否渲染」绑定变量「state.hobby === '游戏'」 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1659076591653-27fac7ab-bba0-4965-a706-d0c1c867f539.png#clientId=u87aade85-8350-4&crop=0&crop=0&crop=1&crop=1&height=369&id=f8kif&margin=%5Bobject%20Object%5D&name=image.png&originHeight=738&originWidth=2164&originalType=binary&ratio=1&rotation=0&showTitle=false&size=306076&status=done&style=none&taskId=ub6da537a-3bc7-450d-b640-dc0db8defac&title=&width=1082) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01oOemw41d0HY3qpwum_!!6000000003673-2-tps-2164-738.png) 3. 「最喜欢的运动」表单标识设置为 sport,「是否渲染」绑定变量「state.hobby === '运动'」 4. 「爱好」设置 onChange 动作 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1659076591442-2903e2b2-4688-4a5e-98de-7df9933710b5.png#clientId=u87aade85-8350-4&crop=0&crop=0&crop=1&crop=1&height=97&id=hR3Pp&margin=%5Bobject%20Object%5D&name=image.png&originHeight=194&originWidth=892&originalType=binary&ratio=1&rotation=0&showTitle=false&size=53803&status=done&style=none&taskId=ue8919283-2e5f-46a8-9d6b-942c03f8482&title=&width=446) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01oH4Giy1GTpwZwVSrO_!!6000000000624-2-tps-892-194.png) 5. 「提交」按钮绑定 onClick 动作 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1659076591508-ddd3c767-bf22-4dae-a006-5e6c4e0ea956.png#clientId=u87aade85-8350-4&crop=0&crop=0&crop=1&crop=1&height=67&id=VWtPz&margin=%5Bobject%20Object%5D&name=image.png&originHeight=134&originWidth=750&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46519&status=done&style=none&taskId=ud6a5d2b0-481b-4bbb-8fe3-8622e2ebfb3&title=&width=375) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN016kkf3O1uj1i9ev7uy_!!6000000006072-2-tps-750-134.png) 按以上配置(不配置渲染唯一标识),确实可以实现切换爱好时下方的文本框切换,但在提交数据时会发现,即使选择了「运动」,提交的时候 sport 字段是「最喜欢的游戏」的值。 diff --git a/docs/docs/faq/faq003.md b/docs/docs/faq/faq003.md index 96e01c1fd..780614dcf 100644 --- a/docs/docs/faq/faq003.md +++ b/docs/docs/faq/faq003.md @@ -6,15 +6,15 @@ tags: [FAQ] 背景: - [Antd Table 下 button 点击事件怎么拿到行数据?](https://github.com/alibaba/lowcode-engine/issues/341) -## 方式1 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1657593243427-fb5641b2-4987-475e-88ab-c68d2085edbd.png#clientId=u31b40d04-56f2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=563&id=u5167bf33&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1126&originWidth=3342&originalType=binary&ratio=1&rotation=0&showTitle=false&size=225551&status=done&style=none&taskId=ud1b89a63-4b6a-4986-a6df-2a463fcf08a&title=&width=1671) +## 方式 1 +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01i58EGG1bxFJBdlS6x_!!6000000003531-2-tps-3342-1126.png) -参考 fusion protable , 将操作列直接耦合 button 组件,因为 col.render 函数能拿到 行数据record,那么 pro-table 组件封装的时候,就可以在渲染操作列按钮的时候,将 col.render 参数透传给 button 组件 +参考 fusion protable,将操作列直接耦合 button 组件,因为 col.render 函数能拿到 行数据 record,那么 pro-table 组件封装的时候,就可以在渲染操作列按钮的时候,将 col.render 参数透传给 button 组件 -## 方式2 +## 方式 2 slot + 扩展参数 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1657593299698-9628db14-7b48-4c06-9e6f-bda637c209a8.png#clientId=u31b40d04-56f2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=574&id=u20b07439&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1148&originWidth=3284&originalType=binary&ratio=1&rotation=0&showTitle=false&size=232140&status=done&style=none&taskId=ubc80905d-0607-4e73-9386-5dde706e572&title=&width=1642) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01pQk2RC1WBXyxjNDif_!!6000000002750-2-tps-3284-1148.png) 将扩展参数写成: ```json diff --git a/docs/docs/faq/faq005.md b/docs/docs/faq/faq005.md index 03efb55b4..dd4c9941b 100644 --- a/docs/docs/faq/faq005.md +++ b/docs/docs/faq/faq005.md @@ -5,19 +5,19 @@ tags: [FAQ] --- ## 设计器 ### 通过引擎 API 配置 -[https://www.yuque.com/lce/doc/dffghx](https://www.yuque.com/lce/doc/dffghx) +[API-init](/site/docs/api/init) ### 通过资产包 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1657273720962-70045da1-7559-4f7f-a3da-35759778066c.png#averageHue=%231f221e&clientId=ueb9290e1-769e-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=394&id=u698ffae7&margin=%5Bobject%20Object%5D&name=image.png&originHeight=788&originWidth=806&originalType=binary&ratio=1&rotation=0&showTitle=false&size=175357&status=error&style=none&taskId=u2ed6a3cd-5ec4-4b84-a3c0-fd3379b7019&title=&width=403) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01WWJVSA1WutBvCzXnl_!!6000000002849-2-tps-806-788.png) 就可以在引擎代码中访问到 moment -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1657273737110-6c064e4c-6435-456a-b168-480058b14da8.png#averageHue=%23fdfdfc&clientId=ueb9290e1-769e-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=126&id=u4ec5fba0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=252&originWidth=1248&originalType=binary&ratio=1&rotation=0&showTitle=false&size=128347&status=error&style=none&taskId=udd229103-04e3-4fc5-9fba-9115354bb9d&title=&width=624) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01EEJ0Kp1nZgJm68nSG_!!6000000005104-2-tps-1248-252.png) PS:需要在 packages 中有相关的资源配置,例如: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1657273863884-2068444e-5653-4b25-ba3a-fd192409fbaa.png#averageHue=%231f1f1d&clientId=ueb9290e1-769e-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=210&id=ud2a4b3c6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=420&originWidth=1322&originalType=binary&ratio=1&rotation=0&showTitle=false&size=113099&status=error&style=none&taskId=u7ba0f438-9c39-4398-b048-9d0556e2079&title=&width=661) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01bdiHVv206uRYvvAAr_!!6000000006801-2-tps-1322-420.png) 否则在画布中可能会访问不到对应的资源。 ## 预览态 -参考:[https://www.yuque.com/lce/doc/nhilce#appHelper](https://www.yuque.com/lce/doc/nhilce#appHelper) +[参考资料](/site/docs/guide/expand/runtime/renderer#apphelper) diff --git a/docs/docs/faq/faq006.md b/docs/docs/faq/faq006.md index 0553d5122..5a6334c04 100644 --- a/docs/docs/faq/faq006.md +++ b/docs/docs/faq/faq006.md @@ -3,4 +3,4 @@ title: 如何通过 API 手动调用数据源请求 sidebar_position: 6 tags: [FAQ] --- -参考:[https://www.yuque.com/lce/doc/erckcn](https://www.yuque.com/lce/doc/erckcn) \ No newline at end of file +参考:[DataSource API](/site/docs/api/datasource) \ No newline at end of file diff --git a/docs/docs/faq/faq007.md b/docs/docs/faq/faq007.md index 175d8c73f..07ebba847 100644 --- a/docs/docs/faq/faq007.md +++ b/docs/docs/faq/faq007.md @@ -1,9 +1,9 @@ --- -title: 设置面板中的高级tab如何配置 +title: 设置面板中的高级 tab 如何配置 sidebar_position: 7 tags: [FAQ] --- -![93DC003C-D9A1-4F4F-98A1-F22C0A89EA92.png](https://cdn.nlark.com/yuque/0/2022/png/1053439/1657161085153-a26657ae-2c6e-4124-b9ab-6f8cf8126d1f.png#clientId=u300df630-5bbe-4&crop=0&crop=0&crop=1&crop=1&from=ui&height=591&id=u2ff7824e&margin=%5Bobject%20Object%5D&name=93DC003C-D9A1-4F4F-98A1-F22C0A89EA92.png&originHeight=1714&originWidth=960&originalType=binary&ratio=1&rotation=0&showTitle=false&size=107040&status=done&style=none&taskId=ub377dc1d-db5a-4234-980f-66f7143950d&title=&width=331) +![93DC003C-D9A1-4F4F-98A1-F22C0A89EA92.png](https://img.alicdn.com/imgextra/i4/O1CN01lVutr6243wL6gOQAc_!!6000000007336-2-tps-960-1714.png) -默认这个tab下的内容为引擎内置,如需要定制,可以使用以下API -[https://lowcode-engine.cn/docV2/mu7lml#lIK37](https://lowcode-engine.cn/docV2/mu7lml#lIK37) +默认这个 tab 下的内容为引擎内置,如需要定制,可以使用以下 API +[https://lowcode-engine.cn/site/docs/api/material#物料元数据管道函数](https://lowcode-engine.cn/site/docs/api/material#物料元数据管道函数) diff --git a/docs/docs/faq/faq008.md b/docs/docs/faq/faq008.md index c64a09ae2..6fe0780cb 100644 --- a/docs/docs/faq/faq008.md +++ b/docs/docs/faq/faq008.md @@ -1,7 +1,7 @@ --- -title: 某某npm包对应的源码在哪里? +title: 某某 npm 包对应的源码在哪里? sidebar_position: 8 tags: [FAQ] --- -详见 [NPM包对应源码位置汇总](https://www.yuque.com/lce/doc/ngm44i) \ No newline at end of file +详见 [NPM 包对应源码位置汇总](/site/docs/guide/appendix/npms) \ No newline at end of file diff --git a/docs/docs/faq/faq009.md b/docs/docs/faq/faq009.md index 131dcba6f..f1247bfa4 100644 --- a/docs/docs/faq/faq009.md +++ b/docs/docs/faq/faq009.md @@ -9,7 +9,7 @@ tags: [FAQ] **解决方案** LowCodeEngine 升级到 1.0.8 -> 相关PR:[https://github.com/alibaba/lowcode-engine/pull/383](https://github.com/alibaba/lowcode-engine/pull/383) +> 相关 PR:[https://github.com/alibaba/lowcode-engine/pull/383](https://github.com/alibaba/lowcode-engine/pull/383) ## 编辑态,snippets 和注入组件不对应 @@ -19,7 +19,7 @@ AliLowCodeEngine.material.componentsMap ``` 查看物料配置是否正常。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1655277296065-40eeae64-1323-4f7d-89c3-bc48c928aca4.png#clientId=u21fd51ec-6ae9-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=408&id=u21239467&margin=%5Bobject%20Object%5D&name=image.png&originHeight=816&originWidth=1640&originalType=binary&ratio=1&rotation=0&showTitle=false&size=379372&status=done&style=none&taskId=u12a736de-695e-45b9-817b-0f9f6b3a601&title=&width=820) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01bAsPoT1QOTSp7Fmz5_!!6000000001966-2-tps-1640-816.png) 如果正常继续。 LowCodeEngine 需要升级到 1.0.10 diff --git a/docs/docs/faq/faq010.md b/docs/docs/faq/faq010.md index e98ac7f68..8b54dd2ee 100644 --- a/docs/docs/faq/faq010.md +++ b/docs/docs/faq/faq010.md @@ -15,4 +15,4 @@ AliLowCodeEngine.skeleton.add({ }); ``` 这里设置 index 为负数,可以将其调整到第一的位置。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1653964459415-694283f6-9c5f-4143-b6d4-51b5aa37f719.png#clientId=uaed53506-efef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=579&id=u99009edf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1158&originWidth=1614&originalType=binary&ratio=1&rotation=0&showTitle=false&size=390356&status=done&style=none&taskId=ue153a8c6-13b0-48fa-bfe9-a0d9f7b6cc3&title=&width=807) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01PTCH3r20fiXrrbcXe_!!6000000006877-2-tps-1614-1158.png) diff --git a/docs/docs/faq/faq011.md b/docs/docs/faq/faq011.md index 793ff7af1..3c6bf1d2d 100644 --- a/docs/docs/faq/faq011.md +++ b/docs/docs/faq/faq011.md @@ -5,7 +5,7 @@ tags: [FAQ] --- ## 简单场景 可以利用 props.__designMode -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1653962601596-46e21531-9b8c-45bd-84a7-7522856eb3c9.png#clientId=u8f8d6439-2532-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=220&id=u4d7df210&margin=%5Bobject%20Object%5D&name=image.png&originHeight=440&originWidth=1616&originalType=binary&ratio=1&rotation=0&showTitle=false&size=232329&status=done&style=none&taskId=u85deaa53-ef14-4ce2-a5a2-ac201aa60f5&title=&width=808) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01btr66024FOEldBOr2_!!6000000007361-2-tps-1616-440.png) 设计态中,__designMode 值为 "design" @@ -13,11 +13,11 @@ tags: [FAQ] ## 复杂场景 在资产包里定义 editUrls -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1653962648722-ac8ff758-a0c3-4323-8312-11ac9b511ecf.png#clientId=u8f8d6439-2532-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=269&id=uad79aeaf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=538&originWidth=1590&originalType=binary&ratio=1&rotation=0&showTitle=false&size=257391&status=done&style=none&taskId=u3d8d556b-2da7-40b4-b7e6-cd3600cfbd4&title=&width=795) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01odal6P27Rhjn8NoJ6_!!6000000007794-2-tps-1590-538.png) ### editUrls 在 lowcode/xx/ 下新建一个 view.tsx -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1653971463822-3335e539-6b97-43a7-adf9-cba221a68d87.png#clientId=u89265c24-4294-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=77&id=u466ed474&margin=%5Bobject%20Object%5D&name=image.png&originHeight=154&originWidth=598&originalType=binary&ratio=1&rotation=0&showTitle=false&size=31756&status=done&style=none&taskId=u1f7eeec2-323c-45c7-a1f7-e18bfa3a1db&title=&width=299) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01q0Bbn91Lrig7d0alA_!!6000000001353-2-tps-598-154.png) 再执行 ```json @@ -26,4 +26,4 @@ npm run lowcode:build 之后,build/lowcode 目录下既有 view.js,可作为 editUrls 配置在资产包中。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1653971523747-c15e63e6-9fb7-481e-bf5b-c4bd6cb25927.png#clientId=u89265c24-4294-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=493&id=ucaf08028&margin=%5Bobject%20Object%5D&name=image.png&originHeight=986&originWidth=1082&originalType=binary&ratio=1&rotation=0&showTitle=false&size=235573&status=done&style=none&taskId=ue21c1ab4-0d1b-49fb-8889-b7210b90d41&title=&width=541) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01dvIZ441alxwIlwexS_!!6000000003371-2-tps-1082-986.png) diff --git a/docs/docs/faq/faq012.md b/docs/docs/faq/faq012.md index 6c0e61db0..db156e5b1 100644 --- a/docs/docs/faq/faq012.md +++ b/docs/docs/faq/faq012.md @@ -61,7 +61,7 @@ condition: () => false, ### 配置没有生效 查看组件中的 schema,对应的配置是否已经正确设置。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1653894934869-963be13a-1d6a-458a-a1e1-fd21fa9fc765.png#clientId=uc4e9cec0-362f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=577&id=u956bc36a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1154&originWidth=1046&originalType=binary&ratio=1&rotation=0&showTitle=false&size=339838&status=done&style=none&taskId=uf64dae1b-23e9-4444-ab20-9e5f17a5449&title=&width=523) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN015AGT4l1MwaVGGwgua_!!6000000001499-2-tps-1046-1154.png) 没有正确设置上可能的原因是 1.snippets 中没有默认值 @@ -87,4 +87,4 @@ const snippets: Snippet[] = [ ``` ### 如何全局生效 -通过 [https://www.yuque.com/lce/doc/mu7lml#LRXhp](https://www.yuque.com/lce/doc/mu7lml#LRXhp) 来修改元数据信息,注意如果有 snippets 相关配置也需要修改相关的配置。 +通过 [registerMetadataTransducer API](/site/docs/api/material#registermetadatatransducer) 来修改元数据信息,注意如果有 snippets 相关配置也需要修改相关的配置。 diff --git a/docs/docs/faq/faq013.md b/docs/docs/faq/faq013.md index 2d8f6f703..bf073e733 100644 --- a/docs/docs/faq/faq013.md +++ b/docs/docs/faq/faq013.md @@ -4,7 +4,7 @@ sidebar_position: 13 tags: [FAQ] --- ## 注意 -弹窗的正确弹出方式请参考:[https://www.yuque.com/lce/usage/ozsg2m](https://www.yuque.com/lce/usage/ozsg2m) +弹窗的正确弹出方式请参考:[如何通过按钮展示/隐藏弹窗](/site/docs/demoUsage/makeStuff/dialog) ## 问题原因 由于 hidden 属性,导致 Modal 组件在预览的时候不渲染,也就无法获取到实例。 ## 处理方式 diff --git a/docs/docs/faq/faq014.md b/docs/docs/faq/faq014.md index 9c72b2a2a..8f5f15fe3 100644 --- a/docs/docs/faq/faq014.md +++ b/docs/docs/faq/faq014.md @@ -12,7 +12,7 @@ tags: [FAQ] 在项目的 externals 配置里加[一行配置](https://github.com/alibaba/lowcode-demo/blob/f8afad0df3190565caccc0a1dfd750dbf84c680f/build.json#L16) ## 其他项目 -[相关文档](https://lowcode-engine.cn/docV2/start-with-lce#OMRA2) +[相关文档](/site/docs/guide/create/useEditor#引入-umd-包资源) ### webpack [https://webpack.docschina.org/configuration/externals/](https://webpack.docschina.org/configuration/externals/) diff --git a/docs/docs/faq/faq015.md b/docs/docs/faq/faq015.md index 02ca13915..48e97bc22 100644 --- a/docs/docs/faq/faq015.md +++ b/docs/docs/faq/faq015.md @@ -3,5 +3,5 @@ title: 已有组件如何快速接入引擎 sidebar_position: 15 tags: [FAQ] --- -你可以通过在线工具 「Parts造物」生产物料描述协议,然后使用到你的项目中去。 -文档地址:[https://www.yuque.com/lce/xhk5hf/qa9pbx](https://www.yuque.com/lce/xhk5hf/qa9pbx) +你可以通过在线工具「Parts 造物」生产物料描述协议,然后使用到你的项目中去。 +文档地址:[利用 Parts 造物快速使用 react 组件](/site/docs/guide/expand/editor/partsIntro) diff --git a/docs/docs/faq/faq016.md b/docs/docs/faq/faq016.md index bb72e17ec..001a3e921 100644 --- a/docs/docs/faq/faq016.md +++ b/docs/docs/faq/faq016.md @@ -7,7 +7,7 @@ tags: [FAQ] 需要在资产包中检查是否有下列代码: ```typescript { - "title": "fusion组件库", + "title": "fusion 组件库", "package": "@alifd/next", "version": "1.23.0", "urls": [ diff --git a/docs/docs/faq/faq018.md b/docs/docs/faq/faq018.md index a7b79e44d..b5a590240 100644 --- a/docs/docs/faq/faq018.md +++ b/docs/docs/faq/faq018.md @@ -5,6 +5,6 @@ tags: [FAQ] --- 低代码引擎在架构上是和具体语言无关的,通过一定的扩展和插件是可以生成 Vue 页面代码的。 如果只是用现有的基于 React 的 fusion 物料来搭建,只是在最终出码的时候生成 Vue 页面代码,那您需要准备一套和 fusion 兼容的 vue 物料,并定制个出码方案,将[下面的一些出码插件](https://github.com/alibaba/lowcode-engine/blob/main/modules/code-generator/src/solutions/icejs.ts)替换成生成 Vue 框架的即可: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/263300/1648542644942-c019ffd4-1312-4d31-ad61-4e487a47df71.png#clientId=ue0e8d3cc-f9f8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=517&id=u64b1f996&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1368&originWidth=974&originalType=binary&ratio=1&rotation=0&showTitle=false&size=771387&status=done&style=none&taskId=u51022017-4248-49b8-b8b3-be9a7bb48fb&title=&width=368) -详细定制方案可以参考下[《自定义出码》](https://lowcode-engine.cn/docV2/cplfv0#857ba793)。 -如果您希望在搭建的时候也使用 Vue 的物料,则还需要扩展定制入料、画布和渲染器等模块,详细方案请参考下[《扩展低代码编辑器》](https://lowcode-engine.cn/docV2/srdo3s) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01VxkwCL1l85DiDC2BO_!!6000000004773-2-tps-974-1368.png) +详细定制方案可以参考下[《自定义出码》](/site/docs/guide/expand/runtime/codeGeneration#5自定义出码)。 +如果您希望在搭建的时候也使用 Vue 的物料,则还需要扩展定制入料、画布和渲染器等模块,详细方案请参考下[《扩展低代码编辑器》](/site/docs/guide/expand/editor/summary) diff --git a/docs/docs/faq/faq020.md b/docs/docs/faq/faq020.md index 641e64eb1..5ab1e15f9 100644 --- a/docs/docs/faq/faq020.md +++ b/docs/docs/faq/faq020.md @@ -5,7 +5,7 @@ tags: [FAQ] --- 如果您是自己配置的引擎打包,那么可能会遇到这个问题。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644896737710-a746e04d-bf4a-40a3-b917-a09235363c81.png#clientId=u627d7b4e-5fe3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=492&id=u06a9f219&margin=%5Bobject%20Object%5D&name=image.png&originHeight=984&originWidth=1912&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1210174&status=done&style=none&taskId=u2b829db8-026d-472a-baf4-d4660fb5a4a&title=&width=956) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN013xHmcz1WBXygt7VvC_!!6000000002750-2-tps-1912-984.png) 问题的根源是 code-editor 插件运行时直接依赖了 babel 来完成 jsx 编译,babel 从 7.17.0 开始依赖了使用 ESM 编写的 @ampproject/remapping@2.1.0。如果打包工具无法正确处理 ESM,则可能报错。 diff --git a/docs/docs/faq/faq021.md b/docs/docs/faq/faq021.md new file mode 100644 index 000000000..ba5c18e11 --- /dev/null +++ b/docs/docs/faq/faq021.md @@ -0,0 +1,18 @@ +--- +title: 提交 PR 时,明明签署过 CLA,仍被提示需要签署 +sidebar_position: 21 +tags: [FAQ] +--- +## 问题原因 + +原因是:git commit 时,本地 git config 配置的 email 与 github 账号的 email 不一致,导致未被识别出来,检查方式 + +```bash +git config user.email +``` + +## 解决办法 + +如何配置,可参考 [is-it-possible-to-have-different-git-configuration-for-different-projects](https://stackoverflow.com/questions/8801729/is-it-possible-to-have-different-git-configuration-for-different-projects) + +配置好正确的 email 之后,已提交的代码需要以新的配置重新提交才可生效。 \ No newline at end of file diff --git a/docs/docs/faq/faq022.md b/docs/docs/faq/faq022.md new file mode 100644 index 000000000..86ec00c37 --- /dev/null +++ b/docs/docs/faq/faq022.md @@ -0,0 +1,18 @@ +--- +title: 节点无法拖拽到 Page 下 +sidebar_position: 22 +tags: [FAQ] +--- +查看 Page 节点的 childWhitelist 配置,如果 Page 配置了 childWhitelist,且当前节点不在白名单下,是无法拖拽的。 +```typescript +AliLowCodeEngine.material.getComponentMeta('Page').getMetadata().configure.component.nestingRule.childWhitelist +``` + +比如在 [demo](https://lowcode-engine.cn/demo/demo-general/index.html) 中 Page 组件的 childWhitelist 为:['NextPage', 'ProDialog', 'Dialog', 'Drawer'],则只有这些组件可以拖拽到 Page 的 children 下,其他组件均不可以。 + +说明:1.0.15 之前 Page 组件的 childWhitelist 限制是失效的,在 1.0.16 版本进行了 bug 修复。 + +### 解决办法 +**方法 1:直接修改 Page 组件的 childWhitelist,比如删除**。 + +**方法 2:通过 **[**material.registerMetadataTransducer**](/site/docs/api/material#registermetadatatransducer)** 修改 Page 组件的 childWhitelist(适用于 Page 组件是其他人维护的)** diff --git a/docs/docs/guide/appendix/glossary.md b/docs/docs/guide/appendix/glossary.md index e044f3e74..6c71e99e7 100644 --- a/docs/docs/guide/appendix/glossary.md +++ b/docs/docs/guide/appendix/glossary.md @@ -2,4 +2,4 @@ title: 名词解释 sidebar_position: 0 --- -![glossary](https://cdn.nlark.com/yuque/0/2022/jpeg/2622706/1648103397469-00227a70-e7ab-4a90-8378-c4da977250b2.jpeg) +![glossary](https://img.alicdn.com/imgextra/i2/O1CN01vPZjCM1jT26YujpGk_!!6000000004548-0-tps-2284-4301.jpg) diff --git a/docs/docs/guide/appendix/metaSpec.md b/docs/docs/guide/appendix/metaSpec.md index 6adcc5907..59bf5e633 100644 --- a/docs/docs/guide/appendix/metaSpec.md +++ b/docs/docs/guide/appendix/metaSpec.md @@ -2,6 +2,6 @@ title: 搭建组件协议结构 sidebar_position: 1 --- -完整协议请查看:[http://lowcode-engine.cn/material](http://lowcode-engine.cn/material) +完整协议[查看](/site/docs/specs/material-spec) -![](https://cdn.nlark.com/yuque/0/2022/jpeg/2622706/1646040400808-9a4a4d7d-6ad2-43be-8c97-d88f0cab7cc6.jpeg) +![](https://img.alicdn.com/imgextra/i4/O1CN01hozDem1apAhnvdESN_!!6000000003378-0-tps-2474-4128.jpg) diff --git a/docs/docs/guide/appendix/npms.md b/docs/docs/guide/appendix/npms.md index 9334140f4..ce25283e6 100644 --- a/docs/docs/guide/appendix/npms.md +++ b/docs/docs/guide/appendix/npms.md @@ -1,5 +1,5 @@ --- -title: NPM包对应源码位置汇总 +title: NPM 包对应源码位置汇总 sidebar_position: 3 --- | 包名 | 仓库 | 路径 | diff --git a/docs/docs/guide/appendix/repos.md b/docs/docs/guide/appendix/repos.md index b4dbca7ac..4fbfdc12c 100644 --- a/docs/docs/guide/appendix/repos.md +++ b/docs/docs/guide/appendix/repos.md @@ -2,7 +2,7 @@ title: 低代码仓库列表 sidebar_position: 2 --- -### 1. 引擎主包 +## 1. 引擎主包 包含引擎的 4 大模块,入料、编排、渲染和出码。 仓库地址:[https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) @@ -25,7 +25,7 @@ sidebar_position: 2 15. material-parser 16. code-generator -### 2. 引擎官方扩展包 +## 2. 引擎官方扩展包 包含了常用的设置器(setter)、跟 setter 绑定的插件等 仓库地址:[https://github.com/alibaba/lowcode-engine-ext](https://github.com/alibaba/lowcode-engine-ext) @@ -56,7 +56,7 @@ sidebar_position: 2 - 插件 plugin - plugin-event-bind-dialog 事件绑定浮层 - plugin-variable-bind-dialog 变量绑定浮层 -### 3. 低代码插件 +## 3. 低代码插件 包含了常用的插件等 仓库地址:[https://github.com/alibaba/lowcode-plugins](https://github.com/alibaba/lowcode-plugins) @@ -70,18 +70,18 @@ sidebar_position: 2 - plugin-undo-redo 前进/后退功能 - plugin-zh-cn 中英文切换功能 -### 4. 引擎 demo +## 4. 引擎 demo 展示使用引擎编排和渲染等模块以及相应的依赖资源配置基础 demo 仓库地址:[https://github.com/alibaba/lowcode-demo](https://github.com/alibaba/lowcode-demo) -### 5. 工具链包 +## 5. 工具链包 包含生成引擎生态元素(setter、物料、插件)的脚手架,启动脚本,调试插件等 仓库地址:[https://github.com/alibaba/lowcode-tools](https://github.com/alibaba/lowcode-tools) -### 6. 低代码数据源引擎 +## 6. 低代码数据源引擎 负责在渲染&出码两种运行时实现数据源管理,承担低代码搭建数据请求的能力; 仓库地址:[https://github.com/alibaba/lowcode-datasource](https://github.com/alibaba/lowcode-datasource) -### 7. 基础物料 & 物料描述 +## 7. 基础物料 & 物料描述 仓库地址:[https://github.com/alibaba/lowcode-materials](https://github.com/alibaba/lowcode-materials) -### 8. 出码 demo +## 8. 出码 demo 仓库地址:[https://github.com/alibaba/lowcode-code-generator-demo](https://github.com/alibaba/lowcode-code-generator-demo) diff --git a/docs/docs/guide/appendix/setterDetails/array.md b/docs/docs/guide/appendix/setterDetails/array.md index bbbd4498b..517292e2c 100644 --- a/docs/docs/guide/appendix/setterDetails/array.md +++ b/docs/docs/guide/appendix/setterDetails/array.md @@ -2,12 +2,12 @@ title: ArraySetter --- -#### 简介 -用来展示属性类型为数组的setter -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395220128-b5d948e3-6a5a-420f-9a7a-a29be25c507d.png#clientId=ud56bf956-0414-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=181&id=u27259ecd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=362&originWidth=584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=27221&status=done&style=none&taskId=u72065990-9557-4dbc-a0ba-eada448e228&title=&width=292) -#### 配置示例 -```javascript +## 简介 +用来展示属性类型为数组的 setter +## 展示 +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01BXCpnh1OFebSSyeDQ_!!6000000001676-2-tps-584-362.png) +## 配置示例 +```json "setter": { "componentName": "ArraySetter", "props": { @@ -18,7 +18,7 @@ title: ArraySetter "items": [{ "name": "title", "description": "标题", - "setter": "StringSetter", + "setter": "StringSetter" }, { "name": "callback", @@ -32,37 +32,36 @@ title: ArraySetter }, "initialValue": { "title": "I am title", - "callback": null, + "callback": null } } } } ``` -#### ArraySetter 配置 -| **属性名** | **类型** | **说明** | -| --- | --- | --- | -| itemSetter | ObjectSetter | ArraySetter的子节点内容必须用ObjectSetter包裹 | +## ArraySetter 配置 -#### itemSetter 配置 | **属性名** | **类型** | **说明** | | --- | --- | --- | -| componentName | String | - | +| itemSetter | ObjectSetter | ArraySetter 的子节点内容必须用 ObjectSetter 包裹 | + +## itemSetter 配置 + +| **属性名** | **类型** | **说明** | +| --- | --- | --- | +| componentName | String || | props | | | | initialValue | Object | 新增一项的初始值 | -#### ObjectSetter 配置 +## ObjectSetter 配置 | **属性名** | **类型** | **说明** | | --- | --- | --- | -| descriptor | String | Item在列表中展示的item.key名,需要和 config.items[] 中key对应 默认为 “项目X” -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448651683-6c44787a-cb6c-4066-9a47-2b22f862cb9c.png#clientId=u05af0495-3e67-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=186&id=ufb6e3681&margin=%5Bobject%20Object%5D&name=image.png&originHeight=372&originWidth=640&originalType=binary&ratio=1&rotation=0&showTitle=false&size=103250&status=done&style=none&taskId=u7a61b6f7-4e26-4d8b-a9e6-a30b5e9e73d&title=&width=320) | +| descriptor | String | Item 在列表中展示的 item.key 名,需要和 config.items[] 中key对应 默认为 “项目X” ![image.png](https://img.alicdn.com/imgextra/i4/O1CN01Okz1DY1Q17GGJBPDf_!!6000000001915-2-tps-640-372.png) | | config | Object | 配置项 | | config.items | Array | 子属性列表数据 | | config.items[].name | String | 子属性名称 | | config.items[].description | String | 子属性描述 | | config.items[].setter | Object | String | 子属性setter配置 | 子属性setter组件名 | -| config.items[].isRequired | Boolean | 子属性是否开启快捷编辑,最多开启4个 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448651860-f4f80e87-4e80-463d-a1e0-99be8bf2a84f.png#clientId=u6ba2ab37-e0fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=211&id=ueea652b0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=422&originWidth=614&originalType=binary&ratio=1&rotation=0&showTitle=false&size=32465&status=done&style=none&taskId=u343405fd-5773-4ebd-b6fc-1367a769fe2&title=&width=307) | +| config.items[].isRequired | Boolean | 子属性是否开启快捷编辑,最多开启4个 ![image.png](https://img.alicdn.com/imgextra/i1/O1CN01EflYAK1IPpiChvjHz_!!6000000000886-2-tps-614-422.png) | | config.items[].condition | Boolean | () => Boolean | 是否展示 | | config.items[].getValue | (target, value) => value | 数据获取的 hook,可修改获取数据 | | config.items[].setValue | (target, value) => value | 数据获取的 hook,可修改设置数据 | diff --git a/docs/docs/guide/appendix/setterDetails/bool.md b/docs/docs/guide/appendix/setterDetails/bool.md index d29274893..a2851e707 100644 --- a/docs/docs/guide/appendix/setterDetails/bool.md +++ b/docs/docs/guide/appendix/setterDetails/bool.md @@ -1,15 +1,18 @@ --- title: BoolSetter --- -#### 简介 +## 简介 开关选择器 -#### 展示 -![](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448646757-b61019f4-d502-473a-8a11-4974479c55dc.png#from=url&id=dnn2b&margin=%5Bobject%20Object%5D&originHeight=82&originWidth=320&originalType=binary&ratio=1&status=done&style=none) -#### setter 配置 +## 展示 + +![](https://img.alicdn.com/imgextra/i3/O1CN01KS7ndr1mHX0MITGPH_!!6000000004929-2-tps-320-82.png) +## setter 配置 + | 属性名 | 说明 | | --- | --- | | disabled | 是否可选 | | defaultValue | 默认值 | -#### 返回类型 +## 返回类型 + Boolean diff --git a/docs/docs/guide/appendix/setterDetails/color.md b/docs/docs/guide/appendix/setterDetails/color.md index 8c09f5883..b0b158b90 100644 --- a/docs/docs/guide/appendix/setterDetails/color.md +++ b/docs/docs/guide/appendix/setterDetails/color.md @@ -2,13 +2,15 @@ title: ColorSetter --- 用来选择颜色。 -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448646203-3eb11d27-0195-4608-91f3-0f3cfb6b7140.png#clientId=u09a8f665-5383-4&from=paste&height=416&id=u417e185d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=728&originWidth=590&originalType=binary&ratio=1&size=230281&status=done&style=none&taskId=u3d246b17-94ab-4eb3-af66-3ffb7fd3145&width=337) -#### setter 配置 +## 展示 + + +## setter 配置 | 属性名 | 说明 | | --- | --- | | defaultValue | 默认值 | -#### 返回类型 +## 返回类型 String -会返回options中的value值 + +会返回 options 中的 value 值 diff --git a/docs/docs/guide/appendix/setterDetails/event.md b/docs/docs/guide/appendix/setterDetails/event.md index 26405e908..b690b308f 100644 --- a/docs/docs/guide/appendix/setterDetails/event.md +++ b/docs/docs/guide/appendix/setterDetails/event.md @@ -1,20 +1,23 @@ --- title: EventSetter --- -#### 简介 +## 简介 可以将事件绑定在物料上 -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394906292-0eb3ab0e-0bb0-4c8d-bbc5-7217b33cdcab.png#clientId=ub4e2d6f6-4877-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=507&id=u2a295c86&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1014&originWidth=1202&originalType=binary&ratio=1&rotation=0&showTitle=false&size=293824&status=done&style=none&taskId=u37e95d95-4425-450a-b4aa-9805d9dcf97&title=&width=601) +## 展示 + + + +## 组件自带事件列表 + +在物料协议的 configure.supports.events 中声明 -#### 组件自带事件列表 -在物料协议的configure.supports.events 中声明 ```json { "configure ": { "supports": { "style": true, "events": [{ - "name": "onChange", + "name": "onChange" }, { "name": "onExpand" }, { @@ -25,34 +28,38 @@ title: EventSetter } ``` -#### 事件绑定 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448650540-8b403233-44a5-4b1f-9379-2c55d4694f12.png#clientId=uf9b6db87-aae9-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=621&id=u95bb9c9a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1242&originWidth=2540&originalType=binary&ratio=1&rotation=0&showTitle=false&size=356836&status=done&style=none&taskId=u13bc14bd-d85c-46c9-aebd-586dcb32f96&title=&width=1270) -可以选择已有的事件(schema中的**methods**节点)进行绑定,也可以选择新建事件,选择新建事件默认会增加_new的事件后缀命名,点确定以后会跳转到对应代码插件对应区块 -#### -#### 参数设置 -如果需要额外传参,需要将扩展参数设置打开,在代码面板中,编辑参数内容 +## 事件绑定 +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01Q5gHFy1uSzqUeEqQK_!!6000000006037-2-tps-2540-1242.png) + +可以选择已有的事件 (schema 中的**methods**节点) 进行绑定,也可以选择新建事件,选择新建事件默认会增加_new 的事件后缀命名,点确定以后会跳转到对应代码插件对应区块。 + +## 参数设置 + +如果需要额外传参,需要将扩展参数设置打开,在代码面板中,编辑参数内容。 + 注意: - 额外参数必须被包装成一个对象,如参数模板中所示 - 可以使用动态变量例如 (this.items,this.state.xxx) -```json -{ - "testKey":this.state.text -} -``` + ```javascript + { + testKey: this.state.text, + } + ``` -- 该参数是额外参数,会加在原有参数后面,例如在onClick中加入扩展传参,最终函数消费的时候应该如下所示 -```javascript -// e为onClick原有函数传参,extParams为自定义传参 -onClick(e, extParams) { - this.setState({ - isShowDialog: extParams.isShowDialog - }) -} -``` -#### 事件新建函数模板 -有时候我们创建的函数会有用到一些通用的函数模板,我们可以在物料协议的events.template中创建一个模板,如下 -```javascript +- 该参数是额外参数,会加在原有参数后面,例如在 onClick 中加入扩展传参,最终函数消费的时候应该如下所示 + ```javascript + // e 为 onClick 原有函数传参,extParams 为自定义传参 + onClick(e, extParams) { + this.setState({ + isShowDialog: extParams.isShowDialog, + }); + } + ``` +## 事件新建函数模板 +有时候我们创建的函数会有用到一些通用的函数模板,我们可以在物料协议的 events.template 中创建一个模板,如下 + +```json { "configure ": { "supports": { @@ -69,5 +76,7 @@ onClick(e, extParams) { } } ``` + 其中 ${extParams} 为扩展参数占位符,如果用户没有声明扩展参数,会移除对应的参数声明,定义模板后,每次创建完函数会自动生成模板函数,如下图 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448650786-62270a89-65d5-42b1-8efd-90b090155c82.png#clientId=uf9b6db87-aae9-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=141&id=u4bb4387b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=282&originWidth=1292&originalType=binary&ratio=1&rotation=0&showTitle=false&size=84790&status=done&style=none&taskId=u2b911f77-a018-4f17-a5df-36c2c142d18&title=&width=646) + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01XUoXnS1XiLxlxXniw_!!6000000002957-2-tps-1292-282.png) diff --git a/docs/docs/guide/appendix/setterDetails/icon.md b/docs/docs/guide/appendix/setterDetails/icon.md index 1e98059c3..ee425f793 100644 --- a/docs/docs/guide/appendix/setterDetails/icon.md +++ b/docs/docs/guide/appendix/setterDetails/icon.md @@ -1,25 +1,28 @@ --- title: IconSetter --- -#### 简介 +## 简介 用来选择图标 -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394747068-9b8f47e1-06f7-48de-ba73-9ed3d389f913.png#clientId=u144a54e7-b111-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=290&id=uae8bb869&margin=%5Bobject%20Object%5D&name=image.png&originHeight=579&originWidth=1172&originalType=binary&ratio=1&rotation=0&showTitle=false&size=148927&status=done&style=none&taskId=ud281e100-e277-493d-8d4a-0e7b2c1b8f2&title=&width=586) -#### setter 配置 +## 展示 + + +## setter 配置 + | **属性名** | **类型** | **说明** | | --- | --- | --- | -| type | String | 选择器返回类型 -**可选值**: -"string" | "node" | +| type | String | 选择器返回类型 **可选值**: "string" \| "node" | | defaultValue | String | ReactNode | 默认值 | | hasClear | Boolean | 选择器是否显示清除按钮 | -| icons | Array | 自定义icon集合;默认值详见[图标可选值](#SWnNn) | +| icons | Array | 自定义 icon 集合;默认值详见[图标可选值](#图标可选值) | | placeholder | String | 没有值的时候的占位符 | -#### 返回类型 +## 返回类型 + String | ReactNode -#### 图标可选值 -```json + +## 图标可选值 + +```javascript [ 'smile', 'cry', diff --git a/docs/docs/guide/appendix/setterDetails/mixed.md b/docs/docs/guide/appendix/setterDetails/mixed.md index 6ce3df024..aa8d8ff42 100644 --- a/docs/docs/guide/appendix/setterDetails/mixed.md +++ b/docs/docs/guide/appendix/setterDetails/mixed.md @@ -1,13 +1,15 @@ --- title: MixedSetter --- -#### 简介 -可以让属性同时支持多个setter +## 简介 +可以让属性同时支持多个 setter -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394866233-4b9127cd-3825-4763-9e2a-526ea2b48140.png#clientId=u7c96c5f7-4dd4-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=240&id=u7ca1df47&margin=%5Bobject%20Object%5D&name=image.png&originHeight=480&originWidth=1552&originalType=binary&ratio=1&rotation=0&showTitle=false&size=272344&status=done&style=none&taskId=u07037884-fbf4-411a-be82-29296ad1fb2&title=&width=776) +## 展示 + + + +## 配置 -#### 配置 | **属性名** | **类型** | **说明** | | --- | --- | --- | | setters | Array | SetterName | diff --git a/docs/docs/guide/appendix/setterDetails/number.md b/docs/docs/guide/appendix/setterDetails/number.md index cd4d95ab0..31a05fe0d 100644 --- a/docs/docs/guide/appendix/setterDetails/number.md +++ b/docs/docs/guide/appendix/setterDetails/number.md @@ -1,11 +1,13 @@ --- title: NumberSetter --- -#### 简介 +## 简介 用于输入数字。 -#### 展示 -![](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448648108-fae36b4c-fb3d-4a4e-b83e-c5233e8bae5d.png#from=url&id=czSyt&margin=%5Bobject%20Object%5D&originHeight=402&originWidth=576&originalType=binary&ratio=1&status=done&style=none) -#### setter 配置 +## 展示 + + + +## setter 配置 | 属性名 | 说明 | | --- | --- | | min, max | 指定最大最小值 | @@ -14,6 +16,7 @@ title: NumberSetter | units | 指定单位 string | | precision | 设置小数位数 number | -#### 返回类型 -#### Number -会返回value值 +## 返回类型 +Number + +会返回 value 值 diff --git a/docs/docs/guide/appendix/setterDetails/radioGroup.md b/docs/docs/guide/appendix/setterDetails/radioGroup.md index 10bbc13f4..44fb47e98 100644 --- a/docs/docs/guide/appendix/setterDetails/radioGroup.md +++ b/docs/docs/guide/appendix/setterDetails/radioGroup.md @@ -1,24 +1,18 @@ --- title: RadioGroupSetter --- -#### 简介 +## 简介 用于直观的展示选择并选择。 -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395469783-17a5f8b5-112a-420b-a64f-09fffea55067.png#clientId=u8044d585-4c1d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=49&id=ucafe75f2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=98&originWidth=564&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9843&status=done&style=none&taskId=ud3ff8182-f29c-4b81-b4de-e23baa325c1&title=&width=282) -#### setter 配置 +## 展示 + + + +## setter 配置 | 属性名 | 说明 | | --- | --- | | defaultValue | 默认值 | -| options | 传入的数据源, -**参数格式**: -[ -{img: 'url', -value: 'text', -label/title: 'text'}, ... -] -|| -[ 'text', 'text', ...] | +| options | 传入的数据源,**参数格式**: [{img: 'url', value: 'text', label/title: 'text'}, ...] \| [ 'text', 'text', ...] | -#### 返回类型 +## 返回类型 String | Number | Boolean -会返回options中的value值 +会返回 options 中的 value 值 diff --git a/docs/docs/guide/appendix/setterDetails/select.md b/docs/docs/guide/appendix/setterDetails/select.md index 296bafebf..2e5039194 100644 --- a/docs/docs/guide/appendix/setterDetails/select.md +++ b/docs/docs/guide/appendix/setterDetails/select.md @@ -1,24 +1,20 @@ --- title: SelectSetter --- -#### 简介 +## 简介 用来选择组件。在限定的可选性内进行选择,核心能力是选择 -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395925308-538eb962-f035-43b9-bdb3-ecc5bc9d1e85.png#clientId=u8b43103b-f292-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=301&id=u7a9a7786&margin=%5Bobject%20Object%5D&name=image.png&originHeight=602&originWidth=574&originalType=binary&ratio=1&rotation=0&showTitle=false&size=36601&status=done&style=none&taskId=u089007a6-76ec-44e8-94b5-127a8ba1a51&title=&width=287) -#### setter 配置 +## 展示 + + + +## setter 配置 | 属性名 | 说明 | | --- | --- | -| mode | 选择器模式 - -可选值: -'single', 'multiple', 'tag' | +| mode | 选择器模式 可选值: 'single', 'multiple', 'tag' | | defaultValue | 默认值 | -| options | 传入的数据源, -**参数格式**: -[ -{label/title: '文字', value: 'text'}, ... -] | +| options | 传入的数据源,**参数格式**: [ {label/title: '文字', value: 'text'}, ...] | + +## 返回类型 -#### 返回类型 String | Number | Boolean -会返回options中的value值 +会返回 options 中的 value 值 diff --git a/docs/docs/guide/appendix/setterDetails/slot.md b/docs/docs/guide/appendix/setterDetails/slot.md index 52e3f9f3b..7559343d5 100644 --- a/docs/docs/guide/appendix/setterDetails/slot.md +++ b/docs/docs/guide/appendix/setterDetails/slot.md @@ -2,92 +2,92 @@ title: SlotSetter --- ## 简介 -通过一个开启一个slot(插槽),可以在物料特定的一个位置渲染一个或者多个节点。slot比较适合物料的局部自定义渲染。 +通过一个开启一个 slot(插槽),可以在物料特定的一个位置渲染一个或者多个节点。slot 比较适合物料的局部自定义渲染。 ## 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448654034-6f527cc2-cf65-4e79-b904-21416800b5b8.png#clientId=u091bb73f-2e93-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=227&id=gAVIU&margin=%5Bobject%20Object%5D&name=image.png&originHeight=454&originWidth=588&originalType=binary&ratio=1&rotation=0&showTitle=false&size=103838&status=done&style=none&taskId=u45d2e179-54ea-40d1-a654-66151c337ff&title=&width=294) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395677385-84c39b6d-2356-4d86-a741-edbb7daffd6c.png#clientId=udcc199c0-6236-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=82&id=u999c2367&margin=%5Bobject%20Object%5D&name=image.png&originHeight=164&originWidth=644&originalType=binary&ratio=1&rotation=0&showTitle=false&size=18486&status=done&style=none&taskId=u6c13f469-173f-4ba0-9bfa-866122ef7a4&title=&width=322) + + +
+
+ + ## setter 配置 | 属性名 | 类型 | 说明 | | --- | --- | --- | -| initialValue | Object | 默认值 -{ -"type": "JSSlot", -"params": [ -"module" - ], -"value": [] -} - -params:接收函数的入参,可以直接在slot节点中消费,通过this.module (这里module是示例值,可根据实际函数入参更改) -value:可以定义一个节点,每次打开插槽的时候默认填充一个节点 - - | -| hideParams | boolean | 是否隐藏入参,注意该值只能隐藏入参的输入框,适合单行展示,实际渲染的时候,还是会传入params的参数,和params:[]不同 | -| checkedText | string | switch选中文案,默认显示"启用" | -| unCheckedText | string | switch取消文案,默认显示"关闭" | +| initialValue | Object | 默认值 { "type": "JSSlot", "params": [ "module" ], "value": [] } params:接收函数的入参,可以直接在slot节点中消费,通过this.module (这里module是示例值,可根据实际函数入参更改) value:可以定义一个节点,每次打开插槽的时候默认填充一个节点 | +| hideParams | boolean | 是否隐藏入参,注意该值只能隐藏入参的输入框,适合单行展示,实际渲染的时候,还是会传入 params 的参数,和 params:[]不同 | +| checkedText | string | switch 选中文案,默认显示"启用" | +| unCheckedText | string | switch 取消文案,默认显示"关闭" | ## 配置示例 -### 普通示例 -#### 配置 +### 配置 + ```typescript { - name: "propName", - title: "propTitle", + name: 'propName', + title: 'propTitle', setter: { - componentName: "SlotSetter", + componentName: 'SlotSetter', isRequired: true, - title: "组件坑位", + title: '组件坑位', initialValue: { - type: "JSSlot", - value: [] + type: 'JSSlot', + value: [], }, } } ``` -#### 组件 +### 组件 + ```typescript function A(props) { return props.propName; } ``` -### 带参数的插槽示例 -#### 配置 +## 带参数的插槽示例 +### 配置 + ```typescript { - name: "propName", - title: "propTitle", - setter: { - componentName: "SlotSetter", - isRequired: true, - title: "组件坑位", - initialValue: { - type: "JSSlot", - params: [ - "module" - ], - value: [] - }, - } + name: 'propName', + title: 'propTitle', + setter: { + componentName: 'SlotSetter', + isRequired: true, + title: '组件坑位', + initialValue: { + type: 'JSSlot', + params: [ 'module'], + value: [], + }, } +} ``` -#### 组件 +### 组件 + 组件需要传参数进行渲染,和普通示例的使用不一样。 + ```typescript function A(props) { - const module = [] + const module = []; return props.propName(module); } ``` -#### param 使用示例 +### param 使用示例 + 1.开启插槽 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652877673290-7a377a36-7da9-40c1-baff-1c7c8ad04a67.png#clientId=udd177887-e136-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=900&id=u9ba2344a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1800&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1291582&status=done&style=none&taskId=u60418282-46e2-46b4-95d2-156288bcbd7&title=&width=1792) + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01RlOXAV1TbFMBZa6xq_!!6000000002400-2-tps-3584-1800.png) + 2.拖拽组件到插槽中 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652877759606-6de16048-a5d9-477c-b38b-962690a39254.png#clientId=udd177887-e136-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=903&id=u43b38264&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1806&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1230647&status=done&style=none&taskId=u96d44a1e-033f-4cd0-ac81-df6cac8ea18&title=&width=1792) + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01NNiWLs26961orvk9i_!!6000000007618-2-tps-3584-1806.png) 3.在插槽内组件中使用变量绑定,绑定 this.xxx + xxx 入参的配置 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652877586491-904d6b18-a41a-4ba2-8664-088cd5feca72.png#clientId=udd177887-e136-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=903&id=u165f1564&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1806&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1278387&status=done&style=none&taskId=uc060e73a-b190-480a-8aad-8c20b27290c&title=&width=1792) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01cBn2ym1XF2cDZo5Yp_!!6000000002893-2-tps-3584-1806.png) diff --git a/docs/docs/guide/appendix/setterDetails/string.md b/docs/docs/guide/appendix/setterDetails/string.md index 77e5aacf4..c30bba770 100644 --- a/docs/docs/guide/appendix/setterDetails/string.md +++ b/docs/docs/guide/appendix/setterDetails/string.md @@ -1,14 +1,18 @@ --- title: StringSetter --- -#### 简介 +## 简介 + 用来展示和修改字符串类型的属性值,不可换行 -#### 展示 -![](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448645493-4a30f02e-1869-4963-8d39-40501891ae84.png#from=url&id=mEkyy&margin=%5Bobject%20Object%5D&originHeight=88&originWidth=714&originalType=binary&ratio=1&status=done&style=none) -#### setter 配置 +## 展示 + + + +## setter 配置 + | 属性名 | 说明 | | --- | --- | | placeholder | 输入提示 | -#### 返回类型 +## 返回类型 String diff --git a/docs/docs/guide/appendix/setterDetails/style.md b/docs/docs/guide/appendix/setterDetails/style.md index f733baaa3..c58f062f5 100644 --- a/docs/docs/guide/appendix/setterDetails/style.md +++ b/docs/docs/guide/appendix/setterDetails/style.md @@ -2,48 +2,27 @@ title: StyleSetter --- ## 简介 -通过开启StyleSetter,我们可以将样式配置面板来配置样式属性。 +通过开启 StyleSetter,我们可以将样式配置面板来配置样式属性。 ## 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1658650544358-3d97f6b1-6269-4627-ab4a-62a43219fd08.png#clientId=u5d06f6c0-ba35-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=739&id=u3f141635&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1478&originWidth=596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=75996&status=done&style=none&taskId=u16f49c5d-a32e-4cf8-95ab-e0c1059fbef&title=&width=298) + + ## setter 配置 | 属性名 | 类型 | 说明 | | --- | --- | --- | -| unit | String | 默认值 px -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1658650635878-fd920e86-ea28-4e08-8676-238ac367a0ee.png#clientId=u5d06f6c0-ba35-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=49&id=u3f243c11&margin=%5Bobject%20Object%5D&name=image.png&originHeight=98&originWidth=576&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9796&status=done&style=none&taskId=ucc541aa4-0765-4da9-820c-cee48ed0635&title=&width=288) - | -| placeholderScale | Number | 默认计算尺寸缩放 默认值为1 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1658650773475-7ecba070-c81e-4a6c-b346-7aad7dd6a897.png#clientId=u5d06f6c0-ba35-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=49&id=u27842257&margin=%5Bobject%20Object%5D&name=image.png&originHeight=98&originWidth=250&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7116&status=done&style=none&taskId=u8ac18c79-d14b-49a6-8788-476524e69da&title=&width=125) -在没有设定数值的时候,系统会通过window.getComputedStyle来计算展示的数值。 -在某些场景下,例如手机场景,在编辑器展示的是375的实际宽度,但是实际设计尺寸是750的宽度,这个时候需要对这个计算尺寸设成2 | -| showModuleList | String[] | 默认值 -['background', 'border', 'font', 'layout', 'position'] -分别对应背景、边框、文字、布局、位置五个区块,可以针对不同的场景按需进行展示。 -例如文字的组件,我不需要修改边框的样式,就可以把边框模块隐藏掉 | +| unit | String | 默认值 px | +| placeholderScale | Number | 默认计算尺寸缩放 默认值为 1 在没有设定数值的时候,系统会通过 window.getComputedStyle 来计算展示的数值。在某些场景下,例如手机场景,在编辑器展示的是 375 的实际宽度,但是实际设计尺寸是 750 的宽度,这个时候需要对这个计算尺寸设成 2 | +| showModuleList | String[] | 默认值 ['background', 'border', 'font', 'layout', 'position'] 分别对应背景、边框、文字、布局、位置五个区块,可以针对不同的场景按需进行展示。 例如文字的组件,我不需要修改边框的样式,就可以把边框模块隐藏掉 | | isShowCssCode | Boolean | 默认值: true, 是否展示css源码编辑 | | layoutPropsConfig | Object | 布局样式设置 | -| layoutPropsConfig.showDisPlayList | String[] | 默认值 ['inline', 'flex', 'block', 'inline-block', 'none'] -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1658651295786-48ca3773-1b4e-4f2e-9521-0ebbfcfe5361.png#clientId=u5d06f6c0-ba35-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=36&id=u50dae00c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=72&originWidth=474&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7621&status=done&style=none&taskId=ub5804835-d0b2-45d7-a419-66ac1005afa&title=&width=237) -可按需展示 - | -| layoutPropsConfig.isShowPadding | String | 默认值 true -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1658651496157-c84348d4-a47f-44b4-b2c5-74b21e97747a.png#clientId=u5d06f6c0-ba35-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=191&id=u70235603&margin=%5Bobject%20Object%5D&name=image.png&originHeight=382&originWidth=548&originalType=binary&ratio=1&rotation=0&showTitle=false&size=20439&status=done&style=none&taskId=udae33336-ce05-41a9-89c5-361a63d061a&title=&width=274) -是否展示内边距 (四个边) | -| layoutPropsConfig.isShowMargin | Boolean | 默认值 true -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1658651539776-090de3e1-6293-4660-b74f-9bcf027381c6.png#clientId=u5d06f6c0-ba35-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=241&id=uab3771c7&margin=%5Bobject%20Object%5D&name=image.png&originHeight=482&originWidth=536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=29325&status=done&style=none&taskId=uc287d55d-5363-4b37-978b-6e150f36141&title=&width=268) -是否展示外边距 (四个边) | -| layoutPropsConfig.isShowWidthHeight | Boolean | 默认值 true -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1658651621765-06e81934-9a90-4290-89dd-75ffb56808a5.png#clientId=u5d06f6c0-ba35-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=51&id=u02aa5918&margin=%5Bobject%20Object%5D&name=image.png&originHeight=102&originWidth=546&originalType=binary&ratio=1&rotation=0&showTitle=false&size=9945&status=done&style=none&taskId=u394451ef-266c-440d-a86e-fc1a01320ea&title=&width=273) -是否展示宽高 | +| layoutPropsConfig.showDisPlayList | String[] | 默认值 ['inline', 'flex', 'block', 'inline-block', 'none'] 可按需展示 | +| layoutPropsConfig.isShowPadding | String | 默认值 true 是否展示内边距(四个边) || +| layoutPropsConfig.isShowMargin | Boolean | 默认值 true 是否展示外边距(四个边) || +| layoutPropsConfig.isShowWidthHeight | Boolean | 默认值 true 是否展示宽高 | | fontPropsConfig | Object | 文字样式设置 | -| fontPropsConfig.fontFamilyList | Array | [ - { value: 'Helvetica', label: 'Helvetica' }, - { value: 'Arial', label: 'Arial' }, - { value: 'serif', label: 'serif' }, - ] -可以定制文字字体选项 | +| fontPropsConfig.fontFamilyList | Array | [ { value: 'Helvetica', label: 'Helvetica' }, { value: 'Arial', label: 'Arial' },] 可以定制文字字体选项 | | positionPropsConfig | Object | 位置样式设置 | -| positionPropsConfig.isShowFloat | Boolean | 默认true 是否展示浮动 | -| positionPropsConfig.isShowClear | Boolean | 默认true 是否展示清除浮动 | +| positionPropsConfig.isShowFloat | Boolean | 默认 true 是否展示浮动 | +| positionPropsConfig.isShowClear | Boolean | 默认 true 是否展示清除浮动 | diff --git a/docs/docs/guide/appendix/setterDetails/textArea.md b/docs/docs/guide/appendix/setterDetails/textArea.md index 9188012f8..eff698b3d 100644 --- a/docs/docs/guide/appendix/setterDetails/textArea.md +++ b/docs/docs/guide/appendix/setterDetails/textArea.md @@ -1,14 +1,16 @@ --- -title: StyleSetter +title: TextAreaSetter --- -#### 简介 +## 简介 表单输入组件。 -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395839676-9feaa4d6-dbec-40c0-a93c-6014006a50c5.png#clientId=u01f23b13-e688-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=146&id=u29c456c5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=292&originWidth=1026&originalType=binary&ratio=1&rotation=0&showTitle=false&size=304205&status=done&style=none&taskId=u83ca85c2-3a04-4c41-a055-31d1bb86d84&title=&width=513) -#### setter 配置 +## 展示 + + + +## setter 配置 | **属性名** | **类型** | **说明** | | --- | --- | --- | | placeholder | String | 输入提示 | -#### 返回类型 +## 返回类型 String diff --git a/docs/docs/guide/appendix/setterDetails/variable.md b/docs/docs/guide/appendix/setterDetails/variable.md index 88e46e0cd..ed7d78c5b 100644 --- a/docs/docs/guide/appendix/setterDetails/variable.md +++ b/docs/docs/guide/appendix/setterDetails/variable.md @@ -1,12 +1,16 @@ --- title: VariableSetter --- -#### 简介 +## 简介 + 用来给属性值设定变量 -#### 展示 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395534301-67aaf74b-2561-4682-a0b2-dcde642a8d7c.png#clientId=u46178fa3-bc0c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=46&id=ucd7e6f91&margin=%5Bobject%20Object%5D&name=image.png&originHeight=92&originWidth=578&originalType=binary&ratio=1&rotation=0&showTitle=false&size=10671&status=done&style=none&taskId=u854e606f-bbd1-42f4-81a2-d161aa4e2d3&title=&width=289) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643448653288-1b5b46c8-5ea1-455d-9ce4-19abade13b31.png#clientId=udec6352b-e220-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=595&id=u2395a6a5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1190&originWidth=1564&originalType=binary&ratio=1&rotation=0&showTitle=false&size=256705&status=done&style=none&taskId=u3f3418f8-b6ad-464e-8fe6-89586fbc07d&title=&width=782) -#### -#### 变量列表 -包含所有的在协议中的**state**(state属性)节点数据和**methods**(自定义处理函数)节点数据 +## 展示 + + +
+ + + +## 变量列表 +包含所有的在协议中的**state**(state 属性) 节点数据和**methods**(自定义处理函数) 节点数据 diff --git a/docs/docs/guide/appendix/setters.md b/docs/docs/guide/appendix/setters.md index 381ef8198..fe578eee6 100644 --- a/docs/docs/guide/appendix/setters.md +++ b/docs/docs/guide/appendix/setters.md @@ -4,38 +4,26 @@ sidebar_position: 4 --- | 预置 Setter | 返回类型 | 用途 | 截图 | | --- | --- | --- | --- | -| [ArraySetter](https://www.yuque.com/lce/doc/eiegwf?view=doc_embed&from=kb&from=kb&outline=1&title=1) | T[] | 列表数组行数据设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395227012-97d27c4d-e053-4aae-9de1-726015081a4d.png#crop=0&crop=0&crop=1&crop=1&from=url&id=MHREr&margin=%5Bobject%20Object%5D&originHeight=362&originWidth=584&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [BoolSetter](https://www.yuque.com/lce/doc/mdxryw?view=doc_embed&from=kb&from=kb&outline=1&title=1) | boolean | 布尔型数据设置器, | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394538926-81adaab2-fe44-4cf4-93a0-4f46d790cfc6.png#crop=0&crop=0&crop=1&crop=1&from=url&id=yVcL4&margin=%5Bobject%20Object%5D&originHeight=82&originWidth=320&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| ClassNameSetter | string | 样式名设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/2553587/1644417220734-fd13e249-43f0-4caa-8122-9c1a791cd30f.png#crop=0&crop=0&crop=1&crop=1&from=url&id=RNQQQ&margin=%5Bobject%20Object%5D&originHeight=180&originWidth=502&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [ColorSetter](https://www.yuque.com/lce/doc/hu5ir6?view=doc_embed&from=kb&from=kb&outline=1&title=1) | string | 颜色设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394553552-2c8c3982-1671-47b3-a569-297bcb838b79.png#crop=0&crop=0&crop=1&crop=1&from=url&id=CxWyj&margin=%5Bobject%20Object%5D&originHeight=728&originWidth=590&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| DateMonthSetter | - | 日期型-月数据设置器 | - | -| DateRangeSetter | - | 日期型数据设置器,可选择时间区间 | - | -| DateSetter | - | 日期型数据设置器 | - | -| DateYearSetter | - | 日期型-年数据设置器 | - | -| [EventSetter](https://www.yuque.com/lce/doc/fiu8cz?view=doc_embed&from=kb&from=kb&outline=1&title=1) | function | 事件绑定设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394913684-e50d5fb4-50f4-4f6a-b5f8-5a6269b56676.png#crop=0&crop=0&crop=1&crop=1&from=url&id=lCP5h&margin=%5Bobject%20Object%5D&originHeight=1014&originWidth=1202&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [IconSetter](https://www.yuque.com/lce/doc/ry138x?view=doc_embed&from=kb&from=kb&outline=1&title=1) | string | 图标设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394768487-d7b9a492-254e-46bd-a755-f8f73d76b932.png#crop=0&crop=0&crop=1&crop=1&from=url&id=pbQvJ&margin=%5Bobject%20Object%5D&originHeight=579&originWidth=1172&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| FunctionSetter | any | 函数型数据设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/2553587/1644417386132-50215eb0-ca7e-499b-8ca8-bd0b19ce89e1.png#crop=0&crop=0&crop=1&crop=1&from=url&id=YZ16c&margin=%5Bobject%20Object%5D&originHeight=110&originWidth=794&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| JsonSetter | object | json型数据设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/2553587/1644418044457-a50b1621-090a-440d-9735-b3e9b7b3abd8.png#crop=0&crop=0&crop=1&crop=1&from=url&id=OywYO&margin=%5Bobject%20Object%5D&originHeight=1068&originWidth=1076&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [MixedSetter](https://www.yuque.com/lce/doc/ah6o2c?view=doc_embed&from=kb&from=kb&outline=1&title=1) | any | 混合型数据设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394872594-bb8f8de1-824a-4ba7-8b83-e408434a7d29.png#crop=0&crop=0&crop=1&crop=1&from=url&id=it6Xz&margin=%5Bobject%20Object%5D&originHeight=480&originWidth=1552&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [NumberSetter](https://www.yuque.com/lce/doc/hk65u5?view=doc_embed&from=kb&from=kb&outline=1&title=1) | number | 数值型数据设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644394982613-b1a43863-fd63-4bb4-b5fe-2f36109c449b.png#crop=0&crop=0&crop=1&crop=1&from=url&id=bEZjH&margin=%5Bobject%20Object%5D&originHeight=328&originWidth=1152&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| ObjectSetter | Record | 对象数据设置器,一般内嵌在ArraySetter中 | - | -| [RadioGroupSetter](https://www.yuque.com/lce/doc/cmpf0b?view=doc_embed&from=kb&from=kb&outline=1&title=1) | string | number | boolean | 枚举型数据设置器,采用tab选择的形式展现 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395460363-1fdb034c-69d7-404d-9226-37f1d4562210.png#crop=0&crop=0&crop=1&crop=1&from=url&id=XSyl3&margin=%5Bobject%20Object%5D&originHeight=98&originWidth=564&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [SelectSetter](https://www.yuque.com/lce/doc/po1t1r?view=doc_embed&from=kb&from=kb&outline=1&title=1) | string | number | boolean | 枚举型数据设置器,采用下拉的形式展现 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395970016-dfe95495-53b1-4f86-afc6-a0c621917440.png#crop=0&crop=0&crop=1&crop=1&from=url&id=NPzvg&margin=%5Bobject%20Object%5D&originHeight=282&originWidth=582&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [SlotSetter](https://www.yuque.com/lce/doc/af5vba?view=doc_embed&from=kb&from=kb&outline=1&title=1) | Element | Element[] | 节点型数据设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395692198-ca0cb611-0b7b-43b2-9f3b-3f6983cc3b37.png#crop=0&crop=0&crop=1&crop=1&from=url&id=SLNSR&margin=%5Bobject%20Object%5D&originHeight=164&originWidth=644&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [StringSetter](https://www.yuque.com/lce/doc/qogni4?view=doc_embed&from=kb&from=kb&outline=1&title=1) | string | 短文本型数据设置器,不可换行 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395613012-e7e5db32-9281-4f19-a18d-284765cd1184.png#crop=0&crop=0&crop=1&crop=1&from=url&id=OySEz&margin=%5Bobject%20Object%5D&originHeight=102&originWidth=414&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| StyleSetter | - | 样式设置器 | ![](https://cdn.nlark.com/yuque/0/2022/png/2553587/1644416984306-00aca829-3611-4f4c-b6b6-a20d0da0bfe7.png#crop=0&crop=0&crop=1&crop=1&from=url&id=aWlAc&margin=%5Bobject%20Object%5D&originHeight=1214&originWidth=788&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| [TextAreaSetter](https://www.yuque.com/lce/doc/gp36z6?view=doc_embed&from=kb&from=kb&outline=1&title=1) | string | 长文本型数据设置器,可换行 | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395843901-4d9c3e04-f6fc-4d50-93ed-44e6d8a99b9a.png#crop=0&crop=0&crop=1&crop=1&from=url&id=grvEZ&margin=%5Bobject%20Object%5D&originHeight=292&originWidth=1026&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | -| TimePicker | - | 时间型数据设置器 | - | -| [VariableSetter](https://www.yuque.com/lce/doc/lkvb36?view=doc_embed&from=kb&from=kb&outline=1&title=1) | any | 变量型数据设置器, | ![](https://cdn.nlark.com/yuque/0/2022/png/242652/1644395524553-dba00e02-f44c-429f-a8f4-c0e5f6d8b35f.png#crop=0&crop=0&crop=1&crop=1&from=url&id=L5BHL&margin=%5Bobject%20Object%5D&originHeight=92&originWidth=578&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) | +| [ArraySetter](./setterDetails/array) | T[] | 列表数组行数据设置器 | ![](https://img.alicdn.com/imgextra/i1/O1CN01UNmb7429mtHsbTHg3_!!6000000008111-2-tps-584-362.png) | +| [BoolSetter](./setterDetails/behavior) | boolean | 布尔型数据设置器, | ![](https://img.alicdn.com/imgextra/i2/O1CN01gZlHyx24MiZfjU61A_!!6000000007377-2-tps-320-82.png) | +| ClassNameSetter | string | 样式名设置器 | ![](https://img.alicdn.com/imgextra/i3/O1CN01ResoVi1PtKWxwuww8_!!6000000001898-2-tps-502-180.png) | +| [ColorSetter](./setterDetails/color) | string | 颜色设置器 | ![](https://img.alicdn.com/imgextra/i4/O1CN018gsNdw1Qt9zsZWP9K_!!6000000002033-2-tps-590-728.png) | +| DateMonthSetter | | 日期型 - 月数据设置器 | | +| DateRangeSetter | | 日期型数据设置器,可选择时间区间 | | +| DateSetter | | 日期型数据设置器 | | +| DateYearSetter || 日期型 - 年数据设置器 | | +| [EventSetter](./setterDetails/event) | function | 事件绑定设置器 | ![](https://img.alicdn.com/imgextra/i4/O1CN01qxIYiO1ksVknhTpnW_!!6000000004739-2-tps-1202-1014.png) | +| [IconSetter](./setterDetails/icon) | string | 图标设置器 | ![](https://img.alicdn.com/imgextra/i3/O1CN01zsOMxo1TXaBmjHCRc_!!6000000002392-2-tps-1172-579.png) | +| FunctionSetter | any | 函数型数据设置器 | ![](https://img.alicdn.com/imgextra/i4/O1CN01jLiJBo1ZIp7OmDLp0_!!6000000003172-2-tps-794-110.png) | +| JsonSetter | object | json 型数据设置器 | ![](https://img.alicdn.com/imgextra/i2/O1CN01mQTFjY1YiBQzWYj64_!!6000000003092-2-tps-1076-1068.png) | +| [MixedSetter](./setterDetails/mixed) | any | 混合型数据设置器 | ![](https://img.alicdn.com/imgextra/i1/O1CN01ZxomFY1JW4j7wIGuQ_!!6000000001035-2-tps-1552-480.png) | +| [NumberSetter](./setterDetails/number) | number | 数值型数据设置器 | ![](https://img.alicdn.com/imgextra/i3/O1CN01dSfSgg1WS2EpbqJIO_!!6000000002786-2-tps-1152-328.png) | +| ObjectSetter | Record | 对象数据设置器,一般内嵌在 ArraySetter 中 || +| [RadioGroupSetter](./setterDetails/radioGroup)| string | number | boolean | 枚举型数据设置器,采用 tab 选择的形式展现 || ![](https://img.alicdn.com/imgextra/i4/O1CN01Z0Zgi51W10s5L2Hce_!!6000000002727-2-tps-564-98.png) | +| [SelectSetter](./setterDetails/select) | string | number | boolean | 枚举型数据设置器,采用下拉的形式展现 | ![](https://img.alicdn.com/imgextra/i1/O1CN01sfUEgZ1I0BXCl60LM_!!6000000000830-2-tps-582-282.png) | +| [SlotSetter](./setterDetails/slot) | Element | Element[] | 节点型数据设置器 | ![](https://img.alicdn.com/imgextra/i3/O1CN01wulNGt1qNip0IlEsF_!!6000000005484-2-tps-644-164.png) | +| [StringSetter](./setterDetails/string) | string | 短文本型数据设置器,不可换行 | ![](https://img.alicdn.com/imgextra/i4/O1CN01iYalzO1xVh1ikLvSr_!!6000000006449-2-tps-414-102.png) | +| StyleSetter || 样式设置器 | ![](https://img.alicdn.com/imgextra/i4/O1CN01ZwX2pO26UAFKuYfuF_!!6000000007664-2-tps-788-1214.png) | +| [TextAreaSetter](./setterDetails/textArea) | string | 长文本型数据设置器,可换行 | ![](https://img.alicdn.com/imgextra/i4/O1CN01GMu8YJ1nqAZoYQ3xi_!!6000000005140-2-tps-1026-292.png) | +| TimePicker | | 时间型数据设置器 || +| [VariableSetter](./setterDetails/variable) | any | 变量型数据设置器, | ![](https://img.alicdn.com/imgextra/i1/O1CN015V5AAY1v3B8XxQ75k_!!6000000006116-2-tps-578-92.png) | diff --git a/docs/docs/guide/create/_category_.json b/docs/docs/guide/create/_category_.json index a5b30e063..a4ace0acc 100644 --- a/docs/docs/guide/create/_category_.json +++ b/docs/docs/guide/create/_category_.json @@ -1,5 +1,5 @@ { - "label": "创建低代码应用", + "label": "创建低代码编辑器", "position": 1, "collapsed": false, "collapsible": true diff --git a/docs/docs/guide/create/useEditor.md b/docs/docs/guide/create/useEditor.md index aca9faf68..21de39108 100644 --- a/docs/docs/guide/create/useEditor.md +++ b/docs/docs/guide/create/useEditor.md @@ -8,39 +8,50 @@ sidebar_position: 0 1. clone 低代码项目的官方 demo,直接启动项目。适合普通人。 2. 手工引入低代码 UMD 包,手工配置、打包和启动。适合 Webpack 配置工程师。 -# 方法 1: Clone 并启动 - -可以通过两种方式之一获取低代码编辑器的示例代码: - -1. 直接[在 github 仓库下](https://github.com/alibaba/lowcode-demo)进行下载 - -![Rectangle 2.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1645178084931-b81f6960-f0be-4695-ae38-e2632c859629.png#clientId=u6721b06e-9fb2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=259&id=ud829c08c&margin=%5Bobject%20Object%5D&name=Rectangle%202.png&originHeight=517&originWidth=1500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=163331&status=done&style=none&taskId=ua56b6104-b23f-4dd6-a95c-4fa8ac8cb3c&title=&width=750) - -2. 如果本地安装了 git,可以通过 git clone 方式进行下载 - -(这个方法的好处是 demo 有了更新,可以通过 merge 方式跟上) -```typescript -git clone https://github.com/alibaba/lowcode-demo.git -``` - -拉取仓库代码后,需要进行如下配置或安装过程: +## 方法 1:通过官方命令行工具创建编辑器 1. 确保本地安装了 Node.js 和 npm,如果没有,[您可以通过 nvm 进行快捷的安装](https://github.com/nvm-sh/nvm) 2. 确保为 npm [设置了可以访问的 npm 源,保证安装过程无网络问题](https://npmmirror.com/) -3. 执行 `npm install` +3. 安装官方命令行工具 + ```bash + npm install -g @alilc/create-element@latest + ``` +4. 通过命令行工具创建 + ```bash + npm init @alilc/element editor-project-name + ``` + 这时会看到一个选项列表 -依赖完全安装完成后,执行 `npm start`,如果看到这个界面,说明项目启动成功。您可以继续看后续章节了。本章节后续内容均为高级配置方式。 + -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644982015764-35bb5f58-fbd6-4838-9792-3c5b2136162d.png#clientId=ub335956d-fdf2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=817&id=u01bca493&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1634&originWidth=3060&originalType=binary&ratio=1&rotation=0&showTitle=false&size=216709&status=done&style=stroke&taskId=u467c43dc-35c5-4c84-907d-d6db9a0b839&title=&width=1530) + 选择`编辑器`,并填写对应的问题,即可完成创建。 -# 方法 2: 手工引入低代码 UMD 包,手工配置打包和启动 + > 注 @alilc/create-element 版本需 >= 1.0.4,若看不到`编辑器`选项,请重新执行步骤 3 +5. 进入创建后的目录 + ```bash + cd editor-project-name + ``` +6. 安装依赖 + ```bash + npm install + ``` +7. 安装依赖成功后,启动项目 (注意观察上一步的输出,如有 error 等失败信息,请先进行排查) + ```bash + npm start + ``` + 执行后如果看到这个界面,说明项目启动成功。您可以继续看后续章节了。本章节后续内容均为高级配置方式。 + + ![image.png](https://img.alicdn.com/imgextra/i4/O1CN013qJVoV1OAcFNKFrIQ_!!6000000001665-2-tps-3060-1634.png) + +## 方法 2: 使用 UMD 包方式配置 如果您不是从零开始的项目,您可能需要手工引入低代码引擎。 -## 引入 UMD 包资源 +### 引入 UMD 包资源 我们需要在启动前,正确在项目中通过 UMD 包方式直接依赖如下内容: -(亦可使用异步加载工具,如果您按照正确的顺序进行加载) +> 亦可使用异步加载工具,如果您按照正确的顺序进行加载 + ```html @@ -72,9 +83,9 @@ git clone https://github.com/alibaba/lowcode-demo.git > 注:如果 unpkg 的服务比较缓慢,您可以使用 alicdn 来获得确定版本的低代码引擎,如对于引擎的 1.0.1 版本,可用 [https://alifd.alicdn.com/npm/@alilc/lowcode-engine@1.0.1/dist/js/engine-core.js](https://alifd.alicdn.com/npm/@alilc/lowcode-engine@1.0.1/dist/js/engine-core.js) -## 配置打包 +### 配置打包 -因为这些资源已经通过 UMD 方式引入,所以在 Webpack 等构建工具中需要配置它们为 external,不再重复打包: +因为这些资源已经通过 UMD 方式引入,所以在 webpack 等构建工具中需要配置它们为 external,不再重复打包: ```javascript { @@ -84,20 +95,16 @@ git clone https://github.com/alibaba/lowcode-demo.git "prop-types": "var window.PropTypes", "@alifd/next": "var window.Next", "@alilc/lowcode-engine": "var window.AliLowCodeEngine", - "@alilc/lowcode-editor-core": "var window.AliLowCodeEngine.common.editorCabin", - "@alilc/lowcode-editor-skeleton": "var window.AliLowCodeEngine.common.skeletonCabin", - "@alilc/lowcode-designer": "var window.AliLowCodeEngine.common.designerCabin", "@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt", - "@ali/lowcode-engine": "var window.AliLowCodeEngine", "moment": "var window.moment", "lodash": "var window._" } } ``` -## 初始化低代码编辑器 +### 初始化低代码编辑器 -### 方法 2.1 使用 init 进行初始化 +#### 方法 2.1 使用 init 进行初始化 正确引入后,我们可以直接通过 window 上的变量进行引用,如 `window.AliLowCodeEngine.init`。您可以直接通过此方式初始化低代码引擎: @@ -114,11 +121,12 @@ window.AliLowCodeEngine.init(document.getElementById('lce-container'), { // package.json { "devDependencies": { - "@alilc/lowcode-engine": "beta" + "@alilc/lowcode-engine": "^1.0.0" } } ``` ```javascript +// src/index.tsx import { init } from '@alilc/lowcode-engine'; init(document.getElementById('lce-container'), { @@ -133,52 +141,61 @@ init 的功能包括但不限于: 2. 传递 preference 并设置 plugins 入参; 3. 初始化 Workbench; -> 本节中的低代码编辑器例子可以在 demo 中找到:[https://github.com/alibaba/lowcode-demo/blob/main/src/index.ts#L21-L34](https://github.com/alibaba/lowcode-demo/blob/main/src/index.ts#L21-L34) +> 本节中的低代码编辑器例子可以在 demo 中找到:[https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/index.ts](https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/index.ts) -### 方法 2.2 使用 skeletonCabin.Workbench 方式初始化 +#### 方法 2.2 使用 skeletonCabin.Workbench 方式初始化 `init()` 内部会调用 `ReactDOM.render()` 函数,因此这样初始化的内容没有办法与外部的 React 组件进行通信,也就没有办法在一些自定义的 plugin 中获取 redux 上的全局数据等内容。 + 因此,这种场景下您可以通过 `skeletonCabin.Workbench` 进行初始化。 -> 注:您不需要同时使用 2.1 和 2.2 的方法。根据使用场景,只有需要低代码引擎插件和外界进行一定通信时,2.2 提供的方法才是必要的。 +> 注:**不需要**同时使用 2.1 和 2.2 的方法。根据使用场景,当且只当有需要插件和外界进行一定通信时,才需要使用 2.2 提供的方法。 ```javascript -import React, { useState, useEffect } from 'react' -import { project, plugins, common, skeleton } from '@alilc/lowcode-engine' +import React, { useState, useEffect } from 'react'; +import { project, plugins, common, skeleton } from '@alilc/lowcode-engine'; -// 此 schema 参考 demo 中的默认 schema 书写 -import userSchema from './schema.json' +// 此处略去若干依赖引用 -export default function EditorView() { +async function registerPlugins() { + // 此处略去若干插件注册 +} +function EditorView() { /** 插件是否已初始化成功,因为必须要等插件初始化后才能渲染 Workbench */ const [hasPluginInited, setHasPluginInited] = useState(false); useEffect(() => { plugins.init().then(() => { - setHasPluginInited(true) - }).catch(err => console.error(err)) + setHasPluginInited(true); + }).catch(err => console.error(err)); }, []); - useEffect(() => { - project.importSchema(userSchema) - }, [userSchema]); - if (!hasPluginInited) { return null; } - - return ( - - ); + const Workbench = common.skeletonCabin.Workbench; + return ; } + +(async function main() { + await registerPlugins(); + config.setConfig({ + enableCondition: true, + enableCanvasLock: true, + supportVariableGlobally: true, + requestHandlersMap: { + fetch: createFetchHandler() + } + }); + + ReactDOM.render(, document.getElementById('lce-container')!); +})(); ``` -> 本节中的低代码编辑器类似的例子可以在 demo 中找到:[https://github.com/alibaba/lowcode-demo/blob/main/src/scenarios/custom-initialization/index.tsx](https://github.com/alibaba/lowcode-demo/blob/main/src/scenarios/custom-initialization/index.tsx) +> 本节中的低代码编辑器类似的例子可以在 demo 中找到:[https://github.com/alibaba/lowcode-demo/blob/main/demo-custom-initialization/src/index.tsx](https://github.com/alibaba/lowcode-demo/blob/main/demo-custom-initialization/src/index.tsx) -# 配置低代码编辑器 -详见“低代码扩展简述“章节。 +## 配置低代码编辑器 +详见[低代码扩展简述](/site/docs/guide/expand/editor/summary)章节。 diff --git a/docs/docs/guide/create/useRenderer.md b/docs/docs/guide/create/useRenderer.md index 4f7a0a08b..a9fc79909 100644 --- a/docs/docs/guide/create/useRenderer.md +++ b/docs/docs/guide/create/useRenderer.md @@ -5,18 +5,20 @@ sidebar_position: 1 低代码引擎的编辑器将产出两份数据: -- 资产包数据 assets:包含物料名称、包名及其获取方式,对应协议中的[《低代码引擎资产包协议规范》](https://lowcode-engine.cn/assets) -- 页面数据 schema:包含页面结构信息、生命周期和代码信息,对应协议中的[《低代码引擎搭建协议规范》](https://lowcode-engine.cn/lowcode) +- 资产包数据 assets:包含物料名称、包名及其获取方式,对应协议中的[《低代码引擎资产包协议规范》](/site/docs/specs/assets-spec) +- 页面数据 schema:包含页面结构信息、生命周期和代码信息,对应协议中的[《低代码引擎搭建协议规范》](/site/docs/specs/lowcode-spec) 经过上述两份数据,可以直接交由渲染模块或者出码模块来运行,二者的区别在于: -- 渲染模块:使用资产包数据、页面数据和低代码运行时,并且允许维护者在低代码编辑器中用 Low Code 的方式继续维护; -- 出码模块:不依赖低代码运行时和页面数据,直接生成可直接运行的代码,并且允许维护者用 Pro Code 的方式继续维护,但无法再利用用低代码编辑器; +- 渲染模块:使用资产包数据、页面数据和低代码运行时,并且允许维护者在低代码编辑器中用 `低代码(LowCode)`的方式继续维护; +- 出码模块:不依赖低代码运行时和页面数据,直接生成可直接运行的代码,并且允许维护者用 `源码(ProCode)` 的方式继续维护,但无法再利用低代码编辑器; + +> 渲染和出码的详细阐述可参考此文:[低代码技术在研发团队的应用模式探讨](https://mp.weixin.qq.com/s/Ynk_wjJbmNw7fEG6UtGZbQ) ## 渲染模块 -[在 Demo 中](https://lowcode-engine.cn/demo),右上角有渲染模块的示例使用方式: -![Mar-13-2022 16-52-49.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1647161579197-20c72ea4-6d9a-4692-9b23-005182f6387e.gif#clientId=u244806d0-100a-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u9b403d3d&margin=%5Bobject%20Object%5D&name=Mar-13-2022%2016-52-49.gif&originHeight=514&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=755539&status=done&style=stroke&taskId=u14f0f4c2-4d6c-4296-b2df-ccda870faff&title=) +[在 Demo 中](https://lowcode-engine.cn/demo/demo-general/index.html),右上角有渲染模块的示例使用方式: +![Mar-13-2022 16-52-49.gif](https://img.alicdn.com/imgextra/i2/O1CN01PRsEl61o7Zct5fJML_!!6000000005178-1-tps-1534-514.gif) 基于官方提供的渲染模块 [@alifd/lowcode-react-renderer](https://github.com/alibaba/lowcode-engine/tree/main/packages/react-renderer),你可以在 React 上下文渲染低代码编辑器产出的页面。 @@ -28,6 +30,7 @@ sidebar_position: 1 - components:需要根据编辑器产出的资产包 assets 中,根据页面 projectSchema 中声明依赖的 componentsMap,来加载所有依赖的资产包,最后获取资产包的实例并生成物料 - 资产包的键值对 components。 这个过程可以参考 demo 项目中的 `src/preview.tsx`: + ```typescript async function getSchemaAndComponents() { const packages = JSON.parse(window.localStorage.getItem('packages') || ''); @@ -76,25 +79,28 @@ const SamplePreview = () => { schema={schema} components={components} /> - ) + ); } ``` -> 注:您可以注意到,此处是依赖了 React 进行渲染的,对于 Vue 形态的渲染或编辑器支持,详见[对应公告](https://github.com/alibaba/lowcode-engine/issues/236)。 -> 本节示例可在 Demo 代码里找到:[https://github.com/alibaba/lowcode-demo/blob/main/src/preview.tsx](https://github.com/alibaba/lowcode-demo/blob/main/src/preview.tsx#L54-L58) +> 注 1:您可以注意到,此处是依赖了 React 进行渲染的,对于 Vue 形态的渲染或编辑器支持,详见[对应公告](https://github.com/alibaba/lowcode-engine/issues/236)。 +> +> 注 2:本节示例可在 Demo 代码里找到更完整的版本:[https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/preview.tsx](https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/preview.tsx) ## 出码模块 -[在 Demo 中](https://lowcode-engine.cn/demo),右上角有出码模块的示例使用方式: -![Mar-13-2022 16-55-56.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1647161777243-b16045c4-3cac-4920-8e68-ce064a90fe26.gif#clientId=u244806d0-100a-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=ud7bfd5a2&margin=%5Bobject%20Object%5D&name=Mar-13-2022%2016-55-56.gif&originHeight=514&originWidth=1536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1727314&status=done&style=stroke&taskId=u4e079100-d6a0-4ad2-ac0c-938ab8e7759&title=) +[在 Demo 中](https://lowcode-engine.cn/demo/demo-general/index.html),右上角有出码模块的示例使用方式: + +![Mar-13-2022 16-55-56.gif](https://img.alicdn.com/imgextra/i3/O1CN017CVeka27p3vwrGI1D_!!6000000007845-1-tps-1536-514.gif) > 本节示例可在出码插件里找到:[https://github.com/alibaba/lowcode-code-generator-demo](https://github.com/alibaba/lowcode-code-generator-demo) -## 低代码的生产和消费 +## 低代码的生产和消费流程总览 -经过“接入编辑器” - “接入运行时” 这两节的介绍,我们已经可以了解到低代码所构建的生产和消费流程了,梳理如下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644405393410-1c54fa37-74de-4c48-a4a9-1cbce359feeb.png#clientId=ua752ee55-c225-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u4ceefadb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1786&originWidth=3206&originalType=binary&ratio=1&rotation=0&showTitle=false&size=312489&status=done&style=none&taskId=uae8eacd1-4c05-4689-bb6a-24ceb76327d&title=&width=710) +经过“接入编辑器” - “接入运行时”这两节的介绍,我们已经可以了解到低代码所构建的生产和消费流程了,梳理如下图: + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01yiFiUc1rT32o9HpnW_!!6000000005631-2-tps-3206-1786.png) 如上述流程所示,您一般需要一个后端项目来保存页面数据信息,如果资产包信息是动态的,也需要保存资产包信息。 diff --git a/docs/docs/guide/design/datasourceEngine.md b/docs/docs/guide/design/datasourceEngine.md index 1ea076866..33c7adb08 100644 --- a/docs/docs/guide/design/datasourceEngine.md +++ b/docs/docs/guide/design/datasourceEngine.md @@ -6,19 +6,19 @@ sidebar_position: 7 考虑之后的扩展性和兼容性,核心分为了 2 类包,一个是 **datasource-engine** ,另一个是 **datasource-engine-x-handler** ,x 的意思其实是对应数据源的 type,比如说 **datasource-engine-mtop-handler**,也就是说我们会将真正的请求工具放在 handler 里面去处理,engine 在使用的时候由使用方自身来决定需要注册哪些 handler,这样的目的有 2 个,一个是如果将所有的 handler 都放到一个包,对于端上来说这个包过大,有一些浪费资源和损耗性能的问题,另一个是如果有新的类型的数据源出现,只需要按照既定的格式去新增一个对应的 handler 处理器即可,达到了高扩展性的目的; -![](https://intranetproxy.alipay.com/skylark/lark/0/2020/png/275191/1599545889374-73acbe09-3bb6-4df9-b6f9-80a86764afa2.png?x-oss-process=image%2Fresize%2Cw_720#crop=0&crop=0&crop=1&crop=1&id=zq0Rr&originHeight=370&originWidth=720&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) +![](https://img.alicdn.com/imgextra/i3/O1CN011ep9No2ACzrgzgtk0_!!6000000008168-2-tps-720-370.png) ### DataSourceEngine -- engine: engine 主要分 2 类,一类是面向 render 引擎的,可以从 engine/interpret 引入,一类是面向出码或者说直接单纯使用数据源引擎的场景,可以从 engine/runtime 引入,代码如下 +- engine:engine 主要分 2 类,一类是面向 render 引擎的,可以从 engine/interpret 引入,一类是面向出码或者说直接单纯使用数据源引擎的场景,可以从 engine/runtime 引入,代码如下 -```javascript +```typescript import { createInterpret, createRuntime } from '@alilc/lowcode-datasource-engine'; ``` create 方法定义如下 -```javascript +```typescript interface IDataSourceEngineFactory { create(dataSource: DataSource, context: Omit, extraConfig?: { requestHandlersMap: RequestHandlersMap; @@ -29,18 +29,17 @@ interface IDataSourceEngineFactory { create 接收三个参数,第一个是 DataSource,对于运行时渲染和出码来说,DataSource 的定义分别如下: -```javascript +```typescript /** * 数据源对象--运行时渲染 - * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5 */ export interface DataSource { list: DataSourceConfig[]; dataHandler?: JSFunction; } + /** * 数据源对象 - * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5 */ export interface DataSourceConfig { id: string; @@ -63,7 +62,7 @@ export interface DataSourceConfig { 但是对于出码来说,create 和 DataSource 定义如下: -```javascript +```typescript export interface IRuntimeDataSourceEngineFactory { create(dataSource: RuntimeDataSource, context: Omit, extraConfig?: { requestHandlersMap: RequestHandlersMap; @@ -92,9 +91,9 @@ export interface RuntimeDataSourceConfig { options?: RuntimeOptions; [otherKey: string]: unknown; } + /** * 数据源对象 - * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5 */ export interface RuntimeDataSource { list: RuntimeDataSourceConfig[]; @@ -106,18 +105,18 @@ export interface RuntimeDataSource { - context:数据源引擎内部有一些使用了 this 的表达式,这些表达式需要求值的时候依赖上下文,因此需要将当前的上下文丢给数据源引擎,另外在 handler 里面去赋值的时候,也会用到诸如 setState 这种上下文里面的 api,当然,这个是可选的,我们后面再说。 -```javascript +```typescript /** * 运行时上下文--暂时是参考 react,当然可以自己构建,完全没问题 */ export interface IRuntimeContext> { /** 当前容器的状态 */ readonly state: TState; - /** 设置状态(浅合并) */ + /** 设置状态 (浅合并) */ setState(state: Partial): void; /** 自定义的方法 */ [customMethod: string]: any; - /** 数据源, key 是数据源的 ID */ + /** 数据源,key 是数据源的 ID */ dataSourceMap: Record; /** 重新加载所有的数据源 */ reloadDataSource(): Promise; @@ -134,7 +133,7 @@ export interface IRuntimeContext - extraConfig:这个字段是为了留着扩展用的,除了一个必填的字段 **requestHandlersMap** -```javascript +```typescript export declare type RequestHandler = (ds: RuntimeDataSourceConfig, context: IRuntimeContext) => Promise>; export declare type RequestHandlersMap = Record; ``` @@ -143,9 +142,9 @@ RequestHandlersMap 是一个把数据源以及对应的数据源 handler 关联 create 调用结束后,可以获取到一个 DataSourceEngine 实例 -```javascript +```typescript export interface IDataSourceEngine { - /** 数据源, key 是数据源的 ID */ + /** 数据源,key 是数据源的 ID */ dataSourceMap: Record; /** 重新加载所有的数据源 */ reloadDataSource(): Promise; diff --git a/docs/docs/guide/design/editor.md b/docs/docs/guide/design/editor.md index d861ae7d6..b04cb4eb6 100644 --- a/docs/docs/guide/design/editor.md +++ b/docs/docs/guide/design/editor.md @@ -4,18 +4,22 @@ sidebar_position: 3 --- 本篇重点介绍如何从零开始设计编排模块,设计思路是什么?思考编排的本质是什么?围绕着本质,如何设计并实现对应的功能模块。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397577227-99a77c7d-6a6e-4d92-b222-eaac0ee7988e.png#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=540&id=u4613aa03&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1080&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=911801&status=done&style=none&taskId=u449864e5-516f-41eb-b86a-7c026b797a8&title=&width=960) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01fGzyI41bqpl6AavNp_!!6000000003517-2-tps-1920-1080.png) + +## 编排是什么 + +所谓编排,即将设计器中的所有物料,进行布局设置、组件设置、交互设置(JS 编写/逻辑编排)后,形成符合业务诉求的 schema 描述。 +## 编排的本质 -# 编排是什么 -所谓编排,即将设计器中的所有物料,进行布局设置、组件设置、交互设置(JS编写/逻辑编排)后,形成符合业务诉求的 schema 描述。 -# 编排的本质 首先,思考编排的本质是什么? + 编排的本质是生产符合《阿里巴巴中后台前端搭建协议规范》的数据**,**在这个场景里,协议是通过 JSON 来承载的。如: + ```json { "componentName": "Page", "props": { - "layout": "wide", + "layout": "wide" }, "children": [ { @@ -29,35 +33,52 @@ sidebar_position: 3 ``` 可是在真实场景,节点数可能有成百上千,每个节点都具有新增、删除、修改、移动、插入子节点等操作,同时还有若干约束,JSON 结构操作起来不是很便利,于是我们仿 DOM 设计了 **节点模型 & 属性模型,**用更具可编程性的方式来编排,这是**编排系统的基石**。 + 其次,每次编排动作后(CRUD),都需要实时的渲染出视图。广义的视图应该包括各种平台上的展现,浏览器、Rax、小程序、Flutter 等等,所以使用何种渲染器去渲染 JSON 结构应该可以由用户去扩展,我们定义一种机制去衔接设计态和渲染态。 + 至此,我们已经完成了**编排模块最基础的功能**,接下来,就是完善细节,逐步丰满功能。比如: -1)编排面板的整体功能区划分设计; -2)节点属性设计;节点删除、移动等操作设计;容器节点设计; -3)节点拖拽功能、拖拽定位设计和实现; -4)节点在画布上的辅助功能,比如 hover、选中、选中时的操作项、resize、拖拽占位符等; -5)设计态和渲染态的坐标系转换,滚动监听等; -6)快捷键机制; -7)历史功能,撤销和重做; -8)结构化的插件扩展机制; -9)原地编辑功能; +1. 编排面板的整体功能区划分设计; +2. 节点属性设计;节点删除、移动等操作设计;容器节点设计; +3. 节点拖拽功能、拖拽定位设计和实现; +4. 节点在画布上的辅助功能,比如 hover、选中、选中时的操作项、resize、拖拽占位符等; +5. 设计态和渲染态的坐标系转换,滚动监听等; +6. 快捷键机制; +7. 历史功能,撤销和重做; +8. 结构化的插件扩展机制; +9. 原地编辑功能; + 有非常多模块,但只要记住一点,这些功能的目的都是辅助用户在画布上有更好的编排体验、扩展能力而逐个增加设计的。 -# 编排功能模块 -## 模型设计 + +## 编排功能模块 +### 模型设计 + 编排实际上操作 schema,但是实际代码运行的过程中,我们将 schema 分成了很多层,每一层有各自的职责,他们所负责的功能是明确清晰的。这就是低代码引擎中的模型设计。 + 我们通过将 schema 和常用的操作等结合起来,最终将低代码引擎的模型分为节点模型、属性模型、文档模型和项目模型。 -### 项目模型(`Project`) + +#### 项目模型(`Project`) + 项目模型提供项目管理能力。通常一个引擎启动会默认创建一个 `Project` 实例,有且只有一个。项目模型实例下可以持有多个文档模型的实例,而当前处于设计器设计状态的文档模型,我们将其添加 active 标识,也将其称为 `currentDocument`,可以通过 `project.currentDocument` 获得。 + 一个 `Project` 包含若干个 `DocumentModel` 实例,即项目模型和文档模型的关系是 1 对 n,如下图所示: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397244733-2492a7bf-20bf-4610-a335-99cc047037b7.png#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=824&id=uadf98e25&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1648&originWidth=1226&originalType=url&ratio=1&rotation=0&showTitle=false&size=1260603&status=done&style=none&taskId=u50b01e40-96f2-4629-a1b9-1b5a22967fc&title=&width=613) -### 文档模型(`DocumentModel`) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01G28BKC1RvHRvhhiDf_!!6000000002173-2-tps-1226-1648.png) + +#### 文档模型(`DocumentModel`) + 文档模型提供文档管理的能力,每一个页面即一个文档流,对应一个文档模型。文档模型包含了一组 Node 组成的一颗树,类似于 DOM。我们可以通过文档模型来操作 `Node` 树,来达到管理文档模型的能力。每一个文档模型对应多个 `Node`,但是根 `Node` 只有一个,即 `rootNode` 和 `nodes`。 + 文档模型可以通过 `Node` 树,通过 `doc.schema` 来导出文档的 `schema`,并使用其进行渲染。 + 他们的关系如下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397244327-d931aff8-40d4-47df-8b1c-b81c06c40c48.png#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=745&id=L5LAf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1490&originWidth=960&originalType=url&ratio=1&rotation=0&showTitle=false&size=1110316&status=done&style=none&taskId=u7d873681-f61a-40ea-baaa-8f7b76c769c&title=&width=480) -### 节点模型(`Node`) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01NYVhN61nab6hsw5ZK_!!6000000005106-2-tps-960-1490.png) + +#### 节点模型(`Node`) + 我们先看一下一个 `Node` 在 `schema` 中对应的示例: -```json + +```javascript { componentName: 'Text', id: 'node_k1ow3cbf', @@ -76,7 +97,9 @@ sidebar_position: 3 condition: true, } ``` + 上面的示例是一个 `Text` 的 `Node` 节点,而我们的 `Node` 节点模型就是负责这一层级的 `Schema` 管理。它的功能聚焦于单层级的 schema 相关操作。我们可以看一下节点模型的一些方法,了解其功能。 + ```typescript declare class Node { // Props @@ -111,15 +134,22 @@ declare class Node { replaceWith(schema: Schema, migrate?: boolean): any; } ``` -这里没有展示全部的方法,但是我们可以发现,`Node` 节点模型核心功能点有三个 -1)`Props` 管理:通过 `Props` 实例管理所有的 `Prop`,包括新增、设置、删除等 `Prop` 相关操作。 -2)`Node` 管理:管理 `Node` 树的关系,修改当前 `Node` 节点或者 `Node` 子节点等。 -3)`Schema` 管理:可以通过 `Node` 获取当前层级的 `Schema` 描述协议内容,并且也可以修改它。 + +这里没有展示全部的方法,但是我们可以发现,`Node` 节点模型核心功能点有三个: + +1. `Props` 管理:通过 `Props` 实例管理所有的 `Prop`,包括新增、设置、删除等 `Prop` 相关操作。 +2. `Node` 管理:管理 `Node` 树的关系,修改当前 `Node` 节点或者 `Node` 子节点等。 +3. `Schema` 管理:可以通过 `Node` 获取当前层级的 `Schema` 描述协议内容,并且也可以修改它。 + 通过 `Node` 这一层级,对 `Props`、`Node` 树和 `Schema` 的管理粒度控制到最低,这样扩展性也就更强。 -### 属性模型(Prop) + +#### 属性模型(Prop) + 一个 `Props` 对应多个 `Prop`,每一个 `Prop` 对应 schema 的 `props` 下的一个字段。 + `Props` 管理的是 `Node` 节点模型中的 `props` 字段下的内容。而 `Prop` 管理的是 `props` 下的每一个 `key` 的内容,例如下面的示例中,一个 `Props` 管理至少 6 个 `Prop`,而其中一个 `Prop` 管理的是 `showTitle` 的结果。 -```typescript + +```javascript { props: { showTitle: false, @@ -135,17 +165,27 @@ declare class Node { }, } ``` -### 组件描述模型(ComponentMeta) +#### 组件描述模型(ComponentMeta) + 编排已经等价于直接操作节点 & 属性了,而一个节点和一组对应的属性相当于一个真实的组件,而真实的组件一定是有约束的,比如组件名、组件类型、支持哪些属性以及属性类型、组件能否拖动、支持哪些扩展操作、组件是否是容器型组件、A 组件中能否放入 B 组件等等。 + 于是,我们设计了一份协议专门负责组件描述,即《中后台搭建组件描述协议》,而编排模块中也有负责解析和使用符合描述协议规范的模块。 + 每一个组件对应一个 `ComponentMeta` 的实例,其属性和方法就是描述协议中的所有字段,所有 `ComponentMeta` 都由设计器器的 `designer` 模块进行创建和管理,其他模块通过 `designer` 来获取指定的 `ComponentMeta` 实例,尤其是每个 `Node` 实例上都会挂载对应的 `ComponentMeta` 实例。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397244032-8aa176d5-a74e-49c9-a309-251dba81b37c.png#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u044bdacd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=756&originWidth=998&originalType=url&ratio=1&rotation=0&showTitle=false&size=294191&status=done&style=none&taskId=uee9dfeef-f646-41db-afd4-a0b1acf8019&title=) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01NSh0LI1b150RUzOUc_!!6000000003404-2-tps-998-756.png) + 组件描述模型是后续编排辅助的基础,包括设置面板、拖拽定位机制等。 -### 项目、文档、节点和属性模型关系 +#### 项目、文档、节点和属性模型关系 + 整体来看,一个 Project 包含若干个 DocumentModel 实例,每个 DocumentModel 包含一组 Node 构成一颗树(类似 DOM 树),每个 Node 通过 Props 实例管理所有 Prop。整体的关系图如下。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1645066478805-57802de7-382e-4105-99cb-161b8c07f117.png#clientId=uf22d1b91-761d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=678&id=uc2db9afa&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1356&originWidth=1694&originalType=binary&ratio=1&rotation=0&showTitle=false&size=285816&status=done&style=none&taskId=u6526eafb-f082-46dd-8584-9dd9b1bb395&title=&width=847) + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01mufxpY1qCGvDTSdw9_!!6000000005459-2-tps-1694-1356.png) + 节点 & 属性模型是引擎基石,几乎贯穿所有模块,相信从上面的类图已经能看出几个基础类的职责以及依赖关系。 + 节点 & 属性模型等价于 JSON 数据结构,而编排的本质是产出 JSON 数据结构,现在可以重新表述为编排的本质是操作节点 & 属性模型了。 + ```typescript // 一段编排的示例代码 rootNode.insertAfter({ componentName: 'Button', props: { size: 'medium' } }); @@ -156,33 +196,51 @@ rootNode.export(); // => 产出 schema ``` -## 画布渲染 -画布渲染使用了设计态与渲染态的双层架构。![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397244328-61bb9ce7-a27c-4917-baee-c0a93bd0fd36.png#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u3c9164cd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=710&originWidth=1416&originalType=url&ratio=1&rotation=0&showTitle=false&size=287707&status=done&style=none&taskId=u6c993606-238b-478f-9317-397eb0708eb&title=) +### 画布渲染 + +画布渲染使用了设计态与渲染态的双层架构。 + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01cZ6Q32260qtiDofwi_!!6000000007600-2-tps-1416-710.png) + 如上图,设计器和渲染器其实处在不同的 Frame 下,渲染器以单独的 `iframe` 嵌入。这样做的好处,一是为了给渲染器一个更纯净的运行环境,更贴近生产环境,二是扩展性考虑,让用户基于接口约束自定义自己的渲染器。 -### xxx-renderer +#### xxx-renderer + xxx-renderer 是一个纯 renderer,即一个渲染器,通过给定输入 schema、依赖组件和配置参数之后完成渲染。 -### xxx-simulator-renderer -xxx-simulator-renderer 通过和 host进行通信来和设计器打交道,提供了 `DocumentModel` 获取 schema 和组件。将其传入 xxx-renderer 来完成渲染。 +#### xxx-simulator-renderer + +xxx-simulator-renderer 通过和 host 进行通信来和设计器打交道,提供了 `DocumentModel` 获取 schema 和组件。将其传入 xxx-renderer 来完成渲染。 + 另外其提供了一些必要的接口,来帮助设计器完成交互,比如点击渲染画布任意一个位置,需要能计算出点击的组件实例,继而找到设计器对应的 Node 实例,以及组件实例的位置/尺寸信息,让设计器完成辅助 UI 的绘制,如节点选中。 -### react-simulator-renderer +#### react-simulator-renderer + 以官方提供的 react-simulator-renderer 为例,我们看一下点击一个 DOM 节点后编排模块是如何处理的。 + 首先在初始化的时候,renderer 渲染的时候会给每一个元素添加 ref,通过 ref 机制在组件创建时将其存储起来。在存储的时候我们给实例添加 `Symbol('_LCNodeId')` 的属性。 + 当点击之后,会去根据 `__reactInternalInstance$` 查找相应的 fiberNode,通过递归查找到对应的 React 组件实例。找到一个挂载着 `Symbol('_LCNodeId')` 的实例,也就是上面我们初始化添加的属性。 + 通过 `Symbol('_LCNodeId')` 属性,我们可以获取 Node 的 id,这样我们就可以找到 Node 实例。 + 通过 `getBoundingClientRect` 我们可以获取到 Node 渲染出来的 DOM 的相关信息,包括 `x`、`y`、`width`、`height` 等。 + 通过 DOM 信息,我们将 focus 节点所需的标志渲染到对应的地方。hover、拖拽占位符、resize handler 等辅助 UI 都是类似逻辑。 -### 通信机制 +#### 通信机制 + 既然设计器和渲染器处于两个 Frame,它们之间的事件通信、方法调用是通过各自的代理对象进行的,不允许其他方式,避免代码耦合。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397245794-927fa812-ea1c-4bc1-967b-4c1dff924fd1.png#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u22088dc8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=648&originWidth=1290&originalType=url&ratio=1&rotation=0&showTitle=false&size=223251&status=done&style=none&taskId=uf720b921-07c2-4cda-a101-74e863ce10d&title=) -**host** -host 可以访问设计器的所有模块,由于 renderer 层不负责与设计器相关的交互。所以增加了一层 host,作为通信的中间层。host 可以访问到设计器中所有模块,并提供相关方法供 simulator-renderer 层调用。例如schema 的获取、组件获取等。 + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01hxtg7X1M3AZsAdt83_!!6000000001378-2-tps-1290-648.png) + +##### host +host 可以访问设计器的所有模块,由于 renderer 层不负责与设计器相关的交互。所以增加了一层 host,作为通信的中间层。host 可以访问到设计器中所有模块,并提供相关方法供 simulator-renderer 层调用。例如 schema 的获取、组件获取等。 + simulator-renderer 通过调用 host 的方法,将 schema、components 等参数传给 renderer,让 renderer 进行渲染。 -**xxx-simulator-renderer** +##### xxx-simulator-renderer + 为了完成双向交互,simulator-renderer 也需要提供一些方法来供 host 层调用,之后当设计器和用户有交互,例如上述提到的节点选中。这里需要提供的方法有: - getClientRects @@ -196,12 +254,16 @@ simulator-renderer 通过调用 host 的方法,将 schema、components 等参 这样,host 和 simulator-renderer 之间便通过相关方法实现了双向通信,能在隔离设计器的基础上完成设计器到画布和画布到设计器的通信流程。 -## 编排辅助的核心 -### 设置面板与设置器 +### 编排辅助的核心 +#### 设置面板与设置器 当在渲染画布上点击一个 DOM 节点,我们可以通过 xxx-simulator-renderer 获取 `Node` 节点,我们在 `Node` 上挂载了 `ComponentMeta` 实例。通过 `ComponentMeta` 我们获取到当前组件的描述模型。通过描述模型,我们即可获得组件、即当前 Node 支持的所有属性配置。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397246381-ed265cc3-b6c1-4a38-985a-df1898862fe8.png#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u1422ee5e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=985&originWidth=1500&originalType=url&ratio=1&rotation=0&showTitle=false&size=332497&status=done&style=none&taskId=u2bbbb9ae-7834-48ba-b87f-fa5ccf8fa39&title=) -#### 设置面板 + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01c7nkoo1OXyRhVAFlK_!!6000000001716-2-tps-1500-985.png) + +##### 设置面板 + 设置面板对于配置项的呈现结构是通过 `ComponentMeta.configure` 来确定的。 + ```json { "component": { @@ -231,14 +293,22 @@ simulator-renderer 通过调用 host 的方法,将 schema、components 等参 } } ``` + 上述的 `component.isContainer` 描述了这个组件是否是一个容器组件。而 props 下的属性就是我们在设置面板中展示的属性,包含了这个属性的名称、使用的设置器、配置之后影响的是哪个属性等。 + 而这只是描述,编排模块的 `SettingTopEntry` 便是管理设置面板的实现模块。 + `SettingTopEntry` 包含了 n 个 `SettingField`,每一个 `SettingField` 就对应下面要将的设置器。即 `SettingTopEntry` 负责管理多个 `SettingField`。 -#### 设置器 + +##### 设置器 选中节点可供配置的属性都有相应的设置器配置,比如文本、数字、颜色、JSON、Choice、I18N、表达式 等等,或者混合多种。 + 设置器本质上是一个 React 组件,但是设置面板在渲染时会传入当前配置项对应的 `SettingField` 实例,`SettingField` 本质上就是包裹了 `Prop` 实例,设置器内部的行为以及 UI 变化都由设置器自己把控,但当属性值发生变化时需要通过 `SettingField` 下的 `Prop` 来修改值,因为修改 `Prop` 实例就相当于修改了 schema。一方面这样的设置器设置之后,保存的 schema 才是正确的,另外一方面,只有 schema 变化了,才能触发渲染画布重新渲染。 -### 拖拽引擎 & 拖拽定位机制 -![](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644397245744-af8b951c-ee22-4fcb-9175-6f1b0eb2ba37.gif#clientId=u45d0137b-8a6f-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uf8b286a2&margin=%5Bobject%20Object%5D&originHeight=917&originWidth=1425&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u9b4475cb-bb5c-4c86-9b03-b824bc46b12&title=) + +#### 拖拽引擎 & 拖拽定位机制 + +![](https://img.alicdn.com/imgextra/i4/O1CN01G8zyBw1OkL8m0FG4J_!!6000000001743-1-tps-1425-917.gif) + 拖拽引擎(`Dragon`)核心完成的工作是将被拖拽对象拖拽到目标位置,涉及到几个概念: - 被拖拽对象 - `DragObject` @@ -246,38 +316,53 @@ simulator-renderer 通过调用 host 的方法,将 schema、components 等参 - 拖拽感应区 - `ISensor` - 定位事件 - `LocateEvent` -#### Sensor +##### Sensor + 在引擎初始化的时候,我们监听 `document` 和 iframe `contentDocument` 的 `mouse`、`keyboard`、`drag` 事件来感知拖拽的发生。而这些监听的区域我们又称为拖拽感应区,也就是 `Sensor`。`Sensor` 会有多个,因为感应器有多个,默认设置器和设置面板是没有 `Sensor`,但是他们是可以注册 `Sensor` 来增加感应区域,例如大纲树就注册了自己的 `Sensor`。 `Sensor` 有两个关键职责: -1)用于事件对象转换,比如坐标系换算 -2)根据拖拽过程中提供的位置信息,结合每一层 `Node` 也就是组件包含的描述信息,知道其是否能作为容器等限制条件,来进行进一步的定位,最后计算出精准信息来进行视图渲染。 +1. 用于事件对象转换,比如坐标系换算。 +2. 根据拖拽过程中提供的位置信息,结合每一层 `Node` 也就是组件包含的描述信息,知道其是否能作为容器等限制条件,来进行进一步的定位,最后计算出精准信息来进行视图渲染。 **拖拽流程** -在引擎初始化的时候,初始化多个 `Sensor`。 -当拖拽开始的时候,开启 `mousemove`、`mouseleave`、`mouseover` 等事件的监听。 -拖拽过程中根据 `mousemove` 的 `MouseEvent` 对象封装出 `LocateEvent` 对象,继而交给相应 `sensor` 做进一步定位处理。 -拖拽结束时,根据拖拽的结果进行 schema 变更和视图渲染。 -最后关闭拖拽开始时的事件监听。 +1. 在引擎初始化的时候,初始化多个 `Sensor`。 +2. 当拖拽开始的时候,开启 `mousemove`、`mouseleave`、`mouseover` 等事件的监听。 +3. 拖拽过程中根据 `mousemove` 的 `MouseEvent` 对象封装出 `LocateEvent` 对象,继而交给相应 `sensor` 做进一步定位处理。 +4. 拖拽结束时,根据拖拽的结果进行 schema 变更和视图渲染。 +5. 最后关闭拖拽开始时的事件监听。 -#### 拖拽方式 +##### 拖拽方式 根据拖拽的对象不同,我们将拖拽分为几种方式: -1)**画布内拖拽:**此时 sensor 是 simulatorHost,拖拽完成之后,会根据拖拽的位置来完成节点的精确插入。 -2)**从组件面板拖拽到画布**:此时的 sensor 还是 simulatorHost,因为拖拽结束的目标还是画布。 -3)**大纲树面板拖拽到画布中**:此时有两个 sensor,一个是大纲树,当我们拖拽到画布区域时,画布区域内的 simulatorHost 开始接管。 -4)画布拖拽到画布中:从画布中开始拖拽时,最新生效的是 simulatorHost,当离开画布到大纲树时,大纲树 sensor 开始接管生效。当拖拽到大纲树的某一个节点下时,大纲树会将大纲树中的信息转化为 schema,然后渲染到画布中。 -## 其他 +1. **画布内拖拽:**此时 sensor 是 simulatorHost,拖拽完成之后,会根据拖拽的位置来完成节点的精确插入。 +2. **从组件面板拖拽到画布**:此时的 sensor 还是 simulatorHost,因为拖拽结束的目标还是画布。 +3. **大纲树面板拖拽到画布中**:此时有两个 sensor,一个是大纲树,当我们拖拽到画布区域时,画布区域内的 simulatorHost 开始接管。 +4. **画布拖拽到画布中**:从画布中开始拖拽时,最新生效的是 simulatorHost,当离开画布到大纲树时,大纲树 sensor 开始接管生效。当拖拽到大纲树的某一个节点下时,大纲树会将大纲树中的信息转化为 schema,然后渲染到画布中。 +### 其他 + 引擎的编排能力远远不止上述所描述的功能,这里只描述了其核心和关键的功能。在整个引擎的迭代和设计过程中还有很多细节来使我们的引擎更好用、更容易扩展。 -**schema 处理的管道机制** -通过PropsReducer 的管道机制,用户可以定制自己需要的逻辑,来修改 Schema。 -**组件 metadata 处理的管道机制** + +#### schema 处理的管道机制 + +通过 PropsReducer 的管道机制,用户可以定制自己需要的逻辑,来修改 Schema。 + +#### 组件 metadata 处理的管道机制 + 组件的描述信息都收拢在各自的 ComponentMeta 实例内,涉及到的消费方几乎遍及整个编排过程,包括但不限于 组件拖拽、拖拽辅助 UI、设置区、原地编辑、大纲树 等等。 + 在用户需要自定义的场景,开放 ComponentMeta 的修改能力至关重要,因此我们设计了 metadata 初始化/修改的管道机制。 -**hotkey & builtin-hotkey** + +#### hotkey & builtin-hotkey + 快捷键的实现,以及引擎内核默认绑定的快捷键行为。 -**drag resize 引擎** + +#### drag resize 引擎 + 对于布局等类型的组件,支持拖拽改变大小。resize 拖拽引擎根据组件 ComponentMeta 声明来开启,拖拽后,触发组件的钩子函数(`onResizeStart` / `onResize` / `onResizeEnd`),完成 resize 过程。 -**OffsetObserver** + +#### OffsetObserver + 设计态的辅助 UI 需要根据渲染态的视图变化而变化,比如渲染容器滚动了,此时通过 OffsetObserver 做一个动态的监听。 -**插件机制** + +#### 插件机制 + 我们希望保持引擎内核足够小,但拥有足够强的扩展能力,所有扩展功能都通过插件机制来承载。 diff --git a/docs/docs/guide/design/generator.md b/docs/docs/guide/design/generator.md index 19d34560b..2310cb7a5 100644 --- a/docs/docs/guide/design/generator.md +++ b/docs/docs/guide/design/generator.md @@ -2,18 +2,20 @@ title: 出码模块设计 sidebar_position: 5 --- -本篇主要讲解了出码模块实现的基本思路与一些概念。如需接入出码和定制出码方案,可以参考《[使用出码功能](https://www.yuque.com/lce/doc/cplfv0)》一节。 -# npm 包与仓库信息 + +本篇主要讲解了出码模块实现的基本思路与一些概念。如需接入出码和定制出码方案,可以参考《[使用出码功能](/site/docs/guide/expand/runtime/codeGeneration)》一节。 + +## npm 包与仓库信息 + | **NPM 包** | **代码仓库** | **说明** | | --- | --- | --- | -| [@alilc/lowcode-code-generator](https://www.npmjs.com/package/@alilc/lowcode-code-generator) | [alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) -(子目录:modules/code-generator) | 出码模块核心库,支持在 node 环境下运行,也提供了浏览器下运行的 standalone 模式 | +| [@alilc/lowcode-code-generator](https://www.npmjs.com/package/@alilc/lowcode-code-generator) | [alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine)(子目录:modules/code-generator)| 出码模块核心库,支持在 node 环境下运行,也提供了浏览器下运行的 standalone 模式 | | [@alilc/lowcode-plugin-code-generator](https://www.npmjs.com/package/@alilc/lowcode-plugin-code-generator) | [alibaba/lowcode-code-generator-demo](https://github.com/alibaba/lowcode-code-generator-demo) | 出码示例 -- 浏览器端出码插件 | -# 出码模块原理 +## 出码模块原理 出码模块的输入和输出很简单: -![](https://cdn.nlark.com/yuque/0/2022/jpeg/263300/1644825891969-1777dbe4-5ffc-4c94-a022-3aba0c116021.jpeg) +![](https://img.alicdn.com/imgextra/i3/O1CN01OkDmKq1xMX6Xxv6co_!!6000000006429-0-tps-1262-346.jpg) 这里有几个概念: @@ -23,19 +25,23 @@ sidebar_position: 5 可以看出,这是一个与用户基本没有交互,通过既定的流程完成整个功能链路的模块。其核心暴露的是一个将搭建协议 schema 按既定的 solution 转换为代码的函数。对于使用者来说就是一个输入输出都确定的黑盒系统。 -## 出码流程概述 +### 出码流程概述 + 出码模块和编译器很类似,都是将代码的一种表现形式转换成另一种表现形式,如: -**编译器流程** -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644403720547-e5021c3c-0c63-47ea-b8f0-1af79bbae3ef.png#clientId=u70bc6751-fff0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=246&id=u3b3e3126&margin=%5Bobject%20Object%5D&name=image.png&originHeight=492&originWidth=3228&originalType=binary&ratio=1&rotation=0&showTitle=false&size=110319&status=done&style=none&taskId=u32f55257-a18c-4caa-9334-0b3ca5b0bc0&title=&width=1614) +#### 编译器流程 +![image.png](https://img.alicdn.com/imgextra/i3/O1CN019F21Lb1bsCwvNcWRq_!!6000000003520-2-tps-3228-492.png) -**出码模块流程** -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644402753768-02d402da-dd1a-4783-9021-606e276d4c68.png#clientId=u70bc6751-fff0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=182&id=GlAz4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=182&originWidth=1536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=23743&status=done&style=none&taskId=ubbea9289-cb03-4fcf-9ce7-22da1ce077b&title=&width=1536) +#### 出码模块流程 +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01SEcVta1uLD72W0URZ_!!6000000006020-2-tps-1536-182.png) + +### 出码流程详解 +#### 协议解析 -## 出码流程详解 -### 协议解析 协议解析主要是将输入的 schema 解析成更适合出码模块内部使用的数据结构的过程。这样在后面的代码生成过程中就可以直接用这些数据,不必重复解析了。 -![](https://intranetproxy.alipay.com/skylark/lark/0/2021/jpeg/154771/1636960093808-624b5e50-18d6-476d-a951-556912832cdb.jpeg) + +![](https://img.alicdn.com/imgextra/i3/O1CN016EeitG1giCNCNTLVF_!!6000000004175-0-tps-1282-515.jpg) + 主要步骤如下: - 解析三方组件依赖 @@ -46,21 +52,30 @@ sidebar_position: 5 - 分析 utils 和 NPM 包依赖关系 - 其他兼容处理 -### 前置优化 -前置优化是计划基于策略对 schema 做一些优化。 -主要逻辑分为分析、规则和优化三个部分,组合为一个支持通过配置进行一定程度定制化的策略包。每个策略包会先执行分析器,对输入进行特征提取,然后通过规则对特征进行判断,决定是否执行优化动作: -![](https://intranetproxy.alipay.com/skylark/lark/0/2021/jpeg/154771/1636960832211-0db6925b-c4b5-4be4-a883-fdd52a47e19a.jpeg) +#### 前置优化 -### 代码生成 +前置优化是计划基于策略对 schema 做一些优化。 + +主要逻辑分为分析、规则和优化三个部分,组合为一个支持通过配置进行一定程度定制化的策略包。每个策略包会先执行分析器,对输入进行特征提取,然后通过规则对特征进行判断,决定是否执行优化动作: + +![](https://img.alicdn.com/imgextra/i4/O1CN01P0Lw7v1lfyWtfQTuR_!!6000000004847-2-tps-994-278.png) + +#### 代码生成 代码生成的流程如下: -![](https://intranetproxy.alipay.com/skylark/lark/0/2021/jpeg/154771/1636975834791-e3fe89f9-cd2d-446f-aa9f-fca0bb1d56c3.jpeg) +![](https://img.alicdn.com/imgextra/i1/O1CN01lhcWBg1RG3nsoSoY2_!!6000000002083-2-tps-1468-464.png) + 如果简单粗暴地拼字符串生成源代码将难以扩展和维护,因此出码模块在代码生成过程中将代码进行了一些抽象化。 + 日常开发中,我们常常是基于某一个特定的项目框架,将一些配置、UI 代码、逻辑代码放到他们应该在的地方,最终形成一套可以 run 起来的业务系统。那么其实对于出码这件事,我们也可以层层拆解,**项目 -> 插槽 -> 模块 -> 文件 -> 代码块**(代码片段)。这样就能将复杂的项目产出问题,拆分为一个个相对专注且单一的代码块产出问题,同时也支持组合复用。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644402753919-1f063db3-5ad9-406b-9b45-6eeef79ea38b.png#clientId=u70bc6751-fff0-4&crop=0&crop=0&crop=1&crop=1&height=305&id=LgGUo&margin=%5Bobject%20Object%5D&name=image.png&originHeight=454&originWidth=892&originalType=binary&ratio=1&rotation=0&showTitle=false&size=230321&status=done&style=none&taskId=u50d38d84-3a3e-4c77-af05-8bc5f794643&title=&width=600) + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01vOGmBT1JaegccXDt8_!!6000000001045-2-tps-892-454.png) + 注:中间表达结构即为对 Schema 解析后的结构化产物 -**插槽** +##### 插槽 + 首先来看下插槽,插槽描述了对应模块在项目中相对路径,并且可以对模块做固定的命名。每个插槽都有一系列插件来完成代码产出工作。生成的一个或多个文件,最终会依照插槽的描述放入项目中。 + ```typescript // 项目模版 export interface IProjectTemplate { @@ -78,20 +93,23 @@ interface IProjectPlugins { [slotName: string]: BuilderComponentPlugin[]; } ``` -**代码块** +##### 代码块 + 代码块是出码产物的最小单元,由出码模块插件产出,多个代码块最后会被组装为代码文件。每个代码块通过 name 描述自己,再通过 linkAfter 描述应该跟在哪些 name 的代码块后面。 + ```typescript interface ICodeChunk { - type: ChunkType; // 处理类型 ast | string | json - fileType: string; // 文件类型 js | css | ts ... - name: string; // 代码块名称,与 linkAfter 相关 - subModule?: string; // 模块内文件名,默认是 index - content: ChunkContent; // 代码块内容,数据格式与 type 相关 - linkAfter: string[]; // + type: ChunkType; // 处理类型 ast | string | json + fileType: string; // 文件类型 js | css | ts ... + name: string; // 代码块名称,与 linkAfter 相关 + subModule?: string; // 模块内文件名,默认是 index + content: ChunkContent; // 代码块内容,数据格式与 type 相关 + linkAfter: string[]; } ``` -### 后置优化 +#### 后置优化 + 后置优化分为文件级别和项目级别两种: - 文件级别:在生成完一个文件后进行处理 diff --git a/docs/docs/guide/design/materialParser.md b/docs/docs/guide/design/materialParser.md index 42aaadcf0..78936011f 100644 --- a/docs/docs/guide/design/materialParser.md +++ b/docs/docs/guide/design/materialParser.md @@ -3,7 +3,7 @@ title: 入料模块设计 sidebar_position: 2 --- ## 介绍 -入料模块负责物料接入,通过自动扫描、解析源码组件,产出一份符合《中后台低代码组件描述协议》的** **JSON Schema。这份 Schema 包含基础信息和属性描述信息部分,低代码引擎会基于它们在运行时自动生成一份configure 配置,用作设置面板展示。 +入料模块负责物料接入,通过自动扫描、解析源码组件,产出一份符合《中后台低代码组件描述协议》的** **JSON Schema。这份 Schema 包含基础信息和属性描述信息部分,低代码引擎会基于它们在运行时自动生成一份 configure 配置,用作设置面板展示。 ## npm 包与仓库信息 @@ -15,7 +15,7 @@ sidebar_position: 2 ### 整体流程 大体分为本地化、扫描、解析、转换、校验 5 部分,如下图所示。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644396777217-58246e52-b5b9-4509-8bac-db2820535c39.png#clientId=u41c9ba96-15b6-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u8b5a70fd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=206&originWidth=2116&originalType=url&ratio=1&rotation=0&showTitle=false&size=51634&status=done&style=none&taskId=u76c5b45a-6fa8-404e-8d8b-f1d6f38438e&title=) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01sXf5fL1E5RcRxAlM1_!!6000000000300-2-tps-2116-206.png) ### 静态解析 在静态分析时,分为 JS 和 TS 两种情况。 @@ -23,48 +23,58 @@ sidebar_position: 2 #### 静态解析 JS 在 JS 情况下,基于 react-docgen 进行扩展,自定义了 resolver 及 handler,前者用于寻找组件定义,后者用于解析 propTypes、defaultProps 等信息,整体流程图如下: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644396777192-c9d3c3b3-c7d2-4780-b7dc-632349b00edb.png#clientId=u41c9ba96-15b6-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u3edfb33c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=478&originWidth=2176&originalType=url&ratio=1&rotation=0&showTitle=false&size=93513&status=done&style=none&taskId=ua23bd89a-3d0c-43cf-936b-13080cdc5ef&title=) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01VrhkEb1R6tsntvGhV_!!6000000002063-2-tps-2176-478.png) -react-docgen 使用 babel 生成语法树,再使用 ast-types 进行遍历去寻找组件节点及其属性类型定义。原本的 react-docgen 只能解析单文件,且不能解析 IIFE、逗号表达式等语法结构(一般出现在转码后的代码中)。笔者对其进行改造,使之可以递归解析多文件去查找组件定义,且能够解开 IIFE,以及对逗号表达式进行转换,以方便后续的组件解析。另外,还增加了子组件解析的功能,即类似 `Button.Group = Group` 这种定义。 +react-docgen 使用 babel 生成语法树,再使用 ast-types 进行遍历去寻找组件节点及其属性类型定义。原本的 react-docgen 只能解析单文件,且不能解析 IIFE、逗号表达式等语法结构 (一般出现在转码后的代码中)。笔者对其进行改造,使之可以递归解析多文件去查找组件定义,且能够解开 IIFE,以及对逗号表达式进行转换,以方便后续的组件解析。另外,还增加了子组件解析的功能,即类似 `Button.Group = Group` 这种定义。 #### 静态解析 TS 在 TS 情况下,还要再细分为 TS 源码和 TS 编译后的代码。 -TS 源码中,React 组件具有类型签名;TS 编译后的代码中,dts 文件(如有)包含全部的 class / interface / type 类型信息。可以从这些类型信息中获取组件属性描述。整体流程图如下: +TS 源码中,React 组件具有类型签名;TS 编译后的代码中,dts 文件 (如有) 包含全部的 class / interface / type 类型信息。可以从这些类型信息中获取组件属性描述。整体流程图如下: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644396777193-14c74287-d0cb-4864-ba64-9259a88c8b99.png#clientId=u41c9ba96-15b6-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ud7fc6e1a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=240&originWidth=2280&originalType=url&ratio=1&rotation=0&showTitle=false&size=59331&status=done&style=none&taskId=u711959ae-241a-48c9-a446-59b9fcdc52e&title=) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN014lOIIy1FUvGW6wcYZ_!!6000000000491-2-tps-2280-240.png) -react-docgen 内置了 TypeScript 的 babel 插件,所以也具备解析 interface 的能力,可惜能力有限,babel 只能解析 TS 代码,但没法做类型检查,类型处理是由 react-docgen 实现的,它对于extends/implements/utility 的情况处理不好,并且没有类型推断,虽然可以对其功能进行完善,不过这种情况下,应该借助 TypeScript Compiler 的能力,而非自己造轮子。通过调研,发现市面上有 typescript-react-docgen 这个项目。它在底层依赖了 TypeScript,且产出的数据格式与 react-docgen 一致,所以我们选择基于它进行解析。 +react-docgen 内置了 TypeScript 的 babel 插件,所以也具备解析 interface 的能力,可惜能力有限,babel 只能解析 TS 代码,但没法做类型检查,类型处理是由 react-docgen 实现的,它对于 extends/implements/utility 的情况处理不好,并且没有类型推断,虽然可以对其功能进行完善,不过这种情况下,应该借助 TypeScript Compiler 的能力,而非自己造轮子。通过调研,发现市面上有 typescript-react-docgen 这个项目。它在底层依赖了 TypeScript,且产出的数据格式与 react-docgen 一致,所以我们选择基于它进行解析。 TypeScript Compiler 会递归解析某个文件中出现及引用的全部类型,当然,前提是已经定义或安装了相应的类型声明。typescript-react-docgen 会调用 TypeScript Compiler 的 API,获取每个文件输出的类型,判断其是否为 React 组件。满足下列条件之一的,会被判定为 React 组件: -1. 获取其函数签名,如果只有一个入参,或者第一个入参名称为 props ,会被判定为函数式组件; +1. 获取其函数签名,如果只有一个入参,或者第一个入参名称为 props,会被判定为函数式组件; 2. 获取其 `constructor` 方法,如果其返回值包含 props 属性,会被判定为有状态组件。 然后,遍历组件的 props 类型,获取每个属性的类型签名字符串,比如 `(a: string) => void`。typescript-react-docgen 可以克服 react-docgen 解析 TypeScirpt 类型的问题,但是每个类型都以字符串的形式来呈现,不利于后续的解析。所以,笔者对其进行了扩展,递归解析每一层的属性值。此外,在函数式组件的判定上,笔者做了完善,会看函数的返回值是否为 `ReactElement` ,若是,才为函数式组件。 下面讲对于一些特殊情况的处理。 + **循环定义** + TypeScript 类型可以循环定义,比如下面的 JSON 类型: + ```typescript interface Json { [x: string]: string | number | boolean | Json | JsonArray; } type JsonArray = Array; ``` + 因为低代码组件描述协议中没有引用功能,而且也不方便在界面上展示出来,所以这种循环定义无需完全解析,入料模块会在检测到循环定义的时候,把类型简化为 `object` 。对于特殊的类型,如 JSON,可以用相应的 Setter 来编辑。 **复杂类型** TypeScript Compiler 会将合成类型的所有属性展开,比如 `boolean | string`,会被展开为 `true | false | string`,这带来了不必要的精确,我们需要的只是 `boolean | string` 而已。当然,对于这个例子,我们很容易把它还原回 `boolean | string`,然而,对于诸如 `React.ButtonHTMLAttributes & {'data-name': string}` 这种类型,它会把 `ButtonHTMLAttributes` 中众多的属性和 `data-name` 混杂在一起,完全无法分辨,只能以展开的形式提供。这 100 多个属性,如果都放在设置面板,绝对是使用者的噩梦,所以,其结果会被简化为 `object` 。当然,即使没有 `{'data-name': string}`,`ButtonHTMLAttributes` 也是没有单独的 Setter 的,同样会被简化为 `object` 。 ### 动态解析 + 当一个组件,使用静态解析无法入料时,会使用动态解析。 + 整体流程图如下: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644396776984-d390ec0c-33c6-4468-b68c-555a263b097e.png#clientId=u41c9ba96-15b6-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ube12dcbd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=449&originWidth=2516&originalType=url&ratio=1&rotation=0&showTitle=false&size=84334&status=done&style=none&taskId=ube349a5b-94c0-4a77-9bf3-ffe453226e1&title=) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01dJ62Dm1u5de8GihG6_!!6000000005986-2-tps-2516-449.png) + 基本思想很简单,require 组件进来,然后读取其组件类上定义的 propTypes 和 defaultProps 属性。这里使用了 parse-prop-types 库,使用它的时候必须在组件之前引用,因为它会先对 prop-types 库进行修改,在每个 PropTypes 透出的函数上挂上类型,比如 string, number 等等,然后再去遍历。动态解析可以解析出全部的类型信息,因为 PropTypes 有可能引入依赖组件的一些类型定义,这在静态解析中很难做到,或者成本较高,而对于动态解析来说,都由运行时完成了。 ##### 技术细节 -值得注意的是,有些 js 文件里还会引入 css 文件,而且从笔者了解的情况来看,这种情况在集团内部不在少数。这种组件不配合 webpack 使用,肯定会报错,但是使用 webpack 会明显拖慢速度,所以笔者采用了sandbox 的方式,对 require 进来的类 css 文件进行 mock。这里,笔者使用了 vm2 这个库,它对 node 自带的 vm 进行了封装,可以劫持文件中的 require 方法。因为 parse-prop-types 的修改在沙箱中会失效,所以笔者也 mock 了组件中的 prop-types 库。 + +值得注意的是,有些 js 文件里还会引入 css 文件,而且从笔者了解的情况来看,这种情况在集团内部不在少数。这种组件不配合 webpack 使用,肯定会报错,但是使用 webpack 会明显拖慢速度,所以笔者采用了 sandbox 的方式,对 require 进来的类 css 文件进行 mock。这里,笔者使用了 vm2 这个库,它对 node 自带的 vm 进行了封装,可以劫持文件中的 require 方法。因为 parse-prop-types 的修改在沙箱中会失效,所以笔者也 mock 了组件中的 prop-types 库。 ### 整体大图 把上述的静态解析和动态解析流程结合起来,可以得到以下大图。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644396777248-9e26dd26-51ac-473e-ae66-c08f8bed3aeb.png#clientId=u41c9ba96-15b6-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ue6806530&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1072&originWidth=2658&originalType=url&ratio=1&rotation=0&showTitle=false&size=184784&status=done&style=none&taskId=u0d982b36-25b8-442f-8d98-43b9e1629bb&title=) + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01TA9lQp27QmwVT7WUC_!!6000000007792-2-tps-2658-1072.png) diff --git a/docs/docs/guide/design/renderer.md b/docs/docs/guide/design/renderer.md index 74674bcdb..bef13694a 100644 --- a/docs/docs/guide/design/renderer.md +++ b/docs/docs/guide/design/renderer.md @@ -2,12 +2,13 @@ title: 渲染模块设计 sidebar_position: 4 --- -# 低代码渲染介绍 +## 低代码渲染介绍 + + -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644398134750-7b352564-a400-460e-a189-e72ef551624f.png#clientId=udd4eb4ee-bdb1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=198&id=OSLhL&margin=%5Bobject%20Object%5D&name=image.png&originHeight=872&originWidth=1440&originalType=binary&ratio=1&rotation=0&showTitle=false&size=193396&status=done&style=none&taskId=ua5d2ae84-0117-4744-a49c-bd3dd1b8a5e&title=&width=327) 基于 Schema 和物料组件,如何渲染出我们的页面?这一节描述的就是这个。 -# npm 包与仓库信息 +## npm 包与仓库信息 - React 框架渲染 npm 包:@alilc/lowcode-react-renderer - Rax 框架渲染 npm 包:@alilc/lowcode-rax-renderer @@ -16,22 +17,25 @@ sidebar_position: 4 - packages/react-renderer - packages/react-simulator-renderer -# 渲染框架原理 -## 整体架构 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644398135242-d83a9d48-c244-4869-b61e-70e825006727.png#clientId=udd4eb4ee-bdb1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=531&id=udb49df4c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1062&originWidth=1686&originalType=binary&ratio=1&rotation=0&showTitle=false&size=821823&status=done&style=none&taskId=u90381546-a7a8-4099-b24f-844b8489f4d&title=&width=843) +## 渲染框架原理 +### 整体架构 -- 协议层:基于标准的《阿里巴巴中后台前端搭建协议规范》产出的 Schema 作为我们的规范协议。 +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01i4IiSR1cMtUFXaWQq_!!6000000003587-2-tps-1686-1062.png) + +- 协议层:基于《低代码引擎搭建协议规范》](/site/docs/specs/lowcode-spec) 产出的 Schema 作为我们的规范协议。 - 能力层:提供组件、区块、页面等渲染所需的核心能力,包括 Props 解析、样式注入、条件渲染等。 - 适配层:由于我们使用的运行时框架不是统一的,所以统一使用适配层将不同运行框架的差异部分,通过接口对外,让渲染层注册/适配对应所需的方法。能保障渲染层和能力层直接通过适配层连接起来,能起到独立可扩展的作用。 - 渲染层:提供核心的渲染方法,由于不同运行时框架提供的渲染方法是不同的,所以其通过适配层进行注入,只需要提供适配层所需的接口,即可实现渲染。 - 应用层:根据渲染层所提供的方法,可以应用到项目中,根据使用的方法和规模即可实现应用、页面、区块的渲染。 -## 核心解析 +### 核心解析 + 这里主要解析一下刚刚提到的架构中的适配层和渲染层。 -### 适配层 + +#### 适配层 适配层提供的是各个框架之间的差异项。比如 `React.createElement` 和 `Rax.createElement` 方法是不同的。所以需要在适配层对 API 进行抹平。 -#### React +##### React ```typescript import { createElement } from 'react'; import { @@ -42,7 +46,7 @@ adapter.setRuntime({ createElement, }); ``` -#### Rax +##### Rax ```typescript import { createElement } from 'rax'; import { @@ -69,10 +73,12 @@ adapter.setRuntime({ - `ComponentRenderer`:组件渲染的方法。 - `BlockRenderer`:区块渲染的方法。 -### 渲染层 -#### React Renderer +#### 渲染层 +##### React Renderer 内部的技术栈统一都是 React,大多数适配层的 API 都是按照 React 来设计的,所以对于 React Renderer 来说,需要做的不多。 + React Renderer 的代码量很少,主要是将 React API 注册到适配层中。 + ```typescript import React, { Component, PureComponent, createElement, createContext, forwardRef, ReactInstance, ContextType } from 'react'; import ReactDOM from 'react-dom'; @@ -112,7 +118,7 @@ adapter.setRenderers({ adapter.setConfigProvider(ConfigProvider); ``` -#### Rax Renderer +##### Rax Renderer Rax 的大多数 API 和 React 基本也是一致的,差异点在于重写了一些方法。 ```typescript import { Component, PureComponent, createElement, createContext, forwardRef } from 'rax'; @@ -146,8 +152,8 @@ adapter.setRenderers({ }); ``` -## 多模式渲染 -### 预览模式渲染 +### 多模式渲染 +#### 预览模式渲染 预览模式的渲染,主要是通过 Schema、components 即可完成上述的页面渲染能力。 ```typescript import ReactRenderer from '@ali/lowcode-react-renderer'; @@ -183,12 +189,12 @@ ReactDOM.render(( ), document.getElementById('root')); ``` -### 设计模式渲染(Simulator) +#### 设计模式渲染(Simulator) 设计模式渲染就是将编排生成的《搭建协议》渲染成视图的过程,视图是可以交互的,所以必须要处理好内部数据流、生命周期、事件绑定、国际化等等。也称为画布的渲染,画布是 UI 编排的核心,它一般融合了页面的渲染以及组件/区块的拖拽、选择、快捷配置。 画布的渲染和预览模式的渲染的区别在于,画布的渲染和设计器之间是有交互的。所以在这里我们新增了一层 `Simulator` 作为设计器和渲染的连接器。 `Simulator` 是将设计器传入的 `DocumentModel` 和组件/库描述转成相应的 Schema 和 组件类。再调用 Render 层完成渲染。我们这里介绍一下它提供的能力。 -#### 整体架构 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644398136330-0f48202b-b581-4b1f-af79-72a667a194d9.png#clientId=udd4eb4ee-bdb1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=432&id=u734b5c16&margin=%5Bobject%20Object%5D&name=image.png&originHeight=864&originWidth=1500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=572012&status=done&style=none&taskId=u7d7cf569-d5a9-4bea-9b2d-1121b85728f&title=&width=750) +##### 整体架构 +![image.png](https://img.alicdn.com/imgextra/i2/O1CN017cYBAp1hvJKPUVLbx_!!6000000004339-2-tps-1500-864.png) - `Project`:位于顶层的 Project,保留了对所有文档模型的引用,用于管理应用级 Schema 的导入与导出。 - `Document`:文档模型包括 Simulator 与数据模型两部分。Simulator 通过一份 Simulator Host 协议与数据模型层通信,达到画布上的 UI 操作驱动数据模型变化。通过多文档的设计及多 Tab 交互方式,能够实现同时设计多个页面,以及在一个浏览器标签里进行搭建与配置应用属性。 @@ -200,11 +206,11 @@ ReactDOM.render(( - `SettingField`:它连接属性设置器 `Setter` 与属性模型 `Prop`,它是实现多节点属性批处理的关键。 - 通用交互模型:内置了拖拽、活跃追踪、悬停探测、剪贴板、滚动、快捷键绑定。 -#### 模拟器介绍 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644398137096-260646a0-f264-48af-9600-6f7141a6a1d8.png#clientId=udd4eb4ee-bdb1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=370&id=ubfb08f11&margin=%5Bobject%20Object%5D&name=image.png&originHeight=740&originWidth=1500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=353179&status=done&style=none&taskId=u3cd764bb-52f6-47a6-8026-fee6a36d08d&title=&width=750) +##### 模拟器介绍 +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01GF1PMj288kxovvnK8_!!6000000007888-2-tps-1500-740.png) - 运行时环境:从运行时环境来看,目前我们有 React 生态、Rax 生态。而在对外的历程中,我们也会拥有 Vue 生态、Angular 生态等。 - 布局模式:不同于 C 端营销页的搭建,中后台场景大多是表单、表格,流式布局是主流的选择。对于设计师、产品来说,是需要绝对布局的方式来进行页面研发的。 - 研发场景:从研发场景来看,低代码搭建不仅有页面编排,还有诸如逻辑编排、业务编排的场景。 -基于以上思考,我们通过基于沙箱隔离的模拟器技术来实现了多运行时环境(如 React、Rax、小程序、Vue)、多模式(如流式布局、自由布局)、多场景(如页面编排、关系图编排)的 UI 编排。通过注册不同的运行时环境的渲染模块,能够实现编辑器从 React 页面搭建到 Rax 页面搭建的迁移。通过注册不同的模拟器画布,你可以基于 G6或者 mxgraph 来做关系图编排。你可以定制一个流式布局的画布,也可以定制一个自由布局的画布。 +基于以上思考,我们通过基于沙箱隔离的模拟器技术来实现了多运行时环境(如 React、Rax、小程序、Vue)、多模式(如流式布局、自由布局)、多场景(如页面编排、关系图编排)的 UI 编排。通过注册不同的运行时环境的渲染模块,能够实现编辑器从 React 页面搭建到 Rax 页面搭建的迁移。通过注册不同的模拟器画布,你可以基于 G6 或者 mxgraph 来做关系图编排。你可以定制一个流式布局的画布,也可以定制一个自由布局的画布。 diff --git a/docs/docs/guide/design/setter.md b/docs/docs/guide/design/setter.md index 66de03bb1..968e7bbf8 100644 --- a/docs/docs/guide/design/setter.md +++ b/docs/docs/guide/design/setter.md @@ -2,22 +2,27 @@ title: 设置器设计 sidebar_position: 6 --- + 设置器,又称为 Setter,是作为物料属性和用户交互的重要途径,在编辑器日常使用中有着非常重要的作用,本文重点介绍 Setter 的设计原理和使用方式,帮助用户更好的理解 Setter。 + 在编辑器的右边区域,Setter 的区块就展现在这里,如下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644404887956-8ffc8c8c-380c-4843-8bc9-512be77a9b18.png#clientId=u4cc5b992-0df5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=865&id=wNOuZ&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1730&originWidth=3836&originalType=binary&ratio=1&rotation=0&showTitle=false&size=947162&status=done&style=none&taskId=ue623b488-8774-401a-b80c-c102e8aac8f&title=&width=1918) + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01qEjjoQ24QNkD42wzl_!!6000000007385-2-tps-3836-1730.png) + 其中包含 属性、样式、事件、高级: - 属性:展示该物料常规的属性; - 样式:展示该物料样式的属性; - 事件:如果该物料有声明事件,则会出现事件面板,用于绑定事件; - 高级:两个逻辑相关的属性,**条件渲染**和**循环。** -# npm 包与仓库信息 +## npm 包与仓库信息 - npm 包:@alilc/lowcode-engine-ext - 仓库:[https://github.com/alibaba/lowcode-engine-ext](https://github.com/alibaba/lowcode-engine-ext) -# 设置器模块原理 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644404909143-eede0a27-e990-4333-816a-d2d0cf2594b3.png#clientId=u4cc5b992-0df5-4&crop=0&crop=0&crop=1&crop=1&height=482&id=PyO6v&name=image.png&originHeight=964&originWidth=1534&originalType=binary&ratio=1&rotation=0&showTitle=false&size=273494&status=done&style=none&taskId=ufb317b56-de50-4693-8c39-8faa9b38307&title=&width=767) +## 设置器模块原理 + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01EAmitQ1U5TUws63AV_!!6000000002466-2-tps-1534-964.png) 设置面板依赖于以下三块抽象 @@ -25,7 +30,8 @@ sidebar_position: 6 - 设置对象 `settingTarget`,主要包含:选中的节点、是否同一值、值的储存等 - 设置列 `settingField`,主要和当前设置视图相关,包含视图的 `ref`、以及设置对象 `settingTarget` -#### SettingTarget 抽象 +### SettingTarget 抽象 + 如果不是多选,可以直接暴露 `Node` 给到这,但涉及多选编辑的时候,大家的值时通常是不一样的,设置的时候需要批量设置进去,这里主要封装这些逻辑,把多选编辑的复杂性屏蔽掉。 所选节点所构成的**设置对象**抽象如下: @@ -49,7 +55,7 @@ interface SettingTarget { } ``` -基于设置对象所派生的**设置目标属性**抽象如下: +基于设置对象所派生的**设置目标属性**抽象如下: ```typescript interface SettingTargetProp extends SettingTarget { @@ -68,8 +74,8 @@ interface SettingTargetProp extends SettingTarget { } ``` -#### SettingField 抽象 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644396933393-779423e2-29a7-4e97-9ef9-e3c7964a5412.png#clientId=u41c9ba96-15b6-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=201&id=uc71z&margin=%5Bobject%20Object%5D&name=image.png&originHeight=402&originWidth=2022&originalType=binary&ratio=1&rotation=0&showTitle=false&size=218611&status=done&style=none&taskId=u534089f2-363d-464e-8c69-ac79f268f5a&title=&width=1011) +### SettingField 抽象 +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01D855j01j8sg9GdtJr_!!6000000004504-2-tps-2022-402.png) ```typescript interface SettingField extends SettingTarget { diff --git a/docs/docs/guide/design/specs.md b/docs/docs/guide/design/specs.md index be449e3dc..3e2b1342c 100644 --- a/docs/docs/guide/design/specs.md +++ b/docs/docs/guide/design/specs.md @@ -1,31 +1,51 @@ --- -title: 低代码引擎协议栈简介 +title: 协议栈简介 sidebar_position: 1 --- -# 什么是低代码协议 -这是两份中后台低代码领域的标准协议,即《低代码引擎物料协议规范》和《低代码引擎搭建协议规范》。它们保障了低代码领域的标准化,成为了生态建设和流通的基石。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1648642508161-64dd3a2c-d2d2-43ed-92e4-ead40ab62498.png#clientId=ub4563dfd-c5b1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=532&id=u60966832&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1064&originWidth=1928&originalType=binary&ratio=1&rotation=0&showTitle=false&size=974317&status=done&style=none&taskId=u88a8512e-a57c-43f6-a01f-19f6878b7a0&title=&width=964) -# 为什么需要协议 -首先,我们做一个不恰当的类比,我们将低代码引擎和 JavaScript 语言做一下类别。还记得之前,大家都被浏览器兼容性支配的恐惧,特别是 IE 和其他浏览器,对上层 API 实现的不一致,导致一份代码需要运行在两端需要做适配。当浏览器 / JavaScript 相关的标准出现之后,各个浏览器进行了 API 的统一,使得我们终于可以从这部分工作中解放出来(PS:Babel 对于语言特性的转换是另一个方面的问题)。 -而在《低代码引擎搭建协议规范》出现之前,低代码领域也有类似的问题。 -## 概念不通 -在交流的过程中,一些对于搭建产品的术语的不一致,导致了一些沟通成本,不管是在文章分享、技术分享、交流会上,都会有这个问题。 -## 物料孤岛 -由于低代码产品实现的方式不同,物料的消费方式也各不相同。这里分为两种物料,低代码物料和 ProCode 物料。 -对于低代码物料来说,A 平台创建的物料无法使用到 B 平台上,如果想在 B 平台实现同样的物料,需要按照 B 平台的标准搭建一份物料。 -对于 ProCode 物料来说,需要在低代码平台进行消费,是需要进行转换的,包括搭建配置项的生成、物料搭建试图等,可能还需要特殊的描述文件进行描述。由于这一层没有统一,同一份 ProCode 物料每接入一个低代码,可能需要的描述文件格式不同,转换的代码不同,使用的工具也不同。 -## 生态隔离 -不同低代码平台的生态体系也不相同,有的低代码平台的物料生态不错,有的低代码平台的搭建体验生态不错。但是这些利好的生态,都是无法互通的,甚至就算知道了代码,也无法复用,因为底层是不一致的。对于集团来说,每一个平台都创建一份自己的生态,这并不是利好的。 -## 技术深度不够 -大家可能觉得,以上问题对于自己造轮子来说,其实也是有利的,因为自己得到了技术上的成长。 -但是对于低代码的平台方,实际上更多的工作,在物料的转化、物料的生成、搭建体验的小优化、部分其他平台生态的实现。这些的技术深度其实并不高。 -## 价值不高 -如果每个业务都要从 0 开始做,做自己的平台,会花费大量的时间来构建底层基础设施,对业务本身而言并不是一件好事;而且前端领域的底层基础设施都大同小异,不同团队重复构建造成了极大的资源浪费。 -这样的建设,会导致从 0 到 1 都需要花费大量的时间,往往在内部人力不足、投入有限时,产品很容易在未发展壮大的时候就面临了死亡相关的决策。 -设想一下,如果可以开发一份全集团低代码平台都可以使用的物料,是否更有成就感呢?如果可以基于已有生态进行低代码平台的快速落地,而不是花费 1-2 年搭建一个可用的低代码平台,再验证市场。在快速的验证之后,再进行更深入的打磨,这其中的思考和技术含量是否更优于之前的模式呢? -比如不同平台的低代码物料 +## 什么是低代码协议 +低代码引擎体系基于三份协议来构建,分别是 [《低代码引擎搭建协议规范》](/site/docs/specs/lowcode-spec)、[《低代码引擎物料协议规范》](/site/docs/specs/material-spec)和[《低代码引擎资产包协议规范》](/site/docs/specs/assets-spec), 它们保障了低代码领域的标准化,成为了生态建设和流通的基石。 -1. vc-deep — vc 协议 + Deep 组件库(企业智能基于 Fusion Next 定制); +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01axsOyW1s01YgXnT8z_!!6000000005703-2-tps-1888-1000.png) + +## 为什么需要协议 + +首先,我们做一个不恰当的类比,我们将低代码引擎和 JavaScript 语言做一下类别。还记得之前,大家都被浏览器兼容性支配的恐惧,特别是 IE 和其他浏览器,对上层 API 实现的不一致,导致一份代码需要运行在两端需要做适配。当浏览器 / JavaScript 相关的标准出现之后,各个浏览器进行了 API 的统一,使得我们终于可以从这部分工作中解放出来(PS:Babel 对于语言特性的转换是另一个方面的问题)。 + +而在《低代码引擎搭建协议规范》出现之前,低代码领域也有类似的问题。 + +### 概念不通 + +在交流的过程中,一些对于搭建产品的术语的不一致,导致了一些沟通成本,不管是在文章分享、技术分享、交流会上,都会有这个问题。 + +### 物料孤岛 + +由于低代码产品实现的方式不同,物料的消费方式也各不相同。这里分为两种物料,低代码物料和 ProCode 物料。 + +对于低代码物料来说,A 平台创建的物料无法使用到 B 平台上,如果想在 B 平台实现同样的物料,需要按照 B 平台的标准搭建一份物料。 + +对于 ProCode 物料来说,需要在低代码平台进行消费,是需要进行转换的,包括搭建配置项的生成、物料搭建试图等,可能还需要特殊的描述文件进行描述。由于这一层没有统一,同一份 ProCode 物料每接入一个低代码,可能需要的描述文件格式不同,转换的代码不同,使用的工具也不同。 + +### 生态隔离 + +不同低代码平台的生态体系也不相同,有的低代码平台的物料生态不错,有的低代码平台的搭建体验生态不错。但是这些利好的生态,都是无法互通的,甚至就算知道了代码也无法复用,因为底层是不一致的。对于阿里巴巴集团来说,每一个平台都创建一份自己的生态,这并不是利好的。 + +### 低水平重复建设 + +大家可能觉得,以上问题对于自己造轮子来说,其实也是有利的,因为自己得到了技术上的成长。 + +但是对于低代码的平台方,实际上更多的工作,在物料的转化、物料的生成、搭建体验的小优化、部分其他平台生态的实现。这些的技术深度其实并不高,属于低水平重复建设部分。 + +### 价值不高 + +如果每个业务都要从 0 开始做,做自己的平台,会花费大量的时间来构建底层基础设施,对业务本身而言并不是一件好事;而且前端领域的底层基础设施都大同小异,不同团队重复构建造成了极大的资源浪费。 + +这样的建设,会导致从 0 到 1 都需要花费大量的时间,往往在内部人力不足、投入有限时,产品很容易在未发展壮大的时候就面临了死亡相关的决策。 + +设想一下,如果可以开发一份全集团低代码平台都可以使用的物料,是否更有成就感呢?如果可以基于已有生态进行低代码平台的快速落地,而不是花费 1-2 年搭建一个可用的低代码平台,再验证市场。在快速的验证之后,再进行更深入的打磨,这其中的思考和技术含量是否更优于之前的模式呢? + +以 2019 年的阿里巴巴的情况举例,不同平台的低代码物料但不限于: + +1. vc-deep — vc 协议 + Deep 组件库 (阿里巴巴企业智能团队基于 Fusion Next 定制); 2. Iceluna 协议 + Fusion Next; 3. AIMake 物料; 4. vc-fusion-basic + 业务改造 — vc 协议 + Fusion Next(各业务 Fork 定制); @@ -33,28 +53,37 @@ sidebar_position: 1 6. vc 协议 + antd; 可以看到,各个搭建平台都需要维护一套自己的基础组件库,这是非常不合理的,对基础组件库的维护会分散开发同学完成业务目标的精力。 -建立统一的低代码领域标准化,是百利而无一害的。于是,在阿里巴巴集团2020财年进行了讨论,建立了搭建治理&物料流通战役,此战役便产出了《低代码引擎物料协议规范》、《低代码引擎搭建协议规范》两份规范,成为了低代码引擎和其生态的基础。 -# 协议的作用 -基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,集团各类中后台研发系统生产的物料可借助物料中心进行跨系统流通,通过丰富物料生态的共享提升阿里巴巴中后台研发系统的效率。同时完成低代码引擎的标准统一以及低代码搭建中台能力的输出,帮助业务方快速孵化本业务域中后台研发系统。 -## 打破物料孤岛 -### 物料中心 -在《低代码引擎物料协议规范》成立了之后,规范先行建立了阿里巴巴各个中后台研发平台沟通、对话的基础,物料流通的先决条件已经成熟,这个时候我们还需要一个统一的物料源,用于管理物料的上传、存储、检索、分发,一个典型的中心化架构,类似 npm 的管理,这便是我们物料中心。 +建立统一的低代码领域标准化,是百利而无一害的。于是,在阿里巴巴集团 2020 年进行了讨论,建立了搭建治理&物料流通战役,此战役便产出了上文中的协议规范,成为了低代码引擎和其生态的基础。 + +## 协议的作用 + +基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,各类中后台研发系统生产的物料可借助物料中心进行跨系统流通,通过丰富物料生态的共享提升各平台研发系统的效率。同时完成低代码引擎的标准统一以及低代码搭建中台能力的输出,帮助业务方快速孵化本业务域中后台研发系统。 + +### 打破物料孤岛 + +#### 物料中心 + +这里以阿里集团的前端物料中间建设为例,在《低代码引擎物料协议规范》落地之后,建立了阿里巴巴各个中后台研发平台沟通、对话的基础,物料流通的先决条件已经成熟,这个时候我们还需要一个统一的物料源,用于管理物料的上传、存储、检索、分发,一个典型的中心化架构,类似 npm 的管理,这便是我们物料中心。 + Fusion Market 是物料中心的前身,它提供了业务组件的存储、文档展示和全局透出的功能,由于 fusion 体系在集团内的广泛使用,Fusion Market 沉淀了不少的业务组件,但是这个项目却一直不温不火,只看到业务组件数量的增加,却未看到物料流通起来。其中一个原因是,没有阿里巴巴前端委员会的背书,规范很难统一,规范如果不统一,物料就很难流通; + 在规范成立之后,物料中心也将有了建设的基础,最终于 2019 年建立了物料中心,提供了物料流通的平台能力。 -### 低代码基础物料 + +#### 低代码基础物料 + 就像 AntD、Element 之于源码研发模式,在低代码研发模式下各个搭建平台也需要一套统一的、开箱即用的低代码基础组件库。基于低代码描述协议完成了两份低代码基础物料的建设,即“Fusion 低代码基础组件库”和“AntD 低代码基础组件库”。 -### 源码组件低代码化 + +#### 源码组件低代码化 + 将源码组件一键转化为低代码物料,符合低代码物料规范,可以在低代码平台进行流通。 ### 低代码物料中心 + 当低代码物料积累到一定的量级之后,所有的搭建平台的业务物料越来越多。这些物料通过低代码物料中心进行统一的管理和消费。 -## Setter 生态的基础 +### 设置器生态的基础 + +Snippet(组件默认搭建 schema ) 由《低代码引擎搭建协议规范》定义,低代码引擎会按照规范对组件进行渲染,Configure 由《低代码引擎物料协议规范》定义,它描述了组件的 props 以及每个 prop 对应的设置器 (Prop 配置面板),低代码引擎提供了 20+ 个内置设置器,但如果我们组件的 props 超出了引擎内置设置器的范围,就需要我们自己来开发对应设置器。 +设置器最终也慢慢形成了自己的生态,这使得开发物料更加容易,可以使用已有的生态中的设置器,进行物料配置描述。 +### 低代码引擎实现标准 -Snippet(组件默认搭建 schema )由《低代码引擎搭建协议规范》定义,低代码引擎会按照规范对组件进行渲染,Configure 由《低代码引擎物料协议规范》定义,它描述了组件的 props 以及每个 prop 对应的 setter (Prop 配置面板),低代码引擎提供了 14 个内置 Setter,但如果我们组件的 props 超出了引擎内置 setter 的范围,就需要我们自己来开发对应 Setter。 -setter 最终也慢慢形成了自己的生态,这使得开发物料更加容易,可以使用已有的 setter 生态,进行物料配置描述。 -## 低代码引擎实现标准 低代码引擎是以上生态的消费端,它是实现了标准协议的低代码引擎。这是不可或缺的部分,低代码引擎这里就相当于一个标准浏览器,一方面给其他的低代码平台提供了一个 Demo,其他平台可以参考低代码引擎进行实现,满足官方协议,便也可以消费相关的物料生态和其他生态。 -通过物料中心实现集团各业务域物料跨系统流通是第一步,通过低代码引擎快速搭建出来的各业务域低代码平台平滑高效地使用各业务域物料,提升集团中后台研发系统的效率是关键的第二步。 - - -其中入料模块,使得任意符合物料协议的物料都可以被消费,也就打破了物料孤岛,实现物料之间的流通。 diff --git a/docs/docs/guide/design/summary.md b/docs/docs/guide/design/summary.md index 604886e8b..cd5edfd88 100644 --- a/docs/docs/guide/design/summary.md +++ b/docs/docs/guide/design/summary.md @@ -1,46 +1,55 @@ --- -title: 低代码引擎架构综述 +title: 架构综述 sidebar_position: 0 --- ## 分层架构描述 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644392855407-44040c3e-f98e-4e93-a7ba-7efc0a7927fb.png#clientId=ue3f00c22-d0cc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=540&id=u0d1fdc91&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1080&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=177518&status=done&style=none&taskId=u0ac7d0a3-e838-4982-ad41-e830af33545&title=&width=960) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN016l8gDo1z7zlRlW1P0_!!6000000006668-2-tps-1920-1080.png) + 我们设计了这样一套分层架构,自下而上分别是协议 - 引擎 - 生态 - 平台。 -底层协议栈定义的是标准,**标准的统一让上层产物的互通成为可能**, -**引擎是对协议的实现,同时通过能力的输出,向上支撑生态开放体系,提供各种生态扩展能力,** -那么生态就好理解了,是基于引擎核心能力上扩展出来的,比如物料、设置器、插件等,还有工具链支撑开发体系, -最后,各个平台基于引擎内核以及生态中的产品组合、衔接形成满足其需求的低代码平台。 + +- 底层协议栈定义的是标准,**标准的统一让上层产物的互通成为可能**。 +- 引擎是**对协议的实现**,同时通过能力的输出,向上**支撑生态开放体系**,提供各种生态扩展能力。 +- 生态就好理解了,是基于引擎核心能力上扩展出来的,比如物料、设置器、插件等,还有工具链支撑开发体系。 +- 最后,各个平台基于引擎内核以及生态中的产品组合、衔接形成满足其需求的低代码平台。 + **每一层都明确自身的定位,各司其职,协议不会去思考引擎如何实现,引擎也不会实现具体上层平台功能,上层平台的定制化均通过插件来实现,这些理念将会贯穿我们体系设计、实现的过程。** ## 引擎内核简述 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644393521380-2b5dda70-cd35-4cc2-aeae-6d0ba98deccd.png#clientId=ue3f00c22-d0cc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=540&id=u6b0dd5f3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1080&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=330340&status=done&style=none&taskId=u39127ebd-dbac-4636-9cb5-5c4833146a1&title=&width=960) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01QUUVu21LjTXqY6H8I_!!6000000001335-2-tps-1920-1080.png) -低代码引擎分为 4 大模块,入料 - 编排 - 渲染 - 出码。 -入料模块就是将外部的物料,比如海量的 npm 组件,按照《物料描述协议》进行描述。 -**注意,这里仅是增加描述,而非重写一套,这样我们能最大程度复用ProCode体系已沉淀的组件。** -将描述后的数据通过引擎 API 注册后,在编辑器中使用。 -编排,本质上来讲,就是**不断在生成符合《搭建协议》的页面描述,将编辑器中的所有物料,进行布局设置、组件 CRUD 操作、以及 JS/CSS编写/逻辑编排**等,最终转换成页面描述,技术细节待会儿我们再展开讲讲。 -渲染,顾名思义,就是**将编排生成的页面描述结构渲染成视图的过程**,视图是面向用户的,所以必须处理好内部数据流、生命周期、事件绑定、国际化等。 -出码,就是**将页面描述结构解析和转换成应用代码的机制**。 +低代码引擎分为 4 大模块,入料 - 编排 - 渲染 - 出码: + +- 入料模块就是将外部的物料,比如海量的 npm 组件,按照《物料描述协议》进行描述。将描述后的数据通过引擎 API 注册后,在编辑器中使用。 + > **注意,这里仅是增加描述,而非重写一套,这样我们能最大程度复用 ProCode 体系已沉淀的组件。** +- 编排,本质上来讲,就是**不断在生成符合[《低代码引擎搭建协议规范》](/site/docs/specs/lowcode-spec)的页面描述,将编辑器中的所有物料,进行布局设置、组件 CRUD 操作、以及 JS / CSS 编写/ 逻辑编排 **等,最终转换成页面描述,技术细节后文会展开。 +- 渲染,顾名思义,就是**将编排生成的页面描述结构渲染成视图的过程**,视图是面向用户的,所以必须处理好内部数据流、生命周期、事件绑定、国际化等。 +- 出码,就是**将编排过程产生的符合[《低代码引擎搭建协议规范》](/site/docs/specs/lowcode-spec)的页面描述转换成另一种 DSL 或 编程语言代码的过程**。 ## 引擎生态简述 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644393489755-b9a6a471-c099-480b-b40b-3094b793394d.png#clientId=ue3f00c22-d0cc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=540&id=u81ccc9e2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1080&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=504671&status=done&style=none&taskId=u52008ac0-e9c6-407b-a59e-7dbf4c02c0c&title=&width=960) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01LkRseZ23W31l8DPzS_!!6000000007262-2-tps-1920-1080.png) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644397483218-2b58bfca-94b1-474e-8983-afc757f20e59.png#clientId=uafdaa655-f89e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=540&id=u3aeacdac&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1080&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=394834&status=done&style=none&taskId=udcd28484-1df2-484c-9f98-87175972d65&title=&width=960) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01PYBVfZ1hL82XPrXzX_!!6000000004260-2-tps-1920-1080.png) 引擎生态主要分为 3 部分,物料、设置器和插件。 + ### 物料生态 + 物料是低代码平台的生产资料,没有物料低代码平台则变成了无源之水无本之木。低代码平台的物料即低代码组件。因此低代码物料生态指的是: -1)低代码物料生产能力和规范。 -2)对低代码物料进行统一管理的物料中心。 -3)基于 Fusion Next 的低代码基础组件库。 +1. 低代码物料生产能力和规范。 +2. 对低代码物料进行统一管理的物料中心。 +3. 基于 Fusion Next 的低代码基础组件库。 ### 设置器生态 + 对于已接入物料的属性配置,需要不同的设置器。 + 比如配置数值类型的 age,需要一个数值设置器,配置对象类型的 hobby,需要一个对象设置器,依次类推。 + 每个设置器本质上都是一个 React 组件,接受由引擎传入的参数,比如 value 和 onChange,value 是初始传入的值,onChange 是在设置器的值变化时的回传函数,将值写回到引擎中。 -```json + +```typescript // 一个最简单的文本设置器示例 class TextSetter extends Component { render() { @@ -49,9 +58,12 @@ class TextSetter extends Component { } } ``` + 大多数组件所使用的设置器都是一致或相似的。如同建设低代码基础组件库一样,设置器生态是一组基础的设置器,供大多数组件配置场景使用。 + 同时提供了设置器的定制功能。 ### 插件生态 低代码引擎本身只包含了最小的内核,而我们所能看到的设计器上的按钮、面板等都是插件提供的。插件是组成设计器的必要部分。 + 因此我们提供了一套官方的插件生态,提供最基础的设计器功能。帮助用户通过使用插件,快速完成自己的设计器。 diff --git a/docs/docs/guide/expand/_category_.json b/docs/docs/guide/expand/_category_.json index 36116999b..15aeb3dea 100644 --- a/docs/docs/guide/expand/_category_.json +++ b/docs/docs/guide/expand/_category_.json @@ -1,5 +1,5 @@ { - "label": "扩展低代码应用", + "label": "扩展低代码编辑器", "position": 2, "collapsed": false, "collapsible": true diff --git a/docs/docs/guide/expand/editor/cli.md b/docs/docs/guide/expand/editor/cli.md index 7f46c7b2e..0218e6f73 100644 --- a/docs/docs/guide/expand/editor/cli.md +++ b/docs/docs/guide/expand/editor/cli.md @@ -7,175 +7,191 @@ sidebar_position: 7 在 fork 低代码编辑器 demo 项目后,您可以直接在项目中任意扩展低代码编辑器。如果您想要将自己的组件/插件/设置器封装成一个独立的 npm 包并提供给社区,您可以使用我们的低代码脚手架建立低代码扩展。 > Windows 开发者请在 WSL 环境下使用开发工具 +> > WSL 中文 doc:[https://docs.microsoft.com/zh-cn/windows/wsl/install](https://docs.microsoft.com/zh-cn/windows/wsl/install) -中文教程:[https://blog.csdn.net/weixin_45027467/article/details/106862520](https://blog.csdn.net/weixin_45027467/article/details/106862520) +> +> 中文教程:[https://blog.csdn.net/weixin_45027467/article/details/106862520](https://blog.csdn.net/weixin_45027467/article/details/106862520) ## 脚手架功能 ### 脚手架初始化 -```shell -$ npm init @alilc/element your-element-name + +```bash +npm init @alilc/element your-element-name ``` 不写 your-element-name 的情况下,则在当前目录创建。 -> 觉得安装速度比较慢的同学,可以设置 npm 国内镜像,如 - +> 注 1:如遇错误提示 `sh: create-element: command not found` 可先执行下述命令 ```bash -$ npm init @alilc/element your-element-name --registry=https://registry.npmmirror.com +npm install -g @alilc/create-element +``` + +> 注 2:觉得安装速度比较慢的同学,可以设置 npm 国内镜像,如 +```bash +npm init @alilc/element your-element-name --registry=https://registry.npmmirror.com ``` 选择对应的元素类型,并填写对应的问题,即可完成创建。 -![截屏2022-02-09 下午8.15.07.png](https://cdn.nlark.com/yuque/0/2022/png/134449/1644408912640-ae7a9a9b-54a4-49c3-a5d8-ccac1db7da0b.png#averageHue=%23f0f0ef&clientId=ue2be1de5-5d30-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=drop&height=82&id=uaff32f98&margin=%5Bobject%20Object%5D&name=%E6%88%AA%E5%B1%8F2022-02-09%20%E4%B8%8B%E5%8D%888.15.07.png&originHeight=148&originWidth=688&originalType=binary&ratio=1&rotation=0&showTitle=false&size=72918&status=error&style=none&taskId=uf08c7e98-b502-416d-be39-0029f765203&title=&width=382) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01LAaw2R1veHDYUzGB1_!!6000000006197-2-tps-676-142.png) + ### 脚手架本地环境调试 -```shell + +```bash cd your-element-name npm install npm start ``` ### 脚手架构建 -```shell -$ npm run build + +```bash +npm run build ``` + ### 脚手架发布 + 修改版本号后,执行如下指令即可: -```shell -$ npm publish + +```bash +npm publish ``` -# 🔥🔥🔥 调试物料/插件/设置器 +## 🔥🔥🔥 在低代码项目中调试物料/插件/设置器 -> 📢📢 📢 低代码生态脚手架提供的调试利器,在启动 setter/插件/物料 项目后,直接在已有的低代码平台就可以调试,不需要 npm link / 手改 npm main 入口等传统方式,轻松上手,强烈推荐使用!! +> 📢📢📢 低代码生态脚手架提供的调试利器,在启动 setter/插件/物料 项目后,直接在已有的低代码平台就可以调试,不需要 npm link / 手改 npm main 入口等传统方式,轻松上手,强烈推荐使用!! - -注:若控制台出现如下错误,直接访问一次该 url 即可~ -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1652408638502-0509191d-1cd6-435c-9196-5c7abac7cc4d.png#averageHue=%23c8e1be&clientId=u0b1196f0-7f06-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=113&id=tjF5F&margin=%5Bobject%20Object%5D&name=image.png&originHeight=226&originWidth=1418&originalType=binary&ratio=1&rotation=0&showTitle=false&size=180782&status=error&style=none&taskId=u57eb2bdc-6dfd-4332-b176-c453947be2d&title=&width=709) - -## 组件/插件/Setter 侧 +### 组件/插件/Setter 侧 1. 插件/setter 在原有 alt 的配置中添加相关的调试配置 -```json -// build.json 中 -{ - "plugins": [ - [ - "@alilc/build-plugin-alt", - { - "type": "plugin", - "inject": true, // 开启注入调试 - // 配置要打开的页面,在注入调试模式下,不配置此项的话不会打开浏览器 - // 支持直接使用官方 demo 项目:https://lowcode-engine.cn/demo/index.html - "openUrl": "https://lowcode-engine.cn/demo/index.html?debug" - } - ], - ] -} -``` + ```json + // build.json 中 + { + "plugins": [ + [ + "@alilc/build-plugin-alt", + { + "type": "plugin", + "inject": true, // 开启注入调试 + // 配置要打开的页面,在注入调试模式下,不配置此项的话不会打开浏览器 + // 支持直接使用官方 demo 项目:https://lowcode-engine.cn/demo/index.html + "openUrl": "https://lowcode-engine.cn/demo/index.html?debug" + } + ], + ] + } + ``` 2. 组件需先安装 @alilc/build-plugin-alt,再将组件内的 `build.lowcode.js`文件修改如下 -```javascript -const { library } = require('./build.json'); + ```javascript + const { library } = require('./build.json'); -module.exports = { - alias: { - '@': './src', - }, - plugins: [ - [ - // lowcode 的配置保持不变,这里仅为示意。 - '@alifd/build-plugin-lowcode', - { - library, - engineScope: "@alilc" - }, - ], - [ - '@alilc/build-plugin-alt', - { - type: 'component', - inject: true, - library, - // 配置要打开的页面,在注入调试模式下,不配置此项的话不会打开浏览器 - // 支持直接使用官方 demo 项目:https://lowcode-engine.cn/demo/index.html - openUrl: "https://lowcode-engine.cn/demo/index.html?debug" - } - ]], -}; -``` + module.exports = { + alias: { + '@': './src', + }, + plugins: [ + [ + // lowcode 的配置保持不变,这里仅为示意。 + '@alifd/build-plugin-lowcode', + { + library, + engineScope: "@alilc" + }, + ], + [ + '@alilc/build-plugin-alt', + { + type: 'component', + inject: true, + library, + // 配置要打开的页面,在注入调试模式下,不配置此项的话不会打开浏览器 + // 支持直接使用官方 demo 项目:https://lowcode-engine.cn/demo/index.html + openUrl: "https://lowcode-engine.cn/demo/index.html?debug" + } + ]], + }; + ``` 3. 本地组件/插件/Setter正常启动调试,在项目的访问地址增加 debug,即可开启注入调试。 -```typescript -https://lowcode-engine.cn/demo/index.html?debug -``` -## 项目侧的准备 + ```url + https://lowcode-engine.cn/demo/demo-general/index.html?debug + ``` + +### 项目侧的准备 + > 如果你的低代码项目 fork 自官方 demo,那么项目侧的准备已经就绪,不用再看以下内容~ 1. 安装 @alilc/lowcode-plugin-inject -```shell -npm i @alilc/lowcode-plugin-inject --save-dev -``` + ```bash + npm i @alilc/lowcode-plugin-inject --save-dev + ``` 2. 在引擎初始化侧引入插件 -```json -import Inject, { injectAssets } from '@alilc/lowcode-plugin-inject'; + ```typescript + import Inject, { injectAssets } from '@alilc/lowcode-plugin-inject'; -export default async () => { - // 注意 Inject 插件必须在其他插件前注册,且所有插件的注册必须 await - await plugins.register(Inject); - await plugins.register(OtherPlugin); - await plugins.register((ctx: ILowCodePluginContext) => { - return { - name: "editor-init", - async init() { - // 设置物料描述前,使用插件提供的 injectAssets 进行处理 - const { material, project } = ctx; - material.setAssets(await injectAssets(assets)); - }, - }; - }); -} -``` + export default async () => { + // 注意 Inject 插件必须在其他插件前注册,且所有插件的注册必须 await + await plugins.register(Inject); + await plugins.register(OtherPlugin); + await plugins.register((ctx: ILowCodePluginContext) => { + return { + name: "editor-init", + async init() { + // 设置物料描述前,使用插件提供的 injectAssets 进行处理 + const { material, project } = ctx; + material.setAssets(await injectAssets(assets)); + }, + }; + }); + } + ``` -3. 在 saveSchema 时过滤掉插入的url,避免影响渲染态 -```javascript -import { filterPackages } from '@alilc/lowcode-plugin-inject'; -export const saveSchema = async () => { - // ... - const packages = await filterPackages(editor.get('assets').packages); - window.localStorage.setItem( - 'packages', - JSON.stringify(packages), - ); - // ... -}; - -``` +3. 在 saveSchema 时过滤掉插入的 url,避免影响渲染态 + ```typescript + import { filterPackages } from '@alilc/lowcode-plugin-inject'; + export const saveSchema = async () => { + // ... + const packages = await filterPackages(editor.get('assets').packages); + window.localStorage.setItem( + 'packages', + JSON.stringify(packages), + ); + // ... + }; + ``` 4. 如果希望预览态也可以注入调试组件,则需要在 preview 逻辑里插入组件 -```javascript -import { injectComponents } from '@alilc/lowcode-plugin-inject'; + ```javascript + import { injectComponents } from '@alilc/lowcode-plugin-inject'; -async function init() { - // 在传递给 ReactRenderer 前,先通过 injectComponents 进行处理 - const components = await injectComponents(buildComponents(libraryMap, componentsMap)); - // ... -} -``` + async function init() { + // 在传递给 ReactRenderer 前,先通过 injectComponents 进行处理 + const components = await injectComponents(buildComponents(libraryMap, componentsMap)); + // ... + } + ``` -# Meta 信息 +注:若控制台出现如下错误,直接访问一次该 url 即可~ + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01cvKmeK1saCqpIxbLW_!!6000000005782-2-tps-1418-226.png) + + +## Meta 信息 meta 信息是放在生态元素 package.json 中的一小段 json,用户可以通过 meta 了解到这个元素的一些基本信息,如元素类型,一些入口信息等。 ```typescript interface LcMeta { - type: 'plugin' | 'setter' | 'component'; // 元素类型,尚未实现 - pluginName: string; // 插件名,仅插件包含 + type: 'plugin' | 'setter' | 'component'; // 元素类型,尚未实现 + pluginName: string; // 插件名,仅插件包含 meta: { - dependencies: string[]; // 插件依赖的其他插件列表,仅插件包含 + dependencies: string[]; // 插件依赖的其他插件列表,仅插件包含 engines: { - lowcodeEngine: string; // 适配的引擎版本 + lowcodeEngine: string; // 适配的引擎版本 } - prototype: string; // 物料描述入口,仅组件包含,尚未实现 - prototypeView: string; // 物料设计态入口,仅组件包含,尚未实现 + prototype: string; // 物料描述入口,仅组件包含,尚未实现 + prototypeView: string; // 物料设计态入口,仅组件包含,尚未实现 } } ``` diff --git a/docs/docs/guide/expand/editor/material.md b/docs/docs/guide/expand/editor/material.md index 88ea8b908..a5e374db9 100644 --- a/docs/docs/guide/expand/editor/material.md +++ b/docs/docs/guide/expand/editor/material.md @@ -12,14 +12,14 @@ sidebar_position: 1 低代码编辑器中的物料需要进行一定的配置和处理,才能让用户在低代码平台使用起来。这个过程中,需要一份一份配置文件,也就是资产包。资产包文件中,针对每个物料定义了它们在低代码编辑器中的使用描述。 ## 资产包配置 ### 什么是低代码资产包 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1647671718994-e013a162-37be-4fa7-bd3b-3af06878c3c2.png#clientId=uf20508c2-6786-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=579&id=u7a0c3dae&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1646&originWidth=3068&originalType=binary&ratio=1&rotation=0&showTitle=false&size=635660&status=done&style=stroke&taskId=uc304cc2b-24bf-449d-8e2e-fd25c88b189&title=&width=1080) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01SQJfxh1Y8uwDXksaK_!!6000000003015-2-tps-3068-1646.png) 在低代码 Demo 中,我们可以看到,组件面板不只提供一个组件,组件是以集合的形式提供给低代码平台的,而低代码资产包正是这些组件构成集合的形式。 **_它背后的 Interface,_**[**_在引擎中的定义摘抄如下_**](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/assets.ts)**_:_** ```typescript export interface Assets { version: string; // 资产包协议版本号 - packages?: Array; // 大包列表,external与package的概念相似,融合在一起 + packages?: Array; // 大包列表,external 与 package 的概念相似,融合在一起 components: Array | Array; // 所有组件的描述协议列表 sort: ComponentSort; // 新增字段,用于描述组件面板中的 tab 和 category } @@ -32,7 +32,7 @@ export interface ComponentSort { export interface RemoteComponentDescription { exportName: string; // 组件描述导出名字,可以通过 window[exportName] 获取到组件描述的 Object 内容; url: string; // 组件描述的资源链接; - package: { // 组件(库)的 npm 信息; + package: { // 组件 (库) 的 npm 信息; npm: string; } } @@ -40,14 +40,14 @@ export interface RemoteComponentDescription { 资产包协议 TS 描述 ### Demo 中的资产包 在 Demo 项目中,自带了一份默认的资产包: -> [https://github.com/alibaba/lowcode-demo/blob/main/src/universal/assets.json](https://github.com/alibaba/lowcode-demo/blob/main/src/universal/assets.json) +> [https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/services/assets.json](https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/services/assets.json) 这份资产包里的物料是我们内部沉淀出的,用户可以通过这套资产包体验引擎提供的搭建、配置能力。 **_在项目中正常注册资产包:_** -```json -import { material } from '@alilc/lowcode-engine' +```typescript +import { material } from '@alilc/lowcode-engine'; // 以任何方式引入 assets -material.setAssets(assets) +material.setAssets(assets); ``` **_以支持调试的方式注册资产包:_** > 这样启动并部署出来的项目,可以通过在预览地址加上 ?debug 来调试本地物料。 @@ -55,18 +55,18 @@ material.setAssets(assets) > - 通过插件初始化一个物料 > - 按照参考文章配置物料支持调试 > - 启动物料 -> - 访问:[https://lowcode-engine.cn/demo?debug](https://lowcode-engine.cn/demo?debug) +> - 访问:[https://lowcode-engine.cn/demo/demo-general/index.html?debug](https://lowcode-engine.cn/demo/demo-general/index.html) > -详细参考:[https://www.yuque.com/lce/doc/ulvlkz](https://www.yuque.com/lce/doc/ulvlkz) +详细参考:[低代码生态脚手架 & 调试机制](https://lowcode-engine.cn/site/docs/guide/expand/editor/cli) -```javascript -import { material } from '@alilc/lowcode-engine' +```typescript +import { material } from '@alilc/lowcode-engine'; import Inject, { injectAssets } from '@alilc/lowcode-plugin-inject'; await material.setAssets(await injectAssets(assets)); ``` ### 手工配置资产包 -参考 Demo 中的[基础 Fusion Assets 定义](https://github.com/alibaba/lowcode-demo/blob/main/src/scenarios/basic-fusion/assets.json),如果我们修改 assets.json,我们就能做到配置资产包: +参考 Demo 中的[基础 Fusion Assets 定义](https://github.com/alibaba/lowcode-demo/blob/main/demo-basic-fusion/src/services/assets.json),如果我们修改 assets.json,我们就能做到配置资产包: - packages 对象:我们需要在其中定义这个包的获取方式,如果不定义,就不会被低代码引擎动态加载并对应上组件实例。定义方式是 UMD 的包,低代码引擎会尝试在 window 上寻找对应 library 的实例; - components 对象:我们需要在其中定义物料描述,物料描述我们将在下一节继续讲解。 @@ -80,14 +80,14 @@ await material.setAssets(await injectAssets(assets)); 4. 画布更新生效。 **_当我们选中一个组件,我们可以看到面板右侧会显示组件的配置项。_** -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644312295732-5e0df2b5-065a-4d80-a66c-b5b20c8c32af.png#clientId=ue1d4eb8d-3b5c-4&crop=0&crop=0&crop=1&crop=1&from=url&height=535&id=ML9vP&margin=%5Bobject%20Object%5D&name=image.png&originHeight=743&originWidth=1500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=212807&status=done&style=stroke&taskId=u2458e0f7-6bea-40d8-bb9b-9811562c6fe&title=&width=1080) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01T5hGcl25ABLpLIWKh_!!6000000007485-2-tps-1500-743.png) **_它包含以下内容:_** 1. 基础信息:描述组件的基础信息,通常包含包信息、组件名称、标题、描述等。 2. 组件属性信息:描述组件属性信息,通常包含参数、说明、类型、默认值 4 项内容。 3. 能力配置/体验增强:推荐用于优化搭建产品编辑体验,定制编辑能力的配置信息。 -因此,我们设计了[**《中后台低代码组件描述协议》**](http://lowcode-engine.cn/material)来描述一个低代码编辑器中可被配置的内容。 +因此,我们设计了[**《中后台低代码组件描述协议》**](/site/docs/specs/material-spec)来描述一个低代码编辑器中可被配置的内容。 ### Demo 中的物料描述 我们可以从 Demo 中的 assets.json 找到如下三个物料描述: @@ -97,13 +97,13 @@ await material.setAssets(await injectAssets(assets)); **_引擎中,会尝试调用对应 meta 文件,并注入到全局:_** ```tsx -const src = 'https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.5/build/lowcode/meta.js' -const script = document.createElement('script') -script.src = src -document.head.appendChild(script) +const src = 'https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.5/build/lowcode/meta.js'; +const script = document.createElement('script'); +script.src = src; +document.head.appendChild(script); ``` 然后在 window 上就能拿到对应的物料描述内容了: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1647672326187-ec19ed1e-645a-4086-8384-ccca19b9f36c.png#clientId=uf20508c2-6786-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=648&id=ue7a84d56&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1138&originWidth=1896&originalType=binary&ratio=1&rotation=0&showTitle=false&size=582492&status=done&style=stroke&taskId=u11707d78-e1c5-4368-9de0-e98b7597815&title=&width=1080) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01DHSEOH1RwCEq19Ro9_!!6000000002175-2-tps-1896-1138.png) 手工配置物料描述时,可以用这样的方式参考一下 Demo 中的物料描述是如何实现的。 ### 手工配置物料描述 详见:“物料描述详解”章节。 @@ -113,18 +113,18 @@ document.head.appendChild(script) 您可以通过本节内容,完成一个组件在低代码编辑器中的配置和调试。 ### 前言(必读) 引擎提供的物料开发脚手架内置了**_入料模块_**,初始化的时候会自动根据源码解析出一份_**低代码描述**_,但是从源码解析出来的低代码描述让用户直接使用是不够精细的,因为源码包含的信息不够,它没办法完全包含配置项的交互; -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1650539267595-c15e6200-9747-46bf-a61d-2a635d295406.png?x-oss-process=image/format,png#clientId=u97daa023-2ae2-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=856&id=u5b22ab2d&name=image.png&originHeight=1830&originWidth=802&originalType=binary&ratio=1&rotation=0&showTitle=false&size=4406602&status=done&style=stroke&taskId=ued90eb0c-b714-401a-bbfe-9f0b04794f6&title=&width=375) -比如设计师出了上面的设计稿,这里面除了有哪些 props 可被配置,通过哪个设置器配置,还包含了 props 之间的聚合、排序,甚至有自定义 setter ,这些信息源码里是不具备的,需要在低代码描述里进行开发; +![image.png](https://img.alicdn.com/imgextra/i1/O1CN010t0YzC1znDPQB1LUA_!!6000000006758-2-tps-802-1830.png) +比如设计师出了上面的设计稿,这里面除了有哪些 props 可被配置,通过哪个设置器配置,还包含了 props 之间的聚合、排序,甚至有自定义 setter,这些信息源码里是不具备的,需要在低代码描述里进行开发; **_因此我们建议只把 cli 初始化的低代码描述作为启动,要根据用户习惯对配置项进行设计,然后人工地去开发调试直接的低代码描述。_** ### 新开发组件 #### 组件项目初始化 -```json +```bash npm init @alilc/element your-material-name ``` #### 选择组件类型 > 组件 -> <组件组织方式> -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647569723981-d0cb5f94-c137-4abf-8165-947b49595c8c.png#clientId=u6b9f3678-e2a3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=174&id=ud7ad63de&margin=%5Bobject%20Object%5D&name=image.png&originHeight=464&originWidth=1596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=298505&status=done&style=stroke&taskId=ud5e35ff9-c823-41bf-b441-db9e06a1f29&title=&width=600) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01BTiMt51iLPtzDbuh8_!!6000000004396-2-tps-1596-464.png) 这里我们选择 react-组件库,之后便生出我们的组件库项目,目录结构如下: ``` my-materials @@ -147,7 +147,7 @@ my-materials └── └── ExampleComponent2 // 业务组件2 ``` #### 组件开发与调试 -``` +```bash # 安装依赖 npm install @@ -157,15 +157,15 @@ npm run lowcode:dev # 构建低代码产物 npm run lowcode:build ``` -执行上述命令后会在组件(库)根目录生成一个 `lowcode` 文件夹,里面会包含每个组件的低代码描述: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644314663918-b2464be7-a65b-447c-af2a-12ea326a7558.png#clientId=ue1d4eb8d-3b5c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=376&id=AYq7T&margin=%5Bobject%20Object%5D&name=image.png&originHeight=906&originWidth=1446&originalType=binary&ratio=1&rotation=0&showTitle=false&size=347634&status=done&style=stroke&taskId=u25ffbb86-6681-427f-b199-69a22560a9c&title=&width=600) +执行上述命令后会在组件 (库) 根目录生成一个 `lowcode` 文件夹,里面会包含每个组件的低代码描述: +![image.png](https://img.alicdn.com/imgextra/i2/O1CN016m7gOK1DvpIcnlTvY_!!6000000000279-2-tps-1446-906.png) 在 src/components 目录新增一个组件并在 src/index.tsx 中导出,然后再执行 npm run lowcode:dev 时,低代码插件会在 lowcode/ 目录自动生成新增组件的低代码描述(meta.ts)。 用户可以直接修改低代码描述来修改组件的配置: -- 设置组件的 setter;(上一个章节介绍的设置器,也可以定制设置器用到物料中) -- 新增组件配置项 +- 设置组件的 setter(上一个章节介绍的设置器,也可以定制设置器用到物料中); +- 新增组件配置项; - 更改当前配置项; #### 配置示例 隐藏一个 prop @@ -179,24 +179,34 @@ npm run lowcode:build ```typescript { name: 'dataSource', - display: 'accordion' | 'inline' | 'block' | 'plain' | 'popup' | 'entry' // 常用的是 inline(默认), block、entry + display: 'accordion' | 'inline' | 'block' | 'plain' | 'popup' | 'entry', // 常用的是 inline(默认), block、entry } ``` -发布组件 -``` +#### 编辑态视图 +用户可以在 lowcode/ 目录下新增 view.tsx 来增加编辑态视图。编辑态视图用于在编辑态时展示与真实预览不一样的视图。 +view.tsx 输出的也是一个 React 组件。 + +注意:如果是单组件,而非组件库模式的话,view.tsx 应置于 lowcode 而非 lowcode/ 目录下 + + +#### 发布组件 +```bash # 在组件根目录下,执行 $ npm publish ``` ### 现存组件低代码化 组件低代码化是指,在引入低代码平台之前,我们大多数都是使用源码开发的组件,也就是 ProCode 组件。 + 在引入低代码平台之后,原来的源码组件是需要转化为低代码物料,这样才能在低代码平台进行消费。 + 所以接下来会说明,对于已有的源码组件,我们如何把它低代码化。 #### 配置低代码开发环境 在您的组件开发环境中,安装 [build-scripts](https://github.com/ice-lab/build-scripts) 和它的低代码开发插件: -```shell +```bash npm install -D @alifd/build-plugin-lowcode @alib/build-scripts --save-dev ``` 新增 build-scripts 配置文件:build.lowcode.js + ```javascript module.exports = { alias: { @@ -218,39 +228,49 @@ module.exports = { "lowcode:dev": "build-scripts start --config ./build.lowcode.js", "lowcode:build": "build-scripts build --config ./build.lowcode.js", ``` -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644314665584-018b6675-ca7c-4bf5-b755-15a9b629f78f.png#clientId=ue1d4eb8d-3b5c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=270&id=brUY9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=822&originWidth=1830&originalType=binary&ratio=1&rotation=0&showTitle=false&size=972113&status=done&style=stroke&taskId=u09d05c9e-cf05-417e-bf32-8268d004134&title=&width=600) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN014iSa1P1dNdkUUtoMm_!!6000000003724-2-tps-1830-822.png) #### 开发调试 + ```bash # 启动低代码开发调试环境 npm run lowcode:dev ``` + 组件开发形式还和原来的保持一致,但是新增了一份组件的配置文件,其中配置方式和低代码物料的配置是一样的。 + #### 构建 + ```bash # 构建低代码产物 npm run lowcode:build ``` + #### 发布组件 ```bash # 在组件根目录下,执行 npm publish ``` -## 在项目中引入组件(库) -> 以下内容可观看[《阿里巴巴低代码引擎项目实战(3)-自定义组件接入》](https://www.bilibili.com/video/BV1dZ4y1m76S/)直播回放 + +## 在项目中引入组件 (库) +> 以下内容可观看[《阿里巴巴低代码引擎项目实战 (3)-自定义组件接入》](https://www.bilibili.com/video/BV1dZ4y1m76S/)直播回放 对于平台或者用户来说,可能所需要的组件集合是不同的。如果需要自定义组件集合,就需要定制资产包,定制的资产包是配置了一系列组件的,将这份资产包用于引擎即可在引擎中使用自定义的组件集合。 + ### 管理一份资产包 项目中使用的组件相关资源都需要在资产包中定义,那么我们自己开发的组件库如果要在项目中使用,只需要把组件构建好的相关资源 merge 到 assets.json 中就可以; + #### 自定义组件加入到资产包 通过官方脚手架自定义组件构建发布之后,npm 包里会出现一个 `build/lowcode/assets-prod.json`文件,我们只需要把该文件的内容 merge 到项目的 assets.json 中就可以; + #### 资产包托管 -- 最简单的方式就是类似[引擎 demo 项目](https://github.com/alibaba/lowcode-demo/blob/main/src/universal/assets.json)的做法,在项目中维护一份 assets.json,新增组件或者组件版本更新都需要修改这份资产包; -- 灵活一点的做法是通过 oss 等服务维护一份远程可配置的 assets.json ,新增组件或者组件更新只需要修改这份远程的资产包,项目无需更新; +- 最简单的方式就是类似[引擎 demo 项目](https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/services/assets.json)的做法,在项目中维护一份 assets.json,新增组件或者组件版本更新都需要修改这份资产包; +- 灵活一点的做法是通过 oss 等服务维护一份远程可配置的 assets.json,新增组件或者组件更新只需要修改这份远程的资产包,项目无需更新; - 再高级一点的做法是实现一个资产包管理的服务,能够通过用户界面去更新资产包的内容; + ### 在项目中引入资产包 -```javascript -import { ILowCodePluginContext, material, plugins } from '@alilc/lowcode-engine' +```typescript +import { ILowCodePluginContext, material, plugins } from '@alilc/lowcode-engine'; // 动态加载 assets plugins.register((ctx: ILowCodePluginContext) => { @@ -259,13 +279,13 @@ plugins.register((ctx: ILowCodePluginContext) => { async init() { try { // 将下述链接替换为您的物料即可。无论是通过 utils 从物料中心引入,还是通过其他途径如直接引入物料描述 - const res = await window.fetch('https://fusion.alicdn.com/assets/default@0.1.95/assets.json') - const assets = await res.text() - material.setAssets(assets) + const res = await window.fetch('https://fusion.alicdn.com/assets/default@0.1.95/assets.json'); + const assets = await res.text(); + material.setAssets(assets); } catch (err) { - console.error(err) + console.error(err); } }, } -}).catch(err => console.error(err)) +}).catch(err => console.error(err)); ``` diff --git a/docs/docs/guide/expand/editor/metaSpec.md b/docs/docs/guide/expand/editor/metaSpec.md index b1c41dfd9..2e70550ac 100644 --- a/docs/docs/guide/expand/editor/metaSpec.md +++ b/docs/docs/guide/expand/editor/metaSpec.md @@ -4,13 +4,13 @@ sidebar_position: 2 --- ## 物料描述概述 -中后台前端体系中,存在大量的组件,程序员可以通过阅读文档,知悉组件的用法。可是搭建平台无法理解 README,而且很多时候,README 里并没有属性列表。这时,我们需要一份额外的描述,来告诉低代码搭建平台,组件接受哪些属性,又是该用怎样的方式来配置这些属性,于是,[**《中后台低代码组件描述协议》**](http://lowcode-engine.cn/material)应运而生。协议主要包含三部分:基础信息、属性信息 props、能力配置/体验增强 configure。 +中后台前端体系中,存在大量的组件,程序员可以通过阅读文档,知悉组件的用法。可是搭建平台无法理解 README,而且很多时候,README 里并没有属性列表。这时,我们需要一份额外的描述,来告诉低代码搭建平台,组件接受哪些属性,又是该用怎样的方式来配置这些属性,于是,[**《中后台低代码组件描述协议》**](/site/docs/specs/material-spec)应运而生。协议主要包含三部分:基础信息、属性信息 props、能力配置/体验增强 configure。 -物料配置,就是产出一份符合[**《中后台低代码组件描述协议》**](http://lowcode-engine.cn/material)的 JSON Schema。如果需要补充属性描述信息,或需要定制体验增强部分(如修改 Setter、调整展示顺序等),就可以通过修改这份 Schema 来实现。目前有自动生成、手工配置这两种方式生成物料描述配置。 +物料配置,就是产出一份符合[**《中后台低代码组件描述协议》**](/site/docs/specs/material-spec)的 JSON Schema。如果需要补充属性描述信息,或需要定制体验增强部分(如修改 Setter、调整展示顺序等),就可以通过修改这份 Schema 来实现。目前有自动生成、手工配置这两种方式生成物料描述配置。 ## 可视化生成物料描述 -使用Parts造物平台:[https://www.yuque.com/lce/xhk5hf/qa9pbx](https://www.yuque.com/lce/xhk5hf/qa9pbx) +使用 Parts 造物平台:[使用文档](/site/docs/guide/expand/editor/partsIntro) ## 自动生成物料描述 @@ -28,7 +28,7 @@ export default class FusionForm extends PureComponent { static defaultProps = { name: '张三', age: 18, - friends: ['李四','王五','赵六'] + friends: ['李四','王五','赵六'], } static propTypes = { @@ -47,11 +47,13 @@ export default class FusionForm extends PureComponent { }; render() { - return
dumb
+ return
dumb
; } } ``` + 引入 parse 工具自动解析 + ```typescript import parse from '@alilc/lowcode-material-parser'; (async () => { @@ -59,7 +61,9 @@ import parse from '@alilc/lowcode-material-parser'; console.log(JSON.stringify(result, null, 2)); })(); ``` + 因为一个组件可能输出多个子组件,所以解析结果是个数组。 + ```json [ { @@ -103,6 +107,7 @@ import parse from '@alilc/lowcode-material-parser'; } ] ``` + ## 手工配置物料描述 如果自动生成的物料无法满足需求,我们就需要手动配置物料描述。本节将分场景描述物料配置的内容。 @@ -113,7 +118,8 @@ import parse from '@alilc/lowcode-material-parser'; 增加一个 size 属性,只能从 'large'、'normal'、'small' 这个候选值中选择。 -以上面自动解析的物料为例,在此基础上手工加上 size 属性: +以上面自动解析的物料为例,在此基础上手工加上 size 属性: + ```json [ { @@ -168,7 +174,7 @@ import parse from '@alilc/lowcode-material-parser'; "options": [ { "title": "大", "value": "large" }, { "title": "中", "value": "normal" }, - { "title": "小", "value": "small" }, + { "title": "小", "value": "small" } ] }, } @@ -180,18 +186,20 @@ import parse from '@alilc/lowcode-material-parser'; ``` #### 组件的属性既可以设置固定值,也可以绑定到变量 -我们知道一种属性形式就需要一种 setter 来设置,如果想要将 value 属性允许输入字符串,那就需要设置为 `StringSetter`,如果允许绑定变量,就需要设置为 `VariableSetter`,具体设置器请参考[预置 Setter 列表](https://www.yuque.com/lce/doc/oc220p) -那如果都想要呢?可以使用 `MixedSetter` 来实现 -```json +我们知道一种属性形式就需要一种 setter 来设置,如果想要将 value 属性允许输入字符串,那就需要设置为 `StringSetter`,如果允许绑定变量,就需要设置为 `VariableSetter`,具体设置器请参考[预置设置器列表](/site/docs/guide/appendix/setters)。 + +那如果都想要呢?可以使用 `MixedSetter` 来实现。 + +```javascript { - ..., + // ... configure: { isExtend: true, props: [ { - title: "输入框的值", - name: "activeValue", + title: '输入框的值', + name: 'activeValue', setter: { componentName: 'MixedSetter', isRequired: true, @@ -208,14 +216,18 @@ import parse from '@alilc/lowcode-material-parser'; } } ``` -设置后,就会出现 “切换设置器” 的操作项了 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/189077/1647590065530-b50ed66a-8d24-40fc-91a9-13561663537b.png#clientId=ubd9972cd-765c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=126&id=ub0e036f6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=252&originWidth=598&originalType=binary&ratio=1&rotation=0&showTitle=false&size=62314&status=done&style=none&taskId=u6545c47c-0fed-44eb-bfab-03694941981&title=&width=299) ![image.png](https://cdn.nlark.com/yuque/0/2022/png/189077/1647590197192-cd0071cf-a90c-4882-9b65-4b46bff13ce9.png#clientId=ubd9972cd-765c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=154&id=u67de127d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=308&originWidth=244&originalType=binary&ratio=1&rotation=0&showTitle=false&size=24027&status=done&style=none&taskId=u1a44a2d7-3680-4018-8709-9832cd03ad0&title=&width=122) + +设置后,就会出现“切换设置器”的操作项了 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01jBqcuK1xYRP00WyVx_!!6000000006455-2-tps-598-252.png) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01944xqq1PYihvYQb4v_!!6000000001853-2-tps-244-308.png) #### 开启组件样式设置 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571003600-48ef05cd-dbac-4aad-b7a5-012727fe1c6f.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u467d584c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=772&originWidth=820&originalType=url&ratio=1&rotation=0&showTitle=false&size=128316&status=done&style=none&taskId=ub01cb8bb-e784-485b-b2a6-aead3302c4f&title=) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01EBStyl24EvqJkAdh1_!!6000000007360-2-tps-820-772.png) -```tsx +```javascript { configure: { // ..., @@ -229,12 +241,12 @@ import parse from '@alilc/lowcode-material-parser'; #### 设置组件的默认事件 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571003649-c0da562f-220c-415e-83ea-e07b71c07552.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u7b452a11&margin=%5Bobject%20Object%5D&name=image.png&originHeight=800&originWidth=776&originalType=url&ratio=1&rotation=0&showTitle=false&size=120022&status=done&style=none&taskId=u6805e481-897b-4929-86c8-9321791a21a&title=) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN012gijqt1NERwqF5f6Y_!!6000000001538-2-tps-776-800.png) -```tsx +```javascript { configure: { - // ..., + // ... supports: { events: ['onPressEnter', 'onClear', 'onChange', 'onKeyDown', 'onFocus', 'onBlur'], }, @@ -245,9 +257,9 @@ import parse from '@alilc/lowcode-material-parser'; #### 设置 prop 标题的 tip -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571003618-4a1bb1c4-da39-437b-8510-a121329aa91d.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u7fe57bc7&margin=%5Bobject%20Object%5D&name=image.png&originHeight=176&originWidth=908&originalType=url&ratio=1&rotation=0&showTitle=false&size=39688&status=done&style=none&taskId=u7e9e26eb-a4c3-423c-b7f1-f096d654d4e&title=) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01d8TdsY1jhENsKvwAv_!!6000000004579-2-tps-908-176.png) -```tsx +```javascript { name: 'label', setter: 'StringSetter', @@ -259,7 +271,7 @@ import parse from '@alilc/lowcode-material-parser'; }, tip: { type: 'i18n', - zh_CN: '属性: label | 说明: 标签文本内容', + zh_CN: '属性:label | 说明:标签文本内容', en_US: 'prop: label | description: label content', }, }, @@ -268,72 +280,79 @@ import parse from '@alilc/lowcode-material-parser'; #### 配置 prop 对应 setter 在配置面板的展示方式 -inline:![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571004529-c879ec4c-18af-46fd-8231-4ab80c937399.png#clientId=uad16fa90-b520-4&crop=0.0174&crop=0.0597&crop=0.9933&crop=0.3909&from=paste&height=260&id=u8cdcc718&margin=%5Bobject%20Object%5D&name=image.png&originHeight=266&originWidth=790&originalType=url&ratio=1&rotation=0&showTitle=false&size=40667&status=done&style=none&taskId=u9390a3bb-0290-46c7-b487-7380f162fd0&title=&width=771) +##### inline -```tsx +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01z1sXj420vkP7vbeHj_!!6000000006912-2-tps-790-266.png) + +```javascript { configure: { props: [{ description: '标签文本', - display: 'inline' + display: 'inline', }] } } ``` -block: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571004690-22e7dc4f-db0d-43fe-b837-48ed1145bde7.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=0.996&crop=1&from=paste&height=273&id=ua1717366&margin=%5Bobject%20Object%5D&name=image.png&originHeight=274&originWidth=792&originalType=url&ratio=1&rotation=0&showTitle=false&size=31246&status=done&style=none&taskId=u9e678772-1217-4c64-ac75-c5928b48834&title=&width=789) -```tsx +##### block + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01i3MVKF299xchs6kMX_!!6000000008026-2-tps-792-274.png) + +```javascript { configure: { props: [{ description: '高级', - display: 'block' + display: 'block', }] } } ``` -accordion +##### accordion -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571005189-552ef14d-6043-48fa-a526-4565d42fa581.png#clientId=uad16fa90-b520-4&crop=0&crop=0.0159&crop=1&crop=1&from=paste&height=740&id=u53a75049&margin=%5Bobject%20Object%5D&name=image.png&originHeight=740&originWidth=798&originalType=url&ratio=1&rotation=0&showTitle=false&size=163685&status=done&style=none&taskId=ub42fca77-545e-435f-bafe-88e2b2ddfd1&title=&width=798) -```tsx +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01RePeyy1nhvRiBMm2w_!!6000000005122-2-tps-798-740.png) + +```javascript { configure: { props: [{ description: '表单项配置', - display: 'accordion' + display: 'accordion', }] } } ``` -entry +##### entry -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571005244-fb508efb-a2d8-4064-8ff3-d6140e4c20a1.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u16645b5c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=424&originWidth=796&originalType=url&ratio=1&rotation=0&showTitle=false&size=91418&status=done&style=none&taskId=u38c7b284-f480-4440-baac-9f7c985104f&title=) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571005468-1c7f4b24-4330-45e2-b6c9-5bf5362874b4.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u2fad6ab5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=632&originWidth=794&originalType=url&ratio=1&rotation=0&showTitle=false&size=158094&status=done&style=none&taskId=u7c356adc-4286-46b8-9a2c-d33b4268ddc&title=) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01zkjBak1YY6igYUO1n_!!6000000003070-2-tps-796-424.png) -```tsx + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01lmuRTl1LOPKMnsfLJ_!!6000000001289-2-tps-794-632.png) + +```javascript { configure: { props: [{ description: '风格与样式', - display: 'entry' + display: 'entry', }] } } ``` -plain +##### plain -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571005702-ad979f93-cc47-4c6f-8de7-454cc6305614.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u6aa6d230&margin=%5Bobject%20Object%5D&name=image.png&originHeight=438&originWidth=776&originalType=url&ratio=1&rotation=0&showTitle=false&size=133070&status=done&style=none&taskId=u1db8205a-79ed-4d60-91b4-6e7f5bfaff3&title=) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01G0DOfV1jGD0v049gk_!!6000000004520-2-tps-776-438.png) -```tsx +```javascript { configure: { props: [{ description: '返回上级', - display: 'plain' + display: 'plain', }] } } @@ -343,14 +362,18 @@ plain ### 进阶配置 #### 组件的 children 属性允许传入 ReactNode + 例如有一个如下的 Tab 选项卡组件,每个 TabPane 的 children 都是一个组件 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/189077/1647588145478-fb8b7296-a8ee-4698-9851-846c78de301e.png#clientId=ubd9972cd-765c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=167&id=bi43p&margin=%5Bobject%20Object%5D&name=image.png&originHeight=334&originWidth=2332&originalType=binary&ratio=1&rotation=0&showTitle=false&size=55470&status=done&style=none&taskId=ub8c8b04a-e2e9-4b5d-9be7-c7ad7154864&title=&width=1166) + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01Cu09HV1m8pTucSc7Q_!!6000000004910-2-tps-2332-334.png) + 只需要增加 `isContainer` 配置即可 -```json + +```javascript { - ..., + // ... configure: { - ..., + // ... component: { // 新增,设置组件为容器组件,可拖入组件 isContainer: true, @@ -358,12 +381,14 @@ plain } } ``` + 假设我们希望只允许拖拽 Table、Button 等内容放在 TabPane 里。配置白名单 `childWhitelist` 即可 -```json + +```javascript { - ..., + // ... configure: { - ..., + // ... component: { isContainer: true, nestingRule: { @@ -377,17 +402,20 @@ plain } ``` #### 组件的非 children 属性允许传入 ReactNode + 这就需要使用 `SlotSetter` 开启插槽了,如下面示例,给 Tab 的 title 开启插槽,允许拖拽组件 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/189077/1647590398244-479c820e-3b2f-4d7e-8742-37cf896bcafb.png#clientId=ubd9972cd-765c-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=290&id=Utp8Y&margin=%5Bobject%20Object%5D&name=image.png&originHeight=580&originWidth=3016&originalType=binary&ratio=1&rotation=0&showTitle=false&size=254405&status=done&style=none&taskId=u0c8f777c-3559-455a-b136-c884312bb67&title=&width=1508) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01P77m5m1pKEBXTk9Yt_!!6000000005341-2-tps-3016-580.png) + ```json { - // ..., + // ... configure: { isExtend: true, props: [ { - title: "选项卡标题", - name: "title", + title: '选项卡标题', + name: 'title', setter: { componentName: 'MixedSetter', props: { @@ -397,35 +425,38 @@ plain 'VariableSetter', ], }, - } - } - ] - } + }, + }, + ], + }, } ``` #### 屏蔽组件在设计器中的操作按钮 正常情况下,组件允许复制: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/231502/1647571003626-06d80381-4d97-4d5b-8621-331674832c82.png#clientId=uad16fa90-b520-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=Sp6IN&margin=%5Bobject%20Object%5D&name=image.png&originHeight=226&originWidth=1158&originalType=url&ratio=1&rotation=0&showTitle=false&size=54949&status=done&style=none&taskId=u7e4b2cbe-5acf-467f-950b-ee48deb9502&title=) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01925Nyl1a2AKNQ1XCP_!!6000000003271-2-tps-1158-226.png) + 如果希望禁止组件的复制行为,我们可以这样做: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1647673808399-2708ff56-70d1-4c58-b93b-aa65269fb179.png#clientId=ufbfe731c-4217-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=150&id=A304J&margin=%5Bobject%20Object%5D&name=image.png&originHeight=300&originWidth=1176&originalType=binary&ratio=1&rotation=0&showTitle=false&size=90147&status=done&style=none&taskId=uf8da0392-c584-4d27-b664-95b3e908103&title=&width=588) -```tsx +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01IoLKUu1CXGRb0ileB_!!6000000000090-2-tps-1176-300.png) + +```javascript { configure: { component: { disableBehaviors: ['copy'], - } - } + }, + }, } ``` #### 实现一个 BackwardSetter -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1647674621328-6b0a5afc-eafc-43cc-95ce-bbe00981ac20.png#clientId=ufbfe731c-4217-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=219&id=u9c11597c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=438&originWidth=776&originalType=binary&ratio=1&rotation=0&showTitle=false&size=125336&status=done&style=none&taskId=u01853245-46a8-42dd-9c62-6cdbb909afa&title=&width=388) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01GI4VfT23ga8TUCjIh_!!6000000007285-2-tps-776-438.png) -```tsx +```javascript { name: 'back', title: ' ', @@ -457,16 +488,16 @@ const BackwardSetter: DynamicSetter = (target: SettingTarget) => { - 始终隐藏当前 prop -```tsx +```javascript { // 始终隐藏当前 prop 配置 - condition: () => false + condition: () => false, } ``` - 根据其它 prop 的值展示/隐藏当前 prop -```tsx +```javascript { // direction 为 hoz 则展示当前 prop 配置 condition: (target) => { @@ -477,7 +508,7 @@ const BackwardSetter: DynamicSetter = (target: SettingTarget) => { #### props 联动 -```tsx +```javascript // 根据当前 prop 的值动态设置其它 prop 的值 { name: 'labelAlign', @@ -510,9 +541,9 @@ const BackwardSetter: DynamicSetter = (target: SettingTarget) => { #### 动态 setter 配置 -可以通过 DynamicSetter 传入的 target 获取一些引擎暴露的数据,例如当前有哪些组件被加载到引擎中,将这个数据作为 SelectSetter 的选项,让用户选择: +可以通过 DynamicSetter 传入的 target 获取一些引擎暴露的数据,例如当前有哪些组件被加载到引擎中,将这个数据作为 SelectSetter 的选项,让用户选择: -```tsx +```javascript { setter: (target) => { return { @@ -528,7 +559,7 @@ const BackwardSetter: DynamicSetter = (target: SettingTarget) => { } ), ), - } + }, }; } } diff --git a/docs/docs/guide/expand/editor/partsIntro.md b/docs/docs/guide/expand/editor/partsIntro.md index 6e56ae1e6..174afc37a 100644 --- a/docs/docs/guide/expand/editor/partsIntro.md +++ b/docs/docs/guide/expand/editor/partsIntro.md @@ -1,75 +1,99 @@ --- -title: 利用Parts造物快速使用react组件 +title: 利用 Parts 造物快速使用 react 组件 sidebar_position: 3 --- ## 介绍 -大家在使用[低代码引擎](https://lowcode-engine.cn/)构建低代码应用平台时,遇到的一个主要问题是如何让已有的 React 组件能够快速低成本地接入进来。这个问题拆解下来主要包括两个子问题:1. 如何给已有组件[配置物料描述](https://lowcode-engine.cn/material),2. 如何构建出一个低代码引擎能够识别的资产包(Assets)。 -我们的产品 「[Parts·造物](https://parts.lowcode-engine.cn/)」 可以帮助大家解决这个问题。我们通过在线可视化的方式完成物料描述配置,并且提供一键打包的功能生成引擎可以识别的资产包。 +大家在使用[低代码引擎](https://lowcode-engine.cn/)构建低代码应用平台时,遇到的一个主要问题是如何让已有的 React 组件能够快速低成本地接入进来。这个问题拆解下来主要包括两个子问题: +1. 如何给已有组件[配置物料描述](/site/docs/specs/material-spec), +2. 如何构建出一个低代码引擎能够识别的资产包 (Assets)。 + +我们的产品「[Parts·造物](https://parts.lowcode-engine.cn/)」可以帮助大家解决这个问题。我们通过在线可视化的方式完成物料描述配置,并且提供一键打包的功能生成引擎可以识别的资产包。 ## 导入物料 -首先,我们需要在 [物料管理](https://parts.lowcode-engine.cn/material#/) 页面导入我们需要进行在线物料描述配置的物料。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434800993-0fbf5ed5-63e5-492b-85ab-feafd663ad2d.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=196&id=u918deb34&margin=%5Bobject%20Object%5D&name=image.png&originHeight=342&originWidth=1399&originalType=binary&ratio=1&rotation=0&showTitle=false&size=33102&status=done&style=stroke&taskId=u95c39b84-836c-45f8-aee6-0effc1ccfd1&title=&width=800) +首先,我们需要在 [物料管理](/site/docs/specs/material-spec) 页面导入我们需要进行在线物料描述配置的物料。 +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01IyZdZf1L1VWWU3dnp_!!6000000001239-2-tps-1399-342.png) - 点击列表左上方的 导入已有物料 按钮 -- 在弹框中输入 npm包名 -- 点击 获取包信息 按钮,获取npm包基本信息 +- 在弹框中输入 npm 包名 +- 点击 获取包信息 按钮,获取 npm 包基本信息 - 点击确定,导入成功 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434801003-7bd783f0-8804-445e-b508-8601501dfa60.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u825d698a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=315&originWidth=640&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21969&status=done&style=stroke&taskId=ued992c2e-822b-4c32-81b5-9c9add84954&title=) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN019FwWgs1kqgAXq5UNJ_!!6000000004735-2-tps-640-315.png) ## 配置管理 -第二步:物料导入以后,我们就可以为导入的物料新增[物料描述配置](https://lowcode-engine.cn/material),点击右侧的组件配置开始配置。 +第二步:物料导入以后,我们就可以为导入的物料新增[物料描述配置](/site/docs/specs/material-spec),点击右侧的组件配置开始配置。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434801125-979e6348-b78a-47b4-bb2e-fa8f1bb4ff90.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=216&id=u7fb954eb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=261&originWidth=965&originalType=binary&ratio=1&rotation=0&showTitle=false&size=15305&status=done&style=stroke&taskId=uc1e18ffd-fe76-4fe4-83a4-c907f308b14&title=&width=800) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01kqymdB1nkDQclPk7F_!!6000000005127-2-tps-965-261.png) ### 新增配置 - 点击配置管理右上角的 新增配置 - 选择组件的版本号 - - 填写组件路径,一般和 npm 包的 package.json 里的 main 字段相同 (如果填写错误,后面会渲染不出来) + - 填写组件路径,一般和 npm 包的 package.json 里的 main 字段相同(如果填写错误,后面会渲染不出来) - 描述字段用于给这份配置增加一些备注信息。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434801095-1957da7f-5d9d-4c17-a762-c576bf0f763f.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=380&id=u9ad0ec47&margin=%5Bobject%20Object%5D&name=image.png&originHeight=418&originWidth=596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=26130&status=done&style=stroke&taskId=u2b592498-195a-4fec-9853-ec5c3b95ef7&title=&width=541.8181700745893) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01i78OhT1cKbVWnXRNu_!!6000000003582-2-tps-596-418.png) + 为了降低配置成本,第一次新增配置的时候会自动解析组件代码,生成一份初始化组件物料描述。所以需要等待片刻,用于代码解析。解析完成后,点击配置按钮即可进入在线配置界面。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434801053-1a48b598-e987-4cd5-b657-030d345e0a99.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=193&id=ud384a13d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=232&originWidth=963&originalType=binary&ratio=1&rotation=0&showTitle=false&size=23541&status=done&style=stroke&taskId=ud2efc4d3-6d52-4b77-adbd-14dd5ee4b11&title=&width=800) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01R24mTl1tJY3oJ5DCi_!!6000000005881-2-tps-963-232.png) + ### 组件描述配置 操作界面如下,接下来讲具体的配置流程 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434802081-6546d0f5-19da-475e-8dec-93ea324cc4e3.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=522&id=uf73c4753&margin=%5Bobject%20Object%5D&name=image.png&originHeight=938&originWidth=1438&originalType=binary&ratio=1&rotation=0&showTitle=false&size=111984&status=done&style=stroke&taskId=u0ce37d2b-8ca3-48b5-ac67-8fb461d17b5&title=&width=800) -#### 新增组件 -如果新增配置的过程中,代码自动解析失败或者解析出来的组件列表不满足开发要求,我们可以点击左侧组件列表插件 新增 按钮,添加新的组件,具体的字段描述可以参考提示内容,以 [react-color](https://github.com/casesandberg/react-color) 为例: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434802087-eaf4e2f1-2028-4415-b696-9788a6b2d0ed.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=560&id=u4341eb1b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1005&originWidth=1436&originalType=binary&ratio=1&rotation=0&showTitle=false&size=147918&status=done&style=stroke&taskId=ud921b52d-1961-4be9-b4ec-77d6364b213&title=&width=800) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434802555-bbd14a55-89a6-42cd-a4b3-76c98febf00c.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=472&id=u06e0b78f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=704&originWidth=1193&originalType=binary&ratio=1&rotation=0&showTitle=false&size=240470&status=done&style=stroke&taskId=u77603c5d-9d14-4379-86d2-deb4deaba50&title=&width=800) -#### 给组件增加物料描述 -选中刚刚新增的BlockPicker组件,然后给它增加描述: -- 打开左侧 Sette r面板 -- 按照组件的属性拖入需要 Setter 类型 (如图中组件的width属性,拖入数字Setter) -- 各种 Setter 的介绍可以参看这篇文档:[https://www.yuque.com/lce/doc/grfylu](https://www.yuque.com/lce/doc/grfylu) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01XjSW9I1u662raRg8E_!!6000000005987-2-tps-1438-938.png) + +#### 新增组件 + +如果新增配置的过程中,代码自动解析失败或者解析出来的组件列表不满足开发要求,我们可以点击左侧组件列表插件 新增 按钮,添加新的组件,具体的字段描述可以参考提示内容,以 [react-color](https://github.com/casesandberg/react-color) 为例: + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01A9VFfQ1m9kH2Qliz4_!!6000000004912-2-tps-1436-1005.png) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01klci7y1IUPflKpeVB_!!6000000000896-2-tps-1193-704.png) +#### 给组件增加物料描述 + +选中刚刚新增的 BlockPicker 组件,然后给它增加描述: + +- 打开左侧 Setter 面板 +- 按照组件的属性拖入需要 Setter 类型(如图中组件的 width 属性,拖入数字 Setter) +- 各种 Setter 的介绍可以参看这篇文档:[预置设置器列表](/site/docs/guide/appendix/setters) - 配置属性的基本信息(如图所示) - 配置完成后点击右上角的保存 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434802458-b0fb8a0e-307e-458c-a9f9-af3d2697024c.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=539&id=udeb647da&margin=%5Bobject%20Object%5D&name=image.png&originHeight=967&originWidth=1434&originalType=binary&ratio=1&rotation=0&showTitle=false&size=158958&status=done&style=stroke&taskId=u2950484f-659b-4643-af5e-75d04f14346&title=&width=800) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434802443-cdc533bf-1b08-4c11-b3d2-7cfd7fe0a5dd.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=311&id=uaaaa88fb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=360&originWidth=925&originalType=binary&ratio=1&rotation=0&showTitle=false&size=64587&status=done&style=stroke&taskId=u7139e8ef-eee3-468b-833c-a42d8f3cb56&title=&width=800) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01gxLKBp1RaDEMPS54O_!!6000000002127-2-tps-1434-967.png) + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01uReCQ825yYuwIfj2J_!!6000000007595-2-tps-925-360.png) + #### 高级配置(属性联动) -举个栗子:如图所示,如果期望 “设置器” 这个配置项的值 “被修改”的时候,下面的 “默认值” 跟着变化。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434803379-009a9783-ec24-4a08-8a46-55ae775ce7ba.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=520&id=u005ad05e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=572&originWidth=371&originalType=binary&ratio=1&rotation=0&showTitle=false&size=96588&status=done&style=stroke&taskId=u97330f9d-6728-4a05-a842-55df114ccee&title=&width=337.27271996253796) + +举个栗子:如图所示,如果期望“设置器”这个配置项的值“被修改”的时候,下面的“默认值”跟着变化。 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01bg7X571bpSZdnXTBW_!!6000000003514-2-tps-371-572.png) + 如何使用 -组件的属性配置目前支持3个基本的联动函数: -- 显示状态:返回true | false,如果返回true,表示组件配置显示,否则配置时不显示 -- 获取值:当调用该配置节点的getValue方法时触发的方法 -- 值变化:当调用该配置节点的setValue方法时触发的方法 +组件的属性配置目前支持 3 个基本的联动函数: + +- 显示状态:返回 true | false,如果返回 true,表示组件配置显示,否则配置时不显示 +- 获取值:当调用该配置节点的 getValue 方法时触发的方法 +- 值变化:当调用该配置节点的 setValue 方法时触发的方法 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN018ZJAJO21q57TdWfjM_!!6000000007035-2-tps-316-142.png) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434803522-85aed489-4e00-4787-a496-54cc73e25bc5.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=129&id=u0a782260&margin=%5Bobject%20Object%5D&name=image.png&originHeight=142&originWidth=316&originalType=binary&ratio=1&rotation=0&showTitle=false&size=29086&status=done&style=stroke&taskId=u95864da5-4ccf-4e4b-b903-1ce26af4f66&title=&width=287.2727210462587) 方法的第一个参数都是当前配置节点的对象,常用到的有以下几个: -- getValue(): 获取当前节点的值,如果当前节点是子节点的话,否则为undefined +- getValue(): 获取当前节点的值,如果当前节点是子节点的话,否则为 undefined - setValue(): 设置当前节点的值,如果当前节点是子节点的话 - parent: 当前节点的父节点 -- getPropValue(propName): 父节点获取子节点的属性值,propName为子节点的属性名称 -- setPropValue(propName, value): 父节点设置子节点的属性值,propName为子节点的属性名称, value 为设置的值 -- getConfig: 获取当前节点的配置,如title、setter等 +- getPropValue(propName): 父节点获取子节点的属性值,propName 为子节点的属性名称 +- setPropValue(propName, value): 父节点设置子节点的属性值,propName 为子节点的属性名称,value 为设置的值 +- getConfig: 获取当前节点的配置,如 title、setter 等 + + #### 调试物料描述 -点击右上角的预览按钮,开始调试我们刚刚配置的属性,如果是组件的首次预览,会有一段组件构建的过程(构建出umd包的过程),构建完成后就可以调试我们的配置了。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434804408-717e49bd-26b3-4a28-b3e5-bd1d67cdab00.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=209&id=ucf92cc3e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=373&originWidth=1431&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46363&status=done&style=stroke&taskId=u501edca5-bbef-4fde-b341-b42c28b125a&title=&width=800) + +点击右上角的预览按钮,开始调试我们刚刚配置的属性,如果是组件的首次预览,会有一段组件构建的过程(构建出 umd 包的过程),构建完成后就可以调试我们的配置了。 + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN012biqEn1uGAl650nb2_!!6000000006009-2-tps-1431-373.png) + #### 发布物料描述 物料描述调试没问题后,就可以到项目中去使用了,使用前需要先发布物料描述 @@ -77,24 +101,32 @@ sidebar_position: 3 - 选择需要发布的组件 - 点击确定发布完成 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434804305-276f03e2-4dd2-41e9-9375-1c3bd0c7092a.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=410&id=uf879e7fd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=734&originWidth=1431&originalType=binary&ratio=1&rotation=0&showTitle=false&size=103858&status=done&style=stroke&taskId=udc267585-ffb7-4247-b1f5-b7aca386e10&title=&width=800) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01uwa8RH1QDwM7FN31k_!!6000000001943-2-tps-1431-734.png) + ## 资产包构建 + 第三步:物料描述发布完成后,接下来我们就需要构建出可用的资产包用于低代码应用中。 + #### 资产包构建 - 选择需要构建的组件 - 点击构建资产包按钮 - 选择刚刚的物料描述配置 -- 开始构建,构建完成后你将得到一份json文件(里面包含了物料描述和umd包),就可以到项目中使用了 +- 开始构建,构建完成后你将得到一份 json 文件(里面包含了物料描述和 umd 包),就可以到项目中使用了 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01Oc73aw1TH5vlJx9oj_!!6000000002356-2-tps-1431-770.png) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434804769-6f6f60f1-9ee3-4561-972d-610f0616576e.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=430&id=ue119fa2b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=770&originWidth=1431&originalType=binary&ratio=1&rotation=0&showTitle=false&size=93492&status=done&style=stroke&taskId=ubfd97421-964b-4823-adc8-b056a588924&title=&width=800) #### 资产包使用 -**方式一、在 **[**lowcode-demo**](https://github.com/alibaba/lowcode-demo)**中直接引用,可直接替换demo中原来的资产包文件:** -例如,在basic-fusion demo中,直接用你的资产包文件替换文件[assets.json](https://github.com/alibaba/lowcode-demo/blob/main/src/scenarios/basic-fusion/assets.json),即可快速使用自己的物料了。 + +**方式一、在 **[**lowcode-demo**](https://github.com/alibaba/lowcode-demo)**中直接引用,可直接替换 demo 中原来的资产包文件:** + +例如,在 basic-fusion demo 中,直接用你的资产包文件替换文件[assets.json](https://github.com/alibaba/lowcode-demo/blob/main/demo-basic-fusion/src/services/assets.json),即可快速使用自己的物料了。 + **方式二、将新的资产包内容和现有的资产包内容融合:** -将上面构建完成的资产包与你项目中的[assets.json文件](https://github.com/alibaba/lowcode-demo/blob/main/src/scenarios/basic-fusion/assets.json)合并,主要合并packages 和 components -- packages中是构建好的umd包 -- components中是上面配置好的[物料描述](https://lowcode-engine.cn/material),你也可以在基础上二次加工 +将上面构建完成的资产包与你项目中的[assets.json 文件](https://github.com/alibaba/lowcode-demo/blob/main/demo-basic-fusion/src/services/assets.json)合并,主要合并 packages 和 components。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/12718919/1652434804944-860abc0c-057c-46d5-a6e5-8d33fde8a762.png#clientId=u0f780a28-b8dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=676&id=u5499b1c9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=744&originWidth=1140&originalType=binary&ratio=1&rotation=0&showTitle=false&size=116233&status=done&style=stroke&taskId=u7be27934-77ce-4dd7-a406-1d402acef2c&title=&width=1036.36361390106) +- packages 中是构建好的 umd 包; +- components 中是上面配置好的[物料描述](https://lowcode-engine.cn/material),你也可以在基础上二次加工; + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01m7QkDN1P7hL86mjyH_!!6000000001794-2-tps-1140-744.png) diff --git a/docs/docs/guide/expand/editor/pluginContextMenu.md b/docs/docs/guide/expand/editor/pluginContextMenu.md index 603aa09c0..9dc75ce65 100644 --- a/docs/docs/guide/expand/editor/pluginContextMenu.md +++ b/docs/docs/guide/expand/editor/pluginContextMenu.md @@ -1,11 +1,13 @@ --- -title: 插件扩展-编排扩展 +title: 插件扩展 - 编排扩展 sidebar_position: 6 --- ## 场景一:扩展选中节点操作项 ### 增加节点操作项 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1647693318212-173890bc-b0b5-437b-9802-4b1fd9f74c5a.png#clientId=u2eca2bba-d284-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=254&id=u55228975&margin=%5Bobject%20Object%5D&name=image.png&originHeight=292&originWidth=1240&originalType=binary&ratio=1&rotation=0&showTitle=false&size=38144&status=done&style=none&taskId=u426cac9f-24ad-4d06-adbe-faca1896eaa&title=&width=1080) +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01J7PrJc1S86XNDBIFQ_!!6000000002201-2-tps-1240-292.png) + 选中节点后,在选中框的右上角有操作按钮,编排模块默认实现了查看组件直系父节点、复制节点和删除节点按钮外,还可以通过相关 API 来扩展更多操作,如下代码: + ```typescript import { plugins } from '@alilc/lowcode-engine'; import { Icon, Message } from '@alifd/next'; @@ -30,14 +32,18 @@ const addHelloAction = (ctx: ILowCodePluginContext) => { }); } }; -} +}; addHelloAction.pluginName = 'addHelloAction'; await plugins.register(addHelloAction); ``` + **_效果如下:_** -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1647694920149-b8d9a534-b943-45d2-b67e-cc42b906f827.png#clientId=u2eca2bba-d284-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=282&id=ua20a09c8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=343&originWidth=1315&originalType=binary&ratio=1&rotation=0&showTitle=false&size=35131&status=done&style=none&taskId=u3f47b55d-15ff-495c-8615-31e3ccb0222&title=&width=1080) -具体 API 参考:[https://www.yuque.com/lce/doc/mu7lml#ieJzi](https://www.yuque.com/lce/doc/mu7lml#ieJzi) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01O8W2H61ybw2b7K5nV_!!6000000006598-2-tps-1315-343.png) + +具体 API 参考:[API 文档](/site/docs/api/material#addbuiltincomponentaction) ### 删除节点操作项 + ```typescript import { plugins } from '@alilc/lowcode-engine'; @@ -48,22 +54,26 @@ const removeCopyAction = (ctx: ILowCodePluginContext) => { removeBuiltinComponentAction('copy'); } } -} +}; removeCopyAction.pluginName = 'removeCopyAction'; await plugins.register(removeCopyAction); ``` + **_效果如下:_** -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1647695353667-e22bef51-3c6a-4b6a-87d2-c144ddb68115.png#clientId=u2eca2bba-d284-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=237&id=ufa1f9434&margin=%5Bobject%20Object%5D&name=image.png&originHeight=290&originWidth=1319&originalType=binary&ratio=1&rotation=0&showTitle=false&size=22495&status=done&style=none&taskId=u73e01acc-96e8-45e7-9d42-a31edca193e&title=&width=1080) -具体 API 参考:[https://www.yuque.com/lce/doc/mu7lml#va9mb](https://www.yuque.com/lce/doc/mu7lml#va9mb) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01Gfnu8J1O7PTRdoFQZ_!!6000000001658-2-tps-1319-290.png) + +具体 API 参考:[API 文档](/site/docs/api/material#removebuiltincomponentaction) + ## 实际案例 ### 区块管理 - 仓库地址:[https://github.com/alibaba/lowcode-plugins](https://github.com/alibaba/lowcode-plugins) - 具体代码:[https://github.com/alibaba/lowcode-plugins/tree/main/packages/action-block](https://github.com/alibaba/lowcode-plugins/tree/main/packages/action-block) - 直播回放: - - [低代码引擎项目实战(9)-区块管理(1)-保存为区块](https://www.bilibili.com/video/BV1YF411M7RK/) - - [低代码引擎项目实战(10)-区块管理-区块面板](https://www.bilibili.com/video/BV1FB4y1S7tu/) - - [阿里巴巴低代码引擎项目实战(11)-区块管理- ICON优化](https://www.bilibili.com/video/BV1zr4y1H7Km/) - - [阿里巴巴低代码引擎项目实战(11)-区块管理-自动截图](https://www.bilibili.com/video/BV1GZ4y117VH/) - - [阿里巴巴低代码引擎项目实战(11)-区块管理-样式优化](https://www.bilibili.com/video/BV1Pi4y1S7ZT/) - - [阿里低代码引擎项目实战(12)-区块管理(完结)-给引擎插件提个 PR](https://www.bilibili.com/video/BV1hB4y1277o/) + - [低代码引擎项目实战 (9)-区块管理 (1)-保存为区块](https://www.bilibili.com/video/BV1YF411M7RK/) + - [低代码引擎项目实战 (10)-区块管理 - 区块面板](https://www.bilibili.com/video/BV1FB4y1S7tu/) + - [阿里巴巴低代码引擎项目实战 (11)-区块管理 - ICON 优化](https://www.bilibili.com/video/BV1zr4y1H7Km/) + - [阿里巴巴低代码引擎项目实战 (11)-区块管理 - 自动截图](https://www.bilibili.com/video/BV1GZ4y117VH/) + - [阿里巴巴低代码引擎项目实战 (11)-区块管理 - 样式优化](https://www.bilibili.com/video/BV1Pi4y1S7ZT/) + - [阿里低代码引擎项目实战 (12)-区块管理 (完结)-给引擎插件提个 PR](https://www.bilibili.com/video/BV1hB4y1277o/) diff --git a/docs/docs/guide/expand/editor/pluginWidget.md b/docs/docs/guide/expand/editor/pluginWidget.md index fd63167e9..f1494bf2a 100644 --- a/docs/docs/guide/expand/editor/pluginWidget.md +++ b/docs/docs/guide/expand/editor/pluginWidget.md @@ -1,16 +1,21 @@ --- -title: 插件扩展-面板扩展 +title: 插件扩展 - 面板扩展 sidebar_position: 5 --- ## 插件简述 + 插件功能赋予低代码引擎更高的灵活性,低代码引擎的生态提供了一些官方的插件,但是无法满足所有人的需求,所以提供了强大的插件定制功能。 + 通过定制插件,在和低代码引擎解耦的基础上,我们可以和引擎核心模块进行交互,从而满足多样化的功能。不仅可以自定义插件的 UI,还可以实现一些非 UI 的逻辑: -1)调用编辑器框架提供的 API 进行编辑器操作或者 schema 操作; -2)通过插件类的生命周期函数实现一些插件初始化的逻辑; -3)通过实现监听编辑器内的消息实现特定的切片逻辑(例如面板打开、面板关闭等) -> 本文仅介绍面板层面的扩展,编辑器插件层面的扩展可以参考 "插件扩展 - 编排扩展" 章节。 + +1. 调用编辑器框架提供的 API 进行编辑器操作或者 schema 操作; +2. 通过插件类的生命周期函数实现一些插件初始化的逻辑; +3. 通过实现监听编辑器内的消息实现特定的切片逻辑(例如面板打开、面板关闭等); + +> 本文仅介绍面板层面的扩展,编辑器插件层面的扩展可以参考 ["插件扩展 - 编排扩展"](./pluginContextMenu.md) 章节。 ## 注册插件 API + ```typescript import { plugins, ILowCodePluginContext } from '@alilc/lowcode-engine'; @@ -38,42 +43,67 @@ pluginA.pluginName = 'pluginA'; plugins.register(pluginA, { key: 'test' }); ``` -> 如果您想了解抽取出来的插件如何封装成为一个 npm 包并提供给社区,可以参考“扩展低代码应用 - 扩展低代码编辑器 - 低代码插件脚手架”章节。 -插件系统的详细设计,可参考“参与低代码引擎开发 - 低代码引擎设计文档 - 插件”章节。 + +> 如果您想了解抽取出来的插件如何封装成为一个 npm 包并提供给社区,可以参考[“低代码生态脚手架 & 调试机制”](./cli)章节。 ## 面板插件配置说明 + 面板插件是作用于设计器的,主要是通过按钮、图标等展示在设计器的骨架中。设计器的骨架我们分为下面的几个区域,而我们的插件大多数都是作用于这几个区域的。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644393006009-165e36cd-fa7b-4ee0-b3e3-dc7ba9d80d55.png#averageHue=%237cac76&clientId=u45843f36-7f71-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=608&id=u9e018f89&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1080&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=149463&status=done&style=stroke&taskId=u74f952e4-c783-47ae-b11c-be48d3c52be&title=&width=1080) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644320581783-b8fcd29c-45c2-48df-be2c-7101b12474e3.png#averageHue=%23edf6d4&clientId=u221f0bd4-c19e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=580&id=ixlrN&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1648&originWidth=3068&originalType=binary&ratio=1&rotation=0&showTitle=false&size=165621&status=done&style=stroke&taskId=u030d9faf-015f-4475-b34a-ba1fbf8868b&title=&width=1080) + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01Bkfm9E1MQWmBWeIOh_!!6000000001429-2-tps-1920-1080.png) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01y05ZHC1Gix0p4nXxH_!!6000000000657-2-tps-3068-1648.png) + ### 展示区域 area #### topArea -展示在设计器的顶部区域,常见的相关区域的插件主要是: -1)注册设计器 Logo; -2)设计器操作回退和撤销按钮; -3)全局操作按钮,例如:保存、预览等; + +展示在设计器的顶部区域,常见的相关区域的插件主要是:、 + +1. 注册设计器 Logo; +2. 设计器操作回退和撤销按钮; +3. 全局操作按钮,例如:保存、预览等; + #### leftArea + 左侧区域的展示形式大多数是 Icon 和对应的面板,通过点击 Icon 可以展示对应的面板并隐藏其他的面板。 + 该区域相关插件的主要有: -1)大纲树展示,展示该设计器设计页面的大纲。 -2)组件库,展示注册到设计器中的组件,点击之后,可以从组件库面板中拖拽到设计器的画布中。 -3)数据源面板 -4)JS 等代码面板。 + +1. 大纲树展示,展示该设计器设计页面的大纲。 +2. 组件库,展示注册到设计器中的组件,点击之后,可以从组件库面板中拖拽到设计器的画布中。 +3. 数据源面板 +4. JS 等代码面板。 + 可以发现,这个区域的面板大多数操作时是不需要同时并存的,且交互比较复杂的,需要一个更整块的区域来进行操作。 #### centerArea + 画布区域,由于画布大多数是展示作用,所以一般扩展的种类比较少。常见的扩展有: -1)画布大小修改 -2)物料选中扩展区域修改 + +1. 画布大小修改 +2. 物料选中扩展区域修改 + #### rightArea + 右侧区域,常用于组件的配置。常见的扩展有:统一处理组件的配置项,例如统一删除某一个配置项,统一添加某一个配置项的。 + #### toolbar + 跟 topArea 类似,按需放置面板插件~ + ### 展示形式 type + #### PanelDock + PanelDock 是以面板的形式展示在设计器的左侧区域的。其中主要有两个部分组成,一个是图标,一个是面板。当点击图标时可以控制面板的显示和隐藏。 + 下图是组件库插件的展示效果。 -![Feb-08-2022 19-44-15.gif](https://cdn.nlark.com/yuque/0/2022/gif/242652/1644320663827-ee9c54a1-f684-40e2-8a6b-875103d04b31.gif#averageHue=%23eaf6d2&clientId=u221f0bd4-c19e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=555&id=u5292d9cc&margin=%5Bobject%20Object%5D&name=Feb-08-2022%2019-44-15.gif&originHeight=790&originWidth=1536&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1381641&status=done&style=stroke&taskId=ub28a13a4-3d80-4a02-bcaa-cc9d6127243&title=&width=1080) + +![Feb-08-2022 19-44-15.gif](https://img.alicdn.com/imgextra/i3/O1CN01XCrv5Q1hR5BgsyAiq_!!6000000004273-1-tps-1536-790.gif) + 其中右上角可以进行固定,可以对弹出的宽度做设定 + 接入可以参考代码 + ```javascript import { skeleton } from "@alilc/lowcode-engine"; @@ -85,7 +115,7 @@ skeleton.add({ props: { align: "left", icon: "wenjian", - description: "JS面板", + description: "JS 面板", }, panelProps: { floatable: true, // 是否可浮动 @@ -93,15 +123,20 @@ skeleton.add({ hideTitleBar: false, maxHeight: 800, maxWidth: 1200, - title: "JS面板", + title: "JS 面板", width: 600, }, }); ``` + #### Widget + Widget 形式是直接渲染在当前编辑器的对应位置上。如 demo 中在设计器顶部的所有组件都是这种展现形式。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644320068765-47efc836-30c2-452f-8104-b98b1ea3533d.png#averageHue=%23fefefb&clientId=u221f0bd4-c19e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=51&id=u68c58cad&margin=%5Bobject%20Object%5D&name=image.png&originHeight=94&originWidth=1988&originalType=binary&ratio=1&rotation=0&showTitle=false&size=58410&status=done&style=stroke&taskId=u4eadd643-2e63-4be7-8736-b27b9c82b81&title=&width=1080) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01h89p5W1pfknnzwMqS_!!6000000005388-2-tps-1988-94.png) + 接入可以参考代码: + ```javascript import {skeleton} from "@alilc/lowcode-engine"; // 注册 logo 面板 @@ -110,7 +145,7 @@ skeleton.add({ type: "Widget", name: "logo", content: Logo, // Widget 组件实例 - contentProps: { // Widget 插件props + contentProps: { // Widget 插件 props logo: "https://img.alicdn.com/tfs/TB1_SocGkT2gK0jSZFkXXcIQFXa-66-66.png", href: "/", @@ -121,21 +156,24 @@ skeleton.add({ }, }); ``` + #### Dock -一个图标的表现形式,可以用于语言切换、跳转到外部链接、打开一个 widget 等场景 + +一个图标的表现形式,可以用于语言切换、跳转到外部链接、打开一个 widget 等场景。 + ```javascript import { skeleton } from "@alilc/lowcode-engine"; skeleton.add({ - area: "leftArea", - type: "Dock", - name: "opener", + area: 'leftArea', + type: 'Dock', + name: 'opener', content: Opener, // Widget 组件实例 - contentProps: { // Widget 插件props - xxx: "1", + contentProps: { // Widget 插件 props + xxx: '1', }, props: { - align: "bottom", + align: 'bottom', }, onClick: function() { // 打开外部链接 @@ -145,26 +183,31 @@ skeleton.add({ } }); ``` + #### Panel + 一般不建议单独使用,通过 PanelDock 使用~ + ## 实际案例 + ### 页面管理面板 - 仓库地址:[https://github.com/mark-ck/lowcode-portal](https://github.com/mark-ck/lowcode-portal) - 具体代码:[https://github.com/mark-ck/lowcode-portal/blob/master/src/plugins/pages-plugin/index.tsx](https://github.com/mark-ck/lowcode-portal/blob/master/src/plugins/pages-plugin/index.tsx) - 直播回放: - - [低代码引擎项目实战(4)-自定义插件-页面管理](https://www.bilibili.com/video/BV17a411i73f/) - - [低代码引擎项目实战(4)-自定义插件-页面管理-后端](https://www.bilibili.com/video/BV1uZ4y1U7Ly/) - - [低代码引擎项目实战(4)-自定义插件-页面管理-前端](https://www.bilibili.com/video/BV1Yq4y1a74P/) - - [低代码引擎项目实战(4)-自定义插件-页面管理-完结](https://www.bilibili.com/video/BV13Y4y1e7EV/) + - [低代码引擎项目实战 (4)-自定义插件 - 页面管理](https://www.bilibili.com/video/BV17a411i73f/) + - [低代码引擎项目实战 (4)-自定义插件 - 页面管理 - 后端](https://www.bilibili.com/video/BV1uZ4y1U7Ly/) + - [低代码引擎项目实战 (4)-自定义插件 - 页面管理 - 前端](https://www.bilibili.com/video/BV1Yq4y1a74P/) + - [低代码引擎项目实战 (4)-自定义插件 - 页面管理 - 完结](https://www.bilibili.com/video/BV13Y4y1e7EV/) + ### 区块面板 - 仓库地址:[https://github.com/alibaba/lowcode-plugins](https://github.com/alibaba/lowcode-plugins) - 具体代码:[https://github.com/alibaba/lowcode-plugins/tree/main/packages/plugin-block](https://github.com/alibaba/lowcode-plugins/tree/main/packages/plugin-block) - 直播回放: - - [低代码引擎项目实战(9)-区块管理(1)-保存为区块](https://www.bilibili.com/video/BV1YF411M7RK/) - - [低代码引擎项目实战(10)-区块管理-区块面板](https://www.bilibili.com/video/BV1FB4y1S7tu/) - - [阿里巴巴低代码引擎项目实战(11)-区块管理- ICON优化](https://www.bilibili.com/video/BV1zr4y1H7Km/) - - [阿里巴巴低代码引擎项目实战(11)-区块管理-自动截图](https://www.bilibili.com/video/BV1GZ4y117VH/) - - [阿里巴巴低代码引擎项目实战(11)-区块管理-样式优化](https://www.bilibili.com/video/BV1Pi4y1S7ZT/) - - [阿里低代码引擎项目实战(12)-区块管理(完结)-给引擎插件提个 PR](https://www.bilibili.com/video/BV1hB4y1277o/) + - [低代码引擎项目实战 (9)-区块管理 (1)-保存为区块](https://www.bilibili.com/video/BV1YF411M7RK/) + - [低代码引擎项目实战 (10)-区块管理 - 区块面板](https://www.bilibili.com/video/BV1FB4y1S7tu/) + - [阿里巴巴低代码引擎项目实战 (11)-区块管理 - ICON 优化](https://www.bilibili.com/video/BV1zr4y1H7Km/) + - [阿里巴巴低代码引擎项目实战 (11)-区块管理 - 自动截图](https://www.bilibili.com/video/BV1GZ4y117VH/) + - [阿里巴巴低代码引擎项目实战 (11)-区块管理 - 样式优化](https://www.bilibili.com/video/BV1Pi4y1S7ZT/) + - [阿里低代码引擎项目实战 (12)-区块管理 (完结)-给引擎插件提个 PR](https://www.bilibili.com/video/BV1hB4y1277o/) \ No newline at end of file diff --git a/docs/docs/guide/expand/editor/setter.md b/docs/docs/guide/expand/editor/setter.md index 846c60b3e..6a720374f 100644 --- a/docs/docs/guide/expand/editor/setter.md +++ b/docs/docs/guide/expand/editor/setter.md @@ -3,24 +3,37 @@ title: 设置器扩展 sidebar_position: 4 --- ## 设置器简述 + 设置器主要用于低代码组件属性值的设置,顾名思义叫"设置器",又称为 Setter。由于组件的属性有各种类型,需要有与之对应的设置器支持,每一个设置器对应一个值的类型。 + ### 设计器展示位置 + 设置器展示在编辑器的右边区域,如下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644387351052-0be9546e-9e46-41ff-bbb4-a1effe650d7f.png#clientId=u39aebc41-90a1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=487&id=pi5XH&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1730&originWidth=3836&originalType=binary&ratio=1&rotation=0&showTitle=false&size=947162&status=done&style=stroke&taskId=u4d4deed8-40f5-40a6-b20d-d092c90775c&title=&width=1080) + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01F0yBV91jNzkZKLzvJ_!!6000000004537-2-tps-3836-1730.png) + 其中包含四类设置器: - 属性:展示该物料常规的属性 - 样式:展示该物料样式的属性 - 事件:如果该物料有声明事件,则会出现事件面板,用于绑定事件。 - 高级:两个逻辑相关的属性,**条件渲染**和**循环** + ### 设置器类型 + 上述区域中是有多项设置器的,对于一个组件来说,每一项配置都对应一个设置器,比如我们的配置是一个文本,我们需要的是文本设置器,我们需要配置的是数字,我们需要的就是数字设置器。 下图中的标题和按钮类型配置就分别是文本设置器和下拉框设置器。 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1644387350762-7337e729-53e9-4a6c-8da1-8f17260e1347.png#clientId=u39aebc41-90a1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=744&id=ztLvk&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1460&originWidth=2120&originalType=binary&ratio=1&rotation=0&showTitle=false&size=489840&status=done&style=stroke&taskId=u7375a322-b6c8-43f1-a096-07b204656aa&title=&width=1080) + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01uMd1zQ20fiXawR4IU_!!6000000006877-2-tps-2120-1460.png) + 我们提供了常用的设置器作为内置设置器,也提供了定制能力帮助大家开发特定需求的设置器。 + ## 为物料配置设置器 -我们提供了[常用的设置器](https://www.yuque.com/lce/doc/oc220p?view=doc_embed&from=kb&from=kb&outline=1&title=1)作为内置设置器。 + +我们提供了[常用的设置器](/site/docs/guide/appendix/setters)作为内置设置器。 + 我们可以将目标组件的属性值类型值配置到物料资源配置文件中: + ```json { "componentName": "Message", @@ -35,10 +48,15 @@ sidebar_position: 4 } } ``` + props 字段是入料模块扫描自动填入的类型,用户可以通过 configure 节点进行配置通过 override 节点对属性的声明重新定义,setter 就是注册在引擎中的 setter。 + 为物料配置引擎内置的 setter 时,均可以使用对应 setter 的高级功能,对应功能参考“全部内置设置器”章节下的对应 setter 文章。 -**_对高级功能的配置如下:_** -例如我们需要在NumberSetter中配置units属性,可以在asset.json中声明 + +### 对高级功能的配置如下: + +例如我们需要在 NumberSetter 中配置 units 属性,可以在 asset.json 中声明。 + ```json "configure": { "component": { @@ -81,27 +99,35 @@ props 字段是入料模块扫描自动填入的类型,用户可以通过 conf } }, ``` + ## 自定义设置器 ### 编写 AltStringSetter + 我们编写一个简单的 Setter,它的功能如下: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2553587/1644764687180-0121f0c0-d113-4907-a86d-e4f3a04ff221.png#clientId=ucb27c83c-48cf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=45&id=u32dc8cd0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=90&originWidth=720&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17539&status=done&style=stroke&taskId=u0f886bda-a93e-4b10-ad7e-9ba9a38a3fb&title=&width=360) -**_代码如下:_** -```typescript + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01fQ4GLd1RzrPSdULiw_!!6000000002183-2-tps-720-90.png) + +**代码如下:** +```tsx import * as React from "react"; import { Input } from "@alifd/next"; - import "./index.scss"; + interface AltStringSetterProps { // 当前值 value: string; // 默认值 defaultValue: string; - // setter唯一输出 + // setter 唯一输出 onChange: (val: string) => void; // AltStringSetter 特殊配置 placeholder: string; } + export default class AltStringSetter extends React.PureComponent { + // 声明 Setter 的 title + static displayName = 'AltStringSetter'; + componentDidMount() { const { onChange, value, defaultValue } = this.props; if (value == undefined && defaultValue) { @@ -109,9 +135,6 @@ export default class AltStringSetter extends React.PureComponent { @@ -140,41 +166,52 @@ bindEvent = (eventName) => { } componentWillUnmount() { - // setter是以实例为单位的,每个setter注销的时候需要把事件也注销掉,避免事件池过多 - event.off(`${this.emitEventName}.bindEvent`, this.bindEvent) + // setter 是以实例为单位的,每个 setter 注销的时候需要把事件也注销掉,避免事件池过多 + event.off(`${this.emitEventName}.bindEvent`, this.bindEvent); } ``` + 在 B setter 中触发事件,来完成通信: + ```javascript import { event } from '@alilc/lowcode-engine'; bindFunction = () => { const { field, value } = this.props; - // 这里展示的和插件进行通信,事件规则是插件名+方法 + // 这里展示的和插件进行通信,事件规则是插件名 + 方法 event.emit('eventBindDialog.openDialog', field.name, this.emitEventName); } ``` + #### 修改同级 props 的其他属性值 + setter 本身只影响其中一个 props 的值,如果需要影响其他组件的 props 的值,需要使用 field 的 props: -```json + +```javascript bindFunction = () => { const { field, value } = this.props; const propsField = field.parent; - // 获取同级其他属性showJump的值 + // 获取同级其他属性 showJump 的值 const otherValue = propsField.getPropValue('showJump'); - // set同级其他属性showJump的值 + // set 同级其他属性 showJump 的值 propsField.setPropValue('showJump', false); } ``` + ### 注册 AltStringSetter + 我们需要在低代码引擎中注册 Setter,这样就可以通过 AltStringSetter 的名字在物料中使用了。 + ```typescript import AltStringSetter from './AltStringSetter'; const registerSetter = window.AliLowCodeEngine.setters.registerSetter; registerSetter('AltStringSetter', AltStringSetter); ``` + ### 物料中使用 + 我们需要将目标组件的属性值类型值配置到物料资源配置文件中,其中核心配置如下: + ```json { "props": [ @@ -185,7 +222,9 @@ registerSetter('AltStringSetter', AltStringSetter); ] } ``` + 在物料中的相关配置如下: + ```json { "componentName": "Message", @@ -199,4 +238,4 @@ registerSetter('AltStringSetter', AltStringSetter); ] } } -``` +``` \ No newline at end of file diff --git a/docs/docs/guide/expand/editor/summary.md b/docs/docs/guide/expand/editor/summary.md index e8487213c..bcb1e2b71 100644 --- a/docs/docs/guide/expand/editor/summary.md +++ b/docs/docs/guide/expand/editor/summary.md @@ -5,9 +5,9 @@ sidebar_position: 0 ## 扩展点简述 我们可以从 Demo 的项目中看到页面中有很多的区块: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643447049972-e324320a-7f97-4e48-bef3-a4c5d2b06517.png#clientId=udea0fe9a-4e7e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1080&id=rGr7U&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2160&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=518455&status=done&style=none&taskId=u872d1136-0f18-41b3-900d-710e9fc9eea&title=&width=1920) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01WkdvNi1TamxZblYFA_!!6000000002399-2-tps-3840-2160.png) 这些功能点背后都是可扩展项目,如下图所示: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643447052089-8e340da7-3c2c-4a88-9ed8-c89516dccf75.png#clientId=udea0fe9a-4e7e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=957&id=lL1sN&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1914&originWidth=3838&originalType=binary&ratio=1&rotation=0&showTitle=false&size=538736&status=done&style=none&taskId=u43e8a14e-0d52-4a22-bd19-e5083814daf&title=&width=1919) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01wZLOzm24hmnMTwXdF_!!6000000007423-2-tps-3838-1914.png) - 插件定制:可以配置低代码编辑器的功能和面板 - 物料定制:可以配置能够拖入的物料 @@ -16,7 +16,7 @@ sidebar_position: 0 我们从可扩展项目的视角,可以把低代码引擎架构理解为下图: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643447051959-7abb91ea-44af-46e0-b73a-dd2127648b32.png#clientId=udea0fe9a-4e7e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1080&id=M07o7&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2160&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=779021&status=done&style=none&taskId=u640e4616-d38d-45fb-a560-e4a98cd1605&title=&width=1920) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01fhZ3Q11hwE7RwSq7g_!!6000000004341-2-tps-3840-2160.png) (注:引擎内核中大量数据交互的细节被简化,这张图仅仅强调编辑器和外部扩展的交互) ## 配置扩展点 @@ -24,17 +24,17 @@ sidebar_position: 0 ### 配置物料 通过配置注入物料,这里的配置是物料中心根据物料资产包协议生成的,后面“物料扩展”章节会有详细说明。 ```typescript -import { material } from '@alilc/lowcode-engine' +import { material } from '@alilc/lowcode-engine'; // 假设您已把物料配置在本地 -import assets from './assets.json' +import assets from './assets.json'; // 静态加载 assets -material.setAssets(assets) +material.setAssets(assets); ``` 也可以通过异步加载物料中心上的物料。 ```typescript -import { ILowCodePluginContext, material, plugins } from '@alilc/lowcode-engine' +import { ILowCodePluginContext, material, plugins } from '@alilc/lowcode-engine'; // 动态加载 assets plugins.register((ctx: ILowCodePluginContext) => { @@ -51,27 +51,27 @@ plugins.register((ctx: ILowCodePluginContext) => { } }, } -}).catch(err => console.error(err)) +}).catch(err => console.error(err)); ``` ### 配置插件 可以通过 npm 包的方式引入社区插件,配置如下所示: ```typescript -import { ILowCodePluginContext, plugins } from '@alilc/lowcode-engine' -import PluginIssueTracker from '@alilc/lowcode-plugin-issue-tracker' +import { ILowCodePluginContext, plugins } from '@alilc/lowcode-engine'; +import PluginIssueTracker from '@alilc/lowcode-plugin-issue-tracker'; // 注册一个提 issue 组件到您的编辑器中,方位默认在左栏下侧 plugins.register(PluginIssueTracker) - .catch(err => console.error(err)) + .catch(err => console.error(err)); ``` 后续“插件扩展”章节会详细说明。 ### 配置设置器 低代码引擎默认内置了设置器(详见“配置设置器”章节)。您可以通过 npm 包的方式引入自定义的设置器,配置如下所示: ```typescript -import { setters } from '@alilc/lowcode-engine' +import { setters } from '@alilc/lowcode-engine'; // 假设您自定义了一个 setter -import MuxMonacoEditorSetter from './components/setters/MuxMonacoEditorSetter' +import MuxMonacoEditorSetter from './components/setters/MuxMonacoEditorSetter'; // 注册设置器 setters.registerSetter({ @@ -83,8 +83,8 @@ setters.registerSetter({ return typeof v === 'string' }, }, -}) +}); ``` 后续“设置器扩展”章节会详细说明。 -> 本章节所有可扩展配置内容在 demo 中均可找到:[https://github.com/alibaba/lowcode-demo/blob/main/src/universal/plugin.tsx](https://github.com/alibaba/lowcode-demo/blob/main/src/universal/plugin.tsx) +> 本章节所有可扩展配置内容在 demo 中均可找到:[https://github.com/alibaba/lowcode-demo/tree/main/demo-general](https://github.com/alibaba/lowcode-demo/tree/main/demo-general) diff --git a/docs/docs/guide/expand/runtime/codeGeneration.md b/docs/docs/guide/expand/runtime/codeGeneration.md index e1d9dc3d8..5cb63c9f6 100644 --- a/docs/docs/guide/expand/runtime/codeGeneration.md +++ b/docs/docs/guide/expand/runtime/codeGeneration.md @@ -29,8 +29,8 @@ sidebar_position: 1 ### 2) 通过设计器插件快速体验 -1. 安装依赖: `npm install --save @alilc/lowcode-plugin-code-generator` -2. 注册插件: +1. 安装依赖: `npm install --save @alilc/lowcode-plugin-code-generator` +2. 注册插件: ```typescript import { plugins } from '@alilc/lowcode-engine'; @@ -49,14 +49,14 @@ await plugins.register(CodeGenPlugin, { disableCodeGenActionBtn: true }); 此代码生成器一开始就是为服务端出码设计的,你可以直接这样来在 node.js 环境中使用: -1. 安装依赖: `npm install --save @alilc/lowcode-code-generator` -2. 引入代码生成器: +1. 安装依赖: `npm install --save @alilc/lowcode-code-generator` +2. 引入代码生成器: ```javascript import CodeGenerator from '@alilc/lowcode-code-generator'; ``` -3. 创建项目构建器: +3. 创建项目构建器: ```javascript const projectBuilder = CodeGenerator.solutions.icejs(); @@ -70,7 +70,7 @@ const project = await projectBuilder.generateProject( ); ``` -5. 将生成的代码写入到磁盘中(也可以生成一个 zip 包) +5. 将生成的代码写入到磁盘中 (也可以生成一个 zip 包) ```javascript // 写入磁盘 @@ -94,17 +94,17 @@ await CodeGenerator.publishers.zip().publish({ 随着现在电脑性能和浏览器技术的发展,出码其实已经不必非得在服务端做了,借助于 Web Worker 特性,可以在浏览器中进行出码: -1. 安装依赖: `npm install --save @alilc/lowcode-code-generator` -2. 引入代码生成器: +1. 安装依赖: `npm install --save @alilc/lowcode-code-generator` +2. 引入代码生成器: ```javascript import * as CodeGenerator from '@alilc/lowcode-code-generator/standalone-loader'; ``` -3. 【可选】提前初始化代码生成器: +3. 【可选】提前初始化代码生成器: ```javascript -// 提前初始化下,这样后面用的时候更快(这个 init 内部会提前准备好创建 worker 的一些资源) +// 提前初始化下,这样后面用的时候更快 (这个 init 内部会提前准备好创建 worker 的一些资源) await CodeGenerator.init(); ``` @@ -116,17 +116,17 @@ const result = await CodeGenerator.generateCode({ schema, // 编排搭建出来的 schema }); -console.log(result); // 出码结果(默认是递归结构描述的,可以传 flattenResult: true 以生成扁平结构的结果) +console.log(result); // 出码结果 (默认是递归结构描述的,可以传 flattenResult: true 以生成扁平结构的结果) ``` 注:一般来说在浏览器中出码适合做即时预览功能。 ### 5)自定义出码 前端框架灵活多变,默认内置的出码方案很难满足所有人的需求,好在此代码生成器支持非常灵活的插件机制 -- 内置功能大多都是通过插件完成的(在 `src/plugins`下),比如: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/263300/1644824565650-584c2be5-4be3-4c9a-96d9-e27990111b0b.png#averageHue=%232b2b2e&clientId=u8b65d964-7bef-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=376&id=u3e0a61a8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=376&originWidth=457&originalType=binary&ratio=1&rotation=0&showTitle=false&size=151355&status=done&style=none&taskId=ueef52494-2e18-45a2-8409-7f68e200f63&title=&width=457) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01CEl2Hq1omnH0UCyGF_!!6000000005268-2-tps-457-376.png) 所以您可以通过添加自己的插件或替换掉默认内置的插件来实现您的自定义功能。 为了方便自定义出码方案,出码模块还提供自定义出码方案的脚手架功能,即执行下面脚本即可生成一个自定义出码方案: ```shell npx @alilc/lowcode-code-generator init-solution ``` -里面内置了一个示例的插件(在 `src/plugins/example.ts`中),您可以根据注释引导来完善相关插件,从而组合生成您的专属出码方案(`src/index.ts`)。您所生成的出码方案可以发布成 NPM 包,从而能按上文 1~4 中的使用方案进行使用。 +里面内置了一个示例的插件 (在 `src/plugins/example.ts`中),您可以根据注释引导来完善相关插件,从而组合生成您的专属出码方案 (`src/index.ts`)。您所生成的出码方案可以发布成 NPM 包,从而能按上文 1~4 中的使用方案进行使用。 diff --git a/docs/docs/guide/expand/runtime/renderer.md b/docs/docs/guide/expand/runtime/renderer.md index 20cc35bae..71eb75598 100644 --- a/docs/docs/guide/expand/runtime/renderer.md +++ b/docs/docs/guide/expand/runtime/renderer.md @@ -43,7 +43,7 @@ ReactDOM.render(( - rax-renderer:npm 包替换为 @alilc/lowcode-rax-renderer #### ### 项目使用示例 -> 设计器 demo:[https://lowcode-engine.cn/demo](https://lowcode-engine.cn/demo) +> [设计器 demo](https://lowcode-engine.cn/demo/demo-general/index.html) > 项目代码完整示例:[https://github.com/alibaba/lowcode-demo](https://github.com/alibaba/lowcode-demo) **step 1:在设计器中获取组件列表** @@ -310,13 +310,13 @@ designMode 属性主要在搭建场景中使用,主要有以下作用: ### suspended -渲染模块是否挂起,当设置为 `true` 时,渲染模块最外层容器的 `shouldComponentUpdate` 将始终返回false,在下钻编辑或者多引擎渲染的场景会用到该参数。 +渲染模块是否挂起,当设置为 `true` 时,渲染模块最外层容器的 `shouldComponentUpdate`将始终返回 false,在下钻编辑或者多引擎渲染的场景会用到该参数。 ### onCompGetRef 组件 ref 的回调,在搭建场景下编排模块可以根据该回调获取组件实例并实现生命周期注入或者组件 DOM 操作等功能,回调函数主要包含两个参数: -- `schema`: 当前组件的 schema 模型结构 +- `schema`:当前组件的 schema 模型结构 - `ref`:当前组件的 ref 实例 ### onCompGetCtx diff --git a/docs/docs/guide/quickStart/demo.md b/docs/docs/guide/quickStart/demo.md index 536c8efab..a05a42486 100644 --- a/docs/docs/guide/quickStart/demo.md +++ b/docs/docs/guide/quickStart/demo.md @@ -2,46 +2,55 @@ title: 试用低代码引擎 Demo sidebar_position: 1 --- -# 访问地址 +## 访问地址 低代码引擎的 Demo 可以通过如下永久链接访问到: -[https://lowcode-engine.cn/demo](https://lowcode-engine.cn/demo) +[设计器 demo](https://lowcode-engine.cn/demo/demo-general/index.html) > 注意我们会经常更新 demo,所以您可以通过上述链接得到最新版地址。 -# 低代码引擎 Demo 功能概览 +## 低代码引擎 Demo 功能概览 -我们可以从 Demo 的项目中看到页面中有很多的区块:
![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643447049972-e324320a-7f97-4e48-bef3-a4c5d2b06517.png#clientId=udea0fe9a-4e7e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1080&id=rGr7U&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2160&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=518455&status=done&style=none&taskId=u872d1136-0f18-41b3-900d-710e9fc9eea&title=&width=1920)
它主要包含这些功能点:
![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1643447051103-de714f27-ec70-4982-b180-e1ebe444b0fe.png#clientId=udea0fe9a-4e7e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1080&id=lD0YM&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2160&originWidth=3840&originalType=binary&ratio=1&rotation=0&showTitle=false&size=616472&status=done&style=none&taskId=u61de17fa-6df0-43c8-9171-96388fda32e&title=&width=1920) +我们可以从 Demo 的项目中看到页面中有很多的区块: -- 顶部:操作区 - - 右侧:撤回和重做、保存到本地、重置页面、预览、异步加载资源 -- 左侧:面板与操作区 - - 大纲面板:可以调整页面内的组件树结构 - - 物料面板:可以查找组件,并在此拖动组件到编辑器画布中 - - 源码面板:可以编辑页面级别的 JavaScript 代码和 CSS 配置 - - 提交 Issue:可以给引擎开发提 bug - - Schema 编辑:可以编辑页面的底层数据 - - 中英文切换:可以切换编辑器的语言 -- 中部:可视化页面编辑画布区域 - - 点击组件在右侧面板中能够显示出对应组件的属性配置选项 - - 拖拽修改组件的排列顺序 - - 将组件拖拽到容器类型的组件中 - - 复制组件:点击组件右上角的复制按钮 - - 删除组件:点击组件右上角的 X 或者直接使用 `Delete` 键 -- 右侧:组件级别配置 - - 选中的组件:从页面开始一直到当前选中的组件位置,点击对应的名称可以切换到对应的组件上 - - 选中组件的配置:当前组件的大类目选项,根据组件类型不同,包含如下子类目: - - 属性:组件的基础属性值设置 - - 样式:组件的样式配置 - - 事件:绑定组件对外暴露的事件 - - 高级:循环、条件渲染与 key 设置 +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01vlxdTD28c4JZcebbf_!!6000000007952-2-tps-3840-2160.png) -# 深入使用低代码引擎 Demo +它主要包含这些功能点: + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01QITHRY1sQaWzlvJv9_!!6000000005761-2-tps-3840-2160.png) + +### 顶部:操作区 + +- 右侧:撤回和重做、保存到本地、重置页面、预览、异步加载资源 +### 左侧:面板与操作区 +- 大纲面板:可以调整页面内的组件树结构 +- 物料面板:可以查找组件,并在此拖动组件到编辑器画布中 +- 源码面板:可以编辑页面级别的 JavaScript 代码和 CSS 配置 +- 提交 Issue:可以给引擎开发提 bug +- Schema 编辑:可以编辑页面的底层数据 +- 中英文切换:可以切换编辑器的语言 + +### 中部:可视化页面编辑画布区域 +- 点击组件在右侧面板中能够显示出对应组件的属性配置选项 +- 拖拽修改组件的排列顺序 +- 将组件拖拽到容器类型的组件中 +- 复制组件:点击组件右上角的复制按钮 +- 删除组件:点击组件右上角的 X 或者直接使用 `Delete` 键 + +### 右侧:组件级别配置 +- 选中的组件:从页面开始一直到当前选中的组件位置,点击对应的名称可以切换到对应的组件上 +- 选中组件的配置:当前组件的大类目选项,根据组件类型不同,包含如下子类目: + - 属性:组件的基础属性值设置 + - 样式:组件的样式配置 + - 事件:绑定组件对外暴露的事件 + - 高级:循环、条件渲染与 key 设置 + +## 深入使用低代码引擎 Demo 我们在低代码引擎 Demo 中直接内置了产品使用文档,对常见场景中的使用进行了向导,它的入口如下: -![image.png](https://cdn.nlark.com/yuque/0/2022/png/242652/1647163471895-a12d0f5d-e09e-462d-bd0b-b633c64afb15.png#clientId=uecc3752b-3539-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=825&id=u86d6fa24&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1650&originWidth=3070&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1040703&status=done&style=none&taskId=u54aeddda-78e0-4259-b184-d06e2dba10b&title=&width=1535) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01YU2LYS29YEbuLTtLL_!!6000000008079-2-tps-3070-1650.png) -如果暂时没有看到对应的产品使用文档,可以通过此永久链接直接访问:[https://www.yuque.com/lce/usage](https://www.yuque.com/lce/usage) +如果暂时没有看到对应的产品使用文档,可以通过此永久链接直接访问:[https://lowcode-engine.cn/site/docs/demoUsage/intro](https://lowcode-engine.cn/site/docs/demoUsage/intro) diff --git a/docs/docs/guide/quickStart/intro.md b/docs/docs/guide/quickStart/intro.md index 67750b2a9..661f5912f 100644 --- a/docs/docs/guide/quickStart/intro.md +++ b/docs/docs/guide/quickStart/intro.md @@ -18,7 +18,7 @@ sidebar_position: 0 - **可视化页面搭建**,通过简单的拖拽完成应用页面开发,对前端技能没有要求或不需要特别专业的了解; - **可视化模型设计**,与业务相关的数据存储变得更容易理解,甚至大多数简单场景可以做到表单即模型,模型字段的类型更加业务化; - **可视化流程设计**,不管是业务流程还是审批流程,都可以通过简单的点线连接来进行配置; -- **可视化报表及数据分析**,BI数据分析能力成为标配,随时随地通过拖拽选择来定义自定义分析报表; +- **可视化报表及数据分析**,BI 数据分析能力成为标配,随时随地通过拖拽选择来定义自定义分析报表; - **可视化服务与数据开放、集成**,具备与其他系统互联互通的配置; - **权限、角色设置标准化和业务化**,通过策略规则配置来将数据、操作的权限进行精细化管理; - **无需关心服务器、数据库等底层运维、计算设施设备、网络等等复杂技术概念**,具备安全、性能的统一解决方案,开发者只需要专注于业务本身; @@ -35,14 +35,14 @@ sidebar_position: 0 **低代码设计器** 现如今低代码平台越来越多,而每一个低代码平台中都会有的一个能力就是搭建和配置页面、模块的页面,这个页面我们称为设计器。例如,下图是中后台低代码平台的设计器。 -![image.png](https://img.alicdn.com/imgextra/i4/O1CN01LunuQh23b5NtP8k86_!!6000000007273-2-tps-1682-969.png?originHeight=1914&originWidth=3838&originalType=binary&ratio=1&rotation=0&showTitle=false&size=538736&status=done&style=stroke&taskId=u9a19d4d1-4d87-4b4e-b7cc-3aedfb00aaa&title=&width=1080) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01sXuwkK1j8sg4S53Dx_!!6000000004504-2-tps-1682-969.png) 设计器承载着低代码平台的核心功能,包括入料、编排、组件配置、画布渲染等等。由于其功能多,打磨精细难,也是低代码平台建设最耗时的地方。 **定制扩展能力** 什么是扩展能力呢,一方面我们可以快速拥有一份标准的低代码设计器,另外一方面如果有业务独特的功能需要,我们可以不用看它的源码、不用关心其实现,可以使用 API、插件等方式快速完成能力的开发。 而低代码引擎对于设计器的扩展能力支持基本上覆盖了低代码设计器的所有功能点。下图是针对标准的设计器提供了扩展功能的区域。 -![](https://cdn.nlark.com/yuque/0/2022/png/242652/1643446752531-8b1493d4-ea8a-463b-9631-6bb4fc681719.png#clientId=u2b839b63-1827-4&crop=0&crop=0&crop=1&crop=1&from=drop&height=539&id=ucff2881c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1914&originWidth=3838&originalType=binary&ratio=1&rotation=0&showTitle=false&size=538736&status=done&style=stroke&taskId=u9a19d4d1-4d87-4b4e-b7cc-3aedfb00aaa&title=&width=1080) +![](https://img.alicdn.com/imgextra/i1/O1CN01ZVgAE31wltQ4BVnCe_!!6000000006349-2-tps-3838-1914.png) **低代码设计器研发框架** 低代码引擎的核心是设计器,通过扩展、周边生态等可以产出各式各样的设计器。它不是一套可以适合所有人的低代码平台,而是帮助低代码平台的开发者,快速生产低代码平台的工具。 diff --git a/docs/docs/guide/quickStart/start.md b/docs/docs/guide/quickStart/start.md index 001e4e789..13f30159e 100644 --- a/docs/docs/guide/quickStart/start.md +++ b/docs/docs/guide/quickStart/start.md @@ -2,70 +2,83 @@ sidebar_position: 2 title: 快速开始 --- -# 前置知识 -我们假定你已经对 HTML 和 JavaScript 都比较熟悉了。即便你之前使用其他编程语言,你也可以跟上这篇教程的。除此之外,我们假定你也已经熟悉了一些编程的概念,例如,函数、对象、数组,以及 class 的一些内容。
如果你想回顾一下 JavaScript,你可以阅读[这篇教程](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript)。注意,我们也用到了一些 ES6(较新的 JavaScript 版本)的特性。在这篇教程里,我们主要使用了[箭头函数(arrow functions)](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions)、[class](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes)、[let](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let) 语句和 [const](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/const) 语句。你可以使用 [Babel REPL](https://babeljs.io/repl/#?presets=react&code_lz=MYewdgzgLgBApgGzgWzmWBeGAeAFgRgD4AJRBEAGhgHcQAnBAEwEJsB6AwgbgChRJY_KAEMAlmDh0YWRiGABXVOgB0AczhQAokiVQAQgE8AkowAUAcjogQUcwEpeAJTjDgUACIB5ALLK6aRklTRBQ0KCohMQk6Bx4gA) 在线预览 ES6 的编译结果。 +## 前置知识 +我们假定你已经对 HTML 和 JavaScript 都比较熟悉了。即便你之前使用其他编程语言,你也可以跟上这篇教程的。除此之外,我们假定你也已经熟悉了一些编程的概念,例如,函数、对象、数组,以及 class 的一些内容。 -# 环境准备 -## WSL(Window 电脑) +如果你想回顾一下 JavaScript,你可以阅读[这篇教程](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript)。注意,我们也用到了一些 ES6(较新的 JavaScript 版本)的特性。在这篇教程里,我们主要使用了[箭头函数(arrow functions)](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions)、[class](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes)、[let](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let) 语句和 [const](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/const) 语句。你可以使用 [Babel REPL](https://babeljs.io/repl/#?presets=react&code_lz=MYewdgzgLgBApgGzgWzmWBeGAeAFgRgD4AJRBEAGhgHcQAnBAEwEJsB6AwgbgChRJY_KAEMAlmDh0YWRiGABXVOgB0AczhQAokiVQAQgE8AkowAUAcjogQUcwEpeAJTjDgUACIB5ALLK6aRklTRBQ0KCohMQk6Bx4gA) 在线预览 ES6 的编译结果。 + +## 环境准备 +### WSL(Window 电脑) Window 环境需要使用 WSL 在 windows 下进行低代码引擎相关的开发。安装教程 ➡️ [WSL 安装教程](https://docs.microsoft.com/zh-cn/windows/wsl/install)。
**对于 Window 环境来说,之后所有需要执行命令的操作都是在 WSL 终端执行的。** -## Node -node 版本推荐 14.17.0。 +### Node +node 版本推荐 16.18.0。 -### 查看 Node 版本 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660653856191-128d8e3f-9636-4b73-94ab-c03cf6965365.png#clientId=ubcf63daf-5747-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=35&id=u44a9af04&margin=%5Bobject%20Object%5D&name=image.png&originHeight=70&originWidth=238&originalType=binary&ratio=1&rotation=0&showTitle=false&size=11948&status=done&style=none&taskId=udb616117-a27c-409d-9e1c-1b89931a714&title=&width=119) +#### 查看 Node 版本 +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01oCZKNz290LIu8YUTk_!!6000000008005-2-tps-238-70.png) -### 变更 node 版本 +#### 通过 n 来管理 node 版本 可以安装 [n](https://www.npmjs.com/package/n) 来管理和变更 node 版本。 -#### 安装 -```json +##### 安装 n +```bash npm install -g n ``` -#### 变更 node 版本 -```json +##### 变更 node 版本 +```bash n 14.17.0 ``` -## React +### React 低代码引擎的扩展能力都是基于 React 来研发的,在继续阅读之前最好有一定的 React 基础,React 学习教程 ➡️ [React 快速开始教程](https://zh-hans.reactjs.org/docs/getting-started.html)。 -## 下载 Demo +### 下载 Demo 可以前往 github(https://github.com/alibaba/lowcode-demo)将 DEMO 下载到本地。 -### git clone -#### HTTPS +#### git clone +##### HTTPS 需要使用到 git 工具 -```json +```bash git clone https://github.com/alibaba/lowcode-demo.git ``` -#### SSH +##### SSH 需要配置 SSH key,如果没有配置可以 -```json +```bash git clone git@github.com:alibaba/lowcode-demo.git ``` -### 下载 Zip 包 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660653725650-ab734ba4-64a7-4801-9d2f-5c496879054f.png#clientId=ubcf63daf-5747-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=897&id=uc1b07458&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1794&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1306258&status=done&style=stroke&taskId=ubaa4eb12-0e87-464e-b3da-306ed9685b7&title=&width=1792) +#### 下载 Zip 包 +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01iYC7E11phaNwLFUrN_!!6000000005392-2-tps-3584-1794.png) -## 安装依赖 -在 lowcode-demo 目录下执行: -```json +### 选择一个 demo 项目 +在 以 `demo-general` 为例: +```bash +cd demo-general +``` + +### 安装依赖 +在 `lowcode-demo/demo-general` 目录下执行: +```bash npm install ``` -## 启动 demo -在 lowcode-demo 目录下执行: -```json +### 启动 demo +在 `lowcode-demo/demo-general` 目录下执行: +```bash npm run start ``` 之后就可以通过 [http://localhost:5556/](http://localhost:5556/) 来访问我们的 DEMO 了。 -# 认识 Demo -我们的 Demo 是一个**低代码平台的设计器**。它是一个低代码平台中最重要的一环,用户可以在这里通过拖拽、配置、写代码等等来完成一个页面的开发。由于用户的人群不同、场景不同、诉求不同等等,这个页面的功能就会有所差异。
这里记住**设计器**这个词,它描述的就是下面的这个页面,后面我们会经常看到它。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660654189055-45fd0c7e-75cb-4072-a4d4-7cf244405c7d.png#clientId=ubcf63daf-5747-4&crop=0&crop=0.008&crop=1&crop=1&from=paste&height=904&id=LBi2j&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1808&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=763122&status=done&style=stroke&taskId=u82753ad5-3b5d-43b2-b309-a99c2a7bb24&title=&width=1792) -## 场景介绍 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660654738730-490fc94a-8b42-4c48-b21e-4c0694416b07.png#clientId=ubcf63daf-5747-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=903&id=ub700edc2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1806&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=802013&status=done&style=stroke&taskId=u317bff98-636d-402a-98f2-f9e0b08293b&title=&width=1792) +## 认识 Demo +我们的 Demo 是一个**低代码平台的设计器**。它是一个低代码平台中最重要的一环,用户可以在这里通过拖拽、配置、写代码等等来完成一个页面的开发。由于用户的人群不同、场景不同、诉求不同等等,这个页面的功能就会有所差异。 + +这里记住**设计器**这个词,它描述的就是下面的这个页面,后面我们会经常看到它。 +![image.png](https://img.alicdn.com/imgextra/i1/O1CN014nYXgF20pKrQIG2zV_!!6000000006898-2-tps-3584-1808.png) + +### 场景介绍 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01nnP60l1dqUhUiNSx6_!!6000000003787-2-tps-2852-1156.png) Demo 根据**不同的设计器所需要的物料不同**,分为了下面的 8 个场景: @@ -75,30 +88,39 @@ Demo 根据**不同的设计器所需要的物料不同**,分为了下面的 8 - 基础 antd 组件 - 自定义初始化引擎 - 扩展节点操作项 -- 基于next实现的高级表单低代码物料 +- 基于 next 实现的高级表单低代码物料 - antd 高级组件 + formily 表单组件 可以点开不同的场景,看看他们使用的物料。 +![](https://img.alicdn.com/imgextra/i1/O1CN01EU2jRN1wUwlal17WK_!!6000000006312-2-tps-3110-1974.png) -## 目录介绍 -仓库下的 src/scenarios 目录就对应刚刚介绍的场景。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660655237007-fddd8534-d4ed-4a25-ba2f-f335f8ac3c36.png#clientId=ubcf63daf-5747-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=348&id=ubf68019d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=696&originWidth=696&originalType=binary&ratio=1&rotation=0&showTitle=false&size=148777&status=done&style=stroke&taskId=u68648c51-7648-494e-bd41-4f29fb144f9&title=&width=348) +### 目录介绍 +仓库下每个 demo-xxx-xxx 目录都是一个可独立运行的 demo 工程,分别对应到刚刚介绍的场景。 -不同场景的目录结构实际上都是类似的,这里我们主要介绍一下综合场景的目录结构即可。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660655399364-b40d206a-977d-4000-9be1-681823f8a995.png#clientId=ubcf63daf-5747-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1010&id=ub727a7fa&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2020&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1373541&status=done&style=stroke&taskId=ue55dc86f-375d-4c7f-a63f-d5208683035&title=&width=1792)
综合场景目录下只有一个文件,这个文件做了几个事情: +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01ztxv5Y1mJozBsLdni_!!6000000004934-2-tps-696-958.png) -- 通过 plugins.register 注册「切换场景」的插件,也就是上面介绍的切换场景的功能。 -- 通过 registerPlugins 注册更多的插件: - - ManualPlugin:增加弹出「低代码产品使用文档」按钮 - - Inject:支持调试功能 - - registerRefProp:支持给每个组件注入 ref - - ... -- 通过 init 初始化低代码设计器 +不同场景的目录结构实际上都是类似的,这里我们主要介绍一下综合场景的目录结构即可。 -做了这些事情之后,我们的低代码设计器就已经有了基本的能力了。也就是最开始我们看到的这样。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660654189055-45fd0c7e-75cb-4072-a4d4-7cf244405c7d.png#clientId=ubcf63daf-5747-4&crop=0&crop=0.008&crop=1&crop=1&from=paste&height=904&id=MZdfk&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1808&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=763122&status=done&style=stroke&taskId=u82753ad5-3b5d-43b2-b309-a99c2a7bb24&title=&width=1792) +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01A50oW522S5zg2eDUH_!!6000000007118-2-tps-732-1384.png) + +介绍下其中主要的内容 +- 设计器入口文件 `source/index.ts` 这个文件做了下述几个事情: + - 通过 plugins.register 注册各种插件,包括官方插件 (已发布 npm 包形式的插件) 和 `plugins` 目录下内置的示例插件 + - 通过 init 初始化低代码设计器 +- plugins 目录,存放的都是示例插件,方便用户从中看到一个插件是如何实现的 +- services 目录,模拟数据请求、提供默认 schema、默认资产包等,此目录下内容在真是项目中应替换成真是的与服务端交互的服务。 +- 预览页面入口文件 `preview.tsx` + +剩下的各位看官可以通过源码来进一步了解。 + +做了这些事情之后,我们的低代码设计器就已经有了基本的能力了。也就是最开始我们看到的这样。 + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01YJVcOd1PiL1am6bz2_!!6000000001874-2-tps-3248-1970.png) 接下来我们就根据我们自己的诉求通过对设计器进行扩展,改动成我们需要的设计器功能。 -# 开发一个插件 -## 方式1:在 DEMO 中直接新增插件 -![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660656064139-8da57c37-7e0b-4e8d-9f2d-8ea86d5af134.png#clientId=ubcf63daf-5747-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=280&id=uc7f75c37&margin=%5Bobject%20Object%5D&name=image.png&originHeight=560&originWidth=820&originalType=binary&ratio=1&rotation=0&showTitle=false&size=125690&status=done&style=stroke&taskId=u53c07118-a2ca-4a77-a27f-3b2b20085ac&title=&width=410) +## 开发一个插件 +### 方式 1:在 DEMO 中直接新增插件 +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01pXpSRs1QvRyut2EE3_!!6000000002038-2-tps-718-1144.png) 可以在 demo/sample-plugins 直接新增插件,这里我新增的插件目录是 plugin-demo。并且新增了 index.tsx 文件,将下面的代码粘贴到 index.tsx 中。 ```javascript @@ -153,64 +175,94 @@ LowcodePluginPluginDemo.meta = { export default LowcodePluginPluginDemo; ``` -在 src/scenarios/index/index.ts 中新增下面代码
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660656497051-49e08633-2d78-428c-becc-c282905cdb90.png#clientId=ubcf63daf-5747-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1010&id=u426edc7b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2020&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1458910&status=done&style=stroke&taskId=uf1e42399-caf7-4d82-a797-698fa730486&title=&width=1792) +在 src/index.ts 中新增下面代码 -这样在我们的设计器中就新增了一个 Demo 面板。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660656566260-86dfed37-60d0-45ca-967e-5df8ea7a34d0.png#clientId=ubcf63daf-5747-4&crop=0&crop=0.0053&crop=1&crop=1&from=paste&height=903&id=u17565cd3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1806&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=734227&status=done&style=stroke&taskId=u5dbe00f3-447b-451e-ac48-9b02281afc3&title=&width=1792) -## 方式2:在新的仓库下开发插件 +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01pNTr4N1kldoYZRzgI_!!6000000004724-2-tps-1976-1250.png) + +这样在我们的设计器中就新增了一个 Demo 面板。 + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01wtPIOV1TQiFLz5Vkf_!!6000000002377-2-tps-3584-1806.png) +### 方式 2:在新的仓库下开发插件 初始化 -```json +```bash npm init @alilc/element your-plugin-name ``` -选择设计器插件(plugin)
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660702297326-ccfe60f9-ee22-4a24-a293-26351d107663.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=107&id=ub2bf5248&margin=%5Bobject%20Object%5D&name=image.png&originHeight=214&originWidth=730&originalType=binary&ratio=1&rotation=0&showTitle=false&size=82091&status=done&style=stroke&taskId=u82628265-73f0-4d57-b4ba-1b18600a1f0&title=&width=365) +选择设计器插件(plugin) -根据操作完善信息
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660702439529-867a893f-f27a-4e48-8a5a-ee45aa97e355.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=109&id=uc9b09fec&margin=%5Bobject%20Object%5D&name=image.png&originHeight=218&originWidth=866&originalType=binary&ratio=1&rotation=0&showTitle=false&size=102705&status=done&style=stroke&taskId=ue4a95f21-43d3-4da8-9c0e-b21dfe239bf&title=&width=433) +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01sA6sYW1tijqVeQCuq_!!6000000005936-2-tps-730-214.png) -插件项目就初始化完成了
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660702464438-3d7e07eb-53c7-417c-9e6d-06fdf9acfb86.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=280&id=u0ee65b4e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2020&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1197702&status=done&style=stroke&taskId=u5f9fdae3-1adc-4b02-969c-5c43c3d4c9c&title=&width=496) +根据操作完善信息 + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01BzM1Jb1RcxbiJ0tJi_!!6000000002133-2-tps-866-218.png) + +插件项目就初始化完成了 + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01iVIAXD1XVWsOdKttI_!!6000000002929-2-tps-3584-2020.png) 在插件项目下安装依赖 -```json +```bash npm install ``` 启动项目 -```json +```bash npm run start ``` -调试项目
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660705712773-f2446689-2b5f-42e7-9e85-30857270dfbb.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=346&id=u448649c5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1936&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=757713&status=done&style=stroke&taskId=u0b617456-826e-4993-951e-303da417172&title=&width=641) +调试项目 -在 Demo 中调试项目
在 build.json 下面新增 "inject": true,就可以在 [https://lowcode-engine.cn/demo/index.html?debug](https://lowcode-engine.cn/demo/index.html?debug) 页面下进行调试了。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660705860117-5a11a5fa-9215-4b94-84b7-497899cafe10.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1010&id=u3a36c42f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2020&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=887101&status=done&style=stroke&taskId=u747bc337-5212-4a8b-a88f-127c53ea621&title=&width=1792) -# 开发一个自定义物料 -## 初始化物料 -```json +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01A4vPqC1xbeAqNxBRM_!!6000000006462-2-tps-3584-1936.png) + +在 Demo 中调试项目 + +在 build.json 下面新增 "inject": true,就可以在 [https://lowcode-engine.cn/demo/demo-general/index.html?debug](https://lowcode-engine.cn/demo/demo-general/index.html?debug) 页面下进行调试了。 + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01uqSmrX1oqupxeGH1m_!!6000000005277-2-tps-3584-2020.png) + + +## 开发一个自定义物料 +### 初始化物料 +```bash npm init @alilc/element your-material-demo ``` -选择组件/物料栏
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660706045985-db73ca55-925a-446b-ace4-b59fa1e18469.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=104&id=kuWIf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=208&originWidth=824&originalType=binary&ratio=1&rotation=0&showTitle=false&size=88910&status=done&style=stroke&taskId=u92f5fa65-386a-4f52-a093-bcbbebdc2d7&title=&width=412) -配置其他信息
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660706116845-9b3b938f-c132-426b-81bd-d49283ebf9e8.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=124&id=u941c9808&margin=%5Bobject%20Object%5D&name=image.png&originHeight=248&originWidth=800&originalType=binary&ratio=1&rotation=0&showTitle=false&size=111864&status=done&style=stroke&taskId=ue4ff4dab-3a53-4811-bf70-7fa6fc0c8b6&title=&width=400) +选择组件/物料栏 -这样我们就初始化好了一个 React 物料。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660706173968-3e5db25a-e08d-4852-90c9-ffaa0968fd62.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1010&id=u854b37cc&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2020&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1080400&status=done&style=stroke&taskId=u10e21350-23d4-4d8f-8c16-0c5a221fc2e&title=&width=1792) -## 启动并调试物料 -### 安装依赖 -```json +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01qVJQvG1Yhj2PJhhvk_!!6000000003091-2-tps-824-208.png) + +配置其他信息 + +![image.png](https://img.alicdn.com/imgextra/i3/O1CN017fFT8O1IVmrLYg87F_!!6000000000899-2-tps-800-248.png) + +这样我们就初始化好了一个 React 物料。 + +![image.png](https://img.alicdn.com/imgextra/i1/O1CN01SU2xn91TZPlzcARVI_!!6000000002396-2-tps-3584-2020.png) + +### 启动并调试物料 +#### 安装依赖 +```bash npm i ``` -### 启动 -```json +#### 启动 +```bash npm run lowcode:dev ``` -我们就可以通过 [http://localhost:3333/](http://localhost:3333/) 看到我们的研发的物料了。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660706484894-73798e35-1e58-4ffe-bb3c-bfba7b014433.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=895&id=zVMiy&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1790&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=678753&status=done&style=stroke&taskId=u241f50c0-1a43-4854-8443-7e972f15623&title=&width=1792) -### 在 Demo 中调试 -```json +我们就可以通过 [http://localhost:3333/](http://localhost:3333/) 看到我们的研发的物料了。 + +![image.png](https://img.alicdn.com/imgextra/i4/O1CN01JqoHqc1z7zlSWFYJD_!!6000000006668-2-tps-3584-1790.png) +#### 在 Demo 中调试 +```bash npm i @alilc/build-plugin-alt ``` -修改 build.lowcode.js
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660706733149-0170b2fb-88de-40e3-8204-f510d7e42f77.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=311&id=u8a1a8bea&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1046&originWidth=1388&originalType=binary&ratio=1&rotation=0&showTitle=false&size=291155&status=done&style=stroke&taskId=u61ede7d2-f92d-43b9-8582-a2362a9ea14&title=&width=413) +修改 build.lowcode.js + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01K7u7ci1KCfYlBj2yf_!!6000000001128-2-tps-1388-1046.png) 如图,新增如下代码 -```json +```javascript [ '@alilc/build-plugin-alt', { @@ -224,16 +276,18 @@ npm i @alilc/build-plugin-alt ], ``` -我们重新启动项目,就可以在 Demo 中找到我们的自定义组件。
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660706823666-ca28a08d-6241-4112-bc78-b9078c81fb75.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=906&id=u31bdc31a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1812&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=788013&status=done&style=stroke&taskId=uaa4789a2-452f-4b04-8894-759989e4568&title=&width=1792) +我们重新启动项目,就可以在 Demo 中找到我们的自定义组件。 -## 发布 +![image.png](https://img.alicdn.com/imgextra/i1/O1CN0166WywE26Lv7NuJMus_!!6000000007646-2-tps-3584-1812.png) + +### 发布 首先进行构建 -```json +```bash npm run lowcode:build ``` 发布组件 -```json +```bash npm publish ``` @@ -243,7 +297,8 @@ npm publish - 组件代码:[https://unpkg.com/my-material-demo@0.1.0/build/lowcode/render/default/view.js](https://unpkg.com/my-material-demo@0.1.0/build/lowcode/render/default/view.js) 我们也可以从 [https://unpkg.com/my-material-demo@0.1.0/build/lowcode/assets-prod.json](https://unpkg.com/my-material-demo@0.1.0/build/lowcode/assets-prod.json) 找到我们的资产包描述。 -```json + +```bash { "packages": [ { @@ -288,9 +343,18 @@ npm publish } ``` -## 使用 -我们将刚刚发布的组件的 assets-prod.json 的内容放到 demo 的 src/universal/assets.json 中。
*最好放到最后,防止因为资源加载顺序问题导致出现报错。
如图,新增 packages 配置
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660707789785-ea75a399-6845-45a8-8c53-08402749c9a8.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1010&id=uf0f75c17&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2020&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1327766&status=done&style=stroke&taskId=ub053d846-69fd-4a55-8e9e-b41d1e06e47&title=&width=1792)
如图,新增 components 配置
![image.png](https://cdn.nlark.com/yuque/0/2022/png/2622706/1660707811725-a0e36f48-910d-45b5-b162-3aa4e2f87e9b.png#clientId=udb19495f-ea47-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=1010&id=uf8c9506f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=2020&originWidth=3584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1222080&status=done&style=stroke&taskId=u10147f1f-27ed-4cec-bfc9-2cb3d61d6a2&title=&width=1792) +### 使用 +我们将刚刚发布的组件的 assets-prod.json 的内容放到 demo 的 src/universal/assets.json 中。 + +> 最好放到最后,防止因为资源加载顺序问题导致出现报错。 + +如图,新增 packages 配置 +![image.png](https://img.alicdn.com/imgextra/i1/O1CN018dnIB91XHmzeTrq3n_!!6000000002899-2-tps-3584-2020.png) + +如图,新增 components 配置 + +![image.png](https://img.alicdn.com/imgextra/i2/O1CN01UNp89s1vQXKyfsFaL_!!6000000006167-2-tps-3584-2020.png) 这时候再启动 DEMO 项目,就会有新的低代码物料了。接下来就按照你们的需求,继续扩展物料吧。 -# 总结 +## 总结 这里只是简单的介绍了一些低代码引擎的基础能力,带大家简单的对低代码 DEMO 进行扩展,定制一些新的功能。低代码引擎的能力还有很多很多,可以继续去探索更多的功能。 diff --git a/docs/community/code-specification.md b/docs/docs/participate/code-specification.md similarity index 93% rename from docs/community/code-specification.md rename to docs/docs/participate/code-specification.md index f4378ee2c..d6b387e30 100644 --- a/docs/community/code-specification.md +++ b/docs/docs/participate/code-specification.md @@ -1,5 +1,6 @@ --- title: 编码规约 +sidebar_position: 5 --- 编码规约 @@ -26,7 +27,7 @@ title: 编码规约 - 不要在全局命名空间内定义类型/值 - 共享的类型应该在 `types.ts` 里定义 - 在一个文件里,类型定义应该出现在顶部 - - interface 和 type 很类似,原则上能用 interface 实现,就用 interface , 如果不能才用 type + - interface 和 type 很类似,原则上能用 interface 实现,就用 interface , 如果不能才用 type ### 注释 diff --git a/docs/docs/participate/config.md b/docs/docs/participate/config.md index e30040010..0694cdba3 100644 --- a/docs/docs/participate/config.md +++ b/docs/docs/participate/config.md @@ -2,7 +2,7 @@ title: 工程化配置 sidebar_position: 3 --- -目前引擎体系共包含 3 个 js 文件,即: +目前引擎体系共包含 2 个 js 文件,即: ```html diff --git a/docs/docs/participate/doc.md b/docs/docs/participate/doc.md index c1ef26f8d..1e19918db 100644 --- a/docs/docs/participate/doc.md +++ b/docs/docs/participate/doc.md @@ -1,5 +1,5 @@ --- -title: 官网文档协作流程 +title: 参与文档贡献 sidebar_position: 3 --- @@ -7,11 +7,19 @@ sidebar_position: 3 ### 维护方式 -- 官方文档通过 github 管理文档源, 官网文档与[主仓库 develop 分支](https://github.com/alibaba/lowcode-engine/tree/develop/docs)保持同步。 +- 官方文档通过 github 管理文档源,官网文档与[主仓库 develop 分支](https://github.com/alibaba/lowcode-engine/tree/develop/docs)保持同步。 - 点击每篇文档下发的 `编辑此页` 可直接定位到 github 中位置。 -- 欢迎 PR, 文档 PR 也会作为贡献者贡献,会用于贡献度统计。 -- 文档同步到官方网站由官方人员进行操作,如有需要可以通过 issue 或 贡献者群与相关人员沟通。 +- 欢迎 PR,文档 PR 也会作为贡献者贡献,会用于贡献度统计。 +- **文档同步到官方网站由官方人员进行操作**,如有需要可以通过 issue 或 贡献者群与相关人员沟通。 +- 为了提供更好的阅读和使用体验,文档中的图片文件会定期转换成可信的 CDN 地址。 -### PR 方式 +### PR 提交注意事项 -- 操作与代码贡献一致,指向 develop 分支。 \ No newline at end of file +- 指向 develop 分支。 +- 涉及到图片的,需附在文档同级的 img 目录下,通过相对地址引用。 + +### 文档格式 + +本项目文档参考[文档编写指南](https://github.com/sparanoid/chinese-copywriting-guidelines)。 + +使用 vscode 进行编辑的朋友可以安装 vscode 插件 [huacnlee.autocorrect](https://github.com/huacnlee/autocorrect) 辅助文档 lint。 diff --git a/docs/docs/participate/flow.md b/docs/docs/participate/flow.md index 24ebd3629..676abffed 100644 --- a/docs/docs/participate/flow.md +++ b/docs/docs/participate/flow.md @@ -19,7 +19,7 @@ sidebar_position: 2 几点要求: 1. commit message 格式遵循 [ConvensionalCommits](https://www.conventionalcommits.org/en/v1.0.0/#summary) -![image.png](https://cdn.nlark.com/yuque/0/2022/png/110793/1645066644352-4de1c64c-bff6-4482-90d1-1fb610aa91f2.png#averageHue=%23eceef0&clientId=u6dcee4f0-35df-4&crop=0&crop=0&crop=1&crop=1&height=297&id=CfpQy&margin=%5Bobject%20Object%5D&name=image.png&originHeight=594&originWidth=2070&originalType=binary&ratio=1&rotation=0&showTitle=false&size=341605&status=done&style=none&taskId=u4499b752-5e24-42f6-9186-280fd5a51aa&title=&width=1035) +![image.png](https://img.alicdn.com/imgextra/i3/O1CN01M9UzVM1iqYpyxECdV_!!6000000004464-2-tps-2070-594.png) 2. 请按照一个 bugfix / feature 对应一个 commit,假如不是,请 rebase 后再提交 MR,不要一堆无用的、试验性的 commit。 好处:从引擎的整体 commit 历史来看,会很清晰,**每个 commit 完成一件确定的事,changelog 也能自动生成**。另外,假如因为某个 commit 导致了 bug,也很容易通过 rebase drop 等方式快速修复。 @@ -44,7 +44,7 @@ sidebar_position: 2 - 日常迭代 2 周,一般月中或月底 - 特殊情况紧急迭代随时发 -- 大Feature迭代,每年 2 - 4 次 +- 大 Feature 迭代,每年 2 - 4 次 ### 发布步骤 @@ -57,7 +57,7 @@ sidebar_position: 2 ```bash git checkout develop ``` -2. 创建release分支 +2. 创建 release 分支 ```bash git checkout -b release/1.0.0 ``` @@ -65,7 +65,7 @@ sidebar_position: 2 ```bash npm run build ``` -4. 发布到npm +4. 发布到 npm ```bash npm run pub ``` @@ -77,9 +77,9 @@ sidebar_position: 2 7. 合并 release/x.x.x 到 main 分支 8. 合并 main 分支到 develop 分支 -如果是发布beta 版本,步骤如下(以发布 1.0.1 版本为例): +如果是发布 beta 版本,步骤如下(以发布 1.0.1 版本为例): -#### 发某版本首个 beta ,如 1.0.1-beta.0 +#### 发某版本首个 beta,如 1.0.1-beta.0 1. 拉 develop 分支 ```bash git checkout develop @@ -91,6 +91,7 @@ sidebar_position: 2 2. 拉 release 分支,此处以 1.0.1 版本做示例 ```bash git checkout -b release/1.0.1-beta + git push --set-upstream origin release/1.0.1-beta ``` 3. build ```bash @@ -105,7 +106,7 @@ sidebar_position: 2 tnpm run sync ``` -#### 发某版本非首个 beta ,如 1.0.1-beta.0 -> 1.0.1-beta.1 +#### 发某版本非首个 beta,如 1.0.1-beta.0 -> 1.0.1-beta.1 1. 切换到 release 分支 ```bash git checkout release/1.0.1-beta @@ -136,7 +137,7 @@ sidebar_position: 2 ```bash npm run build ``` -3. publish (此步骤需要 npm 发包权限) +3. publish(此步骤需要 npm 发包权限) ```bash npm run pub ``` diff --git a/docs/docs/participate/index.md b/docs/docs/participate/index.md index 854da7e18..ea87651ff 100644 --- a/docs/docs/participate/index.md +++ b/docs/docs/participate/index.md @@ -22,9 +22,10 @@ sidebar_position: 0 3. 如果你修复了 bug 或者添加了代码,而这些内容需要测试,请添加测试! 4. 确保通过测试套件(yarn test)。 5. 请签订贡献者许可证协议(Contributor License Agreement)。 + > 如已签署 CLA 仍被提示需要签署,[解决办法](/site/docs/faq/faq021) ### 核心贡献者交流 如果你想长期参与到项目维护中,我们提供了一个核心贡献者交流群。 1. 可以通过[填写问卷](https://survey.taobao.com/apps/zhiliao/4YEtu9gHF)的方式,参与到其中。 -2. 填写问卷后加微信号 `wxidvlalalalal` 说明一下 +2. 填写问卷后加微信号 `wxidvlalalalal` 说明一下。 diff --git a/docs/docs/participate/prepare.md b/docs/docs/participate/prepare.md index dd962cd64..b23dff33d 100644 --- a/docs/docs/participate/prepare.md +++ b/docs/docs/participate/prepare.md @@ -9,7 +9,7 @@ sidebar_position: 1 如果您需要对低代码编辑器进行定制,您可能只需要 clone [lowcode-demo 项目](https://github.com/alibaba/lowcode-demo)并进行修改,参考“[配置低代码扩展点](/site/docs/guide/expand/editor/summary)”章节。 > 前置条件: -> node >= 14 +> node 推荐使用 16.18.0(14.x 也可以) ### 1. 拉取代码,启动项目 ```bash diff --git a/docs/docs/specs/assets-spec.md b/docs/docs/specs/assets-spec.md index 5c7df0163..dc55b12c1 100644 --- a/docs/docs/specs/assets-spec.md +++ b/docs/docs/specs/assets-spec.md @@ -65,7 +65,7 @@ sidebar_position: 2 - setters { Array } 设计器中设置器描述协议列表 - extConfig { Object } 平台自定义扩展字段 -### 2.1 version(A) +### 2.1 version (A) 定义当前协议 schema 的版本号; @@ -73,9 +73,9 @@ sidebar_position: 2 | ---------- | ------ | ---------- | -------- | ------ | | version | String | 协议版本号 | - | 1.1.0 | -### 2.2 packages(A) +### 2.2 packages (A) -定义低代码编辑器中加载的资源列表,包含公共库和组件(库) cdn 资源等; +定义低代码编辑器中加载的资源列表,包含公共库和组件 (库) cdn 资源等; | 字段 | 字段描述 | 字段类型 | 规范等级 | 备注 | | -------------------- | --------------------------------------------------------------- | ------------- | -------- | -------------------------------------------------------------------------------------------------------- | @@ -92,13 +92,13 @@ sidebar_position: 2 | packages[].advancedEditUrls | 组件多个编辑态视图打包后的 CDN url 列表集合,包含 js 和 css | Object | AAA | 上层平台根据特定标识提取某个编辑态的资源,低代码引擎编辑器会加载这些资源,优先级高于 packages[].editUrls | | packages[].advancedUrls | 组件多个端的渲染态视图打包后的 CDN url 列表集合,包含 js 和 css | Object | AAA | 上层平台根据特定标识提取某个渲染态的资源, 低代码引擎渲染模块会加载这些资源,优先级高于 packages[].urls | | packages[].external | 当前资源在作为其他资源的依赖,在其他依赖打包时时是否被排除了(同 webpack 中 external 概念) | Boolean | AAA | 某些资源会被单独提取出来,是其他依赖的前置依赖,根据这个字段决定是否提前加载该资源 | -| packages[].loadEnv | 指定当前资源加载的环境 | Array | AAA | 主要用于指定 external 资源加载的环境,取值为 design(设计态)、runtime(预览态)中的一个或多个 | +| packages[].loadEnv | 指定当前资源加载的环境 | Array | AAA | 主要用于指定 external 资源加载的环境,取值为 design(设计态)、runtime(预览态) 中的一个或多个 | | packages[].exportSourceId | 标识当前 package 内容是从哪个 package 导出来的 | String | AAA | 此时 urls 无效 | | packages[].exportSourceLibrary | 标识当前 package 是从 window 上的哪个属性导出来的 | String | AAA | exportSourceId 的优先级高于exportSourceLibrary ,此时 urls 无效 | | packages[].async | 标识当前 package 资源加载在 window.library 上的是否是一个异步对象 | Boolean | A | async 为 true 时,需要通过 await 才能拿到真正内容 | | packages[].exportMode | 标识当前 package 从其他 package 的导出方式 | String | A | 目前只支持 `"functionCall"`, exportMode等于 `"functionCall"` 时,当前package 的内容以函数的方式从其他 package 中导出,具体导出接口如: (library: string, packageName: string, isRuntime?: boolean) => any | Promise, library 为当前 package 的 library, packageName 为当前的包名,返回值为当前 package 的导出内容 | -描述举例: +描述举例: ```json { @@ -298,14 +298,14 @@ sidebar_position: 2 } ``` -### 2.3 components (A) +### 2.3 components (A) 定义资产包中包含的所有组件的低代码描述的集合,分为“ComponentDescription”和“RemoteComponentDescription”(详见 2.6 TypeScript 定义): - ComponentDescription: 符合“组件描述协议”的数据,详见物料规范中`2.2.2 组件描述协议`部分; - RemoteComponentDescription 是将一个或多个 ComponentDescription 构建打包的 js 资源的描述,在浏览器中加载该资源后可获取到其中包含的每个组件的 ComponentDescription 的具体内容; -### 2.4 sort (AA) +### 2.4 sort (AA) 定义组件列表分组 @@ -346,7 +346,7 @@ sidebar_position: 2 ### 2.7 extConfig (AAA) -定义平台相关的扩展内容,用于存放平台自身实现的一些私有协议, 以允许存量平台能够平滑地迁移至标准协议。 extConfig 是一个 key-value 结构的对象,协议不会规定 extConfig 中的字段名称以及类型, 完全自定义 +定义平台相关的扩展内容,用于存放平台自身实现的一些私有协议,以允许存量平台能够平滑地迁移至标准协议。extConfig 是一个 key-value 结构的对象,协议不会规定 extConfig 中的字段名称以及类型,完全自定义 ### 2.8 TypeScript 定义 diff --git a/docs/docs/specs/lowcode-spec.md b/docs/docs/specs/lowcode-spec.md index e1d57daa0..6ad87caef 100644 --- a/docs/docs/specs/lowcode-spec.md +++ b/docs/docs/specs/lowcode-spec.md @@ -78,7 +78,7 @@ sidebar_position: 0 ### 1.7 背景 -- **协议目标**: 通过约束低代码引擎的搭建协议规范,让上层低代码编辑器的产出物(低代码业务组件、区块、应用)保持一致性,可跨低代码研发平台进行流通而提效,亦不阻碍集团业务间融合的发展。  +- **协议目标**:通过约束低代码引擎的搭建协议规范,让上层低代码编辑器的产出物(低代码业务组件、区块、应用)保持一致性,可跨低代码研发平台进行流通而提效,亦不阻碍集团业务间融合的发展。  - **协议通**: - 协议顶层结构统一 - 协议 schema 具备有完整的描述能力,包含版本、国际化、组件树、组件映射关系等; @@ -179,10 +179,10 @@ sidebar_position: 0 "props": { "prop1": 1234, // 简单 json 数据 "prop2": [{ // 简单 json 数据 - "label": "选项1", + "label": "选项 1", "value": 1 }, { - "label": "选项2", + "label": "选项 2", "value": 2 }], "prop3": [{ @@ -232,8 +232,8 @@ sidebar_position: 0 "primary": "#ff9966" } }, - "meta": { // 应用元数据信息, key 为业务自定义 - "name": "demo 应用", // 应用中文名称, + "meta": { // 应用元数据信息,key 为业务自定义 + "name": "demo 应用", // 应用中文名称, "git_group": "appGroup", // 应用对应 git 分组名 "project_name": "app_demo", // 应用对应 git 的 project 名称 "description": "这是一个测试应用", // 应用描述 @@ -343,7 +343,7 @@ sidebar_position: 0 出码结果: ```javascript -// 使用解构方式, destructuring is true. +// 使用解构方式,destructuring is true. import { Button } from '@alifd/next'; // 使用解构方式,且 exportName 和 componentName 不同 @@ -376,7 +376,7 @@ import { Input as CustomInput } from '@ali/custom/lib/input'; 与源码对应的转换关系如下: - 组件结构:转换成一个 .jsx 文件内 React Class 类 render 函数返回的 **jsx** 代码。 -- 容器结构:将转换成一个标准文件,如 React 的 jsx 文件, export 一个 React Class,包含生命周期定义、自定义方法、事件属性绑定、异步数据请求等。 +- 容器结构:将转换成一个标准文件,如 React 的 jsx 文件,export 一个 React Class,包含生命周期定义、自定义方法、事件属性绑定、异步数据请求等。 #### 2.3.1 基础结构描述 (A) @@ -427,9 +427,9 @@ import { Input as CustomInput } from '@ali/custom/lib/input'; | shouldFetch | 本次请求是否可以正常请求 | (options: ComponentDataSourceItemOptions) => boolean | - | ```() => true``` | function 参数参考 [ComponentDataSourceItemOptions 对象描述](#2315-componentdatasourceitemoptions-对象描述) | | willFetch | 单个数据结果请求参数处理函数 | Function | - | options => options | 只接受一个参数(options),返回值作为请求的 options,当处理异常时,使用原 options。也可以返回一个 Promise,resolve 的值作为请求的 options,reject 时,使用原 options | | requestHandler | 自定义扩展的外部请求处理器 | Function | - | - | 仅 type='custom' 时生效 | -| dataHandler | request 成功后的回调函数 | Function | - | `response => response.data` | 参数: 请求成功后 promise 的 value 值 | -| errorHandler | request 失败后的回调函数 | Function | - | - | 参数: 请求出错 promise 的 error 内容 | -| options {} | 请求参数 | **ComponentDataSourceItemOptions** | - | - | 每种请求类型对应不同参数, 详见 [ComponentDataSourceItemOptions 对象描述](#2315-componentdatasourceitemoptions-对象描述) | +| dataHandler | request 成功后的回调函数 | Function | - | `response => response.data`| 参数:请求成功后 promise 的 value 值 || +| errorHandler | request 失败后的回调函数 | Function | - | - | 参数:请求出错 promise 的 error 内容 | +| options {} | 请求参数 | **ComponentDataSourceItemOptions**| - | - | 每种请求类型对应不同参数,详见 | 每种请求类型对应不同参数,详见 [ComponentDataSourceItemOptions 对象描述](#2315-componentdatasourceitemoptions-对象描述) | **关于 dataHandler 于 errorHandler 的细节说明:** @@ -518,7 +518,7 @@ try { | 参数 | 说明 | 类型 | 支持变量 | 默认值 | 备注 | | ------------ | ---------- | -------------- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------- | | name | 属性名称 | String | - | - | | -| propType | 属性类型 | String\|Object | - | - | 具体值内容结构,参考《低代码引擎物料协议规范》 内的 “2.2.2.3 组件属性信息”中描述的**基本类型**和**复合类型** | +| propType | 属性类型 | String\|Object | - | - | 具体值内容结构,参考《低代码引擎物料协议规范》内的“2.2.2.3 组件属性信息”中描述的**基本类型**和**复合类型** | | description | 属性描述 | String | - | '' | | | defaultValue | 属性默认值 | Any | - | undefined | 当 defaultValue 和 defaultProps 中存在同一个 prop 的默认值时,优先使用 defaultValue。 | @@ -544,9 +544,9 @@ try { | 参数 | 说明 | 类型 | 支持变量 | 默认值 | 备注 | | ------------- | ---------------------- | ---------------- | -------- | ----------------- | ---------------------------------------------------------------------------------------------------------- | -| id | 组件唯一标识 | String | - | | 可选, 组件 id 由引擎随机生成(UUID),并保证唯一性,消费方为上层应用平台,在组件发生移动等场景需保持 id 不变 | -| componentName | 组件名称 | String | - | Div | 必填,首字母大写, 同 [componentsMap](#22-组件映射关系 a) 中的要求 | -| props {} | 组件属性对象 | **Props** | - | {} | 必填, 详见 [Props 结构描述](#2311-props-结构描述) | +| id | 组件唯一标识 | String | - | | 可选,组件 id 由引擎随机生成(UUID),并保证唯一性,消费方为上层应用平台,在组件发生移动等场景需保持 id 不变 | +| componentName | 组件名称 | String | - | Div | 必填,首字母大写,同 [componentsMap](#22-组件映射关系 a) 中的要求 | +| props {} | 组件属性对象 | **Props**| - | {} | 必填,详见 | 必填,详见 [Props 结构描述](#2311-props-结构描述) | | condition | 渲染条件 | Boolean | ✅ | true | 选填,根据表达式结果判断是否渲染物料;支持变量表达式 | | loop | 循环数据 | Array | ✅ | - | 选填,默认不进行循环渲染;支持变量表达式 | | loopArgs | 循环迭代对象、索引名称 | [String, String] | | ["item", "index"] | 选填,仅支持字符串 | @@ -611,10 +611,10 @@ try { | condition | 渲染条件 | Boolean | ✅ | true | 选填,根据表达式结果判断是否渲染物料;支持变量表达式 | | state | 容器初始数据 | Object | ✅ | - | 选填,支持变量表达式 | | children | 子组件 | Array | - | | 选填,支持变量表达式 | -| css/less/scss | 样式属性 | String | ✅ | - | 选填, 详见 [css/less/scss 样式描述](#2312-csslessscss 样式描述) | +| css/less/scss | 样式属性 | String | ✅ | - | 选填,详见 [css/less/scss 样式描述](#2312-csslessscss 样式描述) | | lifeCycles | 生命周期对象 | **ComponentLifeCycles** | - | - | 详见 [ComponentLifeCycles 对象描述](#2316-componentlifecycles-对象描述) | | methods | 自定义方法对象 | Object | - | - | 选填,对象成员为函数类型 | -| dataSource {} | 数据源对象 | **ComponentDataSource** | - | - | 选填,异步数据源, 详见 [ComponentDataSource 对象描述](#2313-componentdatasource-对象描述) | +| dataSource {} | 数据源对象 | **ComponentDataSource**| - | - | 选填,异步数据源,详见 | - | - | 选填,异步数据源,详见 [ComponentDataSource 对象描述](#2313-componentdatasource-对象描述) | @@ -891,7 +891,7 @@ try { "value": "this.state.num - this.state.num2" } ``` -- return "8万" 字符串类型 +- return "8 万" 字符串类型 ```json { @@ -899,7 +899,7 @@ try { "value": "`${this.state.num}万`" } ``` -- return "8万" 字符串类型 +- return "8 万" 字符串类型 ```json { @@ -1056,7 +1056,7 @@ type Ti18n = { 请将 `setState()` 视为请求而不是立即更新组件的命令。为了更好的感知性能,低代码引擎会延迟调用它,然后通过一次传递更新多个组件。低代码引擎并不会保证 state 的变更会立即生效。 -`setState()` 并不总是立即更新组件, 它会批量推迟更新。这使得在调用 `setState()` 后立即读取 `this.state` 成为了隐患。为了消除隐患,请使用 `setState` 的回调函数(`setState(updater, callback)`),`callback` 将在应用更新后触发。即,如下例所示: +`setState()`并不总是立即更新组件,它会批量推迟更新。这使得在调用用 `setState()` 后立即读取 `this.state` 成为了隐患。为了消除隐患,请使用 `setState` 的回调函数(`setState(updater, callback)`),`callback` 将在应用更新后触发。即,如下例所示: ```js this.setState(newState, () => { @@ -1087,7 +1087,7 @@ this.setState((prevState) => ({ count: prevState.count + 1 })); | data | 获取上次请求成功后的数据 | Any | | | error | 获取上次请求失败的错误对象 | Error 对象 | | -备注: 如果组件没有在区块容器内,而是直接在页面内,那么 `this === this.page` +备注:如果组件没有在区块容器内,而是直接在页面内,那么 `this === this.page` ##### 2.3.5.2 循环数据 API @@ -1108,7 +1108,7 @@ this.setState((prevState) => ({ count: prevState.count + 1 })); | ------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------- | -------- | ------ | | utils[] | 工具类扩展映射关系 | Array\<**UtilItem**\> | - | | | *UtilItem*.name | 工具类扩展项名称 | String | - | | -| *UtilItem*.type | 工具类扩展项类型 | 枚举, `'npm'` (代表公网 npm 类型) / `'tnpm'` (代表阿里巴巴内部 npm 类型) / `'function'` (代表 Javascript 函数类型) | - | | +| *UtilItem*.type | 工具类扩展项类型 | 枚举, `'npm'` (代表公网 npm 类型) / `'tnpm'` (代表阿里巴巴内部 npm 类型) / `'function'` (代表 Javascript 函数类型) | - | | | *UtilItem*.content | 工具类扩展项内容 | [ComponentMap 类型](#22-组件映射关系 a) 或 [JSFunction](#2432事件函数类型 a) | - | | 描述示例: @@ -1161,7 +1161,7 @@ export const recordEvent = function(logkey, gmkey, gokey, reqMethod) { ... ``` -扩展的工具类,用户可以通过统一的上下文 this.utils 方法获取所有扩展的工具类或自定义函数 ,例如:this.utils.moment、this.utils.clone。搭建协议中的使用方式如下所示: +扩展的工具类,用户可以通过统一的上下文 this.utils 方法获取所有扩展的工具类或自定义函数,例如:this.utils.moment、this.utils.clone。搭建协议中的使用方式如下所示: ```javascript { @@ -1202,7 +1202,7 @@ export const recordEvent = function(logkey, gmkey, gokey, reqMethod) { } ``` -使用举例: +使用举例: ```json { @@ -1303,11 +1303,11 @@ export const recordEvent = function(logkey, gmkey, gokey, reqMethod) { │ │ └── app.js # 应用配置文件 │ ├── utils/ # 工具库 │ │ └── index.js # 应用第三方扩展函数 -│ ├── locales/ # [可选]国际化资源 +│ ├── locales/ # [可选] 国际化资源 │ │ ├── en-US │ │ └── zh-CN │ ├── global.scss # 全局样式 -│ └── index.jsx # 应用入口脚本, 依赖 config/routes.js 的路由配置动态生成路由; +│ └── index.jsx # 应用入口脚本,依赖 config/routes.js 的路由配置动态生成路由; ├── webpack.config.js # 项目工程配置,包含插件配置及自定义 webpack 配置等 ├── README.md ├── package.json diff --git a/docs/docs/specs/material-spec.md b/docs/docs/specs/material-spec.md index f7687114b..c74d0c96a 100644 --- a/docs/docs/specs/material-spec.md +++ b/docs/docs/specs/material-spec.md @@ -250,7 +250,7 @@ API 是组件的属性解释,给开发者作为组件属性配置的参考。 | direction | enum | 方向,取值采用缩写的方式。 | hoz(水平), ver(垂直) | | align | enum | 对齐方式 | tl, tc, tr, cl, cc, cr, bl, bc, br | | status | enum | 状态 | normal, success, error, warning | -| size | enum | 大小 | small, medium, large 更大或更小可用(xxs, xs, xl, xxl) | +| size | enum | 大小 | small, medium, large 更大或更小可用 (xxs, xs, xl, xxl) | | type | enum or string | 分类:1. dom 结构不变、只有皮肤的变化 2.组件类型只有并列的几类 | normal, primary, secondary | | visible | boolean | 是否显示 | | | defaultVisible | boolean | 是否显示(非受控) | | @@ -266,7 +266,7 @@ API 是组件的属性解释,给开发者作为组件属性配置的参考。 当某个 API 的接口,允许用户指定多个枚举值的时候,我们把这个接口定义为多选枚举。一个很典型的例子是某个弹层组件的 `closable` 属性,我们会允许:键盘 esc 按键、点击 mask、点击 close 按钮、点击组件以外的任何区域进行关闭。 -不要有一个 API 值,支持多种类型。例如某个弹层的组件,我们会允许 esc、点击 mask、点击 close 按钮等进行关闭。此时 API 设计可以通过多个 API 承载,例如: +不要有一个 API 值,支持多种类型。例如某个弹层的组件,我们会允许 esc、点击 mask、点击 close 按钮等进行关闭。此时 API 设计可以通过多个 API 承载,例如: ```js closable?: boolean; // 默认为 true @@ -283,14 +283,14 @@ true 表示触发规则都会关闭,false 表示触发规则不会关闭。 #### 事件 -- 标准事件或者自定义的符合 w3c 标准的事件,命名必须 on 开头, 即 `on` + 事件名,如 onExpand。 +- 标准事件或者自定义的符合 w3c 标准的事件,命名必须 on 开头, 即 `on` + 事件名,如 onExpand。 #### 表单规范 - 支持[受控模式](https://reactjs.org/docs/forms.html#controlled-components)(value + onChange) (A) - value 控制组件数据展现 - onChange 组件发生变化时候的回调函数(第一个参数可以给到 value) -- `value={undefined}` 的时候清空数据, field 的 reset 函数会给所有组件下发 undefined 数据 (AA) +- `value={undefined}`的时候清空数据,field 的 reset 函数会给所有组件下发 undefined 数据 (AA)) - 一次完整操作抛一次 onChange 事件 `建议` 比如有 Process 表示进展中的状态,建议增加 API `onProcess`;如果有 Start 表示启动状态,建议增加 API `onStart`  (AA) #### 属性的传递 @@ -357,7 +357,7 @@ $ iceworks sync #### 目录规范 -在 `src` 目录新增 `locale` 目录用于管理不同语言的文案. +在 `src` 目录新增 `locale` 目录用于管理不同语言的文案。 ``` |- BizHello @@ -499,9 +499,9 @@ export default { api 属性标准参考 [https://fusion.design/help.html#/dev-biz](https://fusion.design/help.html#/dev-biz) -#### 2.1.7 无障碍访问规范(AAA) +#### 2.1.7 无障碍访问规范 (AAA) -无障碍需要符合 [WCAG 2.1 A级标准](https://www.w3.org/TR/WCAG21/),可参考 [W3C 无障碍最佳实践](https://www.w3.org/TR/wai-aria-practices-1.1/)、[Fusion 无障碍指引 2.3.1](https://alibaba-fusion.github.io/next/part1/basics.html) 章节等。 +无障碍需要符合 [WCAG 2.1 A 级标准](https://www.w3.org/TR/WCAG21/),可参考 [W3C 无障碍最佳实践](https://www.w3.org/TR/wai-aria-practices-1.1/)、[Fusion 无障碍指引 2.3.1](https://alibaba-fusion.github.io/next/part1/basics.html) 章节等。 #### 增加 a11y.md 无障碍 demo @@ -552,7 +552,7 @@ component | -------------- | ------------------------------------------------------------------------------------------------- | ------ | | version | 协议版本号 | String | | componentsMap | 描述组件映射关系的集合 | Array | -| componentsTree | 低代码业务组件树描述,是长度固定为1的数组, 即数组内仅包含根容器的描述(低代码业务组件容器类型) | Array | +| componentsTree | 低代码业务组件树描述,是长度固定为 1 的数组,即数组内仅包含根容器的描述(低代码业务组件容器类型) | Array | | utils | 工具类扩展映射关系 | Array | | i18n | 国际化语料 | Object | @@ -572,7 +572,7 @@ component "name": "lucy", }, "static": {}, // 用于定义自定组件的 static 属性 - "defaultProps": { // 默认 props: 选填仅用于定义低代码业务组件的默认属性固定对象 + "defaultProps": { // 默认 props:选填仅用于定义低代码业务组件的默认属性固定对象 "name": "xxx" }, "children": [{ @@ -609,8 +609,6 @@ component - **组件属性信息 (A):** 描述组件属性信息,通常包含参数、说明、类型、默认值 4 项内容。 - **能力配置/体验增强:** 推荐用于优化搭建产品编辑体验,定制编辑能力的配置信息。 -整体结构概览: [http://lowcode-engine.cn/doc?url=sde3wf](http://lowcode-engine.cn/doc?url=sde3wf) - ##### 2.2.2.2 基础信息(A) | 字段 | 字段描述 | 字段类型 | 允许空 | @@ -837,13 +835,13 @@ props 数组下对象字段描述: | defaultValue | 默认值 | Any(视字段类型而定) | type = 'field' 生效 | | supportVariable | 是否支持配置变量 | Boolean | type = 'field' 生效 | | condition | 配置当前 prop 是否展示 | (target: SettingTarget) => boolean; | - | -| setter | 单个控件(setter)描述,搭建基础协议组件的描述对象,支持 JSExpression / JSFunction / JSSlot | `String\|Object\|Function` | type = 'field' 生效 | +| setter | 单个控件 (setter) 描述,搭建基础协议组件的描述对象,支持 JSExpression / JSFunction / JSSlot | `String\|Object\|Function` | type = 'field' 生效 | | extraProps | 其他配置属性(不做流通要求) | Object | 其他配置 | | extraProps.getValue | setter 渲染时被调用,setter 会根据该函数的返回值设置 setter 当前值 | Function | (target: SettingTarget, value: any) => any; | | extraProps.setValue | setter 内容修改时调用,开发者可在该函数内部修改节点 schema 或者进行其他操作 | Function | (target: SettingTarget, value: any) => void; | -根据属性值类型 propType,确定对应控件类型 (setter) ,详见 [https://lowcode-engine.cn/docV2/grfylu](https://lowcode-engine.cn/docV2/grfylu) +根据属性值类型 propType,确定对应控件类型 (setter) 。 ###### 2.2.2.4.2 通用扩展面板支持性配置 supports (AA) @@ -885,7 +883,7 @@ props 数组下对象字段描述: | nestingRule.descendantBlacklist | 后裔节点类型黑名单 | `String\|Function` | | nestingRule.ancestorWhitelist | 祖父节点类型白名单 | `String\|Function` | | isNullNode(AAA) | 是否存在渲染的根节点 | Boolean | -| isLayout(AAA) | 是否是layout布局组件 | Boolean | +| isLayout(AAA) | 是否是 layout 布局组件 | Boolean | | rootSelector(AAA) | 组件选中框的 cssSelector | String | | disableBehaviors(AAA) | 用于屏蔽在设计器中选中组件时提供的操作项,默认操作项有 copy、hide、remove | String[] | | actions(AAA) | 用于详细配置上述操作项的内容 | Object | @@ -925,20 +923,20 @@ props 数组下对象字段描述: | 字段 | 用途 | 类型 | 备注 | | ------------------------------- | --------------------------------------------------------------------------------------------------- | ------- | --- | -|initialChildren |组件拖入“设计器”时根据此配置自动生成 children 节点 schema |NodeData[]/Function NodeData[] | ((target: SettingTarget) => NodeData[]);| -|getResizingHandlers| 用于配置设计器中组件 resize 操作工具的样式和内容| Function| (currentNode: any) => Array<{ type: 'N' | 'W' | 'S' | 'E' | 'NW' | 'NE' | 'SE' | 'SW'; content?: ReactElement; propTarget?: string; appearOn?: 'mouse-enter' | 'mouse-hover' | 'selected' | 'always'; }> / ReactElement[]; -|callbacks| 配置 callbacks 可捕获引擎抛出的一些事件,例如 onNodeAdd、onResize 等| Callback| - +|initialChildren | 组件拖入“设计器”时根据此配置自动生成 children 节点 schema |NodeData[]/Function NodeData[] | ((target: SettingTarget) => NodeData[]);| +|getResizingHandlers| 用于配置设计器中组件 resize 操作工具的样式和内容 | Function| (currentNode: any) => Array<{ type: 'N' | 'W' | 'S' | 'E' | 'NW' | 'NE' | 'SE' | 'SW'; content?: ReactElement; propTarget?: string; appearOn?: 'mouse-enter' | 'mouse-hover' | 'selected' | 'always'; }> / ReactElement[]; +|callbacks| 配置 callbacks 可捕获引擎抛出的一些事件,例如 onNodeAdd、onResize 等 | Callback| - |callbacks.onNodeAdd| 在容器中拖入组件时触发的事件回调| Function| (e: MouseEvent, currentNode: any) => any |callbacks.onNodeRemove| 在容器中删除组件时触发的事件回调| Function| (e: MouseEvent, currentNode: any) => any -|callbacks.onResize| 调整容器尺寸时触发的事件回调,常常与 getResizingHandlers搭配使用| Function| 详见 Types 定义 -|callbacks.onResizeStart| 调整容器尺寸开始时触发的事件回调,常常与 getResizingHandlers搭配使用| Function| 详见 Types 定义 -|callbacks.onResizeEnd| 调整容器尺寸结束时触发的事件回调,常常与 getResizingHandlers搭配使用| Function| 详见 Types 定义 +|callbacks.onResize| 调整容器尺寸时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义 +|callbacks.onResizeStart| 调整容器尺寸开始时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义 +|callbacks.onResizeEnd| 调整容器尺寸结束时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义 |callbacks.onSubtreeModified| 容器节点结构树发生变化时触发的回调| Function| (currentNode: any, options: any) => void; |callbacks.onMouseDownHook| 鼠标按下操作回调| Function| (e: MouseEvent, currentNode: any) => any; |callbacks.onClickHook| 鼠标单击操作回调| Function| (e: MouseEvent, currentNode: any) => any; |callbacks.onDblClickHook| 鼠标双击操作回调| Function| (e: MouseEvent, currentNode: any) => any; -|callbacks.onMoveHook| 节点被拖动回调| Function| (currentNode: any) => boolean; -|callbacks.onHoverHook| 节点被 hover 回调| Function| (currentNode: any) => boolean; +|callbacks.onMoveHook| 节点被拖动回调 | Function| (currentNode: any) => boolean; +|callbacks.onHoverHook| 节点被 hover 回调 | Function| (currentNode: any) => boolean; |callbacks.onChildMoveHook| 容器节点的子节点被拖动回调| Function| (childNode: any, currentNode: any) => boolean; @@ -1211,7 +1209,7 @@ export interface ComponentDescription { // 组件描述协议,通过 npm 中 - components { Array } 所有组件的描述协议列表 - sort { Object } 用于描述组件面板中的 tab 和 category -##### 2.2.3.2 version(A) +##### 2.2.3.2 version (A) 定义当前协议 schema 的版本号; @@ -1219,9 +1217,9 @@ export interface ComponentDescription { // 组件描述协议,通过 npm 中 | ---------- | ------ | ---------- | -------- | ------ | | version | String | 协议版本号 | - | 1.0.0 | -##### 2.2.3.3 packages(A) +##### 2.2.3.3 packages (A) -定义低代码编辑器中加载的资源列表,包含公共库和组件(库) cdn 资源等; +定义低代码编辑器中加载的资源列表,包含公共库和组件 (库) cdn 资源等; | 字段 | 字段描述 | 字段类型 | 备注 | | --------------- | ---------------------- | -------- | ------------------------------------------------------------ | @@ -1232,7 +1230,7 @@ export interface ComponentDescription { // 组件描述协议,通过 npm 中 | packages[].editUrls (A) | 组件编辑态视图打包后的 CDN url 列表,包含 js 和 css | Array\ | 低代码引擎编辑器会加载这些 url | | packages[].urls (AA) | 组件渲染态视图打包后的 CDN url 列表,包含 js 和 css | Array\ | 低代码引擎渲染模块会加载这些 url | -描述举例: +描述举例: ```json { @@ -1253,7 +1251,7 @@ export interface ComponentDescription { // 组件描述协议,通过 npm 中 ] }, { - "title": "fusion组件库", + "title": "fusion 组件库", "package": "@alifd/next", "version": "1.24.18", "urls": [ @@ -1292,11 +1290,11 @@ export interface ComponentDescription { // 组件描述协议,通过 npm 中 } ``` -##### 2.2.3.4 components (A) +##### 2.2.3.4 components (A) 定义所有组件的描述协议列表,组件描述协议遵循本规范章节 2.2.2 的定义; -##### 2.2.3.5 sort (A) +##### 2.2.3.5 sort (A) 定义组件列表分组 @@ -1330,7 +1328,7 @@ export interface RemoteComponentDescription { } ``` -## 3 物料规范-区块规范 +## 3 物料规范 - 区块规范 ### 3.1 源码规范 @@ -1386,14 +1384,14 @@ block/ "category": "form", "screenshot": "https://unpkg.com/@icedesign/user-landing-block/screenshot.png", "views": [{ // 区块视图,配置此项后会进入 fusion cool - "title": "视图1标题", // 区块视图标题 + "title": "视图 1 标题", // 区块视图标题 "props": { // 区块支持的 props "type": "primary" }, "screenshot": "build/views/block_view1.png", // 【编译自动填充】视图截图,会在 build 时自动生成 "html": "build/views/block_view1.html", // 【编译自动填充】视图渲染后 html 结构,会在 build 时自动生成 },{ - "title": "视图2标题", // 区块视图标题 + "title": "视图 2 标题", // 区块视图标题 "props": { // 区块支持的 props "type": "sencondary" }, @@ -1417,7 +1415,7 @@ block/ | i18n | 国际化语料 | Object | -描述举例1: +描述举例 1: ```json { @@ -1425,7 +1423,7 @@ block/ "componentsMap": [{ }], "componentsTree": [{ // 区块组件树,顶层由区块容器组件包裹; "componentName": "Block", // 区块容器组件名 - "fileName": "block1", // 区块容器1 + "fileName": "block1", // 区块容器 1 "props": {}, "css": "body {font-size: 12px;}", "state": { @@ -1454,7 +1452,7 @@ block/ } ``` -描述举例2: +描述举例 2: ```json { @@ -1527,13 +1525,13 @@ block/ │ │ └── app.js # 应用配置文件 │ ├── utils/ # 工具库 │ │ └── index.js # 应用第三方扩展函数 -│ ├── stores/ # [可选]全局状态管理 +│ ├── stores/ # [可选] 全局状态管理 │ │ └── user.js -│ ├── locales/ # [可选]国际化资源 +│ ├── locales/ # [可选] 国际化资源 │ │ ├── en-US │ │ └── zh-CN │ ├── global.scss # 全局样式 -│ └── index.jsx # 应用入口脚本, 依赖 config/routes.js 的路由配置动态生成路由; +│ └── index.jsx # 应用入口脚本,依赖 config/routes.js 的路由配置动态生成路由; ├── webpack.config.js # 项目工程配置,包含插件配置及自定义 `webpack` 配置等 ├── README.md ├── package.json @@ -1567,11 +1565,11 @@ ReactDOM.render(, document.getElementById(pkg.config && pkg.config.target (/src/config/app.js) - 支持配置路由方式:historyMode - - 支持2种路由方式: - - 浏览器路由: browser - - 哈希路由:  hash + - 支持 2 种路由方式: + - 浏览器路由:browser + - 哈希路由:hash - 支持透传路由产生的参数到所有组件的上下文 this 对象上 - - history 对象: this.history + - history 对象:this.history - location 对象:this.location - 支持内置 query 参数的解析:this.location.query - match 对象:this.match @@ -1658,15 +1656,15 @@ a { "category": "form", "screenshot": "https://unpkg.com/@icedesign/user-landing-block/screenshot.png", "views": [{ // 模板视图,配置此项后会进入 fusion cool - "title": "视图1标题", // 模板视图标题 - "path": "#/dashboard/monitor", // 读取路由列表生成,hash 路由必须加# - "screenshot": "build/views/page0.png", // 【编译自动填充】视图截图,会在 build 时自动生成 - "html": "build/views/page0.html", // 【编译自动填充】视图渲染后 html 结构,会在 build 时自动生成 + "title": "视图 1 标题", // 模板视图标题 + "path": "#/dashboard/monitor", // 读取路由列表生成,hash 路由必须加# + "screenshot": "build/views/page0.png", // 【编译自动填充】视图截图,会在 build 时自动生成 + "html": "build/views/page0.html", // 【编译自动填充】视图渲染后 html 结构,会在 build 时自动生成 },{ - "title": "视图2标题", // 区块视图标题 - "path": "#/dashboard/list", // 读取路由列表生成,hash 路由必须加# - "screenshot": "build/views/page1.png", // 【编译自动填充】视图截图,会在 build 时自动生成 - "html": "build/views/page1.html", // 【编译自动填充】视图渲染后 html 结构,会在 build 时自动生成 + "title": "视图 2 标题", // 区块视图标题 + "path": "#/dashboard/list", // 读取路由列表生成,hash 路由必须加# + "screenshot": "build/views/page1.png", // 【编译自动填充】视图截图,会在 build 时自动生成 + "html": "build/views/page1.html", // 【编译自动填充】视图渲染后 html 结构,会在 build 时自动生成 }] } } diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 04c99067e..97a0237b4 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -74,6 +74,10 @@ const config = { }, // 语雀文档导出的图片,会进行 referrer 校验,这里设置关闭,不然加载不了语雀的图片 metadata: [{ name: 'referrer', content: 'no-referrer' }], + tableOfContents: { + minHeadingLevel: 2, + maxHeadingLevel: 5, + }, }), themes: [ diff --git a/docs/package.json b/docs/package.json index 93b2c4319..c32b19794 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "@alilc/lowcode-engine-docs", - "version": "1.0.1", + "version": "1.0.7", "description": "低代码引擎版本化文档", "license": "MIT", "files": [ diff --git a/modules/code-generator/src/plugins/component/rax/jsx.ts b/modules/code-generator/src/plugins/component/rax/jsx.ts index ebc72104f..e0c6dd01f 100644 --- a/modules/code-generator/src/plugins/component/rax/jsx.ts +++ b/modules/code-generator/src/plugins/component/rax/jsx.ts @@ -147,7 +147,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) => function __$$eval(expr) { try { return expr(); - } catch (error) { + } catch (error) { ${evalErrorsHandler} } } diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/schema.json5 b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/schema.json5 index 282f979e8..94c3a2fb7 100644 --- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/schema.json5 +++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/schema.json5 @@ -1,6 +1,5 @@ { // 本例是一个非常简单的 Hello world 页面 - // Schema 参见:https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr version: '1.0.0', componentsMap: [ { diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/schema.json5 b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/schema.json5 index fa39cdb45..59f1a8bbc 100644 --- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/schema.json5 +++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/schema.json5 @@ -1,6 +1,5 @@ { // 本例是一个比较复杂的,带有循环和条件渲染的,以及有各种事件处理函数的页面 - // Schema 参见:https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr version: '1.0.0', componentsMap: [ { diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/schema.json5 b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/schema.json5 index 5652b1db1..bed7c8092 100644 --- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/schema.json5 +++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/schema.json5 @@ -1,6 +1,5 @@ { // 本例是一个路由测试页面,里面有几个页面,相互之间有跳转关系的 - // Schema 参见:https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr version: '1.0.0', componentsMap: [ { diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/schema.json5 b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/schema.json5 index 3c767dfd9..483e52731 100644 --- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/schema.json5 +++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/schema.json5 @@ -1,6 +1,5 @@ { // 这是一个关于国际化的 schema 示例 - // Schema 参见:https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr version: '1.0.0', componentsMap: [ { diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/schema.json5 b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/schema.json5 index 4f5f5db7f..9a89838a1 100644 --- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/schema.json5 +++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/schema.json5 @@ -1,6 +1,5 @@ { // 这是一个关于国际化的 schema 示例 - // Schema 参见:https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr version: '1.0.0', componentsMap: [ { diff --git a/modules/material-parser/README.md b/modules/material-parser/README.md index 4507b7e6e..0d3f5555d 100644 --- a/modules/material-parser/README.md +++ b/modules/material-parser/README.md @@ -4,7 +4,7 @@ 本模块负责物料接入,能自动扫描、解析源码组件,并最终产出一份符合《中后台搭建组件描述协议》的 **JSON Schema**。 -详见[文档](https://lowcode-engine.cn/docV2/yhgcqb)。 +详见[文档](https://lowcode-engine.cn/site/docs/guide/design/materialParser)。 ## demo diff --git a/modules/material-parser/test/fixtures/ts-component2/package.json b/modules/material-parser/test/fixtures/ts-component2/package.json index 95bb4bd8d..e3fde3e59 100644 --- a/modules/material-parser/test/fixtures/ts-component2/package.json +++ b/modules/material-parser/test/fixtures/ts-component2/package.json @@ -34,7 +34,7 @@ "@alife/build-plugin-lowcode": "^1.0.7", "@alib/build-scripts": "^0.1.3", "@alifd/adaptor-generate": "^0.1.3", - "build-plugin-component": "^0.2.0", + "build-plugin-component": "^1.0.0", "build-plugin-fusion": "^0.1.0", "build-plugin-fusion-cool": "^0.1.0", "build-plugin-moment-locales": "^0.1.0", diff --git a/package.json b/package.json index 7e70b38ae..cbd75e75b 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,8 @@ "lockfile": "enable" }, "resolutions": { - "@builder/babel-preset-ice": "1.0.1" - } + "@builder/babel-preset-ice": "1.0.1", + "typescript": "4.6.2" + }, + "repository": "git@github.com:alibaba/lowcode-engine.git" } diff --git a/packages/designer/jest.config.js b/packages/designer/jest.config.js index 70a1da03d..6866d24a0 100644 --- a/packages/designer/jest.config.js +++ b/packages/designer/jest.config.js @@ -10,8 +10,10 @@ const jestConfig = { // // '^.+\\.(js|jsx)$': 'babel-jest', // }, // testMatch: ['**/node-children.test.ts'], + // testMatch: ['**/plugin-manager.test.ts'], // testMatch: ['**/history/history.test.ts'], - // testMatch: ['**/host-view.test.tsx'], + // testMatch: ['**/document-model.test.ts'], + // testMatch: ['**/prop.test.ts'], // testMatch: ['(/tests?/.*(test))\\.[jt]s$'], transformIgnorePatterns: [ `/node_modules/(?!${esModules})/`, diff --git a/packages/designer/package.json b/packages/designer/package.json index 830d2fa04..4f35daf71 100644 --- a/packages/designer/package.json +++ b/packages/designer/package.json @@ -16,12 +16,9 @@ "license": "MIT", "dependencies": { "@alilc/lowcode-editor-core": "1.0.17", - "@alilc/lowcode-shell": "1.0.17", "@alilc/lowcode-types": "1.0.17", "@alilc/lowcode-utils": "1.0.17", "classnames": "^2.2.6", - "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.5", "react": "^16", "react-dom": "^16.7.0", "ric-shim": "^1.0.1", @@ -30,6 +27,7 @@ }, "devDependencies": { "@alib/build-scripts": "^0.1.29", + "@alilc/lowcode-shell": "1.0.17", "@alilc/lowcode-test-mate": "^1.0.1", "@testing-library/react": "^11.2.2", "@types/classnames": "^2.2.7", @@ -41,8 +39,12 @@ "@types/react-dom": "^16", "@types/semver": "7.3.9", "babel-jest": "^26.5.2", - "build-plugin-component": "^0.2.10", - "build-scripts-config": "^0.1.8", + "build-plugin-component": "^1.0.0", + "build-scripts-config": "^3.0.3", + "enzyme": "^3.11.0", + "@types/enzyme": "^3.10.12", + "enzyme-adapter-react-16": "^1.15.5", + "@types/enzyme-adapter-react-16": "^1.0.6", "jest": "^26.6.3", "lodash": "^4.17.20", "moment": "^2.29.1", diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-container.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-container.tsx index 63874b4ca..05a164c98 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-container.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-container.tsx @@ -2,7 +2,8 @@ import * as React from 'react'; import { Component, Fragment, ReactElement, PureComponent } from 'react'; import classNames from 'classnames'; import { computed, observer, Title, globalLocale } from '@alilc/lowcode-editor-core'; -import { I18nData, isI18nData, TitleContent } from '@alilc/lowcode-types'; +import { I18nData, TitleContent } from '@alilc/lowcode-types'; +import { isI18nData } from '@alilc/lowcode-utils'; import { DropLocation } from '../../designer'; import { BuiltinSimulatorHost } from '../../builtin-simulator/host'; import { ParentalNode } from '../../document/node'; diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx index 31ecc2e12..bb5f288de 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx @@ -9,9 +9,9 @@ import { ComponentType, } from 'react'; import classNames from 'classnames'; -import { observer, computed, Tip, globalContext, makeObservable } from '@alilc/lowcode-editor-core'; -import { createIcon, isReactComponent } from '@alilc/lowcode-utils'; -import { ActionContentObject, isActionContentObject } from '@alilc/lowcode-types'; +import { observer, computed, Tip, globalContext } from '@alilc/lowcode-editor-core'; +import { createIcon, isReactComponent, isActionContentObject } from '@alilc/lowcode-utils'; +import { ActionContentObject } from '@alilc/lowcode-types'; import { BuiltinSimulatorHost } from '../host'; import { OffsetObserver } from '../../designer'; import { Node } from '../../document'; diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index c7d2ea544..c1c66e56c 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -39,8 +39,6 @@ import { transactionManager, } from '@alilc/lowcode-utils'; import { - DragObjectType, - DragNodeObject, isShaken, LocateEvent, isDragAnyObject, @@ -62,6 +60,8 @@ import { ComponentSchema, Package, TransitionType, + DragObjectType, + DragNodeObject, } from '@alilc/lowcode-types'; import { BuiltinSimulatorRenderer } from './renderer'; import clipboard from '../designer/clipboard'; @@ -542,6 +542,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost { }; // An object taking on a particular shape -LowcodeTypes.shape = (typesMap: any) => { +LowcodeTypes.shape = (typesMap: any = {}) => { const configs = Object.keys(typesMap).map(key => { return { name: key, diff --git a/packages/designer/src/component-meta.ts b/packages/designer/src/component-meta.ts index 4e1a74c77..95b974890 100644 --- a/packages/designer/src/component-meta.ts +++ b/packages/designer/src/component-meta.ts @@ -8,12 +8,12 @@ import { TitleContent, TransformedComponentMetadata, NestingFilter, - isTitleConfig, I18nData, LiveTextEditingConfig, FieldConfig, + MetadataTransducer, } from '@alilc/lowcode-types'; -import { deprecate, isRegExp } from '@alilc/lowcode-utils'; +import { deprecate, isRegExp, isTitleConfig } from '@alilc/lowcode-utils'; import { computed, engineConfig } from '@alilc/lowcode-editor-core'; import EventEmitter from 'events'; import { componentDefaults, legacyIssues } from './transducers'; @@ -128,8 +128,8 @@ export class ComponentMeta { private _isTopFixed?: boolean; - get isTopFixed() { - return this._isTopFixed; + get isTopFixed(): boolean { + return !!(this._isTopFixed); } private parentWhitelist?: NestingFilter | null; @@ -279,7 +279,7 @@ export class ComponentMeta { return result as any; } - isRootComponent(includeBlock = true) { + isRootComponent(includeBlock = true): boolean { return ( this.componentName === 'Page' || this.componentName === 'Component' || @@ -326,7 +326,7 @@ export class ComponentMeta { return true; } - checkNestingDown(my: Node, target: Node | NodeSchema | NodeSchema[]) { + checkNestingDown(my: Node, target: Node | NodeSchema | NodeSchema[]): boolean { // 检查父子关系,直接约束型,在画布中拖拽直接掠过目标容器 if (this.childWhitelist) { const _target: any = !Array.isArray(target) ? [target] : target; @@ -375,19 +375,7 @@ function preprocessMetadata(metadata: ComponentMetadata): TransformedComponentMe }; } -export interface MetadataTransducer { - (prev: TransformedComponentMetadata): TransformedComponentMetadata; - /** - * 0 - 9 system - * 10 - 99 builtin-plugin - * 100 - app & plugin - */ - level?: number; - /** - * use to replace TODO - */ - id?: string; -} + const metadataTransducers: MetadataTransducer[] = []; export function registerMetadataTransducer( diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts index 4eeee1e0a..059aaba85 100644 --- a/packages/designer/src/designer/designer.ts +++ b/packages/designer/src/designer/designer.ts @@ -8,10 +8,11 @@ import { IEditor, CompositeObject, PropsList, - isNodeSchema, NodeSchema, + PropsTransducer, + IShellModelFactory, } from '@alilc/lowcode-types'; -import { megreAssets, AssetsJson } from '@alilc/lowcode-utils'; +import { megreAssets, AssetsJson, isNodeSchema } from '@alilc/lowcode-utils'; import { Project } from '../project'; import { Node, DocumentModel, insertChildren, ParentalNode, TransformStage } from '../document'; import { ComponentMeta } from '../component-meta'; @@ -28,6 +29,7 @@ import { BemToolsManager } from '../builtin-simulator/bem-tools/manager'; export interface DesignerProps { editor: IEditor; + shellModelFactory: IShellModelFactory; className?: string; style?: object; defaultSchema?: ProjectSchema; @@ -58,6 +60,8 @@ export class Designer { readonly bemToolsManager = new BemToolsManager(this); + readonly shellModelFactory: IShellModelFactory; + get currentDocument() { return this.project.currentDocument; } @@ -74,26 +78,18 @@ export class Designer { constructor(props: DesignerProps) { makeObservable(this); - const { editor, name } = props; + const { editor, name, shellModelFactory } = props; this.editor = editor; this.name = name; + this.shellModelFactory = shellModelFactory; this.setProps(props); this.project = new Project(this, props.defaultSchema, name); - let startTime: any; - let src = ''; this.dragon.onDragstart((e) => { - startTime = Date.now() / 1000; this.detecting.enable = false; const { dragObject } = e; if (isDragNodeObject(dragObject)) { - const node = dragObject.nodes[0]?.parent; - const npm = node?.componentMeta?.npm; - src = - [npm?.package, npm?.componentName].filter((item) => !!item).join('-') || - node?.componentMeta?.componentName || - ''; if (dragObject.nodes.length === 1) { if (dragObject.nodes[0].parent) { // ensure current selecting @@ -138,34 +134,6 @@ export class Designer { if (nodes) { loc.document.selection.selectAll(nodes.map((o) => o.id)); setTimeout(() => this.activeTracker.track(nodes![0]), 10); - const endTime: any = Date.now() / 1000; - const parent = nodes[0]?.parent; - const npm = parent?.componentMeta?.npm; - const dest = - [npm?.package, npm?.componentName].filter((item) => !!item).join('-') || - parent?.componentMeta?.componentName || - ''; - // eslint-disable-next-line no-unused-expressions - // this.postEvent('drag', { - // time: (endTime - startTime).toFixed(2), - // selected: nodes - // ?.map((n) => { - // if (!n) { - // return; - // } - // // eslint-disable-next-line no-shadow - // const npm = n?.componentMeta?.npm; - // return ( - // [npm?.package, npm?.componentName].filter((item) => !!item).join('-') || - // n?.componentMeta?.componentName - // ); - // }) - // .join('&'), - // align: loc?.detail?.near?.align || '', - // pos: loc?.detail?.near?.pos || '', - // src, - // dest, - // }); } } } @@ -512,7 +480,7 @@ export class Designer { getComponentMeta( componentName: string, generateMetadata?: () => ComponentMetadata | null, - ): ComponentMeta { + ) { if (this._componentMetasMap.has(componentName)) { return this._componentMetasMap.get(componentName)!; } @@ -554,7 +522,7 @@ export class Designer { return maps; } - private propsReducers = new Map(); + private propsReducers = new Map(); transformProps(props: CompositeObject | PropsList, node: Node, stage: TransformStage) { if (Array.isArray(props)) { @@ -578,7 +546,7 @@ export class Designer { }, props); } - addPropsReducer(reducer: PropsReducer, stage: TransformStage) { + addPropsReducer(reducer: PropsTransducer, stage: TransformStage) { const reducers = this.propsReducers.get(stage); if (reducers) { reducers.push(reducer); @@ -594,11 +562,4 @@ export class Designer { purge() { // TODO: } -} - -export type PropsReducerContext = { stage: TransformStage }; -export type PropsReducer = ( - props: CompositeObject, - node: Node, - ctx?: PropsReducerContext, -) => CompositeObject; +} \ No newline at end of file diff --git a/packages/designer/src/designer/dragon.ts b/packages/designer/src/designer/dragon.ts index f7de70483..55d52d2ca 100644 --- a/packages/designer/src/designer/dragon.ts +++ b/packages/designer/src/designer/dragon.ts @@ -1,7 +1,6 @@ import { EventEmitter } from 'events'; import { obx, makeObservable } from '@alilc/lowcode-editor-core'; -import { NodeSchema } from '@alilc/lowcode-types'; -import { Node as ShellNode } from '@alilc/lowcode-shell'; +import { DragNodeObject, DragAnyObject, DragObjectType, DragNodeDataObject, DragObject, IPublicModelNode } from '@alilc/lowcode-types'; import { setNativeSelection, cursor } from '@alilc/lowcode-utils'; import { DropLocation } from './location'; import { Node, DocumentModel } from '../document'; @@ -80,31 +79,6 @@ export interface ISensor { getNodeInstanceFromElement(e: Element | null): NodeInstance | null; } -export type DragObject = DragNodeObject | DragNodeDataObject | DragAnyObject; - -export enum DragObjectType { - // eslint-disable-next-line no-shadow - Node = 'node', - NodeData = 'nodedata', -} - -export interface DragNodeObject { - type: DragObjectType.Node; - nodes: (Node | ShellNode)[]; -} -export interface DragNodeDataObject { - type: DragObjectType.NodeData; - data: NodeSchema | NodeSchema[]; - thumbnail?: string; - description?: string; - [extra: string]: any; -} - -export interface DragAnyObject { - type: string; - [key: string]: any; -} - export function isDragNodeObject(obj: any): obj is DragNodeObject { return obj && obj.type === DragObjectType.Node; } @@ -231,13 +205,13 @@ export class Dragon { * @param dragObject 拖拽对象 * @param boostEvent 拖拽初始时事件 */ - boost(dragObject: DragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: Node | ShellNode) { + boost(dragObject: DragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: Node | IPublicModelNode) { const { designer } = this; const masterSensors = this.getMasterSensors(); const handleEvents = makeEventsHandler(boostEvent, masterSensors); const newBie = !isDragNodeObject(dragObject); const forceCopyState = - isDragNodeObject(dragObject) && dragObject.nodes.some((node: Node | ShellNode) => (typeof node.isSlot === 'function' ? node.isSlot() : node.isSlot)); + isDragNodeObject(dragObject) && dragObject.nodes.some((node: Node | IPublicModelNode) => (typeof node.isSlot === 'function' ? node.isSlot() : node.isSlot)); const isBoostFromDragAPI = isDragEvent(boostEvent); let lastSensor: ISensor | undefined; diff --git a/packages/designer/src/designer/setting/setting-field.ts b/packages/designer/src/designer/setting/setting-field.ts index a38c1323d..9b766519c 100644 --- a/packages/designer/src/designer/setting/setting-field.ts +++ b/packages/designer/src/designer/setting/setting-field.ts @@ -1,10 +1,9 @@ -import { TitleContent, isDynamicSetter, SetterType, DynamicSetter, FieldExtraProps, FieldConfig, CustomView, isCustomView } from '@alilc/lowcode-types'; +import { TitleContent, SetterType, DynamicSetter, FieldExtraProps, FieldConfig, CustomView, ISetValueOptions } from '@alilc/lowcode-types'; import { Transducer } from './utils'; import { SettingPropEntry } from './setting-prop-entry'; import { SettingEntry } from './setting-entry'; import { computed, obx, makeObservable, action } from '@alilc/lowcode-editor-core'; -import { cloneDeep } from '@alilc/lowcode-utils'; -import type { ISetValueOptions } from '../../types'; +import { cloneDeep, isCustomView, isDynamicSetter } from '@alilc/lowcode-utils'; function getSettingFieldCollectorKey(parent: SettingEntry, config: FieldConfig) { let cur = parent; diff --git a/packages/designer/src/designer/setting/setting-prop-entry.ts b/packages/designer/src/designer/setting/setting-prop-entry.ts index a91cb7da0..722c9cc45 100644 --- a/packages/designer/src/designer/setting/setting-prop-entry.ts +++ b/packages/designer/src/designer/setting/setting-prop-entry.ts @@ -1,13 +1,11 @@ import { obx, computed, makeObservable, runInAction, Setters } from '@alilc/lowcode-editor-core'; -import { GlobalEvent, IEditor, isJSExpression } from '@alilc/lowcode-types'; -import { uniqueId } from '@alilc/lowcode-utils'; -import { SettingPropEntry as ShellSettingPropEntry } from '@alilc/lowcode-shell'; +import { GlobalEvent, IEditor, ISetValueOptions } from '@alilc/lowcode-types'; +import { uniqueId, isJSExpression } from '@alilc/lowcode-utils'; import { SettingEntry } from './setting-entry'; import { Node } from '../../document'; import { ComponentMeta } from '../../component-meta'; import { Designer } from '../designer'; import { EventEmitter } from 'events'; -import { ISetValueOptions } from '../../types'; import { isSettingField } from './setting-field'; export class SettingPropEntry implements SettingEntry { @@ -367,6 +365,6 @@ export class SettingPropEntry implements SettingEntry { } internalToShellPropEntry() { - return ShellSettingPropEntry.create(this) as any; + return this.designer.shellModelFactory.createSettingPropEntry(this); } } diff --git a/packages/designer/src/designer/setting/setting-top-entry.ts b/packages/designer/src/designer/setting/setting-top-entry.ts index 663fd0b17..b2ec25723 100644 --- a/packages/designer/src/designer/setting/setting-top-entry.ts +++ b/packages/designer/src/designer/setting/setting-top-entry.ts @@ -1,5 +1,6 @@ import { EventEmitter } from 'events'; -import { CustomView, isCustomView, IEditor } from '@alilc/lowcode-types'; +import { CustomView, IEditor } from '@alilc/lowcode-types'; +import { isCustomView } from '@alilc/lowcode-utils'; import { computed } from '@alilc/lowcode-editor-core'; import { SettingEntry } from './setting-entry'; import { SettingField } from './setting-field'; diff --git a/packages/designer/src/designer/setting/utils.ts b/packages/designer/src/designer/setting/utils.ts index 093e33e75..c921d277c 100644 --- a/packages/designer/src/designer/setting/utils.ts +++ b/packages/designer/src/designer/setting/utils.ts @@ -1,6 +1,7 @@ // all this file for polyfill vision logic import { isValidElement } from 'react'; -import { isSetterConfig, isDynamicSetter, FieldConfig, SetterConfig } from '@alilc/lowcode-types'; +import { FieldConfig, SetterConfig } from '@alilc/lowcode-types'; +import { isSetterConfig, isDynamicSetter } from '@alilc/lowcode-utils'; import { SettingField } from './setting-field'; function getHotterFromSetter(setter) { diff --git a/packages/designer/src/document/document-model.ts b/packages/designer/src/document/document-model.ts index 08d67d238..a4ba37a68 100644 --- a/packages/designer/src/document/document-model.ts +++ b/packages/designer/src/document/document-model.ts @@ -1,15 +1,15 @@ import { makeObservable, obx, engineConfig, action, runWithGlobalEventOff, wrapWithEventSwitch } from '@alilc/lowcode-editor-core'; -import { NodeData, isJSExpression, isDOMText, NodeSchema, isNodeSchema, RootSchema, PageSchema, ComponentsMap } from '@alilc/lowcode-types'; +import { NodeData, NodeSchema, RootSchema, PageSchema, ComponentsMap, DragNodeObject, DragNodeDataObject } from '@alilc/lowcode-types'; import { EventEmitter } from 'events'; import { Project } from '../project'; import { ISimulatorHost } from '../simulator'; import { ComponentMeta } from '../component-meta'; -import { isDragNodeDataObject, DragNodeObject, DragNodeDataObject, DropLocation, Designer, isDragNodeObject } from '../designer'; +import { isDragNodeDataObject, DropLocation, Designer, isDragNodeObject } from '../designer'; import { Node, insertChildren, insertChild, isNode, RootNode, ParentalNode } from './node/node'; import { Selection } from './selection'; import { History } from './history'; import { TransformStage, ModalNodesManager } from './node'; -import { uniqueId, isPlainObject, compatStage } from '@alilc/lowcode-utils'; +import { uniqueId, isPlainObject, compatStage, isJSExpression, isDOMText, isNodeSchema } from '@alilc/lowcode-utils'; export type GetDataType = T extends undefined ? NodeType extends { diff --git a/packages/designer/src/document/history.ts b/packages/designer/src/document/history.ts index bb3cb11d7..f14182e72 100644 --- a/packages/designer/src/document/history.ts +++ b/packages/designer/src/document/history.ts @@ -1,7 +1,6 @@ import { EventEmitter } from 'events'; import { reaction, untracked, globalContext, Editor } from '@alilc/lowcode-editor-core'; import { NodeSchema } from '@alilc/lowcode-types'; -import { History as ShellHistory } from '@alilc/lowcode-shell'; export interface Serialization { serialize(data: K): T; @@ -42,6 +41,12 @@ export class History { if (this.asleep) return; untracked(() => { const log = this.currentSerialization.serialize(data); + + // do not record unchanged data + if (this.session.data === log) { + return; + } + if (this.session.isActive()) { this.session.log(log); } else { @@ -194,10 +199,6 @@ export class History { isModified() { return this.isSavePoint(); } - - internalToShellHistory() { - return new ShellHistory(this); - } } export class Session { diff --git a/packages/designer/src/document/node/node-children.ts b/packages/designer/src/document/node/node-children.ts index 7f42c7e6c..d00d74b6e 100644 --- a/packages/designer/src/document/node/node-children.ts +++ b/packages/designer/src/document/node/node-children.ts @@ -1,17 +1,15 @@ import { obx, computed, globalContext, makeObservable } from '@alilc/lowcode-editor-core'; import { Node, ParentalNode } from './node'; import { TransformStage } from './transform-stage'; -import { NodeData, isNodeSchema } from '@alilc/lowcode-types'; -import { shallowEqual, compatStage } from '@alilc/lowcode-utils'; +import { NodeData } from '@alilc/lowcode-types'; +import { shallowEqual, compatStage, isNodeSchema } from '@alilc/lowcode-utils'; import { EventEmitter } from 'events'; import { foreachReverse } from '../../utils/tree'; import { NodeRemoveOptions } from '../../types'; - export interface IOnChangeOptions { type: string; node: Node; } - export class NodeChildren { @obx.shallow private children: Node[]; @@ -356,7 +354,7 @@ export class NodeChildren { return this.children.find(fn); } - reduce(fn: (acc: any, cur: Node) => any, initialValue: any) { + reduce(fn: (acc: any, cur: Node) => any, initialValue: any): void { return this.children.reduce(fn, initialValue); } @@ -364,7 +362,7 @@ export class NodeChildren { remover: (node: Node, idx: number) => boolean, adder: (children: Node[]) => NodeData[] | null, sorter: (firstNode: Node, secondNode: Node) => number, - ) { + ): any { let changed = false; if (remover) { const willRemove = this.children.filter(remover); diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 9fe98e473..ec6cc811b 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -2,8 +2,6 @@ import { ReactElement } from 'react'; import { EventEmitter } from 'events'; import { obx, computed, autorun, makeObservable, runInAction, wrapWithEventSwitch, action } from '@alilc/lowcode-editor-core'; import { - isDOMText, - isJSExpression, NodeSchema, PropsMap, PropsList, @@ -16,10 +14,10 @@ import { CompositeValue, GlobalEvent, ComponentAction, + IPublicModelNode, } from '@alilc/lowcode-types'; -import { compatStage } from '@alilc/lowcode-utils'; +import { compatStage, isDOMText, isJSExpression } from '@alilc/lowcode-utils'; import { SettingTopEntry } from '@alilc/lowcode-designer'; -import { Node as ShellNode } from '@alilc/lowcode-shell'; import { Props, getConvertedExtraKey } from './props/props'; import { DocumentModel } from '../document-model'; import { NodeChildren } from './node-children'; @@ -94,7 +92,7 @@ export class Node { /** * 节点组件类型 - * 特殊节点: + * 特殊节点: * * Page 页面 * * Block 区块 * * Component 组件/元件 @@ -368,8 +366,8 @@ export class Node { this._slotFor = slotFor; } - internalToShellNode(): ShellNode | null { - return ShellNode.create(this); + internalToShellNode(): IPublicModelNode | null { + return this.document.designer.shellModelFactory.createNode(this); } /** diff --git a/packages/designer/src/document/node/props/prop.ts b/packages/designer/src/document/node/props/prop.ts index 78349154f..634a6b14b 100644 --- a/packages/designer/src/document/node/props/prop.ts +++ b/packages/designer/src/document/node/props/prop.ts @@ -1,6 +1,6 @@ import { untracked, computed, obx, engineConfig, action, makeObservable, mobx, runInAction } from '@alilc/lowcode-editor-core'; -import { CompositeValue, GlobalEvent, isJSExpression, isJSSlot, JSSlot, SlotSchema } from '@alilc/lowcode-types'; -import { uniqueId, isPlainObject, hasOwnProperty, compatStage } from '@alilc/lowcode-utils'; +import { CompositeValue, GlobalEvent, JSSlot, SlotSchema } from '@alilc/lowcode-types'; +import { uniqueId, isPlainObject, hasOwnProperty, compatStage, isJSExpression, isJSSlot } from '@alilc/lowcode-utils'; import { valueToSource } from './value-to-source'; import { Props } from './props'; import { SlotNode, Node } from '../node'; diff --git a/packages/designer/src/plugin/plugin-context.ts b/packages/designer/src/plugin/plugin-context.ts index 78d2df3b1..7ddc3a5bd 100644 --- a/packages/designer/src/plugin/plugin-context.ts +++ b/packages/designer/src/plugin/plugin-context.ts @@ -1,18 +1,15 @@ /* eslint-disable no-multi-assign */ -import { Editor, EngineConfig, engineConfig, Setters as InnerSetters } from '@alilc/lowcode-editor-core'; -import { Designer, ILowCodePluginManager } from '@alilc/lowcode-designer'; -import { Skeleton as InnerSkeleton } from '@alilc/lowcode-editor-skeleton'; +import { EngineConfig, engineConfig } from '@alilc/lowcode-editor-core'; +import { ILowCodePluginManager } from '@alilc/lowcode-designer'; import { - Hotkey, - Project, - Skeleton, - Setters, - Material, - Event, - editorSymbol, - designerSymbol, - skeletonSymbol, -} from '@alilc/lowcode-shell'; + IPublicApiHotkey, + IPublicApiProject, + IPublicApiSkeleton, + IPublicApiSetters, + IPublicApiMaterial, + IPublicApiEvent, + IPublicApiCommon, +} from '@alilc/lowcode-types'; import { getLogger, Logger } from '@alilc/lowcode-utils'; import { ILowCodePluginContext, @@ -20,43 +17,33 @@ import { ILowCodePluginPreferenceDeclaration, PreferenceValueType, IPluginPreferenceMananger, + ILowCodePluginContextApiAssembler, + ILowCodePluginContextPrivate, } from './plugin-types'; import { isValidPreferenceKey } from './plugin-utils'; -export class PluginContext implements ILowCodePluginContext { - private readonly [editorSymbol]: Editor; - private readonly [designerSymbol]: Designer; - private readonly [skeletonSymbol]: InnerSkeleton; - hotkey: Hotkey; - project: Project; - skeleton: Skeleton; - logger: Logger; - setters: Setters; - material: Material; + +export default class PluginContext implements ILowCodePluginContext, ILowCodePluginContextPrivate { + hotkey: IPublicApiHotkey; + project: IPublicApiProject; + skeleton: IPublicApiSkeleton; + setters: IPublicApiSetters; + material: IPublicApiMaterial; + event: IPublicApiEvent; config: EngineConfig; - event: Event; + common: IPublicApiCommon; + logger: Logger; plugins: ILowCodePluginManager; preference: IPluginPreferenceMananger; - constructor(plugins: ILowCodePluginManager, options: IPluginContextOptions) { - const editor = this[editorSymbol] = plugins.editor; - const designer = this[designerSymbol] = editor.get('designer')!; - const skeleton = this[skeletonSymbol] = editor.get('skeleton')!; - const setters = editor.get('setters')!; - const project = editor.get('project')!; - const material = editor.get('material')!; - - const { pluginName = 'anonymous' } = options; - // const project = designer?.project; - const innerSetters = new InnerSetters(); - this.hotkey = new Hotkey(editor.name, editor.workspaceMode); - this.project = project; - this.skeleton = new Skeleton(skeleton); - this.setters = setters; - this.material = material; - this.config = engineConfig; + constructor( + plugins: ILowCodePluginManager, + options: IPluginContextOptions, + contextApiAssembler: ILowCodePluginContextApiAssembler, + ) { + contextApiAssembler.assembleApis(this); this.plugins = plugins; - this.event = new Event(editor, { prefix: 'common' }); + const { pluginName = 'anonymous' } = options; this.logger = getLogger({ level: 'warn', bizName: `designer:plugin:${pluginName}` }); const enhancePluginContextHook = engineConfig.get('enhancePluginContextHook'); diff --git a/packages/designer/src/plugin/plugin-manager.ts b/packages/designer/src/plugin/plugin-manager.ts index 634276d70..bc0dfd947 100644 --- a/packages/designer/src/plugin/plugin-manager.ts +++ b/packages/designer/src/plugin/plugin-manager.ts @@ -1,4 +1,4 @@ -import { Editor, engineConfig } from '@alilc/lowcode-editor-core'; +import { engineConfig } from '@alilc/lowcode-editor-core'; import { getLogger } from '@alilc/lowcode-utils'; import { ILowCodePlugin, @@ -12,10 +12,12 @@ import { PluginPreference, ILowCodePluginPreferenceDeclaration, isLowCodeRegisterOptions, + ILowCodePluginContextApiAssembler, } from './plugin-types'; import { filterValidOptions } from './plugin-utils'; import { LowCodePlugin } from './plugin'; -import { PluginContext } from './plugin-context'; +// eslint-disable-next-line import/no-named-as-default +import LowCodePluginContext from './plugin-context'; import { invariant } from '../utils'; import sequencify from './sequencify'; import semverSatisfies from 'semver/functions/satisfies'; @@ -28,14 +30,15 @@ export class LowCodePluginManager implements ILowCodePluginManager { private pluginsMap: Map = new Map(); private pluginPreference?: PluginPreference = new Map(); - private editor: Editor; - constructor(editor: Editor) { - this.editor = editor; + contextApiAssembler: ILowCodePluginContextApiAssembler; + + constructor(contextApiAssembler: ILowCodePluginContextApiAssembler) { + this.contextApiAssembler = contextApiAssembler; } - _getLowCodePluginContext(options: IPluginContextOptions) { - return new PluginContext(this, options); + private _getLowCodePluginContext(options: IPluginContextOptions) { + return new LowCodePluginContext(this, options, this.contextApiAssembler); } isEngineVersionMatched(versionExp: string): boolean { diff --git a/packages/designer/src/plugin/plugin-types.ts b/packages/designer/src/plugin/plugin-types.ts index f9a1ea1dd..279a1e459 100644 --- a/packages/designer/src/plugin/plugin-types.ts +++ b/packages/designer/src/plugin/plugin-types.ts @@ -1,8 +1,17 @@ -import { CompositeObject, ComponentAction } from '@alilc/lowcode-types'; import Logger from 'zen-logger'; -import { Hotkey, Skeleton, Project, Event, Material } from '@alilc/lowcode-shell'; +import { + IPublicApiHotkey, + IPublicApiProject, + IPublicApiSkeleton, + IPublicApiSetters, + IPublicApiMaterial, + IPublicApiEvent, + IPublicApiCommon, + CompositeObject, + ComponentAction, + MetadataTransducer, +} from '@alilc/lowcode-types'; import { EngineConfig } from '@alilc/lowcode-editor-core'; -import { MetadataTransducer } from '@alilc/lowcode-designer'; import { Setters } from '../types'; export type PreferenceValueType = string | number | boolean; @@ -96,17 +105,32 @@ export interface IPluginPreferenceMananger { } export interface ILowCodePluginContext { - skeleton: Skeleton; - hotkey: Hotkey; + get skeleton(): IPublicApiSkeleton; + get hotkey(): IPublicApiHotkey; + get setters(): IPublicApiSetters; + get config(): EngineConfig; + get material(): IPublicApiMaterial; + get event(): IPublicApiEvent; + get project(): IPublicApiProject; + get common(): IPublicApiCommon; logger: Logger; plugins: ILowCodePluginManager; - setters: Setters; - config: EngineConfig; - material: Material; - event: Event; - project: Project; preference: IPluginPreferenceMananger; } +export interface ILowCodePluginContextPrivate { + set hotkey(hotkey: IPublicApiHotkey); + set project(project: IPublicApiProject); + set skeleton(skeleton: IPublicApiSkeleton); + set setters(setters: Setters); + set material(material: IPublicApiMaterial); + set event(event: IPublicApiEvent); + set config(config: EngineConfig); + set common(common: IPublicApiCommon); +} +export interface ILowCodePluginContextApiAssembler { + assembleApis: (context: ILowCodePluginContextPrivate) => void; +} + interface ILowCodePluginManagerPluginAccessor { [pluginName: string]: ILowCodePlugin | any; diff --git a/packages/designer/src/project/project.ts b/packages/designer/src/project/project.ts index 046dbe093..67035aad4 100644 --- a/packages/designer/src/project/project.ts +++ b/packages/designer/src/project/project.ts @@ -7,9 +7,8 @@ import { RootSchema, ComponentsMap, TransformStage, - isLowCodeComponentType, - isProCodeComponentType, } from '@alilc/lowcode-types'; +import { isLowCodeComponentType, isProCodeComponentType } from '@alilc/lowcode-utils'; import { ISimulatorHost } from '../simulator'; export class Project { diff --git a/packages/designer/src/types/index.ts b/packages/designer/src/types/index.ts index 43b88bf28..c0fffcc50 100644 --- a/packages/designer/src/types/index.ts +++ b/packages/designer/src/types/index.ts @@ -1,6 +1,5 @@ import { getSetter, registerSetter, getSettersMap } from '@alilc/lowcode-editor-core'; -import { isFormEvent, compatibleLegaoSchema, getNodeSchemaById } from '@alilc/lowcode-utils'; -import { isNodeSchema } from '@alilc/lowcode-types'; +import { isFormEvent, compatibleLegaoSchema, getNodeSchemaById, isNodeSchema } from '@alilc/lowcode-utils'; export type Setters = { getSetter: typeof getSetter; @@ -18,21 +17,4 @@ export const utils = { compatibleLegaoSchema, getNodeSchemaById, }; -export type Utils = typeof utils; - -export enum PROP_VALUE_CHANGED_TYPE { - /** - * normal set value - */ - SET_VALUE = 'SET_VALUE', - /** - * value changed caused by sub-prop value change - */ - SUB_VALUE_CHANGE = 'SUB_VALUE_CHANGE', -} - -export interface ISetValueOptions { - disableMutator?: boolean; - type?: PROP_VALUE_CHANGED_TYPE; - fromSetHotValue?: boolean; -} \ No newline at end of file +export type Utils = typeof utils; \ No newline at end of file diff --git a/packages/designer/tests/bugs/prop-variable-jse.test.ts b/packages/designer/tests/bugs/prop-variable-jse.test.ts index b39b5b54e..a27fa59cf 100644 --- a/packages/designer/tests/bugs/prop-variable-jse.test.ts +++ b/packages/designer/tests/bugs/prop-variable-jse.test.ts @@ -1,12 +1,12 @@ -// @ts-nocheck import { Editor } from '@alilc/lowcode-editor-core'; -import { isJSBlock, TransformStage } from '@alilc/lowcode-types'; -import { isPlainObject, isVariable } from '@alilc/lowcode-utils'; +import { TransformStage } from '@alilc/lowcode-types'; +import { isPlainObject, isVariable, isJSBlock } from '@alilc/lowcode-utils'; import '../fixtures/window'; import { Designer } from '../../src/designer/designer'; import { DocumentModel } from '../../src/document/document-model'; import { Project } from '../../src/project/project'; import formSchema from '../fixtures/schema/form'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; /** * bug 背景: @@ -58,7 +58,7 @@ describe('Node 方法测试', () => { it('原始 prop 值是 variable 结构,通过一个 propsReducer 转成了 JSExpression 结构', () => { editor = new Editor(); - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); designer.addPropsReducer(upgradePropsReducer, TransformStage.Upgrade); project = designer.project; doc = new DocumentModel(project, formSchema); diff --git a/packages/designer/tests/builtin-simulator/bem-tools/drag-resize-engine.test.ts b/packages/designer/tests/builtin-simulator/bem-tools/drag-resize-engine.test.ts index 5f52e14b3..ccdc4b2b6 100644 --- a/packages/designer/tests/builtin-simulator/bem-tools/drag-resize-engine.test.ts +++ b/packages/designer/tests/builtin-simulator/bem-tools/drag-resize-engine.test.ts @@ -1,17 +1,12 @@ import '../../fixtures/window'; -import { set } from '../../utils'; import { Editor, globalContext } from '@alilc/lowcode-editor-core'; import { Project } from '../../../src/project/project'; import { DocumentModel } from '../../../src/document/document-model'; import { Designer } from '../../../src/designer/designer'; import DragResizeEngine from '../../../src/builtin-simulator/bem-tools/drag-resize-engine'; import formSchema from '../../fixtures/schema/form'; -import divMetadata from '../../fixtures/component-metadata/div'; -import formMetadata from '../../fixtures/component-metadata/form'; -import otherMeta from '../../fixtures/component-metadata/other'; -import pageMetadata from '../../fixtures/component-metadata/page'; import { fireEvent, createEvent } from '@testing-library/react'; -import { create } from 'lodash'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; describe('DragResizeEngine 测试', () => { let editor: Editor; @@ -26,7 +21,7 @@ describe('DragResizeEngine 测试', () => { }); beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; doc = project.createDocument(formSchema); doc.open(); diff --git a/packages/designer/tests/builtin-simulator/bem-tools/manager.test.tsx b/packages/designer/tests/builtin-simulator/bem-tools/manager.test.tsx index 32e34020f..bed1e27de 100644 --- a/packages/designer/tests/builtin-simulator/bem-tools/manager.test.tsx +++ b/packages/designer/tests/builtin-simulator/bem-tools/manager.test.tsx @@ -1,21 +1,8 @@ import '../../fixtures/window'; -import { set, delayObxTick, delay } from '../../utils'; import { Editor } from '@alilc/lowcode-editor-core'; -import { Project } from '../../../src/project/project'; -import { DocumentModel } from '../../../src/document/document-model'; -import { - isRootNode, - Node, - isNode, - comparePosition, - contains, - insertChild, - insertChildren, - PositionNO, -} from '../../../src/document/node/node'; import { Designer } from '../../../src/designer/designer'; import { BemToolsManager } from '../../../src/builtin-simulator/bem-tools/manager'; -import formSchema from '../../fixtures/schema/form'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; describe('Node 方法测试', () => { let editor: Editor; @@ -26,7 +13,7 @@ describe('Node 方法测试', () => { beforeEach(() => { editor = new Editor(); - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); // project = designer.project; // doc = new DocumentModel(project, formSchema); manager = new BemToolsManager(designer); diff --git a/packages/designer/tests/builtin-simulator/host-view.test.tsx b/packages/designer/tests/builtin-simulator/host-view.test.tsx deleted file mode 100644 index 38ce43bb4..000000000 --- a/packages/designer/tests/builtin-simulator/host-view.test.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import set from 'lodash/set'; -import cloneDeep from 'lodash/cloneDeep'; -import '../fixtures/window'; -import { Editor } from '@alilc/lowcode-editor-core'; -import { Project } from '../../src/project/project'; -import { Node } from '../../src/document/node/node'; -import TestRenderer from 'react-test-renderer'; -import { configure, render, mount } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; -import { Designer } from '../../src/designer/designer'; -import formSchema from '../fixtures/schema/form'; -import { getIdsFromSchema, getNodeFromSchemaById } from '../utils'; -import { BuiltinSimulatorHostView } from '../../src/builtin-simulator/host-view'; - -configure({ adapter: new Adapter() }); -const editor = new Editor(); - -describe('host-view 测试', () => { - let designer: Designer; - beforeEach(() => { - designer = new Designer({ editor }); - }); - afterEach(() => { - designer._componentMetasMap.clear(); - designer = null; - }); - - it.skip('host-view', () => { - const hostView = render(); - }); -}); diff --git a/packages/designer/tests/builtin-simulator/host.test.ts b/packages/designer/tests/builtin-simulator/host.test.ts index 746134c36..4b959565d 100644 --- a/packages/designer/tests/builtin-simulator/host.test.ts +++ b/packages/designer/tests/builtin-simulator/host.test.ts @@ -1,36 +1,20 @@ -// @ts-ignore -import React from 'react'; -import set from 'lodash/set'; -import cloneDeep from 'lodash/cloneDeep'; import '../fixtures/window'; import { Editor, globalContext } from '@alilc/lowcode-editor-core'; import { - AssetLevel, - Asset, - AssetList, - assetBundle, - assetItem, AssetType, } from '@alilc/lowcode-utils'; import { - Dragon, - isDragNodeObject, - isDragNodeDataObject, - isDragAnyObject, - isLocateEvent, DragObjectType, - isShaken, - setShaken, -} from '../../src/designer/dragon'; +} from '@alilc/lowcode-types'; import { Project } from '../../src/project/project'; import pageMetadata from '../fixtures/component-metadata/page'; -import { Node } from '../../src/document/node/node'; import { Designer } from '../../src/designer/designer'; import { DocumentModel } from '../../src/document/document-model'; import formSchema from '../fixtures/schema/form'; import { getMockDocument, getMockWindow, getMockEvent, delayObxTick } from '../utils'; import { BuiltinSimulatorHost } from '../../src/builtin-simulator/host'; import { fireEvent } from '@testing-library/react'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; describe('Host 测试', () => { let editor: Editor; @@ -45,7 +29,7 @@ describe('Host 测试', () => { }); beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; designer.createComponentMeta(pageMetadata); doc = project.createDocument(formSchema); diff --git a/packages/designer/tests/builtin-simulator/utils/parse-metadata.test.ts b/packages/designer/tests/builtin-simulator/utils/parse-metadata.test.ts index f2f399c96..1843a2442 100644 --- a/packages/designer/tests/builtin-simulator/utils/parse-metadata.test.ts +++ b/packages/designer/tests/builtin-simulator/utils/parse-metadata.test.ts @@ -6,4 +6,8 @@ describe('parseMetadata', () => { const md1 = parseMetadata('Div'); const md2 = parseMetadata({ componentName: 'Div' }); }); + it('LowcodeTypes.shape', async () => { + const result = (window as any).PropTypes.shape() + expect(result).toBeDefined(); + }); }); diff --git a/packages/designer/tests/builtin-simulator/viewport.test.ts b/packages/designer/tests/builtin-simulator/viewport.test.ts index 2938e008a..e9972fc7c 100644 --- a/packages/designer/tests/builtin-simulator/viewport.test.ts +++ b/packages/designer/tests/builtin-simulator/viewport.test.ts @@ -1,11 +1,11 @@ import '../fixtures/window'; -import { getMockWindow, set, getMockElement, delay } from '../utils'; +import { getMockWindow, getMockElement, delay } from '../utils'; import { Editor, globalContext } from '@alilc/lowcode-editor-core'; import { Project } from '../../src/project/project'; import { DocumentModel } from '../../src/document/document-model'; import Viewport from '../../src/builtin-simulator/viewport'; import { Designer } from '../../src/designer/designer'; -import { fireEvent } from '@testing-library/react'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; describe('Viewport 测试', () => { @@ -28,7 +28,7 @@ describe('Viewport 测试', () => { }); beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; // doc = project.createDocument(formSchema); }); diff --git a/packages/designer/tests/designer/builtin-hotkey.test.ts b/packages/designer/tests/designer/builtin-hotkey.test.ts index d0fa8a47f..6e7699d4a 100644 --- a/packages/designer/tests/designer/builtin-hotkey.test.ts +++ b/packages/designer/tests/designer/builtin-hotkey.test.ts @@ -5,6 +5,7 @@ import formSchema from '../fixtures/schema/form'; import '../../src/designer/builtin-hotkey'; import { fireEvent } from '@testing-library/react'; import { isInLiveEditing } from '../../src/designer/builtin-hotkey'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; const editor = new Editor(); @@ -23,7 +24,7 @@ describe('快捷键测试', () => { globalContext.register(editor, Editor); }); beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); editor.set('designer', designer); designer.project.open(formSchema); }); diff --git a/packages/designer/tests/designer/designer.test.ts b/packages/designer/tests/designer/designer.test.ts index 51fbabea7..c6d8658c4 100644 --- a/packages/designer/tests/designer/designer.test.ts +++ b/packages/designer/tests/designer/designer.test.ts @@ -3,7 +3,7 @@ import { Editor, globalContext } from '@alilc/lowcode-editor-core'; import { Project } from '../../src/project/project'; import { DocumentModel } from '../../src/document/document-model'; import { Designer } from '../../src/designer/designer'; -import { Dragon, DragObjectType } from '../../src/designer/dragon'; +import { Dragon } from '../../src/designer/dragon'; import { TransformStage } from '../../src/document/node/transform-stage'; import formSchema from '../fixtures/schema/form'; import buttonMetadata from '../fixtures/component-metadata/button'; @@ -11,6 +11,8 @@ import pageMetadata from '../fixtures/component-metadata/page'; import divMetadata from '../fixtures/component-metadata/div'; import { delayObxTick } from '../utils'; import { fireEvent } from '@testing-library/react'; +import { DragObjectType } from '@alilc/lowcode-types'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; const mockNode = { internalToShellNode() { @@ -31,7 +33,7 @@ describe('Designer 测试', () => { }); beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; doc = project.createDocument(formSchema); dragon = new Dragon(designer); @@ -57,6 +59,7 @@ describe('Designer 测试', () => { const designer = new Designer({ editor, + shellModelFactory, onDragstart: dragStartMockFn, onDrag: dragMockFn, onDragend: dragEndMockFn, @@ -123,6 +126,7 @@ describe('Designer 测试', () => { const designer = new Designer({ editor, + shellModelFactory, onDragstart: dragStartMockFn, onDrag: dragMockFn, onDragend: dragEndMockFn, @@ -244,14 +248,18 @@ describe('Designer 测试', () => { suspensed: true, componentMetadatas: [buttonMetadata, divMetadata], }; - designer = new Designer({ editor, ...initialProps }); + designer = new Designer({ + editor, + shellModelFactory, + ...initialProps, + }); expect(designer.simulatorComponent).toEqual({ isSimulatorComp: true }); expect(designer.simulatorProps).toEqual({ designMode: 'design' }); expect(designer.suspensed).toBeTruthy(); - expect(designer._componentMetasMap.has('Div')).toBeTruthy(); - expect(designer._componentMetasMap.has('Button')).toBeTruthy(); - const { editor: editorFromDesigner, ...others } = designer.props; + expect((designer as any)._componentMetasMap.has('Div')).toBeTruthy(); + expect((designer as any)._componentMetasMap.has('Button')).toBeTruthy(); + const { editor: editorFromDesigner, shellModelFactory: shellModelFactoryFromDesigner, ...others } = (designer as any).props; expect(others).toEqual(initialProps); expect(designer.get('simulatorProps')).toEqual({ designMode: 'design' }); expect(designer.get('suspensed')).toBeTruthy(); @@ -269,9 +277,9 @@ describe('Designer 测试', () => { expect(designer.simulatorComponent).toEqual({ isSimulatorComp2: true }); expect(designer.simulatorProps).toEqual({ designMode: 'live' }); expect(designer.suspensed).toBeFalsy(); - expect(designer._componentMetasMap.has('Button')).toBeTruthy(); - expect(designer._componentMetasMap.has('Div')).toBeTruthy(); - const { editor: editorFromDesigner2, ...others2 } = designer.props; + expect((designer as any)._componentMetasMap.has('Button')).toBeTruthy(); + expect((designer as any)._componentMetasMap.has('Div')).toBeTruthy(); + const { editor: editorFromDesigner2, shellModelFactory: shellModelFactoryFromDesigner2, ...others2 } = (designer as any).props; expect(others2).toEqual(updatedProps); // 第三次设置 props,跟第二次值一样,for 覆盖率测试 @@ -281,9 +289,9 @@ describe('Designer 测试', () => { expect(designer.simulatorComponent).toEqual({ isSimulatorComp2: true }); expect(designer.simulatorProps).toEqual({ designMode: 'live' }); expect(designer.suspensed).toBeFalsy(); - expect(designer._componentMetasMap.has('Button')).toBeTruthy(); - expect(designer._componentMetasMap.has('Div')).toBeTruthy(); - const { editor: editorFromDesigner3, ...others3 } = designer.props; + expect((designer as any)._componentMetasMap.has('Button')).toBeTruthy(); + expect((designer as any)._componentMetasMap.has('Div')).toBeTruthy(); + const { editor: editorFromDesigner3, shellModelFactory: shellModelFactoryFromDesigner3, ...others3 } = (designer as any).props; expect(others3).toEqual(updatedProps); }); diff --git a/packages/designer/tests/designer/dragon.test.ts b/packages/designer/tests/designer/dragon.test.ts index eaa53bd5b..bfafa0651 100644 --- a/packages/designer/tests/designer/dragon.test.ts +++ b/packages/designer/tests/designer/dragon.test.ts @@ -1,5 +1,4 @@ import '../fixtures/window'; -import { set } from '../utils'; import { Editor, globalContext } from '@alilc/lowcode-editor-core'; import { Project } from '../../src/project/project'; import { DocumentModel } from '../../src/document/document-model'; @@ -10,14 +9,15 @@ import { isDragNodeDataObject, isDragAnyObject, isLocateEvent, - DragObjectType, isShaken, setShaken, isInvalidPoint, isSameAs, } from '../../src/designer/dragon'; +import { DragObjectType } from '@alilc/lowcode-types'; import formSchema from '../fixtures/schema/form'; import { fireEvent } from '@testing-library/react'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; describe('Dragon 测试', () => { let editor: Editor; @@ -32,7 +32,7 @@ describe('Dragon 测试', () => { }); beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; doc = project.createDocument(formSchema); dragon = new Dragon(designer); diff --git a/packages/designer/tests/designer/scroller.test.ts b/packages/designer/tests/designer/scroller.test.ts index 00f0b86e8..ff03608b0 100644 --- a/packages/designer/tests/designer/scroller.test.ts +++ b/packages/designer/tests/designer/scroller.test.ts @@ -1,35 +1,14 @@ import '../fixtures/window'; -import { set } from '../utils'; import { Editor, globalContext } from '@alilc/lowcode-editor-core'; import { Project } from '../../src/project/project'; import { DocumentModel } from '../../src/document/document-model'; import { ScrollTarget, Scroller } from '../../src/designer/scroller'; -import { - isRootNode, - isNode, - comparePosition, - contains, - insertChild, - insertChildren, - PositionNO, -} from '../../src/document/node/node'; import { Designer } from '../../src/designer/designer'; import { Dragon, - isDragNodeObject, - isDragNodeDataObject, - isDragAnyObject, - isLocateEvent, - DragObjectType, - isShaken, - setShaken, } from '../../src/designer/dragon'; import formSchema from '../fixtures/schema/form'; -import divMetadata from '../fixtures/component-metadata/div'; -import formMetadata from '../fixtures/component-metadata/form'; -import otherMeta from '../fixtures/component-metadata/other'; -import pageMetadata from '../fixtures/component-metadata/page'; -import { fireEvent } from '@testing-library/react'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; describe('Scroller 测试', () => { let editor: Editor; @@ -44,7 +23,7 @@ describe('Scroller 测试', () => { }); beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; doc = project.createDocument(formSchema); dragon = new Dragon(designer); diff --git a/packages/designer/tests/designer/setting/setting-field.test.ts b/packages/designer/tests/designer/setting/setting-field.test.ts index 0e600e2ea..fb8c9d16f 100644 --- a/packages/designer/tests/designer/setting/setting-field.test.ts +++ b/packages/designer/tests/designer/setting/setting-field.test.ts @@ -1,7 +1,6 @@ // @ts-nocheck import '../../fixtures/window'; import { Editor } from '@alilc/lowcode-editor-core'; -import { Project } from '../../../src/project/project'; import { SettingTopEntry } from '../../../src/designer/setting/setting-top-entry'; import { SettingField } from '../../../src/designer/setting/setting-field'; import { Node } from '../../../src/document/node/node'; @@ -10,6 +9,7 @@ import settingSchema from '../../fixtures/schema/setting'; import buttonMeta from '../../fixtures/component-metadata/button'; import { DocumentModel } from 'designer/src/document'; import { delayObxTick } from '../../utils'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; const editor = new Editor(); @@ -17,7 +17,7 @@ describe('setting-field 测试', () => { let designer: Designer; let doc: DocumentModel; beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); designer.createComponentMeta(buttonMeta); doc = designer.project.open(settingSchema); }); diff --git a/packages/designer/tests/designer/setting/setting-prop-entry.test.ts b/packages/designer/tests/designer/setting/setting-prop-entry.test.ts index 72b394035..c9aee1244 100644 --- a/packages/designer/tests/designer/setting/setting-prop-entry.test.ts +++ b/packages/designer/tests/designer/setting/setting-prop-entry.test.ts @@ -1,18 +1,13 @@ -// @ts-nocheck -import set from 'lodash/set'; -import cloneDeep from 'lodash/cloneDeep'; import '../../fixtures/window'; import { Editor } from '@alilc/lowcode-editor-core'; -import { Project } from '../../../src/project/project'; import { SettingTopEntry } from '../../../src/designer/setting/setting-top-entry'; import { SettingPropEntry } from '../../../src/designer/setting/setting-prop-entry'; import { Node } from '../../../src/document/node/node'; import { Designer } from '../../../src/designer/designer'; -import formSchema from '../../../fixtures/schema/form'; import settingSchema from '../../fixtures/schema/setting'; import divMeta from '../../fixtures/component-metadata/div'; -import { getIdsFromSchema, getNodeFromSchemaById } from '../../utils'; import { DocumentModel } from 'designer/src/document'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; const editor = new Editor(); @@ -20,7 +15,7 @@ describe('setting-prop-entry 测试', () => { let designer: Designer; let doc: DocumentModel; beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); designer.createComponentMeta(divMeta); doc = designer.project.open(settingSchema); }); diff --git a/packages/designer/tests/designer/setting/setting-top-entry.test.ts b/packages/designer/tests/designer/setting/setting-top-entry.test.ts index e7a2a7a66..caad12917 100644 --- a/packages/designer/tests/designer/setting/setting-top-entry.test.ts +++ b/packages/designer/tests/designer/setting/setting-top-entry.test.ts @@ -1,22 +1,17 @@ -// @ts-nocheck -import set from 'lodash/set'; -import cloneDeep from 'lodash/cloneDeep'; import '../../fixtures/window'; import { Editor } from '@alilc/lowcode-editor-core'; -import { Project } from '../../../src/project/project'; import { Node } from '../../../src/document/node/node'; import { Designer } from '../../../src/designer/designer'; -import formSchema from '../../fixtures/schema/form'; import settingSchema from '../../fixtures/schema/setting'; import divMeta from '../../fixtures/component-metadata/div'; -import { getIdsFromSchema, getNodeFromSchemaById } from '../../utils'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; const editor = new Editor(); describe('setting-top-entry 测试', () => { let designer: Designer; beforeEach(() => { - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); }); afterEach(() => { designer._componentMetasMap.clear(); 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 1061a609c..9eb7b41ff 100644 --- a/packages/designer/tests/document/document-model/document-model.test.ts +++ b/packages/designer/tests/document/document-model/document-model.test.ts @@ -2,15 +2,13 @@ import '../../fixtures/window'; import { DocumentModel, isDocumentModel, isPageSchema } from '../../../src/document/document-model'; import { Editor } from '@alilc/lowcode-editor-core'; import { Project } from '../../../src/project/project'; -import { Node } from '../../../src/document/node/node'; import { Designer } from '../../../src/designer/designer'; import formSchema from '../../fixtures/schema/form'; import divMeta from '../../fixtures/component-metadata/div'; import formMeta from '../../fixtures/component-metadata/form'; import otherMeta from '../../fixtures/component-metadata/other'; import pageMeta from '../../fixtures/component-metadata/page'; -// const { DocumentModel } = require('../../../src/document/document-model'); -// const { Node } = require('../__mocks__/node'); +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; describe('document-model 测试', () => { let editor: Editor; @@ -19,7 +17,7 @@ describe('document-model 测试', () => { beforeEach(() => { editor = new Editor(); - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; }); diff --git a/packages/designer/tests/document/history/history.test.ts b/packages/designer/tests/document/history/history.test.ts index a4c6d3a66..960b183f9 100644 --- a/packages/designer/tests/document/history/history.test.ts +++ b/packages/designer/tests/document/history/history.test.ts @@ -272,20 +272,6 @@ describe('History', () => { expect(history.records).toHaveLength(0); }); - it('internalToShellHistory()', async () => { - const history = new History( - () => { - const data = tree.toObject(); - return data; - }, - (data) => { - mockRedoFn(data); - }, - ); - - expect(history.internalToShellHistory().isModified).toBeUndefined(); - }); - it('sleep & wakeup', async () => { const mockRedoFn = jest.fn(); const history = new History( diff --git a/packages/designer/tests/document/node/modal-nodes-manager.test.ts b/packages/designer/tests/document/node/modal-nodes-manager.test.ts index 80ca53b3e..3e5dcdb79 100644 --- a/packages/designer/tests/document/node/modal-nodes-manager.test.ts +++ b/packages/designer/tests/document/node/modal-nodes-manager.test.ts @@ -7,6 +7,7 @@ import { Designer } from '../../../src/designer/designer'; import formSchema from '../../fixtures/schema/form-with-modal'; import dlgMetadata from '../../fixtures/component-metadata/dialog'; import { getModalNodes } from '../../../src/document/node/modal-nodes-manager'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; let editor: Editor; let designer: Designer; @@ -15,7 +16,7 @@ let doc: DocumentModel; beforeEach(() => { editor = new Editor(); - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); designer.createComponentMeta(dlgMetadata); project = designer.project; doc = new DocumentModel(project, formSchema); diff --git a/packages/designer/tests/document/node/node-children.test.ts b/packages/designer/tests/document/node/node-children.test.ts index c48c9e708..1aa7e3ccb 100644 --- a/packages/designer/tests/document/node/node-children.test.ts +++ b/packages/designer/tests/document/node/node-children.test.ts @@ -8,6 +8,7 @@ import { import { Designer } from '../../../src/designer/designer'; import formSchema from '../../fixtures/schema/form'; import divMetadata from '../../fixtures/component-metadata/div'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; describe('NodeChildren 方法测试', () => { let editor: Editor; @@ -17,7 +18,7 @@ describe('NodeChildren 方法测试', () => { beforeEach(() => { editor = new Editor(); - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; doc = new DocumentModel(project, formSchema); }); diff --git a/packages/designer/tests/document/node/node.test.ts b/packages/designer/tests/document/node/node.test.ts index 113360d44..d8915c991 100644 --- a/packages/designer/tests/document/node/node.test.ts +++ b/packages/designer/tests/document/node/node.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck import '../../fixtures/window'; -import { set, delayObxTick, delay } from '../../utils'; +import { set } from '../../utils'; import { Editor } from '@alilc/lowcode-editor-core'; import { Project } from '../../../src/project/project'; import { DocumentModel } from '../../../src/document/document-model'; @@ -10,8 +10,6 @@ import { isNode, comparePosition, contains, - insertChild, - insertChildren, PositionNO, } from '../../../src/document/node/node'; import { Designer } from '../../../src/designer/designer'; @@ -20,11 +18,11 @@ import divMetadata from '../../fixtures/component-metadata/div'; import dialogMetadata from '../../fixtures/component-metadata/dialog'; import btnMetadata from '../../fixtures/component-metadata/button'; import formMetadata from '../../fixtures/component-metadata/form'; -import otherMeta from '../../fixtures/component-metadata/other'; import pageMetadata from '../../fixtures/component-metadata/page'; import rootHeaderMetadata from '../../fixtures/component-metadata/root-header'; import rootContentMetadata from '../../fixtures/component-metadata/root-content'; import rootFooterMetadata from '../../fixtures/component-metadata/root-footer'; +import { shellModelFactory } from '../../../../engine/src/modules/shell-model-factory'; describe('Node 方法测试', () => { let editor: Editor; @@ -34,7 +32,7 @@ describe('Node 方法测试', () => { beforeEach(() => { editor = new Editor(); - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; doc = new DocumentModel(project, formSchema); }); diff --git a/packages/designer/tests/document/node/props/prop.test.ts b/packages/designer/tests/document/node/props/prop.test.ts index d7b125430..3d7914a85 100644 --- a/packages/designer/tests/document/node/props/prop.test.ts +++ b/packages/designer/tests/document/node/props/prop.test.ts @@ -1,11 +1,10 @@ -// @ts-nocheck import '../../../fixtures/window'; -import { delayObxTick } from '../../../utils'; import { Editor, engineConfig } from '@alilc/lowcode-editor-core'; import { Designer } from '../../../../src/designer/designer'; import { DocumentModel } from '../../../../src/document/document-model'; import { Prop, isProp, isValidArrayIndex } from '../../../../src/document/node/props/prop'; import { TransformStage } from '@alilc/lowcode-types'; +import { shellModelFactory } from '../../../../../engine/src/modules/shell-model-factory'; const slotNodeImportMockFn = jest.fn(); const slotNodeRemoveMockFn = jest.fn(); @@ -465,7 +464,7 @@ describe('Prop 类测试', () => { describe('slotNode / setAsSlot', () => { const editor = new Editor(); - const designer = new Designer({ editor }); + const designer = new Designer({ editor, shellModelFactory }); const doc = new DocumentModel(designer.project, { componentName: 'Page', children: [ diff --git a/packages/designer/tests/plugin/plugin-manager.test.ts b/packages/designer/tests/plugin/plugin-manager.test.ts index b0c40070a..02bc696a8 100644 --- a/packages/designer/tests/plugin/plugin-manager.test.ts +++ b/packages/designer/tests/plugin/plugin-manager.test.ts @@ -1,14 +1,19 @@ import '../fixtures/window'; import { Editor, engineConfig } from '@alilc/lowcode-editor-core'; import { LowCodePluginManager } from '../../src/plugin/plugin-manager'; -import { ILowCodePluginContext, ILowCodePluginManager } from '../../src/plugin/plugin-types'; +import { ILowCodePluginContext, ILowCodePluginManager, ILowCodePluginContextApiAssembler } from '../../src/plugin/plugin-types'; const editor = new Editor(); +const contextApiAssembler = { + assembleApis(){ + // mock set apis + } +}; describe('plugin 测试', () => { let pluginManager: ILowCodePluginManager; beforeEach(() => { - pluginManager = new LowCodePluginManager(editor).toProxy(); + pluginManager = new LowCodePluginManager(contextApiAssembler).toProxy(); }); afterEach(() => { pluginManager.dispose(); diff --git a/packages/designer/tests/project/project-methods.test.ts b/packages/designer/tests/project/project-methods.test.ts index 0e545e4f4..b546f8f52 100644 --- a/packages/designer/tests/project/project-methods.test.ts +++ b/packages/designer/tests/project/project-methods.test.ts @@ -1,13 +1,10 @@ -import set from 'lodash/set'; -import cloneDeep from 'lodash/cloneDeep'; import '../fixtures/window'; import { Editor } from '@alilc/lowcode-editor-core'; import { Project } from '../../src/project/project'; import { DocumentModel } from '../../src/document/document-model'; -import { Node } from '../../src/document/node/node'; import { Designer } from '../../src/designer/designer'; import formSchema from '../fixtures/schema/form'; -import { getIdsFromSchema, getNodeFromSchemaById } from '../utils'; +import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory'; describe.only('Project 方法测试', () => { let editor: Editor; @@ -17,7 +14,7 @@ describe.only('Project 方法测试', () => { beforeEach(() => { editor = new Editor(); - designer = new Designer({ editor }); + designer = new Designer({ editor, shellModelFactory }); project = designer.project; doc = new DocumentModel(project, formSchema); }); diff --git a/packages/designer/tsconfig.json b/packages/designer/tsconfig.json new file mode 100644 index 000000000..9136085c9 --- /dev/null +++ b/packages/designer/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "lib", + "types": ["node","jest"] + }, + "include": [ + "./src/", + "./tests/" + ], + "exclude": ["**/lib", "**/es", "node_modules"] +} diff --git a/packages/editor-core/package.json b/packages/editor-core/package.json index 208f932d6..90c551fec 100644 --- a/packages/editor-core/package.json +++ b/packages/editor-core/package.json @@ -37,7 +37,7 @@ "@types/react": "^16", "@types/react-dom": "^16", "@types/store": "^2.0.2", - "build-plugin-component": "^0.2.11", + "build-plugin-component": "^1.0.0", "build-plugin-fusion": "^0.1.0", "build-plugin-moment-locales": "^0.1.0" }, diff --git a/packages/editor-core/src/config.ts b/packages/editor-core/src/config.ts index deade483a..ad426f74b 100644 --- a/packages/editor-core/src/config.ts +++ b/packages/editor-core/src/config.ts @@ -1,9 +1,6 @@ -import { ComponentType } from 'react'; import { get as lodashGet } from 'lodash'; import { isPlainObject } from '@alilc/lowcode-utils'; - -import { RequestHandlersMap } from '@alilc/lowcode-datasource-types'; - +import { EngineOptions, IEngineConfig } from '@alilc/lowcode-types'; import { getLogger } from './utils/logger'; const logger = getLogger({ level: 'log', bizName: 'config' }); @@ -53,7 +50,7 @@ const VALID_ENGINE_OPTIONS = { enableStrictPluginMode: { type: 'boolean', default: STRICT_PLUGIN_MODE_DEFAULT, - description: '开启严格插件模式,默认值: STRICT_PLUGIN_MODE_DEFAULT , 严格模式下,插件将无法通过engineOptions传递自定义配置项', + description: '开启严格插件模式,默认值:STRICT_PLUGIN_MODE_DEFAULT , 严格模式下,插件将无法通过 engineOptions 传递自定义配置项', }, enableReactiveContainer: { type: 'boolean', @@ -123,7 +120,7 @@ const VALID_ENGINE_OPTIONS = { description: '自定义 simulatorUrl 的地址', }, /** - * 与 react-renderer 的 appHelper 一致, https://lowcode-engine.cn/docV2/nhilce#appHelper + * 与 react-renderer 的 appHelper 一致,https://lowcode-engine.cn/site/docs/guide/expand/runtime/renderer#apphelper */ appHelper: { type: 'object', @@ -146,140 +143,7 @@ const VALID_ENGINE_OPTIONS = { description: '配置指定节点为根组件', }, }; -export interface EngineOptions { - /** - * 是否开启 condition 的能力,默认在设计器中不管 condition 是啥都正常展示 - */ - enableCondition?: boolean; - /** - * @todo designMode 无法映射到文档渲染模块 - * - * 设计模式,live 模式将会实时展示变量值,默认值:'design' - */ - designMode?: 'design' | 'live'; - /** - * 设备类型,默认值:'default' - */ - device?: 'default' | 'mobile' | string; - /** - * 指定初始化的 deviceClassName,挂载到画布的顶层节点上 - */ - deviceClassName?: string; - /** - * 语言,默认值:'zh-CN' - */ - locale?: string; - /** - * 渲染器类型,默认值:'react' - */ - renderEnv?: 'react' | 'rax' | string; - /** - * 设备类型映射器,处理设计器与渲染器中 device 的映射 - */ - deviceMapper?: { - transform: (originalDevice: string) => string; - }; - /** - * 开启严格插件模式,默认值: STRICT_PLUGIN_MODE_DEFAULT , 严格模式下,插件将无法通过engineOptions传递自定义配置项 - * enable strict plugin mode, default value: false - * under strict mode, customed engineOption is not accepted. - */ - enableStrictPluginMode?: boolean; - /** - * 开启拖拽组件时,即将被放入的容器是否有视觉反馈,默认值:false - */ - enableReactiveContainer?: boolean; - /** - * 关闭画布自动渲染,在资产包多重异步加载的场景有效,默认值:false - */ - disableAutoRender?: boolean; - /** - * 关闭拖拽组件时的虚线响应,性能考虑,默认值:false - */ - disableDetecting?: boolean; - /** - * 定制画布中点击被忽略的 selectors,默认值:undefined - */ - customizeIgnoreSelectors?: (defaultIgnoreSelectors: string[], e: MouseEvent) => string[]; - /** - * 禁止默认的设置面板,默认值:false - */ - disableDefaultSettingPanel?: boolean; - /** - * 禁止默认的设置器,默认值:false - */ - disableDefaultSetters?: boolean; - /** - * 打开画布的锁定操作,默认值:false - */ - enableCanvasLock?: boolean; - /** - * 容器锁定后,容器本身是否可以设置属性,仅当画布锁定特性开启时生效, 默认值为:false - */ - enableLockedNodeSetting?: boolean; - /** - * 当选中节点切换时,是否停留在相同的设置 tab 上,默认值:false - */ - stayOnTheSameSettingTab?: boolean; - /** - * 是否在只有一个 item 的时候隐藏设置 tabs,默认值:false - */ - hideSettingsTabsWhenOnlyOneItem?: boolean; - /** - * 自定义 loading 组件 - */ - loadingComponent?: ComponentType; - /** - * 设置所有属性支持变量配置,默认值:false - */ - supportVariableGlobally?: boolean; - /** - * 设置 simulator 相关的 url,默认值:undefined - */ - simulatorUrl?: string[]; - /** - * Vision-polyfill settings - */ - visionSettings?: { - // 是否禁用降级 reducer,默认值:false - disableCompatibleReducer?: boolean; - // 是否开启在 render 阶段开启 filter reducer,默认值:false - enableFilterReducerInRenderStage?: boolean; - }; - /** - * 与 react-renderer 的 appHelper 一致, https://lowcode-engine.cn/docV2/nhilce#appHelper - */ - appHelper?: { - /** 全局公共函数 */ - utils?: Record; - /** 全局常量 */ - constants?: Record; - }; - /** - * 数据源引擎的请求处理器映射 - */ - requestHandlersMap?: RequestHandlersMap; - - /** - * @default true - * JSExpression 是否只支持使用 this 来访问上下文变量,假如需要兼容原来的 'state.xxx',则设置为 false - */ - thisRequiredInJSE?: boolean; - - /** - * @default false - * 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件 - */ - enableStrictNotFoundMode?: boolean; - - /** - * 配置指定节点为根组件 - */ - focusNodeSelector?: (rootNode: Node) => Node; - - enableWorkspaceMode?: boolean; -} const getStrictModeValue = (engineOptions: EngineOptions, defaultValue: boolean): boolean => { if (!engineOptions || !isPlainObject(engineOptions)) { @@ -291,7 +155,25 @@ const getStrictModeValue = (engineOptions: EngineOptions, defaultValue: boolean) } return engineOptions.enableStrictPluginMode; }; -export class EngineConfig { + +export interface IEngineConfigPrivate { + /** + * if engineOptions.strictPluginMode === true, only accept propertied predefined in EngineOptions. + * + * @param {EngineOptions} engineOptions + * @memberof EngineConfig + */ + setEngineOptions(engineOptions: EngineOptions): void; + + notifyGot(key: string): void; + + setWait(key: string, resolve: (data: any) => void, once?: boolean): void; + + delWait(key: string, fn: any): void; +} + + +export class EngineConfig implements IEngineConfig, IEngineConfigPrivate { private config: { [key: string]: any } = {}; private waits = new Map< @@ -365,7 +247,7 @@ export class EngineConfig { }; Object.keys(engineOptions).forEach((key) => { if (isValidKey(key)) { - this.set(key, engineOptions[key]); + this.set(key, (engineOptions as any)[key]); } else { logger.warn(`failed to config ${key} to engineConfig, only predefined options can be set under strict mode, predefined options: `, VALID_ENGINE_OPTIONS); } @@ -410,7 +292,7 @@ export class EngineConfig { } } - private notifyGot(key: string) { + notifyGot(key: string): void { let waits = this.waits.get(key); if (!waits) { return; @@ -430,7 +312,7 @@ export class EngineConfig { } } - private setWait(key: string, resolve: (data: any) => void, once?: boolean) { + setWait(key: string, resolve: (data: any) => void, once?: boolean) { const waits = this.waits.get(key); if (waits) { waits.push({ resolve, once }); @@ -439,7 +321,7 @@ export class EngineConfig { } } - private delWait(key: string, fn: any) { + delWait(key: string, fn: any) { const waits = this.waits.get(key); if (!waits) { return; @@ -456,4 +338,4 @@ export class EngineConfig { } } -export const engineConfig = new EngineConfig(); +export const engineConfig = new EngineConfig(); \ No newline at end of file diff --git a/packages/editor-core/src/di/setter.ts b/packages/editor-core/src/di/setter.ts index e4973652b..cd7abf456 100644 --- a/packages/editor-core/src/di/setter.ts +++ b/packages/editor-core/src/di/setter.ts @@ -1,23 +1,41 @@ import { ReactNode } from 'react'; -import { CustomView, isCustomView, TitleContent } from '@alilc/lowcode-types'; -import { createContent } from '@alilc/lowcode-utils'; +import { CustomView, RegisteredSetter } from '@alilc/lowcode-types'; +import { createContent, isCustomView } from '@alilc/lowcode-utils'; -export type RegisteredSetter = { - component: CustomView; - defaultProps?: object; - title?: TitleContent; - /** - * for MixedSetter to check this setter if available - */ - condition?: (field: any) => boolean; - /** - * for MixedSetter to manual change to this setter - */ - initialValue?: any | ((field: any) => any); - recommend?: boolean; - // 标识是否为动态setter,默认为true - isDynamic?: boolean; -}; + +const settersMap = new Map(); +export function registerSetter( + typeOrMaps: string | { [key: string]: CustomView | RegisteredSetter }, + setter?: CustomView | RegisteredSetter, +) { + if (typeof typeOrMaps === 'object') { + Object.keys(typeOrMaps).forEach(type => { + registerSetter(type, typeOrMaps[type]); + }); + return; + } + if (!setter) { + return; + } + if (isCustomView(setter)) { + setter = { + component: setter, + // todo: intl + title: (setter as any).displayName || (setter as any).name || 'CustomSetter', + }; + } + if (!setter.initialValue) { + const initial = getInitialFromSetter(setter.component); + if (initial) { + setter.initialValue = (field: any) => { + return initial.call(field, field.getValue()); + }; + } + } + settersMap.set(typeOrMaps, { type: typeOrMaps, ...setter }); +} function getInitialFromSetter(setter: any) { return setter && ( diff --git a/packages/editor-core/src/editor.ts b/packages/editor-core/src/editor.ts index 2cdf119e5..53dcb39ce 100644 --- a/packages/editor-core/src/editor.ts +++ b/packages/editor-core/src/editor.ts @@ -1,3 +1,5 @@ +/* eslint-disable no-console */ +/* eslint-disable max-len */ import { StrictEventEmitter } from 'strict-event-emitter-types'; import { EventEmitter } from 'events'; import { @@ -13,7 +15,6 @@ import { } from '@alilc/lowcode-types'; import { engineConfig } from './config'; import { globalLocale } from './intl'; -import * as utils from './utils'; import Preference from './utils/preference'; import { obx } from './utils'; import { AssetsJson, AssetLoader } from '@alilc/lowcode-utils'; @@ -50,6 +51,7 @@ export declare interface Editor extends StrictEventEmitter(keyOrType: KeyOrType): GetReturnType | undefined { + get( + keyOrType: KeyOrType, + ): GetReturnType | undefined { return this.context.get(keyOrType as any); } @@ -253,7 +257,7 @@ export class Editor extends (EventEmitter as any) implements IEditor { registerHooks = (hooks: HookConfig[]) => { this.initHooks(hooks).forEach(({ message, type, handler }) => { if (['on', 'once'].indexOf(type) !== -1) { - this[type](message, handler); + this[type]((message as any), handler); } }); }; diff --git a/packages/editor-core/src/hotkey.ts b/packages/editor-core/src/hotkey.ts index c193b62b5..884e2a1d1 100644 --- a/packages/editor-core/src/hotkey.ts +++ b/packages/editor-core/src/hotkey.ts @@ -1,6 +1,7 @@ import { isEqual } from 'lodash'; import { globalContext } from './di'; import { Editor } from './editor'; +import { HotkeyCallback } from '@alilc/lowcode-types'; interface KeyMap { [key: number]: string; @@ -22,8 +23,6 @@ interface HotkeyDirectMap { [key: string]: HotkeyCallback; } -export type HotkeyCallback = (e: KeyboardEvent, combo?: string) => any | false; - interface HotkeyCallbackCfg { callback: HotkeyCallback; modifiers: string[]; diff --git a/packages/editor-core/src/intl/index.ts b/packages/editor-core/src/intl/index.ts index 1af991e69..6d9d840c3 100644 --- a/packages/editor-core/src/intl/index.ts +++ b/packages/editor-core/src/intl/index.ts @@ -1,7 +1,7 @@ import { ReactNode, Component, createElement } from 'react'; import { IntlMessageFormat } from 'intl-messageformat'; import { globalLocale } from './global-locale'; -import { isI18nData } from '@alilc/lowcode-types'; +import { isI18nData } from '@alilc/lowcode-utils'; import { observer } from '../utils'; function generateTryLocales(locale: string) { diff --git a/packages/editor-core/src/widgets/title/index.tsx b/packages/editor-core/src/widgets/title/index.tsx index bacfee9f1..735921389 100644 --- a/packages/editor-core/src/widgets/title/index.tsx +++ b/packages/editor-core/src/widgets/title/index.tsx @@ -1,7 +1,7 @@ import { Component, isValidElement, ReactNode } from 'react'; import classNames from 'classnames'; -import { createIcon } from '@alilc/lowcode-utils'; -import { TitleContent, isI18nData, I18nData } from '@alilc/lowcode-types'; +import { createIcon, isI18nData } from '@alilc/lowcode-utils'; +import { TitleContent, I18nData } from '@alilc/lowcode-types'; import { intl } from '../../intl'; import { Tip } from '../tip'; import './title.less'; diff --git a/packages/editor-skeleton/package.json b/packages/editor-skeleton/package.json index 705c418b2..784736412 100644 --- a/packages/editor-skeleton/package.json +++ b/packages/editor-skeleton/package.json @@ -30,7 +30,7 @@ "@alib/build-scripts": "^0.1.3", "@types/react": "^16.9.13", "@types/react-dom": "^16.9.4", - "build-plugin-component": "^0.2.7", + "build-plugin-component": "^1.0.0", "build-plugin-fusion": "^0.1.0", "build-plugin-moment-locales": "^0.1.0" }, diff --git a/packages/editor-skeleton/src/components/settings/settings-pane.tsx b/packages/editor-skeleton/src/components/settings/settings-pane.tsx index 9f354bddd..116f33bcc 100644 --- a/packages/editor-skeleton/src/components/settings/settings-pane.tsx +++ b/packages/editor-skeleton/src/components/settings/settings-pane.tsx @@ -1,13 +1,12 @@ import { Component, MouseEvent, Fragment } from 'react'; import { shallowIntl, observer, obx, engineConfig, runInAction, globalContext } from '@alilc/lowcode-editor-core'; -import { createContent } from '@alilc/lowcode-utils'; +import { createContent, isJSSlot, isSetterConfig } from '@alilc/lowcode-utils'; import { Skeleton } from '@alilc/lowcode-editor-skeleton'; -import { isSetterConfig, CustomView, isJSSlot } from '@alilc/lowcode-types'; +import { CustomView } from '@alilc/lowcode-types'; import { SettingField, isSettingField, SettingTopEntry, SettingEntry, ComponentMeta } from '@alilc/lowcode-designer'; import { createField } from '../field'; import PopupService, { PopupPipe } from '../popup'; import { SkeletonContext } from '../../context'; -// import { Icon } from '@alifd/next'; import { intl } from '../../locale'; import { Setters } from '@alilc/lowcode-shell'; diff --git a/packages/editor-skeleton/src/components/stage-box/stage.tsx b/packages/editor-skeleton/src/components/stage-box/stage.tsx index 64209fbd5..e4b0c0ef1 100644 --- a/packages/editor-skeleton/src/components/stage-box/stage.tsx +++ b/packages/editor-skeleton/src/components/stage-box/stage.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import { IconArrow } from '../../icons/arrow'; import { IconExit } from '../../icons/exit'; import { Stage as StageWidget } from '../../widget/stage'; -import { isTitleConfig } from '@alilc/lowcode-types'; +import { isTitleConfig } from '@alilc/lowcode-utils'; export const StageDefaultProps = { current: false, diff --git a/packages/editor-skeleton/src/skeleton.ts b/packages/editor-skeleton/src/skeleton.ts index 3f55f68db..b21aae2bf 100644 --- a/packages/editor-skeleton/src/skeleton.ts +++ b/packages/editor-skeleton/src/skeleton.ts @@ -3,7 +3,6 @@ import { DockConfig, PanelConfig, WidgetConfig, - IWidgetBaseConfig, PanelDockConfig, DialogDockConfig, isDockConfig, @@ -11,7 +10,6 @@ import { isPanelConfig, DividerConfig, isDividerConfig, - IWidgetConfigArea, } from './types'; import Panel, { isPanel } from './widget/panel'; import WidgetContainer from './widget/widget-container'; @@ -23,7 +21,12 @@ import { Stage, StageConfig } from './widget/stage'; import { isValidElement } from 'react'; import { isPlainObject, uniqueId } from '@alilc/lowcode-utils'; import { Divider } from '@alifd/next'; -import { EditorConfig, PluginClassSet } from '@alilc/lowcode-types'; +import { + EditorConfig, + PluginClassSet, + IWidgetBaseConfig, + IWidgetConfigArea, +} from '@alilc/lowcode-types'; export enum SkeletonEvents { PANEL_DOCK_ACTIVE = 'skeleton.panel-dock.active', diff --git a/packages/editor-skeleton/src/transducers/addon-combine.ts b/packages/editor-skeleton/src/transducers/addon-combine.ts index 8975e7efa..d02d6aa18 100644 --- a/packages/editor-skeleton/src/transducers/addon-combine.ts +++ b/packages/editor-skeleton/src/transducers/addon-combine.ts @@ -319,7 +319,7 @@ export default function (metadata: TransformedComponentMetadata): TransformedCom title: { label: '渲染唯一标识(key)', tip: '搭配「条件渲染」或「循环渲染」时使用,和 react 组件中的 key 原理相同,点击查看帮助', - docUrl: 'https://lowcode-engine.cn/docV2/qm75w3', + docUrl: 'https://www.yuque.com/lce/doc/qm75w3', }, setter: [ { diff --git a/packages/editor-skeleton/src/transducers/parse-func.ts b/packages/editor-skeleton/src/transducers/parse-func.ts index 8dc0a4cd8..b1caa3453 100644 --- a/packages/editor-skeleton/src/transducers/parse-func.ts +++ b/packages/editor-skeleton/src/transducers/parse-func.ts @@ -1,9 +1,5 @@ -import { - FieldConfig, - TransformedComponentMetadata, - isJSFunction, -} from '@alilc/lowcode-types'; -import { isPlainObject } from '@alilc/lowcode-utils'; +import { TransformedComponentMetadata } from '@alilc/lowcode-types'; +import { isPlainObject, isJSFunction } from '@alilc/lowcode-utils'; const leadingFnRe = /^function/; const leadingFnNameRe = /^\w+\s*\(/; diff --git a/packages/editor-skeleton/src/types.ts b/packages/editor-skeleton/src/types.ts index cefe86c92..ef6b43875 100644 --- a/packages/editor-skeleton/src/types.ts +++ b/packages/editor-skeleton/src/types.ts @@ -1,35 +1,14 @@ import { ReactElement, ComponentType } from 'react'; -import { TitleContent, IconType, I18nData, TipContent } from '@alilc/lowcode-types'; +import { + TitleContent, + IconType, + I18nData, + TipContent, + IWidgetConfigArea, + IWidgetBaseConfig, +} from '@alilc/lowcode-types'; import { IWidget } from './widget/widget'; -/** - * 所有可能的停靠位置 - */ -export type IWidgetConfigArea = - | 'leftArea' | 'left' | 'rightArea' - | 'right' | 'topArea' | 'top' - | 'toolbar' | 'mainArea' | 'main' - | 'center' | 'centerArea' | 'bottomArea' - | 'bottom' | 'leftFixedArea' - | 'leftFloatArea' | 'stages'; - -export interface IWidgetBaseConfig { - type: string; - name: string; - /** - * 停靠位置: - * - 当 type 为 'Panel' 时自动为 'leftFloatArea'; - * - 当 type 为 'Widget' 时自动为 'mainArea'; - * - 其他时候自动为 'leftArea'; - */ - area?: IWidgetConfigArea; - props?: Record; - content?: any; - contentProps?: Record; - // index?: number; - [extra: string]: any; -} - export interface WidgetConfig extends IWidgetBaseConfig { type: 'Widget'; props?: { diff --git a/packages/editor-skeleton/src/widget/utils.ts b/packages/editor-skeleton/src/widget/utils.ts index 73657d08f..556a8cb2a 100644 --- a/packages/editor-skeleton/src/widget/utils.ts +++ b/packages/editor-skeleton/src/widget/utils.ts @@ -1,4 +1,5 @@ -import { IconType, TitleContent, isI18nData, TipContent, isTitleConfig } from '@alilc/lowcode-types'; +import { IconType, TitleContent, TipContent } from '@alilc/lowcode-types'; +import { isI18nData, isTitleConfig } from '@alilc/lowcode-utils'; import { isValidElement } from 'react'; export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipContent, tipAsTitle?: boolean, noIcon?: boolean) { diff --git a/packages/editor-view/package.json b/packages/editor-view/package.json index 02036bdd7..39e086638 100644 --- a/packages/editor-view/package.json +++ b/packages/editor-view/package.json @@ -40,8 +40,8 @@ "@types/react": "^16", "@types/react-dom": "^16", "babel-jest": "^26.5.2", - "build-plugin-component": "^0.2.10", - "build-scripts-config": "^0.1.8", + "build-plugin-component": "^1.0.0", + "build-scripts-config": "^3.0.3", "jest": "^26.6.3", "lodash": "^4.17.20", "moment": "^2.29.1", diff --git a/packages/editor-window/package.json b/packages/editor-window/package.json index 0d47bb328..d4ebfc7d9 100644 --- a/packages/editor-window/package.json +++ b/packages/editor-window/package.json @@ -40,8 +40,8 @@ "@types/react": "^16", "@types/react-dom": "^16", "babel-jest": "^26.5.2", - "build-plugin-component": "^0.2.10", - "build-scripts-config": "^0.1.8", + "build-plugin-component": "^1.0.0", + "build-scripts-config": "^3.0.3", "jest": "^26.6.3", "lodash": "^4.17.20", "moment": "^2.29.1", diff --git a/packages/engine/README-zh_CN.md b/packages/engine/README-zh_CN.md index 5a070affb..000a711f5 100644 --- a/packages/engine/README-zh_CN.md +++ b/packages/engine/README-zh_CN.md @@ -41,7 +41,7 @@ - 🌈 提炼自企业级低代码平台的面向扩展设计的内核引擎,奉行最小内核,最强生态的设计理念 - 📦 开箱即用的高质量生态元素,包括 物料体系、设置器、插件 等 - ⚙️ 完善的工具链,支持 物料体系、设置器、插件 等生态元素的全链路研发周期 -- 🔌 强大的扩展能力,已支撑近 100 个各种垂直类低代码平台 +- 🔌 强大的扩展能力,已支撑 100+ 个各种类型低代码平台 - 🛡 使用 TypeScript 开发,提供完整的类型定义文件 ## 🎯 兼容环境 @@ -126,9 +126,9 @@ https://cdn.jsdelivr.net/npm/@alilc/lowcode-react-simulator-renderer@1.0.0/dist/ - [官方物料](https://github.com/alibaba/lowcode-materials) - [官方设置器(setter)](https://github.com/alibaba/lowcode-engine-ext) - [官方插件(plugin)](https://github.com/alibaba/lowcode-plugins) -- [生态元素(物料、setter、插件)工具链](https://www.yuque.com/lce/doc/ulvlkz) -- [用户文档](https://lowcode-engine.cn/docV2) -- [API](https://lowcode-engine.cn/docV2/vlmeme) +- [生态元素(物料、setter、插件)工具链](https://lowcode-engine.cn/site/docs/guide/expand/editor/cli) +- [用户文档](https://lowcode-engine.cn/doc) +- [API](https://lowcode-engine.cn/site/docs/api/) [awesome-lowcode-engine](https://github.com/lowcode-workspace/awesome-lowcode-engine) 中包含了一系列围绕引擎建设的工具、解决方案等,如果你有类似的解决方案或者工具,欢迎提 PR 到该仓库,让更多人了解到 @@ -146,14 +146,14 @@ $ npm start > > 📢 windows 环境必须使用 [WSL](https://docs.microsoft.com/zh-cn/windows/wsl/install),其他终端不保证能正常运行 -lowcode-engine 启动后,提供了几个 umd 文件,可以结合 [lowcode-demo](https://github.com/alibaba/lowcode-demo) 项目做调试,文件代理规则参考[这里](https://www.yuque.com/lce/doc/glz0fx)。 +lowcode-engine 启动后,提供了几个 umd 文件,可以结合 [lowcode-demo](https://github.com/alibaba/lowcode-demo) 项目做调试,文件代理规则参考[这里](https://lowcode-engine.cn/site/docs/participate/prepare#2-配置资源代理)。 ## 🤝 参与共建 请先阅读: -1. [如何配置引擎调试环境?](https://www.yuque.com/lce/doc/glz0fx) -2. [关于引擎的研发协作流程](https://www.yuque.com/lce/doc/contributing) -3. [引擎的工程化配置](https://www.yuque.com/lce/doc/gxwqg6) +1. [如何配置引擎调试环境?](https://lowcode-engine.cn/site/docs/participate/prepare) +2. [关于引擎的研发协作流程](https://lowcode-engine.cn/site/docs/participate/flow) +3. [引擎的工程化配置](https://lowcode-engine.cn/site/docs/participate/config) > 强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)、[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545) 和 [《如何有效地报告 Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html)、[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。(此段参考 [antd](https://github.com/ant-design/ant-design)) diff --git a/packages/engine/README.md b/packages/engine/README.md index 63e967140..8b11e5a1a 100644 --- a/packages/engine/README.md +++ b/packages/engine/README.md @@ -126,9 +126,9 @@ Pass the files under packages/engine/dist and packages/(react|rax)-simulator-ren - [Official Materials](https://github.com/alibaba/lowcode-materials) - [official setter](https://github.com/alibaba/lowcode-engine-ext) - [Official plugin (plugin)](https://github.com/alibaba/lowcode-plugins) -- [Ecological elements (materials, setters, plugins) toolchain](https://www.yuque.com/lce/doc/ulvlkz) -- [User Documentation](http://lowcode-engine.cn/docV2) -- [API](http://lowcode-engine.cn/docV2/vlmeme) +- [Ecological elements (materials, setters, plugins) toolchain](https://lowcode-engine.cn/site/docs/guide/expand/editor/cli) +- [User Documentation](http://lowcode-engine.cn/doc) +- [API](https://lowcode-engine.cn/site/docs/api/) This [awesome-lowcode-engine](https://github.com/lowcode-workspace/awesome-lowcode-engine) page links to a repository which records all of the tools\materials\solutions that use or built for the lowcode-engine, PR is welcomed. @@ -146,14 +146,14 @@ $ npm start > > 📢 Windows environment must use [WSL](https://docs.microsoft.com/en-us/windows/wsl/install), other terminals are not guaranteed to work normally -After lowcode-engine is started, several umd files are provided, which can be debugged in combination with the [lowcode-demo](https://github.com/alibaba/lowcode-demo) project. Refer to the file proxy rules [here](https://www.yuque.com/lce/doc/glz0fx). +After lowcode-engine is started, several umd files are provided, which can be debugged in combination with the [lowcode-demo](https://github.com/alibaba/lowcode-demo) project. Refer to the file proxy rules [here](https://lowcode-engine.cn/site/docs/participate/prepare). ## 🤝 Participation Please read first: -1. [How to configure the engine debugging environment? ](https://www.yuque.com/lce/doc/glz0fx) -2. [About the R&D collaboration process of the engine](https://www.yuque.com/lce/doc/contributing) -3. [Engineering Configuration of Engine](https://www.yuque.com/lce/doc/gxwqg6) +1. [How to configure the engine debugging environment? ](https://lowcode-engine.cn/site/docs/participate/prepare) +2. [About the R&D collaboration process of the engine](https://lowcode-engine.cn/site/docs/participate/flow) +3. [Engineering Configuration of Engine](https://lowcode-engine.cn/site/docs/participate/config) > Strongly recommend reading ["The Wisdom of Asking Questions"](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way), ["How to Ask Questions to the Open Source Community"](https: //github.com/seajs/seajs/issues/545) and [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html), [ "How to Submit Unanswerable Questions to Open Source Projects"](https://zhuanlan.zhihu.com/p/25795393), better questions are easier to get help. (This paragraph refers to [antd](https://github.com/ant-design/ant-design)) diff --git a/packages/engine/src/engine-core.ts b/packages/engine/src/engine-core.ts index 1610d456c..38761402e 100644 --- a/packages/engine/src/engine-core.ts +++ b/packages/engine/src/engine-core.ts @@ -1,9 +1,13 @@ +/* eslint-disable no-param-reassign */ import { createElement } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { globalContext, Editor, engineConfig, EngineOptions, Setters as InnerSetters } from '@alilc/lowcode-editor-core'; +import { globalContext, Editor, engineConfig, Setters as InnerSetters } from '@alilc/lowcode-editor-core'; +import { EngineOptions } from '@alilc/lowcode-types'; import { Designer, LowCodePluginManager, + ILowCodePluginContextPrivate, + ILowCodePluginContextApiAssembler, PluginPreference, } from '@alilc/lowcode-designer'; import { @@ -32,7 +36,8 @@ import symbols from './modules/symbols'; import { componentMetaParser } from './inner-plugins/component-meta-parser'; import { setterRegistry } from './inner-plugins/setter-registry'; import { defaultPanelRegistry } from './inner-plugins/default-panel-registry'; -export * from './modules/editor-types'; +import { shellModelFactory } from './modules/shell-model-factory'; + export * from './modules/skeleton-types'; export * from './modules/designer-types'; export * from './modules/lowcode-types'; @@ -48,12 +53,8 @@ globalContext.register(workSpace, 'workSpace'); const innerSkeleton = new InnerSkeleton(editor); editor.set('skeleton' as any, innerSkeleton); -const designer = new Designer({ editor }); +const designer = new Designer({ editor, shellModelFactory }); editor.set('designer' as any, designer); - -const plugins = new LowCodePluginManager(editor).toProxy(); -editor.set('plugins' as any, plugins); - const { project: innerProject } = designer; const hotkey = new Hotkey(); @@ -71,6 +72,21 @@ const event = new Event(editor, { prefix: 'common' }); const logger = getLogger({ level: 'warn', bizName: 'common' }); const common = new Common(editor, innerSkeleton); +const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = { + assembleApis: (context: ILowCodePluginContextPrivate) => { + context.hotkey = hotkey; + context.project = project; + context.skeleton = skeleton; + context.setters = setters; + context.material = material; + context.event = event; + context.config = config; + context.common = common; + }, +}; +const plugins = new LowCodePluginManager(pluginContextApiAssembler).toProxy(); +editor.set('plugins' as any, plugins); + export { skeleton, plugins, diff --git a/packages/engine/src/modules/designer-types.ts b/packages/engine/src/modules/designer-types.ts index e2023ef6f..9799f6b2c 100644 --- a/packages/engine/src/modules/designer-types.ts +++ b/packages/engine/src/modules/designer-types.ts @@ -13,7 +13,4 @@ export type ILowCodePluginConfig = designerCabin.ILowCodePluginConfig; export type ILowCodePluginManager = designerCabin.ILowCodePluginManager; export type ILowCodePluginContext = designerCabin.ILowCodePluginContext; export type IPluginConfigCreator = designerCabin.IPluginConfigCreator; -export type PluginPreference = designerCabin.PluginPreference; -export type PropsReducerContext = designerCabin.PropsReducerContext; -export type DragObjectType = designerCabin.DragObjectType; -export type DragNodeDataObject = designerCabin.DragNodeDataObject; \ No newline at end of file +export type PluginPreference = designerCabin.PluginPreference; \ No newline at end of file diff --git a/packages/engine/src/modules/editor-types.ts b/packages/engine/src/modules/editor-types.ts deleted file mode 100644 index 1306712a7..000000000 --- a/packages/engine/src/modules/editor-types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as editorCabin from '@alilc/lowcode-editor-core'; - -export type RegisteredSetter = editorCabin.RegisteredSetter; diff --git a/packages/engine/src/modules/live-editing.ts b/packages/engine/src/modules/live-editing.ts index 620fef895..b6e110a1c 100644 --- a/packages/engine/src/modules/live-editing.ts +++ b/packages/engine/src/modules/live-editing.ts @@ -1,5 +1,5 @@ import { EditingTarget, Node as DocNode, SaveHandler, LiveEditing } from '@alilc/lowcode-designer'; -import { isJSExpression } from '@alilc/lowcode-types'; +import { isJSExpression } from '@alilc/lowcode-utils'; function getText(node: DocNode, prop: string) { const p = node.getProp(prop, false); @@ -53,8 +53,7 @@ function equalText(v: any, innerText: string) { export const liveEditingSaveHander: SaveHandler = { condition: (prop) => { - // const v = prop.getValue(); - return prop.type === 'expression'; // || isI18nData(v); + return prop.type === 'expression'; }, onSaveContent: (content, prop) => { const v = prop.getValue(); diff --git a/packages/engine/src/modules/shell-model-factory.ts b/packages/engine/src/modules/shell-model-factory.ts new file mode 100644 index 000000000..05c7b19cb --- /dev/null +++ b/packages/engine/src/modules/shell-model-factory.ts @@ -0,0 +1,18 @@ +import { + Node as InnerNode, + SettingField as InnerSettingField, +} from '@alilc/lowcode-designer'; +import { IShellModelFactory, IPublicModelNode, IPublicModelSettingPropEntry } from '@alilc/lowcode-types'; +import { + Node, + SettingPropEntry, +} from '@alilc/lowcode-shell'; +class ShellModelFactory implements IShellModelFactory { + createNode(node: InnerNode | null | undefined): IPublicModelNode | null { + return Node.create(node); + } + createSettingPropEntry(prop: InnerSettingField): IPublicModelSettingPropEntry { + return SettingPropEntry.create(prop); + } +} +export const shellModelFactory = new ShellModelFactory(); \ No newline at end of file diff --git a/packages/ignitor/public/index.html b/packages/ignitor/public/index.html index 8f182f42c..147fe334d 100644 --- a/packages/ignitor/public/index.html +++ b/packages/ignitor/public/index.html @@ -8,12 +8,12 @@

- This project only provides engine resource files. For usage, go for + This project only provides engine resource files. For usage, go for Lowcode Demo

For local debugging of lowcode engine, please visit - proxy documentation + proxy documentation to get more information.

diff --git a/packages/plugin-designer/package.json b/packages/plugin-designer/package.json index 5e06b8cd8..a01ac6d4e 100644 --- a/packages/plugin-designer/package.json +++ b/packages/plugin-designer/package.json @@ -28,7 +28,7 @@ "@alib/build-scripts": "^0.1.3", "@types/react": "^16.9.13", "@types/react-dom": "^16.9.4", - "build-plugin-component": "^0.2.7" + "build-plugin-component": "^1.0.0" }, "publishConfig": { "access": "public", diff --git a/packages/plugin-outline-pane/package.json b/packages/plugin-outline-pane/package.json index a5129db9d..c67a36f66 100644 --- a/packages/plugin-outline-pane/package.json +++ b/packages/plugin-outline-pane/package.json @@ -28,7 +28,7 @@ "@types/node": "^13.7.1", "@types/react": "^16", "@types/react-dom": "^16", - "build-plugin-component": "^0.2.10", + "build-plugin-component": "^1.0.0", "build-plugin-fusion": "^0.1.1", "build-plugin-moment-locales": "^0.1.0" }, diff --git a/packages/plugin-outline-pane/src/tree-node.ts b/packages/plugin-outline-pane/src/tree-node.ts index 67efe5fba..54627de2c 100644 --- a/packages/plugin-outline-pane/src/tree-node.ts +++ b/packages/plugin-outline-pane/src/tree-node.ts @@ -1,4 +1,5 @@ -import { TitleContent, isI18nData } from '@alilc/lowcode-types'; +import { TitleContent } from '@alilc/lowcode-types'; +import { isI18nData } from '@alilc/lowcode-utils'; import { computed, obx, intl, makeObservable, action } from '@alilc/lowcode-editor-core'; import { Node, DocumentModel, isLocationChildrenDetail, LocationChildrenDetail, Designer } from '@alilc/lowcode-designer'; import { Tree } from './tree'; diff --git a/packages/plugin-outline-pane/src/views/tree.tsx b/packages/plugin-outline-pane/src/views/tree.tsx index 47ffd3c28..1765b7983 100644 --- a/packages/plugin-outline-pane/src/views/tree.tsx +++ b/packages/plugin-outline-pane/src/views/tree.tsx @@ -1,9 +1,10 @@ import { Component, MouseEvent as ReactMouseEvent } from 'react'; import { observer, Editor, globalContext } from '@alilc/lowcode-editor-core'; -import { Node, DragObjectType, isShaken } from '@alilc/lowcode-designer'; +import { Node, isShaken } from '@alilc/lowcode-designer'; import { isFormEvent, canClickNode } from '@alilc/lowcode-utils'; import { Tree } from '../tree'; import RootTreeNodeView from './root-tree-node'; +import { DragObjectType } from '@alilc/lowcode-types'; function getTreeNodeIdByEvent(e: ReactMouseEvent, stop: Element): null | string { let target: Element | null = e.target as Element; diff --git a/packages/rax-simulator-renderer/package.json b/packages/rax-simulator-renderer/package.json index 87134571b..680e78a70 100644 --- a/packages/rax-simulator-renderer/package.json +++ b/packages/rax-simulator-renderer/package.json @@ -36,7 +36,7 @@ "@types/rax": "^1.0.0", "@types/react": "^16", "@types/react-dom": "^16", - "build-plugin-component": "^0.2.11", + "build-plugin-component": "^1.0.0", "build-plugin-rax-component": "^0.2.11" }, "peerDependencies": { diff --git a/packages/rax-simulator-renderer/src/renderer.ts b/packages/rax-simulator-renderer/src/renderer.ts index 2e3f86cc4..0adb16aee 100644 --- a/packages/rax-simulator-renderer/src/renderer.ts +++ b/packages/rax-simulator-renderer/src/renderer.ts @@ -1,8 +1,8 @@ import { BuiltinSimulatorRenderer, Component, DocumentModel, Node, NodeInstance } from '@alilc/lowcode-designer'; -import { ComponentSchema, NodeSchema, NpmInfo, RootSchema, TransformStage } from '@alilc/lowcode-types'; +import { ComponentSchema, NodeSchema, NpmInfo, TransformStage } from '@alilc/lowcode-types'; import { Asset, compatibleLegaoSchema, cursor, isElement, isESModule, isPlainObject, isReactComponent, setNativeSelection } from '@alilc/lowcode-utils'; import LowCodeRenderer from '@alilc/lowcode-rax-renderer'; -import { computed, observable as obx, untracked, makeObservable, configure } from 'mobx'; +import { computed, observable as obx, makeObservable, configure } from 'mobx'; import DriverUniversal from 'driver-universal'; import { EventEmitter } from 'events'; import { createMemoryHistory, MemoryHistory } from 'history'; diff --git a/packages/react-renderer/package.json b/packages/react-renderer/package.json index 7d1ebf112..52c5211dd 100644 --- a/packages/react-renderer/package.json +++ b/packages/react-renderer/package.json @@ -27,7 +27,7 @@ "devDependencies": { "@alib/build-scripts": "^0.1.18", "@alifd/next": "^1.19.17", - "build-plugin-component": "^0.2.10", + "build-plugin-component": "^1.0.0", "build-plugin-fusion": "^0.1.0", "build-plugin-moment-locales": "^0.1.0", "react": "^16.4.1", diff --git a/packages/react-simulator-renderer/package.json b/packages/react-simulator-renderer/package.json index c91dec079..45cc423c8 100644 --- a/packages/react-simulator-renderer/package.json +++ b/packages/react-simulator-renderer/package.json @@ -34,7 +34,7 @@ "@types/react": "^16", "@types/react-dom": "^16", "@types/react-router": "5.1.18", - "build-plugin-component": "^0.2.11" + "build-plugin-component": "^1.0.0" }, "publishConfig": { "access": "public", diff --git a/packages/renderer-core/package.json b/packages/renderer-core/package.json index 6c818991f..217606287 100644 --- a/packages/renderer-core/package.json +++ b/packages/renderer-core/package.json @@ -46,7 +46,7 @@ "@types/react-is": "^17.0.3", "@types/react-test-renderer": "^17.0.1", "babel-jest": "^26.5.2", - "build-plugin-component": "^0.2.11", + "build-plugin-component": "^1.0.0", "jest": "^26.6.3", "react-test-renderer": "^17.0.2", "ts-jest": "^26.5.0" diff --git a/packages/renderer-core/src/renderer/base.tsx b/packages/renderer-core/src/renderer/base.tsx index afa3938e7..718a5d9c0 100644 --- a/packages/renderer-core/src/renderer/base.tsx +++ b/packages/renderer-core/src/renderer/base.tsx @@ -3,7 +3,8 @@ /* eslint-disable react/prop-types */ import classnames from 'classnames'; import { create as createDataSourceEngine } from '@alilc/lowcode-datasource-engine/interpret'; -import { isI18nData, isJSExpression, isJSFunction, NodeSchema, NodeData, JSONValue, CompositeValue } from '@alilc/lowcode-types'; +import { NodeSchema, NodeData, JSONValue, CompositeValue } from '@alilc/lowcode-types'; +import { isI18nData, isJSExpression, isJSFunction } from '@alilc/lowcode-utils'; import adapter from '../adapter'; import divFactory from '../components/Div'; import visualDomFactory from '../components/VisualDom'; @@ -29,7 +30,7 @@ import { isVariable, isJSSlot, } from '../utils'; -import { IBaseRendererProps, INodeInfo, IBaseRenderComponent, IBaseRendererContext, IGeneralConstructor, IRendererAppHelper, DataSource } from '../types'; +import { IBaseRendererProps, INodeInfo, IBaseRenderComponent, IBaseRendererContext, IRendererAppHelper, DataSource } from '../types'; import { compWrapper } from '../hoc'; import { IComponentConstruct, leafWrapper } from '../hoc/leaf'; import logger from '../utils/logger'; diff --git a/packages/renderer-core/src/utils/common.ts b/packages/renderer-core/src/utils/common.ts index d064b5593..7f3deed43 100644 --- a/packages/renderer-core/src/utils/common.ts +++ b/packages/renderer-core/src/utils/common.ts @@ -1,7 +1,8 @@ /* eslint-disable no-console */ /* eslint-disable no-new-func */ import logger from './logger'; -import { isI18nData, RootSchema, NodeSchema, isJSExpression, JSSlot } from '@alilc/lowcode-types'; +import { RootSchema, NodeSchema, JSSlot } from '@alilc/lowcode-types'; +import { isI18nData, isJSExpression } from '@alilc/lowcode-utils'; import { isEmpty } from 'lodash'; import IntlMessageFormat from 'intl-messageformat'; import pkg from '../../package.json'; diff --git a/packages/renderer-core/src/utils/data-helper.ts b/packages/renderer-core/src/utils/data-helper.ts index 9eb152df9..d884c13c9 100644 --- a/packages/renderer-core/src/utils/data-helper.ts +++ b/packages/renderer-core/src/utils/data-helper.ts @@ -1,7 +1,7 @@ /* eslint-disable no-console */ /* eslint-disable max-len */ /* eslint-disable object-curly-newline */ -import { isJSFunction } from '@alilc/lowcode-types'; +import { isJSFunction } from '@alilc/lowcode-utils'; import { transformArrayToMap, transformStringToFunction } from './common'; import { jsonp, request, get, post } from './request'; import logger from './logger'; diff --git a/packages/renderer-core/src/utils/is-use-loop.ts b/packages/renderer-core/src/utils/is-use-loop.ts index 913480f63..59d356f5d 100644 --- a/packages/renderer-core/src/utils/is-use-loop.ts +++ b/packages/renderer-core/src/utils/is-use-loop.ts @@ -1,4 +1,5 @@ -import { isJSExpression, JSExpression } from '@alilc/lowcode-types'; +import { JSExpression } from '@alilc/lowcode-types'; +import { isJSExpression } from '@alilc/lowcode-utils'; // 1.渲染模式下,loop 是数组,则按照数组长度渲染组件 // 2.设计模式下,loop 需要长度大于 0,按照循环模式渲染,防止无法设计的情况 diff --git a/packages/shell/package.json b/packages/shell/package.json index 9d0e0b62f..fd794904b 100644 --- a/packages/shell/package.json +++ b/packages/shell/package.json @@ -39,8 +39,8 @@ "@types/react": "^16", "@types/react-dom": "^16", "babel-jest": "^26.5.2", - "build-plugin-component": "^0.2.10", - "build-scripts-config": "^0.1.8", + "build-plugin-component": "^1.0.0", + "build-scripts-config": "^3.0.3", "jest": "^26.6.3", "lodash": "^4.17.20", "moment": "^2.29.1", diff --git a/packages/shell/src/canvas.ts b/packages/shell/src/canvas.ts index 268dbc4a8..a927f63d8 100644 --- a/packages/shell/src/canvas.ts +++ b/packages/shell/src/canvas.ts @@ -1,16 +1,19 @@ import { Designer } from '@alilc/lowcode-designer'; import { designerSymbol } from './symbols'; import DropLocation from './drop-location'; +import { IPublicModelCanvas } from '@alilc/lowcode-types'; -export default class Canvas { +export default class Canvas implements IPublicModelCanvas { private readonly [designerSymbol]: Designer; constructor(designer: Designer) { this[designerSymbol] = designer; } - static create(designer: Designer) { - if (!designer) return null; + static create(designer: Designer): IPublicModelCanvas | null { + if (!designer) { + return null; + } return new Canvas(designer); } diff --git a/packages/shell/src/common.tsx b/packages/shell/src/common.tsx index 6bd01bae0..f5f439397 100644 --- a/packages/shell/src/common.tsx +++ b/packages/shell/src/common.tsx @@ -3,36 +3,40 @@ import { isFormEvent as innerIsFormEvent, compatibleLegaoSchema as innerCompatibleLegaoSchema, getNodeSchemaById as innerGetNodeSchemaById, + isNodeSchema as innerIsNodeSchema, } from '@alilc/lowcode-utils'; import { - isNodeSchema as innerIsNodeSchema, NodeSchema, TransitionType, + TransformStage as InnerTransitionStage, + IPublicCommonDesignerCabin, + IPublicCommonSkeletonCabin, + IPublicCommonUtils, + IPublicApiCommon, + DragObjectType as InnerDragObjectType, } from '@alilc/lowcode-types'; import { - SettingField, - isSettingField, + SettingField as InnerSettingField, + isSettingField as innerIsSettingField, Designer, - TransformStage, - LiveEditing, - isDragNodeDataObject, - isDragNodeObject, - isDragAnyObject, - DragObjectType, - isNode, - isShaken, - contains, - LocationDetailType, - isLocationChildrenDetail, - ScrollTarget, + LiveEditing as InnerLiveEditing, + isDragNodeDataObject as innerIsDragNodeDataObject, + isDragNodeObject as innerIsDragNodeObject, + isDragAnyObject as innerIsDragAnyObject, + isNode as innerIsNode, + isShaken as innerIsShaken, + contains as innerContains, + LocationDetailType as InnerLocationDetailType, + isLocationChildrenDetail as innerIsLocationChildrenDetail, + ScrollTarget as InnerScrollTarget, getConvertedExtraKey as innerGetConvertedExtraKey, getOriginalExtraKey as innerGetOriginalExtraKey, } from '@alilc/lowcode-designer'; import { Skeleton as InnerSkeleton, - createSettingFieldView, - PopupContext, - PopupPipe, + createSettingFieldView as innerCreateSettingFieldView, + PopupContext as InnerPopupContext, + PopupPipe as InnerPopupPipe, Workbench as InnerWorkbench, } from '@alilc/lowcode-editor-skeleton'; import Dragon from './dragon'; @@ -40,68 +44,147 @@ import { Editor, Title as InnerTitle, Tip as InnerTip, - shallowIntl, + shallowIntl as innerShallowIntl, createIntl as innerCreateIntl, - intl, - // createSetterContent, - obx, - observable, - makeObservable, - untracked, - computed, - observer, - globalLocale, + intl as innerIntl, + // createSetterContent as innerCreateSetterContent, + globalLocale as innerGlobalLocale, + obx as innerObx, + observable as innerObservable, + makeObservable as innerMakeObservable, + untracked as innerUntracked, + computed as innerComputed, + observer as innerObserver, } from '@alilc/lowcode-editor-core'; import { ReactNode } from 'react'; import { transactionManager } from 'utils/src/transaction-manager'; -const getDesignerCabin = (editor: Editor) => { - const designer = editor.get('designer') as Designer; - - return { - SettingField, - isSettingField, - dragon: Dragon.create(designer.dragon), - TransformStage, - LiveEditing, - DragObjectType, - isDragNodeDataObject, - isNode, - [designerCabinSymbol]: { - isDragNodeObject, - isDragAnyObject, - isShaken, - contains, - LocationDetailType, - isLocationChildrenDetail, - ScrollTarget, - isSettingField, - TransformStage, - SettingField, - LiveEditing, - DragObjectType, - isDragNodeDataObject, - isNode, - }, - }; -}; - -const getSkeletonCabin = (skeleton: InnerSkeleton) => { - return { - createSettingFieldView, - PopupContext, - PopupPipe, - Workbench: (props: any) => , // hijack skeleton - }; -}; - -class Utils { - readonly [editorSymbol]: Editor; +class DesignerCabin implements IPublicCommonDesignerCabin { + private readonly [editorSymbol]: Editor; + /** + * @deprecated + */ + readonly [designerCabinSymbol]: any; constructor(editor: Editor) { this[editorSymbol] = editor; + this[designerCabinSymbol] = { + isDragNodeObject: innerIsDragNodeObject, + isDragAnyObject: innerIsDragAnyObject, + isShaken: innerIsShaken, + contains: innerContains, + LocationDetailType: InnerLocationDetailType, + isLocationChildrenDetail: innerIsLocationChildrenDetail, + ScrollTarget: InnerScrollTarget, + isSettingField: innerIsSettingField, + TransformStage: InnerTransitionStage, + SettingField: InnerSettingField, + LiveEditing: InnerLiveEditing, + DragObjectType: InnerDragObjectType, + isDragNodeDataObject: innerIsDragNodeDataObject, + isNode: innerIsNode, + }; } + /** + * 是否是 SettingField 实例 + * + * @param {*} obj + * @returns {obj is SettingField} + * @memberof DesignerCabin + */ + isSettingField(obj: any): obj is InnerSettingField { + return innerIsSettingField(obj); + } + + /** + * 转换类型枚举对象,包含 init / upgrade / render 等类型 + * [参考](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/transform-stage.ts) + * @deprecated use { TransformStage } from '@alilc/lowcode-types' instead + */ + get TransformStage() { + return InnerTransitionStage; + } + + /** + * @deprecated + */ + get SettingField() { + return InnerSettingField; + } + + /** + * @deprecated + */ + get dragon() { + const designer = this[editorSymbol].get('designer') as Designer; + return Dragon.create(designer.dragon); + } + + /** + * @deprecated + */ + get LiveEditing() { + return InnerLiveEditing; + } + + /** + * @deprecated + */ + get DragObjectType() { + return InnerDragObjectType; + } + + /** + * @deprecated + */ + isDragNodeDataObject(obj: any): boolean { + return innerIsDragNodeDataObject(obj); + } + + /** + * @deprecated + */ + isNode(node: any): boolean { + return innerIsNode(node); + } +} + +class SkeletonCabin implements IPublicCommonSkeletonCabin { + private readonly [skeletonSymbol]: InnerSkeleton; + + constructor(skeleton: InnerSkeleton) { + this[skeletonSymbol] = skeleton; + } + + get Workbench(): any { + const innerSkeleton = this[skeletonSymbol]; + return (props: any) => ; + } + + /** + * @deprecated + */ + createSettingFieldView(item: any, field: any) { + return innerCreateSettingFieldView(item, field); + } + + /** + * @deprecated + */ + get PopupContext(): any { + return InnerPopupContext; + } + + /** + * @deprecated + */ + get PopupPipe(): any { + return InnerPopupPipe; + } +} + +class Utils implements IPublicCommonUtils { isNodeSchema(data: any): data is NodeSchema { return innerIsNodeSchema(data); } @@ -140,47 +223,124 @@ class Utils { } } -export default class Common { - private readonly [editorSymbol]: Editor; - private readonly [skeletonSymbol]: InnerSkeleton; +class EditorCabin { + /** + * @deprecated + */ + get Title() { + return InnerTitle; + } + + /** + * @deprecated + */ + get Tip() { + return InnerTip; + } + + /** + * @deprecated + */ + shallowIntl(data: any): any { + return innerShallowIntl(data); + } + + /** + * @deprecated use common.utils.createIntl instead + */ + createIntl(instance: any): any { + return innerCreateIntl(instance); + } + + /** + * @deprecated + */ + intl(data: any, params?: object): any { + return innerIntl(data, params); + } + + // /** + // * @deprecated + // */ + // createSetterContent(setter: any, props: Record): ReactNode { + // return innerCreateSetterContent(setter, props); + // } + + /** + * @deprecated + */ + get globalLocale() { + return innerGlobalLocale; + } + + /** + * @deprecated + */ + get obx() { + return innerObx; + } + + /** + * @deprecated + */ + get observable() { + return innerObservable; + } + + /** + * @deprecated + */ + makeObservable(target: any, annotations: any, options: any) { + return innerMakeObservable(target, annotations, options); + } + + /** + * @deprecated + */ + untracked(action: any) { + return innerUntracked(action); + } + + /** + * @deprecated + */ + get computed() { + return innerComputed; + } + + /** + * @deprecated + */ + observer(component: any) { + return innerObserver(component); + } +} + + +export default class Common implements IPublicApiCommon { private readonly __designerCabin: any; private readonly __skeletonCabin: any; private readonly __editorCabin: any; private readonly __utils: Utils; constructor(editor: Editor, skeleton: InnerSkeleton) { - this[editorSymbol] = editor; - this[skeletonSymbol] = skeleton; - this.__designerCabin = getDesignerCabin(this[editorSymbol]); - this.__skeletonCabin = getSkeletonCabin(this[skeletonSymbol]); - this.__utils = new Utils(this[editorSymbol]); + this.__designerCabin = new DesignerCabin(editor); + this.__skeletonCabin = new SkeletonCabin(skeleton); + this.__editorCabin = new EditorCabin(); + this.__utils = new Utils(); } - objects = { - TransformStage, - }; - get utils(): any { return this.__utils; } + /** + * 历史原因导致此处设计不合理,慎用。 + * this load of crap will be removed in some future versions, don`t use it. + * @deprecated + */ get editorCabin(): any { - const Setters = this[editorSymbol].get('setters'); - return { - Title: InnerTitle, - Tip: InnerTip, - shallowIntl, - createIntl: innerCreateIntl, - intl, - createSetterContent: Setters.createSetterContent, - obx, - observable, - makeObservable, - untracked, - computed, - observer, - globalLocale, - }; + return this.__editorCabin; } get designerCabin(): any { @@ -190,4 +350,15 @@ export default class Common { get skeletonCabin(): any { return this.__skeletonCabin; } + + /** + * 历史原因导致此处设计不合理,慎用。 + * this load of crap will be removed in some future versions, don`t use it. + * @deprecated use { TransformStage } from '@alilc/lowcode-types' instead + */ + get objects(): any { + return { + TransformStage: InnerTransitionStage, + }; + } } \ No newline at end of file diff --git a/packages/shell/src/component-meta.ts b/packages/shell/src/component-meta.ts index 34502e4b2..8262f8cb8 100644 --- a/packages/shell/src/component-meta.ts +++ b/packages/shell/src/component-meta.ts @@ -2,19 +2,21 @@ import { ComponentMeta as InnerComponentMeta, ParentalNode, } from '@alilc/lowcode-designer'; -import Node from './node'; -import { NodeData, NodeSchema } from '@alilc/lowcode-types'; +import { NodeData, NodeSchema, IPublicModelComponentMeta, I18nData, IconType, NpmInfo, TransformedComponentMetadata, IPublicModelNode } from '@alilc/lowcode-types'; import { componentMetaSymbol, nodeSymbol } from './symbols'; +import { ReactElement } from 'react'; -export default class ComponentMeta { +export default class ComponentMeta implements IPublicModelComponentMeta { private readonly [componentMetaSymbol]: InnerComponentMeta; constructor(componentMeta: InnerComponentMeta) { this[componentMetaSymbol] = componentMeta; } - static create(componentMeta: InnerComponentMeta | null) { - if (!componentMeta) return null; + static create(componentMeta: InnerComponentMeta | null): IPublicModelComponentMeta | null { + if (!componentMeta) { + return null; + } return new ComponentMeta(componentMeta); } @@ -52,28 +54,28 @@ export default class ComponentMeta { /** * 元数据配置 */ - get configure() { + get configure(): any { return this[componentMetaSymbol].configure; } /** * 标题 */ - get title() { + get title(): string | I18nData | ReactElement { return this[componentMetaSymbol].title; } /** * 图标 */ - get icon() { + get icon(): IconType { return this[componentMetaSymbol].icon; } /** * 组件 npm 信息 */ - get npm() { + get npm(): NpmInfo { return this[componentMetaSymbol].npm; } @@ -84,7 +86,7 @@ export default class ComponentMeta { return this[componentMetaSymbol].prototype; } - get availableActions() { + get availableActions(): any { return this[componentMetaSymbol].availableActions; } @@ -92,7 +94,7 @@ export default class ComponentMeta { * 设置 npm 信息 * @param npm */ - setNpm(npm: any) { + setNpm(npm: NpmInfo): void { this[componentMetaSymbol].setNpm(npm); } @@ -100,7 +102,7 @@ export default class ComponentMeta { * 获取元数据 * @returns */ - getMetadata() { + getMetadata(): TransformedComponentMetadata { return this[componentMetaSymbol].getMetadata(); } @@ -111,8 +113,8 @@ export default class ComponentMeta { * @param parent * @returns */ - checkNestingUp(my: Node | NodeData, parent: ParentalNode) { - const curNode = my.isNode ? my[nodeSymbol] : my; + checkNestingUp(my: IPublicModelNode | NodeData, parent: ParentalNode): boolean { + const curNode = (my as any).isNode ? (my as any)[nodeSymbol] : my; return this[componentMetaSymbol].checkNestingUp(curNode as any, parent); } @@ -122,12 +124,12 @@ export default class ComponentMeta { * @param parent * @returns */ - checkNestingDown(my: Node | NodeData, target: NodeSchema | Node | NodeSchema[]) { - const curNode = my.isNode ? my[nodeSymbol] : my; - return this[componentMetaSymbol].checkNestingDown(curNode as any, target[nodeSymbol] || target); + checkNestingDown(my: IPublicModelNode | NodeData, target: NodeSchema | IPublicModelNode | NodeSchema[]) { + const curNode = (my as any)?.isNode ? (my as any)[nodeSymbol] : my; + return this[componentMetaSymbol].checkNestingDown(curNode as any, (target as any)[nodeSymbol] || target); } - refreshMetadata() { + refreshMetadata(): void { this[componentMetaSymbol].refreshMetadata(); } } diff --git a/packages/shell/src/detecting.ts b/packages/shell/src/detecting.ts index d8e6c7fbb..2baf02801 100644 --- a/packages/shell/src/detecting.ts +++ b/packages/shell/src/detecting.ts @@ -4,8 +4,9 @@ import { DocumentModel as InnerDocumentModel, } from '@alilc/lowcode-designer'; import { documentSymbol, detectingSymbol } from './symbols'; +import { IPublicModelDetecting } from '@alilc/lowcode-types'; -export default class Detecting { +export default class Detecting implements IPublicModelDetecting { private readonly [documentSymbol]: InnerDocumentModel; private readonly [detectingSymbol]: InnerDetecting; diff --git a/packages/shell/src/document-model.ts b/packages/shell/src/document-model.ts index 146b3c8f6..f82eab7e4 100644 --- a/packages/shell/src/document-model.ts +++ b/packages/shell/src/document-model.ts @@ -2,16 +2,26 @@ import { Editor } from '@alilc/lowcode-editor-core'; import { DocumentModel as InnerDocumentModel, Node as InnerNode, - IOnChangeOptions as InnerIOnChangeOptions, - DragObject as InnerDragObject, - DragNodeObject, - DragNodeDataObject, isDragNodeObject, + IOnChangeOptions as InnerOnChangeOptions, } from '@alilc/lowcode-designer'; import { TransformStage, RootSchema, GlobalEvent, + IPublicModelDocumentModel, + IPublicOnChangeOptions, + DragObject, + DragNodeObject, + DragNodeDataObject, + IPublicModelNode, + IPublicModelSelection, + IPublicModelDetecting, + IPublicModelHistory, + IPublicModelCanvas, + IPublicApiProject, + IPublicModelModalNodesManager, + PropChangeOptions, } from '@alilc/lowcode-types'; import Node from './node'; import Selection from './selection'; @@ -23,33 +33,20 @@ import Canvas from './canvas'; import ModalNodesManager from './modal-nodes-manager'; import { documentSymbol, editorSymbol, nodeSymbol } from './symbols'; -type IOnChangeOptions = { - type: string; - node: Node; -}; - -type PropChangeOptions = { - key?: string | number; - prop?: Prop; - node: Node; - newValue: any; - oldValue: any; -}; - export const Events = { IMPORT_SCHEMA: 'shell.document.importSchema', }; const shellDocSymbol = Symbol('shellDocSymbol'); -export default class DocumentModel { +export default class DocumentModel implements IPublicModelDocumentModel { private readonly [documentSymbol]: InnerDocumentModel; private readonly [editorSymbol]: Editor; - private _focusNode: Node; - public selection: Selection; - public detecting: Detecting; - public history: History; - public canvas: Canvas; + private _focusNode: IPublicModelNode | null; + selection: IPublicModelSelection; + detecting: IPublicModelDetecting; + history: IPublicModelHistory; + canvas: IPublicModelCanvas; constructor(document: InnerDocumentModel) { this[documentSymbol] = document; @@ -62,10 +59,14 @@ export default class DocumentModel { this._focusNode = Node.create(this[documentSymbol].focusNode); } - static create(document: InnerDocumentModel | undefined | null) { - if (!document) return null; + static create(document: InnerDocumentModel | undefined | null): IPublicModelDocumentModel | null { + if (!document) { + return null; + } // @ts-ignore 直接返回已挂载的 shell doc 实例 - if (document[shellDocSymbol]) return document[shellDocSymbol]; + if (document[shellDocSymbol]) { + return (document as any)[shellDocSymbol]; + } const shellDoc = new DocumentModel(document); // @ts-ignore 直接返回已挂载的 shell doc 实例 document[shellDocSymbol] = shellDoc; @@ -75,7 +76,7 @@ export default class DocumentModel { /** * id */ - get id() { + get id(): string { return this[documentSymbol].id; } @@ -87,7 +88,7 @@ export default class DocumentModel { * 获取当前文档所属的 project * @returns */ - get project() { + get project(): IPublicApiProject | null { return Project.create(this[documentSymbol].project); } @@ -95,15 +96,15 @@ export default class DocumentModel { * 获取文档的根节点 * @returns */ - get root(): Node | null { + get root(): IPublicModelNode | null { return Node.create(this[documentSymbol].getRoot()); } - get focusNode(): Node { + get focusNode(): IPublicModelNode | null { return this._focusNode || this.root; } - set focusNode(node: Node) { + set focusNode(node: IPublicModelNode | null) { this._focusNode = node; } @@ -111,8 +112,8 @@ export default class DocumentModel { * 获取文档下所有节点 * @returns */ - get nodesMap() { - const map = new Map(); + get nodesMap(): any { + const map = new Map(); for (let id of this[documentSymbol].nodesMap.keys()) { map.set(id, this.getNodeById(id)!); } @@ -122,12 +123,15 @@ export default class DocumentModel { /** * 模态节点管理 */ - get modalNodesManager() { + get modalNodesManager(): IPublicModelModalNodesManager | null { return ModalNodesManager.create(this[documentSymbol].modalNodesManager); } - // @TODO: 不能直接暴露 - get dropLocation() { + /** + * @TODO: 不能直接暴露 + * @deprecated + */ + get dropLocation(): any { return this[documentSymbol].dropLocation; } @@ -136,7 +140,7 @@ export default class DocumentModel { * @param nodeId * @returns */ - getNodeById(nodeId: string) { + getNodeById(nodeId: string): IPublicModelNode | null { return Node.create(this[documentSymbol].getNode(nodeId)); } @@ -144,7 +148,7 @@ export default class DocumentModel { * 导入 schema * @param schema */ - importSchema(schema: RootSchema) { + importSchema(schema: RootSchema): void { this[documentSymbol].import(schema); this[editorSymbol].emit(Events.IMPORT_SCHEMA, schema); } @@ -154,7 +158,7 @@ export default class DocumentModel { * @param stage * @returns */ - exportSchema(stage: TransformStage = TransformStage.Render) { + exportSchema(stage: TransformStage = TransformStage.Render): any { return this[documentSymbol].export(stage); } @@ -167,14 +171,14 @@ export default class DocumentModel { * @returns */ insertNode( - parent: Node, - thing: Node, + parent: IPublicModelNode, + thing: IPublicModelNode, at?: number | null | undefined, copy?: boolean | undefined, - ) { + ): IPublicModelNode | null { const node = this[documentSymbol].insertNode( - parent[nodeSymbol] ? parent[nodeSymbol] : parent, - thing?.[nodeSymbol] ? thing[nodeSymbol] : thing, + (parent as any)[nodeSymbol] ? (parent as any)[nodeSymbol] : parent, + (thing as any)?.[nodeSymbol] ? (thing as any)[nodeSymbol] : thing, at, copy, ); @@ -186,7 +190,7 @@ export default class DocumentModel { * @param data * @returns */ - createNode(data: any) { + createNode(data: any): IPublicModelNode | null { return Node.create(this[documentSymbol].createNode(data)); } @@ -194,7 +198,7 @@ export default class DocumentModel { * 移除指定节点/节点id * @param idOrNode */ - removeNode(idOrNode: string | Node) { + removeNode(idOrNode: string | IPublicModelNode): void { this[documentSymbol].removeNode(idOrNode as any); } @@ -203,7 +207,7 @@ export default class DocumentModel { * @param extraComps * @returns */ - getComponentsMap(extraComps?: string[]) { + getComponentsMap(extraComps?: string[]): any { return this[documentSymbol].getComponentsMap(extraComps); } @@ -213,13 +217,16 @@ export default class DocumentModel { * @param dragObject 拖拽的对象 * @returns boolean 是否可以放置 */ - checkNesting(dropTarget: Node, dragObject: DragNodeObject | DragNodeDataObject): boolean { - let innerDragObject: InnerDragObject = dragObject; + checkNesting( + dropTarget: IPublicModelNode, + dragObject: DragNodeObject | DragNodeDataObject, + ): boolean { + let innerDragObject: DragObject = dragObject; if (isDragNodeObject(dragObject)) { innerDragObject.nodes = innerDragObject.nodes.map((node: Node) => (node[nodeSymbol] || node)); } return this[documentSymbol].checkNesting( - (dropTarget[nodeSymbol] || dropTarget) as any, + ((dropTarget as any)[nodeSymbol] || dropTarget) as any, innerDragObject as any, ); } @@ -227,7 +234,7 @@ export default class DocumentModel { /** * 当前 document 新增节点事件 */ - onAddNode(fn: (node: Node) => void) { + onAddNode(fn: (node: IPublicModelNode) => void): () => void { return this[documentSymbol].onNodeCreate((node: InnerNode) => { fn(Node.create(node)!); }); @@ -236,7 +243,7 @@ export default class DocumentModel { /** * 当前 document 新增节点事件,此时节点已经挂载到 document 上 */ - onMountNode(fn: (payload: { node: Node }) => void) { + onMountNode(fn: (payload: { node: IPublicModelNode }) => void): () => void { this[editorSymbol].on('node.add', fn as any); return () => { this[editorSymbol].off('node.add', fn as any); @@ -246,7 +253,7 @@ export default class DocumentModel { /** * 当前 document 删除节点事件 */ - onRemoveNode(fn: (node: Node) => void) { + onRemoveNode(fn: (node: IPublicModelNode) => void): () => void { return this[documentSymbol].onNodeDestroy((node: InnerNode) => { fn(Node.create(node)!); }); @@ -255,7 +262,7 @@ export default class DocumentModel { /** * 当前 document 的 hover 变更事件 */ - onChangeDetecting(fn: (node: Node) => void) { + onChangeDetecting(fn: (node: IPublicModelNode) => void): () => void { return this[documentSymbol].designer.detecting.onDetectingChange((node: InnerNode) => { fn(Node.create(node)!); }); @@ -264,7 +271,7 @@ export default class DocumentModel { /** * 当前 document 的选中变更事件 */ - onChangeSelection(fn: (ids: string[]) => void) { + onChangeSelection(fn: (ids: string[]) => void): () => void { return this[documentSymbol].selection.onSelectionChange((ids: string[]) => { fn(ids); }); @@ -274,9 +281,9 @@ export default class DocumentModel { * 当前 document 的节点显隐状态变更事件 * @param fn */ - onChangeNodeVisible(fn: (node: Node, visible: boolean) => void) { + onChangeNodeVisible(fn: (node: IPublicModelNode, visible: boolean) => void): void { // TODO: history 变化时需要重新绑定 - this[documentSymbol].nodesMap.forEach((node) => { + this[documentSymbol].nodesMap?.forEach((node) => { node.onVisibleChange((flag: boolean) => { fn(Node.create(node)!, flag); }); @@ -287,10 +294,10 @@ export default class DocumentModel { * 当前 document 的节点 children 变更事件 * @param fn */ - onChangeNodeChildren(fn: (info?: IOnChangeOptions) => void) { + onChangeNodeChildren(fn: (info?: IPublicOnChangeOptions) => void): void { // TODO: history 变化时需要重新绑定 - this[documentSymbol].nodesMap.forEach((node) => { - node.onChildrenChange((info?: InnerIOnChangeOptions) => { + this[documentSymbol].nodesMap?.forEach((node) => { + node.onChildrenChange((info?: InnerOnChangeOptions) => { return info ? fn({ type: info.type, @@ -305,7 +312,7 @@ export default class DocumentModel { * 当前 document 节点属性修改事件 * @param fn */ - onChangeNodeProp(fn: (info: PropChangeOptions) => void) { + onChangeNodeProp(fn: (info: PropChangeOptions) => void): void { this[editorSymbol].on( GlobalEvent.Node.Prop.InnerChange, (info: GlobalEvent.Node.Prop.ChangeOptions) => { @@ -324,7 +331,7 @@ export default class DocumentModel { * import schema event * @param fn */ - onImportSchema(fn: (schema: RootSchema) => void) { + onImportSchema(fn: (schema: RootSchema) => void): void { this[editorSymbol].on(Events.IMPORT_SCHEMA, fn as any); } } diff --git a/packages/shell/src/drag-object.ts b/packages/shell/src/drag-object.ts index 1261b4d26..f09cedecb 100644 --- a/packages/shell/src/drag-object.ts +++ b/packages/shell/src/drag-object.ts @@ -1,30 +1,34 @@ -import { DragObject as InnerDragObject, DragNodeDataObject } from '@alilc/lowcode-designer'; import { dragObjectSymbol } from './symbols'; +import { IPublicModelDragObject, DragObject as InnerDragObject, DragNodeDataObject } from '@alilc/lowcode-types'; import Node from './node'; -export default class DragObject { +export default class DragObject implements IPublicModelDragObject { private readonly [dragObjectSymbol]: InnerDragObject; constructor(dragObject: InnerDragObject) { this[dragObjectSymbol] = dragObject; } - static create(dragObject: InnerDragObject) { - if (!dragObject) return null; + static create(dragObject: InnerDragObject): IPublicModelDragObject | null { + if (!dragObject) { + return null; + } return new DragObject(dragObject); } - get type() { + get type(): any { return this[dragObjectSymbol].type; } - get nodes() { + get nodes(): any { const { nodes } = this[dragObjectSymbol]; - if (!nodes) return null; + if (!nodes) { + return null; + } return nodes.map(Node.create); } - get data() { + get data(): any { return (this[dragObjectSymbol] as DragNodeDataObject).data; } } \ No newline at end of file diff --git a/packages/shell/src/dragon.ts b/packages/shell/src/dragon.ts index d6c464cc1..cf65d5b56 100644 --- a/packages/shell/src/dragon.ts +++ b/packages/shell/src/dragon.ts @@ -1,17 +1,27 @@ import { Dragon as InnerDragon, - DragObject as InnerDragObject, - DragNodeDataObject, LocateEvent as InnerLocateEvent, } from '@alilc/lowcode-designer'; import { dragonSymbol } from './symbols'; import LocateEvent from './locate-event'; import DragObject from './drag-object'; import { globalContext } from '@alilc/lowcode-editor-core'; +import { + IPublicModelDragon, + IPublicModelLocateEvent, + IPublicModelDragObject, + DragObject as InnerDragObject, + DragNodeDataObject, +} from '@alilc/lowcode-types'; export const innerDragonSymbol = Symbol('innerDragonSymbol'); -export default class Dragon { + +export default class Dragon implements IPublicModelDragon { + constructor(dragon: InnerDragon) { + this[innerDragonSymbol] = dragon; + } + private readonly [innerDragonSymbol]: InnerDragon; get [dragonSymbol](): any { @@ -26,19 +36,17 @@ export default class Dragon { return designer.dragon; } - constructor(dragon: InnerDragon) { - this[innerDragonSymbol] = dragon; - } - - static create(dragon: InnerDragon | null) { - if (!dragon) return null; + static create(dragon: InnerDragon | null): IPublicModelDragon | null { + if (!dragon) { + return null; + } return new Dragon(dragon); } /** * is dragging or not */ - get dragging() { + get dragging(): boolean { return this[dragonSymbol].dragging; } @@ -47,7 +55,7 @@ export default class Dragon { * @param func * @returns */ - onDragstart(func: (e: LocateEvent) => any) { + onDragstart(func: (e: IPublicModelLocateEvent) => any): () => void { return this[dragonSymbol].onDragstart((e: InnerLocateEvent) => func(LocateEvent.create(e)!)); } @@ -56,7 +64,7 @@ export default class Dragon { * @param func * @returns */ - onDrag(func: (e: LocateEvent) => any) { + onDrag(func: (e: IPublicModelLocateEvent) => any): () => void { return this[dragonSymbol].onDrag((e: InnerLocateEvent) => func(LocateEvent.create(e)!)); } @@ -65,7 +73,7 @@ export default class Dragon { * @param func * @returns */ - onDragend(func: (o: { dragObject: DragObject; copy?: boolean }) => any) { + onDragend(func: (o: { dragObject: IPublicModelDragObject; copy?: boolean }) => any): () => void { return this[dragonSymbol].onDragend( (o: { dragObject: InnerDragObject; copy?: boolean }) => func({ dragObject: DragObject.create(o.dragObject)!, @@ -79,7 +87,7 @@ export default class Dragon { * @param shell 拖拽监听的区域 * @param boost 拖拽转换函数 */ - from(shell: Element, boost: (e: MouseEvent) => DragNodeDataObject | null) { + from(shell: Element, boost: (e: MouseEvent) => DragNodeDataObject | null): any { return this[dragonSymbol].from(shell, boost); } } diff --git a/packages/shell/src/drop-location.ts b/packages/shell/src/drop-location.ts index 14eff23ed..42e8a30df 100644 --- a/packages/shell/src/drop-location.ts +++ b/packages/shell/src/drop-location.ts @@ -3,16 +3,19 @@ import { } from '@alilc/lowcode-designer'; import { dropLocationSymbol } from './symbols'; import Node from './node'; +import { IPublicModelDropLocation } from '@alilc/lowcode-types'; -export default class DropLocation { +export default class DropLocation implements IPublicModelDropLocation { private readonly [dropLocationSymbol]: InnerDropLocation; constructor(dropLocation: InnerDropLocation) { this[dropLocationSymbol] = dropLocation; } - static create(dropLocation: InnerDropLocation | null) { - if (!dropLocation) return null; + static create(dropLocation: InnerDropLocation | null): DropLocation | null { + if (!dropLocation) { + return null; + } return new DropLocation(dropLocation); } diff --git a/packages/shell/src/event.ts b/packages/shell/src/event.ts index 425bf16a1..c3cb56c06 100644 --- a/packages/shell/src/event.ts +++ b/packages/shell/src/event.ts @@ -1,6 +1,7 @@ import { Editor as InnerEditor, globalContext } from '@alilc/lowcode-editor-core'; import { getLogger } from '@alilc/lowcode-utils'; import { editorSymbol } from './symbols'; +import { IPublicApiEvent } from '@alilc/lowcode-types'; const logger = getLogger({ level: 'warn', bizName: 'shell:event' }); @@ -10,8 +11,9 @@ type EventOptions = { const innerEditorSymbol = Symbol('editor'); -export default class Event { +export default class Event implements IPublicApiEvent { private readonly [innerEditorSymbol]: InnerEditor; + // private readonly [editorSymbol]: InnerEditor; private readonly options: EventOptions; // TODO: diff --git a/packages/shell/src/history.ts b/packages/shell/src/history.ts index 267c7fd99..06945a2d6 100644 --- a/packages/shell/src/history.ts +++ b/packages/shell/src/history.ts @@ -1,7 +1,8 @@ -import { History as InnerHistory, DocumentModel as InnerDocumentModel } from '@alilc/lowcode-designer'; +import { DocumentModel as InnerDocumentModel } from '@alilc/lowcode-designer'; import { historySymbol, documentSymbol } from './symbols'; +import { IPublicModelHistory } from '@alilc/lowcode-types'; -export default class History { +export default class History implements IPublicModelHistory { private readonly [documentSymbol]: InnerDocumentModel; private get [historySymbol]() { @@ -16,28 +17,28 @@ export default class History { * 历史记录跳转到指定位置 * @param cursor */ - go(cursor: number) { + go(cursor: number): void { this[historySymbol].go(cursor); } /** * 历史记录后退 */ - back() { + back(): void { this[historySymbol].back(); } /** * 历史记录前进 */ - forward() { + forward(): void { this[historySymbol].forward(); } /** * 保存当前状态 */ - savePoint() { + savePoint(): void { this[historySymbol].savePoint(); } @@ -45,7 +46,7 @@ export default class History { * 当前是否是「保存点」,即是否有状态变更但未保存 * @returns */ - isSavePoint() { + isSavePoint(): boolean { return this[historySymbol].isSavePoint(); } @@ -53,7 +54,7 @@ export default class History { * 获取 state,判断当前是否为「可回退」、「可前进」的状态 * @returns */ - getState() { + getState(): any { return this[historySymbol].getState(); } @@ -62,7 +63,7 @@ export default class History { * @param func * @returns */ - onChangeState(func: () => any) { + onChangeState(func: () => any): () => void { return this[historySymbol].onStateChange(func); } @@ -71,7 +72,7 @@ export default class History { * @param func * @returns */ - onChangeCursor(func: () => any) { + onChangeCursor(func: () => any): () => void { return this[historySymbol].onCursor(func); } } diff --git a/packages/shell/src/hotkey.ts b/packages/shell/src/hotkey.ts index 23126dd42..c2daeaa21 100644 --- a/packages/shell/src/hotkey.ts +++ b/packages/shell/src/hotkey.ts @@ -1,7 +1,7 @@ -import { hotkey, HotkeyCallback } from '@alilc/lowcode-editor-core'; -import { Disposable } from '@alilc/lowcode-types'; +import { hotkey } from '@alilc/lowcode-editor-core'; +import { Disposable, HotkeyCallback, IPublicApiHotkey } from '@alilc/lowcode-types'; -export default class Hotkey { +export default class Hotkey implements IPublicApiHotkey { constructor(public name: string = 'unknown', public workspaceMode: boolean = false) { } diff --git a/packages/shell/src/locate-event.ts b/packages/shell/src/locate-event.ts index 01c97edae..d6ca596ee 100644 --- a/packages/shell/src/locate-event.ts +++ b/packages/shell/src/locate-event.ts @@ -1,48 +1,51 @@ import { LocateEvent as InnerLocateEvent } from '@alilc/lowcode-designer'; import { locateEventSymbol } from './symbols'; import DragObject from './drag-object'; +import { IPublicModelLocateEvent, IPublicModelDragObject } from '@alilc/lowcode-types'; -export default class LocateEvent { +export default class LocateEvent implements IPublicModelLocateEvent { private readonly [locateEventSymbol]: InnerLocateEvent; constructor(locateEvent: InnerLocateEvent) { this[locateEventSymbol] = locateEvent; } - static create(locateEvent: InnerLocateEvent) { - if (!locateEvent) return null; + static create(locateEvent: InnerLocateEvent): IPublicModelLocateEvent | null { + if (!locateEvent) { + return null; + } return new LocateEvent(locateEvent); } - get type() { + get type(): string { return this[locateEventSymbol].type; } - get globalX() { + get globalX(): number { return this[locateEventSymbol].globalX; } - get globalY() { + get globalY(): number { return this[locateEventSymbol].globalY; } - get originalEvent() { + get originalEvent(): MouseEvent | DragEvent { return this[locateEventSymbol].originalEvent; } - get target() { + get target(): Element | null | undefined { return this[locateEventSymbol].target; } - get canvasX() { + get canvasX(): number | undefined { return this[locateEventSymbol].canvasX; } - get canvasY() { + get canvasY(): number | undefined { return this[locateEventSymbol].canvasY; } - get dragObject() { + get dragObject(): IPublicModelDragObject | null { return DragObject.create(this[locateEventSymbol].dragObject); } } \ No newline at end of file diff --git a/packages/shell/src/material.ts b/packages/shell/src/material.ts index 78d5ee4fb..32f00ca4f 100644 --- a/packages/shell/src/material.ts +++ b/packages/shell/src/material.ts @@ -2,7 +2,6 @@ import { Editor, globalContext } from '@alilc/lowcode-editor-core'; import { Designer, registerMetadataTransducer, - MetadataTransducer, getRegisteredMetadataTransducers, addBuiltinComponentAction, removeBuiltinComponentAction, @@ -10,13 +9,18 @@ import { isComponentMeta, } from '@alilc/lowcode-designer'; import { AssetsJson } from '@alilc/lowcode-utils'; -import { ComponentAction, ComponentMetadata } from '@alilc/lowcode-types'; +import { + ComponentAction, + ComponentMetadata, + IPublicApiMaterial, + MetadataTransducer, + IPublicModelComponentMeta, +} from '@alilc/lowcode-types'; import { editorSymbol, designerSymbol } from './symbols'; import ComponentMeta from './component-meta'; const innerEditorSymbol = Symbol('editor'); - -export default class Material { +export default class Material implements IPublicApiMaterial { // private readonly [editorSymbol]: Editor; private readonly [innerEditorSymbol]: Editor; // private readonly [designerSymbol]: Designer; @@ -106,8 +110,9 @@ export default class Material { * @param componentName * @returns */ - getComponentMeta(componentName: string) { - return ComponentMeta.create(this[designerSymbol].getComponentMeta(componentName)); + getComponentMeta(componentName: string): IPublicModelComponentMeta | null { + const innerMeta = this[designerSymbol].getComponentMeta(componentName); + return ComponentMeta.create(innerMeta); } /** @@ -132,8 +137,8 @@ export default class Material { * 获取所有已注册的物料元数据 * @returns */ - getComponentMetasMap() { - const map = new Map(); + getComponentMetasMap(): Map { + const map = new Map(); const originalMap = this[designerSymbol].getComponentMetasMap(); for (let componentName of originalMap.keys()) { map.set(componentName, this.getComponentMeta(componentName)!); diff --git a/packages/shell/src/modal-nodes-manager.ts b/packages/shell/src/modal-nodes-manager.ts index 739ca9406..4e556607a 100644 --- a/packages/shell/src/modal-nodes-manager.ts +++ b/packages/shell/src/modal-nodes-manager.ts @@ -1,24 +1,28 @@ import { ModalNodesManager as InnerModalNodesManager, Node as InnerNode } from '@alilc/lowcode-designer'; -import { NodeSchema, NodeData, TransformStage } from '@alilc/lowcode-types'; +import { IPublicModelModalNodesManager, IPublicModelNode } from '@alilc/lowcode-types'; import Node from './node'; import { nodeSymbol, modalNodesManagerSymbol } from './symbols'; -export default class ModalNodesManager { +export default class ModalNodesManager implements IPublicModelModalNodesManager { private readonly [modalNodesManagerSymbol]: InnerModalNodesManager; constructor(modalNodesManager: InnerModalNodesManager) { this[modalNodesManagerSymbol] = modalNodesManager; } - static create(modalNodesManager: InnerModalNodesManager | null) { - if (!modalNodesManager) return null; + static create( + modalNodesManager: InnerModalNodesManager | null, + ): IPublicModelModalNodesManager | null { + if (!modalNodesManager) { + return null; + } return new ModalNodesManager(modalNodesManager); } /** * 设置模态节点,触发内部事件 */ - setNodes() { + setNodes(): void { this[modalNodesManagerSymbol].setNodes(); } @@ -26,7 +30,7 @@ export default class ModalNodesManager { * 获取模态节点(们) * @returns */ - getModalNodes() { + getModalNodes(): any { return this[modalNodesManagerSymbol].getModalNodes().map((node) => Node.create(node)); } @@ -34,14 +38,14 @@ export default class ModalNodesManager { * 获取当前可见的模态节点 * @returns */ - getVisibleModalNode() { + getVisibleModalNode(): any { return Node.create(this[modalNodesManagerSymbol].getVisibleModalNode()); } /** * 隐藏模态节点(们) */ - hideModalNodes() { + hideModalNodes(): void { this[modalNodesManagerSymbol].hideModalNodes(); } @@ -49,7 +53,7 @@ export default class ModalNodesManager { * 设置指定节点为可见态 * @param node Node */ - setVisible(node: Node) { + setVisible(node: IPublicModelNode): void { this[modalNodesManagerSymbol].setVisible(node[nodeSymbol]); } @@ -57,7 +61,7 @@ export default class ModalNodesManager { * 设置指定节点为不可见态 * @param node Node */ - setInvisible(node: Node) { + setInvisible(node: IPublicModelNode): void { this[modalNodesManagerSymbol].setInvisible(node[nodeSymbol]); } } \ No newline at end of file diff --git a/packages/shell/src/node-children.ts b/packages/shell/src/node-children.ts index 2557e37ac..9ff2f93b6 100644 --- a/packages/shell/src/node-children.ts +++ b/packages/shell/src/node-children.ts @@ -1,31 +1,33 @@ import { NodeChildren as InnerNodeChildren, Node as InnerNode } from '@alilc/lowcode-designer'; -import { NodeSchema, NodeData, TransformStage } from '@alilc/lowcode-types'; +import { NodeSchema, NodeData, TransformStage, IPublicModelNodeChildren, IPublicModelNode } from '@alilc/lowcode-types'; import Node from './node'; import { nodeSymbol, nodeChildrenSymbol } from './symbols'; -export default class NodeChildren { +export default class NodeChildren implements IPublicModelNodeChildren { private readonly [nodeChildrenSymbol]: InnerNodeChildren; constructor(nodeChildren: InnerNodeChildren) { this[nodeChildrenSymbol] = nodeChildren; } - static create(nodeChldren: InnerNodeChildren | null) { - if (!nodeChldren) return null; + static create(nodeChldren: InnerNodeChildren | null): IPublicModelNodeChildren | null { + if (!nodeChldren) { + return null; + } return new NodeChildren(nodeChldren); } /** * 返回当前 children 实例所属的节点实例 */ - get owner(): Node | null { + get owner(): IPublicModelNode | null { return Node.create(this[nodeChildrenSymbol].owner); } /** * children 内的节点实例数 */ - get size() { + get size(): number { return this[nodeChildrenSymbol].size; } @@ -33,14 +35,14 @@ export default class NodeChildren { * 是否为空 * @returns */ - get isEmpty() { + get isEmpty(): boolean { return this[nodeChildrenSymbol].isEmpty(); } /** * judge if it is not empty */ - get notEmpty() { + get notEmpty(): boolean { return !this.isEmpty; } @@ -49,8 +51,8 @@ export default class NodeChildren { * @param node * @returns */ - delete(node: Node) { - return this[nodeChildrenSymbol].delete(node[nodeSymbol]); + delete(node: IPublicModelNode): boolean { + return this[nodeChildrenSymbol].delete((node as any)[nodeSymbol]); } /** @@ -59,8 +61,8 @@ export default class NodeChildren { * @param at 插入下标 * @returns */ - insert(node: Node, at?: number | null) { - return this[nodeChildrenSymbol].insert(node[nodeSymbol], at, true); + insert(node: IPublicModelNode, at?: number | null): void { + return this[nodeChildrenSymbol].insert((node as any)[nodeSymbol], at, true); } /** @@ -68,8 +70,8 @@ export default class NodeChildren { * @param node * @returns */ - indexOf(node: Node) { - return this[nodeChildrenSymbol].indexOf(node[nodeSymbol]); + indexOf(node: IPublicModelNode): number { + return this[nodeChildrenSymbol].indexOf((node as any)[nodeSymbol]); } /** @@ -78,8 +80,8 @@ export default class NodeChildren { * @param deleteCount * @param node */ - splice(start: number, deleteCount: number, node?: Node) { - this[nodeChildrenSymbol].splice(start, deleteCount, node?.[nodeSymbol]); + splice(start: number, deleteCount: number, node?: IPublicModelNode): any { + this[nodeChildrenSymbol].splice(start, deleteCount, (node as any)?.[nodeSymbol]); } /** @@ -87,7 +89,7 @@ export default class NodeChildren { * @param index * @returns */ - get(index: number) { + get(index: number): any { return Node.create(this[nodeChildrenSymbol].get(index)); } @@ -96,15 +98,15 @@ export default class NodeChildren { * @param node * @returns */ - has(node: Node) { - return this[nodeChildrenSymbol].has(node[nodeSymbol]); + has(node: IPublicModelNode): boolean { + return this[nodeChildrenSymbol].has((node as any)[nodeSymbol]); } /** * 类似数组的 forEach * @param fn */ - forEach(fn: (node: Node, index: number) => void) { + forEach(fn: (node: IPublicModelNode, index: number) => void): void { this[nodeChildrenSymbol].forEach((item: InnerNode, index: number) => { fn(Node.create(item)!, index); }); @@ -114,7 +116,7 @@ export default class NodeChildren { * 类似数组的 map * @param fn */ - map(fn: (node: Node, index: number) => T[]) { + map(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null { return this[nodeChildrenSymbol].map((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }); @@ -124,7 +126,7 @@ export default class NodeChildren { * 类似数组的 every * @param fn */ - every(fn: (node: Node, index: number) => boolean) { + every(fn: (node: IPublicModelNode, index: number) => boolean): boolean { return this[nodeChildrenSymbol].every((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }); @@ -134,7 +136,7 @@ export default class NodeChildren { * 类似数组的 some * @param fn */ - some(fn: (node: Node, index: number) => boolean) { + some(fn: (node: IPublicModelNode, index: number) => boolean): boolean { return this[nodeChildrenSymbol].some((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); }); @@ -144,7 +146,7 @@ export default class NodeChildren { * 类似数组的 filter * @param fn */ - filter(fn: (node: Node, index: number) => boolean) { + filter(fn: (node: IPublicModelNode, index: number) => boolean): any { return this[nodeChildrenSymbol] .filter((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); @@ -156,7 +158,7 @@ export default class NodeChildren { * 类似数组的 find * @param fn */ - find(fn: (node: Node, index: number) => boolean) { + find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null { return Node.create( this[nodeChildrenSymbol].find((item: InnerNode, index: number) => { return fn(Node.create(item)!, index); @@ -168,7 +170,7 @@ export default class NodeChildren { * 类似数组的 reduce * @param fn */ - reduce(fn: (acc: any, cur: Node) => any, initialValue: any) { + reduce(fn: (acc: any, cur: IPublicModelNode) => any, initialValue: any): void { return this[nodeChildrenSymbol].reduce((acc: any, cur: InnerNode) => { return fn(acc, Node.create(cur)!); }, initialValue); @@ -178,7 +180,7 @@ export default class NodeChildren { * 导入 schema * @param data */ - importSchema(data?: NodeData | NodeData[]) { + importSchema(data?: NodeData | NodeData[]): void { this[nodeChildrenSymbol].import(data); } @@ -187,7 +189,7 @@ export default class NodeChildren { * @param stage * @returns */ - exportSchema(stage: TransformStage = TransformStage.Render) { + exportSchema(stage: TransformStage = TransformStage.Render): any { return this[nodeChildrenSymbol].export(stage); } @@ -198,9 +200,9 @@ export default class NodeChildren { * @param sorter */ mergeChildren( - remover: (node: Node, idx: number) => boolean, - adder: (children: Node[]) => any, - sorter: (firstNode: Node, secondNode: Node) => number, + remover: (node: IPublicModelNode, idx: number) => boolean, + adder: (children: IPublicModelNode[]) => any, + sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number, ) { if (!sorter) { sorter = () => 0; diff --git a/packages/shell/src/node.ts b/packages/shell/src/node.ts index e12551b0c..34faf5f57 100644 --- a/packages/shell/src/node.ts +++ b/packages/shell/src/node.ts @@ -1,9 +1,23 @@ import { DocumentModel as InnerDocumentModel, Node as InnerNode, - getConvertedExtraKey, } from '@alilc/lowcode-designer'; -import { CompositeValue, NodeSchema, TransformStage } from '@alilc/lowcode-types'; +import { + CompositeValue, + NodeSchema, + TransformStage, + IPublicModelNode, + IconType, + I18nData, + IPublicModelComponentMeta, + IPublicModelDocumentModel, + IPublicModelNodeChildren, + IPublicModelProp, + IPublicModelProps, + PropsMap, + PropsList, + IPublicModelSettingTopEntry, +} from '@alilc/lowcode-types'; import Prop from './prop'; import Props from './props'; import DocumentModel from './document-model'; @@ -11,10 +25,11 @@ import NodeChildren from './node-children'; import ComponentMeta from './component-meta'; import SettingTopEntry from './setting-top-entry'; import { documentSymbol, nodeSymbol } from './symbols'; +import { ReactElement } from 'react'; const shellNodeSymbol = Symbol('shellNodeSymbol'); -export default class Node { +export default class Node implements IPublicModelNode { private readonly [documentSymbol]: InnerDocumentModel; private readonly [nodeSymbol]: InnerNode; @@ -27,10 +42,14 @@ export default class Node { this._id = this[nodeSymbol].id; } - static create(node: InnerNode | null | undefined) { - if (!node) return null; + static create(node: InnerNode | null | undefined): IPublicModelNode | null { + if (!node) { + return null; + } // @ts-ignore 直接返回已挂载的 shell node 实例 - if (node[shellNodeSymbol]) return node[shellNodeSymbol]; + if (node[shellNodeSymbol]) { + return (node as any)[shellNodeSymbol]; + } const shellNode = new Node(node); // @ts-ignore 挂载 shell node 实例 node[shellNodeSymbol] = shellNode; @@ -54,70 +73,70 @@ export default class Node { /** * 节点标题 */ - get title() { + get title(): string | I18nData | ReactElement { return this[nodeSymbol].title; } /** * 是否为「容器型」节点 */ - get isContainer() { + get isContainer(): boolean { return this[nodeSymbol].isContainer(); } /** * 是否为根节点 */ - get isRoot() { + get isRoot(): boolean { return this[nodeSymbol].isRoot(); } /** * 是否为空节点(无 children 或者 children 为空) */ - get isEmpty() { + get isEmpty(): boolean { return this[nodeSymbol].isEmpty(); } /** * 是否为 Page 节点 */ - get isPage() { + get isPage(): boolean { return this[nodeSymbol].isPage(); } /** * 是否为 Component 节点 */ - get isComponent() { + get isComponent(): boolean { return this[nodeSymbol].isComponent(); } /** * 是否为「模态框」节点 */ - get isModal() { + get isModal(): boolean { return this[nodeSymbol].isModal(); } /** * 是否为插槽节点 */ - get isSlot() { + get isSlot(): boolean { return this[nodeSymbol].isSlot(); } /** * 是否为父类/分支节点 */ - get isParental() { + get isParental(): boolean { return this[nodeSymbol].isParental(); } /** * 是否为叶子节点 */ - get isLeaf() { + get isLeaf(): boolean { return this[nodeSymbol].isLeaf(); } @@ -129,7 +148,7 @@ export default class Node { /** * 获取当前节点的锁定状态 */ - get isLocked() { + get isLocked(): boolean { return this[nodeSymbol].isLocked; } @@ -143,28 +162,28 @@ export default class Node { /** * 图标 */ - get icon() { + get icon(): IconType { return this[nodeSymbol].icon; } /** * 节点所在树的层级深度,根节点深度为 0 */ - get zLevel() { + get zLevel(): number { return this[nodeSymbol].zLevel; } /** * 节点 componentName */ - get componentName() { + get componentName(): string { return this[nodeSymbol].componentName; } /** * 节点的物料元数据 */ - get componentMeta() { + get componentMeta(): IPublicModelComponentMeta | null { return ComponentMeta.create(this[nodeSymbol].componentMeta); } @@ -172,7 +191,7 @@ export default class Node { * 获取节点所属的文档模型对象 * @returns */ - get document() { + get document(): IPublicModelDocumentModel | null { return DocumentModel.create(this[documentSymbol]); } @@ -180,7 +199,7 @@ export default class Node { * 获取当前节点的前一个兄弟节点 * @returns */ - get prevSibling(): Node | null { + get prevSibling(): IPublicModelNode | null { return Node.create(this[nodeSymbol].prevSibling); } @@ -188,7 +207,7 @@ export default class Node { * 获取当前节点的后一个兄弟节点 * @returns */ - get nextSibling(): Node | null { + get nextSibling(): IPublicModelNode | null { return Node.create(this[nodeSymbol].nextSibling); } @@ -196,7 +215,7 @@ export default class Node { * 获取当前节点的父亲节点 * @returns */ - get parent(): Node | null { + get parent(): IPublicModelNode | null { return Node.create(this[nodeSymbol].parent); } @@ -204,46 +223,46 @@ export default class Node { * 获取当前节点的孩子节点模型 * @returns */ - get children() { + get children(): IPublicModelNodeChildren | null { return NodeChildren.create(this[nodeSymbol].children); } /** * 节点上挂载的插槽节点们 */ - get slots(): Node[] { + get slots(): IPublicModelNode[] { return this[nodeSymbol].slots.map((node: InnerNode) => Node.create(node)!); } /** * 当前节点为插槽节点时,返回节点对应的属性实例 */ - get slotFor() { + get slotFor(): IPublicModelProp | null { return Prop.create(this[nodeSymbol].slotFor); } /** * 返回节点的属性集 */ - get props() { + get props(): IPublicModelProps | null { return Props.create(this[nodeSymbol].props); } /** * 返回节点的属性集 */ - get propsData() { + get propsData(): PropsMap | PropsList | null { return this[nodeSymbol].propsData; } /** - * 获取符合搭建协议-节点 schema 结构 + * 获取符合搭建协议 - 节点 schema 结构 */ - get schema(): any { + get schema(): NodeSchema { return this[nodeSymbol].schema; } - get settingEntry(): any { + get settingEntry(): IPublicModelSettingTopEntry { return SettingTopEntry.create(this[nodeSymbol].settingEntry as any); } @@ -256,6 +275,7 @@ export default class Node { /** * 获取节点实例对应的 dom 节点 + * @deprecated */ getDOMNode() { return this[nodeSymbol].getDOMNode(); @@ -268,10 +288,10 @@ export default class Node { * @param sorter */ mergeChildren( - remover: (node: Node, idx: number) => boolean, - adder: (children: Node[]) => any, - sorter: (firstNode: Node, secondNode: Node) => number, - ) { + remover: (node: IPublicModelNode, idx: number) => boolean, + adder: (children: IPublicModelNode[]) => any, + sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number, + ): any { return this.children?.mergeChildren(remover, adder, sorter); } @@ -279,7 +299,7 @@ export default class Node { * 返回节点的尺寸、位置信息 * @returns */ - getRect() { + getRect(): DOMRect | null { return this[nodeSymbol].getRect(); } @@ -287,7 +307,7 @@ export default class Node { * 是否有挂载插槽节点 * @returns */ - hasSlots() { + hasSlots(): boolean { return this[nodeSymbol].hasSlots(); } @@ -295,7 +315,7 @@ export default class Node { * 是否设定了渲染条件 * @returns */ - hasCondition() { + hasCondition(): boolean { return this[nodeSymbol].hasCondition(); } @@ -303,19 +323,19 @@ export default class Node { * 是否设定了循环数据 * @returns */ - hasLoop() { + hasLoop(): boolean { return this[nodeSymbol].hasLoop(); } - getVisible() { + getVisible(): boolean { return this[nodeSymbol].getVisible(); } - setVisible(flag: boolean) { + setVisible(flag: boolean): void { this[nodeSymbol].setVisible(flag); } - isConditionalVisible() { + isConditionalVisible(): boolean | undefined { return this[nodeSymbol].isConditionalVisible(); } @@ -323,7 +343,7 @@ export default class Node { * 设置节点锁定状态 * @param flag */ - lock(flag?: boolean) { + lock(flag?: boolean): void { this[nodeSymbol].lock(flag); } @@ -334,8 +354,8 @@ export default class Node { return this.props; } - contains(node: Node) { - return this[nodeSymbol].contains(node[nodeSymbol]); + contains(node: IPublicModelNode): boolean { + return this[nodeSymbol].contains((node as any)[nodeSymbol]); } /** @@ -343,7 +363,7 @@ export default class Node { * @param path 属性路径,支持 a / a.b / a.0 等格式 * @returns */ - getProp(path: string, createIfNone = true): Prop | null { + getProp(path: string, createIfNone = true): IPublicModelProp | null { return Prop.create(this[nodeSymbol].getProp(path, createIfNone)); } @@ -363,7 +383,7 @@ export default class Node { * @param createIfNone 当没有属性的时候,是否创建一个属性 * @returns */ - getExtraProp(path: string, createIfNone?: boolean): Prop | null { + getExtraProp(path: string, createIfNone?: boolean): IPublicModelProp | null { return Prop.create(this[nodeSymbol].getExtraProp(path, createIfNone)); } @@ -373,7 +393,7 @@ export default class Node { * @param path 属性路径,支持 a / a.b / a.0 等格式 * @returns */ - getExtraPropValue(path: string) { + getExtraPropValue(path: string): any { return this.getExtraProp(path)?.getValue(); } @@ -383,7 +403,7 @@ export default class Node { * @param value 值 * @returns */ - setPropValue(path: string, value: CompositeValue) { + setPropValue(path: string, value: CompositeValue): void { return this.getProp(path)?.setValue(value); } @@ -393,7 +413,7 @@ export default class Node { * @param value 值 * @returns */ - setExtraPropValue(path: string, value: CompositeValue) { + setExtraPropValue(path: string, value: CompositeValue): void { return this.getExtraProp(path)?.setValue(value); } @@ -401,7 +421,7 @@ export default class Node { * 导入节点数据 * @param data */ - importSchema(data: NodeSchema) { + importSchema(data: NodeSchema): void { this[nodeSymbol].import(data); } @@ -411,7 +431,7 @@ export default class Node { * @param options * @returns */ - exportSchema(stage: TransformStage = TransformStage.Render, options?: any) { + exportSchema(stage: TransformStage = TransformStage.Render, options?: any): NodeSchema { return this[nodeSymbol].export(stage, options); } @@ -421,8 +441,16 @@ export default class Node { * @param ref * @param useMutator */ - insertBefore(node: Node, ref?: Node | undefined, useMutator?: boolean) { - this[nodeSymbol].insertBefore(node[nodeSymbol] || node, ref?.[nodeSymbol], useMutator); + insertBefore( + node: IPublicModelNode, + ref?: IPublicModelNode | undefined, + useMutator?: boolean, + ): void { + this[nodeSymbol].insertBefore( + (node as any)[nodeSymbol] || node, + (ref as any)?.[nodeSymbol], + useMutator, + ); } /** @@ -431,8 +459,16 @@ export default class Node { * @param ref * @param useMutator */ - insertAfter(node: Node, ref?: Node | undefined, useMutator?: boolean) { - this[nodeSymbol].insertAfter(node[nodeSymbol] || node, ref?.[nodeSymbol], useMutator); + insertAfter( + node: IPublicModelNode, + ref?: IPublicModelNode | undefined, + useMutator?: boolean, + ): void { + this[nodeSymbol].insertAfter( + (node as any)[nodeSymbol] || node, + (ref as any)?.[nodeSymbol], + useMutator, + ); } /** @@ -441,22 +477,22 @@ export default class Node { * @param data 用作替换的节点对象或者节点描述 * @returns */ - replaceChild(node: Node, data: any) { - return Node.create(this[nodeSymbol].replaceChild(node[nodeSymbol], data)); + replaceChild(node: IPublicModelNode, data: any): IPublicModelNode | null { + return Node.create(this[nodeSymbol].replaceChild((node as any)[nodeSymbol], data)); } /** * 将当前节点替换成指定节点描述 * @param schema */ - replaceWith(schema: NodeSchema) { + replaceWith(schema: NodeSchema): any { this[nodeSymbol].replaceWith(schema); } /** * 选中当前节点实例 */ - select() { + select(): void { this[nodeSymbol].select(); } @@ -464,14 +500,14 @@ export default class Node { * 设置悬停态 * @param flag */ - hover(flag = true) { + hover(flag = true): void { this[nodeSymbol].hover(flag); } /** * 删除当前节点实例 */ - remove() { + remove(): void { this[nodeSymbol].remove(); } /** diff --git a/packages/shell/src/project.ts b/packages/shell/src/project.ts index 39a029c91..4b0cd773c 100644 --- a/packages/shell/src/project.ts +++ b/packages/shell/src/project.ts @@ -1,18 +1,26 @@ import { BuiltinSimulatorHost, Project as InnerProject, - PropsReducer as PropsTransducer, TransformStage, } from '@alilc/lowcode-designer'; -import { RootSchema, ProjectSchema, IEditor } from '@alilc/lowcode-types'; import { globalContext } from '@alilc/lowcode-editor-core'; -import DocumentModel, { Events } from './document-model'; +import { + RootSchema, + ProjectSchema, + IEditor, + IPublicApiProject, + IPublicApiSimulatorHost, + IPublicModelDocumentModel, + PropsTransducer, +} from '@alilc/lowcode-types'; + + +import DocumentModel from './document-model'; import SimulatorHost from './simulator-host'; import { editorSymbol, projectSymbol, simulatorHostSymbol, simulatorRendererSymbol, documentSymbol } from './symbols'; const innerProjectSymbol = Symbol('project'); - -export default class Project { +export default class Project implements IPublicApiProject { private readonly [editorSymbol]: IEditor; private readonly [innerProjectSymbol]: InnerProject; private [simulatorHostSymbol]: BuiltinSimulatorHost; @@ -42,7 +50,7 @@ export default class Project { * 获取当前的 document * @returns */ - get currentDocument(): DocumentModel | null { + get currentDocument(): IPublicModelDocumentModel | null { return this.getCurrentDocument(); } @@ -50,14 +58,14 @@ export default class Project { * 获取当前 project 下所有 documents * @returns */ - get documents(): DocumentModel[] { + get documents(): IPublicModelDocumentModel[] { return this[projectSymbol].documents.map((doc) => DocumentModel.create(doc)!); } /** * 获取模拟器的 host */ - get simulatorHost() { + get simulatorHost(): IPublicApiSimulatorHost | null { return SimulatorHost.create(this[projectSymbol].simulator as any || this[simulatorHostSymbol]); } @@ -84,7 +92,7 @@ export default class Project { * @param data * @returns */ - createDocument(data?: RootSchema): DocumentModel | null { + createDocument(data?: RootSchema): IPublicModelDocumentModel | null { const doc = this[projectSymbol].createDocument(data); return DocumentModel.create(doc); } @@ -93,8 +101,8 @@ export default class Project { * 删除一个 document * @param doc */ - removeDocument(doc: DocumentModel) { - this[projectSymbol].removeDocument(doc[documentSymbol]); + removeDocument(doc: IPublicModelDocumentModel) { + this[projectSymbol].removeDocument((doc as any)[documentSymbol]); } /** @@ -102,7 +110,7 @@ export default class Project { * @param fileName * @returns */ - getDocumentByFileName(fileName: string): DocumentModel | null { + getDocumentByFileName(fileName: string): IPublicModelDocumentModel | null { return DocumentModel.create(this[projectSymbol].getDocumentByFileName(fileName)); } @@ -111,7 +119,7 @@ export default class Project { * @param id * @returns */ - getDocumentById(id: string): DocumentModel | null { + getDocumentById(id: string): IPublicModelDocumentModel | null { return DocumentModel.create(this[projectSymbol].getDocument(id)); } @@ -127,7 +135,7 @@ export default class Project { * 导入 project * @param schema 待导入的 project 数据 */ - importSchema(schema?: ProjectSchema) { + importSchema(schema?: ProjectSchema): void { this[projectSymbol].load(schema, true); // this[editorSymbol].emit(Events.IMPORT_SCHEMA, schema); } @@ -136,7 +144,7 @@ export default class Project { * 获取当前的 document * @returns */ - getCurrentDocument(): DocumentModel | null { + getCurrentDocument(): IPublicModelDocumentModel | null { return DocumentModel.create(this[projectSymbol].currentDocument); } @@ -145,7 +153,7 @@ export default class Project { * @param transducer * @param stage */ - addPropsTransducer(transducer: PropsTransducer, stage: TransformStage) { + addPropsTransducer(transducer: PropsTransducer, stage: TransformStage): void { this[projectSymbol].designer.addPropsReducer(transducer, stage); } @@ -154,14 +162,14 @@ export default class Project { * @param fn * @returns */ - onRemoveDocument(fn: (data: { id: string}) => void) { + onRemoveDocument(fn: (data: { id: string}) => void): any { return this[editorSymbol].on('designer.document.remove', (data: { id: string }) => fn(data)); } /** * 当前 project 内的 document 变更事件 */ - onChangeDocument(fn: (doc: DocumentModel) => void) { + onChangeDocument(fn: (doc: IPublicModelDocumentModel) => void) { const offFn = this[projectSymbol].onCurrentDocumentChange((originalDoc) => { fn(DocumentModel.create(originalDoc)!); }); @@ -174,7 +182,7 @@ export default class Project { /** * 当前 project 的模拟器 ready 事件 */ - onSimulatorHostReady(fn: (host: SimulatorHost) => void) { + onSimulatorHostReady(fn: (host: IPublicApiSimulatorHost) => void) { const offFn = this[projectSymbol].onSimulatorReady((simulator: BuiltinSimulatorHost) => { this[simulatorHostSymbol] = simulator; fn(SimulatorHost.create(simulator)!); diff --git a/packages/shell/src/prop.ts b/packages/shell/src/prop.ts index b386d0593..8cb6c9cda 100644 --- a/packages/shell/src/prop.ts +++ b/packages/shell/src/prop.ts @@ -1,65 +1,69 @@ import { Prop as InnerProp } from '@alilc/lowcode-designer'; -import { CompositeValue, TransformStage } from '@alilc/lowcode-types'; +import { CompositeValue, TransformStage, IPublicModelProp, IPublicModelNode } from '@alilc/lowcode-types'; import { propSymbol } from './symbols'; import Node from './node'; -export default class Prop { +export default class Prop implements IPublicModelProp { private readonly [propSymbol]: InnerProp; constructor(prop: InnerProp) { this[propSymbol] = prop; } - static create(prop: InnerProp | undefined | null) { - if (!prop) return null; + static create(prop: InnerProp | undefined | null): IPublicModelProp | null { + if (!prop) { + return null; + } return new Prop(prop); } /** * id */ - get id() { + get id(): string { return this[propSymbol].id; } /** * key 值 */ - get key() { + get key(): string | number | undefined { return this[propSymbol].key; } /** * 返回当前 prop 的路径 */ - get path() { + get path(): any[] { return this[propSymbol].path; } /** * 返回所属的节点实例 */ - get node(): Node | null { + get node(): IPublicModelNode | null { return Node.create(this[propSymbol].getNode()); } /** * return the slot node (only if the current prop represents a slot) */ - get slotNode(): Node | null { + get slotNode(): IPublicModelNode | null { return Node.create(this[propSymbol].slotNode); } /** * judge if it is a prop or not */ - get isProp() { return true; } + get isProp(): boolean { + return true; + } /** * 设置值 * @param val */ - setValue(val: CompositeValue) { + setValue(val: CompositeValue): void { this[propSymbol].setValue(val); } @@ -67,14 +71,14 @@ export default class Prop { * 获取值 * @returns */ - getValue() { + getValue(): any { return this[propSymbol].getValue(); } /** * 移除值 */ - remove() { + remove(): void { this[propSymbol].remove(); } diff --git a/packages/shell/src/props.ts b/packages/shell/src/props.ts index 293fa60df..10bcfaba2 100644 --- a/packages/shell/src/props.ts +++ b/packages/shell/src/props.ts @@ -1,39 +1,41 @@ import { Props as InnerProps, getConvertedExtraKey } from '@alilc/lowcode-designer'; -import { CompositeValue, TransformStage } from '@alilc/lowcode-types'; +import { CompositeValue, IPublicModelProps, IPublicModelNode, IPublicModelProp } from '@alilc/lowcode-types'; import { propsSymbol } from './symbols'; import Node from './node'; import Prop from './prop'; -export default class Props { +export default class Props implements IPublicModelProps { private readonly [propsSymbol]: InnerProps; constructor(props: InnerProps) { this[propsSymbol] = props; } - static create(props: InnerProps | undefined | null) { - if (!props) return null; + static create(props: InnerProps | undefined | null): IPublicModelProps | null { + if (!props) { + return null; + } return new Props(props); } /** * id */ - get id() { + get id(): string { return this[propsSymbol].id; } /** * 返回当前 props 的路径 */ - get path() { + get path(): any[] { return this[propsSymbol].path; } /** * 返回所属的 node 实例 */ - get node(): Node | null { + get node(): IPublicModelNode | null { return Node.create(this[propsSymbol].getNode()); } @@ -42,7 +44,7 @@ export default class Props { * @param path 属性路径,支持 a / a.b / a.0 等格式 * @returns */ - getProp(path: string): Prop | null { + getProp(path: string): IPublicModelProp | null { return Prop.create(this[propsSymbol].getProp(path)); } @@ -51,7 +53,7 @@ export default class Props { * @param path 属性路径,支持 a / a.b / a.0 等格式 * @returns */ - getPropValue(path: string) { + getPropValue(path: string): any { return this.getProp(path)?.getValue(); } @@ -61,7 +63,7 @@ export default class Props { * @param path 属性路径,支持 a / a.b / a.0 等格式 * @returns */ - getExtraProp(path: string): Prop | null { + getExtraProp(path: string): IPublicModelProp | null { return Prop.create(this[propsSymbol].getProp(getConvertedExtraKey(path))); } @@ -71,7 +73,7 @@ export default class Props { * @param path 属性路径,支持 a / a.b / a.0 等格式 * @returns */ - getExtraPropValue(path: string) { + getExtraPropValue(path: string): any { return this.getExtraProp(path)?.getValue(); } @@ -81,7 +83,7 @@ export default class Props { * @param value 值 * @returns */ - setPropValue(path: string, value: CompositeValue) { + setPropValue(path: string, value: CompositeValue): void { return this.getProp(path)?.setValue(value); } @@ -91,7 +93,7 @@ export default class Props { * @param value 值 * @returns */ - setExtraPropValue(path: string, value: CompositeValue) { + setExtraPropValue(path: string, value: CompositeValue): void { return this.getExtraProp(path)?.setValue(value); } @@ -100,7 +102,7 @@ export default class Props { * @param key * @returns */ - has(key: string) { + has(key: string): boolean { return this[propsSymbol].has(key); } @@ -110,7 +112,7 @@ export default class Props { * @param key * @returns */ - add(value: CompositeValue, key?: string | number | undefined) { + add(value: CompositeValue, key?: string | number | undefined): any { return this[propsSymbol].add(value, key); } } \ No newline at end of file diff --git a/packages/shell/src/selection.ts b/packages/shell/src/selection.ts index b5b9e7a16..43d2c3ccc 100644 --- a/packages/shell/src/selection.ts +++ b/packages/shell/src/selection.ts @@ -4,14 +4,13 @@ import { Selection as InnerSelection, } from '@alilc/lowcode-designer'; import Node from './node'; -import { documentSymbol, selectionSymbol } from './symbols'; +import { selectionSymbol } from './symbols'; +import { IPublicModelSelection, IPublicModelNode } from '@alilc/lowcode-types'; -export default class Selection { - private readonly [documentSymbol]: InnerDocumentModel; +export default class Selection implements IPublicModelSelection { private readonly [selectionSymbol]: InnerSelection; constructor(document: InnerDocumentModel) { - this[documentSymbol] = document; this[selectionSymbol] = document.selection; } @@ -25,15 +24,16 @@ export default class Selection { /** * return selected Node instance */ - get node(): Node { - return this.getNodes()[0]; + get node(): IPublicModelNode | null { + const nodes = this.getNodes(); + return nodes && nodes.length > 0 ? nodes[0] : null; } /** * 选中指定节点(覆盖方式) * @param id */ - select(id: string) { + select(id: string): void { this[selectionSymbol].select(id); } @@ -41,7 +41,7 @@ export default class Selection { * 批量选中指定节点们 * @param ids */ - selectAll(ids: string[]) { + selectAll(ids: string[]): void { this[selectionSymbol].selectAll(ids); } @@ -49,14 +49,14 @@ export default class Selection { * 移除选中的指定节点 * @param id */ - remove(id: string) { + remove(id: string): void { this[selectionSymbol].remove(id); } /** * 清除所有选中节点 */ - clear() { + clear(): void { this[selectionSymbol].clear(); } @@ -65,7 +65,7 @@ export default class Selection { * @param id * @returns */ - has(id: string) { + has(id: string): boolean { return this[selectionSymbol].has(id); } @@ -73,7 +73,7 @@ export default class Selection { * 选中指定节点(增量方式) * @param id */ - add(id: string) { + add(id: string): void { this[selectionSymbol].add(id); } @@ -81,7 +81,7 @@ export default class Selection { * 获取选中的节点实例 * @returns */ - getNodes(): Node[] { + getNodes(): Array { return this[selectionSymbol].getNodes().map((node: InnerNode) => Node.create(node)); } @@ -92,7 +92,7 @@ export default class Selection { * getTopNodes() will return [A, B], subA will be removed * @returns */ - getTopNodes(): Node[] { + getTopNodes(): Array { return this[selectionSymbol].getTopNodes().map((node: InnerNode) => Node.create(node)); } } diff --git a/packages/shell/src/setting-prop-entry.ts b/packages/shell/src/setting-prop-entry.ts index 2c2bb6ce6..ad07aa963 100644 --- a/packages/shell/src/setting-prop-entry.ts +++ b/packages/shell/src/setting-prop-entry.ts @@ -1,106 +1,118 @@ -import { SettingField, ISetValueOptions } from '@alilc/lowcode-designer'; -import { CompositeValue, FieldConfig, CustomView, isCustomView } from '@alilc/lowcode-types'; +import { SettingField, SettingEntry } from '@alilc/lowcode-designer'; +import { + CompositeValue, + FieldConfig, + CustomView, + IPublicModelSettingPropEntry, + SetterType, + FieldExtraProps, + IPublicModelSettingTopEntry, + IPublicModelNode, + IPublicModelComponentMeta, + ISetValueOptions, +} from '@alilc/lowcode-types'; import { settingPropEntrySymbol } from './symbols'; import Node from './node'; import SettingTopEntry from './setting-top-entry'; import ComponentMeta from './component-meta'; +import { isCustomView } from '@alilc/lowcode-utils'; -export default class SettingPropEntry { +export default class SettingPropEntry implements IPublicModelSettingPropEntry { private readonly [settingPropEntrySymbol]: SettingField; constructor(prop: SettingField) { this[settingPropEntrySymbol] = prop; } - static create(prop: SettingField) { + static create(prop: SettingField): IPublicModelSettingPropEntry { return new SettingPropEntry(prop); } /** * 获取设置属性的 isGroup */ - get isGroup() { + get isGroup(): boolean { return this[settingPropEntrySymbol].isGroup; } /** * 获取设置属性的 id */ - get id() { + get id(): string { return this[settingPropEntrySymbol].id; } /** * 获取设置属性的 name */ - get name() { + get name(): string | number { return this[settingPropEntrySymbol].name; } /** * 获取设置属性的 key */ - get key() { + get key(): string | number { return this[settingPropEntrySymbol].getKey(); } /** * 获取设置属性的 path */ - get path() { + get path(): any[] { return this[settingPropEntrySymbol].path; } /** * 获取设置属性的 title */ - get title() { + get title(): any { return this[settingPropEntrySymbol].title; } /** * 获取设置属性的 setter */ - get setter() { + get setter(): SetterType | null { return this[settingPropEntrySymbol].setter; } /** * 获取设置属性的 expanded */ - get expanded() { + get expanded(): boolean { return this[settingPropEntrySymbol].expanded; } /** * 获取设置属性的 extraProps */ - get extraProps() { + get extraProps(): FieldExtraProps { return this[settingPropEntrySymbol].extraProps; } - get props() { + get props(): IPublicModelSettingTopEntry { return SettingTopEntry.create(this[settingPropEntrySymbol].props); } /** * 获取设置属性对应的节点实例 */ - get node(): Node | null { + get node(): IPublicModelNode | null { return Node.create(this[settingPropEntrySymbol].getNode()); } /** * 获取设置属性的父设置属性 */ - get parent(): SettingPropEntry { + get parent(): IPublicModelSettingPropEntry { return SettingPropEntry.create(this[settingPropEntrySymbol].parent as any); } /** * 获取顶级设置属性 */ - get top(): SettingTopEntry { + get top(): IPublicModelSettingTopEntry { return SettingTopEntry.create(this[settingPropEntrySymbol].top); } @@ -114,14 +126,14 @@ export default class SettingPropEntry { /** * componentMeta */ - get componentMeta(): ComponentMeta | null { + get componentMeta(): IPublicModelComponentMeta | null { return ComponentMeta.create(this[settingPropEntrySymbol].componentMeta); } /** * 获取设置属性的 items */ - get items(): Array { + get items(): Array { return this[settingPropEntrySymbol].items?.map((item) => { if (isCustomView(item)) { return item; @@ -134,7 +146,7 @@ export default class SettingPropEntry { * 设置 key 值 * @param key */ - setKey(key: string | number) { + setKey(key: string | number): void { this[settingPropEntrySymbol].setKey(key); } @@ -156,7 +168,7 @@ export default class SettingPropEntry { * 设置值 * @param val 值 */ - setValue(val: CompositeValue, extraOptions?: ISetValueOptions) { + setValue(val: CompositeValue, extraOptions?: ISetValueOptions): void { this[settingPropEntrySymbol].setValue(val, false, false, extraOptions); } @@ -165,7 +177,7 @@ export default class SettingPropEntry { * @param propName 子属性名 * @param value 值 */ - setPropValue(propName: string | number, value: any) { + setPropValue(propName: string | number, value: any): void { this[settingPropEntrySymbol].setPropValue(propName, value); } @@ -173,7 +185,7 @@ export default class SettingPropEntry { * 清空指定属性值 * @param propName */ - clearPropValue(propName: string | number) { + clearPropValue(propName: string | number): void { this[settingPropEntrySymbol].clearPropValue(propName); } @@ -181,7 +193,7 @@ export default class SettingPropEntry { * 获取配置的默认值 * @returns */ - getDefaultValue() { + getDefaultValue(): any { return this[settingPropEntrySymbol].getDefaultValue(); } @@ -189,7 +201,7 @@ export default class SettingPropEntry { * 获取值 * @returns */ - getValue() { + getValue(): any { return this[settingPropEntrySymbol].getValue(); } @@ -198,21 +210,21 @@ export default class SettingPropEntry { * @param propName 子属性名 * @returns */ - getPropValue(propName: string | number) { + getPropValue(propName: string | number): any { return this[settingPropEntrySymbol].getPropValue(propName); } /** * 获取顶层附属属性值 */ - getExtraPropValue(propName: string) { + getExtraPropValue(propName: string): any { return this[settingPropEntrySymbol].getExtraPropValue(propName); } /** * 设置顶层附属属性值 */ - setExtraPropValue(propName: string, value: any) { + setExtraPropValue(propName: string, value: any): void { this[settingPropEntrySymbol].setExtraPropValue(propName, value); } @@ -220,7 +232,7 @@ export default class SettingPropEntry { * 获取设置属性集 * @returns */ - getProps() { + getProps(): IPublicModelSettingTopEntry { return SettingTopEntry.create(this[settingPropEntrySymbol].getProps() as SettingEntry) as any; } @@ -228,7 +240,7 @@ export default class SettingPropEntry { * 是否绑定了变量 * @returns */ - isUseVariable() { + isUseVariable(): boolean { return this[settingPropEntrySymbol].isUseVariable(); } @@ -236,7 +248,7 @@ export default class SettingPropEntry { * 设置绑定变量 * @param flag */ - setUseVariable(flag: boolean) { + setUseVariable(flag: boolean): void { this[settingPropEntrySymbol].setUseVariable(flag); } @@ -245,7 +257,7 @@ export default class SettingPropEntry { * @param config * @returns */ - createField(config: FieldConfig) { + createField(config: FieldConfig): IPublicModelSettingPropEntry { return SettingPropEntry.create(this[settingPropEntrySymbol].createField(config)); } @@ -253,21 +265,21 @@ export default class SettingPropEntry { * 获取值,当为变量时,返回 mock * @returns */ - getMockOrValue() { + getMockOrValue(): any { return this[settingPropEntrySymbol].getMockOrValue(); } /** * 销毁当前 field 实例 */ - purge() { + purge(): void { this[settingPropEntrySymbol].purge(); } /** * 移除当前 field 实例 */ - remove() { + remove(): void { this[settingPropEntrySymbol].remove(); } @@ -276,7 +288,7 @@ export default class SettingPropEntry { * @param action * @returns */ - onEffect(action: () => void) { + onEffect(action: () => void): () => void { return this[settingPropEntrySymbol].onEffect(action); } diff --git a/packages/shell/src/setting-top-entry.ts b/packages/shell/src/setting-top-entry.ts index 6f5d888d4..d7693799c 100644 --- a/packages/shell/src/setting-top-entry.ts +++ b/packages/shell/src/setting-top-entry.ts @@ -2,22 +2,23 @@ import { SettingEntry } from '@alilc/lowcode-designer'; import { settingTopEntrySymbol } from './symbols'; import Node from './node'; import SettingPropEntry from './setting-prop-entry'; +import { IPublicModelSettingTopEntry, IPublicModelNode, IPublicModelSettingPropEntry } from '@alilc/lowcode-types'; -export default class SettingTopEntry { +export default class SettingTopEntry implements IPublicModelSettingTopEntry { private readonly [settingTopEntrySymbol]: SettingEntry; constructor(prop: SettingEntry) { this[settingTopEntrySymbol] = prop; } - static create(prop: SettingEntry) { + static create(prop: SettingEntry): IPublicModelSettingTopEntry { return new SettingTopEntry(prop); } /** * 返回所属的节点实例 */ - get node(): Node | null { + get node(): IPublicModelNode | null { return Node.create(this[settingTopEntrySymbol].getNode()); } @@ -26,7 +27,7 @@ export default class SettingTopEntry { * @param propName * @returns */ - get(propName: string | number) { + get(propName: string | number): IPublicModelSettingPropEntry { return SettingPropEntry.create(this[settingTopEntrySymbol].get(propName) as any); } @@ -42,7 +43,7 @@ export default class SettingTopEntry { * @param propName * @returns */ - getPropValue(propName: string | number) { + getPropValue(propName: string | number): any { return this[settingTopEntrySymbol].getPropValue(propName); } @@ -51,7 +52,7 @@ export default class SettingTopEntry { * @param propName * @param value */ - setPropValue(propName: string | number, value: any) { + setPropValue(propName: string | number, value: any): void { this[settingTopEntrySymbol].setPropValue(propName, value); } } \ No newline at end of file diff --git a/packages/shell/src/simulator-host.ts b/packages/shell/src/simulator-host.ts index 077564550..f9ebc36b5 100644 --- a/packages/shell/src/simulator-host.ts +++ b/packages/shell/src/simulator-host.ts @@ -2,16 +2,17 @@ import { BuiltinSimulatorHost, } from '@alilc/lowcode-designer'; import { simulatorHostSymbol, nodeSymbol } from './symbols'; +import { IPublicApiSimulatorHost, IPublicModelNode } from '@alilc/lowcode-types'; import type Node from './node'; -export default class SimulatorHost { +export default class SimulatorHost implements IPublicApiSimulatorHost { private readonly [simulatorHostSymbol]: BuiltinSimulatorHost; constructor(simulator: BuiltinSimulatorHost) { this[simulatorHostSymbol] = simulator; } - static create(host: BuiltinSimulatorHost) { + static create(host: BuiltinSimulatorHost): IPublicApiSimulatorHost | null { if (!host) return null; return new SimulatorHost(host); } @@ -19,18 +20,18 @@ export default class SimulatorHost { /** * 获取 contentWindow */ - get contentWindow() { + get contentWindow(): Window | undefined { return this[simulatorHostSymbol].contentWindow; } /** * 获取 contentDocument */ - get contentDocument() { + get contentDocument(): Document | undefined { return this[simulatorHostSymbol].contentDocument; } - get renderer() { + get renderer(): any { return this[simulatorHostSymbol].renderer; } @@ -39,7 +40,7 @@ export default class SimulatorHost { * @param key * @param value */ - set(key: string, value: any) { + set(key: string, value: any): void { this[simulatorHostSymbol].set(key, value); } @@ -48,7 +49,7 @@ export default class SimulatorHost { * @param key * @returns */ - get(key: string) { + get(key: string): any { return this[simulatorHostSymbol].get(key); } @@ -56,14 +57,14 @@ export default class SimulatorHost { * scroll to specific node * @param node */ - scrollToNode(node: Node) { - this[simulatorHostSymbol].scrollToNode(node[nodeSymbol]); + scrollToNode(node: IPublicModelNode): void { + this[simulatorHostSymbol].scrollToNode((node as any)[nodeSymbol]); } /** * 刷新渲染画布 */ - rerender() { + rerender(): void { this[simulatorHostSymbol].rerender(); } } diff --git a/packages/shell/src/skeleton.ts b/packages/shell/src/skeleton.ts index a83b85cad..2344407d9 100644 --- a/packages/shell/src/skeleton.ts +++ b/packages/shell/src/skeleton.ts @@ -1,15 +1,13 @@ import { globalContext } from '@alilc/lowcode-editor-core'; import { Skeleton as InnerSkeleton, - IWidgetBaseConfig, - IWidgetConfigArea, SkeletonEvents, } from '@alilc/lowcode-editor-skeleton'; import { skeletonSymbol } from './symbols'; +import { IPublicApiSkeleton, IWidgetBaseConfig, IWidgetConfigArea } from '@alilc/lowcode-types'; const innerSkeletonSymbol = Symbol('skeleton'); - -export default class Skeleton { +export default class Skeleton implements IPublicApiSkeleton { private readonly [innerSkeletonSymbol]: InnerSkeleton; get [skeletonSymbol]() { @@ -43,11 +41,13 @@ export default class Skeleton { * @param config * @returns */ - remove(config: IWidgetBaseConfig) { + remove(config: IWidgetBaseConfig): number | undefined { const { area, name } = config; const skeleton = this[skeletonSymbol]; - if (!normalizeArea(area)) return; - skeleton[normalizeArea(area)!].container.remove(name); + if (!normalizeArea(area)) { + return; + } + skeleton[normalizeArea(area)!].container?.remove(name); } /** diff --git a/packages/types/package.json b/packages/types/package.json index 39d3e7c49..c61ecded9 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -20,7 +20,7 @@ "@alib/build-scripts": "^0.1.18", "@types/node": "^13.7.1", "@types/react": "^16", - "build-plugin-component": "^0.2.10" + "build-plugin-component": "^1.0.0" }, "publishConfig": { "access": "public", diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index 65129532a..581af679b 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -62,7 +62,7 @@ export interface AssetsJson { */ version: string; /** - * 大包列表,external与package的概念相似,融合在一起 + * 大包列表,external 与 package 的概念相似,融合在一起 */ packages?: Package[]; /** diff --git a/packages/types/src/deprecated/index.ts b/packages/types/src/deprecated/index.ts new file mode 100644 index 000000000..7e65173c0 --- /dev/null +++ b/packages/types/src/deprecated/index.ts @@ -0,0 +1,18 @@ +export * from './isActionContentObject'; +export * from './isCustomView'; +export * from './isDOMText'; +export * from './isDynamicSetter'; +export * from './isI18nData'; +export * from './isJSBlock'; +export * from './isJSExpression'; +export * from './isJSFunction'; +export * from './isJSSlot'; +export * from './isLowCodeComponentType'; +export * from './isNodeSchema'; +export * from './isPlainObject'; +export * from './isProCodeComponentType'; +export * from './isProjectSchema'; +export * from './isReactClass'; +export * from './isReactComponent'; +export * from './isSetterConfig'; +export * from './isTitleConfig'; \ No newline at end of file diff --git a/packages/types/src/deprecated/isActionContentObject.ts b/packages/types/src/deprecated/isActionContentObject.ts new file mode 100644 index 000000000..f56ec1128 --- /dev/null +++ b/packages/types/src/deprecated/isActionContentObject.ts @@ -0,0 +1,8 @@ +import { ActionContentObject } from '../metadata'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isActionContentObject(obj: any): obj is ActionContentObject { + return obj && typeof obj === 'object'; +} diff --git a/packages/types/src/deprecated/isCustomView.ts b/packages/types/src/deprecated/isCustomView.ts new file mode 100644 index 000000000..84ac84c93 --- /dev/null +++ b/packages/types/src/deprecated/isCustomView.ts @@ -0,0 +1,10 @@ +import { isValidElement } from 'react'; +import { isReactComponent } from './isReactComponent'; +import { CustomView } from '../setter-config'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isCustomView(obj: any): obj is CustomView { + return obj && (isValidElement(obj) || isReactComponent(obj)); +} diff --git a/packages/types/src/deprecated/isDOMText.ts b/packages/types/src/deprecated/isDOMText.ts new file mode 100644 index 000000000..d590d5aa3 --- /dev/null +++ b/packages/types/src/deprecated/isDOMText.ts @@ -0,0 +1,8 @@ +import { DOMText } from '../schema'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isDOMText(data: any): data is DOMText { + return typeof data === 'string'; +} diff --git a/packages/types/src/deprecated/isDynamicSetter.ts b/packages/types/src/deprecated/isDynamicSetter.ts new file mode 100644 index 000000000..7bfebd9a3 --- /dev/null +++ b/packages/types/src/deprecated/isDynamicSetter.ts @@ -0,0 +1,9 @@ +import { isReactClass } from './isReactClass'; +import { DynamicSetter } from '../setter-config'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isDynamicSetter(obj: any): obj is DynamicSetter { + return obj && typeof obj === 'function' && !isReactClass(obj); +} diff --git a/packages/types/src/deprecated/isI18nData.ts b/packages/types/src/deprecated/isI18nData.ts new file mode 100644 index 000000000..1194b338a --- /dev/null +++ b/packages/types/src/deprecated/isI18nData.ts @@ -0,0 +1,8 @@ +import { I18nData } from '../i18n'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isI18nData(obj: any): obj is I18nData { + return obj && obj.type === 'i18n'; +} diff --git a/packages/types/src/deprecated/isJSBlock.ts b/packages/types/src/deprecated/isJSBlock.ts new file mode 100644 index 000000000..28878eb6a --- /dev/null +++ b/packages/types/src/deprecated/isJSBlock.ts @@ -0,0 +1,8 @@ +import { JSBlock } from '../value-type'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isJSBlock(data: any): data is JSBlock { + return data && data.type === 'JSBlock'; +} diff --git a/packages/types/src/deprecated/isJSExpression.ts b/packages/types/src/deprecated/isJSExpression.ts new file mode 100644 index 000000000..1e58c6538 --- /dev/null +++ b/packages/types/src/deprecated/isJSExpression.ts @@ -0,0 +1,8 @@ +import { JSExpression } from '../value-type'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isJSExpression(data: any): data is JSExpression { + return data && data.type === 'JSExpression' && data.extType !== 'function'; +} diff --git a/packages/types/src/deprecated/isJSFunction.ts b/packages/types/src/deprecated/isJSFunction.ts new file mode 100644 index 000000000..8a98a8c5c --- /dev/null +++ b/packages/types/src/deprecated/isJSFunction.ts @@ -0,0 +1,8 @@ +import { JSFunction } from '../value-type'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isJSFunction(x: any): x is JSFunction { + return typeof x === 'object' && x && x.type === 'JSFunction'; +} diff --git a/packages/types/src/deprecated/isJSSlot.ts b/packages/types/src/deprecated/isJSSlot.ts new file mode 100644 index 000000000..e2096034a --- /dev/null +++ b/packages/types/src/deprecated/isJSSlot.ts @@ -0,0 +1,8 @@ +import { JSSlot } from '../value-type'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isJSSlot(data: any): data is JSSlot { + return data && data.type === 'JSSlot'; +} diff --git a/packages/types/src/deprecated/isLowCodeComponentType.ts b/packages/types/src/deprecated/isLowCodeComponentType.ts new file mode 100644 index 000000000..1ba2689ca --- /dev/null +++ b/packages/types/src/deprecated/isLowCodeComponentType.ts @@ -0,0 +1,9 @@ +import { isProCodeComponentType } from './isProCodeComponentType'; +import { ComponentMap, LowCodeComponentType } from '../npm'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isLowCodeComponentType(desc: ComponentMap): desc is LowCodeComponentType { + return !isProCodeComponentType(desc); +} diff --git a/packages/types/src/deprecated/isNodeSchema.ts b/packages/types/src/deprecated/isNodeSchema.ts new file mode 100644 index 000000000..b3daf4e46 --- /dev/null +++ b/packages/types/src/deprecated/isNodeSchema.ts @@ -0,0 +1,8 @@ +import { NodeSchema } from '../schema'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isNodeSchema(data: any): data is NodeSchema { + return data && data.componentName; +} diff --git a/packages/types/src/deprecated/isPlainObject.ts b/packages/types/src/deprecated/isPlainObject.ts new file mode 100644 index 000000000..549f49736 --- /dev/null +++ b/packages/types/src/deprecated/isPlainObject.ts @@ -0,0 +1,10 @@ +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isPlainObject(value: any): value is Record { + if (typeof value !== 'object') { + return false; + } + const proto = Object.getPrototypeOf(value); + return proto === Object.prototype || proto === null || Object.getPrototypeOf(proto) === null; +} diff --git a/packages/types/src/deprecated/isProCodeComponentType.ts b/packages/types/src/deprecated/isProCodeComponentType.ts new file mode 100644 index 000000000..071a9dc7e --- /dev/null +++ b/packages/types/src/deprecated/isProCodeComponentType.ts @@ -0,0 +1,8 @@ +import { ComponentMap, ProCodeComponentType } from '../npm'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isProCodeComponentType(desc: ComponentMap): desc is ProCodeComponentType { + return 'package' in desc; +} diff --git a/packages/types/src/deprecated/isProjectSchema.ts b/packages/types/src/deprecated/isProjectSchema.ts new file mode 100644 index 000000000..92e65041c --- /dev/null +++ b/packages/types/src/deprecated/isProjectSchema.ts @@ -0,0 +1,8 @@ +import { ProjectSchema } from '../schema'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isProjectSchema(data: any): data is ProjectSchema { + return data && data.componentsTree; +} diff --git a/packages/types/src/deprecated/isReactClass.ts b/packages/types/src/deprecated/isReactClass.ts new file mode 100644 index 000000000..846c522d7 --- /dev/null +++ b/packages/types/src/deprecated/isReactClass.ts @@ -0,0 +1,8 @@ +import { ComponentClass, Component } from 'react'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isReactClass(obj: any): obj is ComponentClass { + return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component); +} diff --git a/packages/types/src/deprecated/isReactComponent.ts b/packages/types/src/deprecated/isReactComponent.ts new file mode 100644 index 000000000..1ed04427f --- /dev/null +++ b/packages/types/src/deprecated/isReactComponent.ts @@ -0,0 +1,9 @@ +import { ComponentType } from 'react'; +import { isReactClass } from './isReactClass'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isReactComponent(obj: any): obj is ComponentType { + return obj && (isReactClass(obj) || typeof obj === 'function'); +} diff --git a/packages/types/src/deprecated/isSetterConfig.ts b/packages/types/src/deprecated/isSetterConfig.ts new file mode 100644 index 000000000..38121c355 --- /dev/null +++ b/packages/types/src/deprecated/isSetterConfig.ts @@ -0,0 +1,9 @@ +import { SetterConfig } from '../setter-config'; +import { isCustomView } from './isCustomView'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isSetterConfig(obj: any): obj is SetterConfig { + return obj && typeof obj === 'object' && 'componentName' in obj && !isCustomView(obj); +} diff --git a/packages/types/src/deprecated/isTitleConfig.ts b/packages/types/src/deprecated/isTitleConfig.ts new file mode 100644 index 000000000..65f1403fc --- /dev/null +++ b/packages/types/src/deprecated/isTitleConfig.ts @@ -0,0 +1,10 @@ +import { isI18nData } from './isI18nData'; +import { isPlainObject } from './isPlainObject'; +import { TitleConfig } from '../title'; + +/** + * @deprecated use same function from '@alilc/lowcode-utils' instead + */ +export function isTitleConfig(obj: any): obj is TitleConfig { + return isPlainObject(obj) && !isI18nData(obj); +} diff --git a/packages/types/src/designer.ts b/packages/types/src/designer.ts new file mode 100644 index 000000000..0c6981578 --- /dev/null +++ b/packages/types/src/designer.ts @@ -0,0 +1,23 @@ +import { IPublicModelNode } from './shell'; + +export enum PROP_VALUE_CHANGED_TYPE { + /** + * normal set value + */ + SET_VALUE = 'SET_VALUE', + /** + * value changed caused by sub-prop value change + */ + SUB_VALUE_CHANGE = 'SUB_VALUE_CHANGE', +} + +export interface ISetValueOptions { + disableMutator?: boolean; + type?: PROP_VALUE_CHANGED_TYPE; + fromSetHotValue?: boolean; +} + +export interface IPublicOnChangeOptions { + type: string; + node: IPublicModelNode; +} diff --git a/packages/types/src/dragon.ts b/packages/types/src/dragon.ts new file mode 100644 index 000000000..5047b07c9 --- /dev/null +++ b/packages/types/src/dragon.ts @@ -0,0 +1,29 @@ +import { NodeSchema } from './schema'; +import { IPublicModelNode } from './shell'; + +export interface DragAnyObject { + type: string; + [key: string]: any; +} + +export interface DragNodeDataObject { + type: DragObjectType.NodeData; + data: NodeSchema | NodeSchema[]; + thumbnail?: string; + description?: string; + [extra: string]: any; +} + +export type DragObject = DragNodeObject | DragNodeDataObject | DragAnyObject; + +// eslint-disable-next-line no-shadow +export enum DragObjectType { + // eslint-disable-next-line no-shadow + Node = 'node', + NodeData = 'nodedata', +} + +export interface DragNodeObject { + type: DragObjectType.Node; + nodes: (Node | IPublicModelNode)[]; +} \ No newline at end of file diff --git a/packages/types/src/editor-skeleton.ts b/packages/types/src/editor-skeleton.ts new file mode 100644 index 000000000..e339c4c8a --- /dev/null +++ b/packages/types/src/editor-skeleton.ts @@ -0,0 +1,27 @@ +/** + * 所有可能的停靠位置 + */ + export type IWidgetConfigArea = + | 'leftArea' | 'left' | 'rightArea' + | 'right' | 'topArea' | 'top' + | 'toolbar' | 'mainArea' | 'main' + | 'center' | 'centerArea' | 'bottomArea' + | 'bottom' | 'leftFixedArea' + | 'leftFloatArea' | 'stages'; + +export interface IWidgetBaseConfig { + type: string; + name: string; + /** + * 停靠位置: + * - 当 type 为 'Panel' 时自动为 'leftFloatArea'; + * - 当 type 为 'Widget' 时自动为 'mainArea'; + * - 其他时候自动为 'leftArea'; + */ + area?: IWidgetConfigArea; + props?: Record; + content?: any; + contentProps?: Record; + // index?: number; + [extra: string]: any; +} diff --git a/packages/types/src/editor.ts b/packages/types/src/editor.ts index a11c7eaf7..cf5d3ae48 100644 --- a/packages/types/src/editor.ts +++ b/packages/types/src/editor.ts @@ -3,6 +3,8 @@ import StrictEventEmitter from 'strict-event-emitter-types'; import { ReactNode, ComponentType } from 'react'; import { NpmInfo } from './npm'; import * as GlobalEvent from './event'; +import { CustomView } from './setter-config'; +import { TitleContent } from './title'; export type KeyType = (new (...args: any[]) => any) | symbol | string; export type ClassType = new (...args: any[]) => any; @@ -197,3 +199,22 @@ export interface PluginStatus { export interface PluginStatusSet { [key: string]: PluginStatus; } + +export type HotkeyCallback = (e: KeyboardEvent, combo?: string) => any | false; + +export interface RegisteredSetter { + component: CustomView; + defaultProps?: object; + title?: TitleContent; + /** + * for MixedSetter to check this setter if available + */ + condition?: (field: any) => boolean; + /** + * for MixedSetter to manual change to this setter + */ + initialValue?: any | ((field: any) => any); + recommend?: boolean; + // 标识是否为动态 setter,默认为 true + isDynamic?: boolean; +} \ No newline at end of file diff --git a/packages/types/src/engine-config.ts b/packages/types/src/engine-config.ts new file mode 100644 index 000000000..5fb2196fd --- /dev/null +++ b/packages/types/src/engine-config.ts @@ -0,0 +1,181 @@ +import { RequestHandlersMap } from '@alilc/lowcode-datasource-types'; +import { ComponentType } from 'react'; + +export interface EngineOptions { + /** + * 是否开启 condition 的能力,默认在设计器中不管 condition 是啥都正常展示 + */ + enableCondition?: boolean; + /** + * @todo designMode 无法映射到文档渲染模块 + * + * 设计模式,live 模式将会实时展示变量值,默认值:'design' + */ + designMode?: 'design' | 'live'; + /** + * 设备类型,默认值:'default' + */ + device?: 'default' | 'mobile' | string; + /** + * 指定初始化的 deviceClassName,挂载到画布的顶层节点上 + */ + deviceClassName?: string; + /** + * 语言,默认值:'zh-CN' + */ + locale?: string; + /** + * 渲染器类型,默认值:'react' + */ + renderEnv?: 'react' | 'rax' | string; + /** + * 设备类型映射器,处理设计器与渲染器中 device 的映射 + */ + deviceMapper?: { + transform: (originalDevice: string) => string; + }; + /** + * 开启严格插件模式,默认值:STRICT_PLUGIN_MODE_DEFAULT , 严格模式下,插件将无法通过 engineOptions 传递自定义配置项 + * enable strict plugin mode, default value: false + * under strict mode, customed engineOption is not accepted. + */ + enableStrictPluginMode?: boolean; + /** + * 开启拖拽组件时,即将被放入的容器是否有视觉反馈,默认值:false + */ + enableReactiveContainer?: boolean; + /** + * 关闭画布自动渲染,在资产包多重异步加载的场景有效,默认值:false + */ + disableAutoRender?: boolean; + /** + * 关闭拖拽组件时的虚线响应,性能考虑,默认值:false + */ + disableDetecting?: boolean; + /** + * 定制画布中点击被忽略的 selectors,默认值:undefined + */ + customizeIgnoreSelectors?: (defaultIgnoreSelectors: string[], e: MouseEvent) => string[]; + /** + * 禁止默认的设置面板,默认值:false + */ + disableDefaultSettingPanel?: boolean; + /** + * 禁止默认的设置器,默认值:false + */ + disableDefaultSetters?: boolean; + /** + * 打开画布的锁定操作,默认值:false + */ + enableCanvasLock?: boolean; + /** + * 容器锁定后,容器本身是否可以设置属性,仅当画布锁定特性开启时生效,默认值为:false + */ + enableLockedNodeSetting?: boolean; + /** + * 当选中节点切换时,是否停留在相同的设置 tab 上,默认值:false + */ + stayOnTheSameSettingTab?: boolean; + /** + * 是否在只有一个 item 的时候隐藏设置 tabs,默认值:false + */ + hideSettingsTabsWhenOnlyOneItem?: boolean; + /** + * 自定义 loading 组件 + */ + loadingComponent?: ComponentType; + /** + * 设置所有属性支持变量配置,默认值:false + */ + supportVariableGlobally?: boolean; + /** + * 设置 simulator 相关的 url,默认值:undefined + */ + simulatorUrl?: string[]; + /** + * Vision-polyfill settings + */ + visionSettings?: { + // 是否禁用降级 reducer,默认值:false + disableCompatibleReducer?: boolean; + // 是否开启在 render 阶段开启 filter reducer,默认值:false + enableFilterReducerInRenderStage?: boolean; + }; + /** + * 与 react-renderer 的 appHelper 一致,https://lowcode-engine.cn/site/docs/guide/expand/runtime/renderer#apphelper + */ + appHelper?: { + /** 全局公共函数 */ + utils?: Record; + /** 全局常量 */ + constants?: Record; + }; + + /** + * 数据源引擎的请求处理器映射 + */ + requestHandlersMap?: RequestHandlersMap; + + /** + * @default true + * JSExpression 是否只支持使用 this 来访问上下文变量,假如需要兼容原来的 'state.xxx',则设置为 false + */ + thisRequiredInJSE?: boolean; + + /** + * @default false + * 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件 + */ + enableStrictNotFoundMode?: boolean; + + /** + * 配置指定节点为根组件 + */ + focusNodeSelector?: (rootNode: Node) => Node; +} + +export interface IEngineConfig { + /** + * 判断指定 key 是否有值 + * @param key + * @returns + */ + has(key: string): boolean; + + /** + * 获取指定 key 的值 + * @param key + * @param defaultValue + * @returns + */ + get(key: string, defaultValue?: any): any; + + /** + * 设置指定 key 的值 + * @param key + * @param value + */ + set(key: string, value: any): void; + + /** + * 批量设值,set 的对象版本 + * @param config + */ + setConfig(config: { [key: string]: any }): void; + + /** + * 获取指定 key 的值,若此时还未赋值,则等待,若已有值,则直接返回值 + * 注:此函数返回 Promise 实例,只会执行(fullfill)一次 + * @param key + * @returns + */ + onceGot(key: string): Promise; + + /** + * 获取指定 key 的值,函数回调模式,若多次被赋值,回调会被多次调用 + * @param key + * @param fn + * @returns + */ + onGot(key: string, fn: (data: any) => void): () => void; +} \ No newline at end of file diff --git a/packages/types/src/i18n.ts b/packages/types/src/i18n.ts index 44f8ef855..adcc72438 100644 --- a/packages/types/src/i18n.ts +++ b/packages/types/src/i18n.ts @@ -6,11 +6,6 @@ export interface I18nData { [key: string]: any; } -// type checks -export function isI18nData(obj: any): obj is I18nData { - return obj && obj.type === 'i18n'; -} - export interface I18nMap { [lang: string]: { [key: string]: string }; } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 9b540cc5f..9db5bae46 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -22,3 +22,12 @@ export * from './assets'; export * as GlobalEvent from './event'; export * from './disposable'; export * from './start-transaction'; +export * from './props-transducer'; +export * from './editor-skeleton'; +export * from './designer'; +export * from './dragon'; +export * from './shell'; +export * from './shell-model-factory'; +export * from './engine-config'; +// TODO: remove this in future versions +export * from './deprecated'; diff --git a/packages/types/src/metadata.ts b/packages/types/src/metadata.ts index dd93aea00..394dd2909 100644 --- a/packages/types/src/metadata.ts +++ b/packages/types/src/metadata.ts @@ -336,10 +336,6 @@ export interface ComponentAction { important?: boolean; } -export function isActionContentObject(obj: any): obj is ActionContentObject { - return obj && typeof obj === 'object'; -} - /** * 组件 meta 配置 */ @@ -473,3 +469,17 @@ export interface Callbacks { currentNode: any, ) => void; } + +export interface MetadataTransducer { + (prev: TransformedComponentMetadata): TransformedComponentMetadata; + /** + * 0 - 9 system + * 10 - 99 builtin-plugin + * 100 - app & plugin + */ + level?: number; + /** + * use to replace TODO + */ + id?: string; +} \ No newline at end of file diff --git a/packages/types/src/npm.ts b/packages/types/src/npm.ts index 88449f435..f805158e5 100644 --- a/packages/types/src/npm.ts +++ b/packages/types/src/npm.ts @@ -1,3 +1,4 @@ + /** * npm 源引入完整描述对象 */ @@ -45,13 +46,4 @@ export interface LowCodeComponentType { export type ProCodeComponentType = NpmInfo; export type ComponentMap = ProCodeComponentType | LowCodeComponentType; - -export function isProCodeComponentType(desc: ComponentMap): desc is ProCodeComponentType { - return 'package' in desc; -} - -export function isLowCodeComponentType(desc: ComponentMap): desc is LowCodeComponentType { - return !isProCodeComponentType(desc); -} - export type ComponentsMap = ComponentMap[]; diff --git a/packages/types/src/props-transducer.ts b/packages/types/src/props-transducer.ts new file mode 100644 index 000000000..227247569 --- /dev/null +++ b/packages/types/src/props-transducer.ts @@ -0,0 +1,12 @@ +import { TransformStage } from './transform-stage'; +import { CompositeObject } from './value-type'; + +export type PropsReducerContext = { + stage: TransformStage; +}; + +export type PropsTransducer = ( + props: CompositeObject, + node: Node, + ctx?: PropsReducerContext, +) => CompositeObject; diff --git a/packages/types/src/schema.ts b/packages/types/src/schema.ts index 5d0fad444..e320d6b51 100644 --- a/packages/types/src/schema.ts +++ b/packages/types/src/schema.ts @@ -75,11 +75,6 @@ export type PropsList = Array<{ export type NodeData = NodeSchema | JSExpression | DOMText; export type NodeDataType = NodeData | NodeData[]; - -export function isDOMText(data: any): data is DOMText { - return typeof data === 'string'; -} - export type DOMText = string; /** @@ -217,12 +212,4 @@ export interface ProjectSchema { * 当前应用元数据信息 */ meta?: Record; -} - -export function isNodeSchema(data: any): data is NodeSchema { - return data && data.componentName; -} - -export function isProjectSchema(data: any): data is ProjectSchema { - return data && data.componentsTree; -} +} \ No newline at end of file diff --git a/packages/types/src/setter-config.ts b/packages/types/src/setter-config.ts index d579240ef..5138e3649 100644 --- a/packages/types/src/setter-config.ts +++ b/packages/types/src/setter-config.ts @@ -1,18 +1,9 @@ -import { ComponentClass, Component, ComponentType, ReactElement, isValidElement } from 'react'; +import { ComponentType, ReactElement } from 'react'; import { TitleContent } from './title'; import { SettingTarget } from './setting-target'; import { CompositeValue } from './value-type'; -function isReactClass(obj: any): obj is ComponentClass { - return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component); -} - -function isReactComponent(obj: any): obj is ComponentType { - return obj && (isReactClass(obj) || typeof obj === 'function'); -} - export type CustomView = ReactElement | ComponentType; - export type DynamicProps = (target: SettingTarget) => Record; export type DynamicSetter = (target: SettingTarget) => string | SetterConfig | CustomView; @@ -63,21 +54,9 @@ export interface SetterConfig { * @todo 物料协议推进 */ valueType?: CompositeValue[]; - // 标识是否为动态setter,默认为true + // 标识是否为动态 setter,默认为 true isDynamic?: boolean; } // if *string* passed must be a registered Setter Name, future support blockSchema -export type SetterType = SetterConfig | SetterConfig[] | string | CustomView; - -export function isSetterConfig(obj: any): obj is SetterConfig { - return obj && typeof obj === 'object' && 'componentName' in obj && !isCustomView(obj); -} - -export function isCustomView(obj: any): obj is CustomView { - return obj && (isValidElement(obj) || isReactComponent(obj)); -} - -export function isDynamicSetter(obj: any): obj is DynamicSetter { - return obj && typeof obj === 'function' && !isReactClass(obj); -} +export type SetterType = SetterConfig | SetterConfig[] | string | CustomView; \ No newline at end of file diff --git a/packages/types/src/shell-model-factory.ts b/packages/types/src/shell-model-factory.ts new file mode 100644 index 000000000..a7a57648f --- /dev/null +++ b/packages/types/src/shell-model-factory.ts @@ -0,0 +1,8 @@ +import { IPublicModelSettingPropEntry, IPublicModelNode } from './shell'; + +export interface IShellModelFactory { + // TODO: 需要给 innerNode 提供一个 interface 并用在这里 + createNode(node: any | null | undefined): IPublicModelNode | null; + // TODO: 需要给 InnerSettingField 提供一个 interface 并用在这里 + createSettingPropEntry(prop: any): IPublicModelSettingPropEntry; +} diff --git a/packages/types/src/shell/api/common.ts b/packages/types/src/shell/api/common.ts new file mode 100644 index 000000000..0c59bbcad --- /dev/null +++ b/packages/types/src/shell/api/common.ts @@ -0,0 +1,50 @@ + +import { Component, ReactNode } from 'react'; +import { NodeSchema } from '../../schema'; +import { TransitionType } from '../../start-transaction'; + +export interface IPublicCommonUtils { + isNodeSchema(data: any): boolean; + + isFormEvent(e: KeyboardEvent | MouseEvent): boolean; + + compatibleLegaoSchema(props: any): any; + + getNodeSchemaById(schema: NodeSchema, nodeId: string): NodeSchema | undefined; + + getConvertedExtraKey(key: string): string; + + getOriginalExtraKey(key: string): string; + + executeTransaction(fn: () => void, type: TransitionType): void; + + createIntl(instance: string | object): { + intlNode(id: string, params?: object): ReactNode; + intl(id: string, params?: object): string; + getLocale(): string; + setLocale(locale: string): void; + }; +} +export interface IPublicCommonSkeletonCabin { + get Workbench(): Component; +} + +export interface IPublicCommonDesignerCabin { + /** + * 是否是 SettingField 实例 + * + * @param {*} obj + * @returns {obj is SettingField} + * @memberof DesignerCabin + */ + isSettingField(obj: any): boolean; +} + +export interface IPublicApiCommon { + + get utils(): IPublicCommonUtils; + + get designerCabin(): IPublicCommonDesignerCabin; + + get skeletonCabin(): IPublicCommonSkeletonCabin; +} diff --git a/packages/types/src/shell/api/event.ts b/packages/types/src/shell/api/event.ts new file mode 100644 index 000000000..c7f35ff58 --- /dev/null +++ b/packages/types/src/shell/api/event.ts @@ -0,0 +1,26 @@ + +export interface IPublicApiEvent { + + /** + * 监听事件 + * @param event 事件名称 + * @param listener 事件回调 + */ + on(event: string, listener: (...args: unknown[]) => void): void; + + + /** + * 取消监听事件 + * @param event 事件名称 + * @param listener 事件回调 + */ + off(event: string, listener: (...args: unknown[]) => void): void; + + /** + * 触发事件 + * @param event 事件名称 + * @param args 事件参数 + * @returns + */ + emit(event: string, ...args: unknown[]): void; +} diff --git a/packages/types/src/shell/api/hotkey.ts b/packages/types/src/shell/api/hotkey.ts new file mode 100644 index 000000000..983792f04 --- /dev/null +++ b/packages/types/src/shell/api/hotkey.ts @@ -0,0 +1,16 @@ +import { Disposable } from '../../disposable'; +import { HotkeyCallback } from '../../editor'; + + +export interface IPublicApiHotkey { + get callbacks(): any; + + /** + * 绑定快捷键 + * @param combos 快捷键,格式如:['command + s'] 、['ctrl + shift + s'] 等 + * @param callback 回调函数 + * @param action + * @returns + */ + bind(combos: string[] | string, callback: HotkeyCallback, action?: string): Disposable; +} diff --git a/packages/types/src/shell/api/index.ts b/packages/types/src/shell/api/index.ts new file mode 100644 index 000000000..9e5152b9e --- /dev/null +++ b/packages/types/src/shell/api/index.ts @@ -0,0 +1,8 @@ +export * from './common'; +export * from './event'; +export * from './hotkey'; +export * from './material'; +export * from './project'; +export * from './setters'; +export * from './simulator-host'; +export * from './skeleton'; \ No newline at end of file diff --git a/packages/types/src/shell/api/material.ts b/packages/types/src/shell/api/material.ts new file mode 100644 index 000000000..d46aa66bf --- /dev/null +++ b/packages/types/src/shell/api/material.ts @@ -0,0 +1,90 @@ +import { AssetsJson } from '../../assets'; +import { MetadataTransducer, ComponentAction } from '../../metadata'; +import { IPublicModelComponentMeta } from '../model/component-meta'; + + +export interface IPublicApiMaterial { + + /** + * 设置「资产包」结构 + * @param assets + * @returns + */ + setAssets(assets: AssetsJson): void; + + /** + * 获取「资产包」结构 + * @returns + */ + getAssets(): any; + + /** + * 加载增量的「资产包」结构,该增量包会与原有的合并 + * @param incrementalAssets + * @returns + */ + loadIncrementalAssets(incrementalAssets: AssetsJson): void; + + /** + * 注册物料元数据管道函数 + * @param transducer + * @param level + * @param id + */ + registerMetadataTransducer( + transducer: MetadataTransducer, + level?: number, + id?: string | undefined + ): void; + + /** + * 获取所有物料元数据管道函数 + * @returns + */ + getRegisteredMetadataTransducers(): MetadataTransducer[]; + + /** + * 获取指定名称的物料元数据 + * @param componentName + * @returns + */ + getComponentMeta(componentName: string): IPublicModelComponentMeta | null; + + /** + * test if the given object is a ComponentMeta instance or not + * @param obj + * @returns + */ + isComponentMeta(obj: any): boolean; + + /** + * 获取所有已注册的物料元数据 + * @returns + */ + getComponentMetasMap(): Map; + + /** + * 在设计器辅助层增加一个扩展 action + * @param action + */ + addBuiltinComponentAction(action: ComponentAction): void; + + /** + * 移除设计器辅助层的指定 action + * @param name + */ + removeBuiltinComponentAction(name: string): void; + + /** + * 修改已有的设计器辅助层的指定 action + * @param actionName + * @param handle + */ + modifyBuiltinComponentAction(actionName: string, handle: (action: ComponentAction) => void): void; + + /** + * 监听 assets 变化的事件 + * @param fn + */ + onChangeAssets(fn: () => void): void; +} diff --git a/packages/types/src/shell/api/project.ts b/packages/types/src/shell/api/project.ts new file mode 100644 index 000000000..398669c94 --- /dev/null +++ b/packages/types/src/shell/api/project.ts @@ -0,0 +1,115 @@ +import { RootSchema, ProjectSchema } from '../../schema'; +import { TransformStage } from '../../transform-stage'; +import { PropsTransducer } from '../../props-transducer'; +import { IPublicApiSimulatorHost } from './simulator-host'; +import { IPublicModelDocumentModel } from '../model'; + + +export interface IPublicApiProject { + /** + * 获取当前的 document + * @returns + */ + get currentDocument(): IPublicModelDocumentModel | null; + + /** + * 获取当前 project 下所有 documents + * @returns + */ + get documents(): IPublicModelDocumentModel[]; + + /** + * 获取模拟器的 host + */ + get simulatorHost(): IPublicApiSimulatorHost | null; + + /** + * 打开一个 document + * @param doc + * @returns + */ + openDocument(doc?: string | RootSchema | undefined): IPublicModelDocumentModel | null; + + /** + * 创建一个 document + * @param data + * @returns + */ + createDocument(data?: RootSchema): IPublicModelDocumentModel | null; + + + /** + * 删除一个 document + * @param doc + */ + removeDocument(doc: IPublicModelDocumentModel): void; + + /** + * 根据 fileName 获取 document + * @param fileName + * @returns + */ + getDocumentByFileName(fileName: string): IPublicModelDocumentModel | null; + + /** + * 根据 id 获取 document + * @param id + * @returns + */ + getDocumentById(id: string): IPublicModelDocumentModel | null; + + /** + * 导出 project + * @returns + */ + exportSchema(stage: TransformStage): ProjectSchema; + + /** + * 导入 project + * @param schema 待导入的 project 数据 + */ + importSchema(schema?: ProjectSchema): void; + + /** + * 获取当前的 document + * @returns + */ + getCurrentDocument(): IPublicModelDocumentModel | null; + + /** + * 增加一个属性的管道处理函数 + * @param transducer + * @param stage + */ + addPropsTransducer(transducer: PropsTransducer, stage: TransformStage): void; + + /** + * 绑定删除文档事件 + * @param fn + * @returns + */ + onRemoveDocument(fn: (data: { id: string }) => void): any; + + /** + * 当前 project 内的 document 变更事件 + */ + onChangeDocument(fn: (doc: IPublicModelDocumentModel) => void): () => void; + + /** + * 当前 project 的模拟器 ready 事件 + */ + onSimulatorHostReady(fn: (host: IPublicApiSimulatorHost) => void): () => void; + + /** + * 当前 project 的渲染器 ready 事件 + */ + onSimulatorRendererReady(fn: () => void): () => void; + + /** + * 设置多语言语料 + * 数据格式参考 https://github.com/alibaba/lowcode-engine/blob/main/specs/lowcode-spec.md#2434%E5%9B%BD%E9%99%85%E5%8C%96%E5%A4%9A%E8%AF%AD%E8%A8%80%E7%B1%BB%E5%9E%8Baa + * @param value object + * @returns + */ + setI18n(value: object): void; +} diff --git a/packages/types/src/shell/api/setters.ts b/packages/types/src/shell/api/setters.ts new file mode 100644 index 000000000..e133c29af --- /dev/null +++ b/packages/types/src/shell/api/setters.ts @@ -0,0 +1,31 @@ +import { RegisteredSetter } from '../../editor'; +import { CustomView } from '../../setter-config'; + + +export interface IPublicApiSetters { + /** + * 获取指定 setter + * @param type + * @returns + */ + getSetter(type: string): RegisteredSetter | null; + + /** + * 获取已注册的所有 settersMap + * @returns + */ + getSettersMap(): Map; + + /** + * 注册一个 setter + * @param typeOrMaps + * @param setter + * @returns + */ + registerSetter( + typeOrMaps: string | { [key: string]: CustomView | RegisteredSetter }, + setter?: CustomView | RegisteredSetter | undefined + ): void; +} diff --git a/packages/types/src/shell/api/simulator-host.ts b/packages/types/src/shell/api/simulator-host.ts new file mode 100644 index 000000000..971e78a83 --- /dev/null +++ b/packages/types/src/shell/api/simulator-host.ts @@ -0,0 +1,41 @@ +import { IPublicModelNode } from '../model'; + + +export interface IPublicApiSimulatorHost { + /** + * 获取 contentWindow + */ + get contentWindow(): Window | undefined; + + /** + * 获取 contentDocument + */ + get contentDocument(): Document | undefined; + + get renderer(): any; + + /** + * 设置 host 配置值 + * @param key + * @param value + */ + set(key: string, value: any): void; + + /** + * 获取 host 配置值 + * @param key + * @returns + */ + get(key: string): any; + + /** + * scroll to specific node + * @param node + */ + scrollToNode(node: IPublicModelNode): void; + + /** + * 刷新渲染画布 + */ + rerender(): void; +} diff --git a/packages/types/src/shell/api/skeleton.ts b/packages/types/src/shell/api/skeleton.ts new file mode 100644 index 000000000..5f81c6407 --- /dev/null +++ b/packages/types/src/shell/api/skeleton.ts @@ -0,0 +1,95 @@ +import { IWidgetBaseConfig } from '../../editor-skeleton'; + + +export interface IPublicApiSkeleton { + /** + * 增加一个面板实例 + * @param config + * @param extraConfig + * @returns + */ + add(config: IWidgetBaseConfig, extraConfig?: Record): any; + + /** + * 移除一个面板实例 + * @param config + * @returns + */ + remove(config: IWidgetBaseConfig): number | undefined; + + /** + * 显示面板 + * @param name + */ + showPanel(name: string): void; + + /** + * 隐藏面板 + * @param name + */ + hidePanel(name: string): void; + + /** + * 显示 widget + * @param name + */ + showWidget(name: string): void; + + /** + * enable widget + * @param name + */ + enableWidget(name: string): void; + + /** + * 隐藏 widget + * @param name + */ + hideWidget(name: string): void; + + /** + * disable widget,不可点击 + * @param name + */ + disableWidget(name: string): void; + + /** + * show area + * @param areaName name of area + */ + showArea(areaName: string): void; + + /** + * hide area + * @param areaName name of area + */ + hideArea(areaName: string): void; + + /** + * 监听 panel 显示事件 + * @param listener + * @returns + */ + onShowPanel(listener: (...args: unknown[]) => void): () => void; + + /** + * 监听 panel 隐藏事件 + * @param listener + * @returns + */ + onHidePanel(listener: (...args: unknown[]) => void): () => void; + + /** + * 监听 widget 显示事件 + * @param listener + * @returns + */ + onShowWidget(listener: (...args: unknown[]) => void): () => void; + + /** + * 监听 widget 隐藏事件 + * @param listener + * @returns + */ + onHideWidget(listener: (...args: unknown[]) => void): () => void; +} diff --git a/packages/types/src/shell/index.ts b/packages/types/src/shell/index.ts new file mode 100644 index 000000000..0ee50daea --- /dev/null +++ b/packages/types/src/shell/index.ts @@ -0,0 +1,15 @@ +import { + IPublicModelNode, + IPublicModelProp, +} from './model'; + +export interface PropChangeOptions { + key?: string | number; + prop?: IPublicModelProp; + node: IPublicModelNode; + newValue: any; + oldValue: any; +} + +export * from './api'; +export * from './model'; \ No newline at end of file diff --git a/packages/types/src/shell/model/canvas.ts b/packages/types/src/shell/model/canvas.ts new file mode 100644 index 000000000..50c6d3905 --- /dev/null +++ b/packages/types/src/shell/model/canvas.ts @@ -0,0 +1,4 @@ + +export interface IPublicModelCanvas { + get dropLocation(): any; +} diff --git a/packages/types/src/shell/model/component-meta.ts b/packages/types/src/shell/model/component-meta.ts new file mode 100644 index 000000000..f50081f14 --- /dev/null +++ b/packages/types/src/shell/model/component-meta.ts @@ -0,0 +1,85 @@ +import { NodeSchema, NodeData } from '../../schema'; +import { IconType } from '../../icon'; +import { TransformedComponentMetadata } from '../../metadata'; +import { ReactElement } from 'react'; +import { I18nData } from '../../i18n'; +import { NpmInfo } from '../../npm'; +import { IPublicModelNode } from './node'; + +export interface IPublicModelComponentMeta { + /** + * 组件名 + */ + get componentName(): string; + + /** + * 是否是「容器型」组件 + */ + get isContainer(): boolean; + + /** + * 是否是最小渲染单元。 + * 当组件需要重新渲染时: + * 若为最小渲染单元,则只渲染当前组件, + * 若不为最小渲染单元,则寻找到上层最近的最小渲染单元进行重新渲染,直至根节点。 + */ + get isMinimalRenderUnit(): boolean; + + /** + * 是否为「模态框」组件 + */ + get isModal(): boolean; + + /** + * 元数据配置 + */ + get configure(): any; + + /** + * 标题 + */ + get title(): string | I18nData | ReactElement; + + /** + * 图标 + */ + get icon(): IconType; + + /** + * 组件 npm 信息 + */ + get npm(): NpmInfo; + + get availableActions(): any; + + /** + * 设置 npm 信息 + * @param npm + */ + setNpm(npm: NpmInfo): void; + + /** + * 获取元数据 + * @returns + */ + getMetadata(): TransformedComponentMetadata; + + /** + * check if the current node could be placed in parent node + * @param my + * @param parent + * @returns + */ + checkNestingUp(my: IPublicModelNode | NodeData, parent: any): boolean; + + /** + * check if the target node(s) could be placed in current node + * @param my + * @param parent + * @returns + */ + checkNestingDown(my: IPublicModelNode | NodeData, target: NodeSchema | IPublicModelNode | NodeSchema[]): boolean; + + + refreshMetadata(): void; +} diff --git a/packages/types/src/shell/model/detecting.ts b/packages/types/src/shell/model/detecting.ts new file mode 100644 index 000000000..a9a480b2e --- /dev/null +++ b/packages/types/src/shell/model/detecting.ts @@ -0,0 +1,23 @@ +export interface IPublicModelDetecting { + /** + * 当前 hover 的节点 + */ + get current(): any; + + /** + * hover 指定节点 + * @param id 节点 id + */ + capture(id: string): any; + + /** + * hover 离开指定节点 + * @param id 节点 id + */ + release(id: string): any; + + /** + * 清空 hover 态 + */ + leave(): any; +} diff --git a/packages/types/src/shell/model/document-model.ts b/packages/types/src/shell/model/document-model.ts new file mode 100644 index 000000000..2407cdab1 --- /dev/null +++ b/packages/types/src/shell/model/document-model.ts @@ -0,0 +1,155 @@ +import { RootSchema } from '../../schema'; +import { TransformStage } from '../../transform-stage'; +import { DragNodeDataObject, DragNodeObject } from '../../dragon'; +import { IPublicApiProject } from '../api'; +import { PropChangeOptions } from '../index'; +import { IPublicModelModalNodesManager } from './modal-nodes-manager'; +import { IPublicModelNode } from './node'; + + +export interface IPublicModelDocumentModel { + + /** + * id + */ + get id(): string; + + set id(id); + + /** + * 获取当前文档所属的 project + * @returns + */ + get project(): IPublicApiProject | null; + + /** + * 获取文档的根节点 + * @returns + */ + get root(): IPublicModelNode | null; + + get focusNode(): IPublicModelNode | null; + + set focusNode(node: IPublicModelNode | null); + + /** + * 获取文档下所有节点 + * @returns + */ + get nodesMap(): any; + + /** + * 模态节点管理 + */ + get modalNodesManager(): IPublicModelModalNodesManager | null; + + /** + * 根据 nodeId 返回 Node 实例 + * @param nodeId + * @returns + */ + getNodeById(nodeId: string): IPublicModelNode | null; + + /** + * 导入 schema + * @param schema + */ + importSchema(schema: RootSchema): void; + + /** + * 导出 schema + * @param stage + * @returns + */ + exportSchema(stage: TransformStage): any; + + /** + * 插入节点 + * @param parent + * @param thing + * @param at + * @param copy + * @returns + */ + insertNode( + parent: IPublicModelNode, + thing: IPublicModelNode, + at?: number | null | undefined, + copy?: boolean | undefined + ): IPublicModelNode | null; + + /** + * 创建一个节点 + * @param data + * @returns + */ + createNode(data: any): IPublicModelNode | null; + + /** + * 移除指定节点/节点id + * @param idOrNode + */ + removeNode(idOrNode: string | IPublicModelNode): void; + + /** + * componentsMap of documentModel + * @param extraComps + * @returns + */ + getComponentsMap(extraComps?: string[]): any; + + /** + * 检查拖拽放置的目标节点是否可以放置该拖拽对象 + * @param dropTarget 拖拽放置的目标节点 + * @param dragObject 拖拽的对象 + * @returns boolean 是否可以放置 + */ + checkNesting( + dropTarget: IPublicModelNode, + dragObject: DragNodeObject | DragNodeDataObject + ): boolean; + + /** + * 当前 document 新增节点事件 + */ + onAddNode(fn: (node: IPublicModelNode) => void): () => void; + + /** + * 当前 document 新增节点事件,此时节点已经挂载到 document 上 + */ + onMountNode(fn: (payload: { node: IPublicModelNode }) => void): () => void; + + /** + * 当前 document 删除节点事件 + */ + onRemoveNode(fn: (node: IPublicModelNode) => void): () => void; + + /** + * 当前 document 的 hover 变更事件 + */ + onChangeDetecting(fn: (node: IPublicModelNode) => void): () => void; + + /** + * 当前 document 的选中变更事件 + */ + onChangeSelection(fn: (ids: string[]) => void): () => void; + + /** + * 当前 document 的节点显隐状态变更事件 + * @param fn + */ + onChangeNodeVisible(fn: (node: IPublicModelNode, visible: boolean) => void): void; + + + /** + * 当前 document 节点属性修改事件 + * @param fn + */ + onChangeNodeProp(fn: (info: PropChangeOptions) => void): void; + + /** + * import schema event + * @param fn + */ + onImportSchema(fn: (schema: RootSchema) => void): void; +} diff --git a/packages/types/src/shell/model/drag-object.ts b/packages/types/src/shell/model/drag-object.ts new file mode 100644 index 000000000..9169ea853 --- /dev/null +++ b/packages/types/src/shell/model/drag-object.ts @@ -0,0 +1,8 @@ +export interface IPublicModelDragObject { + + get type(): any; + + get nodes(): any; + + get data(): any; +} diff --git a/packages/types/src/shell/model/dragon.ts b/packages/types/src/shell/model/dragon.ts new file mode 100644 index 000000000..f6f97ac08 --- /dev/null +++ b/packages/types/src/shell/model/dragon.ts @@ -0,0 +1,39 @@ +import { DragNodeDataObject } from '../../dragon'; +import { IPublicModelDragObject } from './drag-object'; +import { IPublicModelLocateEvent } from './locate-event'; + +export interface IPublicModelDragon { + /** + * is dragging or not + */ + get dragging(): boolean; + + /** + * 绑定 dragstart 事件 + * @param func + * @returns + */ + onDragstart(func: (e: IPublicModelLocateEvent) => any): () => void; + + /** + * 绑定 drag 事件 + * @param func + * @returns + */ + onDrag(func: (e: IPublicModelLocateEvent) => any): () => void; + + /** + * 绑定 dragend 事件 + * @param func + * @returns + */ + onDragend(func: (o: { dragObject: IPublicModelDragObject; copy?: boolean }) => any): () => void; + + + /** + * 设置拖拽监听的区域 shell,以及自定义拖拽转换函数 boost + * @param shell 拖拽监听的区域 + * @param boost 拖拽转换函数 + */ + from(shell: Element, boost: (e: MouseEvent) => DragNodeDataObject | null): any; +} diff --git a/packages/types/src/shell/model/drop-location.ts b/packages/types/src/shell/model/drop-location.ts new file mode 100644 index 000000000..746850b1f --- /dev/null +++ b/packages/types/src/shell/model/drop-location.ts @@ -0,0 +1,3 @@ +export interface IPublicModelDropLocation { + get target(): any; +} diff --git a/packages/types/src/shell/model/history.ts b/packages/types/src/shell/model/history.ts new file mode 100644 index 000000000..1c0020de3 --- /dev/null +++ b/packages/types/src/shell/model/history.ts @@ -0,0 +1,49 @@ +export interface IPublicModelHistory { + + /** + * 历史记录跳转到指定位置 + * @param cursor + */ + go(cursor: number): void; + + /** + * 历史记录后退 + */ + back(): void; + + /** + * 历史记录前进 + */ + forward(): void; + + /** + * 保存当前状态 + */ + savePoint(): void; + + /** + * 当前是否是「保存点」,即是否有状态变更但未保存 + * @returns + */ + isSavePoint(): boolean; + + /** + * 获取 state,判断当前是否为「可回退」、「可前进」的状态 + * @returns + */ + getState(): any; + + /** + * 监听 state 变更事件 + * @param func + * @returns + */ + onChangeState(func: () => any): () => void; + + /** + * 监听历史记录游标位置变更事件 + * @param func + * @returns + */ + onChangeCursor(func: () => any): () => void; +} diff --git a/packages/types/src/shell/model/index.ts b/packages/types/src/shell/model/index.ts new file mode 100644 index 000000000..27d3fcbb6 --- /dev/null +++ b/packages/types/src/shell/model/index.ts @@ -0,0 +1,17 @@ +export * from './canvas'; +export * from './component-meta'; +export * from './detecting'; +export * from './document-model'; +export * from './drag-object'; +export * from './dragon'; +export * from './drop-location'; +export * from './history'; +export * from './locate-event'; +export * from './modal-nodes-manager'; +export * from './node-children'; +export * from './node'; +export * from './prop'; +export * from './props'; +export * from './selection'; +export * from './setting-prop-entry'; +export * from './setting-top-entry'; \ No newline at end of file diff --git a/packages/types/src/shell/model/locate-event.ts b/packages/types/src/shell/model/locate-event.ts new file mode 100644 index 000000000..bde101034 --- /dev/null +++ b/packages/types/src/shell/model/locate-event.ts @@ -0,0 +1,20 @@ +import { IPublicModelDragObject } from './drag-object'; + +export interface IPublicModelLocateEvent { + + get type(): string; + + get globalX(): number; + + get globalY(): number; + + get originalEvent(): MouseEvent | DragEvent; + + get target(): Element | null | undefined; + + get canvasX(): number | undefined; + + get canvasY(): number | undefined; + + get dragObject(): IPublicModelDragObject | null; +} diff --git a/packages/types/src/shell/model/modal-nodes-manager.ts b/packages/types/src/shell/model/modal-nodes-manager.ts new file mode 100644 index 000000000..07d598e2e --- /dev/null +++ b/packages/types/src/shell/model/modal-nodes-manager.ts @@ -0,0 +1,37 @@ +import { IPublicModelNode } from './node'; + +export interface IPublicModelModalNodesManager { + /** + * 设置模态节点,触发内部事件 + */ + setNodes(): void; + + /** + * 获取模态节点(们) + * @returns + */ + getModalNodes(): any; + + /** + * 获取当前可见的模态节点 + * @returns + */ + getVisibleModalNode(): any; + + /** + * 隐藏模态节点(们) + */ + hideModalNodes(): void; + + /** + * 设置指定节点为可见态 + * @param node Node + */ + setVisible(node: IPublicModelNode): void; + + /** + * 设置指定节点为不可见态 + * @param node Node + */ + setInvisible(node: IPublicModelNode): void; +} diff --git a/packages/types/src/shell/model/node-children.ts b/packages/types/src/shell/model/node-children.ts new file mode 100644 index 000000000..204405454 --- /dev/null +++ b/packages/types/src/shell/model/node-children.ts @@ -0,0 +1,128 @@ +import { NodeSchema, NodeData } from '../../schema'; +import { TransformStage } from '../../transform-stage'; +import { IPublicModelNode } from './node'; + +export interface IPublicModelNodeChildren { + /** + * 返回当前 children 实例所属的节点实例 + */ + get owner(): IPublicModelNode | null; + + /** + * children 内的节点实例数 + */ + get size(): number; + + /** + * 是否为空 + * @returns + */ + get isEmpty(): boolean; + + /** + * judge if it is not empty + */ + get notEmpty(): boolean; + + /** + * 删除指定节点 + * @param node + * @returns + */ + delete(node: IPublicModelNode): boolean; + + /** + * 插入一个节点 + * @param node 待插入节点 + * @param at 插入下标 + * @returns + */ + insert(node: IPublicModelNode, at?: number | null): void; + + /** + * 返回指定节点的下标 + * @param node + * @returns + */ + indexOf(node: IPublicModelNode): number; + + /** + * 类似数组 splice 操作 + * @param start + * @param deleteCount + * @param node + */ + splice(start: number, deleteCount: number, node?: IPublicModelNode): any; + + /** + * 返回指定下标的节点 + * @param index + * @returns + */ + get(index: number): any; + + /** + * 是否包含指定节点 + * @param node + * @returns + */ + has(node: IPublicModelNode): boolean; + + /** + * 类似数组的 forEach + * @param fn + */ + forEach(fn: (node: IPublicModelNode, index: number) => void): void; + + /** + * 类似数组的 map + * @param fn + */ + map(fn: (node: IPublicModelNode, index: number) => T[]): any[] | null; + + /** + * 类似数组的 every + * @param fn + */ + every(fn: (node: IPublicModelNode, index: number) => boolean): boolean; + + /** + * 类似数组的 some + * @param fn + */ + some(fn: (node: IPublicModelNode, index: number) => boolean): boolean; + + /** + * 类似数组的 filter + * @param fn + */ + filter(fn: (node: IPublicModelNode, index: number) => boolean): any; + + /** + * 类似数组的 find + * @param fn + */ + find(fn: (node: IPublicModelNode, index: number) => boolean): IPublicModelNode | null; + + reduce(fn: (acc: any, cur: IPublicModelNode) => any, initialValue: any): void; + + /** + * 导入 schema + * @param data + */ + importSchema(data?: NodeData | NodeData[]): void; + + /** + * 导出 schema + * @param stage + * @returns + */ + exportSchema(stage: TransformStage): NodeSchema; + + mergeChildren( + remover: (node: IPublicModelNode, idx: number) => boolean, + adder: (children: IPublicModelNode[]) => NodeData[] | null, + sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number + ): any; + +} diff --git a/packages/types/src/shell/model/node.ts b/packages/types/src/shell/model/node.ts new file mode 100644 index 000000000..f0aaf9506 --- /dev/null +++ b/packages/types/src/shell/model/node.ts @@ -0,0 +1,316 @@ +import { NodeSchema, PropsMap, PropsList } from '../../schema'; +import { TransformStage } from '../../transform-stage'; +import { IconType } from '../../icon'; +import { ReactElement } from 'react'; +import { I18nData } from '../../i18n'; +import { CompositeValue } from '../../value-type'; +import { IPublicModelDocumentModel } from './document-model'; +import { IPublicModelSettingTopEntry } from './setting-top-entry'; +import { IPublicModelProps } from './props'; +import { IPublicModelProp } from './prop'; +import { IPublicModelNodeChildren } from './node-children'; +import { IPublicModelComponentMeta } from './component-meta'; + +export interface IPublicModelNode { + + /** + * 节点 id + */ + id: string; + /** + * 节点标题 + */ + get title(): string | I18nData | ReactElement; + + /** + * 是否为「容器型」节点 + */ + get isContainer(): boolean; + + /** + * 是否为根节点 + */ + get isRoot(): boolean; + + /** + * 是否为空节点(无 children 或者 children 为空) + */ + get isEmpty(): boolean; + + /** + * 是否为 Page 节点 + */ + get isPage(): boolean; + + /** + * 是否为 Component 节点 + */ + get isComponent(): boolean; + + /** + * 是否为「模态框」节点 + */ + get isModal(): boolean; + + /** + * 是否为插槽节点 + */ + get isSlot(): boolean; + + /** + * 是否为父类/分支节点 + */ + get isParental(): boolean; + + /** + * 是否为叶子节点 + */ + get isLeaf(): boolean; + + /** + * 获取当前节点的锁定状态 + */ + get isLocked(): boolean; + + /** + * 下标 + */ + get index(): number; + + /** + * 图标 + */ + get icon(): IconType; + + /** + * 节点所在树的层级深度,根节点深度为 0 + */ + get zLevel(): number; + + /** + * 节点 componentName + */ + get componentName(): string; + + /** + * 节点的物料元数据 + */ + get componentMeta(): IPublicModelComponentMeta | null; + + /** + * 获取节点所属的文档模型对象 + * @returns + */ + get document(): IPublicModelDocumentModel | null; + + /** + * 获取当前节点的前一个兄弟节点 + * @returns + */ + get prevSibling(): IPublicModelNode | null; + + /** + * 获取当前节点的后一个兄弟节点 + * @returns + */ + get nextSibling(): IPublicModelNode | null; + + /** + * 获取当前节点的父亲节点 + * @returns + */ + get parent(): IPublicModelNode | null; + /** + * 获取当前节点的孩子节点模型 + * @returns + */ + get children(): IPublicModelNodeChildren | null; + + /** + * 节点上挂载的插槽节点们 + */ + get slots(): IPublicModelNode[]; + + /** + * 当前节点为插槽节点时,返回节点对应的属性实例 + */ + get slotFor(): IPublicModelProp | null; + + /** + * 返回节点的属性集 + */ + get props(): IPublicModelProps | null; + + /** + * 返回节点的属性集 + */ + get propsData(): PropsMap | PropsList | null; + + /** + * 获取符合搭建协议 - 节点 schema 结构 + */ + get schema(): NodeSchema; + + get settingEntry(): IPublicModelSettingTopEntry; + + /** + * 执行新增、删除、排序等操作 + * @param remover + * @param adder + * @param sorter + */ + mergeChildren( + remover: (node: IPublicModelNode, idx: number) => boolean, + adder: (children: IPublicModelNode[]) => any, + sorter: (firstNode: IPublicModelNode, secondNode: IPublicModelNode) => number + ): any; + + /** + * 返回节点的尺寸、位置信息 + * @returns + */ + getRect(): DOMRect | null; + + /** + * 是否有挂载插槽节点 + * @returns + */ + hasSlots(): boolean; + + /** + * 是否设定了渲染条件 + * @returns + */ + hasCondition(): boolean; + + /** + * 是否设定了循环数据 + * @returns + */ + hasLoop(): boolean; + + getVisible(): boolean; + + setVisible(flag: boolean): void; + + isConditionalVisible(): boolean | undefined; + + /** + * 设置节点锁定状态 + * @param flag + */ + lock(flag?: boolean): void; + + contains(node: IPublicModelNode): boolean; + + /** + * 获取指定 path 的属性模型实例 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @returns + */ + getProp(path: string, createIfNone: boolean): IPublicModelProp | null; + + /** + * 获取指定 path 的属性模型实例, + * 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @param createIfNone 当没有属性的时候,是否创建一个属性 + * @returns + */ + getExtraProp(path: string, createIfNone?: boolean): IPublicModelProp | null; + + /** + * 获取指定 path 的属性模型实例, + * 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @returns + */ + getExtraPropValue(path: string): any; + + /** + * 设置指定 path 的属性模型实例值 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @param value 值 + * @returns + */ + setPropValue(path: string, value: CompositeValue): void; + + /** + * 设置指定 path 的属性模型实例值 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @param value 值 + * @returns + */ + setExtraPropValue(path: string, value: CompositeValue): void; + + /** + * 导入节点数据 + * @param data + */ + importSchema(data: NodeSchema): void; + + /** + * 导出节点数据 + * @param stage + * @param options + * @returns + */ + exportSchema(stage: TransformStage, options?: any): NodeSchema; + + /** + * 在指定位置之前插入一个节点 + * @param node + * @param ref + * @param useMutator + */ + insertBefore(node: IPublicModelNode, ref?: IPublicModelNode | undefined, useMutator?: boolean): void; + + /** + * 在指定位置之后插入一个节点 + * @param node + * @param ref + * @param useMutator + */ + insertAfter(node: IPublicModelNode, ref?: IPublicModelNode | undefined, useMutator?: boolean): void; + + /** + * 替换指定节点 + * @param node 待替换的子节点 + * @param data 用作替换的节点对象或者节点描述 + * @returns + */ + replaceChild(node: IPublicModelNode, data: any): IPublicModelNode | null; + + /** + * 将当前节点替换成指定节点描述 + * @param schema + */ + replaceWith(schema: NodeSchema): any; + + /** + * 选中当前节点实例 + */ + select(): void; + + /** + * 设置悬停态 + * @param flag + */ + hover(flag: boolean): void; + + /** + * 删除当前节点实例 + */ + remove(): void; + + /** + * 设置为磁贴布局节点 + */ + set isRGLContainer(flag: boolean); + + /** + * 获取磁贴布局节点设置状态 + * @returns Boolean + */ + get isRGLContainer(); +} diff --git a/packages/types/src/shell/model/prop.ts b/packages/types/src/shell/model/prop.ts new file mode 100644 index 000000000..982d22650 --- /dev/null +++ b/packages/types/src/shell/model/prop.ts @@ -0,0 +1,59 @@ +import { TransformStage } from '../../transform-stage'; +import { CompositeValue } from '../../value-type'; +import { IPublicModelNode } from './node'; + +export interface IPublicModelProp { + /** + * id + */ + get id(): string; + + /** + * key 值 + */ + get key(): string | number | undefined; + + /** + * 返回当前 prop 的路径 + */ + get path(): any[]; + + /** + * 返回所属的节点实例 + */ + get node(): IPublicModelNode | null; + + /** + * return the slot node (only if the current prop represents a slot) + */ + get slotNode(): IPublicModelNode | null; + + /** + * judge if it is a prop or not + */ + get isProp(): boolean; + + /** + * 设置值 + * @param val + */ + setValue(val: CompositeValue): void; + + /** + * 获取值 + * @returns + */ + getValue(): any; + + /** + * 移除值 + */ + remove(): void; + + /** + * 导出值 + * @param stage + * @returns + */ + exportSchema(stage: TransformStage): CompositeValue; +} diff --git a/packages/types/src/shell/model/props.ts b/packages/types/src/shell/model/props.ts new file mode 100644 index 000000000..09a5ec4e2 --- /dev/null +++ b/packages/types/src/shell/model/props.ts @@ -0,0 +1,82 @@ +import { CompositeValue } from '../../value-type'; +import { IPublicModelNode } from './node'; +import { IPublicModelProp } from './prop'; + +export interface IPublicModelProps { + /** + * id + */ + get id(): string; + + /** + * 返回当前 props 的路径 + */ + get path(): any[]; + + /** + * 返回所属的 node 实例 + */ + get node(): IPublicModelNode | null; + + /** + * 获取指定 path 的属性模型实例 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @returns + */ + getProp(path: string): IPublicModelProp | null; + + /** + * 获取指定 path 的属性模型实例值 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @returns + */ + getPropValue(path: string): any; + + /** + * 获取指定 path 的属性模型实例, + * 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @returns + */ + getExtraProp(path: string): IPublicModelProp | null; + + /** + * 获取指定 path 的属性模型实例值 + * 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @returns + */ + getExtraPropValue(path: string): any; + + /** + * 设置指定 path 的属性模型实例值 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @param value 值 + * @returns + */ + setPropValue(path: string, value: CompositeValue): void; + + /** + * 设置指定 path 的属性模型实例值 + * @param path 属性路径,支持 a / a.b / a.0 等格式 + * @param value 值 + * @returns + */ + setExtraPropValue(path: string, value: CompositeValue): void; + + /** + * test if the specified key is existing or not. + * @param key + * @returns + */ + has(key: string): boolean; + + /** + * add a key with given value + * @param value + * @param key + * @returns + */ + add(value: CompositeValue, key?: string | number | undefined): any; + +} diff --git a/packages/types/src/shell/model/selection.ts b/packages/types/src/shell/model/selection.ts new file mode 100644 index 000000000..43a5ee494 --- /dev/null +++ b/packages/types/src/shell/model/selection.ts @@ -0,0 +1,65 @@ +import { IPublicModelNode } from './node'; + +export interface IPublicModelSelection { + + /** + * 返回选中的节点 id + */ + get selected(): string[]; + + /** + * return selected Node instance + */ + get node(): IPublicModelNode | null; + + /** + * 选中指定节点(覆盖方式) + * @param id + */ + select(id: string): void; + + /** + * 批量选中指定节点们 + * @param ids + */ + selectAll(ids: string[]): void; + + /** + * 移除选中的指定节点 + * @param id + */ + remove(id: string): void; + + /** + * 清除所有选中节点 + */ + clear(): void; + + /** + * 判断是否选中了指定节点 + * @param id + * @returns + */ + has(id: string): boolean; + + /** + * 选中指定节点(增量方式) + * @param id + */ + add(id: string): void; + + /** + * 获取选中的节点实例 + * @returns + */ + getNodes(): Array; + + /** + * 获取选区的顶层节点 + * for example: + * getNodes() returns [A, subA, B], then + * getTopNodes() will return [A, B], subA will be removed + * @returns + */ + getTopNodes(): Array; +} diff --git a/packages/types/src/shell/model/setting-prop-entry.ts b/packages/types/src/shell/model/setting-prop-entry.ts new file mode 100644 index 000000000..90c75a444 --- /dev/null +++ b/packages/types/src/shell/model/setting-prop-entry.ts @@ -0,0 +1,188 @@ +import { CustomView, SetterType } from '../../setter-config'; +import { CompositeValue } from '../../value-type'; +import { FieldExtraProps, FieldConfig } from '../../field-config'; +import { ISetValueOptions } from '../../designer'; +import { IPublicModelNode } from './node'; +import { IPublicModelComponentMeta } from './component-meta'; +import { IPublicModelSettingTopEntry } from './setting-top-entry'; + +export interface IPublicModelSettingPropEntry { + /** + * 获取设置属性的 isGroup + */ + get isGroup(): boolean; + + /** + * 获取设置属性的 id + */ + get id(): string; + + /** + * 获取设置属性的 name + */ + get name(): string | number; + + /** + * 获取设置属性的 key + */ + get key(): string | number; + + /** + * 获取设置属性的 path + */ + get path(): any[]; + + /** + * 获取设置属性的 title + */ + get title(): any; + + /** + * 获取设置属性的 setter + */ + get setter(): SetterType | null; + + /** + * 获取设置属性的 expanded + */ + get expanded(): boolean; + + /** + * 获取设置属性的 extraProps + */ + get extraProps(): FieldExtraProps; + + get props(): IPublicModelSettingTopEntry; + + /** + * 获取设置属性对应的节点实例 + */ + get node(): IPublicModelNode | null; + + /** + * 获取设置属性的父设置属性 + */ + get parent(): IPublicModelSettingPropEntry; + + /** + * 获取顶级设置属性 + */ + get top(): IPublicModelSettingTopEntry; + + /** + * 是否是 SettingField 实例 + */ + get isSettingField(): boolean; + + /** + * componentMeta + */ + get componentMeta(): IPublicModelComponentMeta | null; + + /** + * 获取设置属性的 items + */ + get items(): Array; + + /** + * 设置 key 值 + * @param key + */ + setKey(key: string | number): void; + + /** + * 设置值 + * @param val 值 + */ + setValue(val: CompositeValue, extraOptions?: ISetValueOptions): void; + + /** + * 设置子级属性值 + * @param propName 子属性名 + * @param value 值 + */ + setPropValue(propName: string | number, value: any): void; + + /** + * 清空指定属性值 + * @param propName + */ + clearPropValue(propName: string | number): void; + + /** + * 获取配置的默认值 + * @returns + */ + getDefaultValue(): any; + + /** + * 获取值 + * @returns + */ + getValue(): any; + + /** + * 获取子级属性值 + * @param propName 子属性名 + * @returns + */ + getPropValue(propName: string | number): any; + + /** + * 获取顶层附属属性值 + */ + getExtraPropValue(propName: string): any; + + /** + * 设置顶层附属属性值 + */ + setExtraPropValue(propName: string, value: any): void; + + /** + * 获取设置属性集 + * @returns + */ + getProps(): IPublicModelSettingTopEntry; + + /** + * 是否绑定了变量 + * @returns + */ + isUseVariable(): boolean; + + /** + * 设置绑定变量 + * @param flag + */ + setUseVariable(flag: boolean): void; + + /** + * 创建一个设置 field 实例 + * @param config + * @returns + */ + createField(config: FieldConfig): IPublicModelSettingPropEntry; + + /** + * 获取值,当为变量时,返回 mock + * @returns + */ + getMockOrValue(): any; + + /** + * 销毁当前 field 实例 + */ + purge(): void; + + /** + * 移除当前 field 实例 + */ + remove(): void; + + /** + * 设置 autorun + * @param action + * @returns + */ + onEffect(action: () => void): () => void; +} diff --git a/packages/types/src/shell/model/setting-top-entry.ts b/packages/types/src/shell/model/setting-top-entry.ts new file mode 100644 index 000000000..5a7726346 --- /dev/null +++ b/packages/types/src/shell/model/setting-top-entry.ts @@ -0,0 +1,30 @@ +import { IPublicModelNode } from './node'; +import { IPublicModelSettingPropEntry } from './setting-prop-entry'; + +export interface IPublicModelSettingTopEntry { + /** + * 返回所属的节点实例 + */ + get node(): IPublicModelNode | null; + + /** + * 获取子级属性对象 + * @param propName + * @returns + */ + get(propName: string | number): IPublicModelSettingPropEntry; + + /** + * 获取指定 propName 的值 + * @param propName + * @returns + */ + getPropValue(propName: string | number): any; + + /** + * 设置指定 propName 的值 + * @param propName + * @param value + */ + setPropValue(propName: string | number, value: any): void; +} diff --git a/packages/types/src/title.ts b/packages/types/src/title.ts index a4ac36614..bba02c489 100644 --- a/packages/types/src/title.ts +++ b/packages/types/src/title.ts @@ -1,5 +1,5 @@ import { ReactElement, ReactNode } from 'react'; -import { I18nData, isI18nData } from './i18n'; +import { I18nData } from './i18n'; import { TipContent } from './tip'; import { IconType } from './icon'; @@ -29,16 +29,4 @@ export interface TitleConfig { className?: string; } -export type TitleContent = string | I18nData | ReactElement | TitleConfig; - -function isPlainObject(value: any): value is Record { - if (typeof value !== 'object') { - return false; - } - const proto = Object.getPrototypeOf(value); - return proto === Object.prototype || proto === null || Object.getPrototypeOf(proto) === null; -} - -export function isTitleConfig(obj: any): obj is TitleConfig { - return isPlainObject(obj) && !isI18nData(obj); -} +export type TitleContent = string | I18nData | ReactElement | TitleConfig; \ No newline at end of file diff --git a/packages/types/src/value-type.ts b/packages/types/src/value-type.ts index a266cb9f3..81358fda1 100644 --- a/packages/types/src/value-type.ts +++ b/packages/types/src/value-type.ts @@ -126,30 +126,4 @@ export type CompositeValue = export type CompositeArray = CompositeValue[]; export interface CompositeObject { [key: string]: CompositeValue; -} - -/** - * 为了避免把 { type: 'JSExpression', extType: 'function' } 误判为表达式,故增加如下逻辑。 - * - * 引擎中关于函数的表达: - * 开源版本:{ type: 'JSFunction', source: '', value: '' } - * 内部版本:{ type: 'JSExpression', source: '', value: '', extType: 'function' } - * 能力是对标的,不过开源的 react-renderer 只认识第一种,而内部只识别第二种(包括 Java 代码、RE)。 - * @param data - * @returns - */ -export function isJSExpression(data: any): data is JSExpression { - return data && data.type === 'JSExpression' && data.extType !== 'function'; -} - -export function isJSFunction(x: any): x is JSFunction { - return typeof x === 'object' && x && x.type === 'JSFunction'; -} - -export function isJSSlot(data: any): data is JSSlot { - return data && data.type === 'JSSlot'; -} - -export function isJSBlock(data: any): data is JSBlock { - return data && data.type === 'JSBlock'; -} +} \ No newline at end of file diff --git a/packages/utils/package.json b/packages/utils/package.json index 5555f8457..2b1b75fb1 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -24,7 +24,7 @@ "@alib/build-scripts": "^0.1.18", "@types/node": "^13.7.1", "@types/react": "^16", - "build-plugin-component": "^0.2.10" + "build-plugin-component": "^1.0.0" }, "publishConfig": { "access": "public", diff --git a/packages/utils/src/check-types/index.ts b/packages/utils/src/check-types/index.ts new file mode 100644 index 000000000..d4dfa6f32 --- /dev/null +++ b/packages/utils/src/check-types/index.ts @@ -0,0 +1,16 @@ +// 此模块存放 @alilc/lowcode-types 中类型相关判断工具 +export * from './is-action-content-object'; +export * from './is-custom-view'; +export * from './is-dom-text'; +export * from './is-dynamic-setter'; +export * from './is-i18n-data'; +export * from './is-jsblock'; +export * from './is-jsexpression'; +export * from './is-isfunction'; +export * from './is-jsslot'; +export * from './is-lowcode-component-type'; +export * from './is-node-schema'; +export * from './is-procode-component-type'; +export * from './is-project-schema'; +export * from './is-setter-config'; +export * from './is-title-config'; \ No newline at end of file diff --git a/packages/utils/src/check-types/is-action-content-object.ts b/packages/utils/src/check-types/is-action-content-object.ts new file mode 100644 index 000000000..917f11ee3 --- /dev/null +++ b/packages/utils/src/check-types/is-action-content-object.ts @@ -0,0 +1,6 @@ +import { ActionContentObject } from '@alilc/lowcode-types'; + + +export function isActionContentObject(obj: any): obj is ActionContentObject { + return obj && typeof obj === 'object'; +} diff --git a/packages/utils/src/check-types/is-custom-view.ts b/packages/utils/src/check-types/is-custom-view.ts new file mode 100644 index 000000000..6f098a921 --- /dev/null +++ b/packages/utils/src/check-types/is-custom-view.ts @@ -0,0 +1,8 @@ +import { isValidElement } from 'react'; +import { isReactComponent } from '../is-react'; +import { CustomView } from '@alilc/lowcode-types'; + + +export function isCustomView(obj: any): obj is CustomView { + return obj && (isValidElement(obj) || isReactComponent(obj)); +} diff --git a/packages/utils/src/check-types/is-dom-text.ts b/packages/utils/src/check-types/is-dom-text.ts new file mode 100644 index 000000000..b5c778517 --- /dev/null +++ b/packages/utils/src/check-types/is-dom-text.ts @@ -0,0 +1,5 @@ +import { DOMText } from '@alilc/lowcode-types'; + +export function isDOMText(data: any): data is DOMText { + return typeof data === 'string'; +} diff --git a/packages/utils/src/check-types/is-dynamic-setter.ts b/packages/utils/src/check-types/is-dynamic-setter.ts new file mode 100644 index 000000000..2e0ac63b9 --- /dev/null +++ b/packages/utils/src/check-types/is-dynamic-setter.ts @@ -0,0 +1,7 @@ +import { isReactClass } from '../is-react'; +import { DynamicSetter } from '@alilc/lowcode-types'; + + +export function isDynamicSetter(obj: any): obj is DynamicSetter { + return obj && typeof obj === 'function' && !isReactClass(obj); +} diff --git a/packages/utils/src/check-types/is-i18n-data.ts b/packages/utils/src/check-types/is-i18n-data.ts new file mode 100644 index 000000000..d315a77c4 --- /dev/null +++ b/packages/utils/src/check-types/is-i18n-data.ts @@ -0,0 +1,7 @@ +import { I18nData } from '@alilc/lowcode-types'; + +// type checks + +export function isI18nData(obj: any): obj is I18nData { + return obj && obj.type === 'i18n'; +} diff --git a/packages/utils/src/check-types/is-isfunction.ts b/packages/utils/src/check-types/is-isfunction.ts new file mode 100644 index 000000000..75506d1ff --- /dev/null +++ b/packages/utils/src/check-types/is-isfunction.ts @@ -0,0 +1,5 @@ +import { JSFunction } from '@alilc/lowcode-types'; + +export function isJSFunction(x: any): x is JSFunction { + return typeof x === 'object' && x && x.type === 'JSFunction'; +} diff --git a/packages/utils/src/check-types/is-jsblock.ts b/packages/utils/src/check-types/is-jsblock.ts new file mode 100644 index 000000000..b19fb9a60 --- /dev/null +++ b/packages/utils/src/check-types/is-jsblock.ts @@ -0,0 +1,5 @@ +import { JSBlock } from '@alilc/lowcode-types'; + +export function isJSBlock(data: any): data is JSBlock { + return data && data.type === 'JSBlock'; +} diff --git a/packages/utils/src/check-types/is-jsexpression.ts b/packages/utils/src/check-types/is-jsexpression.ts new file mode 100644 index 000000000..969b72cd4 --- /dev/null +++ b/packages/utils/src/check-types/is-jsexpression.ts @@ -0,0 +1,15 @@ +import { JSExpression } from '@alilc/lowcode-types'; + +/** + * 为了避免把 { type: 'JSExpression', extType: 'function' } 误判为表达式,故增加如下逻辑。 + * + * 引擎中关于函数的表达: + * 开源版本:{ type: 'JSFunction', source: '', value: '' } + * 内部版本:{ type: 'JSExpression', source: '', value: '', extType: 'function' } + * 能力是对标的,不过开源的 react-renderer 只认识第一种,而内部只识别第二种(包括 Java 代码、RE)。 + * @param data + * @returns + */ +export function isJSExpression(data: any): data is JSExpression { + return data && data.type === 'JSExpression' && data.extType !== 'function'; +} diff --git a/packages/utils/src/check-types/is-jsslot.ts b/packages/utils/src/check-types/is-jsslot.ts new file mode 100644 index 000000000..bc7c3576f --- /dev/null +++ b/packages/utils/src/check-types/is-jsslot.ts @@ -0,0 +1,5 @@ +import { JSSlot } from '@alilc/lowcode-types'; + +export function isJSSlot(data: any): data is JSSlot { + return data && data.type === 'JSSlot'; +} diff --git a/packages/utils/src/check-types/is-lowcode-component-type.ts b/packages/utils/src/check-types/is-lowcode-component-type.ts new file mode 100644 index 000000000..7c6978378 --- /dev/null +++ b/packages/utils/src/check-types/is-lowcode-component-type.ts @@ -0,0 +1,7 @@ +import { isProCodeComponentType } from './is-procode-component-type'; +import { ComponentMap, LowCodeComponentType } from '@alilc/lowcode-types'; + + +export function isLowCodeComponentType(desc: ComponentMap): desc is LowCodeComponentType { + return !isProCodeComponentType(desc); +} diff --git a/packages/utils/src/check-types/is-node-schema.ts b/packages/utils/src/check-types/is-node-schema.ts new file mode 100644 index 000000000..2552a920f --- /dev/null +++ b/packages/utils/src/check-types/is-node-schema.ts @@ -0,0 +1,5 @@ +import { NodeSchema } from '@alilc/lowcode-types'; + +export function isNodeSchema(data: any): data is NodeSchema { + return data && data.componentName; +} diff --git a/packages/utils/src/check-types/is-procode-component-type.ts b/packages/utils/src/check-types/is-procode-component-type.ts new file mode 100644 index 000000000..53c33c6c9 --- /dev/null +++ b/packages/utils/src/check-types/is-procode-component-type.ts @@ -0,0 +1,6 @@ +import { ComponentMap, ProCodeComponentType } from '@alilc/lowcode-types'; + + +export function isProCodeComponentType(desc: ComponentMap): desc is ProCodeComponentType { + return 'package' in desc; +} diff --git a/packages/utils/src/check-types/is-project-schema.ts b/packages/utils/src/check-types/is-project-schema.ts new file mode 100644 index 000000000..9dd6d4961 --- /dev/null +++ b/packages/utils/src/check-types/is-project-schema.ts @@ -0,0 +1,5 @@ +import { ProjectSchema } from '@alilc/lowcode-types'; + +export function isProjectSchema(data: any): data is ProjectSchema { + return data && data.componentsTree; +} diff --git a/packages/utils/src/check-types/is-setter-config.ts b/packages/utils/src/check-types/is-setter-config.ts new file mode 100644 index 000000000..7176a5968 --- /dev/null +++ b/packages/utils/src/check-types/is-setter-config.ts @@ -0,0 +1,7 @@ +import { SetterConfig } from '@alilc/lowcode-types'; +import { isCustomView } from './is-custom-view'; + + +export function isSetterConfig(obj: any): obj is SetterConfig { + return obj && typeof obj === 'object' && 'componentName' in obj && !isCustomView(obj); +} diff --git a/packages/utils/src/check-types/is-title-config.ts b/packages/utils/src/check-types/is-title-config.ts new file mode 100644 index 000000000..2d5088dc0 --- /dev/null +++ b/packages/utils/src/check-types/is-title-config.ts @@ -0,0 +1,8 @@ +import { isI18nData } from './is-i18n-data'; +import { isPlainObject } from '../is-plain-object'; +import { TitleConfig } from '@alilc/lowcode-types'; + + +export function isTitleConfig(obj: any): obj is TitleConfig { + return isPlainObject(obj) && !isI18nData(obj); +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 4f47402a1..1dd7168fd 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -27,3 +27,4 @@ export * from './clone-enumerable-property'; export * from './logger'; export * as css from './css-helper'; export { transactionManager } from './transaction-manager'; +export * from './check-types'; diff --git a/packages/utils/src/schema.ts b/packages/utils/src/schema.ts index 1580003d2..0bb124852 100644 --- a/packages/utils/src/schema.ts +++ b/packages/utils/src/schema.ts @@ -1,4 +1,5 @@ -import { isJSBlock, isJSSlot, ActivityType, NodeSchema, PageSchema, RootSchema } from '@alilc/lowcode-types'; +import { ActivityType, NodeSchema, RootSchema } from '@alilc/lowcode-types'; +import { isJSBlock, isJSSlot } from './check-types'; import { isVariable } from './misc'; import { isPlainObject } from './is-plain-object'; diff --git a/packages/workspace/package.json b/packages/workspace/package.json index 54829fb8f..3605f0c3a 100644 --- a/packages/workspace/package.json +++ b/packages/workspace/package.json @@ -40,8 +40,8 @@ "@types/react": "^16", "@types/react-dom": "^16", "babel-jest": "^26.5.2", - "build-plugin-component": "^0.2.10", - "build-scripts-config": "^0.1.8", + "build-plugin-component": "^1.0.0", + "build-scripts-config": "^3.0.3", "jest": "^26.6.3", "lodash": "^4.17.20", "moment": "^2.29.1",