From 933cef1c8ad828a96ee604aab1cd4b8d469a8f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E7=9A=93?= Date: Thu, 17 Sep 2020 13:49:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=E4=B8=80=E4=BA=9B=20?= =?UTF-8?q?vision=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lerna.json | 2 +- .../designer/src/builtin-simulator/host.ts | 21 ++- .../designer/src/document/document-model.ts | 47 +++--- packages/designer/src/project/project.ts | 3 - .../editor-preset-vision/src/base/flags.ts | 147 ++++++++++++++++++ packages/editor-preset-vision/src/index.ts | 4 + packages/editor-preset-vision/src/pages.ts | 3 + packages/editor-skeleton/src/widget/utils.ts | 4 +- .../react-renderer/src/utils/dataHelper.ts | 2 +- .../src/renderer-view.tsx | 24 +-- .../react-simulator-renderer/src/renderer.ts | 7 +- 11 files changed, 218 insertions(+), 46 deletions(-) create mode 100644 packages/editor-preset-vision/src/base/flags.ts diff --git a/lerna.json b/lerna.json index eefec1cb9..82d8bd950 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "lerna": "2.11.0", - "version": "1.0.9-2", + "version": "0.10.0", "npmClient": "tyarn", "registry": "http://registry.npm.alibaba-inc.com", "useWorkspaces": true, diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index 399f63724..a18e1e367 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -30,13 +30,15 @@ import { getRectTarget, Rect, CanvasPoint, + Designer, } from '../designer'; import { parseMetadata } from './utils/parse-metadata'; -import { ComponentMetadata, NodeSchema, ComponentSchema } from '@ali/lowcode-types'; +import { ComponentMetadata, ComponentSchema } from '@ali/lowcode-types'; import { BuiltinSimulatorRenderer } from './renderer'; import clipboard from '../designer/clipboard'; import { LiveEditing } from './live-editing/live-editing'; import { Project } from '../project'; +import { Scroller } from '../designer/scroller'; export interface LibraryItem { package: string; @@ -110,9 +112,19 @@ const defaultRaxEnvironment = [ export class BuiltinSimulatorHost implements ISimulatorHost { readonly isSimulator = true; - constructor(readonly project: Project) {} + readonly project: Project; - readonly designer = this.project.designer; + readonly designer: Designer; + + readonly viewport = new Viewport(); + + readonly scroller: Scroller; + + constructor(project: Project) { + this.project = project; + this.designer = project?.designer; + this.scroller = this.designer.createScroller(this.viewport); + } get currentDocument() { return this.project.currentDocument; @@ -182,9 +194,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost(); + readonly project: Project; + + readonly designer: Designer; + @obx.val private nodes = new Set(); private seqId = 0; @@ -83,28 +87,20 @@ export class DocumentModel { } get fileName(): string { - return this.rootNode.getExtraProp('fileName')?.getAsString() || this.id; + return this.rootNode?.getExtraProp('fileName')?.getAsString() || this.id; } set fileName(fileName: string) { - this.rootNode.getExtraProp('fileName', true)?.setValue(fileName); + this.rootNode?.getExtraProp('fileName', true)?.setValue(fileName); } private _modalNode?: ParentalNode; private _blank?: boolean; - get modalNode() { - return this._modalNode; - } - - get currentRoot() { - return this.modalNode || this.rootNode; - } - private inited = false; - constructor(readonly project: Project, schema?: RootSchema) { + constructor(project: Project, schema?: RootSchema) { /* // TODO // use special purge process @@ -112,6 +108,8 @@ export class DocumentModel { console.info(this.willPurgeSpace); }, true); */ + this.project = project; + this.designer = this.project?.designer; this.emitter = new EventEmitter(); if (!schema) { @@ -140,6 +138,14 @@ export class DocumentModel { @obx.val private willPurgeSpace: Node[] = []; + get modalNode() { + return this._modalNode; + } + + get currentRoot() { + return this.modalNode || this.rootNode; + } + addWillPurge(node: Node) { this.willPurgeSpace.push(node); } @@ -155,8 +161,6 @@ export class DocumentModel { return this._blank && !this.isModified(); } - readonly designer = this.project.designer; - /** * 生成唯一id */ @@ -186,10 +190,6 @@ export class DocumentModel { @obx.val private activeNodes?: Node[]; - private setupListenActiveNodes() { - // todo: - } - /** * 根据 schema 创建一个节点 */ @@ -664,6 +664,17 @@ export class DocumentModel { onRefresh(/* func: () => void */) { console.warn('onRefresh method is deprecated'); } + + onReady(fn: Function) { + this.designer.editor.on('document-open', fn); + return () => { + this.designer.editor.removeListener('document-open', fn); + }; + } + + private setupListenActiveNodes() { + // todo: + } } export function isDocumentModel(obj: any): obj is DocumentModel { diff --git a/packages/designer/src/project/project.ts b/packages/designer/src/project/project.ts index 970f2264d..2d6b2c643 100644 --- a/packages/designer/src/project/project.ts +++ b/packages/designer/src/project/project.ts @@ -261,7 +261,4 @@ export class Project { this.emitter.removeListener('current-document.change', fn); }; } - // 通知标记删除,需要告知服务端 - // 项目角度编辑不是全量打开所有文档,是按需加载,哪个更新就通知更新谁, - // 哪个删除就 } diff --git a/packages/editor-preset-vision/src/base/flags.ts b/packages/editor-preset-vision/src/base/flags.ts new file mode 100644 index 000000000..be0fc8e1b --- /dev/null +++ b/packages/editor-preset-vision/src/base/flags.ts @@ -0,0 +1,147 @@ +import domReady from 'domready'; +import { EventEmitter } from 'events'; + +const Shells = ['iphone6']; + +export class Flags { + public emitter: EventEmitter; + public flags: string[]; + public ready: boolean; + public lastFlags: string[]; + public lastShell: string; + + private lastSimulatorDevice: string; + + constructor() { + this.emitter = new EventEmitter(); + this.flags = ['design-mode']; + + domReady(() => { + this.ready = true; + this.applyFlags(); + }); + } + + public setDragMode(flag: boolean) { + if (flag) { + this.add('drag-mode'); + } else { + this.remove('drag-mode'); + } + } + + public setPreviewMode(flag: boolean) { + if (flag) { + this.add('preview-mode'); + this.remove('design-mode'); + } else { + this.add('design-mode'); + this.remove('preview-mode'); + } + } + + public setWithShell(shell: string) { + if (shell === this.lastShell) { + return; + } + if (this.lastShell) { + this.remove(`with-${this.lastShell}shell`); + } + if (shell) { + if (Shells.indexOf(shell) < 0) { + shell = Shells[0]; + } + this.add(`with-${shell}shell`); + this.lastShell = shell; + } + } + + public setSimulator(device: string) { + if (this.lastSimulatorDevice) { + this.remove(`simulator-${this.lastSimulatorDevice}`); + } + if (device !== '' && device !== 'pc') { + this.add(`simulator-${device}`); + } + this.lastSimulatorDevice = device; + } + + public setHideSlate(flag: boolean) { + if (this.has('slate-fixed')) { + return; + } + if (flag) { + this.add('hide-slate'); + } else { + this.remove('hide-slate'); + } + } + + public setSlateFixedMode(flag: boolean) { + if (flag) { + this.remove('hide-slate'); + this.add('slate-fixed'); + } else { + this.remove('slate-fixed'); + } + } + + public setSlateFullMode(flag: boolean) { + if (flag) { + this.add('slate-full-screen'); + } else { + this.remove('slate-full-screen'); + } + } + + public getFlags() { + return this.flags; + } + + public applyFlags(modifiedFlag?: string) { + if (!this.ready) { + return; + } + + const doe = document.documentElement; + if (this.lastFlags) { + this.lastFlags.filter((flag: string) => this.flags.indexOf(flag) < 0).forEach((flag) => { + doe.classList.remove(`engine-${flag}`); + }); + } + this.flags.forEach((flag) => { + doe.classList.add(`engine-${flag}`); + }); + + this.lastFlags = this.flags.slice(0); + this.emitter.emit('flagschange', this.flags, modifiedFlag); + } + + public has(flag: string) { + return this.flags.indexOf(flag) > -1; + } + + public add(flag: string) { + if (!this.has(flag)) { + this.flags.push(flag); + this.applyFlags(flag); + } + } + + public remove(flag: string) { + const i = this.flags.indexOf(flag); + if (i > -1) { + this.flags.splice(i, 1); + this.applyFlags(flag); + } + } + + public onFlagsChange(func: () => any) { + this.emitter.on('flagschange', func); + return () => { + this.emitter.removeListener('flagschange', func); + }; + } +} + +export default new Flags(); diff --git a/packages/editor-preset-vision/src/index.ts b/packages/editor-preset-vision/src/index.ts index 30a3ddef1..459074e9d 100644 --- a/packages/editor-preset-vision/src/index.ts +++ b/packages/editor-preset-vision/src/index.ts @@ -14,6 +14,7 @@ import Panes from './panes'; import Exchange from './exchange'; import context from './context'; import VisualManager from './base/visualManager'; +import VisualDesigner from './base/visualDesigner'; import Trunk from './bundle/trunk'; import Prototype from './bundle/prototype'; import Bundle from './bundle/bundle'; @@ -22,6 +23,7 @@ import * as Field from './fields'; import Prop from './prop'; import Env from './env'; import DragEngine from './drag-engine'; +import Flags from './base/flags'; import Viewport from './viewport'; import Project from './project'; @@ -60,6 +62,7 @@ const ui = { const modules = { VisualManager, + VisualDesigner, I18nUtil, Prop, }; @@ -107,6 +110,7 @@ const VisualEngine = { Project, logger, Symbols, + Flags, }; (window as any).VisualEngine = VisualEngine; diff --git a/packages/editor-preset-vision/src/pages.ts b/packages/editor-preset-vision/src/pages.ts index 00966c8f1..81ae1d672 100644 --- a/packages/editor-preset-vision/src/pages.ts +++ b/packages/editor-preset-vision/src/pages.ts @@ -124,6 +124,9 @@ Object.defineProperty(pages, 'currentPage', { get() { return project.currentDocument; }, + set(_currentPage) { + // do nothing + }, }); pages.onCurrentPageChange((page: DocumentModel) => { diff --git a/packages/editor-skeleton/src/widget/utils.ts b/packages/editor-skeleton/src/widget/utils.ts index f768e4fc3..bd680c202 100644 --- a/packages/editor-skeleton/src/widget/utils.ts +++ b/packages/editor-skeleton/src/widget/utils.ts @@ -38,7 +38,9 @@ export function composeTitle(title?: TitleContent, icon?: IconType, tip?: TipCon } } if (isTitleConfig(title) && noIcon) { - title.icon = undefined; + if (!isValidElement(title)) { + title.icon = undefined; + } } return title; } diff --git a/packages/react-renderer/src/utils/dataHelper.ts b/packages/react-renderer/src/utils/dataHelper.ts index c7f6f1ce5..7503b92da 100644 --- a/packages/react-renderer/src/utils/dataHelper.ts +++ b/packages/react-renderer/src/utils/dataHelper.ts @@ -160,7 +160,7 @@ export default class DataHelper { const _tb_token_ = csrfInput && csrfInput.value; asyncDataList.forEach((req) => { const { id, type, options } = req; - if (!id || !type) return; + if (!id || !type || type === 'legao') return; if (type === 'doServer') { const { uri, params } = options || {}; if (!uri) return; diff --git a/packages/react-simulator-renderer/src/renderer-view.tsx b/packages/react-simulator-renderer/src/renderer-view.tsx index 6fa9d6cce..07b63d6f7 100644 --- a/packages/react-simulator-renderer/src/renderer-view.tsx +++ b/packages/react-simulator-renderer/src/renderer-view.tsx @@ -151,18 +151,18 @@ class Renderer extends Component<{ viewProps._leaf = leaf; viewProps._componentName = leaf?.componentName; // 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动 - if ( - !viewProps.dataSource && - leaf?.isContainer() && - (children == null || (Array.isArray(children) && !children.length)) && - (!viewProps.style || Object.keys(viewProps.style).length === 0) - ) { - children = ( -
- {viewProps.placeholder || '拖拽组件或模板到这里'} -
- ); - } + // if ( + // !viewProps.dataSource && + // leaf?.isContainer() && + // (children == null || (Array.isArray(children) && !children.length)) && + // (!viewProps.style || Object.keys(viewProps.style).length === 0) + // ) { + // children = ( + //
+ // {viewProps.placeholder || '拖拽组件或模板到这里'} + //
+ // ); + // } if (viewProps._componentName === 'a') { delete viewProps.href; } diff --git a/packages/react-simulator-renderer/src/renderer.ts b/packages/react-simulator-renderer/src/renderer.ts index 884196dbf..f6f357fe6 100644 --- a/packages/react-simulator-renderer/src/renderer.ts +++ b/packages/react-simulator-renderer/src/renderer.ts @@ -3,16 +3,15 @@ import { render as reactRender } from 'react-dom'; import { host } from './host'; import SimulatorRendererView from './renderer-view'; import { computed, obx } from '@recore/obx'; -import { Asset } from '@ali/lowcode-utils'; import { getClientRects } from './utils/get-client-rects'; import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes'; import { + Asset, isElement, cursor, setNativeSelection, buildComponents, getSubComponent, - AssetLoader, } from '@ali/lowcode-utils'; import { RootSchema, ComponentSchema, TransformStage, NodeSchema } from '@ali/lowcode-types'; // import { isESModule, isElement, acceptsRef, wrapReactClass, cursor, setNativeSelection } from '@ali/lowcode-utils'; @@ -270,7 +269,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { this._components = { ...builtinComponents, ...this._components, - } + }; } @obx.ref private _components: any = {}; @computed get components(): object { @@ -365,7 +364,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { } const node = host.currentDocument?.createNode(_schema); - _schema = node?.export(TransformStage.Render); + _schema = node?.export(TransformStage.Render) || {}; const processPropsSchema = (propsSchema: any, propsMap: any): any => { if (!propsSchema) {