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] =?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); - } - }); - } -}