From a37d6550da0f0919917b7d21a3a94af488b119fc Mon Sep 17 00:00:00 2001 From: gengyang Date: Wed, 1 Apr 2020 10:38:12 +0800 Subject: [PATCH 01/21] fix: fix bug of missing ajv --- packages/material-parser/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/material-parser/package.json b/packages/material-parser/package.json index dab853438..a978e307f 100644 --- a/packages/material-parser/package.json +++ b/packages/material-parser/package.json @@ -13,8 +13,6 @@ "@types/js-yaml": "^3.12.2", "@types/lodash": "^4.14.149", "@types/semver": "^7.1.0", - "ajv": "^6.10.2", - "better-ajv-errors": "^0.6.4", "globby": "^10.0.1", "jest": "^24.8.0", "jest-watch-typeahead": "^0.3.1", @@ -48,6 +46,7 @@ "@babel/parser": "^7.8.4", "@babel/traverse": "^7.8.4", "@babel/types": "^7.8.3", + "ajv": "^6.12.0", "ast-types": "^0.13.3", "cross-spawn-promise": "^0.10.2", "debug": "^4.1.1", From 5d8000a991f4776ce9398ce938fcb0463294ce7e Mon Sep 17 00:00:00 2001 From: gengyang Date: Wed, 1 Apr 2020 11:29:18 +0800 Subject: [PATCH 02/21] Publish - @ali/lowcode-material-parser@0.9.1 --- packages/material-parser/CHANGELOG.md | 11 +++++++++++ packages/material-parser/package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/material-parser/CHANGELOG.md b/packages/material-parser/CHANGELOG.md index cc9d6a4cf..0bf74fb7e 100644 --- a/packages/material-parser/CHANGELOG.md +++ b/packages/material-parser/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.9.0...@ali/lowcode-material-parser@0.9.1) (2020-04-01) + + +### Bug Fixes + +* fix bug of missing ajv ([a37d655](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a37d655)) + + + + + # [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.4...@ali/lowcode-material-parser@0.9.0) (2020-03-31) diff --git a/packages/material-parser/package.json b/packages/material-parser/package.json index a978e307f..bd59b4ac4 100644 --- a/packages/material-parser/package.json +++ b/packages/material-parser/package.json @@ -1,6 +1,6 @@ { "name": "@ali/lowcode-material-parser", - "version": "0.9.0", + "version": "0.9.1", "description": "material parser for Ali lowCode engine", "main": "lib/index.js", "files": [ From de4e0be01d51ff21350ac331476c147fc542dd00 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Wed, 1 Apr 2020 13:16:44 +0800 Subject: [PATCH 03/21] =?UTF-8?q?chore:=20=E4=BF=AE=E6=94=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3registerLayout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/demo/src/app/index.ts | 2 +- packages/runtime/package.json | 2 +- packages/runtime/src/core/container.ts | 11 +++++++- packages/runtime/src/core/index.ts | 6 ++--- packages/runtime/src/core/provider/index.ts | 30 ++++++++++++++++++--- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/packages/demo/src/app/index.ts b/packages/demo/src/app/index.ts index f4df24866..d78f6211a 100644 --- a/packages/demo/src/app/index.ts +++ b/packages/demo/src/app/index.ts @@ -8,7 +8,7 @@ import Preview from './plugins/provider'; app.registerRenderer(Renderer); // 注册布局组件,可注册多个 -app.registerLayout('BasicLayout', BasicLayout); +app.registerLayout(BasicLayout, { componentName: 'BasicLayout' }); // 注册页面 Loading app.registerLoading(FusionLoading); diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 4b99d22eb..2236fa63c 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@ali/lowcode-runtime", - "version": "0.8.6", + "version": "0.8.7", "description": "Runtime for Ali lowCode engine", "files": [ "es", diff --git a/packages/runtime/src/core/container.ts b/packages/runtime/src/core/container.ts index c6b2bfc53..677fd32ad 100644 --- a/packages/runtime/src/core/container.ts +++ b/packages/runtime/src/core/container.ts @@ -1,6 +1,11 @@ import { ReactType } from 'react'; import Provider from './provider'; +export interface ILayoutOptions { + componentName?: string; + props?: any; +} + export default class Container { private renderer: ReactType | null = null; private layouts: { [key: string]: ReactType } = {}; @@ -11,7 +16,11 @@ export default class Container { this.renderer = renderer; } - registerLayout(componentName: string, Layout: ReactType): any { + registerLayout(Layout: ReactType, options: ILayoutOptions): any { + if (!options) { + return; + } + const { componentName } = options; if (!componentName || !Layout) { return; } diff --git a/packages/runtime/src/core/index.ts b/packages/runtime/src/core/index.ts index bd1758b52..076fbc2ce 100644 --- a/packages/runtime/src/core/index.ts +++ b/packages/runtime/src/core/index.ts @@ -1,5 +1,5 @@ import { ReactType } from 'react'; -import Container from './container'; +import Container, { ILayoutOptions } from './container'; import run from './run'; class App { @@ -17,8 +17,8 @@ class App { this.container.registerRenderer(renderer); } - registerLayout(componentName: string, Layout: ReactType): any { - this.container.registerLayout(componentName, Layout); + registerLayout(Layout: ReactType, options: ILayoutOptions): any { + this.container.registerLayout(Layout, options); } registerLoading(component: ReactType) { diff --git a/packages/runtime/src/core/provider/index.ts b/packages/runtime/src/core/provider/index.ts index 77f1d388d..fb3512c68 100644 --- a/packages/runtime/src/core/provider/index.ts +++ b/packages/runtime/src/core/provider/index.ts @@ -27,7 +27,7 @@ interface IHistoryConfig { basement?: string; } -interface IAppData { +export interface IAppData { history?: HistoryMode; layout?: ILayoutConfig; routes?: IRouterConfig; @@ -36,6 +36,7 @@ interface IAppData { componentsMap?: IComponentMap[]; utils?: IUtils; constants?: IConstants; + i18n?: I18n; } export interface ComponentProps { @@ -92,6 +93,13 @@ export interface ComponentModel { loopArgs?: string[]; } +export interface I18n { + 'zh-CN': { [key: string]: string }; + 'en-US': { [key: string]: string }; +} + +type Locale = 'zh-CN' | 'en-US'; + // export interface IProvider { // init?(): void; // getAppData?(appkey: string): Promise; @@ -109,6 +117,7 @@ export default class Provider { private componentsMap: IComponentMap[] = []; private history: HistoryMode = 'hash'; private containerId = ''; + private i18n: I18n | null = null; private lazyElementsMap: { [key: string]: any } = {}; constructor() { @@ -118,15 +127,16 @@ export default class Provider { async(): Promise { return new Promise(async (resolve, reject) => { try { - const appData = await this.getAppData(); + const appData: IAppData = await this.getAppData(); if (!appData) { return; } - const { history, layout, routes, containerId, components, componentsMap, utils, constants } = appData; + const { history, layout, routes, containerId, components, componentsMap, utils, constants, i18n } = appData; this.setHistory(history); this.setLayoutConfig(layout); this.setRouterConfig(routes); this.setContainerId(containerId); + this.setI18n(i18n); this.registerComponents(components); this.registerComponentsMap(componentsMap); this.registerUtils(utils); @@ -220,6 +230,13 @@ export default class Provider { this.containerId = id; } + setI18n(i18n: I18n) { + if (!i18n) { + return; + } + this.i18n = i18n; + } + setlazyElement(pageId: string, cache: any) { if (!pageId || !cache) { return; @@ -281,6 +298,13 @@ export default class Provider { return this.containerId; } + getI18n(locale?: Locale) { + if (!this.i18n) { + return; + } + return locale ? this.i18n[locale] : this.i18n; + } + getlazyElement(pageId: string) { if (!pageId) { return; From ee55d43fd97c7d5d365996115e0ec396c3d69cde Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Wed, 1 Apr 2020 13:18:45 +0800 Subject: [PATCH 04/21] chore: @ali/lowcode-runtime@0.8.8 --- packages/runtime/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 2236fa63c..862cc38d9 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@ali/lowcode-runtime", - "version": "0.8.7", + "version": "0.8.8", "description": "Runtime for Ali lowCode engine", "files": [ "es", From f15aefd88137667af94a0e83e2d0e8c6c5f3871e Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Wed, 1 Apr 2020 13:38:17 +0800 Subject: [PATCH 05/21] chore: @ali/lowcode-runtime@0.8.9 --- packages/runtime/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 862cc38d9..191b3e633 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@ali/lowcode-runtime", - "version": "0.8.8", + "version": "0.8.9", "description": "Runtime for Ali lowCode engine", "files": [ "es", From a5eb62dbb0579146d52c6c0a2b1eed572c43d390 Mon Sep 17 00:00:00 2001 From: "jianfang.rjf" Date: Thu, 2 Apr 2020 20:25:51 +0800 Subject: [PATCH 06/21] feat: mixin-setter get all setter --- packages/demo/public/assets.json | 15 +- packages/setters/src/expression-setter.tsx | 375 -------------- packages/setters/src/function-setter.tsx | 471 ------------------ packages/setters/src/index.scss | 93 ---- packages/setters/src/index.tsx | 4 + packages/setters/src/mixin-setter.tsx | 301 ----------- packages/setters/src/mixin-setter/index.scss | 117 ----- packages/setters/src/mixin-setter/index.tsx | 225 ++------- .../src/mixin-setter/locale/snippets.js | 242 --------- 9 files changed, 58 insertions(+), 1785 deletions(-) delete mode 100644 packages/setters/src/expression-setter.tsx delete mode 100644 packages/setters/src/function-setter.tsx delete mode 100644 packages/setters/src/index.scss delete mode 100644 packages/setters/src/mixin-setter.tsx delete mode 100644 packages/setters/src/mixin-setter/locale/snippets.js diff --git a/packages/demo/public/assets.json b/packages/demo/public/assets.json index aceef84ad..5e664fa43 100644 --- a/packages/demo/public/assets.json +++ b/packages/demo/public/assets.json @@ -1053,6 +1053,14 @@ "name": "maxTagCount", "title": "最多显示多少个 tag", "setter": "ExpressionSetter" + }, { + "name": "color", + "title": "颜色选择", + "setter": "ColorSetter" + }, { + "name": "json", + "title": "JSON设置", + "setter": "JsonSetter" }, { "name": "MixinSetter", "placeholder": "混合", @@ -1081,11 +1089,14 @@ }, { "label": "左", "value": "l" - }] + }], + "defaultValue": "l" } }, { "name": "NumberSetter", - "props": {} + "props": { + "defaultValue": 5 + } }, { "name": "BoolSetter", "props": {} diff --git a/packages/setters/src/expression-setter.tsx b/packages/setters/src/expression-setter.tsx deleted file mode 100644 index 1e572a084..000000000 --- a/packages/setters/src/expression-setter.tsx +++ /dev/null @@ -1,375 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { Select, Balloon } from '@alife/next'; -import * as acorn from 'acorn'; - -import { isJSExpression, generateI18n } from './locale/utils'; -import zhCN from './locale/zh-CN'; - -const { Option, AutoComplete } = Select; -const { Tooltip } = Balloon; -const helpMap = { - this: '容器上下文对象', - 'this.state': '容器的state', - 'this.props': '容器的props', - 'this.context': '容器的context', - 'this.page': '页面上下文对象', - 'this.component': '组件上下文对象', - 'this.constants': '应用常量对象', - 'this.utils': '应用工具对象', - 'this.dataSourceMap': '容器数据源Map', - 'this.field': '表单Field对象', -}; - -export default class ExpressionView extends PureComponent { - static displayName = 'Expression'; - static propTypes = { - context: PropTypes.object, - dataSource: PropTypes.array, - locale: PropTypes.string, - messages: PropTypes.object, - onChange: PropTypes.func, - placeholder: PropTypes.string, - value: PropTypes.string, - }; - static defaultProps = { - context: {}, - dataSource: [], - locale: 'zh-CN', - messages: zhCN, - onChange: () => {}, - placeholder: '', - value: '', - }; - expression: React.RefObject; - i18n: any; - t: void; - $input: any; - listenerFun: (event: any) => void; - - static getInitValue(val: { value: any; match: (arg0: RegExp) => any }) { - if (isJSExpression(val)) { - if (typeof val === 'object') { - return val.value; - } else if (typeof val === 'string') { - let arr = val.match(/^\{\{(.*?)\}\}$/); - if (arr) return arr[1]; - } - } - return val; - } - constructor(props: Readonly<{}>) { - super(props); - this.expression = React.createRef(); - this.i18n = generateI18n(props.locale, props.messages); - this.state = { - value: ExpressionView.getInitValue(props.value), - context: props.context || {}, - dataSource: props.dataSource || [], - }; - } - static getDerivedStateFromProps(props: { value: any }, state: { preValue: any }) { - let curValue = ExpressionView.getInitValue(props.value); - if (curValue !== state.preValue) { - return { - preValue: curValue, - value: curValue, - }; - } - return null; - } - onChange(value: string, actionType: string) { - let realInputValue = value; - let realDataSource = null; - const cursorIndex = this.getInputCursorPosition(); - let nextCursorIndex: number; - //更新值 - if (actionType === 'itemClick' || actionType === 'enter') { - let curValue = this.state.value; - if (curValue) { - //如果是非.结束,则替换当前这个变量; - let preStr = curValue.substr(0, cursorIndex); - let nextStr = curValue.substr(cursorIndex); - let preArr = preStr.split('.'); - let preArrLen = preArr.length; - let tarPreStr = ''; - if (!preArr[preArrLen - 1]) { - //如果是.结束,则增加到.后面 - if (preArr[preArrLen - 2] === 'this') { - preArr = preArr.slice(0, preArrLen - 2); - preArr.push(value); - tarPreStr = preArr.join('.'); - } else { - tarPreStr = preStr + value; - } - } else { - if (preArr[preArrLen - 2] === 'this') { - preArr = preArr.slice(0, preArrLen - 2); - } else { - preArr = preArr.slice(0, preArrLen - 1); - } - preArr.push(value); - tarPreStr = preArr.join('.'); - } - realInputValue = tarPreStr + nextStr; - realDataSource = this.getDataSource(tarPreStr + '.') || []; - nextCursorIndex = tarPreStr.length; - } - } else { - let tarPreStr = value.substr(0, cursorIndex); - if (tarPreStr) { - let lastChar = tarPreStr.charAt(tarPreStr.length - 1); - if (lastChar === '.') { - realDataSource = this.getDataSource(tarPreStr) || []; - } else { - realDataSource = this.getDataSource(tarPreStr + '.'); - } - } else { - realDataSource = this.getDataSource('this.'); - } - } - //更新数据源 - let newState = { - value: realInputValue, - }; - if (realDataSource !== null) newState.dataSource = realDataSource; - this.setState(newState, () => { - nextCursorIndex && this.setInputCursorPosition(nextCursorIndex); - }); - //默认加上变量表达式 - this.t && clearTimeout(this.t); - this.t = setTimeout(() => { - const { onChange } = this.props; - // realInputValue = realInputValue ? `{{${realInputValue}}}` : undefined; - onChange && - onChange({ - type: 'JSExpression', - value: realInputValue, - }); - }, 300); - } - - /** - * 获取AutoComplete数据源 - * @param {String} - * @return {Array} - */ - getDataSource(tempStr: string): Array { - if (tempStr === '' || /[^\w\.]$/.test(tempStr)) { - return this.getDataSource('this.') || []; - } else if (/\w\.$/.test(tempStr)) { - let currentField = this.getCurrentFiled(tempStr); - if (!currentField) return null; - let tempKeys = this.getObjectKeys(currentField.str); - tempKeys = this.getContextKeys(tempKeys); - if (!tempKeys) return null; - //给默认情况增加this - if (tempStr === 'this.') { - tempKeys = tempKeys.map((item: string) => { - return 'this.' + item; - }); - tempKeys.unshift('this'); - } - return tempKeys; - } else if (/\.$/.test(tempStr)) { - return []; - } else { - return null; - } - } - - /** - * 获取光标前的对象字符串,语法解析获取对象字符串 - * @param {String} str 模板字符串 - * @return {String} 光标前的对象字符串 - */ - getCurrentFiled(str: string | any[]) { - str += 'x'; //.后面加一个x字符,便于acorn解析 - try { - let astTree = acorn.parse(str); - let right = astTree.body[0].expression.right || astTree.body[0].expression; - if (right.type === 'MemberExpression') { - let { start, end } = right; - str = str.slice(start, end); - return { str, start, end }; - } - } catch (e) { - return null; - } - } - - /** - * 获取输入的上下文信息 - * @param {Array} - * @return {Array} - */ - getContextKeys(keys: any) { - // let context = {}; - // const { appHelper } = this.context; - // const activeKey = appHelper && appHelper.activeKey; - // if (!activeKey) return; - // const activeCtx = appHelper.schemaHelper.compCtxMap && appHelper.schemaHelper.compCtxMap[activeKey]; - // if (!activeCtx) return null; - // let __self = activeCtx; - // if (keys && keys.length > 1) { - // keys.shift(0); - // let path = '/' + keys.join('/'); - // path = path.replace(/[\[\]]/g, '/'); - // context = jsonuri.get(__self, path); - // if (context && typeof context === 'object') { - // return this.filterKey(context); - // } - // } else if (keys && keys[0] === 'this') { - // return this.filterKey(__self); - // } - // return null; - return ['page', 'component']; - } - - /*过滤key */ - filterKey(obj: any) { - let filterKeys = [ - 'reloadDataSource', - 'REACT_HOT_LOADER_RENDERED_GENERATION', - 'refs', - 'updater', - 'appHelper', - 'isReactComponent', - 'forceUpdate', - 'setState', - 'isPureReactComponent', - ]; - let result = []; - for (let key in obj) { - if (key.indexOf('_') !== 0 && filterKeys.indexOf(key) === -1) { - result.push(key); - } - } - return result; - } - - /** - * 根据输入项进行筛选 - * @param {String} - * @param {String} - * @return {Boolen} - */ - filterOption(inputValue: string, item: { value: string | any[] }) { - const cursorIndex = this.getInputCursorPosition(); - let preStr = inputValue.substr(0, cursorIndex); - let lastKey = preStr.split('.').slice(-1); - if (!lastKey) return true; - if (item.value.indexOf(lastKey) > -1) return true; - return false; - } - - render() { - const { value, dataSource } = this.state; - const { placeholder } = this.props; - const isValObject = !!(value == '[object Object]'); - let title = isValObject - ? this.i18n('valueIllegal') - : (value || placeholder || this.i18n('jsExpression')).toString(); - const cursorIndex = this.getInputCursorPosition(); - let childNode = cursorIndex ? ( -
- {title.substr(0, cursorIndex)} - | - {title.substr(cursorIndex)} -
- ) : ( - title - ); - - return ( -
- {'{{'}} - innerAfter={{'}}'}} - itemRender={({ value }) => { - return ( - - ); - }} - onChange={this.onChange.bind(this)} - filter={this.filterOption.bind(this)} - /> - ) - } - > - {childNode} - -
- ); - } - - componentDidMount() { - this.$input = this.findInputElement(); - if (this.$input) { - this.listenerFun = (event) => { - let isMoveKey = !!(event.type == 'keyup' && ~[37, 38, 39, 91].indexOf(event.keyCode)); - let isMouseup = event.type == 'mouseup'; - if (isMoveKey || isMouseup) { - let dataSource = this.getDataSource(this.state.value) || []; - this.setState({ - dataSource, - }); - } - }; - this.$input.addEventListener('keyup', this.listenerFun, false); - this.$input.addEventListener('mouseup', this.listenerFun, false); - } - } - componentWillUnmount() { - if (this.listenerFun && this.$input) { - this.$input.removeEventListener('keyup', this.listenerFun, false); - this.$input.removeEventListener('mouseup', this.listenerFun, false); - } - } - /** - * 获取Input输入框DOM节点 - */ - findInputElement() { - return this.expression.current.children[0].getElementsByTagName('input')[0]; - } - /** - * 获取光标位置 - * - */ - getInputCursorPosition() { - if (!this.$input) return; - return this.$input.selectionStart; - } - /* - * 字符串取得对象keys - */ - getObjectKeys(str: string) { - let keys = []; - if (str) keys = str.split('.'); - return keys.slice(0, keys.length - 1); - } - /* - * 设置input组件光标位置在闭合}前 - */ - setInputCursorPosition(idx: number) { - this.$input.setSelectionRange(idx, idx); - this.forceUpdate(); - } -} diff --git a/packages/setters/src/function-setter.tsx b/packages/setters/src/function-setter.tsx deleted file mode 100644 index 2c5995cea..000000000 --- a/packages/setters/src/function-setter.tsx +++ /dev/null @@ -1,471 +0,0 @@ -import { Component, isValidElement, ReactElement, ReactNode, PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import MonacoEditor from 'react-monaco-editor'; -import classNames from 'classnames'; -import { Icon } from '@alifd/next'; -import ObjectButton from '@ali/iceluna-comp-object-button'; -import FormItem from '@ali/iceluna-comp-form/lib/item'; -import { serialize, jsonuri, generateI18n } from '@ali/iceluna-sdk/lib/utils'; - -import Snippets from './locale/snippets'; -import zhCN from './locale/zh-CN'; -import './index.scss'; - -let registerApiAndSnippetStatus = false; //判断注册api机制 - -class MonacoEditorDefaultView extends PureComponent { - static displayName = 'MonacoEditorDefault'; - static propTypes = { - locale: PropTypes.string, - messages: PropTypes.object - }; - static defaultProps = { - locale: 'zh-CN', - messages: zhCN, - width: '100%', - height: '100%', - language: 'javascript', - autoFocus: false, //自动获得焦点 - autoSubmit: true, //自动提交 - placeholder: '', //默认占位内容 - btnText: '提交', - btnSize: 'small', - rules: [], //校验规则 - options: { - readOnly: false, - automaticLayout: true, - folding: true, //默认开启折叠代码功能 - lineNumbers: 'on', - wordWrap: 'off', - formatOnPaste: true, - fontSize: 12, - tabSize: 2, - scrollBeyondLastLine: false, - fixedOverflowWidgets: false, - snippetSuggestions: 'top', - minimap: { - enabled: true - }, - scrollbar: { - vertical: 'hidden', - horizontal: 'hidden', - verticalScrollbarSize: 0 - } - } - }; - constructor(props) { - super(props); - this.strValue = ''; - this.i18n = generateI18n(props.locale, props.messages); - this.editorRef = React.createRef(); - this.options = Object.assign({}, MonacoEditorDefaultView.defaultProps.options, props.options); - this.fullScreenOptions = { - ...this.options, - lineNumbers: 'on', - folding: true, - scrollBeyondLastLine: true, - minimap: { - enabled: true - } - }; - this.state = { - isFullScreen: false - }; - this.onChange = this.onChange.bind(this); - this.onSubmit = this.onSubmit.bind(this); - this.fullScreen = this.fullScreen.bind(this); - this.format = this.format.bind(this); - } - - componentDidUpdate() { - //如果是全屏操作,获得焦点,光标保留在原来位置; - if (this.position) { - this.editor.focus(); - this.editor.setPosition(this.position); - delete this.position; - } - } - componentDidMount() { - this.editorNode = this.editorRef.current; //记录当前dom节点; - this.editorParentNode = this.editorNode.parentNode; //记录父节点; - //自动获得焦点, 格式化需要时间 - if (this.props.autoFocus) { - setTimeout(() => { - this.editor.setPosition({ - column: 4, - lineNumber: 2 - }); - this.editor.focus(); - }, 100); - } - //快捷键编码 - let CtrlCmd = 2048; - let KEY_S = 49; - let Shift = 1024; - let KEY_F = 36; - let KEY_B = 32; - let Escape = 9; - - this.editor.addCommand(CtrlCmd | KEY_S, () => { - this.onSubmit(); //保存快捷键 - }); - this.editor.addCommand(CtrlCmd | Shift | KEY_F, () => { - this.fullScreen(); //全屏快捷键 - }); - this.editor.addCommand(CtrlCmd | KEY_B, () => { - this.format(); //美化快捷键 - }); - this.editor.addCommand(Escape, () => { - this.props.onEscape && this.props.onEscape(); - }); - //注册api - this.editor.submit = this.onSubmit; - this.editor.format = this.format; - this.editor.fullScreen = this.fullScreen; - this.editor.toJson = this.toJson; - this.editor.toObject = this.toObject; - this.editor.toFunction = this.toFunction; - //针对object情况,改写setValue和getValue api - if (this.props.language === 'object') { - let getValue = this.editor.getValue; - let setValue = this.editor.setValue; - this.editor.getValue = () => { - return getValue.call(this.editor).substring(this.valuePrefix.length); - }; - this.editor.setValue = value => { - return setValue.call(this.editor, [this.valuePrefix + value]); - }; - } - } - - render() { - const { - value, - placeholder, - style, - className, - width, - height, - language, - theme, - options, - editorWillMount, - editorDidMount, - autoSubmit, - btnText, - btnSize, - registerApi - } = this.props; - - const { isFullScreen } = this.state; - this.valuePrefix = ''; //值前缀 - if (language === 'object') this.valuePrefix = 'export default '; - if (!this.isFullScreenAction) { - //将值转换成目标值 - let nowValue = this.valueHandler(value || placeholder, language); - let curValue = this.valueHandler(this.strValue, language); - if (nowValue !== curValue) this.strValue = nowValue; - if (language === 'object') this.strValue = this.strValue || placeholder || '{\n\t\n}'; //设置初始化值 - if (language === 'json' && this.strValue === '{}') this.strValue = '{\n\t\n}'; - } - this.isFullScreenAction = false; - //真实高亮语言 - let tarLanguage = language; - if (language === 'object' || language === 'function') { - tarLanguage = 'javascript'; - } - let classes = classNames('monaco-editor-wrap', { - ['monaco-fullscreen']: !!isFullScreen, - ['monaco-nofullscreen']: !isFullScreen - }); - let tarStyle = Object.assign({ minHeight: 360, width, height }, style); - return ( -
-
- { - this.editor = editor; - // registerApi({ editor }); - this.registerApiAndSnippet(monaco); - editorDidMount && editorDidMount.call(this, arguments); - }} - /> - - - -
-
- ); - } - - //值变化 - onChange(curValue) { - if (curValue === this.valuePrefix + this.strValue) return; - const { onAfterChange, language, autoSubmit, onChange } = this.props; - this.strValue = curValue; //记录当前格式 - if (this.ct) clearTimeout(this.ct); - this.ct = setTimeout(() => { - this.position = this.editor.getPosition(); - let ret = this.resultHandler(curValue, language); - if (autoSubmit) onChange && onChange(ret.value); - onAfterChange && onAfterChange(ret.value, ret.error, this.editor); - }, 300); - } - - //提交动作 - onSubmit() { - const { onSubmit, onChange, language } = this.props; - let curValue = this.editor.getValue(); - let ret = this.resultHandler(curValue, language); - if (!ret.error) onChange && onChange(ret.value); - onSubmit && onSubmit(ret.value, ret.error, this.editor); - } - - //值类型转换处理 - valueHandler(value, language) { - let tarValue = value || ''; - if (language === 'json') { - if (value && typeof value === 'object') { - tarValue = JSON.stringify(value, null, 2); - } else if (value && typeof value === 'string') { - try { - let ret = this.toJson(value); - if (!ret.error) tarValue = JSON.stringify(ret.value, null, 2); - } catch (err) {} - } - } else if (language === 'function') { - if (typeof value === 'function') { - tarValue = value.toString(); - } - if (tarValue && typeof tarValue === 'string') { - tarValue = js_beautify(tarValue, { indent_size: 2, indent_empty_lines: true }); - } - } else if (language === 'object') { - //先转成对象,在进行序列化和格式化; - value = value || {}; - if (value && typeof value === 'object') { - try { - tarValue = serialize(value, { unsafe: true }); - tarValue = js_beautify(tarValue, { indent_size: 2, indent_empty_lines: true }); - } catch (err) {} - } else if (typeof value === 'string') { - try { - let ret = this.resultHandler(value, 'object'); - tarValue = ret.error ? ret.value : serialize(ret.value, { unsafe: true }); - tarValue = js_beautify(tarValue, { indent_size: 2, indent_empty_lines: true }); - } catch (err) {} - } - } - return tarValue; - } - - //结果处理 - resultHandler(value, language) { - let ret = { value }; - if (language === 'json') { - ret = this.toJson(value); - } else if (language === 'object') { - ret = this.toObject(value); - } else if (language === 'function') { - ret = this.toFunction(value); - } - return ret; - } - - //设置全屏时的动作 - fullScreen() { - if (!this.editorRef) return; - //还原到原来位置; - this.position = this.editor.getPosition(); - if (this.state.isFullScreen) { - if (this.editorParentNode) { - if (this.editorParentNode.firstChild) { - this.editorParentNode.insertBefore(this.editorNode, this.editorParentNode.firstChild); - } else { - this.editorParentNode.appendChild(this.editorNode); - } - } - } else { - document.body.appendChild(this.editorNode); - } - let nextFs = !this.state.isFullScreen; - this.isFullScreenAction = true; //记录是全屏幕操作 - this.setState( - { - isFullScreen: nextFs - }, - () => { - this.editor.updateOptions(nextFs ? this.fullScreenOptions : this.options); - } - ); - } - - //美化代码 - format() { - if (!this.editor) return; - if (/^\$_obj?\{.*?\}$/m.test(this.editor.getValue())) return; - if (this.props.language === 'json' || this.props.language === 'object' || this.props.language === 'function') { - let tarValue = js_beautify(this.editor.getValue(), { indent_size: 2 }); - this.editor.setValue(tarValue); - } else if (this.props.language === 'less' || this.props.language === 'css' || this.props.language === 'scss') { - let tarValue = css_beautify(this.editor.getValue(), { indent_size: 2 }); - this.editor.setValue(tarValue); - } else { - this.editor.getAction('editor.action.formatDocument').run(); - } - } - - //校验是否是json - toJson(value) { - try { - let obj = new Function(`'use strict'; return ${value.replace(/[\r\n\t]/g, '')}`)(); - if (typeof obj === 'object' && obj) { - let tarValue = new Function(`'use strict'; return ${value}`)(); - return { value: JSON.parse(JSON.stringify(tarValue)) }; - } - return { error: this.i18n('jsonIllegal'), value }; - } catch (err) { - return { error: err, value }; - } - } - - //校验是否为object对象 - toObject(value) { - try { - let obj = new Function(`'use strict';return ${value}`)(); - if (obj && typeof obj === 'object') { - if (jsonuri.isCircular(obj)) return { error: this.i18n('circularRef'), value }; - return { value: obj }; - } else { - return { error: this.i18n('objectIllegal'), value }; - } - } catch (err) { - return { error: err, value }; - } - } - - //校验是否为function - toFunction(value) { - try { - let fun = new Function(`'use strict';return ${value}`)(); - if (fun && typeof fun === 'function') { - return { value: fun }; - } else { - return { error: this.i18n('functionIllegal'), value }; - } - } catch (err) { - return { error: err, value }; - } - } - - //注册api和代码片段 - registerApiAndSnippet(monaco) { - if (registerApiAndSnippetStatus) return; - registerApiAndSnippetStatus = true; - //注册this.提示的方法; - let thisSuggestions = []; - Snippets.map(item => { - if (!item.label || !item.kind || !item.insertText) return; - let tarItem = Object.assign(item, { - label: item.label, - kind: monaco.languages.CompletionItemKind[item.kind], - insertText: item.insertText - }); - if (item.insertTextRules) - tarItem.insertTextRules = monaco.languages.CompletionItemInsertTextRule[item.insertTextRules]; - thisSuggestions.push(tarItem); - }); - monaco.languages.registerCompletionItemProvider('javascript', { - provideCompletionItems: (model, position) => { - let textUntilPosition = model.getValueInRange({ - startLineNumber: position.lineNumber, - startColumn: 1, - endLineNumber: position.lineNumber, - endColumn: position.column - }); - let match = textUntilPosition.match(/(^this\.)|(\sthis\.)/); - let suggestions = match ? thisSuggestions : []; - return { suggestions: suggestions }; - }, - triggerCharacters: ['.'] - }); - } -} - -export default class Title extends Component<{ title: TitleContent; onClick?: () => void }> { - static defaultProps = { - locale: 'zh-CN', - } - - render() { - const self = this; - const { locale, messages, id, value, onChange, __parent = {}, rules, objectButtonProps, ...restProps } = this.props; - let tarRestProps = { ...restProps }; - let tarObjProps = { ...objectButtonProps }; - tarObjProps.className = 'luna-monaco-button'; - if (tarRestProps['data-meta']) { - delete tarRestProps['data-meta']; - tarObjProps['data-meta'] = 'Field'; - } - tarObjProps.id = id; - tarObjProps.value = value; - tarObjProps.onChange = onChange; - let tarRule = []; - //判断,如果是json,function, object等类型,自动追加校验规则; - if (tarRestProps.language && ['json', 'function', 'object'].includes(tarRestProps.language)) { - if (['json', 'object'].includes(tarRestProps.language)) { - tarRule.push({ - validator: function(rule, value, callback) { - if (typeof value !== 'object') { - callback(self.i18n('formatError')); - } else { - callback(); - } - } - }); - } else { - tarRule.push({ - validator: function(rule, value, callback) { - if (typeof value !== 'function') { - callback(self.i18n('formatError')); - } else { - callback(); - } - } - }); - } - } - if (rules && Array.isArray(rules) && rules.length) { - tarRule = tarRule.concat(rules); - } - if (__parent && __parent.rules) { - tarRule = tarRule.concat(__parent.rules); - } - return ( - - - - - - ); - } -} diff --git a/packages/setters/src/index.scss b/packages/setters/src/index.scss deleted file mode 100644 index d35c686d4..000000000 --- a/packages/setters/src/index.scss +++ /dev/null @@ -1,93 +0,0 @@ -// mixin -.lowcode-setter-mixin > * { - vertical-align: middle; -} -.lowcode-setter-mixin { - width: 86%; -} -.lowcode-setter-mixin .next-input { - width: 100%; -} -.lowcode-setter-mixin .next-select-trigger { - width: 100%; -} -// function -:global { - .nrs-monaco-form { - .next-form-item:last-child { - margin: 0 !important; - } - } - .monaco-editor-wrap { - min-height: 300px; - .monaco_fullscreen_icon { - position: absolute; - line-height: 1; - z-index: 7; - color: #ddd; - &:hover { - color: #fff; - } - } - .btns-eare { - text-align: left; - line-height: initial; - margin-top: 5px; - // button{ - // margin-right: 10px; - // } - } - &.monaco-nofullscreen { - position: relative !important; - .monaco_fullscreen_icon { - position: absolute; - top: 5px; - right: 5px; - line-height: 1; - z-index: 7; - i:before { - font-size: 16px; - } - } - } - &.monaco-fullscreen { - position: fixed !important; - height: 100% !important; - width: 100% !important; - border: 0; - margin: 0; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1001; - overflow: hidden; - .monaco_fullscreen_icon { - top: 10px; - right: 10px; - i:before { - font-size: 24px; - } - } - } - } - .luna-monaco-button button { - width: 100%; - } - .luna-monaco-button-dialog { - .next-dialog-body { - padding: 0; - .next-form-item { - height: 100%; - margin-bottom: 0; - .next-form-item-control, - .next-form-item-control > div { - height: 100% !important; - } - .next-form-item-help { - position: absolute; - } - } - } - } -} \ No newline at end of file diff --git a/packages/setters/src/index.tsx b/packages/setters/src/index.tsx index 13df30c45..73dd1091b 100644 --- a/packages/setters/src/index.tsx +++ b/packages/setters/src/index.tsx @@ -2,6 +2,8 @@ import { registerSetter } from '@ali/lowcode-globals'; import { DatePicker, Input, Radio, Select, Switch, NumberPicker } from '@alifd/next'; import ExpressionSetter from './expression-setter'; import MixinSetter from './mixin-setter'; +import ColorSetter from './color-setter'; +import JsonSetter from './json-setter'; import EventsSetter from './events-setter'; import StyleSetter from './style-setter'; @@ -49,6 +51,8 @@ const builtinSetters = { DateRangeSetter, EventsSetter, StyleSetter, + ColorSetter, + JsonSetter, }; export function registerSetters() { diff --git a/packages/setters/src/mixin-setter.tsx b/packages/setters/src/mixin-setter.tsx deleted file mode 100644 index 65a854334..000000000 --- a/packages/setters/src/mixin-setter.tsx +++ /dev/null @@ -1,301 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { Dropdown, Button, Menu, Icon, Input, NumberPicker, Switch, Select, Radio, DatePicker } from '@alifd/next'; - -import { isJSExpression, generateI18n } from './locale/utils'; -import Expression from './expression-setter'; -import zhCN from './locale/zh-CN'; -import './index.scss'; - -const { Group: RadioGroup } = Radio; -// const isJSExpression = (obj) => { -// if(typeof obj === 'object' && obj.type === 'JSExpression') { -// return true; -// } -// return false; -// } - -export default class Mixin extends PureComponent { - static displayName = 'Mixin'; - static propTypes = { - locale: PropTypes.string, - messages: PropTypes.object, - defaultType: PropTypes.string, - types: PropTypes.arrayOf(PropTypes.string), - onlyChangeType: PropTypes.bool, - inputProps: PropTypes.object, - expressionProps: PropTypes.object, - monacoEditorProps: PropTypes.object, - switchProps: PropTypes.object, - selectProps: PropTypes.object, - radioGroupProps: PropTypes.object, - }; - static defaultProps = { - locale: 'zh-CN', - messages: zhCN, - types: ['StringSetter', 'ExpressionSetter', 'NumberSetter', 'BoolSetter', 'SelectSetter', 'RadioGroupSetter'], - }; - constructor(props) { - super(props); - let type = judgeTypeHandler(props, {}); - this.i18n = generateI18n(props.locale, props.messages); - this.state = { - preType: type, - type - }; - } - static getDerivedStateFromProps(props, state) { - if ('value' in props) { - let curType = judgeTypeHandler(props, state); - if (curType !== state.preType) { - return { - type: curType - }; - } - } - return null; - } - changeType(type) { - if (typeof type === 'object' || type === this.state.type) return; - let { onlyChangeType, value, onChange } = this.props; - if (onlyChangeType) { - this.setState({ type }); - onChange && onChange(value); - } else { - let newValue = undefined; - if (this.typeMap[type]['props']) { - if (this.typeMap[type]['props']['value'] !== undefined) { - newValue = this.typeMap[type]['props']['value']; - } else if (this.typeMap[type]['props']['defaultValue'] !== undefined) { - newValue = this.typeMap[type]['props']['defaultValue']; - } - } - if (type === 'BoolSetter' && newValue === undefined) { - newValue = false; //给切换到switch默认值为false - } - this.setState({ type }); - onChange && onChange(newValue); - } - } - render() { - const { - style = {}, - className, - locale, - messages, - types = [], - defaultType, - // inputProps, - // expressionProps, - // monacoEditorProps, - // numberPickerProps, - // switchProps, - // selectProps, - // radioGroupProps, - ...restProps - } = this.props; - this.typeMap = { - StringSetter: { - label: this.i18n('input'), - component: Input, - // props: inputProps - }, - ExpressionSetter: { - label: this.i18n('expression'), - component: Expression, - // props: expressionProps - }, - // MonacoEditor: { - // label: this.i18n('monacoEditor'), - // component: MonacoEditor, - // props: monacoEditorProps - // }, - NumberSetter: { - label: this.i18n('numberPicker'), - component: NumberPicker, - }, - BoolSetter: { - label: this.i18n('bool'), - component: Switch, - }, - SelectSetter: { - label: this.i18n('select'), - component: Select, - }, - RadioGroupSetter: { - label: this.i18n('radio'), - component: RadioGroup, - }, - TextAreaSetter: { - label: this.i18n('textarea'), - component: Input.TextArea, - }, - DateSetter: { - label: this.i18n('date'), - component: DatePicker, - }, - DateYearSetter: { - label: this.i18n('dateYear'), - component: DatePicker, - }, - DateMonthSetter: { - label: this.i18n('dateMonth'), - component: DatePicker, - }, - DateRangeSetter: { - label: this.i18n('dateRange'), - component: DatePicker, - } - }; - let realTypes = []; - types.forEach( el => { - const { name, props } = el; - if (this.typeMap[name]) { - this.typeMap[name].props = props; - realTypes.push(name); - } - }) - let moreBtnNode = null; - //如果只有2种,且有变量表达式,则直接展示变量按钮 - if (realTypes.length > 1) { - let isTwoType = !!(realTypes.length === 2 && ~realTypes.indexOf('ExpressionSetter')); - let btnProps = { - size: 'small', - text: true, - style: { - position: 'absolute', - left: '100%', - top: 0, - bottom: 0, - margin: 'auto 0 auto 8px', - padding: 0, - width: 16, - height: 16, - lineHeight: '16px', - textAlign: 'center' - } - }; - if (isTwoType) { - btnProps.onClick = this.changeType.bind(this, realTypes.indexOf(this.state.type) ? realTypes[0] : realTypes[1]); - } - let triggerNode = ( - - ); - if (isTwoType) { - moreBtnNode = triggerNode; - } else { - let MenuItems = []; - realTypes.map(type => { - if (this.typeMap[type]) { - MenuItems.push({this.typeMap[type]['label']}); - } else { - console.error( - this.i18n('typeError', { - type - }) - ); - } - }); - let MenuNode = ( - - {MenuItems} - - ); - - moreBtnNode = ( - - {MenuNode} - - ); - } - } - let TargetNode = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['component'] : 'div'; - let targetProps = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['props'] : {}; - - // 特殊处理Switch的值 - if (['BoolSetter', 'RadioGroupSetter'].includes(this.state.type)) { - restProps.checked = this.props.checked !== undefined ? this.props.checked : this.props.value; - } - //判断如果Mixin内部有设置onChange, 则同时触发2处onChange - if (targetProps && targetProps.onChange && typeof targetProps.onChange === 'function') { - let tarOnChange = targetProps.onChange; - targetProps.onChange = function() { - tarOnChange.apply(null, arguments); - restProps.onChange && restProps.onChange.apply(null, arguments); - }; - } - let tarStyle = { position: 'relative', ...style }; - let classes = classNames(className, 'lowcode-setter-mixin'); - return ( -
- - {moreBtnNode} -
- ); - } -} - -// 判断值类型 -function judgeTypeHandler(props, state) { - let { defaultType, types, value } = props; - let selectProps: { dataSource: any[]; }; - let radioGroupProps: { dataSource: any[]; }; - let typeKeys: any[] = []; - types.forEach( el => { - typeKeys.push(el.name); - }) - - types.forEach((el: { name: string; props: {}; }) => { - if (el.name === 'SelectSetter') {selectProps === el.props;} - if (el.name === 'RadioGroupSetter') {radioGroupProps === el.props;} - }) - if (!defaultType || !typeKeys) return; - // 如果defaultType不在typeKeys列表中,默认返回typeKeys的第一项 - if (!typeKeys.includes(defaultType)) return typeKeys[0]; - if (isJSExpression(value)) return 'ExpressionSetter'; - if (value && typeof value === 'string') { - if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) { - let hasOption = selectProps.dataSource.some(item => { - if (typeof item === 'string' && item === value) return true; - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'SelectSetter'; - } - if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) { - let hasOption = radioGroupProps.dataSource.some(item => { - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'RadioGroupSetter'; - } - if (~typeKeys.indexOf('StringSetter')) return 'StringSetter'; - } - if (typeof value === 'number') { - if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) { - let hasOption = selectProps.dataSource.some(item => { - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'Select'; - } - if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) { - let hasOption = radioGroupProps.dataSource.some(item => { - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'RadioGroupSetter'; - } - if (~typeKeys.indexOf('NumberSetter')) return 'NumberSetter'; - } - if (~typeKeys.indexOf('NumberSetter') && typeof value === 'number') return 'NumberSetter'; - if (~typeKeys.indexOf('BoolSetter') && (value === false || value === true)) return 'BoolSetter'; - if (Array.isArray(value)) { - if (~typeKeys.indexOf('SelectSetter') && typeof value[0] === 'string') return 'SelectSetter'; - } - return state.type || defaultType; -} diff --git a/packages/setters/src/mixin-setter/index.scss b/packages/setters/src/mixin-setter/index.scss index 19287099a..5e793311c 100644 --- a/packages/setters/src/mixin-setter/index.scss +++ b/packages/setters/src/mixin-setter/index.scss @@ -10,121 +10,4 @@ } .lowcode-setter-mixin .next-select-trigger { width: 100%; -} -// json-setter -// :global { - .nrs-monaco-form { - .next-form-item:last-child { - margin: 0 !important; - } - } - .monaco-editor-wrap { - .luna-monaco-button .next-icon-first { - height: 26px; - } - .monaco_fullscreen_icon { - position: absolute; - line-height: 1; - z-index: 7; - color: #ddd; - &:hover { - color: #fff; - } - } - .btns-eare { - text-align: left; - line-height: initial; - margin-top: 5px; - // button{ - // margin-right: 10px; - // } - } - &.monaco-nofullscreen { - position: relative !important; - .monaco_fullscreen_icon { - position: absolute; - top: 5px; - right: 5px; - line-height: 1; - z-index: 7; - i:before { - font-size: 16px; - } - } - } - &.monaco-fullscreen { - position: fixed !important; - height: 100% !important; - width: 100% !important; - border: 0; - margin: 0; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1001; - overflow: hidden; - .monaco_fullscreen_icon { - top: 10px; - right: 10px; - i:before { - font-size: 24px; - } - } - } - } - .luna-monaco-button button { - width: 100%; - } - .luna-monaco-button-dialog { - .next-dialog-body { - padding: 0; - .next-form-item { - height: 100%; - margin-bottom: 0; - .next-form-item-control, - .next-form-item-control > div { - height: 100% !important; - } - .next-form-item-help { - position: absolute; - } - } - } - } -// } -// color-setter -.lowcode-color-box { - margin-right: -5px; - padding: 3px 0 3px 3px; - width: 26px; - height: 26px; - display: inline-block; - div { - width: 20px; - height: 20px; - border: 1px solid #ddd; - } -} -.next-balloon-normal.lowcode-color-content { - padding: 0; - background: #ffffff; - border-radius: 0; - border: 1px solid #e5e5e5; - box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); - &:after { - display: none; - } - .sketch-picker { - border-radius: 0 !important; - border: none !important; - box-shadow: none !important; - .flexbox-fix { - input { - width: 100% !important; - min-width: 30px; - text-align: center; - } - } - } } \ No newline at end of file diff --git a/packages/setters/src/mixin-setter/index.tsx b/packages/setters/src/mixin-setter/index.tsx index 47978b704..f71c062d9 100644 --- a/packages/setters/src/mixin-setter/index.tsx +++ b/packages/setters/src/mixin-setter/index.tsx @@ -1,22 +1,13 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { Dropdown, Button, Menu, Icon, Input, NumberPicker, Switch, Select, Radio, DatePicker } from '@alifd/next'; -import MonacoEditor from '@ali/iceluna-comp-monaco-editor'; +import { Dropdown, Button, Menu, Icon } from '@alifd/next'; +import { getSetter } from '@ali/lowcode-globals'; -import { isJSExpression, generateI18n } from './locale/utils'; -import Expression from '../expression-setter'; +import { generateI18n } from './locale/utils'; import zhCN from './locale/zh-CN'; import './index.scss'; -const { Group: RadioGroup } = Radio; -// const isJSExpression = (obj) => { -// if(typeof obj === 'object' && obj.type === 'JSExpression') { -// return true; -// } -// return false; -// } - export default class Mixin extends PureComponent { static displayName = 'Mixin'; static propTypes = { @@ -24,7 +15,6 @@ export default class Mixin extends PureComponent { messages: PropTypes.object, defaultType: PropTypes.string, types: PropTypes.arrayOf(PropTypes.string), - onlyChangeType: PropTypes.bool, inputProps: PropTypes.object, expressionProps: PropTypes.object, monacoEditorProps: PropTypes.object, @@ -35,49 +25,39 @@ export default class Mixin extends PureComponent { static defaultProps = { locale: 'zh-CN', messages: zhCN, - types: ['StringSetter', 'ExpressionSetter', 'NumberSetter', 'BoolSetter', 'SelectSetter', 'RadioGroupSetter'], + types: [{ + "name": "StringSetter", + "props": {} + }], }; - constructor(props) { + typeMap: any; + i18n: (key: any, values?: {}) => string | void | (string | void)[]; + constructor(props: Readonly<{}>) { super(props); - let type = judgeTypeHandler(props, {}); + let type = props.defaultType;// judgeTypeHandler(props, {}); this.i18n = generateI18n(props.locale, props.messages); this.state = { preType: type, type }; } - static getDerivedStateFromProps(props, state) { - if ('value' in props) { - let curType = judgeTypeHandler(props, state); - if (curType !== state.preType) { - return { - type: curType - }; - } - } - return null; - } - changeType(type) { + changeType(type: string) { if (typeof type === 'object' || type === this.state.type) return; - let { onlyChangeType, value, onChange } = this.props; - if (onlyChangeType) { - this.setState({ type }); - onChange && onChange(value); - } else { - let newValue = undefined; - if (this.typeMap[type]['props']) { - if (this.typeMap[type]['props']['value'] !== undefined) { - newValue = this.typeMap[type]['props']['value']; - } else if (this.typeMap[type]['props']['defaultValue'] !== undefined) { - newValue = this.typeMap[type]['props']['defaultValue']; - } + let { onChange } = this.props; + let newValue = undefined; + const setterProps = this.typeMap[type]['props']; + if (setterProps) { + if (setterProps.value !== undefined) { + newValue = setterProps.value; + } else if (setterProps.defaultValue !== undefined) { + newValue = setterProps.defaultValue; } - if (type === 'BoolSetter' && newValue === undefined) { - newValue = false; //给切换到switch默认值为false - } - this.setState({ type }); - onChange && onChange(newValue); } + if (type === 'BoolSetter' && newValue === undefined) { + newValue = false; //给切换到switch默认值为false + } + this.setState({ type }); + onChange && onChange(newValue); } render() { const { @@ -87,75 +67,21 @@ export default class Mixin extends PureComponent { messages, types = [], defaultType, - // inputProps, - // expressionProps, - // monacoEditorProps, - // numberPickerProps, - // switchProps, - // selectProps, - // radioGroupProps, ...restProps } = this.props; - this.typeMap = { - StringSetter: { - label: this.i18n('input'), - component: Input, - // props: inputProps - }, - ExpressionSetter: { - label: this.i18n('expression'), - component: Expression, - // props: expressionProps - }, - // MonacoEditor: { - // label: this.i18n('monacoEditor'), - // component: MonacoEditor, - // props: monacoEditorProps - // }, - NumberSetter: { - label: this.i18n('numberPicker'), - component: NumberPicker, - }, - BoolSetter: { - label: this.i18n('bool'), - component: Switch, - }, - SelectSetter: { - label: this.i18n('select'), - component: Select, - }, - RadioGroupSetter: { - label: this.i18n('radio'), - component: RadioGroup, - }, - TextAreaSetter: { - label: this.i18n('textarea'), - component: Input.TextArea, - }, - DateSetter: { - label: this.i18n('date'), - component: DatePicker, - }, - DateYearSetter: { - label: this.i18n('dateYear'), - component: DatePicker, - }, - DateMonthSetter: { - label: this.i18n('dateMonth'), - component: DatePicker, - }, - DateRangeSetter: { - label: this.i18n('dateRange'), - component: DatePicker, - } - }; - let realTypes = []; - types.forEach( el => { + this.typeMap = {}; + let realTypes: any[] = []; + types.forEach( (el: { name: any; props: any; }) => { const { name, props } = el; - if (this.typeMap[name]) { - this.typeMap[name].props = props; - realTypes.push(name); + const Setter = getSetter(name); + if (Setter) { + this.typeMap[name] = { + label: name, + component: Setter.component, + props, + } } + realTypes.push(name); }) let moreBtnNode = null; //如果只有2种,且有变量表达式,则直接展示变量按钮 @@ -188,7 +114,7 @@ export default class Mixin extends PureComponent { if (isTwoType) { moreBtnNode = triggerNode; } else { - let MenuItems = []; + let MenuItems: {} | null | undefined = []; realTypes.map(type => { if (this.typeMap[type]) { MenuItems.push({this.typeMap[type]['label']}); @@ -218,85 +144,16 @@ export default class Mixin extends PureComponent { ); } } - let TargetNode = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['component'] : 'div'; - let targetProps = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['props'] : {}; - - // 特殊处理Switch的值 - if (['BoolSetter', 'RadioGroupSetter'].includes(this.state.type)) { - restProps.checked = this.props.checked !== undefined ? this.props.checked : this.props.value; - } - //判断如果Mixin内部有设置onChange, 则同时触发2处onChange - if (targetProps && targetProps.onChange && typeof targetProps.onChange === 'function') { - let tarOnChange = targetProps.onChange; - targetProps.onChange = function() { - tarOnChange.apply(null, arguments); - restProps.onChange && restProps.onChange.apply(null, arguments); - }; - } + let TargetNode = this.typeMap[this.state.type]['component'] || 'div'; + let targetProps = this.typeMap[this.state.type]['props'] || {}; let tarStyle = { position: 'relative', ...style }; let classes = classNames(className, 'lowcode-setter-mixin'); + return ( -
+
{moreBtnNode}
); } } - -// 判断值类型 -function judgeTypeHandler(props, state) { - let { defaultType, types, value } = props; - let selectProps: { dataSource: any[]; }; - let radioGroupProps: { dataSource: any[]; }; - let typeKeys: any[] = []; - types.forEach( el => { - typeKeys.push(el.name); - }) - - types.forEach((el: { name: string; props: {}; }) => { - if (el.name === 'SelectSetter') {selectProps === el.props;} - if (el.name === 'RadioGroupSetter') {radioGroupProps === el.props;} - }) - if (!defaultType || !typeKeys) return; - // 如果defaultType不在typeKeys列表中,默认返回typeKeys的第一项 - if (!typeKeys.includes(defaultType)) return typeKeys[0]; - if (isJSExpression(value)) return 'ExpressionSetter'; - if (value && typeof value === 'string') { - if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) { - let hasOption = selectProps.dataSource.some(item => { - if (typeof item === 'string' && item === value) return true; - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'SelectSetter'; - } - if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) { - let hasOption = radioGroupProps.dataSource.some(item => { - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'RadioGroupSetter'; - } - if (~typeKeys.indexOf('StringSetter')) return 'StringSetter'; - } - if (typeof value === 'number') { - if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) { - let hasOption = selectProps.dataSource.some(item => { - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'Select'; - } - if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) { - let hasOption = radioGroupProps.dataSource.some(item => { - if (typeof item === 'object' && item.value === value) return true; - }); - if (hasOption) return 'RadioGroupSetter'; - } - if (~typeKeys.indexOf('NumberSetter')) return 'NumberSetter'; - } - if (~typeKeys.indexOf('NumberSetter') && typeof value === 'number') return 'NumberSetter'; - if (~typeKeys.indexOf('BoolSetter') && (value === false || value === true)) return 'BoolSetter'; - if (Array.isArray(value)) { - if (~typeKeys.indexOf('SelectSetter') && typeof value[0] === 'string') return 'SelectSetter'; - } - return state.type || defaultType; -} diff --git a/packages/setters/src/mixin-setter/locale/snippets.js b/packages/setters/src/mixin-setter/locale/snippets.js deleted file mode 100644 index 7c8484c4f..000000000 --- a/packages/setters/src/mixin-setter/locale/snippets.js +++ /dev/null @@ -1,242 +0,0 @@ -export default [ - { - label: 'constants', - kind: 'Class', - insertText: 'constants', - detail: '应用全局常量', - documentation: '应用范围定义的通用常量' - }, - { - label: 'utils', - kind: 'Class', - insertText: 'utils', - detail: '应用全局公共函数', - documentation: '应用范围扩展的公共函数' - }, - { - label: 'state', - kind: 'Enum', - insertText: 'state', - detail: '当前所在容器组件内部状态', - documentation: 'React Class内部状态state' - }, - { - label: 'setState', - kind: 'Function', - insertText: 'setState({\n\t$0\n})', - insertTextRules: 'InsertAsSnippet', - detail: '设置当前所在容器组件的state数据', - documentation: '原生React方法,会自动更新组件视图' - }, - { - label: 'reloadDataSource', - kind: 'Function', - insertText: 'reloadDataSource(${1:${2:namespace}, ${3:false}, ${4:callback}})', - insertTextRules: 'InsertAsSnippet', - detail: '刷新当前所在的容器组件', - documentation: '触发当前所在的容器组件,重新发送异步请求,并用最新数据更新视图' - }, - { - label: 'location', - kind: 'Class', - insertText: 'location', - detail: '路由解析对象' - }, - { - label: 'location.query', - kind: 'Value', - insertText: 'location.query.${1:xxxx}', - insertTextRules: 'InsertAsSnippet', - detail: '从路由解析对象中获取参数信息' - }, - { - label: 'history', - kind: 'Class', - insertText: 'history', - detail: '路由历史对象' - }, - { - label: 'React', - kind: 'Keyword', - insertText: 'React', - detail: 'React对象' - }, - { - label: 'ReactDOM', - kind: 'Keyword', - insertText: 'ReactDOM', - detail: 'ReactDom对象' - }, - { - label: 'ReactDOM.findDOMNode', - kind: 'Function', - insertText: 'ReactDOM.findDOMNode(${1:this.refs.xxxx})', - insertTextRules: 'InsertAsSnippet', - detail: 'ReactDom查找真实dom node' - }, - { - label: 'Dialog.alert', - kind: 'Method', - insertText: [ - 'Dialog.alert({', - "\tcontent: '${1:Alert content}',", - "\ttitle: '${2:Title}',", - '\tonOk: () => {', - '\t\t$3', - '\t}', - '})' - ].join('\n'), - insertTextRules: 'InsertAsSnippet', - detail: 'alert弹框 By Fusion' - }, - { - label: 'Dialog.confirm', - kind: 'Method', - insertText: [ - 'Dialog.confirm({', - "\tcontent: '${1:Confirm content}',", - "\ttitle: '${2:Title}',", - '\tonOk: () => {', - '\t\t$3', - '\t},', - '\tonCancel: () => {', - '\t\t$4', - '\t}', - '})' - ].join('\n'), - insertTextRules: 'InsertAsSnippet', - detail: '确认弹出框 By Fusion' - }, - { - label: 'Message.success', - kind: 'Method', - insertText: 'Message.success(${1:content})', - insertTextRules: 'InsertAsSnippet', - detail: '成功反馈提示 By Fusion' - }, - { - label: 'Message.error', - kind: 'Method', - insertText: 'Message.error(${1:content})', - insertTextRules: 'InsertAsSnippet', - detail: '错误反馈提示 By Fusion' - }, - { - label: 'Message.help', - kind: 'Method', - insertText: 'Message.help(${1:content})', - insertTextRules: 'InsertAsSnippet', - detail: '帮助反馈提示 By Fusion' - }, - { - label: 'Message.loading', - kind: 'Method', - insertText: 'Message.loading(${1:content})', - insertTextRules: 'InsertAsSnippet', - detail: 'loading反馈提示 By Fusion' - }, - { - label: 'Message.notice', - kind: 'Method', - insertText: 'Message.notice(${1:content})', - insertTextRules: 'InsertAsSnippet', - detail: '注意反馈提示 By Fusion' - }, - { - label: 'Message.waining', - kind: 'Method', - insertText: 'Message.waining(${1:content})', - insertTextRules: 'InsertAsSnippet', - detail: '警告反馈提示 By Fusion' - }, - { - label: 'Modal.confirm', - kind: 'Method', - insertText: [ - 'Modal.confirm({', - "\tcontent: '${1:Confirm content}',", - "\ttitle: '${2:Title}',", - '\tonOk: () => {', - '\t\t$3', - '\t},', - '\tonCancel: () => {', - '\t\t$4', - '\t}', - '})' - ].join('\n'), - insertTextRules: 'InsertAsSnippet', - detail: '确认弹出框 By Antd' - }, - { - label: 'Modal.info', - kind: 'Method', - insertText: [ - 'Modal.info({', - "\tcontent: '${1:Info content}',", - "\ttitle: '${2:Title}',", - '\tonOk: () => {', - '\t\t$3', - '\t},', - '\tonCancel: () => {', - '\t\t$4', - '\t}', - '})' - ].join('\n'), - insertTextRules: 'InsertAsSnippet', - detail: '信息弹出框 By Antd' - }, - { - label: 'Modal.success', - kind: 'Method', - insertText: [ - 'Modal.success({', - "\tcontent: '${1:Success content}',", - "\ttitle: '${2:Title}',", - '\tonOk: () => {', - '\t\t$3', - '\t},', - '\tonCancel: () => {', - '\t\t$4', - '\t}', - '})' - ].join('\n'), - insertTextRules: 'InsertAsSnippet', - detail: '成功弹出框 By Antd' - }, - { - label: 'Modal.error', - kind: 'Method', - insertText: [ - 'Modal.error({', - "\tcontent: '${1:Error content}',", - "\ttitle: '${2:Title}',", - '\tonOk: () => {', - '\t\t$3', - '\t},', - '\tonCancel: () => {', - '\t\t$4', - '\t}', - '})' - ].join('\n'), - insertTextRules: 'InsertAsSnippet', - detail: '错误弹出框 By Antd' - }, - { - label: 'Modal.warning', - kind: 'Method', - insertText: [ - 'Modal.warning({', - "\tcontent: '${1:Warning content}',", - "\ttitle: '${2:Title}',", - '\tonOk: () => {', - '\t\t$3', - '\t},', - '\tonCancel: () => {', - '\t\t$4', - '\t}', - '})' - ].join('\n'), - insertTextRules: 'InsertAsSnippet', - detail: '警告弹出框 By Antd' - } -]; \ No newline at end of file From eaa84d22bfefff5e03858507778156347e3780d9 Mon Sep 17 00:00:00 2001 From: "jianfang.rjf" Date: Thu, 2 Apr 2020 20:49:59 +0800 Subject: [PATCH 07/21] feat: mixin-setter get all setter --- packages/setters/README.md | 139 +++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/packages/setters/README.md b/packages/setters/README.md index e70f29ba0..54458bc05 100644 --- a/packages/setters/README.md +++ b/packages/setters/README.md @@ -1 +1,140 @@ 通用设置器 + +## 使用文档 +- name:绑定props属性key,类型为string +- setter:setter组件内容,类型可以为string或object,当为string时,指setter名,当为object时: + - componentName:setter名,类型为string + - props:setter属性,类型为object + +## 使用demo +``` +{ + "name": "TextAreaSetter", + "setter": "TextAreaSetter" +}, { + "name": "date", + "title": "测试日期", + "setter": "DateSetter" +}, { + "name": "date", + "title": "测试日期-年", + "setter": "DateYearSetter" +}, { + "name": "date", + "title": "测试日期-月", + "setter": "DateMonthSetter" +}, { + "name": "date", + "title": "测试日期-区间", + "setter": "DateRangeSetter" +}, { + "name": "mode", + "title": "选择器模式", + "setter": { + "componentName": "RadioGroupSetter", + "props": { + "defaultValue": "single", + "dataSource": [{ + "value": "single", + "label": "single" + }, { + "value": "multiple", + "label": "multiple" + }, { + "value": "tag", + "label": "tag" + }] + } + } +}, { + "name": "mode", + "title": "选择器模式", + "setter": { + "componentName": "SelectSetter", + "props": { + "defaultValue": "single", + "dataSource": [{ + "value": "single", + "label": "single" + }, { + "value": "multiple", + "label": "multiple" + }, { + "value": "tag", + "label": "tag" + }] + } + } +}, { + "name": "value", + "title": "受控值", + "setter": "StringSetter" +}, { + "name": "hasBorder", + "title": "是否有边框", + "setter": { + "componentName": "BoolSetter", + "props": { + "defaultValue": true + } + } +}, { + "name": "maxTagCount", + "title": "最多显示多少个 tag", + "setter": "NumberSetter" +}, { + "name": "maxTagCount", + "title": "最多显示多少个 tag", + "setter": "ExpressionSetter" +}, { + "name": "color", + "title": "颜色选择", + "setter": "ColorSetter" +}, { + "name": "json", + "title": "JSON设置", + "setter": "JsonSetter" +}, { + "name": "MixinSetter", + "placeholder": "混合", + "setter": { + "componentName": "MixinSetter", + "props": { + "types": [{ + "name": "StringSetter", + "props": {} + }, { + "name": "TextAreaSetter", + "props": {} + }, { + "name": "SelectSetter", + "props": { + "hasClear": true, + "dataSource": [{ + "label": "上", + "value": "t" + }, { + "label": "右", + "value": "r" + }, { + "label": "下", + "value": "b" + }, { + "label": "左", + "value": "l" + }], + "defaultValue": "l" + } + }, { + "name": "NumberSetter", + "props": { + "defaultValue": 5 + } + }, { + "name": "BoolSetter", + "props": {} + }], + "defaultType": "SelectSetter" + } + } +``` \ No newline at end of file From b12c0f83508cd9d18beadff0333acfaa7736f555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E5=B8=8C?= Date: Tue, 7 Apr 2020 16:55:15 +0800 Subject: [PATCH 08/21] fix: path resolve problem --- packages/code-generator/package.json | 9 +--- packages/code-generator/src/demo/main.ts | 6 +-- .../code-generator/src/demo/simpleDemo.ts | 7 +-- .../src/generator/ProjectBuilder.ts | 8 ++-- packages/code-generator/src/index.ts | 6 +-- .../code-generator/src/parser/SchemaParser.ts | 4 +- .../component/react/containerInjectUtils.ts | 1 - .../src/plugins/component/react/jsx.ts | 2 +- .../src/plugins/project/constants.ts | 6 +-- .../project/framework/icejs/plugins/entry.ts | 4 +- .../framework/icejs/plugins/entryHtml.ts | 4 +- .../framework/icejs/plugins/globalStyle.ts | 4 +- .../framework/icejs/plugins/packageJSON.ts | 4 +- .../project/framework/icejs/plugins/router.ts | 4 +- .../icejs/template/files/README.md.ts | 4 +- .../icejs/template/files/abc.json.ts | 4 +- .../icejs/template/files/build.json.ts | 4 +- .../icejs/template/files/editorconfig.ts | 4 +- .../icejs/template/files/eslintignore.ts | 4 +- .../icejs/template/files/eslintrc.js.ts | 4 +- .../icejs/template/files/gitignore.ts | 4 +- .../icejs/template/files/jsconfig.json.ts | 4 +- .../icejs/template/files/prettierignore.ts | 4 +- .../icejs/template/files/prettierrc.js.ts | 4 +- .../components/Footer/index.jsx.ts | 4 +- .../components/Footer/index.module.scss.ts | 4 +- .../BasicLayout/components/Logo/index.jsx.ts | 4 +- .../components/Logo/index.module.scss.ts | 4 +- .../components/PageNav/index.jsx.ts | 4 +- .../src/layouts/BasicLayout/index.jsx.ts | 4 +- .../src/layouts/BasicLayout/menuConfig.js.ts | 4 +- .../icejs/template/files/stylelintignore.ts | 4 +- .../icejs/template/files/stylelintrc.js.ts | 4 +- .../icejs/template/files/tsconfig.json.ts | 4 +- .../project/framework/icejs/template/index.ts | 8 +++- .../src/plugins/project/i18n.ts | 6 +-- .../src/plugins/project/utils.ts | 7 ++- .../src/plugins/utils/compositeType.ts | 2 +- .../src/postprocessor/prettier/index.ts | 2 +- .../src/publisher/disk/index.ts | 2 +- .../src/publisher/disk/utils.ts | 2 +- .../code-generator/src/solutions/icejs.ts | 46 +++++++++---------- packages/code-generator/src/types/core.ts | 5 ++ packages/code-generator/src/utils/children.ts | 2 +- packages/code-generator/tsconfig.json | 13 ++---- packages/code-generator/webpack.config.js | 31 ------------- 46 files changed, 117 insertions(+), 158 deletions(-) delete mode 100644 packages/code-generator/webpack.config.js diff --git a/packages/code-generator/package.json b/packages/code-generator/package.json index a3959d2e6..638819833 100644 --- a/packages/code-generator/package.json +++ b/packages/code-generator/package.json @@ -7,8 +7,7 @@ "lib" ], "scripts": { - "compile": "rimraf lib && tsc", - "build": "rimraf lib && webpack", + "build": "rimraf lib && tsc", "demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts", "test": "ava" }, @@ -24,11 +23,7 @@ "rimraf": "^3.0.2", "ts-loader": "^6.2.2", "ts-node": "^7.0.1", - "tsconfig-paths": "^3.9.0", - "tsconfig-paths-webpack-plugin": "^3.2.0", - "webpack": "^4.42.1", - "webpack-cli": "^3.3.11", - "webpack-node-externals": "^1.7.2" + "tsconfig-paths": "^3.9.0" }, "ava": { "compileEnhancements": false, diff --git a/packages/code-generator/src/demo/main.ts b/packages/code-generator/src/demo/main.ts index 15d011fdb..e0d341ef4 100644 --- a/packages/code-generator/src/demo/main.ts +++ b/packages/code-generator/src/demo/main.ts @@ -1,7 +1,7 @@ -import { IResultDir, IResultFile } from '@/types'; +import { IResultDir, IResultFile } from '../types'; -import CodeGenerator from '@/index'; -import { createDiskPublisher } from '@/publisher/disk'; +import CodeGenerator from '../index'; +import { createDiskPublisher } from '../publisher/disk'; import demoSchema from './simpleDemo'; function flatFiles(rootName: string | null, dir: IResultDir): IResultFile[] { diff --git a/packages/code-generator/src/demo/simpleDemo.ts b/packages/code-generator/src/demo/simpleDemo.ts index b85b1dbba..cf124ceb9 100644 --- a/packages/code-generator/src/demo/simpleDemo.ts +++ b/packages/code-generator/src/demo/simpleDemo.ts @@ -1,9 +1,4 @@ -import { IProjectSchema } from '@/types'; - -// meta: { -// title: '测试', -// router: '/', -// }, +import { IProjectSchema } from '../types'; const demoData: IProjectSchema = { version: '1.0.0', diff --git a/packages/code-generator/src/generator/ProjectBuilder.ts b/packages/code-generator/src/generator/ProjectBuilder.ts index 98f4dc0a4..ada2e47fd 100644 --- a/packages/code-generator/src/generator/ProjectBuilder.ts +++ b/packages/code-generator/src/generator/ProjectBuilder.ts @@ -11,10 +11,10 @@ import { PostProcessor, } from '../types'; -import ResultDir from '@/model/ResultDir'; -import SchemaParser from '@/parser/SchemaParser'; +import ResultDir from '../model/ResultDir'; +import SchemaParser from '../parser/SchemaParser'; -import { createModuleBuilder } from '@/generator/ModuleBuilder'; +import { createModuleBuilder } from '../generator/ModuleBuilder'; interface IModuleInfo { moduleName?: string; @@ -67,7 +67,7 @@ export class ProjectBuilder implements IProjectBuilder { // Parse / Format // Preprocess - // Colllect Deps + // Collect Deps // Parse JSExpression const parseResult: IParseResult = schemaParser.parse(schema); let buildResult: IModuleInfo[] = []; diff --git a/packages/code-generator/src/index.ts b/packages/code-generator/src/index.ts index f6d467bc7..a0af2ba95 100644 --- a/packages/code-generator/src/index.ts +++ b/packages/code-generator/src/index.ts @@ -2,9 +2,9 @@ * 低代码引擎的出码模块,负责将编排产出的 Schema 转换成实际可执行的代码。 * */ -import { createProjectBuilder } from '@/generator/ProjectBuilder'; -import { createDiskPublisher } from '@/publisher/disk'; -import createIceJsProjectBuilder from '@/solutions/icejs'; +import { createProjectBuilder } from './generator/ProjectBuilder'; +import { createDiskPublisher } from './publisher/disk'; +import createIceJsProjectBuilder from './solutions/icejs'; export * from './types'; diff --git a/packages/code-generator/src/parser/SchemaParser.ts b/packages/code-generator/src/parser/SchemaParser.ts index 3104e01f3..4288d894b 100644 --- a/packages/code-generator/src/parser/SchemaParser.ts +++ b/packages/code-generator/src/parser/SchemaParser.ts @@ -6,10 +6,8 @@ import { SUPPORT_SCHEMA_VERSION_LIST } from '../const'; import { handleChildren } from '../utils/children'; -import { uniqueArray } from '../utils/common'; import { - ChildNodeItem, ChildNodeType, CodeGeneratorError, CompatibilityError, @@ -86,7 +84,7 @@ class SchemaParser implements ISchemaParser { }); } } else { - throw new CodeGeneratorError(`Can't find anything to generator.`); + throw new CodeGeneratorError(`Can't find anything to generate.`); } // 建立所有容器的内部依赖索引 diff --git a/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts b/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts index c2deeaa89..a6670230a 100644 --- a/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts +++ b/packages/code-generator/src/plugins/component/react/containerInjectUtils.ts @@ -5,7 +5,6 @@ import { ChunkType, FileType, ICodeStruct, - IContainerInfo, } from '../../../types'; const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/component/react/jsx.ts b/packages/code-generator/src/plugins/component/react/jsx.ts index ed02499f6..3e5162353 100644 --- a/packages/code-generator/src/plugins/component/react/jsx.ts +++ b/packages/code-generator/src/plugins/component/react/jsx.ts @@ -11,7 +11,7 @@ import { IJSExpression, } from '../../../types'; -import { handleChildren } from '@/utils/children'; +import { handleChildren } from '../../../utils/children'; import { generateCompositeType } from '../../utils/compositeType'; import { REACT_CHUNK_NAME } from './const'; diff --git a/packages/code-generator/src/plugins/project/constants.ts b/packages/code-generator/src/plugins/project/constants.ts index 6e6e887b6..7be166d3d 100644 --- a/packages/code-generator/src/plugins/project/constants.ts +++ b/packages/code-generator/src/plugins/project/constants.ts @@ -1,12 +1,12 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; -import { generateCompositeType } from '@/plugins/utils/compositeType'; +import { COMMON_CHUNK_NAME } from '../../const/generator'; +import { generateCompositeType } from '../../plugins/utils/compositeType'; import { BuilderComponentPlugin, ChunkType, FileType, ICodeStruct, IProjectInfo, -} from '@/types'; +} from '../../types'; // TODO: How to merge this logic to common deps const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts index 488e573b5..f32d9abed 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts @@ -1,4 +1,4 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; import { BuilderComponentPlugin, @@ -6,7 +6,7 @@ import { FileType, ICodeStruct, IProjectInfo, -} from '@/types'; +} from '../../../../../types'; // TODO: How to merge this logic to common deps const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts index 7b12c4252..6ceebc04a 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts @@ -1,4 +1,4 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; import { BuilderComponentPlugin, @@ -6,7 +6,7 @@ import { FileType, ICodeStruct, IProjectInfo, -} from '@/types'; +} from '../../../../../types'; // TODO: How to merge this logic to common deps const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts index d0e923968..3e083c1f1 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/globalStyle.ts @@ -1,4 +1,4 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; import { BuilderComponentPlugin, @@ -6,7 +6,7 @@ import { FileType, ICodeStruct, IProjectInfo, -} from '@/types'; +} from '../../../../../types'; // TODO: How to merge this logic to common deps const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts index fbcf98d91..0e4c48805 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts @@ -1,4 +1,4 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; import { BuilderComponentPlugin, @@ -7,7 +7,7 @@ import { ICodeStruct, IPackageJSON, IProjectInfo, -} from '@/types'; +} from '../../../../../types'; interface IIceJsPackageJSON extends IPackageJSON { ideMode: { diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts index 29a9dd995..b2c9c0805 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts @@ -1,4 +1,4 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; +import { COMMON_CHUNK_NAME } from '../../../../../const/generator'; import { BuilderComponentPlugin, @@ -6,7 +6,7 @@ import { FileType, ICodeStruct, IRouterInfo, -} from '@/types'; +} from '../../../../../types'; // TODO: How to merge this logic to common deps const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts index 62933484a..c5a268127 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts index b7e2a9565..9b99a2185 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts index 359a1b6b5..b30c7c58f 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts index 445fe9647..14876b397 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts index f115ec386..8f6f68e1f 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts index 02aed6eec..ad7ce4480 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts index e4c31b7ca..e7bed2e9e 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts index 387a02b1b..f5b5e9fa2 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts index f50c843d1..f6d2e9ed2 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts index 83b4dc8b7..66531c8dc 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts index aa1f1bd08..639337aa5 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts index 3f1f98511..cb57ac646 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts index 517972a5b..cef5376ae 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts index 214dcf88a..6969595e6 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts index 4e81e4b67..b722e6695 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts index 6c3fd945e..6f7cd7b92 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts index 1ed76f426..70ed04738 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts index ee0c9367f..5d369298a 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts index 51f420222..7ed60d2c9 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts index 7d2c26261..4b8aab7ed 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts @@ -1,5 +1,5 @@ -import ResultFile from '@/model/ResultFile'; -import { IResultFile } from '@/types'; +import ResultFile from '../../../../../../model/ResultFile'; +import { IResultFile } from '../../../../../../types'; export default function getFile(): [string[], IResultFile] { const file = new ResultFile( diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts index 326290e3e..2a1f3a285 100644 --- a/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts +++ b/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts @@ -1,5 +1,9 @@ -import ResultDir from '@/model/ResultDir'; -import { IProjectTemplate, IResultDir, IResultFile } from '@/types'; +import ResultDir from '../../../../../model/ResultDir'; +import { + IProjectTemplate, + IResultDir, + IResultFile, +} from '../../../../../types'; import file12 from './files/abc.json'; import file11 from './files/build.json'; diff --git a/packages/code-generator/src/plugins/project/i18n.ts b/packages/code-generator/src/plugins/project/i18n.ts index 59e05b8d4..14b9ef773 100644 --- a/packages/code-generator/src/plugins/project/i18n.ts +++ b/packages/code-generator/src/plugins/project/i18n.ts @@ -1,12 +1,12 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; -import { generateCompositeType } from '@/plugins/utils/compositeType'; +import { COMMON_CHUNK_NAME } from '../../const/generator'; +import { generateCompositeType } from '../../plugins/utils/compositeType'; import { BuilderComponentPlugin, ChunkType, FileType, ICodeStruct, IProjectInfo, -} from '@/types'; +} from '../../types'; // TODO: How to merge this logic to common deps const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/project/utils.ts b/packages/code-generator/src/plugins/project/utils.ts index 8a104dc45..f40ba41e2 100644 --- a/packages/code-generator/src/plugins/project/utils.ts +++ b/packages/code-generator/src/plugins/project/utils.ts @@ -1,13 +1,12 @@ -import { COMMON_CHUNK_NAME } from '@/const/generator'; -import { generateCompositeType } from '@/plugins/utils/compositeType'; -// import { } from '@/plugins/utils/jsExpression'; +import { COMMON_CHUNK_NAME } from '../../const/generator'; + import { BuilderComponentPlugin, ChunkType, FileType, ICodeStruct, IUtilInfo, -} from '@/types'; +} from '../../types'; // TODO: How to merge this logic to common deps const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { diff --git a/packages/code-generator/src/plugins/utils/compositeType.ts b/packages/code-generator/src/plugins/utils/compositeType.ts index a1bfdf220..2e102fcac 100644 --- a/packages/code-generator/src/plugins/utils/compositeType.ts +++ b/packages/code-generator/src/plugins/utils/compositeType.ts @@ -1,4 +1,4 @@ -import { CompositeArray, CompositeValue, ICompositeObject } from '@/types'; +import { CompositeArray, CompositeValue, ICompositeObject } from '../../types'; import { generateValue, isJsExpression } from './jsExpression'; function generateArray(value: CompositeArray): string { diff --git a/packages/code-generator/src/postprocessor/prettier/index.ts b/packages/code-generator/src/postprocessor/prettier/index.ts index 694038aa0..947c535c2 100644 --- a/packages/code-generator/src/postprocessor/prettier/index.ts +++ b/packages/code-generator/src/postprocessor/prettier/index.ts @@ -1,6 +1,6 @@ import prettier from 'prettier'; -import { PostProcessor } from '@/types'; +import { PostProcessor } from '../../types'; const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue']; diff --git a/packages/code-generator/src/publisher/disk/index.ts b/packages/code-generator/src/publisher/disk/index.ts index a806e2ce4..77f45c07a 100644 --- a/packages/code-generator/src/publisher/disk/index.ts +++ b/packages/code-generator/src/publisher/disk/index.ts @@ -1,4 +1,4 @@ -import { CodeGeneratorError, IResultDir } from '@/types'; +import { CodeGeneratorError, IResultDir } from '../../types'; export type PublisherFactory = (configuration?: Partial) => U; diff --git a/packages/code-generator/src/publisher/disk/utils.ts b/packages/code-generator/src/publisher/disk/utils.ts index 4352031ef..35fbbc2ad 100644 --- a/packages/code-generator/src/publisher/disk/utils.ts +++ b/packages/code-generator/src/publisher/disk/utils.ts @@ -1,7 +1,7 @@ import { existsSync, mkdir, writeFile } from 'fs'; import { join } from 'path'; -import { IResultDir, IResultFile } from '@/types'; +import { IResultDir, IResultFile } from '../../types'; export const writeFolder = async ( folder: IResultDir, diff --git a/packages/code-generator/src/solutions/icejs.ts b/packages/code-generator/src/solutions/icejs.ts index e8091e69b..10fe842c4 100644 --- a/packages/code-generator/src/solutions/icejs.ts +++ b/packages/code-generator/src/solutions/icejs.ts @@ -1,27 +1,27 @@ -import { IProjectBuilder } from '@/types'; +import { IProjectBuilder } from '../types'; -import { createProjectBuilder } from '@/generator/ProjectBuilder'; +import { createProjectBuilder } from '../generator/ProjectBuilder'; -import esmodule from '@/plugins/common/esmodule'; -import containerClass from '@/plugins/component/react/containerClass'; -import containerInitState from '@/plugins/component/react/containerInitState'; -// import containerInjectUtils from '@/plugins/component/react/containerInjectUtils'; -import containerLifeCycle from '@/plugins/component/react/containerLifeCycle'; -import containerMethod from '@/plugins/component/react/containerMethod'; -import jsx from '@/plugins/component/react/jsx'; -import reactCommonDeps from '@/plugins/component/react/reactCommonDeps'; -import css from '@/plugins/component/style/css'; -import constants from '@/plugins/project/constants'; -import iceJsEntry from '@/plugins/project/framework/icejs/plugins/entry'; -import iceJsEntryHtml from '@/plugins/project/framework/icejs/plugins/entryHtml'; -import iceJsGlobalStyle from '@/plugins/project/framework/icejs/plugins/globalStyle'; -import iceJsPackageJSON from '@/plugins/project/framework/icejs/plugins/packageJSON'; -import iceJsRouter from '@/plugins/project/framework/icejs/plugins/router'; -import template from '@/plugins/project/framework/icejs/template'; -import i18n from '@/plugins/project/i18n'; -import utils from '@/plugins/project/utils'; +import esmodule from '../plugins/common/esmodule'; +import containerClass from '../plugins/component/react/containerClass'; +import containerInitState from '../plugins/component/react/containerInitState'; +import containerInjectUtils from '../plugins/component/react/containerInjectUtils'; +import containerLifeCycle from '../plugins/component/react/containerLifeCycle'; +import containerMethod from '../plugins/component/react/containerMethod'; +import jsx from '../plugins/component/react/jsx'; +import reactCommonDeps from '../plugins/component/react/reactCommonDeps'; +import css from '../plugins/component/style/css'; +import constants from '../plugins/project/constants'; +import iceJsEntry from '../plugins/project/framework/icejs/plugins/entry'; +import iceJsEntryHtml from '../plugins/project/framework/icejs/plugins/entryHtml'; +import iceJsGlobalStyle from '../plugins/project/framework/icejs/plugins/globalStyle'; +import iceJsPackageJSON from '../plugins/project/framework/icejs/plugins/packageJSON'; +import iceJsRouter from '../plugins/project/framework/icejs/plugins/router'; +import template from '../plugins/project/framework/icejs/template'; +import i18n from '../plugins/project/i18n'; +import utils from '../plugins/project/utils'; -import { prettier } from '@/postprocessor'; +import { prettier } from '../postprocessor'; export default function createIceJsProjectBuilder(): IProjectBuilder { return createProjectBuilder({ @@ -31,7 +31,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder { reactCommonDeps, esmodule, containerClass, - // containerInjectUtils, + containerInjectUtils, containerInitState, containerLifeCycle, containerMethod, @@ -42,7 +42,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder { reactCommonDeps, esmodule, containerClass, - // containerInjectUtils, + containerInjectUtils, containerInitState, containerLifeCycle, containerMethod, diff --git a/packages/code-generator/src/types/core.ts b/packages/code-generator/src/types/core.ts index 8fedf317b..804f4f3e6 100644 --- a/packages/code-generator/src/types/core.ts +++ b/packages/code-generator/src/types/core.ts @@ -143,3 +143,8 @@ export interface IProjectBuilder { } export type PostProcessor = (content: string, fileType: string) => string; + +// TODO: temp interface, need modify +export interface IPluginOptions { + fileDirDepth: number; +} diff --git a/packages/code-generator/src/utils/children.ts b/packages/code-generator/src/utils/children.ts index 3d848f988..2f2d34fda 100644 --- a/packages/code-generator/src/utils/children.ts +++ b/packages/code-generator/src/utils/children.ts @@ -3,7 +3,7 @@ import { ChildNodeType, IComponentNodeItem, IJSExpression, -} from '@/types'; +} from '../types'; // tslint:disable-next-line: no-empty const noop = () => []; diff --git a/packages/code-generator/tsconfig.json b/packages/code-generator/tsconfig.json index 2660ef448..eb8638577 100644 --- a/packages/code-generator/tsconfig.json +++ b/packages/code-generator/tsconfig.json @@ -1,17 +1,12 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "target": "es5", - "strictNullChecks": true, - "inlineSources": false, - "lib": ["es6"], - "downlevelIteration": true, - "paths": { - "@/*": ["./src/*"] - }, "outDir": "./lib", + "lib": [ + "es6" + ], "types": ["node"], - "baseUrl": "." /* Base directory to resolve non-absolute module names. */ + "baseUrl": ".", /* Base directory to resolve non-absolute module names. */ }, "include": [ "src/**/*" diff --git a/packages/code-generator/webpack.config.js b/packages/code-generator/webpack.config.js deleted file mode 100644 index 00f21d2e1..000000000 --- a/packages/code-generator/webpack.config.js +++ /dev/null @@ -1,31 +0,0 @@ -const path = require('path'); -const nodeExternals = require('webpack-node-externals'); -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); - -module.exports = { - mode: 'production', - target: 'node', - entry: { - index: './src/index.ts', - // demo: './src/demo/main.ts', - }, - module: { - rules: [ - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/, - }, - ], - }, - resolve: { - extensions: [ '.tsx', '.ts', '.js' ], - plugins: [new TsconfigPathsPlugin({/* options: see below */})], - }, - output: { - // filename: 'bundle.js', - filename: '[name].js', - path: path.resolve(__dirname, 'lib'), - }, - externals: [nodeExternals()], // in order to ignore all modules in node_modules folder -}; From 2cf8573b7808bdbdf14eb234595189287f7f5967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8B=E7=BE=8A?= Date: Fri, 17 Apr 2020 10:39:29 +0800 Subject: [PATCH 09/21] =?UTF-8?q?feat:=E5=88=A0=E9=99=A4=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=A4=9A=E4=BD=99=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/demo/src/editor/config/skeleton.js | 4 +- packages/editor-core/src/areaManager.ts | 2 +- packages/editor-core/src/editor.ts | 2 +- packages/editor-core/src/index.ts | 1 - packages/editor-skeleton/src/index.ts | 4 +- packages/react-renderer/src/adapter/rax.jsx | 33 - .../react-renderer/src/comp/addon/index.jsx | 87 --- .../react-renderer/src/comp/canvas/index.jsx | 729 ------------------ .../react-renderer/src/comp/canvas/index.scss | 361 --------- .../react-renderer/src/hoc/addonFactory.js | 55 -- .../react-renderer/src/hoc/compFactory.js | 75 -- .../react-renderer/src/hoc/localeConfig.js | 29 - .../react-renderer/src/hoc/suspenseWrapper.js | 15 - .../react-renderer/src/utils/appHelper.js | 49 -- .../react-renderer/src/utils/dndHelper.js | 574 -------------- .../react-renderer/src/utils/postMessager.js | 59 -- .../react-renderer/src/utils/schemaHelper.js | 482 ------------ .../react-renderer/src/utils/storageHelper.js | 81 -- .../src/utils/undoRedoHelper.js | 88 --- packages/react-renderer/src/utils/wsHelper.js | 87 --- 20 files changed, 8 insertions(+), 2809 deletions(-) delete mode 100644 packages/react-renderer/src/adapter/rax.jsx delete mode 100644 packages/react-renderer/src/comp/addon/index.jsx delete mode 100644 packages/react-renderer/src/comp/canvas/index.jsx delete mode 100644 packages/react-renderer/src/comp/canvas/index.scss delete mode 100644 packages/react-renderer/src/hoc/addonFactory.js delete mode 100644 packages/react-renderer/src/hoc/compFactory.js delete mode 100644 packages/react-renderer/src/hoc/localeConfig.js delete mode 100644 packages/react-renderer/src/hoc/suspenseWrapper.js delete mode 100644 packages/react-renderer/src/utils/appHelper.js delete mode 100644 packages/react-renderer/src/utils/dndHelper.js delete mode 100644 packages/react-renderer/src/utils/postMessager.js delete mode 100644 packages/react-renderer/src/utils/schemaHelper.js delete mode 100644 packages/react-renderer/src/utils/storageHelper.js delete mode 100644 packages/react-renderer/src/utils/undoRedoHelper.js delete mode 100644 packages/react-renderer/src/utils/wsHelper.js diff --git a/packages/demo/src/editor/config/skeleton.js b/packages/demo/src/editor/config/skeleton.js index a772f94ee..4a8e417cc 100644 --- a/packages/demo/src/editor/config/skeleton.js +++ b/packages/demo/src/editor/config/skeleton.js @@ -68,7 +68,9 @@ export default { "align": "top", "icon": "zujianku", "title": "组件库", - "floatable": true + "panelProps": { + "floatable": true + } }, "config": { "package": "@ali/lowcode-plugin-components-pane", diff --git a/packages/editor-core/src/areaManager.ts b/packages/editor-core/src/areaManager.ts index f6ce5e782..666f4d6d2 100644 --- a/packages/editor-core/src/areaManager.ts +++ b/packages/editor-core/src/areaManager.ts @@ -18,7 +18,7 @@ export default class AreaManager { this.pluginStatus = clone(editor.pluginStatus); } - public isPluginStatusUpdate(pluginType?: string, notUpdateStatus?: boolean): boolean { + isPluginStatusUpdate(pluginType?: string, notUpdateStatus?: boolean): boolean { const { pluginStatus } = this.editor; const list = pluginType ? this.config.filter((item): boolean => item.type === pluginType) : this.config; diff --git a/packages/editor-core/src/editor.ts b/packages/editor-core/src/editor.ts index 6f9a1a01f..06bd5f133 100644 --- a/packages/editor-core/src/editor.ts +++ b/packages/editor-core/src/editor.ts @@ -77,7 +77,7 @@ export default class Editor extends EventEmitter { return instance; }; - public config: EditorConfig; + config: EditorConfig; public components: PluginClassSet; diff --git a/packages/editor-core/src/index.ts b/packages/editor-core/src/index.ts index 92e36fa4b..89ecdbfda 100644 --- a/packages/editor-core/src/index.ts +++ b/packages/editor-core/src/index.ts @@ -1,7 +1,6 @@ import Editor from './editor'; import * as utils from './utils'; -export * from './definitions'; export { default as PluginFactory } from './pluginFactory'; export { default as EditorContext } from './context'; diff --git a/packages/editor-skeleton/src/index.ts b/packages/editor-skeleton/src/index.ts index c519f0552..061621d42 100644 --- a/packages/editor-skeleton/src/index.ts +++ b/packages/editor-skeleton/src/index.ts @@ -1,7 +1,9 @@ import Skeleton from './skeleton'; import Panel from './components/Panel'; import TopIcon from './components/TopIcon'; +import TopPlugin from './components/TopPlugin'; +import LeftPlugin from './components/LeftPlugin'; export default Skeleton; -export { Panel, TopIcon }; +export { Panel, TopIcon, TopPlugin, LeftPlugin }; diff --git a/packages/react-renderer/src/adapter/rax.jsx b/packages/react-renderer/src/adapter/rax.jsx deleted file mode 100644 index 85176ff68..000000000 --- a/packages/react-renderer/src/adapter/rax.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import { createElement, render, useState } from 'rax'; -import React, { PureComponent } from 'react'; -import DriverUniversal from 'driver-universal'; -import { Engine } from '@ali/iceluna-rax'; -import findDOMNode from 'rax-find-dom-node'; - -let updateRax = () => {}; - -export default class Rax extends PureComponent { - constructor(props) { - super(props); - } - - componentDidMount() { - const RaxEngine = () => { - const [config, setConfig] = useState(this.props); - updateRax = setConfig; - return createElement(Engine, { - ...config, - }); - }; - render(createElement(RaxEngine), document.getElementById('luna-rax-container'), { driver: DriverUniversal }); - } - componentDidUpdate() { - updateRax(this.props); - } - - render() { - return
; - } -} - -Rax.findDOMNode = findDOMNode; diff --git a/packages/react-renderer/src/comp/addon/index.jsx b/packages/react-renderer/src/comp/addon/index.jsx deleted file mode 100644 index 1222a8c8b..000000000 --- a/packages/react-renderer/src/comp/addon/index.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import { PureComponent } from 'react'; -import PropTypes from 'prop-types'; - -import AppContext from '../../context/appContext'; -import { isEmpty, generateI18n, goldlog } from '../../utils'; - -export default class Addon extends PureComponent { - static displayName = 'lunaAddon'; - static propTypes = { - config: PropTypes.object, - locale: PropTypes.string, - messages: PropTypes.object, - }; - static defaultProps = { - config: {}, - }; - static contextType = AppContext; - constructor(props, context) { - super(props, context); - if (isEmpty(props.config) || !props.config.addonKey) { - console.warn('luna addon has wrong config'); - return; - } - // 插件上下文中的appHelper使用IDE的appHelper - context.appHelper = (window.__ctx && window.__ctx.appHelper) || context.appHelper; - context.locale = props.locale; - context.messages = props.messages; - // 注册插件 - this.appHelper = context.appHelper; - let { locale, messages } = props; - this.i18n = generateI18n(locale, messages); - this.addonKey = props.config.addonKey; - this.appHelper.addons = this.appHelper.addons || {}; - this.appHelper.addons[this.addonKey] = this; - } - - async componentWillUnmount() { - // 销毁插件 - const config = this.props.config || {}; - if (config && this.appHelper.addons) { - delete this.appHelper.addons[config.addonKey]; - } - } - - open = () => { - return true; - }; - - close = () => { - return true; - }; - - goldlog = (goKey, params) => { - const { addonKey, addonConfig = {} } = this.props.config || {}; - goldlog( - goKey, - { - addonKey, - package: addonConfig.package, - version: addonConfig.version, - ...this.appHelper.logParams, - ...params, - }, - 'addon', - ); - }; - - get utils() { - return this.appHelper.utils; - } - - get constants() { - return this.appHelper.constants; - } - - get history() { - return this.appHelper.history; - } - - get location() { - return this.appHelper.location; - } - - render() { - return null; - } -} diff --git a/packages/react-renderer/src/comp/canvas/index.jsx b/packages/react-renderer/src/comp/canvas/index.jsx deleted file mode 100644 index 355eba566..000000000 --- a/packages/react-renderer/src/comp/canvas/index.jsx +++ /dev/null @@ -1,729 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { on, off } from '@ali/b3-one/lib/event'; -import AppHelper from '../../utils/appHelper'; -import SchemaHelper from '../../utils/schemaHelper'; -import DndHelper from '../../utils/dndHelper'; -import Engine from '../../engine'; - -import CompFactory from '../../hoc/compFactory'; -import { - isSchema, - isFileSchema, - isEmpty, - isJSSlot, - jsonuri, - registShortCuts, - unRegistShortCuts, - generateUtils, - parseObj, - shallowEqual, - addCssTag, - transformSchemaToPure, - goldlog, -} from '../../utils'; -import './index.scss'; - -const DESIGN_MODE = { - EXTEND: 'extend', - BORDER: 'border', - PREVIEW: 'preview', -}; - -const DEFAULT_PLACEHOLDER = { - emptyImage: '//img.alicdn.com/tfs/TB1zpkUoUT1gK0jSZFhXXaAtVXa-620-430.png', - emptyText: '当前页面为空~\n请拖拽组件放入页面容器内吧!', - nullImage: '//img.alicdn.com/tfs/TB1m_oSoND1gK0jSZFsXXbldVXa-620-430.png', - nullText: '编辑内容不存在~!', -}; - -export default class Canvas extends PureComponent { - static displayName = 'Canvas'; - static propTypes = { - appHelper: PropTypes.object, - components: PropTypes.object, - engine: PropTypes.element, - onCreate: PropTypes.func, - initSchema: PropTypes.object, - shortCuts: PropTypes.array, - utils: PropTypes.object, - }; - static defaultProps = { - components: {}, - engine: Engine, - onCreate: () => {}, - initSchema: {}, - shortCuts: [], - utils: {}, - }; - constructor(props) { - super(props); - this.appHelper = props.appHelper || new AppHelper(); - if (!this.appHelper.schemaHelper) { - this.appHelper.set('schemaHelper', new SchemaHelper(props.initSchema || {}, this.appHelper)); - } - this.appHelper.set('basicSchemaHelper', this.appHelper.schemaHelper); - if (!this.appHelper.dndHelper) { - this.appHelper.set('dndHelper', new DndHelper(this.appHelper)); - } - this.appHelper.dndHelper.setCanvasWin(window); - if (this.appHelper.designMode === undefined) { - this.appHelper.designMode = 'extend'; - } - - this.canvasAppHelper = new AppHelper({ - history: this.appHelper.history, - location: this.appHelper.location, - match: this.appHelper.match, - }); - - this.updateCanvasAppHelper(props); - this.appHelper.once('ide.ready', () => { - this.updateCanvasAppHelper(props); - }); - - window.__ctx = { - appHelper: this.appHelper, - canvasAppHelper: this.canvasAppHelper, - components: this.props.components, - }; - - window.goldlog = window.goldlog || window.parent.goldlog; - - this.state = { - canvasStack: [ - { - lunaKey: 'root', - lunaPath: '', - name: 'root', - schemaHelper: this.appHelper.schemaHelper, - schema: this.appHelper.schemaHelper.get('schema'), - }, - ], - }; - this.appHelper.set('canvasStack', this.state.canvasStack); - } - - componentDidMount() { - const appHelper = this.appHelper; - appHelper.batchOn(['behavior.undo', 'behavior.redo'], this.handleUndoRedo); - appHelper.on('schema.reset', this.handleSchemaReset); - appHelper.on('material.move', this.handleMaterialMove); - appHelper.on('material.add', this.handleMaterialAdd); - appHelper.on('material.remove', this.handleMaterialRemove); - appHelper.on('material.up', this.handleMaterialMoveUp); - appHelper.on('material.down', this.handleMaterialMoveDown); - appHelper.on('material.copy', this.handleMaterialCopy); - appHelper.on('material.update', this.handleMaterialUpdate); - appHelper.on('material.select', this.handleMaterialSelect); - appHelper.on('schemaHelper.schema.afterUpdate', this.handleReset); - appHelper.on('designMode.change', this.handleDesignModeChange); - appHelper.on('preview.change', this.handlePreviewChange); - appHelper.on('canvas.stack.push', this.handleCanvasPush); - appHelper.on('canvas.stack.pop', this.handleCanvasPop); - appHelper.on('canvas.stack.jump', this.handleCanvasJump); - appHelper.on('style.update', this.updateStyle); - appHelper.batchOn(['utils.update', 'constants.update', 'componentsMap.update'], this.handleCanvasAppHelperUpdate); - appHelper.on('viewPort.update', this.handleForceUpdate); - - registShortCuts(this.props.shortCuts, this.appHelper); - this.appHelper.set('canvas', this); - this.props.onCreate(this.appHelper); - appHelper.emit('canvas.ready', this); - goldlog( - 'EXP', - { - action: 'appear', - }, - 'canvas', - ); - } - - componentWillUnmount() { - const appHelper = this.appHelper; - appHelper.batchOff(['behavior.undo', 'behavior.redo'], this.handleUndoRedo); - appHelper.on('schema.reset', this.handleSchemaReset); - appHelper.off('material.move', this.handleMaterialMove); - appHelper.off('material.add', this.handleMaterialAdd); - appHelper.off('material.remove', this.handleMaterialRemove); - appHelper.off('material.up', this.handleMaterialMoveUp); - appHelper.off('material.down', this.handleMaterialMoveDown); - appHelper.off('material.copy', this.handleMaterialCopy); - appHelper.off('material.update', this.handleMaterialUpdate); - appHelper.off('material.select', this.handleMaterialSelect); - appHelper.off('schemaHelper.schema.afterUpdate', this.handleReset); - appHelper.off('designMode.change', this.handleDesignModeChange); - appHelper.off('preview.change', this.handlePreviewChange); - appHelper.off('canvas.stack.push', this.handleCanvasPush); - appHelper.off('canvas.stack.pop', this.handleCanvasPop); - appHelper.off('canvas.stack.jump', this.handleCanvasJump); - appHelper.off('style.update', this.updateStyle); - appHelper.batchOff(['utils.update', 'constants.update', 'componentsMap.update'], this.handleCanvasAppHelperUpdate); - appHelper.off('viewPort.update', this.handleForceUpdate); - unRegistShortCuts(this.props.shortCuts); - } - - // 消息处理 - - handleMaterialMove = ({ lunaKey, targetKey, direction }) => { - const appHelper = this.appHelper; - appHelper.schemaHelper.move(lunaKey, targetKey, direction); - appHelper.emit('behavior.record'); - }; - - handleMaterialAdd = ({ schema, targetKey, direction }) => { - if (!isSchema(schema)) { - throw new Error('物料schema结构异常,无法添加!'); - } - const appHelper = this.appHelper; - const addSchema = Array.isArray(schema) ? schema[0] : schema; - // 对于没有设置文件名的容器组件,交给画布外层处理 - if (isFileSchema(addSchema) && !addSchema.fileName) { - return appHelper.emit('onFileNameMaterial.add', { schema: addSchema, targetKey, direction }); - } - - const addKey = appHelper.schemaHelper.add(schema, targetKey, direction); - appHelper.emit('behavior.record'); - this.autoSelectComponent(addKey); - }; - - handleMaterialRemove = (lunaKey) => { - const appHelper = this.appHelper; - const schemaHelper = appHelper.schemaHelper; - const currCompSchema = schemaHelper.schemaMap[lunaKey]; - // 获取当前删除物料的相邻物料 - const nextCompSchema = jsonuri.get( - schemaHelper.schema, - currCompSchema.__ctx.lunaPath.replace(/\/(\d+)$/, (res, idx) => `/${parseInt(idx) + 1}`), - ); - const activeKey = (nextCompSchema && nextCompSchema.__ctx.lunaKey) || currCompSchema.__ctx.parentKey; - appHelper.schemaHelper.remove(lunaKey); - appHelper.emit('behavior.record'); - this.autoSelectComponent(activeKey); - }; - - handleMaterialMoveUp = (lunaKey) => { - const appHelper = this.appHelper; - appHelper.schemaHelper && appHelper.schemaHelper.slide(lunaKey, 'up'); - appHelper.emit('behavior.record'); - }; - - handleMaterialMoveDown = (lunaKey) => { - const appHelper = this.appHelper; - appHelper.schemaHelper && appHelper.schemaHelper.slide(lunaKey, 'down'); - appHelper.emit('behavior.record'); - }; - - handleMaterialCopy = (lunaKey) => { - const appHelper = this.appHelper; - const addKey = appHelper.schemaHelper.copy(lunaKey); - - appHelper.emit('behavior.record'); - this.autoSelectComponent(addKey); - }; - - handleMaterialUpdate = ({ lunaKey, props, propsKey }) => { - const appHelper = this.appHelper; - appHelper.schemaHelper.update(lunaKey, props); - appHelper.emit('behavior.record', { lunaKey, propsKey }); - }; - - handleMaterialSelect = (lunaKey, options) => { - const appHelper = this.appHelper; - if (appHelper.activeKey === lunaKey) return; - appHelper.set('activeKey', lunaKey); - appHelper.emit('material.select.change', lunaKey, options); - const preNode = document.querySelectorAll('[data-active=true]'); - if (preNode[0] && preNode[0].dataset.lunaKey === lunaKey) return; - (preNode || []).forEach((item) => { - item.removeAttribute('data-active'); - item.removeAttribute('data-nochild'); - }); - //判断是否容器组件且没有子元素 - if (!lunaKey) { - window.parent.t = window.t = null; - return; - } - let schema = appHelper.schemaHelper.schemaMap[lunaKey]; - if (!schema) return; - let componentInfo = appHelper.componentsMap[schema.componentName]; - const currentNode = document.querySelectorAll(`[data-luna-key=${lunaKey}]`); - (currentNode || []).forEach((item) => { - item.setAttribute('data-active', 'true'); - if (componentInfo && componentInfo.isContainer && schema && (!schema.children || !schema.children.length)) { - item.setAttribute('data-nochild', 'true'); - } - }); - // for debug - let ctx = this.appHelper.schemaHelper.compCtxMap[lunaKey]; - let ref = this.appHelper.schemaHelper.compThisMap[lunaKey]; - let t = { - ctx, - schema, - ref, - }; - t.__proto__ = ctx; - window.parent.t = window.t = t; - }; - - handleDesignModeChange = (designMode) => { - this.appHelper.set('designMode', designMode); - this.forceUpdate(); - }; - - handlePreviewChange = (isPreview) => { - this.appHelper.set('isPreview', isPreview); - this.forceUpdate(); - }; - - handleUndoRedo = (schema) => { - this.appHelper.schemaHelper.reset(schema); - this.autoSelectComponent(); - }; - - handleSchemaReset = (schema) => { - this.appHelper.schemaHelper.reset(schema); - this.appHelper.emit('behavior.record'); - this.autoSelectComponent(); - }; - - handleReset = () => { - this.updateCanvasStack(); - this.forceUpdate(); - this.updateStyle(); - }; - - handleCanvasAppHelperUpdate = () => { - this.updateCanvasAppHelper(); - this.forceUpdate(); - }; - - handleForceUpdate = () => { - this.forceUpdate(); - }; - - handleCanvasPush = ({ schema, lunaKey, name }) => { - const appHelper = this.appHelper; - appHelper.emit('canvas.stack.beforePush'); - const { canvasStack } = this.state; - const tempSchema = { - componentName: 'Temp', - fileName: 'temp', - props: {}, - children: isJSSlot(schema) ? schema.value : schema, //兼容slot - }; - const schemaHelper = new SchemaHelper(transformSchemaToPure(tempSchema), this.appHelper); - const schemaMap = this.appHelper.schemaHelper.schemaMap || {}; - const compCtxMap = this.appHelper.schemaHelper.compCtxMap || {}; - const currentComp = schemaMap[lunaKey]; - const undoRedoKey = `${lunaKey}_${canvasStack.length}`; - //若是第一层下钻需要先给最上层加上从appHelper中获取的undoRedoKey - if (canvasStack.length === 1) { - canvasStack[0].undoRedoKey = this.appHelper.undoRedoKey; - } - const currentData = { - lunaKey, - lunaPath: currentComp.__ctx.lunaPath, - name, - schema, - schemaHelper, - ctx: compCtxMap[lunaKey], - undoRedoKey, - componentName: currentComp.componentName, - }; - appHelper.set('schemaHelper', schemaHelper); - appHelper.undoRedoHelper && appHelper.undoRedoHelper.create(undoRedoKey, tempSchema); - appHelper.set('undoRedoKey', undoRedoKey); - appHelper.set('activeKey', null); - this.setState( - { - canvasStack: [...this.state.canvasStack, currentData], - }, - () => { - this.appHelper.set('canvasStack', this.state.canvasStack); - this.appHelper.emit('canvas.stack.afterPush', currentData, this.state.canvasStack); - this.autoSelectComponent(); - }, - ); - }; - - handleCanvasPop = () => { - const { canvasStack } = this.state; - if (canvasStack.length > 1) { - this.handleCanvasJump(null, true); - } - }; - - handleCanvasJump = (idx, isPop) => { - const { canvasStack } = this.state; - const appHelper = this.appHelper; - let preIdx = idx + 1; - if (isPop) { - appHelper.emit('canvas.stack.beforePop'); - preIdx = canvasStack.length - 1; - idx = preIdx - 1; - } else { - appHelper.emit('canvas.stack.beforeJump'); - } - if (idx < 0 || idx > canvasStack.length - 1) return; - const preData = canvasStack[preIdx]; - const currentData = canvasStack[idx]; - appHelper.set('schemaHelper', currentData.schemaHelper); - appHelper.set('undoRedoKey', currentData.undoRedoKey); - appHelper.undoRedoHelper && appHelper.undoRedoHelper.delete(preData.undoRedoKey); - this.setState( - { - canvasStack: canvasStack.slice(0, idx + 1), - }, - () => { - appHelper.set('canvasStack', this.state.canvasStack); - appHelper.schemaHelper.reset(appHelper.schemaHelper.schema); - appHelper.emit('behavior.record'); - appHelper.emit(`canvas.stack.${isPop ? 'afterPop' : 'afterJump'}`, preData, this.state.canvasStack); - this.autoSelectComponent(preData.lunaKey); - }, - ); - }; - - // 引擎处理函数 - - handleCompGetCtx = (schema, ctx) => { - const lunaKey = schema && schema.__ctx && schema.__ctx.lunaKey; - if (!lunaKey) return; - // console.log('+++++ getCtx', lunaKey, ctx); - this.appHelper.schemaHelper.compCtxMap[lunaKey] = ctx; - // for debug - if (this.appHelper.activeKey && lunaKey === this.appHelper.activeKey) { - let ref = this.appHelper.schemaHelper.compThisMap[lunaKey]; - let t = { - ctx, - schema, - ref, - }; - t.__proto__ = ctx; - window.parent.t = window.t = t; - } - }; - - handleCompGetRef = (schema, ref, topLevel) => { - const lunaKey = schema && schema.__ctx && schema.__ctx.lunaKey; - if (!lunaKey) return; - // console.log('----- getRef', lunaKey, ref); - const schemaHelper = this.appHelper.schemaHelper; - schemaHelper.compThisMap[lunaKey] = ref; - if (ref && !ref.__design) { - this.updateDesignMode(ref, schema, topLevel); - const didUpdate = ref.componentDidUpdate; - ref.componentDidUpdate = (...args) => { - didUpdate && didUpdate.apply(ref, args); - this.updateDesignMode(ref, schema, topLevel); - }; - const willUnmount = ref.componentWillUnmount; - ref.componentWillUnmount = (...args) => { - willUnmount && willUnmount.apply(ref, args); - // console.log('----- destroy', lunaKey, ref); - delete schemaHelper.compThisMap[lunaKey]; - delete schemaHelper.compCtxMap[lunaKey]; - }; - ref.__design = true; - } - }; - - handleDnd = (type, ev, schema) => { - const lunaKey = schema && schema.__ctx && schema.__ctx.lunaKey; - const designMode = this.appHelper.designMode; - if (!lunaKey || ![DESIGN_MODE.EXTEND, DESIGN_MODE.BORDER].includes(designMode)) return; - const dndHelper = this.appHelper && this.appHelper.dndHelper; - if (dndHelper) { - dndHelper[`handle${type}`](ev, lunaKey); - } - }; - - //自动选中组件 - autoSelectComponent = (lunaKey) => { - const appHelper = this.appHelper; - // 若未指定需要选中的组件,且当前有选中的组件不做处理 - if (appHelper.activeKey && !lunaKey) return; - if (!lunaKey) { - // 若没有指定的组件,且当前又没有选中组件,默认选中顶部组件,如果是下钻编辑则默认选中第一个子组件 - const schema = appHelper.schemaHelper.schema; - if (schema) { - if (schema.componentName === 'Temp') { - lunaKey = schema.children && schema.children[0] && schema.children[0].__ctx.lunaKey; - } else { - lunaKey = schema.__ctx.lunaKey; - } - } - } - appHelper.emit('material.select', lunaKey); - }; - - // 构造低代码组件 - generateLowComps = (props = this.props) => { - const { components } = props; - const { utils, constants } = this.canvasAppHelper || {}; - const componentsMap = this.appHelper.componentsMap || {}; - Object.keys(componentsMap).forEach((key) => { - const comp = componentsMap[key]; - // 对自定义组件做特殊处理 - if (comp.version === '0.0.0' && comp.code) { - let schema = parseObj(comp.code); - if (isFileSchema(schema) && schema.componentName === 'Component') { - components[comp.name] = CompFactory(schema, components, componentsMap, { - utils, - constants, - }); - } - } - }); - return components; - }; - - updateCanvasAppHelper = (props = this.props) => { - const { utils } = props; - const { entityInfo = {}, componentsMap } = this.appHelper; - this.canvasAppHelper.set({ - componentsMap, - utils: entityInfo.utils ? generateUtils(utils, parseObj(entityInfo.utils)) : utils, - constants: parseObj((entityInfo && entityInfo.constants) || {}), - }); - this.canvasAppHelper.set('components', this.generateLowComps(props)); - }; - - updateStyle = () => { - const entityInfo = this.appHelper.entityInfo || {}; - const blockSchemaMap = (this.appHelper.schemaHelper && this.appHelper.schemaHelper.blockSchemaMap) || {}; - const componentsMap = this.appHelper.componentsMap || {}; - const cssMap = {}; - // 区块中的样式 - Object.keys(blockSchemaMap).forEach((item) => { - const schema = blockSchemaMap[item]; - cssMap[schema.fileName] = schema.css || (schema.__ctx && schema.__ctx.css) || ''; - }); - // 低代码自定义组件中的样式 - Object.keys(componentsMap).forEach((item) => { - const comp = componentsMap[item]; - // 对自定义组件做特殊处理 - if (comp.version === '0.0.0' && comp.code && comp.css) { - cssMap[comp.name] = comp.css; - } - }); - cssMap.__global = entityInfo.css || ''; - if (shallowEqual(this.cacheCssMap, cssMap)) return; - this.cacheCssMap = cssMap; - const { __global, ...other } = cssMap; - addCssTag( - 'luna-canvas-style', - `${__global}\n${Object.keys(other || {}) - .map((item) => cssMap[item]) - .join('\n')}`, - ); - }; - - updateCanvasStack = () => { - const { canvasStack } = this.state; - if (canvasStack.length < 2) return; - for (let idx = canvasStack.length - 1; idx > 0; idx--) { - const currentData = canvasStack[idx]; - const { lunaPath, name, schemaHelper, schema } = currentData; - const preData = canvasStack[idx - 1]; - let data = schemaHelper.getPureSchema().children; - // 如果情况内容则删除属性 - if (isEmpty(data)) { - jsonuri.rm( - preData.schemaHelper.schema, - name === 'children' ? `${lunaPath}/children` : `${lunaPath}/props/${name.replace('.', '/')}`, - ); - continue; - } - if (isJSSlot(schema)) { - data = { - ...schema, - value: data, - }; - } else if (name !== 'children') { - data = { - type: 'JSSlot', - value: data, - }; - } - jsonuri.set( - preData.schemaHelper.schema, - name === 'children' ? `${lunaPath}/children` : `${lunaPath}/props/${name.replace('.', '/')}`, - data, - ); - } - }; - - updateDesignMode = (ref, schema, topLevel) => { - if (!ref || (ref && ref.current === null) || !schema.__ctx) return; - const { engine } = this.props; - const appHelper = this.appHelper; - const { activeKey, isPreview, viewPortConfig } = appHelper; - const designMode = isPreview ? 'preview' : appHelper.designMode; - const node = engine.findDOMNode(ref.current || ref); - - if (!node || !node.getAttribute) return; - // 渲染引擎可以通过设置__disableDesignMode属性的方式阻止组件的可视模式; - const hasDesignMode = - [DESIGN_MODE.EXTEND, DESIGN_MODE.BORDER].includes(designMode) && !ref.props.__disableDesignMode; - node.setAttribute('data-design-mode', designMode && hasDesignMode ? `luna-design-${designMode}` : ''); - if (topLevel) { - node.setAttribute('top-container', true); - } - const lunaKey = schema.__ctx.lunaKey; - let instanceName = schema.componentName + (window.parent.__isDebug ? (lunaKey || '_').split('_')[1] : ''); - switch (schema.componentName) { - case 'Page': - instanceName = '页面容器 ' + instanceName; - break; - case 'Block': - instanceName = '区块容器 ' + instanceName; - break; - case 'Component': - instanceName = '低代码组件容器 ' + instanceName; - break; - case 'Addon': - instanceName = '插件容器 ' + instanceName; - break; - case 'Temp': - instanceName = '下钻编辑器容器'; - } - - if (topLevel && viewPortConfig) { - node.style.transform = `scale(${viewPortConfig.scale ? viewPortConfig.scale / 100 : 1})`; - } - node.setAttribute('data-instance-name', instanceName); - node.setAttribute('data-luna-key', lunaKey); - node.setAttribute('data-luna-path', schema.__ctx.lunaPath); - - if (hasDesignMode) { - if (activeKey && activeKey === lunaKey) { - node.setAttribute('data-active', true); - } else { - node.removeAttribute('data-active'); - } - // 点击 - if (!node.compEvent && schema.componentName !== 'Temp') { - node.compEvent = (ev) => { - ev.stopPropagation(); - appHelper.emit('material.select', lunaKey, { isFromCanvas: true }); - }; - on(node, 'mousedown', node.compEvent, false); - } - - // drag and drop - if (!node.draggableFlag) { - if (topLevel) { - node.ondragleave = (ev) => this.handleDnd('DragLeave', ev, schema); - node.ondrop = (ev) => this.handleDnd('Drop', ev, schema); - } else { - node.setAttribute('draggable', 'true'); - node.ondragstart = (ev) => this.handleDnd('DragStart', ev, schema); - node.ondragend = (ev) => this.handleDnd('DragEnd', ev, schema); - } - node.ondragover = (ev) => this.handleDnd('DragOver', ev, schema); - node.draggableFlag = true; - } - } else { - //点击 - if (node.compEvent) { - off(node, 'mousedown', node.compEvent, false); - delete node.compEvent; - } - //drag and drop - if (node.draggableFlag) { - node.removeAttribute('draggable'); - delete node.ondragstart; - delete node.ondragover; - delete node.ondragend; - delete node.ondragleave; - delete node.ondrop; - delete node.draggableFlag; - } - } - }; - - renderCanvasStack = () => { - const { canvasStack } = this.state; - const lastIndex = canvasStack.length - 1; - const appHelper = this.appHelper; - const canvasAppHelper = this.canvasAppHelper; - const designMode = appHelper.isPreview ? 'preview' : appHelper.designMode; - const Engine = this.props.engine; - - return (canvasStack || []).map((item, idx) => ( -
- -
- )); - }; - - render() { - const { canvasStack } = this.state; - const lastIndex = canvasStack.length - 1; - const schema = canvasStack[lastIndex] && canvasStack[lastIndex].schemaHelper.schema; - - const appHelper = this.appHelper; - const { entityInfo = {}, viewPortConfig = {}, canvasPlaceholder = {} } = appHelper; - const components = this.canvasAppHelper.components || {}; - - const placeholder = { ...DEFAULT_PLACEHOLDER, ...canvasPlaceholder }; - const layoutComp = entityInfo.layoutInfo && entityInfo.layoutInfo.name; - const layoutProps = (entityInfo.layoutInfo && entityInfo.layoutInfo.realProps) || {}; - const Layout = layoutComp && components[layoutComp]; - const { hideLayout } = viewPortConfig; - const isDrillDown = canvasStack && canvasStack.length > 1; - const isSchemaEmpty = isSchema(schema) && isEmpty(schema.children); - const isSchemaNull = schema === null; - const canvasStyle = {}; - if (!isDrillDown) { - if (isSchemaEmpty) { - canvasStyle.backgroundImage = `url(${placeholder.emptyImage})`; - } else if (isSchemaNull) { - canvasStyle.backgroundImage = `url(${placeholder.nullImage})`; - } - } - return ( -
- {Layout && !hideLayout ? ( - - {this.renderCanvasStack()} - - ) : ( - this.renderCanvasStack() - )} -
- ); - } -} diff --git a/packages/react-renderer/src/comp/canvas/index.scss b/packages/react-renderer/src/comp/canvas/index.scss deleted file mode 100644 index 3961561d4..000000000 --- a/packages/react-renderer/src/comp/canvas/index.scss +++ /dev/null @@ -1,361 +0,0 @@ -/*增加标签函数*/ -@mixin labelFun($type: before) { - &:#{$type} { - content: attr(data-instance-name) !important; - position: absolute; - left: 0; - top: 0; - right: unset; - bottom: unset; - color: #666 !important; - font-size: 12px !important; - float: left; - padding: 0 5px !important; - line-height: 12px !important; - height: 12px; - overflow: hidden; - background: rgba(222, 222, 222, 0.7); - z-index: 2; - border-left: 3px solid transparent; - transform-origin: 0 0; - transform: scale(0.8); - transition: all 0.3s ease; - } - - &.luna-block, - &.luna-page, - &.luna-comp { - &:#{$type} { - border-color: #2077ff; - } - } - - &[data-active='true'] { - &:#{$type} { - color: #fff !important; - background: #1861d5 !important; - } - } - - &[data-design-mode='luna-design-border'] { - &:#{$type} { - display: none; - } - - &[data-active='true'] { - &:#{$type} { - display: block; - } - } - } -} - -.luna-canvas-inner { - height: 100%; - - &.empty, - &.null { - position: relative; - background-repeat: no-repeat; - background-position: calc(50% - 180px) 50%; - background-size: 310px 215px; - - &:after { - content: attr(data-placeholder-text); - position: absolute; - pointer-events: none; - top: 50%; - left: 50%; - margin: -40px 0 0 20px; - height: 80px; - line-height: 40px; - color: #aaa; - font-size: 24px; - white-space: pre; - } - } - - &.empty { - &.drill-down { - &:before { - display: none; - } - - &:after { - content: '请拖入组件'; - text-align: center; - left: 0; - right: 0; - margin-left: 0; - font-size: 14px; - } - } - } - - .engine-wrapper { - height: 100%; - display: none; - overflow: auto; - - &.extend, - &.border { - padding: 1px; - - > div { - padding: 1px; - } - } - - &:last-child { - display: block; - } - - &.fixed-width > div { - min-width: unset; - width: auto; - } - - &.fixed-height > div { - min-height: unset; - } - - > div { - transform-origin: left top; - min-width: 100%; - width: fit-content; - min-height: 100%; - } - } -} - -a, -span:not(.next-input-group):not(.next-input) { - &[data-design-mode*='luna-design-'] { - display: inline-block; - min-height: 16px; - } -} - -[data-luna-key] { - transition: all 0.3s ease; -} - -[data-design-mode='luna-design-border'] { - min-height: 10px; -} - -[data-design-mode='luna-design-extend'] { - min-height: 20px; -} - -[data-design-mode*='luna-design-'] { - position: relative; - outline: 1px dotted #d9d9d9; - zoom: 1; - - &:hover { - outline: 1px dotted #2077ff; - } - - [draggable='true'] { - position: relative; - } - - .next-card-body { - overflow: inherit !important; - } - - &.next-loading { - pointer-events: all !important; - } - - &[data-active='true'] { - outline: 1px solid #1861d5 !important; - - &[data-nochild='true']:not(.next-step-item):not([top-container='true']) { - min-height: 60px; - min-width: 200px; - - &:after { - content: '请拖入组件'; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - margin: auto; - opacity: 1 !important; - visibility: visible !important; - line-height: 30px; - height: 30px; - font-size: 13px; - color: #ccc; - text-align: center; - } - } - } - - &:not(.next-tag):not(.next-icon):not(.anticon):not(.icon) { - @include labelFun(before); - } - - &.next-tag, - &.next-icon, - &.anticon, - &.icon { - @include labelFun(after); - } - - &.next-tabs-tabpane.hidden { - min-height: 0; - } - - &.ant-loop:after { - content: ''; - display: block; - clear: both; - line-height: 0; - } - - .ant-tabs-tabpane { - padding: 1px; - } - - .ide-design-placeholder { - position: relative; - text-align: center; - border: 1px dashed #d9d9d9; - outline: none; - padding: 0 !important; - min-height: 20px; - min-width: 80px; - - &:after { - content: attr(data-prop); - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - text-align: center; - line-height: 20px; - color: #e9e9e9; - } - } - - &[data-instance-name='TableGroupHeaderF'] { - clear: both; - - &:after { - content: ''; - width: 100%; - height: 0; - clear: both; - overflow: hidden; - } - } - - &[data-design-mode='luna-design-extend'] { - &[data-luna-key*='luna_'] { - &:not([class*='-input']):not([class*='-picker']):not([class*='-table']):not([class*='-switch']):not([class*='-select']):not(img):not([class*='-btn']):not(.next-tag):not(input):not([class*='-rating']):not([class*='next-menu']) { - padding: 10px; - } - - &.ant-loop { - padding: 10px 0 0; - } - } - - [class*='-form-item-control'] { - & > [data-design-mode*='luna-design-'] { - &:not(button):not(input):not([class*='-input']):not([class*='luna-comp-']) { - padding: 0 !important; - } - } - } - } -} - -#luna-canvas-effect { - position: fixed; - background: #1aab11; - z-index: 10000000; - text-align: center; - pointer-events: none; - - &:before, - &:after { - content: ''; - position: absolute; - width: 2px; - height: 2px; - border: 4px solid #1aab11; - pointer-events: none; - } - - &.left, - &.right { - width: 2px; - - &:before, - &:after { - left: -4px; - border-left-color: transparent; - border-right-color: transparent; - } - - &:before { - top: 0; - border-bottom-width: 0; - } - - &:after { - bottom: 0; - border-top-width: 0; - } - } - - &.top, - &.bottom, - &.in { - height: 2px; - - &:before, - &:after { - top: -4px; - border-top-color: transparent; - border-bottom-color: transparent; - } - - &:before { - left: 0; - border-right-width: 0; - } - - &:after { - right: 0; - border-left-width: 0; - } - } - - &.in { - b { - display: inline-block; - } - } - - b { - display: inline-block; - position: relative; - top: -12px; - margin: 0 auto; - padding: 0 10px; - color: #fff; - background: #1aab11; - height: 16px !important; - line-height: 16px !important; - font-weight: normal; - font-size: 11px; - display: none; - } -} diff --git a/packages/react-renderer/src/hoc/addonFactory.js b/packages/react-renderer/src/hoc/addonFactory.js deleted file mode 100644 index 67065239b..000000000 --- a/packages/react-renderer/src/hoc/addonFactory.js +++ /dev/null @@ -1,55 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import AddonEngine from '../engine/addonEngine'; -import BlockEngine from '../engine/blockEngine'; -import AppContext from '../context/appContext'; -import { forEach, isFileSchema } from '../utils'; -export default function addonFactory(schema, components = {}, componentsMap = {}, config = {}) { - class LNAddonView extends PureComponent { - static dislayName = 'luna-addon-factory'; - static version = config.version || '0.0.0'; - static contextType = AppContext; - static propTypes = { - forwardedRef: PropTypes.func, - }; - render() { - if (!schema || schema.componentName !== 'Addon' || !isFileSchema(schema)) { - console.warn('编辑器插件模型结构异常!'); - return null; - } - const { forwardedRef, ...otherProps } = this.props; - const props = { - ...schema.defaultProps, - ...otherProps, - __schema: schema, - ref: forwardedRef, - }; - return ( - - - - ); - } - } - const ResComp = React.forwardRef((props, ref) => ); - forEach(schema.static, (val, key) => { - ResComp[key] = val; - }); - ResComp.version = config.version || '0.0.0'; - return ResComp; -} diff --git a/packages/react-renderer/src/hoc/compFactory.js b/packages/react-renderer/src/hoc/compFactory.js deleted file mode 100644 index 49c32df7a..000000000 --- a/packages/react-renderer/src/hoc/compFactory.js +++ /dev/null @@ -1,75 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import CompEngine from '../engine/compEngine'; -import BlockEngine from '../engine/blockEngine'; -import AppContext from '../context/appContext'; -import AppHelper from '../utils/appHelper'; -import { forEach, isFileSchema } from '../utils'; -export default function compFactory(schema, components = {}, componentsMap = {}, config = {}) { - // 自定义组件需要有自己独立的appHelper - const appHelper = new AppHelper(config); - class LNCompView extends PureComponent { - static dislayName = 'luna-comp-factory'; - static version = config.version || '0.0.0'; - static contextType = AppContext; - static propTypes = { - forwardedRef: PropTypes.func, - }; - render() { - if (!schema || schema.componentName !== 'Component' || !isFileSchema(schema)) { - console.warn('自定义组件模型结构异常!'); - return null; - } - const { forwardedRef, ...otherProps } = this.props; - // 低代码组件透传应用上下文 - const appCtx = ['utils', 'constants']; - appCtx.forEach((key) => { - if (!appHelper[key] && this.context && this.context.appHelper && this.context.appHelper[key]) { - appHelper.set(key, this.context.appHelper[key]); - } - }); - const routerCtx = ['history', 'location', 'match']; - routerCtx.forEach((key) => { - if (this.context && this.context.appHelper && this.context.appHelper[key]) { - appHelper.set(key, this.context.appHelper[key]); - } - }); - // 支持通过context透传国际化配置 - const localeProps = {}; - const { locale, messages } = this.context; - if (locale && messages && messages[schema.fileName]) { - localeProps.locale = locale; - localeProps.messages = messages[schema.fileName]; - } - const props = { - ...schema.defaultProps, - ...localeProps, - ...otherProps, - __schema: schema, - ref: forwardedRef, - }; - - return ( - - - - ); - } - } - - const ResComp = React.forwardRef((props, ref) => ); - forEach(schema.static, (val, key) => { - ResComp[key] = val; - }); - ResComp.version = config.version || '0.0.0'; - return ResComp; -} diff --git a/packages/react-renderer/src/hoc/localeConfig.js b/packages/react-renderer/src/hoc/localeConfig.js deleted file mode 100644 index ccdfe3db4..000000000 --- a/packages/react-renderer/src/hoc/localeConfig.js +++ /dev/null @@ -1,29 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import AppContext from '../context/appContext'; -export default function localeConfig(componentName, Component) { - class LNLocaleConfigView extends PureComponent { - static dislayName = 'luna-locale-config'; - static contextType = AppContext; - static propTypes = { - forwardedRef: PropTypes.func, - }; - render() { - const { forwardedRef, ...otherProps } = this.props; - const { locale, messages } = this.context; - const localeProps = {}; - if (locale && messages && messages[componentName]) { - localeProps.locale = locale; - localeProps.messages = messages[componentName]; - } - const props = { - ...localeProps, - ...otherProps, - ref: forwardedRef, - }; - return ; - } - } - - return React.forwardRef((props, ref) => ); -} diff --git a/packages/react-renderer/src/hoc/suspenseWrapper.js b/packages/react-renderer/src/hoc/suspenseWrapper.js deleted file mode 100644 index 6a0224af7..000000000 --- a/packages/react-renderer/src/hoc/suspenseWrapper.js +++ /dev/null @@ -1,15 +0,0 @@ -import React, { PureComponent, Suspense } from 'react'; -export default function SuspenseWrapper(fallback = null) { - return function(Component) { - class SuspenseWrapper extends PureComponent { - render() { - return ( - - - - ); - } - } - return SuspenseWrapper; - }; -} diff --git a/packages/react-renderer/src/utils/appHelper.js b/packages/react-renderer/src/utils/appHelper.js deleted file mode 100644 index 8bec5fa83..000000000 --- a/packages/react-renderer/src/utils/appHelper.js +++ /dev/null @@ -1,49 +0,0 @@ -import EventEmitter from 'events'; -import Debug from 'debug'; -let instance = null; -const debug = Debug('utils:appHelper'); -EventEmitter.defaultMaxListeners = 100; - -export default class AppHelper extends EventEmitter { - static getInstance = () => { - if (!instance) { - instance = new AppHelper(); - } - return instance; - }; - - constructor(config) { - super(); - instance = this; - Object.assign(this, config); - } - - get(key) { - return this[key]; - } - - set(key, val) { - if (typeof key === 'string') { - this[key] = val; - } else if (typeof key === 'object') { - Object.keys(key).forEach((item) => { - this[item] = key[item]; - }); - } - } - - batchOn(events, lisenter) { - if (!Array.isArray(events)) return; - events.forEach((event) => this.on(event, lisenter)); - } - - batchOnce(events, lisenter) { - if (!Array.isArray(events)) return; - events.forEach((event) => this.once(event, lisenter)); - } - - batchOff(events, lisenter) { - if (!Array.isArray(events)) return; - events.forEach((event) => this.off(event, lisenter)); - } -} diff --git a/packages/react-renderer/src/utils/dndHelper.js b/packages/react-renderer/src/utils/dndHelper.js deleted file mode 100644 index 8bd20153c..000000000 --- a/packages/react-renderer/src/utils/dndHelper.js +++ /dev/null @@ -1,574 +0,0 @@ -import ReactDOM from 'react-dom'; -import Debug from 'debug'; -import { isFileSchema, isEmpty, throttle, deepEqual } from './index'; -const DICT = { - left: '左', - right: '右', - top: '上', - bottom: '下', - in: '里', -}; -const TOP_COMPONENT = ['Page', 'Component', 'Temp']; // 顶端模块,不支持放置兄弟节点 -const debug = Debug('utils:dndHelper'); -export default class DndHelper { - constructor(appHelper) { - this.appHelper = appHelper; - this.dragDom = null; - this.canvasEffectDom = null; - this.treeEffectDom = null; - this.containrDom = null; - this.sourceEntity = null; - this.tempEntity = null; - this.dragInfo = null; - this.canvasClearTimer = null; - this.treeClearTimer = null; - this.isDragging = false; - this.dragOverFunc = throttle(this.dragOverFunc, 50); - } - - setCanvasWin(win) { - this.canvasWin = win; - if (this.canvasEffectDom) { - this.canvasWin.document.body.appendChild(this.canvasEffectDom); - } - } - - emit(msg, ...args) { - this.appHelper && this.appHelper.emit(msg, ...args); - } - - dragOverFunc(ev, schemaOrNode, isTree) { - if (!this.isDragging || !this.sourceEntity) return; - const entity = isTree - ? this.getTreeEntity(schemaOrNode, ev) - : { - target: ev.currentTarget, - schema: schemaOrNode, - }; - if (this.sourceEntity.schema.__ctx && this.sourceEntity.schema.__ctx.lunaKey === entity.schema.__ctx.lunaKey) - return; - let dragInfo = null; - if (isTree) { - dragInfo = this.getTreeDragInfo(ev, entity); - } else { - dragInfo = this.getDragInfo(ev, entity); - } - if (!dragInfo || deepEqual(this.dragInfo, dragInfo)) return; - this.dragInfo = dragInfo; - this.tempEntity = dragInfo.entity; - this.clearEffect(isTree); - this.addEffect(isTree); - } - - changeCanvas() { - debug('change canvas', this.sourceEntity, this.tempEntity); - if (!this.sourceEntity || !this.tempEntity) return; - if (this.sourceEntity.isAdd) { - debug('add material', this.sourceEntity.schema, this.tempEntity.schema.__ctx.lunaKey, this.dragInfo.position); - this.emit('material.add', { - schema: this.sourceEntity.schema, - targetKey: this.tempEntity.schema.__ctx.lunaKey, - direction: this.dragInfo.position, - }); - } else { - this.emit('material.move', { - lunaKey: this.sourceEntity.schema.__ctx.lunaKey, - targetKey: this.tempEntity.schema.__ctx.lunaKey, - direction: this.dragInfo.position, - }); - } - } - - getTreeEntity(node, ev) { - if (!node) return; - const schemaHelper = this.appHelper.schemaHelper; - const lunaKey = node.props.eventKey; - const schema = schemaHelper.schemaMap[lunaKey]; - if (!schema) return; - const ref = schemaHelper.compThisMap[lunaKey]; - const currentTarget = ev.currentTarget; - return { - schema, - target: ref && ReactDOM.findDOMNode(ref), - treeNodeTarget: currentTarget, - }; - } - - getDragTagDom(tagName) { - if (!this.dragDom) { - const dragDom = document.createElement('div'); - dragDom.id = 'luna-drag-dom'; - dragDom.style.height = '24px'; - dragDom.style.position = 'absolute'; - dragDom.style.zIndex = 10000000; - dragDom.style.transform = 'translateY(-10000px)'; - dragDom.style.background = 'rgba(0, 0, 0, .5)'; - dragDom.style.lineHeight = '24px'; - dragDom.style.color = '#fff'; - dragDom.style.padding = '0px 10px'; - dragDom.style.display = 'inline-block'; - document.body.appendChild(dragDom); - this.dragDom = dragDom; - } - this.dragDom.innerHTML = ` ${tagName}`; - return this.dragDom; - } - - getCanvasEffectDom() { - if (!this.canvasWin) { - throw new Error('should set the canvasWin first'); - } - if (this.canvasClearTimer) { - clearTimeout(this.canvasClearTimer); - this.canvasClearTimer = null; - } - - const { position } = this.dragInfo; - let canvasEffectDom = this.canvasEffectDom; - if (!canvasEffectDom) { - canvasEffectDom = document.createElement('div'); - this.canvasWin.document.body.appendChild(canvasEffectDom); - this.canvasEffectDom = canvasEffectDom; - } - canvasEffectDom.id = 'luna-canvas-effect'; - canvasEffectDom.innerHTML = `${DICT[position]}`; - canvasEffectDom.className = position; - canvasEffectDom.style.display = 'block'; - - return canvasEffectDom; - } - - getTreeEffectDom() { - if (this.treeClearTimer) { - clearTimeout(this.treeClearTimer); - this.treeClearTimer = null; - } - let treeEffectDom = this.treeEffectDom; - if (!treeEffectDom) { - treeEffectDom = document.createElement('div'); - this.treeEffectDom = treeEffectDom; - } - treeEffectDom.id = 'luna-tree-effect'; - treeEffectDom.style.display = 'block'; - return treeEffectDom; - } - - getLunaContainerDom(target) { - if (!target) return null; - let parent = target.parentNode; - while (parent && (!parent.dataset || !parent.dataset.lunaKey)) { - parent = parent.parentNode; - } - return parent; - } - - clearCompTreeEffect() { - const container = document.querySelector('.luna-comp-tree'); - if (!container) return; - - let treeItems = container.querySelectorAll('.tree-item'); - (treeItems || []).forEach((item) => { - const classList = item.classList; - if (classList) { - classList.remove('top'); - classList.remove('in'); - classList.remove('bottom'); - classList.remove('tree-item'); - } - }); - } - - getDragInfo(ev, entity) { - if (!this.sourceEntity || !entity) return null; - const { target, schema } = entity; - const sourcePath = this.sourceEntity.schema.__ctx && this.sourceEntity.schema.__ctx.lunaPath; - const targetPath = schema.__ctx.lunaPath; - const sourceTarget = this.sourceEntity.target; - - if (sourcePath === targetPath) return null; - if (targetPath && targetPath.startsWith(sourcePath)) return null; - const componentsMap = this.appHelper.get('componentsMap'); - // if (!componentsMap || !componentsMap[schema.componentName]) return null; - let isContainer = - (componentsMap[schema.componentName] && componentsMap[schema.componentName].isContainer) || isFileSchema(schema); //是否是容器组件 - if (schema.children && typeof schema.children !== 'object') { - //如果children是文本, 非模型结构,则非容器; - isContainer = false; - } - const rect = target.getBoundingClientRect(); - const isSupportIn = - isContainer && - (!schema.children || (schema.children && typeof schema.children === 'object' && isEmpty(schema.children))); - const sourceIsInline = sourceTarget && ['inline-block', 'inline'].includes(getComputedStyle(sourceTarget).display); - const isInline = ['inline-block', 'inline'].includes(getComputedStyle(target).display) && sourceIsInline; - const measure = isInline ? 'width' : 'height'; - - let sn = 0; - let position = 'top'; - if (isContainer) { - sn = isSupportIn ? rect[measure] * 0.25 : Math.min(rect[measure] * 0.5, 10); - } else { - sn = rect[measure] * 0.5; - } - if (TOP_COMPONENT.includes(schema.componentName)) { - // 顶端组件,拖拽over时,只能放在其内部 - position = 'in'; - } else if (isInline && !isContainer) { - if (Math.abs(ev.clientX - rect.left) <= sn) { - position = 'left'; - } else if (Math.abs(ev.clientX - rect.right) <= sn) { - position = 'right'; - } - } else { - if (Math.abs(ev.clientY - rect.top) <= sn) { - position = 'top'; - } else if (Math.abs(ev.clientY - rect.bottom) <= sn) { - position = 'bottom'; - } else { - position = 'in'; - } - } - - // 判断是否是相邻元素, 往左|上拖 - const isPrevSibling = sourceTarget === target.nextElementSibling; - if (isPrevSibling) { - if (position === 'right') position = 'left'; - if (position === 'bottom') { - position = isContainer ? 'in' : 'top'; - } - } - // 判断是否相邻元素,往右|下拖 - const isPostSibling = sourceTarget === target.previousElementSibling; - if (isPostSibling) { - if (position === 'left') position = 'right'; - if (position === 'top') { - position = isContainer ? 'in' : 'bottom'; - } - } - - //如果是容器组件,且包含有子组件,且是in状态,进行智能识别处理; - let subChildren = []; - const getChildren = (node) => { - if (!node || !node.childNodes || node.childNodes.length === 0) return; - node.childNodes.forEach((child) => { - if (child === sourceTarget) return; - if (child && child.getAttribute && child.getAttribute('draggable')) { - const isInline = ['inline', 'inline-block'].includes(getComputedStyle(child).display) && sourceIsInline; - const rect = child.getBoundingClientRect(); - const l = Math.abs(ev.clientX - rect.left); - const r = Math.abs(ev.clientX - rect.right); - const t = Math.abs(ev.clientY - rect.top); - const b = Math.abs(ev.clientY - rect.bottom); - const minXDistance = Math.min(l, r); - const minYDistance = Math.min(t, b); - subChildren.push({ - lunaKey: child.dataset.lunaKey, - node: child, - minDistance: isInline ? [minXDistance, minYDistance] : [minYDistance, minXDistance], - position: isInline ? (l > r ? 'right' : 'left') : b > t ? 'top' : 'bottom', - }); - } else { - getChildren(child); - } - }); - }; - if (position === 'in' && isContainer && !isSupportIn) { - getChildren(target); - subChildren = subChildren.sort((a, b) => { - if (a.minDistance[0] === b.minDistance[0]) { - return a.minDistance[1] - b.minDistance[1]; - } - return a.minDistance[0] - b.minDistance[0]; - }); - const tempChild = subChildren[0]; - if (tempChild) { - if (sourceTarget === tempChild.node.nextElementSibling && ['bottom', 'right'].includes(tempChild.position)) - return null; - if (sourceTarget === tempChild.node.previousElementSibling && ['top', 'left'].includes(tempChild.position)) - return null; - position = tempChild.position; - entity = { - target: tempChild.node, - schema: this.appHelper.schemaHelper.schemaMap[tempChild.lunaKey], - }; - } - } - - const containrDom = position === 'in' ? entity.target : this.getLunaContainerDom(entity.target); - if (this.containrDom !== containrDom) { - if (this.containrDom) { - this.containrDom.style.outline = ''; - } - this.containrDom = containrDom; - } - if (this.containrDom) { - containrDom.style.outline = '1px solid #1aab11'; - } - // debug('drag info:', position, isSupportIn, isContainer, entity); - return { - position, - isSupportIn, - isContainer, - entity, - }; - } - - getTreeDragInfo(ev, entity) { - if (!this.sourceEntity || !entity) return null; - const { schema, treeNodeTarget } = entity; - const sourcePath = this.sourceEntity.schema.__ctx && this.sourceEntity.schema.__ctx.lunaPath; - const targetPath = schema.__ctx.lunaPath; - if (sourcePath === targetPath) return null; - if (targetPath && targetPath.startsWith(sourcePath)) return null; - const componentsMap = this.appHelper.get('componentsMap'); - // if (!componentsMap || !componentsMap[schema.componentName]) return null; - let isContainer = - (componentsMap[schema.componentName] && componentsMap[schema.componentName].isContainer) || isFileSchema(schema); //是否是容器组件 - if (schema.children && typeof schema.children !== 'object') { - //如果children是文本, 非模型结构,则非容器; - isContainer = false; - } - const rect = treeNodeTarget.getBoundingClientRect(); - const isSupportIn = - isContainer && - (!schema.children || (schema.children && typeof schema.children === 'object' && isEmpty(schema.children))); - - const sn = isContainer && isSupportIn ? rect.height * 0.25 : rect.height * 0.5; - let position = 'in'; - if (Math.abs(ev.clientY - rect.top) <= sn) { - position = 'top'; - } else if (Math.abs(ev.clientY - rect.bottom) <= sn) { - position = 'bottom'; - } - return { - position, - isSupportIn, - isContainer, - entity, - }; - } - - addEffect(isTree) { - if (!this.tempEntity) return; - const { position } = this.dragInfo; - const { target, treeNodeTarget } = this.tempEntity; - // this.clearCompTreeEffect(); - if (isTree) { - //画父元素外框 - let status = true; - let node = treeNodeTarget.parentNode; - while (status) { - if (node && node.parentNode) { - if (node.parentNode.tagName == 'LI' && node.parentNode.classList.contains('next-tree-node')) { - status = false; - if (this.treeNodeTargetParent !== node.parentNode || position === 'in') { - this.treeNodeTargetParent && this.treeNodeTargetParent.classList.remove('selected'); - } - this.treeNodeTargetParent = node.parentNode; - if (position !== 'in') this.treeNodeTargetParent.classList.add('selected'); - } else { - node = node.parentNode; - } - } else { - status = false; - } - } - treeNodeTarget.appendChild(this.getTreeEffectDom()); - this.treeEffectDom.className = position; - } else { - const effectDom = this.getCanvasEffectDom(); - const rect = target.getBoundingClientRect(); - effectDom.style.left = (position === 'right' ? rect.right : rect.left) + 'px'; - effectDom.style.top = - (position === 'bottom' ? rect.bottom : position === 'in' ? (rect.top + rect.bottom) / 2 : rect.top) + 'px'; - effectDom.style.height = ['top', 'in', 'bottom'].includes(position) ? '2px' : rect.height + 'px'; - effectDom.style.width = ['left', 'right'].includes(position) ? '2px' : rect.width + 'px'; - } - } - - clearCanvasEffect() { - if (this.canvasEffectDom) { - this.canvasEffectDom.style.display = 'none'; - } - if (this.containrDom) { - this.containrDom.style.outline = ''; - } - } - - clearTreeEffect() { - if (this.treeEffectDom) { - this.treeEffectDom.style.display = 'none'; - } - if (this.treeNodeTargetParent) { - this.treeNodeTargetParent.classList.remove('selected'); - } - const tempTarget = this.tempEntity && this.tempEntity.treeNodeTarget; - const classList = tempTarget && tempTarget.classList; - if (classList) { - classList.remove('top'); - classList.remove('bottom'); - classList.remove('in'); - classList.remove('tree-item'); - } - } - - clearEffect(isTree) { - if (this.isDragging) { - // if (isTree) { - if (this.treeClearTimer) { - clearTimeout(this.treeClearTimer); - this.treeClearTimer = null; - } - this.treeClearTimer = setTimeout(() => { - this.clearTreeEffect(); - }, 300); - // } else { - if (this.canvasClearTimer) { - clearTimeout(this.canvasClearTimer); - this.canvasClearTimer = null; - } - this.canvasClearTimer = setTimeout(() => { - this.clearCanvasEffect(); - }, 300); - // } - } else { - // if (isTree) { - this.clearTreeEffect(); - // } else { - this.clearCanvasEffect(); - // } - } - } - - handleDragStart(ev, lunaKey) { - ev.stopPropagation(); - const target = ev.currentTarget; - target.style.filter = 'blur(2px)'; - const schema = this.appHelper.schemaHelper.schemaMap[lunaKey]; - ev.dataTransfer.setDragImage(this.getDragTagDom(schema.componentName), 0, 0); - this.sourceEntity = { - target, - schema, - }; - this.isDragging = true; - } - - handleDragEnd(ev) { - ev.stopPropagation(); - ev.preventDefault(); - this.isDragging = false; - if (!this.sourceEntity) return; - if (this.sourceEntity.target) { - this.sourceEntity.target.style.filter = ''; - } - this.clearEffect(); - } - - handleDragOver(ev, lunaKey) { - ev.preventDefault(); - ev.stopPropagation(); - this.isDragging = true; - const schema = this.appHelper.schemaHelper.schemaMap[lunaKey]; - this.dragOverFunc( - { - clientX: ev.clientX, - clientY: ev.clientY, - currentTarget: ev.currentTarget, - }, - schema, - ); - } - - handleDragLeave(ev) { - //避免移动到treeEffectDom上的抖动 - ev.stopPropagation(); - if (!this.tempEntity) return; - const rect = ev.target.getBoundingClientRect(); - // 如果鼠标位置还在当前元素范围内则不认为是dragLeave - if (ev.x >= rect.left && ev.x <= rect.right && ev.y >= rect.top && ev.y <= rect.bottom) return; - debug('canvas drag leave', ev); - this.clearEffect(); - this.dragInfo = null; - this.isDragging = false; - } - - handleDrop(ev) { - ev.stopPropagation(); - debug('drop+++++'); - this.isDragging = false; - this.changeCanvas(); - this.clearEffect(); - } - - handleTreeDragStart(ev) { - const { event, node } = ev; - event.stopPropagation(); - const lunaKey = node.props.eventKey; - const schema = this.appHelper.schemaHelper.schemaMap[lunaKey]; - if (!schema) return; - - event.dataTransfer.setDragImage(this.getDragTagDom(schema.componentName), 0, 0); - this.sourceEntity = this.getTreeEntity(node, event); - if (this.sourceEntity.target) { - this.sourceEntity.target.style.filter = 'blur(2px)'; - } - this.isDragging = true; - } - - handleTreeDragEnd(ev) { - const { event } = ev; - event.stopPropagation(); - event.preventDefault(); - this.isDragging = false; - if (!this.sourceEntity) return; - if (this.sourceEntity.target) { - this.sourceEntity.target.style.filter = ''; - } - this.clearEffect(true); - } - - handleTreeDragOver(ev) { - const { event, node } = ev; - event.preventDefault(); - event.stopPropagation(); - this.isDragging = true; - this.dragOverFunc( - { - clientX: event.clientX, - clientY: event.clientY, - currentTarget: event.currentTarget.children[0], - }, - node, - true, - ); - } - - handleTreeDragLeave(ev) { - const { event } = ev; - event.stopPropagation(); - if (!this.tempEntity) return; - //避免移动到treeEffectDom上的抖动 - if (this.treeEffectDom && this.treeEffectDom.parentNode.parentNode === event.currentTarget) return; - debug('++++ drag leave tree', ev, this.isDragging); - this.clearEffect(true); - this.isDragging = false; - } - - handleTreeDrop(ev) { - const { event } = ev; - event.stopPropagation(); - this.isDragging = false; - this.changeCanvas(); - this.clearEffect(true); - } - - handleResourceDragStart(ev, title, schema) { - ev.stopPropagation(); - ev.dataTransfer.setDragImage(this.getDragTagDom(title), -2, -2); - this.sourceEntity = { - isAdd: true, - schema, - }; - this.isDragging = true; - } -} diff --git a/packages/react-renderer/src/utils/postMessager.js b/packages/react-renderer/src/utils/postMessager.js deleted file mode 100644 index 05cb33bab..000000000 --- a/packages/react-renderer/src/utils/postMessager.js +++ /dev/null @@ -1,59 +0,0 @@ -import EventEmitter from 'events'; -import Debug from 'debug'; -const debug = Debug('utils:postMessager'); -EventEmitter.defaultMaxListeners = 100; - -export class InnerMessager extends EventEmitter { - constructor() { - super(); - this.handleReceive = this.handleReceive.bind(this); - window.addEventListener('message', this.handleReceive, false); - } - - sendMsg(type, data, targetOrigin = '*') { - window.parent && - window.parent.postMessage( - { - type, - data, - }, - targetOrigin, - ); - } - - handleReceive(e) { - if (!e.data || !e.data.type) return; - this.emit(e.data.type, e.data.data); - } - - destroy() { - window.removeEventListener('message', this.handleReceive); - } -} - -export class OuterMessager extends EventEmitter { - constructor(innerWindow) { - super(); - this.innerWindow = innerWindow; - this.handleReceive = this.handleReceive.bind(this); - window.addEventListener('message', this.handleReceive, false); - } - sendMsg(type, data, targetOrigin = '*') { - this.innerWindow && - this.innerWindow.postMessage( - { - type, - data, - }, - targetOrigin, - ); - } - - handleReceive(e) { - if (!e.data || !e.data.type) return; - this.emit(e.data.type, e.data.data); - } - destroy() { - window.removeEventListener('message', this.handleReceive); - } -} diff --git a/packages/react-renderer/src/utils/schemaHelper.js b/packages/react-renderer/src/utils/schemaHelper.js deleted file mode 100644 index 37c247802..000000000 --- a/packages/react-renderer/src/utils/schemaHelper.js +++ /dev/null @@ -1,482 +0,0 @@ -import { forEach } from '@ali/b3-one/lib/obj'; -import { - clone, - fastClone, - jsonuri, - isSchema, - isFileSchema, - isJSFunction, - isJSExpression, - parseObj, - transformSchemaToPure, - transformSchemaToStandard, - isEmpty, - moveArrayItem, - serialize, - deepEqual, -} from './index'; -import Debug from 'debug'; -import compFactory from '../hoc/compFactory'; -const debug = Debug('utils:schemaHelper'); -let keyIndex = 0; -export default class SchemaHelper { - constructor(schema, appHelper) { - this.appHelper = appHelper; - this.reset(schema, true); - } - - reset(schema, isInit) { - debug('start reset'); - this.emit('schemaHelper.schema.beforeReset'); - this.schemaMap = {}; - this.blockSchemaMap = {}; - this.compThisMap = {}; - this.blockTree = {}; - this.compTreeMap = {}; - this.compCtxMap = {}; - this.rebuild(schema, isInit); - this.emit('schemaHelper.schema.afterReset'); - } - - add(schema, targetKey, direction) { - this.emit('schemaHelper.material.beforeAdd'); - const targetSchema = this.schemaMap[targetKey]; - if (isEmpty(schema) || !targetSchema) return; - let targetPath = targetSchema.__ctx.lunaPath; - if (targetPath === '' && direction !== 'in') { - console.warn('add error'); - return; - } - let newSchema = []; - if (Array.isArray(schema)) { - newSchema = schema.filter((item) => isSchema(item, true)); - } else if (isSchema(schema)) { - newSchema = [schema]; - } else { - console.error('模型结构异常'); - return; - } - if (direction === 'in') { - const targetNode = jsonuri.get(this.schema, targetPath); - targetNode.children = (targetNode.children || []).concat(newSchema); - //jsonuri.set(this.schema, targetPath, targetNode); - } else { - direction = ['left', 'top'].includes(direction) ? 'before' : 'after'; - newSchema.reverse().forEach((item) => { - jsonuri.insert(this.schema, targetPath, item, direction); - }); - } - const addKey = `luna_${keyIndex + 1}`; - this.rebuild(this.schema); - this.emit('schemaHelper.material.afterAdd', addKey); - return addKey; - } - - remove(lunaKey) { - this.emit('schemaHelper.material.beforeRemove'); - const schema = this.schemaMap[lunaKey]; - if (!schema) return; - const lunaPath = schema.__ctx.lunaPath; - if (lunaPath === '') { - console.warn('root node can not be removed'); - return; - } - - jsonuri.rm(this.schema, lunaPath); - delete this.schemaMap[lunaKey]; - delete this.blockSchemaMap[lunaKey]; - this.rebuild(this.schema); - this.emit('schemaHelper.material.afterRemove'); - } - - move(lunaKey, targetKey, direction) { - this.emit('schemaHelper.material.beforeMove'); - debug('start move'); - const schema = this.schemaMap[lunaKey]; - const targetSchema = this.schemaMap[targetKey]; - if (!schema || !targetSchema) return; - let lunaPath = schema.__ctx.lunaPath; - let targetPath = targetSchema.__ctx.lunaPath; - if (lunaPath === '' || (targetPath === '' && direction !== 'in')) { - console.warn('move error'); - return; - } - const res = /(.*)\/(\d+)$/.exec(lunaPath); - const prefix = res && res[1]; - const attr = res && res[2]; - if (!prefix || !attr) { - console.warn('异常结构'); - return; - } - const sourceIdx = parseInt(attr); - const reg = new RegExp(`^${prefix}/(\\d+)$`); - const regRes = reg.exec(targetPath); - const sourceParent = jsonuri.get(this.schema, prefix); - direction = direction === 'in' ? 'in' : ['left', 'top'].includes(direction) ? 'before' : 'after'; - if (regRes && regRes[1] && direction !== 'in') { - const distIdx = parseInt(regRes[1]); - moveArrayItem(sourceParent, sourceIdx, distIdx, direction); - } else { - if (direction === 'in') { - const targetNode = jsonuri.get(this.schema, targetPath); - targetNode.children = targetNode.children || []; - if (Array.isArray(targetNode.children)) { - targetNode.children.push(schema); - } - jsonuri.set(this.schema, targetPath, targetNode); - } else { - jsonuri.insert(this.schema, targetPath, schema, direction); - } - sourceParent.splice(sourceIdx, 1); - } - this.rebuild(this.schema); - this.emit('schemaHelper.material.afterMove'); - } - - //组件上移 下移 - // direction 取值 down/up - slide(lunaKey, direction) { - const schema = this.schemaMap[lunaKey]; - if (!schema || !direction) return; - const lunaPath = schema.__ctx && schema.__ctx.lunaPath; - if (!lunaPath) return; - if (direction === 'up' && lunaPath.endsWith('/0')) return; - const targetPath = lunaPath.replace(/\/(\d+)$/, (res, idx) => { - return `/${direction === 'down' ? parseInt(idx) + 1 : parseInt(idx) - 1}`; - }); - const targetSchema = this.getSchemaByPath(targetPath); - const targetKey = targetSchema && targetSchema.__ctx && targetSchema.__ctx.lunaKey; - if (!targetKey) return; - this.move(lunaKey, targetKey, direction === 'down' ? 'bottom' : 'top'); - } - - // 快速复制 - copy(lunaKey) { - this.emit('schemaHelper.material.beforeCopy'); - const schema = this.schemaMap[lunaKey]; - if (!schema) return; - const newSchema = transformSchemaToPure(fastClone(schema)); - delete newSchema.__ctx; - const addKey = this.add(newSchema, schema.__ctx.lunaKey, 'bottom'); - this.emit('schemaHelper.material.afterCopy', addKey); - return addKey; - } - - update(lunaKey, props) { - this.emit('schemaHelper.material.beforeUpdate'); - const schema = this.schemaMap[lunaKey]; - if (!schema) return; - const { - __state, - __defaultProps, - __fileName, - __scss, - __loop, - __loopArgs, - __condition, - __lifeCycles, - __methods, - __dataSource, - children, - ...otherProps - } = props; - debug('update props', props); - - //自定义组件才处理defaultProps - if (schema.componentName === 'Component' && '__defaultProps' in props) { - if (!__defaultProps || typeof __defaultProps !== 'object' || isEmpty(__defaultProps)) { - delete schema.defaultProps; - } else { - schema.defaultProps = __defaultProps; - } - this.appHelper.components[schema.fileName.replace(/^\w/, (a) => a.toUpperCase())] = compFactory(schema); - } - - // 如果loop值没有设置有效值,则删除schema中这个的字段 - if ('__loop' in props) { - if (!__loop || isEmpty(__loop)) { - delete schema.loop; - } else { - schema.loop = __loop; - } - } - - // 指定循环上下文变量名 - if ('__loopArgs' in props) { - if ( - __loopArgs === undefined || - (typeof __loopArgs === 'object' && isEmpty(__loopArgs)) || - !Array.isArray(__loopArgs) || - __loopArgs.every((item) => !item) - ) { - delete schema.loopArgs; - } else { - schema.loopArgs = __loopArgs; - } - } - - // 判断条件 - if ('__condition' in props) { - if (__condition === undefined) { - delete schema.condition; - } else { - schema.condition = __condition; - } - } - - // 处理容器类组件需要考虑的字段 - if (isFileSchema(schema)) { - // filename - if ('__fileName' in props) { - schema.fileName = __fileName; - } - // state - if ('__state' in props) { - // 重走生命周期 - schema.__ctx && ++schema.__ctx.idx; - if (!__state || typeof __state !== 'object' || isEmpty(__state)) { - delete schema.state; - } else { - schema.state = __state; - } - } - // 生命周期 - if ('__lifeCycles' in props) { - if (!__lifeCycles || typeof __lifeCycles !== 'object' || isEmpty(__lifeCycles)) { - delete schema.lifeCycles; - } else { - schema.lifeCycles = __lifeCycles; - } - } - // 自定义方法 - if ('__methods' in props) { - if (!__methods || typeof __methods !== 'object' || isEmpty(__methods)) { - delete schema.methods; - } else { - schema.methods = __methods; - } - } - - // 数据源设置 - if ('__dataSource' in props) { - if (this.needContainerReload(schema.dataSource, __dataSource)) { - schema.__ctx && ++schema.__ctx.idx; - } - if (__dataSource === undefined || (typeof __dataSource === 'object' && isEmpty(__dataSource))) { - delete schema.dataSource; - } else { - schema.dataSource = __dataSource; - } - } - - // 如果scss值没有设置有效值,则删除schema中这个的字段 - if ('__scss' in props) { - if (!__scss) { - delete schema.scss; - } else { - schema.scss = __scss; - } - } - } - - // 子组件 - if ('children' in props) { - if (children === undefined || (typeof children === 'object' && isEmpty(children))) { - delete schema.children; - } else { - schema.children = children; - } - } - - schema.props = { - ...schema.props, - ...otherProps, - }; - - //过滤undefined属性 - Object.keys(schema.props).map((key) => { - if (schema.props[key] === undefined) { - delete schema.props[key]; - } - }); - - this.rebuild(this.schema); - this.emit('schemaHelper.material.afterUpdate'); - } - - createSchema(componentName, props, isContainer) { - const schema = { - componentName, - props: props || {}, - __ctx: { - lunaKey: ++this.lunaKey, - }, - }; - if (isContainer) { - schema.children = []; - } - return schema; - } - - rebuild(schema, isInit) { - if (!isFileSchema(schema)) { - debug('top schema should be a file type'); - //对于null的schema特殊处理一下 - if (schema === null) { - this.schema = schema; - this.emit(`schemaHelper.schema.${isInit ? 'afterInit' : 'afterUpdate'}`); - } - return; - } - this.blockTree = null; - this.compTreeMap = {}; - this.compTree = null; - this.schemaMap = {}; - this.blockSchemaMap = {}; - this.compCtxMap = {}; - const buildSchema = (schema, parentBlockNode, parentCompNode, path = '') => { - if (Array.isArray(schema)) { - return schema.map((item, idx) => buildSchema(item, parentBlockNode, parentCompNode, `${path}/${idx}`)); - } else if (typeof schema === 'object') { - // 对于undefined及null直接返回 - if (!schema) return schema; - //JSFunction转函数 - if (isJSFunction(schema)) { - if (typeof schema.value === 'string') { - let tarFun = parseObj(schema.value); - if (typeof tarFun === 'function') { - return tarFun; - } - } else if (typeof schema.value === 'function') { - return schema.value; - } - return schema; - } - //如果是对象且是JSExpression - if (isJSExpression(schema)) { - return '{{' + schema.value + '}}'; - } - const res = {}; - if (isSchema(schema)) { - res.__ctx = schema.__ctx; - if (!res.__ctx) { - const lunaKey = `luna_${++keyIndex}`; - res.__ctx = { - idx: 0, - lunaKey, - lunaPath: path, - parentKey: parentCompNode && parentCompNode.lunaKey, - blockKey: parentBlockNode && parentBlockNode.lunaKey, - }; - } else { - res.__ctx.lunaPath = path; - } - const label = schema.componentName + (schema.fileName ? '-' + schema.fileName : ''); - const lunaKey = res.__ctx && res.__ctx.lunaKey; - this.schemaMap[lunaKey] = res; - if (isFileSchema(schema)) { - this.blockSchemaMap[lunaKey] = res; - - const blockNode = { - label, - lunaKey, - isFile: true, - children: [], - }; - this.compTreeMap[lunaKey] = blockNode; - const compNode = clone(blockNode); - if (parentBlockNode) { - parentBlockNode.children.push(blockNode); - } else { - this.blockTree = blockNode; - } - parentBlockNode = blockNode; - if (parentCompNode) { - parentCompNode.children.push(compNode); - } else { - this.compTree = compNode; - } - parentCompNode = compNode; - } else { - const compNode = { - label, - lunaKey, - children: [], - }; - parentCompNode.children.push(compNode); - parentCompNode = compNode; - } - } - forEach(schema, (val, key) => { - if (key.startsWith('__')) { - res[key] = val; - } else { - res[key] = buildSchema(val, parentBlockNode, parentCompNode, `${path}/${key}`); - } - }); - return res; - } - return schema; - }; - this.emit(`schemaHelper.schema.${isInit ? 'beforeInit' : 'beforeUpdate'}`); - this.schema = buildSchema(schema); - this.emit(`schemaHelper.schema.${isInit ? 'afterInit' : 'afterUpdate'}`); - } - - needContainerReload(preData = {}, nextData = {}) { - if ( - typeof preData.dataHandler === 'function' && - typeof nextData.dataHandler === 'function' && - preData.dataHandler.toString() !== nextData.dataHandler.toString() - ) { - return true; - } else if (preData.dataHandler !== nextData.dataHandler) { - return true; - } - return !deepEqual( - (preData.list || []).filter((item) => item.isInit), - (nextData.list || []).filter((item) => item.isInit), - (pre, next) => { - if (typeof pre === 'function' && next === 'function') { - return pre.toString() === next.toString(); - } - }, - ); - } - - emit(msg, ...args) { - this.appHelper && this.appHelper.emit(msg, ...args); - } - - get(key) { - return this[key]; - } - - getSchemaByPath(path) { - return jsonuri.get(this.schema, path); - } - - getSchema() { - return this.schema; - } - - getPureSchema() { - return transformSchemaToPure(this.schema); - } - - getPureSchemaStr() { - return serialize(this.getPureSchema(), { - unsafe: true, - }); - } - - getStandardSchema() { - return transformSchemaToStandard(this.schema); - } - - getStandardSchemaStr() { - return serialize(this.getStandardSchema(), { - unsafe: true, - }); - } -} diff --git a/packages/react-renderer/src/utils/storageHelper.js b/packages/react-renderer/src/utils/storageHelper.js deleted file mode 100644 index 7c815b0d6..000000000 --- a/packages/react-renderer/src/utils/storageHelper.js +++ /dev/null @@ -1,81 +0,0 @@ -import localforage from 'localforage'; -import Debug from 'debug'; -import { serialize } from './index'; - -const debug = Debug('utils:storageHelper'); -export default class StorageHelper { - constructor(name) { - this.store = localforage.createInstance(name); - } - - getItem(key) { - if (!this.store) { - throw new Error('store instance not exist'); - } - return this.store.getItem(key); - } - - setItem(key, value) { - if (!this.store) { - throw new Error('store instance not exist'); - } - return this.store.setItem(key, value); - } - - removeItem(key) { - if (!this.store) { - throw new Error('store instance not exist'); - } - return this.store.removeItem(key); - } - - clear() { - if (!this.store) { - throw new Error('store instance not exist'); - } - return this.store.clear(); - } - - addHistory(key, code, limit = 10) { - return new Promise((resolve, reject) => { - key = '__luna_history_' + key; - this.store - .getItem(key) - .then((res) => { - let codeStr = serialize(code, { - unsafe: true, - }); - if (res && res[0] && res[0].code) { - if (codeStr === res[0].code) return; - } - res = res || []; - let newId = 1; - if (res && res[0] && res[0].id) { - newId = res[0].id + 1; - } - res.unshift({ - id: newId, - time: +new Date(), - code: codeStr, - }); - this.store - .setItem(key, res.slice(0, limit)) - .then((res) => { - resolve(res); - }) - .catch(reject); - }) - .catch(reject); - }); - } - - getHistory(key) { - key = '__luna_history_' + key; - return this.store.getItem(key); - } - - clearHistory(key) { - key = '__luna_history_' + key; - this.store.removeItem(key); - } -} diff --git a/packages/react-renderer/src/utils/undoRedoHelper.js b/packages/react-renderer/src/utils/undoRedoHelper.js deleted file mode 100644 index 4cd352591..000000000 --- a/packages/react-renderer/src/utils/undoRedoHelper.js +++ /dev/null @@ -1,88 +0,0 @@ -import Debug from 'debug'; -import { fastClone } from './index'; -const DEFAULT_CONFIG = { - limit: 20, -}; -const debug = Debug('utils:undoRedoHelper'); -export default class UndoRedoHelper { - constructor(config) { - this.config = { ...DEFAULT_CONFIG, ...config }; - this.data = {}; - } - - create(key, value, forceCreate) { - if (!this.data[key] || forceCreate) { - this.data[key] = { - list: [fastClone(value)], - idx: 0, - }; - } - return this.data[key]; - } - - delete(key) { - delete this.data[key]; - } - - resetRecord(key, value) { - const data = this.data[key]; - if (!data || !data.list) return; - data.list = data.list.slice(0, data.idx + 1); - data.list[data.idx] = fastClone(value); - } - - record(key, value) { - const data = this.data[key]; - const limit = this.config.limit; - if (!data || !data.list) return; - data.list = data.list.slice(0, data.idx + 1); - if (data.list.length >= limit) { - data.list.shift(); - } - data.list.push(fastClone(value)); - ++data.idx; - } - - undo(key) { - const data = this.data[key]; - if (!data || !data.list) return null; - //若没有前置操作,返回当前数据 - if (data.idx <= 0) return data.list[data.idx]; - --data.idx; - return data.list[data.idx]; - } - redo(key) { - const data = this.data[key]; - if (!data || !data.list) return null; - //若没有后续操作,返回当前数据 - if (data.idx >= data.list.length - 1) return data.list[data.idx]; - ++data.idx; - return data.list[data.idx]; - } - - past(key) { - const data = this.data[key]; - if (!data || !data.list || data.idx <= 0) return null; - return data.list[data.idx - 1]; - } - - present(key) { - const data = this.data[key]; - if (!data || !data.list) return null; - return data.list[data.idx]; - } - - future(key) { - const data = this.data[key]; - if (!data || !data.list || data.idx >= data.list.length - 1) return null; - return data.list[data.idx + 1]; - } - - get(key) { - return { - past: this.past(key), - present: this.present(key), - future: this.future(key), - }; - } -} diff --git a/packages/react-renderer/src/utils/wsHelper.js b/packages/react-renderer/src/utils/wsHelper.js deleted file mode 100644 index 436080a4d..000000000 --- a/packages/react-renderer/src/utils/wsHelper.js +++ /dev/null @@ -1,87 +0,0 @@ -import Debug from 'debug'; -import client from 'socket.io-client'; -import { parseUrl } from '@ali/b3-one/lib/url'; -const debug = Debug('utils:wsHelper'); - -export default class WSHelper { - constructor(appHelper, namespace, options) { - this.appHelper = appHelper; - this.ws = null; - this.init(namespace, options); - } - - init(namespace = '/', options = {}) { - if (this.ws) { - this.close(); - } - const urlInfo = parseUrl(); - const ws = (this.ws = client(namespace, { - reconnectionDelay: 3000, - transports: ['websocket'], - query: urlInfo.params, - ...options, - })); - const appHelper = this.appHelper; - debug('ws.init'); - - ws.on('connect', (msg) => { - appHelper.emit('wsHelper.connect.success', msg); - debug('ws.connect'); - }); - - ws.on('error', (msg) => { - appHelper.emit('wsHelper.connect.error', msg); - debug('ws.error', msg); - }); - - ws.on('disconnect', (msg) => { - appHelper.emit('wsHelper.connect.break', msg); - debug('ws.disconnect', msg); - }); - - ws.on('reconnecting', (msg) => { - appHelper.emit('wsHelper.connect.retry', msg); - debug('ws.reconnecting', msg); - }); - - ws.on('ping', (msg) => { - debug('ws.ping', msg); - }); - - ws.on('pong', (msg) => { - debug('ws.pong', msg); - }); - - ws.on('data', (msg) => { - appHelper.emit('wsHelper.data.receive', msg); - if (msg.eventName) { - appHelper.emit(`wsHelper.result.${msg.eventName}`, msg); - } - debug('ws.data', msg); - }); - } - - close() { - if (!this.ws) return; - this.ws.close(); - this.ws = null; - this.appHelper.emit('wsHelper.connect.close'); - } - - send(eventName, ...args) { - return new Promise((resolve, reject) => { - try { - this.appHelper.emit('wsHelper.data.request', { - eventName, - params: args, - }); - this.appHelper.once(`wsHelper.result.${eventName}`, resolve); - this.ws && this.ws.emit(eventName, ...args); - debug('ws.send', eventName); - } catch (err) { - console.error('websocket error:', err); - reject(err); - } - }); - } -} From d03844c706544d8199d3197c078ca89b7e83dae7 Mon Sep 17 00:00:00 2001 From: "zude.hzd" Date: Sun, 19 Apr 2020 22:13:58 +0800 Subject: [PATCH 10/21] add source-editor pannel --- packages/demo/build.plugin.js | 12 + packages/demo/package.json | 2 + packages/demo/skeleton.config.js | 10 +- packages/demo/src/editor/config/components.js | 6 +- packages/demo/src/editor/config/skeleton.js | 28 +- packages/plugin-source-editor/CHANGELOG.md | 20 ++ packages/plugin-source-editor/README.md | 1 + packages/plugin-source-editor/build.json | 9 + packages/plugin-source-editor/package.json | 41 +++ packages/plugin-source-editor/src/index.scss | 23 ++ packages/plugin-source-editor/src/index.tsx | 246 ++++++++++++++++++ .../plugin-source-editor/src/transform.ts | 98 +++++++ packages/plugin-source-editor/tsconfig.json | 9 + 13 files changed, 497 insertions(+), 8 deletions(-) create mode 100644 packages/plugin-source-editor/CHANGELOG.md create mode 100644 packages/plugin-source-editor/README.md create mode 100644 packages/plugin-source-editor/build.json create mode 100644 packages/plugin-source-editor/package.json create mode 100644 packages/plugin-source-editor/src/index.scss create mode 100644 packages/plugin-source-editor/src/index.tsx create mode 100644 packages/plugin-source-editor/src/transform.ts create mode 100644 packages/plugin-source-editor/tsconfig.json diff --git a/packages/demo/build.plugin.js b/packages/demo/build.plugin.js index 0fbf67f53..50ac34ddd 100644 --- a/packages/demo/build.plugin.js +++ b/packages/demo/build.plugin.js @@ -1,4 +1,6 @@ const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); +const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); + module.exports = ({ onGetWebpackConfig }) => { onGetWebpackConfig((config) => { @@ -7,6 +9,16 @@ module.exports = ({ onGetWebpackConfig }) => { .use(TsconfigPathsPlugin, [{ configFile: "./tsconfig.json" }]); + + + config + // 定义插件名称 + .plugin('MonacoWebpackPlugin') + // 第一项为具体插件,第二项为插件参数 + .use(new MonacoWebpackPlugin({ + languages:["javascript","css","json"] + }), []); + config.plugins.delete('hot'); config.devServer.hot(false); }); diff --git a/packages/demo/package.json b/packages/demo/package.json index bd8af2d92..bdd8a4759 100644 --- a/packages/demo/package.json +++ b/packages/demo/package.json @@ -18,6 +18,7 @@ "@ali/lowcode-plugin-event-bind-dialog": "^0.8.0", "@ali/lowcode-plugin-outline-pane": "^0.8.7", "@ali/lowcode-plugin-sample-logo": "^0.8.0", + "@ali/lowcode-plugin-source-editor":"^0.8.2", "@ali/lowcode-plugin-sample-preview": "^0.8.6", "@ali/lowcode-plugin-settings-pane": "^0.8.8", "@ali/lowcode-plugin-undo-redo": "^0.8.0", @@ -41,6 +42,7 @@ "build-plugin-fusion": "^0.1.0", "build-plugin-moment-locales": "^0.1.0", "build-plugin-react-app": "^1.1.2", + "monaco-editor-webpack-plugin":"^1.9.0", "tsconfig-paths-webpack-plugin": "^3.2.0" } } diff --git a/packages/demo/skeleton.config.js b/packages/demo/skeleton.config.js index 4dd4cc1c0..b649fd023 100644 --- a/packages/demo/skeleton.config.js +++ b/packages/demo/skeleton.config.js @@ -83,17 +83,18 @@ module.exports = { pluginProps: { } }, + { - pluginKey: 'outlinePane', + pluginKey: 'soueceEditor', type: 'PanelIcon', props: { align: 'top', icon: 'shuxingkongjian', - title: '大纲树' + title: '源码面板' }, config: { - package: '@ali/lowcode-plugin-outline-pane', - version: '^0.8.0' + package: '@ali/lowcode-plugin-source-editor', + version: '^0.8.2' }, pluginProps: {} }, @@ -137,6 +138,7 @@ module.exports = { version: '^0.8.0' } } + ] }, hooks: [], diff --git a/packages/demo/src/editor/config/components.js b/packages/demo/src/editor/config/components.js index 9648a7faf..348e048b7 100644 --- a/packages/demo/src/editor/config/components.js +++ b/packages/demo/src/editor/config/components.js @@ -8,6 +8,7 @@ import zhEn from '@ali/lowcode-plugin-zh-en'; import settingsPane from '@ali/lowcode-plugin-settings-pane'; import designer from '@ali/lowcode-plugin-designer'; import eventBindDialog from '@ali/lowcode-plugin-event-bind-dialog'; +import sourceEditor from '@ali/lowcode-plugin-source-editor' export default { LowcodeSkeleton, logo, @@ -18,5 +19,6 @@ export default { zhEn, settingsPane, designer, - eventBindDialog -}; \ No newline at end of file + eventBindDialog, + sourceEditor +}; diff --git a/packages/demo/src/editor/config/skeleton.js b/packages/demo/src/editor/config/skeleton.js index 4a8e417cc..65d182436 100644 --- a/packages/demo/src/editor/config/skeleton.js +++ b/packages/demo/src/editor/config/skeleton.js @@ -90,7 +90,30 @@ export default { "version": "^0.8.0" }, "pluginProps": {} - }, { + }, + + { + "pluginKey": "sourceEditor", + "type": "PanelIcon", + "props": { + "align": "top", + "icon": "zujianku", + "title": "组件库", + "panelProps":{ + "floatable": true, + "defaultWidth":500 + + }, + + }, + "config": { + "package": "@ali/lowcode-plugin-source-editor", + "version": "^0.8.0" + }, + "pluginProps": {} + }, + + { "pluginKey": "zhEn", "type": "Custom", "props": { @@ -124,7 +147,8 @@ export default { "package": "@ali/lowcode-plugin-event-bind-dialog", "version": "^0.8.0" } - }] + }, + ] }, "hooks": [], "shortCuts": [], diff --git a/packages/plugin-source-editor/CHANGELOG.md b/packages/plugin-source-editor/CHANGELOG.md new file mode 100644 index 000000000..7c5e8d83c --- /dev/null +++ b/packages/plugin-source-editor/CHANGELOG.md @@ -0,0 +1,20 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + + +## [0.8.2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-variable-bind-dialog@0.8.1...@ali/lowcode-plugin-variable-bind-dialog@0.8.2) (2020-03-30) + + + + +**Note:** Version bump only for package @ali/lowcode-plugin-source-editor + + +## 0.8.1 (2020-03-30) + + + + +**Note:** Version bump only for package @ali/lowcode-plugin-source-editor diff --git a/packages/plugin-source-editor/README.md b/packages/plugin-source-editor/README.md new file mode 100644 index 000000000..8a6fb13f0 --- /dev/null +++ b/packages/plugin-source-editor/README.md @@ -0,0 +1 @@ +## todo diff --git a/packages/plugin-source-editor/build.json b/packages/plugin-source-editor/build.json new file mode 100644 index 000000000..e791d5b6b --- /dev/null +++ b/packages/plugin-source-editor/build.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + "build-plugin-component", + "build-plugin-fusion", + ["build-plugin-moment-locales", { + "locales": ["zh-cn"] + }] + ] +} diff --git a/packages/plugin-source-editor/package.json b/packages/plugin-source-editor/package.json new file mode 100644 index 000000000..19c1c9178 --- /dev/null +++ b/packages/plugin-source-editor/package.json @@ -0,0 +1,41 @@ +{ + "name": "@ali/lowcode-plugin-source-editor", + "version": "0.8.2", + "description": "alibaba lowcode editor source-editor plugin", + "files": [ + "es", + "lib" + ], + "main": "lib/index.js", + "module": "es/index.js", + "scripts": { + "build": "build-scripts build --skip-demo", + "test": "ava", + "test:snapshot": "ava --update-snapshots" + }, + "keywords": [ + "lowcode", + "editor" + ], + "author": "zude.hzd", + "dependencies": { + "@ali/lowcode-editor-core": "^0.8.0", + "@alifd/next": "^1.19.16", + "react": "^16.8.1", + "react-dom": "^16.8.1", + "prettier":"^1.18.2", + "js-beautify": "^1.10.1", + "react-monaco-editor": "^0.36.0" + }, + "devDependencies": { + "@alib/build-scripts": "^0.1.3", + "@types/react": "^16.9.13", + "@types/react-dom": "^16.9.4", + "build-plugin-component": "^0.2.7-1", + "build-plugin-fusion": "^0.1.0", + "build-plugin-moment-locales": "^0.1.0" + }, + "publishConfig": { + "registry": "https://registry.npm.alibaba-inc.com" + } +} diff --git a/packages/plugin-source-editor/src/index.scss b/packages/plugin-source-editor/src/index.scss new file mode 100644 index 000000000..02b902227 --- /dev/null +++ b/packages/plugin-source-editor/src/index.scss @@ -0,0 +1,23 @@ +.source-editor-container{ + height: 100%; + + + .next-tabs { + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 100%; + } + + .next-tabs-content{ + height: 100%; + } + + .next-tabs-tabpane.active { + visibility: visible; + opacity: 1; + height: 100%; + } + +} + diff --git a/packages/plugin-source-editor/src/index.tsx b/packages/plugin-source-editor/src/index.tsx new file mode 100644 index 000000000..f1dba0d4e --- /dev/null +++ b/packages/plugin-source-editor/src/index.tsx @@ -0,0 +1,246 @@ +import { Component, isValidElement, ReactElement, ReactNode } from 'react'; +import { Tab, Search, Input, Button } from '@alifd/next'; +import Editor from '@ali/lowcode-editor-core'; +import { js_beautify, css_beautify } from 'js-beautify'; +import MonacoEditor from 'react-monaco-editor'; + +// import lolizer from './sorceEditorPlugin', + +import { Designer } from '@ali/lowcode-designer'; +const TAB_KEY = { + JS_TAB: 'js_tab', + CSS_TAB: 'css_tab', +}; + +import './index.scss'; +import transfrom from './transform'; + +const defaultEditorOption = { + width: '100%', + height: '96%', + options: { + readOnly: false, + automaticLayout: true, + folding: true, //默认开启折叠代码功能 + lineNumbers: 'on', + wordWrap: 'off', + formatOnPaste: true, + fontSize: 12, + tabSize: 2, + scrollBeyondLastLine: false, + fixedOverflowWidgets: false, + snippetSuggestions: 'top', + minimap: { + enabled: false, + }, + scrollbar: { + vertical: 'auto', + horizontal: 'auto', + }, + } +}; + +export default class SourceEditor extends Component<{ + editor: Editor; +}> { + private monocoEditer:Object; + private editorCmd:Object; + + state = { + isShow: false, + tabKey: TAB_KEY.JS_TAB + } + + componentWillMount() { + const { editor } = this.props; + editor.on('leftPanel.show', (key: String) => { + if (key === 'sourceEditor' && !this.monocoEditer) { + this.setState({ + isShow: true, + }); + } + }); + + // 添加函数 + editor.on('sourceEditor.addFunction',(params:Object)=>{ + this.callEditorEvent('sourceEditor.addFunction',params); + }) + + editor.once('designer.mount', (designer: Designer) => { + // let schema = designer.project.getSchema(); + // mock data + let schema = { + componentTree: [ + { + state: { + // 初始state: 选填 对象类型/变量表达式 + btnText: 'submit', // 默认数据值: 选填 变量表达式 + }, + css: 'body {font-size: 12px;} .botton{widht:100px;color:#ff00ff}', //css样式描述: 选填 + lifeCycles: { + //生命周期: 选填 对象类型 + didMount: { + type: 'JSExpression', + value: "function() {\n \t\tconsole.log('did mount');\n\t}", + }, + willUnmount: { + type: 'JSExpression', + value: "function() {\n \t\tconsole.log('will umount');\n\t}", + }, + }, + methods: { + //自定义方法对象: 选填 对象类型 + testFunc: { + //自定义方法: 选填 函数类型 + type: 'JSExpression', + value: "function() {\n \t\tconsole.log('testFunc');\n \t}", + }, + }, + }, + ], + }; + + this.initCode(schema); + }); + + + setTimeout (()=>{ + editor.emit('sourceEditor.addFunction',{ + functionName:'testgaga' + }) + },3000) + + } + + callEditorEvent = (eventName,params) => { + if (!this.monocoEditer){ + this.editorCmd = { + eventName, + params + }; + return; + } + + if (eventName === 'sourceEditor.addFunction'){ + this.addFunction(params); + } + + } + + initCode = (schema) => { + let jsCode = js_beautify(transfrom.schema2Code(schema),{ indent_size: 2, indent_empty_lines: true }); + let css; + + if (schema.componentTree[0].css) { + css = css_beautify(schema.componentTree[0].css,{ indent_size: 2 }); + } + + this.setState({ + jsCode, + css, + selectTab: TAB_KEY.JS_TAB, + }); + + }; + + addFunction (params){ + const count = this.monocoEditer.getModel().getLineCount() || 0; + const range = new monaco.Range(count, 1, count, 1); + const functionCode = transfrom.getNewFunctionCode(params.functionName); + this.monocoEditer.executeEdits('log-source', [{ identifier: 'event_id', range:range , text: functionCode, forceMoveMarkers:true }]); + + this.updateCode(this.monocoEditer.getModel().getValue()) + } + + editorDidMount = (editor, monaco) => { + console.log('editorDidMount', editor); + this.monocoEditer = editor; + + if (this.editorCmd){ + this.callEditorEvent(this.editorCmd.eventName,this.editorCmd.params); + } + + // var commandId = editor.addCommand( + // 0, + // function() { + // // services available in `ctx` + // alert('my command is executing!'); + // }, + // '', + // ); + + // monaco.languages.registerCodeLensProvider('javascript', { + // provideCodeLenses: function(model, token) { + // return { + // lenses: [ + // { + // range: { + // startLineNumber: 1, + // startColumn: 1, + // endLineNumber: 1, + // endColumn: 1, + // }, + // id: 'First Line', + // command: { + // id: commandId, + // title: 'First Line', + // }, + // }, + // ], + // }; + // }, + // resolveCodeLens: function(model, codeLens, token) { + // return codeLens; + // }, + // }); + }; + + onTabChange = (key) => { + this.setState({ + selectTab: key, + }); + }; + + updateCode = (newCode) => { + const { selectTab } = this.state; + if (selectTab === TAB_KEY.JS_TAB) { + this.setState({ + jsCode: newCode, + }); + } else { + this.setState({ + css: newCode, + }); + } + + transfrom.code2Schema(newCode); + } + + render() { + const { isShow, selectTab, jsCode, css } = this.state; + const tabs = [ + { tab: 'index.js', key: TAB_KEY.JS_TAB }, + { tab: 'style.css', key: TAB_KEY.CSS_TAB }, + ]; + + return ( +
+ + {tabs.map((item) => ( + + {isShow && ( + this.updateCode(newCode)} + editorDidMount={this.editorDidMount} + /> + )} + + ))} + +
+ ); + } +} diff --git a/packages/plugin-source-editor/src/transform.ts b/packages/plugin-source-editor/src/transform.ts new file mode 100644 index 000000000..35a87934a --- /dev/null +++ b/packages/plugin-source-editor/src/transform.ts @@ -0,0 +1,98 @@ +import walkSourcePlugin from './sorceEditorPlugin'; + +const transfrom = { + schema2Code(schema: Object) { + let componentSchema = schema.componentTree[0]; + let code = +`export default class { + ${initStateCode(componentSchema)} + ${initLifeCycleCode(componentSchema)} + ${initMethodsCode(componentSchema)} +}`; + console.log(code); + return code; + }, + + code2Schema(code: String) { + + let newCode = code.replace(/export default class/,'class A'); + + let A,a; + try { + A = eval('('+newCode + ')'); + a = new A(); + }catch(e){ + return '' + } + + + let functionNameList = Object.getOwnPropertyNames(a.__proto__); + + let functionMap = {}; + + functionNameList.map((functionName)=>{ + if (functionName != 'constructor'){ + let functionCode = a[functionName].toString().replace(new RegExp(functionName),'function'); + functionMap[functionName] = functionCode; + } + }) + + console.log(JSON.stringify(a.state)); + + console.log(functionMap); + + }, + + getNewFunctionCode(functionName:String){ + return `\n\t${functionName}(){\n\t}\n` + } +}; + + +function initStateCode(componentSchema:Object) { + if (componentSchema.state){ + return `state = ${JSON.stringify(componentSchema.state)}` + } + + return ''; +} + +function initLifeCycleCode(componentSchema: Object) { + if (componentSchema.lifeCycles) { + let lifeCycles = componentSchema.lifeCycles; + let codeList = []; + + for (let key in lifeCycles) { + codeList.push(createFunctionCode(key, lifeCycles[key])); + } + + return codeList.join(''); + } else { + return ''; + } +} + +function initMethodsCode(componentSchema: Object) { + if (componentSchema.methods) { + let methods = componentSchema.methods; + let codeList = []; + + for (let key in methods) { + codeList.push(createFunctionCode(key, methods[key])); + } + + return codeList.join(''); + } else { + return ''; + } +} + +function createFunctionCode(functionName: String, functionNode: Object) { + if (functionNode.type === 'JSExpression') { + let functionCode = functionNode.value; + functionCode = functionCode.replace(/function/, functionName); + return functionCode; + } +} + +export default transfrom; diff --git a/packages/plugin-source-editor/tsconfig.json b/packages/plugin-source-editor/tsconfig.json new file mode 100644 index 000000000..c37b76ecc --- /dev/null +++ b/packages/plugin-source-editor/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": [ + "./src/" + ] +} From fd100c9c3e295b4daa263aabe077fb5229bb0328 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Sun, 19 Apr 2020 22:36:58 +0800 Subject: [PATCH 11/21] feat: add init and ready lifecycles --- packages/runtime/src/core/provider/index.ts | 61 +++++++++++++++++---- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/packages/runtime/src/core/provider/index.ts b/packages/runtime/src/core/provider/index.ts index fb3512c68..79016f2ab 100644 --- a/packages/runtime/src/core/provider/index.ts +++ b/packages/runtime/src/core/provider/index.ts @@ -1,4 +1,5 @@ import { IAppConfig, IUtils, IComponents, HistoryMode } from '../run'; +import EventEmitter from '@ali/offline-events'; interface IConstants { [key: string]: any; @@ -100,15 +101,18 @@ export interface I18n { type Locale = 'zh-CN' | 'en-US'; -// export interface IProvider { -// init?(): void; -// getAppData?(appkey: string): Promise; -// getPageData?(pageId: string): Promise; -// getLazyComponent?(pageId: string, props: any): any; -// createApp?(): void; -// } +export interface IProvider { + init(): void; + ready(): void; + onReady(cb: any): void; + async(): Promise; + getAppData(): Promise; + getPageData(pageId: string): Promise; + getLazyComponent(pageId: string, props: any): any; + createApp(): void; +} -export default class Provider { +export default class Provider implements IProvider { private components: IComponents = {}; private utils: IUtils = {}; private constants: IConstants = {}; @@ -118,7 +122,10 @@ export default class Provider { private history: HistoryMode = 'hash'; private containerId = ''; private i18n: I18n | null = null; + private homePage = ''; private lazyElementsMap: { [key: string]: any } = {}; + private sectionalRender = false; + private emitter: EventEmitter = new EventEmitter(); constructor() { this.init(); @@ -153,8 +160,24 @@ export default class Provider { }); } - async init() { + init() { console.log('init'); + // 默认 ready,当重载了init时需手动触发 this.ready() + this.ready(); + } + + ready(params?: any) { + if (params && typeof params === 'function') { + params = params(); + } + this.emitter.emit('ready', params || ''); + } + + onReady(cb: (params?: any) => void) { + if (!cb || typeof cb !== 'function') { + return; + } + this.emitter.on('ready', cb); } getAppData(): any { @@ -230,7 +253,7 @@ export default class Provider { this.containerId = id; } - setI18n(i18n: I18n) { + setI18n(i18n: I18n | undefined) { if (!i18n) { return; } @@ -244,6 +267,16 @@ export default class Provider { this.lazyElementsMap[pageId] = cache; } + setHomePage(pageId: string) { + if (pageId) { + this.homePage = pageId; + } + } + + setSectionalRender() { + this.sectionalRender = true; + } + getComponents() { return this.components; } @@ -305,10 +338,18 @@ export default class Provider { return locale ? this.i18n[locale] : this.i18n; } + getHomePage() { + return this.homePage; + } + getlazyElement(pageId: string) { if (!pageId) { return; } return this.lazyElementsMap[pageId]; } + + isSectionalRender() { + return this.sectionalRender; + } } From 84642355d44ddf2902b4e178442b9baf605b872a Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Sun, 19 Apr 2020 22:37:57 +0800 Subject: [PATCH 12/21] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E9=85=8D?= =?UTF-8?q?=E7=BD=AElayouts=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/runtime/src/core/container.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/runtime/src/core/container.ts b/packages/runtime/src/core/container.ts index 677fd32ad..e8deee816 100644 --- a/packages/runtime/src/core/container.ts +++ b/packages/runtime/src/core/container.ts @@ -8,7 +8,7 @@ export interface ILayoutOptions { export default class Container { private renderer: ReactType | null = null; - private layouts: { [key: string]: ReactType } = {}; + private layouts: { [key: string]: { content: ReactType; props: any } } = {}; private loading: ReactType | null = null; private provider: any; @@ -20,11 +20,11 @@ export default class Container { if (!options) { return; } - const { componentName } = options; + const { componentName, props = {} } = options; if (!componentName || !Layout) { return; } - this.layouts[componentName] = Layout; + this.layouts[componentName] = { content: Layout, props }; } registerLoading(component: ReactType) { From e96934ae4c91d419c1f35f3628cd02c258e1518e Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Sun, 19 Apr 2020 22:38:26 +0800 Subject: [PATCH 13/21] =?UTF-8?q?feat:=20=E9=80=8F=E5=87=BAloading?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/runtime/src/core/provider/react/lazy-component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime/src/core/provider/react/lazy-component.tsx b/packages/runtime/src/core/provider/react/lazy-component.tsx index 72119ccb8..37c111097 100644 --- a/packages/runtime/src/core/provider/react/lazy-component.tsx +++ b/packages/runtime/src/core/provider/react/lazy-component.tsx @@ -38,6 +38,6 @@ export default class LazyComponent extends Component { // loading扩展点 return createElement(Loading); } - return createElement(Renderer as any, { schema, ...restProps }); + return createElement(Renderer as any, { schema, loading: Loading ? createElement(Loading) : null, ...restProps }); } } From 94690c389b3f63d6968e80d8fca26419c5b89f26 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Sun, 19 Apr 2020 22:39:42 +0800 Subject: [PATCH 14/21] =?UTF-8?q?chore:=20=E5=A3=B0=E6=98=8EgetProvider?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BF=94=E5=9B=9E=E5=80=BC=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/runtime/src/core/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/runtime/src/core/index.ts b/packages/runtime/src/core/index.ts index 076fbc2ce..6160a6a20 100644 --- a/packages/runtime/src/core/index.ts +++ b/packages/runtime/src/core/index.ts @@ -1,5 +1,6 @@ import { ReactType } from 'react'; import Container, { ILayoutOptions } from './container'; +import { IProvider } from './provider'; import run from './run'; class App { @@ -41,7 +42,7 @@ class App { return this.container.getLoading(); } - getProvider() { + getProvider(): IProvider { return this.container.getProvider(); } } From 0a421518cf7d5eae2aab820a5c08c668cff8a059 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Sun, 19 Apr 2020 22:39:56 +0800 Subject: [PATCH 15/21] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/runtime/package.json | 5 +- .../runtime/src/core/provider/react/index.ts | 66 ++++++++++++------- packages/runtime/src/core/run.ts | 27 ++++---- 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 191b3e633..2c667549f 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@ali/lowcode-runtime", - "version": "0.8.9", + "version": "0.8.12", "description": "Runtime for Ali lowCode engine", "files": [ "es", @@ -25,7 +25,8 @@ }, "license": "MIT", "dependencies": { - "@ali/recore": "^1.6.9" + "@ali/recore": "^1.6.9", + "@ali/offline-events": "^1.0.0" }, "devDependencies": { "@alib/build-scripts": "^0.1.18", diff --git a/packages/runtime/src/core/provider/react/index.ts b/packages/runtime/src/core/provider/react/index.ts index 3bff84f94..1c0a3fb07 100644 --- a/packages/runtime/src/core/provider/react/index.ts +++ b/packages/runtime/src/core/provider/react/index.ts @@ -1,4 +1,4 @@ -import { createElement, ReactElement } from 'react'; +import { createElement, ReactType, ReactElement } from 'react'; import { Router } from '@ali/recore'; import app from '../../index'; import Provider from '..'; @@ -7,33 +7,66 @@ import LazyComponent from './lazy-component'; export default class ReactProvider extends Provider { // 定制构造根组件的逻辑,如切换路由机制 createApp() { + const RouterView = this.getRouterView(); + let App; + const layoutConfig = this.getLayoutConfig(); + if (!layoutConfig || !layoutConfig.componentName) { + App = (props: any) => (RouterView ? createElement(RouterView, { ...props }) : null); + return App; + } + const { componentName: layoutName, props: layoutProps } = layoutConfig; + const { content: Layout, props: extraLayoutProps } = app.getLayout(layoutName) || {}; + const sectionalRender = this.isSectionalRender(); + if (!sectionalRender && Layout) { + App = (props: any) => + createElement( + Layout, + { ...layoutProps, ...extraLayoutProps }, + RouterView ? createElement(RouterView, props) : null, + ); + } else { + App = (props: any) => (RouterView ? createElement(RouterView, props) : null); + } + return App; + } + + // 内置实现 for 动态化渲染 + getRouterView(): ReactType | null { const routerConfig = this.getRouterConfig(); if (!routerConfig) { - return; + return null; } - const routes: Array<{ path: string; children: any; exact: boolean; keepAlive: boolean }> = []; - let homePageId = ''; + const routes: Array<{ + path: string; + children: any; + exact: boolean; + defined: { keepAlive: boolean; [key: string]: any }; + }> = []; + let homePageId = this.getHomePage(); Object.keys(routerConfig).forEach((pageId: string, idx: number) => { if (!pageId) { return; } const path = routerConfig[pageId]; - if (idx === 0 || path === '/') { - homePageId = pageId; - } routes.push({ path, children: (props: any) => this.getLazyComponent(pageId, props), exact: true, - keepAlive: true, + defined: { keepAlive: true }, }); + if (homePageId) { + return; + } + if (idx === 0 || path === '/') { + homePageId = pageId; + } }); if (homePageId) { routes.push({ path: '**', children: (props: any) => this.getLazyComponent(homePageId, { ...props }), exact: true, - keepAlive: true, + defined: { keepAlive: true }, }); } const RouterView = (props: any) => { @@ -45,20 +78,7 @@ export default class ReactProvider extends Provider { ...props, }); }; - let App; - const layoutConfig = this.getLayoutConfig(); - if (!layoutConfig || !layoutConfig.componentName) { - App = (props: any) => createElement(RouterView, { ...props }); - return App; - } - const { componentName: layoutName, props: layoutProps } = layoutConfig; - const Layout = app.getLayout(layoutName); - if (Layout) { - App = (props: any) => createElement(Layout, layoutProps, RouterView({ props })); - } else { - App = (props: any) => createElement(RouterView, props); - } - return App; + return RouterView; } getLazyComponent(pageId: string, props: any): ReactElement | null { diff --git a/packages/runtime/src/core/run.ts b/packages/runtime/src/core/run.ts index 3fd4a364e..7cc7ab98f 100644 --- a/packages/runtime/src/core/run.ts +++ b/packages/runtime/src/core/run.ts @@ -46,21 +46,20 @@ function transformConfig(config: IAppConfig | (() => IAppConfig)): IRecoreAppCon }; } -export default function run(config?: IAppConfig | (() => IAppConfig)) { +export default function run() { const provider = app.getProvider(); - if (config) { - config = transformConfig(config); - const App = provider.createApp(); - runApp(App, config); - return; + if (!provider) { + throw new Error(''); } - const promise = provider.async(); - promise.then((config: IAppConfig) => { - if (!config) { - return; - } - const App = provider.createApp(); - config = transformConfig(config); - runApp(App, config); + provider.onReady(() => { + const promise = provider.async(); + promise.then((config: IAppConfig) => { + if (!config) { + return; + } + const App = provider.createApp(); + config = transformConfig(config); + runApp(App, config); + }); }); } From 38ca41a2523340064990d4577a843bb5616715eb Mon Sep 17 00:00:00 2001 From: "zude.hzd" Date: Wed, 22 Apr 2020 15:26:02 +0800 Subject: [PATCH 16/21] =?UTF-8?q?=E8=B5=84=E6=BA=90=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E5=BC=B9=E7=AA=97=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/demo/src/editor/config/components.js | 4 +- packages/demo/src/editor/config/skeleton.js | 7 ++ .../plugin-event-bind-dialog/src/index.tsx | 7 ++ packages/plugin-source-editor/src/index.tsx | 114 +++++++++++++----- packages/setters/src/events-setter/index.tsx | 11 +- 5 files changed, 109 insertions(+), 34 deletions(-) diff --git a/packages/demo/src/editor/config/components.js b/packages/demo/src/editor/config/components.js index 348e048b7..e844c44ed 100644 --- a/packages/demo/src/editor/config/components.js +++ b/packages/demo/src/editor/config/components.js @@ -8,7 +8,8 @@ import zhEn from '@ali/lowcode-plugin-zh-en'; import settingsPane from '@ali/lowcode-plugin-settings-pane'; import designer from '@ali/lowcode-plugin-designer'; import eventBindDialog from '@ali/lowcode-plugin-event-bind-dialog'; -import sourceEditor from '@ali/lowcode-plugin-source-editor' +import variableBindDialog from '@ali/lowcode-plugin-variable-bind-dialog'; +import sourceEditor from '@ali/lowcode-plugin-source-editor'; export default { LowcodeSkeleton, logo, @@ -20,5 +21,6 @@ export default { settingsPane, designer, eventBindDialog, + variableBindDialog, sourceEditor }; diff --git a/packages/demo/src/editor/config/skeleton.js b/packages/demo/src/editor/config/skeleton.js index 65d182436..c9565d572 100644 --- a/packages/demo/src/editor/config/skeleton.js +++ b/packages/demo/src/editor/config/skeleton.js @@ -148,6 +148,13 @@ export default { "version": "^0.8.0" } }, + { + "pluginKey": "variableBindDialog", + "config": { + "package": "@ali/lowcode-plugin-variable-bind-dialog", + "version": "^0.8.0" + } + } ] }, "hooks": [], diff --git a/packages/plugin-event-bind-dialog/src/index.tsx b/packages/plugin-event-bind-dialog/src/index.tsx index 28ffea012..32cf6e474 100644 --- a/packages/plugin-event-bind-dialog/src/index.tsx +++ b/packages/plugin-event-bind-dialog/src/index.tsx @@ -91,6 +91,13 @@ export default class EventBindDialog extends Component<{ onOk = () => { const {editor} = this.props; editor.emit('event-setter.bindEvent',this.state.eventName); + // 选中的是新建事件 + if (this.state.selectedEventName == ''){ + editor.emit('sourceEditor.addFunction',{ + functionName:this.state.eventName + }) + } + this.closeDialog(); }; diff --git a/packages/plugin-source-editor/src/index.tsx b/packages/plugin-source-editor/src/index.tsx index f1dba0d4e..0a2deb5f6 100644 --- a/packages/plugin-source-editor/src/index.tsx +++ b/packages/plugin-source-editor/src/index.tsx @@ -37,19 +37,23 @@ const defaultEditorOption = { vertical: 'auto', horizontal: 'auto', }, - } + }, }; +interface FunctionEventParam { + functionName: String; +} + export default class SourceEditor extends Component<{ editor: Editor; }> { - private monocoEditer:Object; - private editorCmd:Object; + private monocoEditer: Object; + private editorCmd: Object; state = { isShow: false, - tabKey: TAB_KEY.JS_TAB - } + tabKey: TAB_KEY.JS_TAB, + }; componentWillMount() { const { editor } = this.props; @@ -62,10 +66,19 @@ export default class SourceEditor extends Component<{ }); // 添加函数 - editor.on('sourceEditor.addFunction',(params:Object)=>{ - this.callEditorEvent('sourceEditor.addFunction',params); + editor.on('sourceEditor.addFunction', (params: FunctionEventParam) => { + this.callEditorEvent('sourceEditor.addFunction', params); + this.openPluginPannel(); + }); + + // 定位函数 + editor.on('sourceEditor.focusByFunction',(params:FunctionEventParam)=>{ + this.callEditorEvent('sourceEditor.focusByFunction', params); + this.openPluginPannel(); }) + + editor.once('designer.mount', (designer: Designer) => { // let schema = designer.project.getSchema(); // mock data @@ -90,7 +103,7 @@ export default class SourceEditor extends Component<{ }, methods: { //自定义方法对象: 选填 对象类型 - testFunc: { + getData: { //自定义方法: 选填 函数类型 type: 'JSExpression', value: "function() {\n \t\tconsole.log('testFunc');\n \t}", @@ -102,37 +115,41 @@ export default class SourceEditor extends Component<{ this.initCode(schema); }); - - - setTimeout (()=>{ - editor.emit('sourceEditor.addFunction',{ - functionName:'testgaga' - }) - },3000) - } - callEditorEvent = (eventName,params) => { - if (!this.monocoEditer){ + openPluginPannel = () => { + const {editor} = this.props; + // 判断面板是否处于激活状态 + if (!editor.leftNav || editor.leftNav != 'sourceEditor') { + // 打开面板 + editor.emit('leftNav.change', 'sourceEditor'); + } + } + + callEditorEvent = (eventName, params) => { + if (!this.monocoEditer) { this.editorCmd = { eventName, - params + params, }; return; } - if (eventName === 'sourceEditor.addFunction'){ - this.addFunction(params); + if (eventName === 'sourceEditor.addFunction') { + this.addFunction(params); + }else if (eventName === 'sourceEditor.focusByFunction'){ + this.focusByFunctionName(params); } - } + + }; initCode = (schema) => { - let jsCode = js_beautify(transfrom.schema2Code(schema),{ indent_size: 2, indent_empty_lines: true }); + let jsCode = js_beautify(transfrom.schema2Code(schema), { indent_size: 2, indent_empty_lines: true }); let css; if (schema.componentTree[0].css) { - css = css_beautify(schema.componentTree[0].css,{ indent_size: 2 }); + css = css_beautify(schema.componentTree[0].css, { indent_size: 2 }); } this.setState({ @@ -140,24 +157,57 @@ export default class SourceEditor extends Component<{ css, selectTab: TAB_KEY.JS_TAB, }); - }; - addFunction (params){ + /** + * 在js面板中添加一个新函数 + * @param params + */ + addFunction(params: FunctionEventParam) { const count = this.monocoEditer.getModel().getLineCount() || 0; const range = new monaco.Range(count, 1, count, 1); const functionCode = transfrom.getNewFunctionCode(params.functionName); - this.monocoEditer.executeEdits('log-source', [{ identifier: 'event_id', range:range , text: functionCode, forceMoveMarkers:true }]); + this.monocoEditer.executeEdits('log-source', [ + { identifier: 'event_id', range: range, text: functionCode, forceMoveMarkers: true }, + ]); + setTimeout(() => { + let newPosition = new monaco.Position(count + 1, 2); + this.monocoEditer.setPosition(newPosition); + this.monocoEditer.focus(); + }, 100); - this.updateCode(this.monocoEditer.getModel().getValue()) + this.updateCode(this.monocoEditer.getModel().getValue()); + } + + /** + * 根据函数名进行定位 + * @param functionName + */ + focusByFunctionName(params: FunctionEventParam) { + const functionName = params.functionName; + const matchedResult = this.monocoEditer + .getModel() + .findMatches(`${functionName}\\s*\\([\\s\\S]*\\)[\\s\\S]*\\{`, false, true)[0]; + if (matchedResult) { + + setTimeout(()=>{ + this.monocoEditer.revealLineInCenter(matchedResult.range.startLineNumber); + this.monocoEditer.setPosition({ + column: matchedResult.range.endColumn, + lineNumber: matchedResult.range.endLineNumber, + }); + + this.monocoEditer.focus(); + },100) + } } editorDidMount = (editor, monaco) => { console.log('editorDidMount', editor); this.monocoEditer = editor; - if (this.editorCmd){ - this.callEditorEvent(this.editorCmd.eventName,this.editorCmd.params); + if (this.editorCmd) { + this.callEditorEvent(this.editorCmd.eventName, this.editorCmd.params); } // var commandId = editor.addCommand( @@ -214,7 +264,7 @@ export default class SourceEditor extends Component<{ } transfrom.code2Schema(newCode); - } + }; render() { const { isShow, selectTab, jsCode, css } = this.state; @@ -226,7 +276,7 @@ export default class SourceEditor extends Component<{ return (
- {tabs.map((item) => ( + {tabs.map((item) => ( {isShow && (
- + this.onRelatedEventNameClick(record.relatedEventName)}> {record.relatedEventName || ''}
@@ -248,6 +248,8 @@ export default class EventsSetter extends Component<{ }); }; + + onEventMenuClick = (eventName: String) => { const { selectType, eventDataList } = this.state; eventDataList.push({ @@ -264,6 +266,13 @@ export default class EventsSetter extends Component<{ this.openDialog(eventName); }; + onRelatedEventNameClick = (eventName:String) => { + const {editor} = this.props.field; + editor.emit('sourceEditor.focusByFunction',{ + functionName:eventName + }) + } + closeEventMenu = () => { if (this.state.selectType !== null) { this.setState({ From 9c62a490c9f8fee7564dec310031755e7478691e Mon Sep 17 00:00:00 2001 From: "jianfang.rjf" Date: Thu, 7 May 2020 21:25:32 +0800 Subject: [PATCH 17/21] feat: add expression-setter AutoComplete tips --- .../setters/src/expression-setter/index.scss | 141 ++------------ .../setters/src/expression-setter/index.tsx | 179 +++++++----------- 2 files changed, 85 insertions(+), 235 deletions(-) diff --git a/packages/setters/src/expression-setter/index.scss b/packages/setters/src/expression-setter/index.scss index 19287099a..0d12a5571 100644 --- a/packages/setters/src/expression-setter/index.scss +++ b/packages/setters/src/expression-setter/index.scss @@ -1,130 +1,17 @@ -// mixin -.lowcode-setter-mixin > * { - vertical-align: middle; -} -.lowcode-setter-mixin { - width: 86%; -} -.lowcode-setter-mixin .next-input { - width: 100%; -} -.lowcode-setter-mixin .next-select-trigger { - width: 100%; -} -// json-setter -// :global { - .nrs-monaco-form { - .next-form-item:last-child { - margin: 0 !important; - } +.expression-setter-item-inner { + .next-menu-item-text { + vertical-align: middle; + display: flex; + justify-content: space-between; } - .monaco-editor-wrap { - .luna-monaco-button .next-icon-first { - height: 26px; - } - .monaco_fullscreen_icon { - position: absolute; - line-height: 1; - z-index: 7; - color: #ddd; - &:hover { - color: #fff; - } - } - .btns-eare { - text-align: left; - line-height: initial; - margin-top: 5px; - // button{ - // margin-right: 10px; - // } - } - &.monaco-nofullscreen { - position: relative !important; - .monaco_fullscreen_icon { - position: absolute; - top: 5px; - right: 5px; - line-height: 1; - z-index: 7; - i:before { - font-size: 16px; - } - } - } - &.monaco-fullscreen { - position: fixed !important; - height: 100% !important; - width: 100% !important; - border: 0; - margin: 0; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1001; - overflow: hidden; - .monaco_fullscreen_icon { - top: 10px; - right: 10px; - i:before { - font-size: 24px; - } - } - } - } - .luna-monaco-button button { - width: 100%; - } - .luna-monaco-button-dialog { - .next-dialog-body { - padding: 0; - .next-form-item { - height: 100%; - margin-bottom: 0; - .next-form-item-control, - .next-form-item-control > div { - height: 100% !important; - } - .next-form-item-help { - position: absolute; - } - } - } - } -// } -// color-setter -.lowcode-color-box { - margin-right: -5px; - padding: 3px 0 3px 3px; - width: 26px; - height: 26px; - display: inline-block; - div { - width: 20px; - height: 20px; - border: 1px solid #ddd; + .next-menu-item { + padding: 0 10px; } } -.next-balloon-normal.lowcode-color-content { - padding: 0; - background: #ffffff; - border-radius: 0; - border: 1px solid #e5e5e5; - box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1); - &:after { - display: none; - } - .sketch-picker { - border-radius: 0 !important; - border: none !important; - box-shadow: none !important; - .flexbox-fix { - input { - width: 100% !important; - min-width: 30px; - text-align: center; - } - } - } -} \ No newline at end of file +.code-input-value { + float: left; +} +.code-input-help { + float: right; + color: #6897f2; +} diff --git a/packages/setters/src/expression-setter/index.tsx b/packages/setters/src/expression-setter/index.tsx index 7e4ecd14b..2ab0e7a3c 100644 --- a/packages/setters/src/expression-setter/index.tsx +++ b/packages/setters/src/expression-setter/index.tsx @@ -1,24 +1,26 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { Select, Balloon } from '@alife/next'; +import { Select, Balloon, Icon } from '@alife/next'; import * as acorn from 'acorn'; import { isJSExpression, generateI18n } from './locale/utils'; import zhCN from './locale/zh-CN'; +import './index.scss'; + const { Option, AutoComplete } = Select; const { Tooltip } = Balloon; const helpMap = { this: '容器上下文对象', - 'this.state': '容器的state', - 'this.props': '容器的props', - 'this.context': '容器的context', - 'this.page': '页面上下文对象', - 'this.component': '组件上下文对象', - 'this.constants': '应用常量对象', - 'this.utils': '应用工具对象', - 'this.dataSourceMap': '容器数据源Map', - 'this.field': '表单Field对象' + 'state': '容器的state', + 'props': '容器的props', + 'context': '容器的context', + 'schema': '页面上下文对象', + 'component': '组件上下文对象', + 'constants': '应用常量对象', + 'utils': '应用工具对象', + 'dataSourceMap': '容器数据源Map', + 'field': '表单Field对象' } export default class ExpressionView extends PureComponent { @@ -45,7 +47,7 @@ export default class ExpressionView extends PureComponent { i18n: any; t: void; $input: any; - listenerFun: (event: any) => void; + listenerFun: ((event: any) => void) | undefined; static getInitValue(val: { value: any; match: (arg0: RegExp) => any; }) { if (isJSExpression(val)) { @@ -81,51 +83,12 @@ export default class ExpressionView extends PureComponent { onChange(value: string, actionType: string) { let realInputValue = value; let realDataSource = null; - const cursorIndex = this.getInputCursorPosition(); let nextCursorIndex: number; //更新值 if (actionType === 'itemClick' || actionType === 'enter') { let curValue = this.state.value; if (curValue) { - //如果是非.结束,则替换当前这个变量; - let preStr = curValue.substr(0, cursorIndex); - let nextStr = curValue.substr(cursorIndex); - let preArr = preStr.split('.'); - let preArrLen = preArr.length; - let tarPreStr = ''; - if (!preArr[preArrLen - 1]) { - //如果是.结束,则增加到.后面 - if (preArr[preArrLen - 2] === 'this') { - preArr = preArr.slice(0, preArrLen - 2); - preArr.push(value); - tarPreStr = preArr.join('.'); - } else { - tarPreStr = preStr + value; - } - } else { - if (preArr[preArrLen - 2] === 'this') { - preArr = preArr.slice(0, preArrLen - 2); - } else { - preArr = preArr.slice(0, preArrLen - 1); - } - preArr.push(value); - tarPreStr = preArr.join('.'); - } - realInputValue = tarPreStr + nextStr; - realDataSource = this.getDataSource(tarPreStr + '.') || []; - nextCursorIndex = tarPreStr.length; - } - } else { - let tarPreStr = value.substr(0, cursorIndex); - if (tarPreStr) { - let lastChar = tarPreStr.charAt(tarPreStr.length - 1); - if (lastChar === '.') { - realDataSource = this.getDataSource(tarPreStr) || []; - } else { - realDataSource = this.getDataSource(tarPreStr + '.'); - } - } else { - realDataSource = this.getDataSource('this.'); + realInputValue = curValue + realInputValue; } } //更新数据源 @@ -154,21 +117,16 @@ export default class ExpressionView extends PureComponent { * @return {Array} */ getDataSource(tempStr: string): Array { - if (tempStr === '' || /[^\w\.]$/.test(tempStr)) { - return this.getDataSource('this.') || []; + if (/[^\w\.]$/.test(tempStr)) { + return []; + } else if (tempStr === null || tempStr === '') { + return this.getContextKeys([]); } else if (/\w\.$/.test(tempStr)) { let currentField = this.getCurrentFiled(tempStr); if (!currentField) return null; let tempKeys = this.getObjectKeys(currentField.str); tempKeys = this.getContextKeys(tempKeys); if (!tempKeys) return null; - //给默认情况增加this - if (tempStr === 'this.') { - tempKeys = tempKeys.map((item: string) => { - return 'this.' + item; - }); - tempKeys.unshift('this'); - } return tempKeys; } else if (/\.$/.test(tempStr)) { return []; @@ -202,34 +160,31 @@ export default class ExpressionView extends PureComponent { * @param {Array} * @return {Array} */ - getContextKeys(keys: any) { - // let context = {}; - // const { appHelper } = this.context; - // const activeKey = appHelper && appHelper.activeKey; - // if (!activeKey) return; - // const activeCtx = appHelper.schemaHelper.compCtxMap && appHelper.schemaHelper.compCtxMap[activeKey]; - // if (!activeCtx) return null; - // let __self = activeCtx; - // if (keys && keys.length > 1) { - // keys.shift(0); - // let path = '/' + keys.join('/'); - // path = path.replace(/[\[\]]/g, '/'); - // context = jsonuri.get(__self, path); - // if (context && typeof context === 'object') { - // return this.filterKey(context); - // } - // } else if (keys && keys[0] === 'this') { - // return this.filterKey(__self); - // } - // return null; - return [ - "page", - "component" - ] + getContextKeys(keys: []) { + const editor = this.props.field.editor; + console.log(editor); + const limitKeys = ['schema', 'utils', 'constants']; + if (keys.length === 0) return limitKeys; + if (!limitKeys.includes(keys[0])) return []; + let result = []; + let keyValue = editor; + let assert = false; + keys.forEach(item => { + if (!keyValue[item] || typeof keyValue[item] !== 'object') { + assert = true; + } + if (keyValue[item]) { + keyValue = keyValue[item]; + } + }) + if (assert) return []; + result = Object.keys(keyValue); + return result; + // return utilsKeys.concat(constantsKeys).concat(schemaKeys); } /*过滤key */ - filterKey(obj: any) { + filterKey(obj: any, name: string) { let filterKeys = [ 'reloadDataSource', 'REACT_HOT_LOADER_RENDERED_GENERATION', @@ -244,7 +199,7 @@ export default class ExpressionView extends PureComponent { let result = []; for (let key in obj) { if (key.indexOf('_') !== 0 && filterKeys.indexOf(key) === -1) { - result.push(key); + result.push(`${name}.${key}`); } } return result; @@ -259,12 +214,16 @@ export default class ExpressionView extends PureComponent { filterOption(inputValue: string, item: { value: string | any[]; }) { const cursorIndex = this.getInputCursorPosition(); let preStr = inputValue.substr(0, cursorIndex); - let lastKey = preStr.split('.').slice(-1); + let lastKey: string[] = preStr.split('.').slice(-1); if (!lastKey) return true; if (item.value.indexOf(lastKey) > -1) return true; return false; } + // handleClick = () => { + // this.props.field.editor.emit('variableBindDialog.open'); + // } + render() { const { value, dataSource } = this.state; const { placeholder } = this.props; @@ -293,26 +252,30 @@ export default class ExpressionView extends PureComponent { isValObject ? ( value ) : ( - {'{{'}} - innerAfter={{'}}'}} - itemRender={({ value }) => { - return ( - - ); - }} - onChange={this.onChange.bind(this)} - filter={this.filterOption.bind(this)} - /> +
+ {'{{'}} + innerAfter={{'}}'}} + popupClassName="expression-setter-item-inner" + itemRender={({ value }) => { + console.log(value); + return ( + + ); + }} + onChange={this.onChange.bind(this)} + filter={this.filterOption.bind(this)} + /> +
) } > @@ -363,7 +326,7 @@ export default class ExpressionView extends PureComponent { * 字符串取得对象keys */ getObjectKeys(str: string) { - let keys = []; + let keys: string | any[] = []; if (str) keys = str.split('.'); return keys.slice(0, keys.length - 1); } From 0e50a2056a9c00bfddfe25af82462a781e231910 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Mon, 18 May 2020 16:03:00 +0800 Subject: [PATCH 18/21] feat: ReactProvider --- packages/react-provider/CHANGELOG.md | 4 + packages/react-provider/README.md | 1 + packages/react-provider/build.json | 5 + packages/react-provider/package.json | 43 ++++++++ packages/react-provider/src/index.ts | 5 + .../react-provider/src/lazy-component.tsx | 43 ++++++++ packages/react-provider/src/provider.tsx | 104 ++++++++++++++++++ packages/react-provider/tsconfig.json | 9 ++ 8 files changed, 214 insertions(+) create mode 100644 packages/react-provider/CHANGELOG.md create mode 100644 packages/react-provider/README.md create mode 100644 packages/react-provider/build.json create mode 100644 packages/react-provider/package.json create mode 100644 packages/react-provider/src/index.ts create mode 100644 packages/react-provider/src/lazy-component.tsx create mode 100644 packages/react-provider/src/provider.tsx create mode 100644 packages/react-provider/tsconfig.json diff --git a/packages/react-provider/CHANGELOG.md b/packages/react-provider/CHANGELOG.md new file mode 100644 index 000000000..e4d87c4d4 --- /dev/null +++ b/packages/react-provider/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/react-provider/README.md b/packages/react-provider/README.md new file mode 100644 index 000000000..f37b9b0f6 --- /dev/null +++ b/packages/react-provider/README.md @@ -0,0 +1 @@ +# 低代码引擎运行时框架 diff --git a/packages/react-provider/build.json b/packages/react-provider/build.json new file mode 100644 index 000000000..bd5cf18dd --- /dev/null +++ b/packages/react-provider/build.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + "build-plugin-component" + ] +} diff --git a/packages/react-provider/package.json b/packages/react-provider/package.json new file mode 100644 index 000000000..29cca8ab3 --- /dev/null +++ b/packages/react-provider/package.json @@ -0,0 +1,43 @@ +{ + "name": "@ali/lowcode-react-provider", + "version": "0.8.14", + "description": "React Provider for Runtime", + "files": [ + "es", + "lib" + ], + "main": "lib/index.js", + "module": "es/index.js", + "scripts": { + "build": "build-scripts build --skip-demo", + "test": "ava", + "test:snapshot": "ava --update-snapshots" + }, + "ava": { + "compileEnhancements": false, + "snapshotDir": "test/fixtures/__snapshots__", + "extensions": [ + "ts" + ], + "require": [ + "ts-node/register" + ] + }, + "license": "MIT", + "dependencies": { + "@ali/lowcode-runtime": "^0.8.13", + "react": "^16", + "react-dom": "^16", + "@recore/router": "^1.0.11" + }, + "devDependencies": { + "@alib/build-scripts": "^0.1.18", + "build-plugin-component": "^0.2.16", + "@types/node": "^13.7.1", + "@types/react": "^16", + "@types/react-dom": "^16" + }, + "publishConfig": { + "registry": "https://registry.npm.alibaba-inc.com" + } +} diff --git a/packages/react-provider/src/index.ts b/packages/react-provider/src/index.ts new file mode 100644 index 000000000..515d26e3e --- /dev/null +++ b/packages/react-provider/src/index.ts @@ -0,0 +1,5 @@ +import ReactProvider from './provider'; +import { Router } from '@recore/router'; + +export { Router }; +export default ReactProvider; diff --git a/packages/react-provider/src/lazy-component.tsx b/packages/react-provider/src/lazy-component.tsx new file mode 100644 index 000000000..b20fd2bf8 --- /dev/null +++ b/packages/react-provider/src/lazy-component.tsx @@ -0,0 +1,43 @@ +import { Component, createElement } from 'react'; +import { app } from '@ali/lowcode-runtime'; + +interface IProps { + getPageData: () => any; + [key: string]: any; +} + +interface IState { + schema: object | null; +} + +export default class LazyComponent extends Component { + constructor(props: IProps) { + super(props); + this.state = { + schema: null, + }; + } + + async componentDidMount() { + const { getPageData } = this.props; + if (getPageData && !this.state.schema) { + const schema = await getPageData(); + this.setState({ schema }); + } + } + + render() { + const { getPageData, ...restProps } = this.props; + const { schema } = this.state; + const Renderer = app.getRenderer(); + const Loading = app.getLoading(); + if (!Renderer || !schema) { + if (!Loading) { + return null; + } + // loading扩展点 + return createElement(Loading); + } + return createElement(Renderer as any, { schema, loading: Loading ? createElement(Loading) : null, ...restProps }); + } +} diff --git a/packages/react-provider/src/provider.tsx b/packages/react-provider/src/provider.tsx new file mode 100644 index 000000000..de4d97352 --- /dev/null +++ b/packages/react-provider/src/provider.tsx @@ -0,0 +1,104 @@ +import { createElement, ReactType, ReactElement } from 'react'; +import ReactDOM from 'react-dom'; +import { Router } from '@recore/router'; +import { app, Provider } from '@ali/lowcode-runtime'; +import LazyComponent from './lazy-component'; + +export default class ReactProvider extends Provider { + // 定制构造根组件的逻辑,如切换路由机制 + createApp() { + const RouterView = this.getRouterView(); + let App; + const layoutConfig = this.getLayoutConfig(); + if (!layoutConfig || !layoutConfig.componentName) { + App = (props: any) => (RouterView ? createElement(RouterView, { ...props }) : null); + return App; + } + const { componentName: layoutName, props: layoutProps } = layoutConfig; + const { content: Layout, props: extraLayoutProps } = app.getLayout(layoutName) || {}; + const sectionalRender = this.isSectionalRender(); + if (!sectionalRender && Layout) { + App = (props: any) => + createElement( + Layout, + { ...layoutProps, ...extraLayoutProps }, + RouterView ? createElement(RouterView, props) : null, + ); + } else { + App = (props: any) => (RouterView ? createElement(RouterView, props) : null); + } + return App; + } + + runApp(App: any, config: any) { + ReactDOM.render(, document.getElementById(config?.containerId || 'App')); + } + + // 内置实现 for 动态化渲染 + getRouterView(): ReactType | null { + const routerConfig = this.getRouterConfig(); + if (!routerConfig) { + return null; + } + const routes: Array<{ + path: string; + children: any; + exact: boolean; + defined: { keepAlive: boolean; [key: string]: any }; + }> = []; + let homePageId = this.getHomePage(); + Object.keys(routerConfig).forEach((pageId: string, idx: number) => { + if (!pageId) { + return; + } + const path = routerConfig[pageId]; + routes.push({ + path, + children: (props: any) => this.getLazyComponent(pageId, props), + exact: true, + defined: { keepAlive: true }, + }); + if (homePageId) { + return; + } + if (idx === 0 || path === '/') { + homePageId = pageId; + } + }); + if (homePageId) { + routes.push({ + path: '**', + children: (props: any) => this.getLazyComponent(homePageId, { ...props }), + exact: true, + defined: { keepAlive: true }, + }); + } + const RouterView = (props: any) => { + return createElement(Router as any, { + routes, + components: this.getComponents(), + utils: this.getUtils(), + componentsMap: this.getComponentsMapObj(), + ...props, + }); + }; + return RouterView; + } + + getLazyComponent(pageId: string, props: any): ReactElement | null { + if (!pageId) { + return null; + } + if (this.getlazyElement(pageId)) { + return this.getlazyElement(pageId); + } else { + const lazyElement = createElement(LazyComponent as any, { + getPageData: async () => await this.getPageData(pageId), + key: pageId, + ...props, + }); + this.setlazyElement(pageId, lazyElement); + return lazyElement; + } + } +} diff --git a/packages/react-provider/tsconfig.json b/packages/react-provider/tsconfig.json new file mode 100644 index 000000000..c37b76ecc --- /dev/null +++ b/packages/react-provider/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": [ + "./src/" + ] +} From 8e361967e04eb353dda286dc7d90bbd7538dcb3e Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Mon, 18 May 2020 16:03:44 +0800 Subject: [PATCH 19/21] =?UTF-8?q?chore:=20=E6=8A=BD=E7=A6=BBReact?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/runtime/build.json | 6 +- packages/runtime/package.json | 10 +- packages/runtime/src/core/container.ts | 17 ++- packages/runtime/src/core/index.ts | 15 ++- .../core/{provider/index.ts => provider.ts} | 7 +- .../runtime/src/core/provider/react/index.ts | 100 ------------------ .../core/provider/react/lazy-component.tsx | 43 -------- .../runtime/src/core/{run.ts => runApp.ts} | 54 +++++----- packages/runtime/src/index.ts | 4 +- 9 files changed, 53 insertions(+), 203 deletions(-) rename packages/runtime/src/core/{provider/index.ts => provider.ts} (96%) delete mode 100644 packages/runtime/src/core/provider/react/index.ts delete mode 100644 packages/runtime/src/core/provider/react/lazy-component.tsx rename packages/runtime/src/core/{run.ts => runApp.ts} (50%) diff --git a/packages/runtime/build.json b/packages/runtime/build.json index e791d5b6b..bd5cf18dd 100644 --- a/packages/runtime/build.json +++ b/packages/runtime/build.json @@ -1,9 +1,5 @@ { "plugins": [ - "build-plugin-component", - "build-plugin-fusion", - ["build-plugin-moment-locales", { - "locales": ["zh-cn"] - }] + "build-plugin-component" ] } diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 2c667549f..276e1cc32 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@ali/lowcode-runtime", - "version": "0.8.12", + "version": "0.8.14", "description": "Runtime for Ali lowCode engine", "files": [ "es", @@ -25,15 +25,13 @@ }, "license": "MIT", "dependencies": { - "@ali/recore": "^1.6.9", - "@ali/offline-events": "^1.0.0" + "@ali/offline-events": "^1.0.0", + "history": "^4.10.1" }, "devDependencies": { "@alib/build-scripts": "^0.1.18", "@types/node": "^13.7.1", - "@types/react": "^16", - "@types/react-dom": "^16", - "build-plugin-component": "^0.2.11" + "build-plugin-component": "^0.2.16" }, "publishConfig": { "registry": "https://registry.npm.alibaba-inc.com" diff --git a/packages/runtime/src/core/container.ts b/packages/runtime/src/core/container.ts index e8deee816..809394bf6 100644 --- a/packages/runtime/src/core/container.ts +++ b/packages/runtime/src/core/container.ts @@ -1,4 +1,3 @@ -import { ReactType } from 'react'; import Provider from './provider'; export interface ILayoutOptions { @@ -7,16 +6,16 @@ export interface ILayoutOptions { } export default class Container { - private renderer: ReactType | null = null; - private layouts: { [key: string]: { content: ReactType; props: any } } = {}; - private loading: ReactType | null = null; + private renderer: any = null; + private layouts: { [key: string]: { content: any; props: any } } = {}; + private loading: any = null; private provider: any; - registerRenderer(renderer: ReactType): any { + registerRenderer(renderer: any): any { this.renderer = renderer; } - registerLayout(Layout: ReactType, options: ILayoutOptions): any { + registerLayout(Layout: any, options: ILayoutOptions): any { if (!options) { return; } @@ -27,7 +26,7 @@ export default class Container { this.layouts[componentName] = { content: Layout, props }; } - registerLoading(component: ReactType) { + registerLoading(component: any) { if (!component) { return; } @@ -50,11 +49,11 @@ export default class Container { return this.layouts[componentName]; } - getRenderer(): ReactType | null { + getRenderer(): any { return this.renderer; } - getLoading(): ReactType | null { + getLoading(): any { return this.loading; } diff --git a/packages/runtime/src/core/index.ts b/packages/runtime/src/core/index.ts index 6160a6a20..de70f9229 100644 --- a/packages/runtime/src/core/index.ts +++ b/packages/runtime/src/core/index.ts @@ -1,7 +1,6 @@ -import { ReactType } from 'react'; import Container, { ILayoutOptions } from './container'; import { IProvider } from './provider'; -import run from './run'; +import runApp from './runApp'; class App { private container: Container; @@ -11,18 +10,18 @@ class App { } run() { - run(); + runApp(); } - registerRenderer(renderer: ReactType): any { + registerRenderer(renderer: any): any { this.container.registerRenderer(renderer); } - registerLayout(Layout: ReactType, options: ILayoutOptions): any { + registerLayout(Layout: any, options: ILayoutOptions): any { this.container.registerLayout(Layout, options); } - registerLoading(component: ReactType) { + registerLoading(component: any) { this.container.registerLoading(component); } @@ -34,11 +33,11 @@ class App { return this.container.getLayout(componentName); } - getRenderer(): ReactType | null { + getRenderer(): any | null { return this.container.getRenderer(); } - getLoading(): ReactType | null { + getLoading(): any | null { return this.container.getLoading(); } diff --git a/packages/runtime/src/core/provider/index.ts b/packages/runtime/src/core/provider.ts similarity index 96% rename from packages/runtime/src/core/provider/index.ts rename to packages/runtime/src/core/provider.ts index 79016f2ab..907dd4903 100644 --- a/packages/runtime/src/core/provider/index.ts +++ b/packages/runtime/src/core/provider.ts @@ -1,4 +1,4 @@ -import { IAppConfig, IUtils, IComponents, HistoryMode } from '../run'; +import { IAppConfig, IUtils, IComponents, HistoryMode } from './runApp'; import EventEmitter from '@ali/offline-events'; interface IConstants { @@ -110,6 +110,7 @@ export interface IProvider { getPageData(pageId: string): Promise; getLazyComponent(pageId: string, props: any): any; createApp(): void; + runApp(App: any, config: IAppConfig): void; } export default class Provider implements IProvider { @@ -197,6 +198,10 @@ export default class Provider implements IProvider { throw new Error('Method called "createApp" not implemented.'); } + runApp(App: any, config: IAppConfig) { + throw new Error('Method called "runApp" not implemented.'); + } + registerComponents(components: IComponents | undefined) { if (!components) { return; diff --git a/packages/runtime/src/core/provider/react/index.ts b/packages/runtime/src/core/provider/react/index.ts deleted file mode 100644 index 1c0a3fb07..000000000 --- a/packages/runtime/src/core/provider/react/index.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { createElement, ReactType, ReactElement } from 'react'; -import { Router } from '@ali/recore'; -import app from '../../index'; -import Provider from '..'; -import LazyComponent from './lazy-component'; - -export default class ReactProvider extends Provider { - // 定制构造根组件的逻辑,如切换路由机制 - createApp() { - const RouterView = this.getRouterView(); - let App; - const layoutConfig = this.getLayoutConfig(); - if (!layoutConfig || !layoutConfig.componentName) { - App = (props: any) => (RouterView ? createElement(RouterView, { ...props }) : null); - return App; - } - const { componentName: layoutName, props: layoutProps } = layoutConfig; - const { content: Layout, props: extraLayoutProps } = app.getLayout(layoutName) || {}; - const sectionalRender = this.isSectionalRender(); - if (!sectionalRender && Layout) { - App = (props: any) => - createElement( - Layout, - { ...layoutProps, ...extraLayoutProps }, - RouterView ? createElement(RouterView, props) : null, - ); - } else { - App = (props: any) => (RouterView ? createElement(RouterView, props) : null); - } - return App; - } - - // 内置实现 for 动态化渲染 - getRouterView(): ReactType | null { - const routerConfig = this.getRouterConfig(); - if (!routerConfig) { - return null; - } - const routes: Array<{ - path: string; - children: any; - exact: boolean; - defined: { keepAlive: boolean; [key: string]: any }; - }> = []; - let homePageId = this.getHomePage(); - Object.keys(routerConfig).forEach((pageId: string, idx: number) => { - if (!pageId) { - return; - } - const path = routerConfig[pageId]; - routes.push({ - path, - children: (props: any) => this.getLazyComponent(pageId, props), - exact: true, - defined: { keepAlive: true }, - }); - if (homePageId) { - return; - } - if (idx === 0 || path === '/') { - homePageId = pageId; - } - }); - if (homePageId) { - routes.push({ - path: '**', - children: (props: any) => this.getLazyComponent(homePageId, { ...props }), - exact: true, - defined: { keepAlive: true }, - }); - } - const RouterView = (props: any) => { - return createElement(Router as any, { - routes, - components: this.getComponents(), - utils: this.getUtils(), - componentsMap: this.getComponentsMapObj(), - ...props, - }); - }; - return RouterView; - } - - getLazyComponent(pageId: string, props: any): ReactElement | null { - if (!pageId) { - return null; - } - if (this.getlazyElement(pageId)) { - return this.getlazyElement(pageId); - } else { - const lazyElement = createElement(LazyComponent as any, { - getPageData: async () => await this.getPageData(pageId), - key: pageId, - ...props, - }); - this.setlazyElement(pageId, lazyElement); - return lazyElement; - } - } -} diff --git a/packages/runtime/src/core/provider/react/lazy-component.tsx b/packages/runtime/src/core/provider/react/lazy-component.tsx deleted file mode 100644 index 37c111097..000000000 --- a/packages/runtime/src/core/provider/react/lazy-component.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Component, createElement } from 'react'; -import app from '../../index'; - -interface IProps { - getPageData: () => any; - [key: string]: any; -} - -interface IState { - schema: object | null; -} - -export default class LazyComponent extends Component { - constructor(props: IProps) { - super(props); - this.state = { - schema: null, - }; - } - - async componentDidMount() { - const { getPageData } = this.props; - if (getPageData && !this.state.schema) { - const schema = await getPageData(); - this.setState({ schema }); - } - } - - render() { - const { getPageData, ...restProps } = this.props; - const { schema } = this.state; - const Renderer = app.getRenderer(); - const Loading = app.getLoading(); - if (!Renderer || !schema) { - if (!Loading) { - return null; - } - // loading扩展点 - return createElement(Loading); - } - return createElement(Renderer as any, { schema, loading: Loading ? createElement(Loading) : null, ...restProps }); - } -} diff --git a/packages/runtime/src/core/run.ts b/packages/runtime/src/core/runApp.ts similarity index 50% rename from packages/runtime/src/core/run.ts rename to packages/runtime/src/core/runApp.ts index 7cc7ab98f..6fb287f99 100644 --- a/packages/runtime/src/core/run.ts +++ b/packages/runtime/src/core/runApp.ts @@ -1,6 +1,4 @@ -import { ReactType } from 'react'; -import { runApp } from '@ali/recore'; -import { HashHistoryBuildOptions, BrowserHistoryBuildOptions, MemoryHistoryBuildOptions } from '@recore/history'; +import { HashHistoryBuildOptions, BrowserHistoryBuildOptions, MemoryHistoryBuildOptions } from 'history'; import app from './index'; export type HistoryOptions = { @@ -8,7 +6,7 @@ export type HistoryOptions = { } & (HashHistoryBuildOptions | BrowserHistoryBuildOptions | MemoryHistoryBuildOptions); export interface IComponents { - [key: string]: ReactType; + [key: string]: any; } export interface IUtils { @@ -22,34 +20,35 @@ export interface IAppConfig { components?: IComponents; utils?: IUtils; containerId?: string; + [key: string]: any; } -export interface IRecoreAppConfig { - history?: HistoryMode; - globalComponents?: IComponents; - globalUtils?: IUtils; - containerId?: string; -} +// export interface IRecoreAppConfig { +// history?: HistoryMode; +// globalComponents?: IComponents; +// globalUtils?: IUtils; +// containerId?: string; +// } -function transformConfig(config: IAppConfig | (() => IAppConfig)): IRecoreAppConfig { - if (!config) { - return {}; - } - if (typeof config === 'function') { - config = config(); - } - return { - history: config.history, - globalComponents: config.components, - globalUtils: config.utils, - containerId: config.containerId, - }; -} +// function transformConfig(config: IAppConfig | (() => IAppConfig)): IRecoreAppConfig { +// if (!config) { +// return {}; +// } +// if (typeof config === 'function') { +// config = config(); +// } +// return { +// history: config.history, +// globalComponents: config.components, +// globalUtils: config.utils, +// containerId: config.containerId, +// }; +// } -export default function run() { +export default function runApp() { const provider = app.getProvider(); if (!provider) { - throw new Error(''); + throw new Error('Please register class Provider'); } provider.onReady(() => { const promise = provider.async(); @@ -58,8 +57,7 @@ export default function run() { return; } const App = provider.createApp(); - config = transformConfig(config); - runApp(App, config); + provider.runApp(App, config); }); }); } diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index bb8e079a1..7a0999d95 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -1,7 +1,5 @@ -import { navigator, Router } from '@ali/recore'; import Provider from './core/provider'; -import ReactProvider from './core/provider/react'; import app from './core'; import * as Utils from './utils'; -export { app, Router, Provider, ReactProvider, navigator, Utils }; +export { app, Provider, Utils }; From 93cd908adb92946802607ac32d2f47acb5872df3 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Tue, 19 May 2020 21:03:13 +0800 Subject: [PATCH 20/21] chore(runtime): index.d.ts --- packages/runtime/index.d.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/runtime/index.d.ts b/packages/runtime/index.d.ts index 6e3013290..76ca8e969 100644 --- a/packages/runtime/index.d.ts +++ b/packages/runtime/index.d.ts @@ -1,8 +1,7 @@ -import { ReactType } from 'react'; type HistoryMode = 'browser' | 'hash'; interface ComponentsMap { - [key: string]: ReactType; + [key: string]: any; } interface UtilsMap { From cb0f3827c775be8ef58fb64367c45fb5a707c6a1 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Tue, 19 May 2020 21:03:34 +0800 Subject: [PATCH 21/21] feat(rax-provider): init --- packages/rax-provider/CHANGELOG.md | 4 + packages/rax-provider/README.md | 1 + packages/rax-provider/build.json | 11 +++ packages/rax-provider/package.json | 30 ++++++ packages/rax-provider/src/index.js | 5 + packages/rax-provider/src/lazy-component.js | 28 ++++++ packages/rax-provider/src/provider.js | 103 ++++++++++++++++++++ packages/rax-provider/src/router.js | 26 +++++ 8 files changed, 208 insertions(+) create mode 100644 packages/rax-provider/CHANGELOG.md create mode 100644 packages/rax-provider/README.md create mode 100644 packages/rax-provider/build.json create mode 100644 packages/rax-provider/package.json create mode 100644 packages/rax-provider/src/index.js create mode 100644 packages/rax-provider/src/lazy-component.js create mode 100644 packages/rax-provider/src/provider.js create mode 100644 packages/rax-provider/src/router.js diff --git a/packages/rax-provider/CHANGELOG.md b/packages/rax-provider/CHANGELOG.md new file mode 100644 index 000000000..e9fb6ecf5 --- /dev/null +++ b/packages/rax-provider/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. \ No newline at end of file diff --git a/packages/rax-provider/README.md b/packages/rax-provider/README.md new file mode 100644 index 000000000..f37b9b0f6 --- /dev/null +++ b/packages/rax-provider/README.md @@ -0,0 +1 @@ +# 低代码引擎运行时框架 diff --git a/packages/rax-provider/build.json b/packages/rax-provider/build.json new file mode 100644 index 000000000..3edf14380 --- /dev/null +++ b/packages/rax-provider/build.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "build-plugin-rax-component", + { + "type": "rax", + "targets": ["web"] + } + ] + ] +} diff --git a/packages/rax-provider/package.json b/packages/rax-provider/package.json new file mode 100644 index 000000000..62712f312 --- /dev/null +++ b/packages/rax-provider/package.json @@ -0,0 +1,30 @@ +{ + "name": "@ali/lowcode-rax-provider", + "version": "0.8.14-beta.0", + "description": "Rax Provider for Runtime", + "files": [ + "es", + "lib" + ], + "main": "lib/index.js", + "module": "es/index.js", + "scripts": { + "start": "build-scripts start", + "build": "build-scripts build" + }, + "license": "MIT", + "dependencies": { + "@ali/lowcode-runtime": "^0.8.14-beta.0", + "rax": "1.1.2", + "driver-universal": "^3.1.3", + "rax-use-router": "^3.0.0", + "history": "^4.10.1" + }, + "devDependencies": { + "@alib/build-scripts": "^0.1.18", + "build-plugin-rax-component": "^0.2.0" + }, + "publishConfig": { + "registry": "https://registry.npm.alibaba-inc.com" + } +} diff --git a/packages/rax-provider/src/index.js b/packages/rax-provider/src/index.js new file mode 100644 index 000000000..e51321b80 --- /dev/null +++ b/packages/rax-provider/src/index.js @@ -0,0 +1,5 @@ +import RaxProvider from './provider'; +import getRouter from './router'; + +export { getRouter }; +export default RaxProvider; diff --git a/packages/rax-provider/src/lazy-component.js b/packages/rax-provider/src/lazy-component.js new file mode 100644 index 000000000..5430c75b9 --- /dev/null +++ b/packages/rax-provider/src/lazy-component.js @@ -0,0 +1,28 @@ +import { createElement, useState, useEffect } from 'rax'; +import { app } from '@ali/lowcode-runtime'; + +export default function LazyComponent(props) { + const [schema, setSchema] = useState(null); + + useEffect(() => { + (async () => { + const { getPageData } = props || {}; + if (getPageData && !schema) { + const data = await getPageData(); + setSchema(data); + } + })(); + }); + + const { getPageData, ...restProps } = props || {}; + const Renderer = app.getRenderer(); + const Loading = app.getLoading(); + if (!Renderer || !schema) { + if (!Loading) { + return null; + } + // loading扩展点 + return createElement(Loading); + } + return createElement(Renderer, { schema, loading: Loading ? createElement(Loading) : null, ...restProps }); +} diff --git a/packages/rax-provider/src/provider.js b/packages/rax-provider/src/provider.js new file mode 100644 index 000000000..b64b2316e --- /dev/null +++ b/packages/rax-provider/src/provider.js @@ -0,0 +1,103 @@ +import { createElement, render } from 'rax'; +import UniversalDriver from 'driver-universal'; +import { app, Provider } from '@ali/lowcode-runtime'; +import LazyComponent from './lazy-component'; +import getRouter from './router'; + +export default class RaxProvider extends Provider { + // 定制构造根组件的逻辑,如切换路由机制 + createApp() { + const RouterView = this.getRouterView(); + let App; + const layoutConfig = this.getLayoutConfig(); + if (!layoutConfig || !layoutConfig.componentName) { + App = (props) => (RouterView ? createElement(RouterView, { ...props }) : null); + return App; + } + const { componentName: layoutName, props: layoutProps } = layoutConfig; + const { content: Layout, props: extraLayoutProps } = app.getLayout(layoutName) || {}; + const sectionalRender = this.isSectionalRender(); + if (!sectionalRender && Layout) { + App = (props) => + createElement( + Layout, + { ...layoutProps, ...extraLayoutProps }, + RouterView ? createElement(RouterView, props) : null, + ); + } else { + App = (props) => (RouterView ? createElement(RouterView, props) : null); + } + return App; + } + + runApp(App, config) { + render(createElement(App), document.getElementById(config?.containerId || 'App'), { driver: UniversalDriver }); + } + + // 内置实现 for 动态化渲染 + getRouterView() { + const routerConfig = this.getRouterConfig(); + if (!routerConfig) { + return null; + } + const routes = []; + let homePageId = this.getHomePage(); + Object.keys(routerConfig).forEach((pageId, idx) => { + if (!pageId) { + return; + } + const path = routerConfig[pageId]; + routes.push({ + path, + component: (props: any) => + this.getLazyComponent(pageId, { + components: this.getComponents(), + utils: this.getUtils(), + componentsMap: this.getComponentsMapObj(), + ...props, + }), + }); + if (homePageId) { + return; + } + if (idx === 0 || path === '/') { + homePageId = pageId; + } + }); + if (homePageId) { + routes.push({ + path: '**', + component: (props) => + this.getLazyComponent(homePageId, { + components: this.getComponents(), + utils: this.getUtils(), + componentsMap: this.getComponentsMapObj(), + ...props, + }), + }); + } + const Router = getRouter({ + history: this.getHistory(), + routes, + }); + const RouterView = (props) => createElement(Router, props); + return RouterView; + } + + getLazyComponent(pageId, props) { + if (!pageId) { + return null; + } + if (this.getlazyElement(pageId)) { + return this.getlazyElement(pageId); + } + const lazyElement = createElement(LazyComponent, { + // eslint-disable-next-line no-return-await + getPageData: async () => await this.getPageData(pageId), + key: pageId, + ...props, + }); + this.setlazyElement(pageId, lazyElement); + return lazyElement; + } +} diff --git a/packages/rax-provider/src/router.js b/packages/rax-provider/src/router.js new file mode 100644 index 000000000..5f2ffaba4 --- /dev/null +++ b/packages/rax-provider/src/router.js @@ -0,0 +1,26 @@ +import { useRouter } from 'rax-use-router'; +import { createHashHistory, createBrowserHistory } from 'history'; + +const getConfig = (config) => { + let { history } = config; + const { routes } = config; + if (typeof history === 'string') { + if (history === 'hash') { + history = createHashHistory(); + } else if (history === 'browser') { + history = createBrowserHistory(); + } + } + return () => ({ + history, + routes, + }); +}; + +export default function getRouter(config) { + return function Router() { + const configWrapper = getConfig(config); + const { component } = useRouter(configWrapper); + return component; + }; +}