diff --git a/docs/docs/api/model/editor-view.md b/docs/docs/api/model/editor-view.md new file mode 100644 index 000000000..a3cc83e1f --- /dev/null +++ b/docs/docs/api/model/editor-view.md @@ -0,0 +1,21 @@ +--- +title: EditorView +sidebar_position: 12 +--- + +> **[@experimental](./#experimental)**
+> **@types** [IPublicModelEditorView](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/editor-view.ts)
+> **@since** v1.1.7 + +窗口编辑视图 + +## 类型定义 + +``` +import { IPublicModelPluginContext } from "./plugin-context"; + +export interface IPublicModelEditorView extends IPublicModelPluginContext {}; + +``` + +相关类型定义: [IPublicModelPluginContext](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/plugin-context.ts) diff --git a/docs/docs/api/model/window.md b/docs/docs/api/model/window.md index f102c0cab..3cc8b5d5e 100644 --- a/docs/docs/api/model/window.md +++ b/docs/docs/api/model/window.md @@ -38,6 +38,22 @@ sidebar_position: 12 关联模型 [IPublicModelResource](./resource) +### currentEditorView +窗口当前视图 + +`@type {IPublicModelEditorView}` + +关联模型 [IPublicModelEditorView](./editor-view) + +### editorViews + +窗口所有视图 + +`@type {IPublicModelEditorView[]}` + +关联模型 [IPublicModelEditorView](./editor-view) + + ## 方法 ### importSchema diff --git a/packages/designer/src/plugin/plugin-types.ts b/packages/designer/src/plugin/plugin-types.ts index 23aac2849..ac08d7d0c 100644 --- a/packages/designer/src/plugin/plugin-types.ts +++ b/packages/designer/src/plugin/plugin-types.ts @@ -17,6 +17,7 @@ import { IPublicTypePluginMeta, IPublicTypePluginRegisterOptions, IPublicModelWindow, + IPublicEnumPluginRegisterLevel, } from '@alilc/lowcode-types'; import PluginContext from './plugin-context'; @@ -58,6 +59,7 @@ export interface ILowCodePluginContextPrivate { set canvas(canvas: IPublicApiCanvas); set workspace(workspace: IPublicApiWorkspace); set editorWindow(window: IPublicModelWindow); + set registerLevel(level: IPublicEnumPluginRegisterLevel); } export interface ILowCodePluginContextApiAssembler { assembleApis( diff --git a/packages/engine/src/engine-core.ts b/packages/engine/src/engine-core.ts index f0c283ec1..84dfd67aa 100644 --- a/packages/engine/src/engine-core.ts +++ b/packages/engine/src/engine-core.ts @@ -18,6 +18,7 @@ import { IPublicTypeDisposable, IPublicApiPlugins, IPublicApiWorkspace, + IPublicEnumPluginRegisterLevel, } from '@alilc/lowcode-types'; import { Designer, @@ -138,6 +139,7 @@ const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = { context.plugins = plugins; context.logger = new Logger({ level: 'warn', bizName: `plugin:${pluginName}` }); context.workspace = workspace; + context.registerLevel = IPublicEnumPluginRegisterLevel.Default; }, }; diff --git a/packages/plugin-outline-pane/package.json b/packages/plugin-outline-pane/package.json index ec4738cd7..8a1472ce2 100644 --- a/packages/plugin-outline-pane/package.json +++ b/packages/plugin-outline-pane/package.json @@ -13,8 +13,6 @@ }, "dependencies": { "@alifd/next": "^1.19.16", - "@alilc/lowcode-designer": "1.1.6", - "@alilc/lowcode-editor-core": "1.1.6", "@alilc/lowcode-types": "1.1.6", "@alilc/lowcode-utils": "1.1.6", "classnames": "^2.2.6", diff --git a/packages/plugin-outline-pane/src/controllers/pane-controller.ts b/packages/plugin-outline-pane/src/controllers/pane-controller.ts index a02844ad1..e7c41892c 100644 --- a/packages/plugin-outline-pane/src/controllers/pane-controller.ts +++ b/packages/plugin-outline-pane/src/controllers/pane-controller.ts @@ -16,16 +16,15 @@ import { IPublicModelDropLocation, IPublicModelScroller, IPublicModelScrollTarget, - IPublicModelPluginContext, IPublicModelLocateEvent, } from '@alilc/lowcode-types'; import TreeNode from './tree-node'; import { IndentTrack } from '../helper/indent-track'; import DwellTimer from '../helper/dwell-timer'; -import { ITreeBoard, TreeMaster } from './tree-master'; +import { IOutlinePanelPluginContext, ITreeBoard, TreeMaster } from './tree-master'; export class PaneController implements IPublicModelSensor, ITreeBoard, IPublicTypeScrollable { - private pluginContext: IPublicModelPluginContext; + private pluginContext: IOutlinePanelPluginContext; private treeMaster?: TreeMaster; @@ -100,8 +99,8 @@ export class PaneController implements IPublicModelSensor, ITreeBoard, IPublicTy private _shell: HTMLDivElement | null = null; - constructor(at: string | symbol, pluginContext: IPublicModelPluginContext, treeMaster: TreeMaster) { - this.pluginContext = pluginContext; + constructor(at: string | symbol, treeMaster: TreeMaster) { + this.pluginContext = treeMaster.pluginContext; this.treeMaster = treeMaster; this.at = at; let inited = false; @@ -237,7 +236,7 @@ export class PaneController implements IPublicModelSensor, ITreeBoard, IPublicTy let { node } = treeNode; if (isDragNodeObject(dragObject)) { const newNodes = operationalNodes; - let i = newNodes.length; + let i = newNodes?.length; let p: any = node; while (i-- > 0) { if (newNodes[i].contains(p)) { @@ -482,7 +481,7 @@ export class PaneController implements IPublicModelSensor, ITreeBoard, IPublicTy const isSlotContainer = treeNode.hasSlots(); const isContainer = treeNode.isContainer(); - if (container.isSlot && !treeNode.expanded) { + if (container.isSlotNode && !treeNode.expanded) { // 未展开,直接定位到内部第一个节点 if (isSlotContainer) { detail.index = null; diff --git a/packages/plugin-outline-pane/src/controllers/tree-master.ts b/packages/plugin-outline-pane/src/controllers/tree-master.ts index 074ed3447..a6852803b 100644 --- a/packages/plugin-outline-pane/src/controllers/tree-master.ts +++ b/packages/plugin-outline-pane/src/controllers/tree-master.ts @@ -1,69 +1,141 @@ import { isLocationChildrenDetail } from '@alilc/lowcode-utils'; -import { IPublicModelPluginContext, IPublicTypeActiveTarget, IPublicModelNode } from '@alilc/lowcode-types'; +import { IPublicModelPluginContext, IPublicTypeActiveTarget, IPublicModelNode, IPublicTypeDisposable, IPublicEnumPluginRegisterLevel } from '@alilc/lowcode-types'; import TreeNode from './tree-node'; import { Tree } from './tree'; +import EventEmitter from 'events'; +import { enUS, zhCN } from '../locale'; +import { ReactNode } from 'react'; export interface ITreeBoard { readonly at: string | symbol; scrollToNode(treeNode: TreeNode, detail?: any): void; } +enum EVENT_NAMES { + pluginContextChanged = 'pluginContextChanged', +} + +export interface IOutlinePanelPluginContext extends IPublicModelPluginContext { + extraTitle?: string; + intlNode(id: string, params?: object): ReactNode; + intl(id: string, params?: object): string; + getLocale(): string; +} + export class TreeMaster { - readonly pluginContext: IPublicModelPluginContext; + pluginContext: IOutlinePanelPluginContext; private boards = new Set(); private treeMap = new Map(); - constructor(pluginContext: IPublicModelPluginContext) { - this.pluginContext = pluginContext; - let startTime: any; - const { event, project, canvas } = this.pluginContext; - canvas.dragon?.onDragstart(() => { - startTime = Date.now() / 1000; - // needs? - this.toVision(); - }); - canvas.activeTracker?.onChange((target: IPublicTypeActiveTarget) => { - const { node, detail } = target; - const tree = this.currentTree; - if (!tree/* || node.document !== tree.document */) { - return; - } - const treeNode = tree.getTreeNode(node); - if (detail && isLocationChildrenDetail(detail)) { - treeNode.expand(true); - } else { - treeNode.expandParents(); - } - this.boards.forEach((board) => { - board.scrollToNode(treeNode, detail); + private disposeEvents: (IPublicTypeDisposable | undefined)[] = []; + + event = new EventEmitter(); + + constructor(pluginContext: IPublicModelPluginContext, readonly options: { + extraTitle?: string; + }) { + this.setPluginContext(pluginContext); + const { workspace } = this.pluginContext; + this.initEvent(); + if (pluginContext.registerLevel === IPublicEnumPluginRegisterLevel.Workspace) { + workspace.onWindowRendererReady(() => { + this.setPluginContext(workspace.window?.currentEditorView); + let dispose: IPublicTypeDisposable | undefined; + const windowViewTypeChangeEvent = () => { + dispose = workspace.window?.onChangeViewType(() => { + this.setPluginContext(workspace.window?.currentEditorView); + }); + }; + + windowViewTypeChangeEvent(); + + workspace.onChangeActiveWindow(() => { + windowViewTypeChangeEvent(); + this.setPluginContext(workspace.window?.currentEditorView); + dispose && dispose(); + }); }); + } + } + + private setPluginContext(pluginContext: IPublicModelPluginContext | undefined) { + if (!pluginContext) { + return; + } + const { intl, intlNode, getLocale } = pluginContext.common.utils.createIntl({ + 'en-US': enUS, + 'zh-CN': zhCN, }); - canvas.dragon?.onDragend(() => { - const endTime: any = Date.now() / 1000; - const nodes = project.currentDocument?.selection?.getNodes(); - event.emit('outlinePane.dragend', { - selected: nodes - ?.map((n) => { - if (!n) { - return; - } - const npm = n?.componentMeta?.npm; - return ( - [npm?.package, npm?.componentName].filter((item) => !!item).join('-') || n?.componentMeta?.componentName - ); - }) - .join('&'), - time: (endTime - startTime).toFixed(2), - }); + let _pluginContext: IOutlinePanelPluginContext = Object.assign(pluginContext, { + intl, + intlNode, + getLocale, }); - project.onRemoveDocument((data: {id: string}) => { - const { id } = data; - this.treeMap.delete(id); + _pluginContext.extraTitle = this.options && this.options['extraTitle']; + this.pluginContext = _pluginContext; + this.disposeEvent(); + this.initEvent(); + this.emitPluginContextChange(); + } + + private disposeEvent() { + this.disposeEvents.forEach(d => { + d && d(); }); } + private initEvent() { + let startTime: any; + const { event, project, canvas } = this.pluginContext; + this.disposeEvents = [ + canvas.dragon?.onDragstart(() => { + startTime = Date.now() / 1000; + // needs? + this.toVision(); + }), + canvas.activeTracker?.onChange((target: IPublicTypeActiveTarget) => { + const { node, detail } = target; + const tree = this.currentTree; + if (!tree/* || node.document !== tree.document */) { + return; + } + const treeNode = tree.getTreeNode(node); + if (detail && isLocationChildrenDetail(detail)) { + treeNode.expand(true); + } else { + treeNode.expandParents(); + } + this.boards.forEach((board) => { + board.scrollToNode(treeNode, detail); + }); + }), + canvas.dragon?.onDragend(() => { + const endTime: any = Date.now() / 1000; + const nodes = project.currentDocument?.selection?.getNodes(); + event.emit('outlinePane.dragend', { + selected: nodes + ?.map((n) => { + if (!n) { + return; + } + const npm = n?.componentMeta?.npm; + return ( + [npm?.package, npm?.componentName].filter((item) => !!item).join('-') || n?.componentMeta?.componentName + ); + }) + .join('&'), + time: (endTime - startTime).toFixed(2), + }); + }), + project.onRemoveDocument((data: {id: string}) => { + const { id } = data; + this.treeMap.delete(id); + }), + ]; + } + private toVision() { const tree = this.currentTree; if (tree) { @@ -86,6 +158,14 @@ export class TreeMaster { // todo others purge } + onPluginContextChange(fn: () => void) { + this.event.on(EVENT_NAMES.pluginContextChanged, fn); + } + + emitPluginContextChange() { + this.event.emit(EVENT_NAMES.pluginContextChanged); + } + get currentTree(): Tree | null { const doc = this.pluginContext.project.getCurrentDocument(); if (doc) { @@ -93,7 +173,7 @@ export class TreeMaster { if (this.treeMap.has(id)) { return this.treeMap.get(id)!; } - const tree = new Tree(this.pluginContext); + const tree = new Tree(this); this.treeMap.set(id, tree); return tree; } diff --git a/packages/plugin-outline-pane/src/controllers/tree-node.ts b/packages/plugin-outline-pane/src/controllers/tree-node.ts index 62f373e2a..2a6bc0aca 100644 --- a/packages/plugin-outline-pane/src/controllers/tree-node.ts +++ b/packages/plugin-outline-pane/src/controllers/tree-node.ts @@ -2,12 +2,12 @@ import { IPublicTypeTitleContent, IPublicTypeLocationChildrenDetail, IPublicModelNode, - IPublicModelPluginContext, IPublicTypeDisposable, } from '@alilc/lowcode-types'; import { isI18nData, isLocationChildrenDetail } from '@alilc/lowcode-utils'; import EventEmitter from 'events'; import { Tree } from './tree'; +import { IOutlinePanelPluginContext } from './tree-master'; /** * 大纲树过滤结果 @@ -38,7 +38,7 @@ enum EVENT_NAMES { } export default class TreeNode { - readonly pluginContext: IPublicModelPluginContext; + readonly pluginContext: IOutlinePanelPluginContext; event = new EventEmitter(); private _node: IPublicModelNode; @@ -160,9 +160,9 @@ export default class TreeNode { return this._node; } - constructor(tree: Tree, node: IPublicModelNode, pluginContext: IPublicModelPluginContext) { + constructor(tree: Tree, node: IPublicModelNode) { this.tree = tree; - this.pluginContext = pluginContext; + this.pluginContext = tree.pluginContext; this._node = node; } diff --git a/packages/plugin-outline-pane/src/controllers/tree.ts b/packages/plugin-outline-pane/src/controllers/tree.ts index c0098794c..94cab7879 100644 --- a/packages/plugin-outline-pane/src/controllers/tree.ts +++ b/packages/plugin-outline-pane/src/controllers/tree.ts @@ -1,12 +1,13 @@ import TreeNode from './tree-node'; -import { IPublicModelNode, IPublicModelPluginContext, IPublicTypePropChangeOptions } from '@alilc/lowcode-types'; +import { IPublicModelNode, IPublicTypePropChangeOptions } from '@alilc/lowcode-types'; +import { IOutlinePanelPluginContext, TreeMaster } from './tree-master'; export class Tree { private treeNodesMap = new Map(); readonly id: string | undefined; - readonly pluginContext: IPublicModelPluginContext; + readonly pluginContext: IOutlinePanelPluginContext; get root(): TreeNode | null { if (this.pluginContext.project.currentDocument?.focusNode) { @@ -15,8 +16,11 @@ export class Tree { return null; } - constructor(pluginContext: IPublicModelPluginContext) { - this.pluginContext = pluginContext; + readonly treeMaster: TreeMaster; + + constructor(treeMaster: TreeMaster) { + this.treeMaster = treeMaster; + this.pluginContext = treeMaster.pluginContext; const doc = this.pluginContext.project.currentDocument; this.id = doc?.id; @@ -51,7 +55,7 @@ export class Tree { return tnode; } - const treeNode = new TreeNode(this, node, this.pluginContext); + const treeNode = new TreeNode(this, node); this.treeNodesMap.set(node.id, treeNode); return treeNode; } diff --git a/packages/plugin-outline-pane/src/index.tsx b/packages/plugin-outline-pane/src/index.tsx index 701e46540..1ea53b2f0 100644 --- a/packages/plugin-outline-pane/src/index.tsx +++ b/packages/plugin-outline-pane/src/index.tsx @@ -1,21 +1,13 @@ import { Pane } from './views/pane'; import { IconOutline } from './icons/outline'; import { IPublicModelPluginContext, IPublicModelDocumentModel } from '@alilc/lowcode-types'; -import { enUS, zhCN } from './locale'; import { MasterPaneName, BackupPaneName } from './helper/consts'; import { TreeMaster } from './controllers/tree-master'; import { PaneController } from './controllers/pane-controller'; +import { useState } from 'react'; export const OutlinePlugin = (ctx: IPublicModelPluginContext, options: any) => { - const { skeleton, config, common, event, canvas, project } = ctx; - const { intl, intlNode, getLocale } = common.utils.createIntl({ - 'en-US': enUS, - 'zh-CN': zhCN, - }); - ctx.intl = intl; - ctx.intlNode = intlNode; - ctx.getLocale = getLocale; - ctx.extraTitle = options && options['extraTitle']; + const { skeleton, config, canvas, project } = ctx; let isInFloatArea = true; const hasPreferenceForOutline = config.getPreference().contains('outline-pane-pinned-status-isFloat', 'skeleton'); @@ -26,8 +18,7 @@ export const OutlinePlugin = (ctx: IPublicModelPluginContext, options: any) => { masterPane: false, backupPane: false, }; - const treeMaster = new TreeMaster(ctx); - let masterPaneController: PaneController | null = null; + const treeMaster = new TreeMaster(ctx, options); let backupPaneController: PaneController | null = null; return { async init() { @@ -40,16 +31,20 @@ export const OutlinePlugin = (ctx: IPublicModelPluginContext, options: any) => { name: MasterPaneName, props: { icon: IconOutline, - description: intlNode('Outline Tree'), + description: treeMaster.pluginContext.intlNode('Outline Tree'), }, - content: (props: any) => { - masterPaneController = new PaneController(MasterPaneName, ctx, treeMaster); + content: function Context(props: any) { + const [masterPaneController, setMasterPaneController] = useState(new PaneController(MasterPaneName, treeMaster)); + treeMaster.onPluginContextChange(() => { + setMasterPaneController(new PaneController(MasterPaneName, treeMaster)); + }); + return ( ); @@ -73,10 +68,9 @@ export const OutlinePlugin = (ctx: IPublicModelPluginContext, options: any) => { hiddenWhenInit: true, }, content: (props: any) => { - backupPaneController = new PaneController(BackupPaneName, ctx, treeMaster); + backupPaneController = new PaneController(BackupPaneName, treeMaster); return ( + {/* @ts-ignore */} + {/* @ts-ignore */} )} > + {/* @ts-ignore */} - {this.props.pluginContext.intlNode('Check All')} + {this.props.tree.pluginContext.intlNode('Check All')} + {/* @ts-ignore */} + {/* @ts-ignore */} - {this.props.pluginContext.intlNode(op.label)} + {this.props.tree.pluginContext.intlNode(op.label)} ))} diff --git a/packages/plugin-outline-pane/src/views/pane.tsx b/packages/plugin-outline-pane/src/views/pane.tsx index adaada786..8805cfffa 100644 --- a/packages/plugin-outline-pane/src/views/pane.tsx +++ b/packages/plugin-outline-pane/src/views/pane.tsx @@ -1,47 +1,71 @@ import React, { PureComponent } from 'react'; +import { Loading } from '@alifd/next'; import { PaneController } from '../controllers/pane-controller'; import TreeView from './tree'; import './style.less'; -import { IPublicModelPluginContext } from '@alilc/lowcode-types'; import Filter from './filter'; import { TreeMaster } from '../controllers/tree-master'; +import { Tree } from '../controllers/tree'; +import { IPublicTypeDisposable } from '@alilc/lowcode-types'; export class Pane extends PureComponent<{ config: any; - pluginContext: IPublicModelPluginContext; treeMaster: TreeMaster; controller: PaneController; +}, { + tree: Tree | null; }> { private controller; - private treeMaster: TreeMaster; + + private dispose: IPublicTypeDisposable; constructor(props: any) { super(props); const { controller, treeMaster } = props; - this.treeMaster = treeMaster; this.controller = controller; + this.state = { + tree: treeMaster.currentTree, + }; } componentWillUnmount() { this.controller.purge(); + this.dispose && this.dispose(); + } + + componentDidMount() { + this.dispose = this.props.treeMaster.pluginContext.project.onSimulatorRendererReady(() => { + this.setState({ + tree: this.props.treeMaster.currentTree, + }); + }); } render() { - const tree = this.treeMaster.currentTree; + const tree = this.state.tree; if (!tree) { return (
-

{this.props.pluginContext.intl('Initializing')}

+

+ {/* @ts-ignore */} + +

); } return (
- +
this.controller.mount(shell)} className="lc-outline-tree-container"> - +
); diff --git a/packages/plugin-outline-pane/src/views/tree-branches.tsx b/packages/plugin-outline-pane/src/views/tree-branches.tsx index 210fe0af8..2e281071b 100644 --- a/packages/plugin-outline-pane/src/views/tree-branches.tsx +++ b/packages/plugin-outline-pane/src/views/tree-branches.tsx @@ -2,12 +2,11 @@ import { PureComponent } from 'react'; import classNames from 'classnames'; import TreeNode from '../controllers/tree-node'; import TreeNodeView from './tree-node'; -import { IPublicModelPluginContext, IPublicModelExclusiveGroup, IPublicTypeDisposable, IPublicTypeLocationChildrenDetail } from '@alilc/lowcode-types'; +import { IPublicModelExclusiveGroup, IPublicTypeDisposable, IPublicTypeLocationChildrenDetail } from '@alilc/lowcode-types'; export default class TreeBranches extends PureComponent<{ treeNode: TreeNode; isModal?: boolean; - pluginContext: IPublicModelPluginContext; expanded: boolean; treeChildren: TreeNode[] | null; }> { @@ -51,12 +50,11 @@ export default class TreeBranches extends PureComponent<{ return (
{ - !isModal && + !isModal && }
@@ -73,7 +71,6 @@ interface ITreeNodeChildrenState { class TreeNodeChildren extends PureComponent<{ treeNode: TreeNode; isModal?: boolean; - pluginContext: IPublicModelPluginContext; treeChildren: TreeNode[] | null; }, ITreeNodeChildrenState> { state: ITreeNodeChildrenState = { @@ -84,8 +81,8 @@ class TreeNodeChildren extends PureComponent<{ }; offLocationChanged: IPublicTypeDisposable | undefined; componentDidMount() { - const { treeNode, pluginContext } = this.props; - const { project } = pluginContext; + const { treeNode } = this.props; + const { project } = treeNode.pluginContext; const { filterWorking, matchSelf, keywords } = treeNode.filterReult; const { dropDetail } = treeNode; this.setState({ @@ -122,13 +119,14 @@ class TreeNodeChildren extends PureComponent<{ let groupContents: any[] = []; let currentGrp: IPublicModelExclusiveGroup; const { filterWorking, matchSelf, keywords } = this.state; - const Title = this.props.pluginContext.common.editorCabin.Title; + const Title = this.props.treeNode.pluginContext.common.editorCabin.Title; const endGroup = () => { if (groupContents.length > 0) { children.push(
+ {/* @ts-ignore */} ); + groupContents.push(<TreeNodeView key={child.id} treeNode={child} isModal={isModal} />); } else { if (index === dropIndex) { children.push(insertion); } - children.push(<TreeNodeView key={child.id} treeNode={child} isModal={isModal} pluginContext={this.props.pluginContext} />); + children.push(<TreeNodeView key={child.id} treeNode={child} isModal={isModal} />); } }); endGroup(); @@ -191,14 +189,13 @@ class TreeNodeChildren extends PureComponent<{ class TreeNodeSlots extends PureComponent<{ treeNode: TreeNode; - pluginContext: IPublicModelPluginContext; }> { render() { const { treeNode } = this.props; if (!treeNode.hasSlots()) { return null; } - const Title = this.props.pluginContext.common.editorCabin.Title; + const Title = this.props.treeNode.pluginContext.common.editorCabin.Title; return ( <div className={classNames('tree-node-slots', { @@ -207,10 +204,11 @@ class TreeNodeSlots extends PureComponent<{ data-id={treeNode.id} > <div className="tree-node-slots-title"> - <Title title={{ type: 'i18n', intl: this.props.pluginContext.intlNode('Slots') }} /> + {/* @ts-ignore */} + <Title title={{ type: 'i18n', intl: this.props.treeNode.pluginContext.intlNode('Slots') }} /> </div> {treeNode.slots.map(tnode => ( - <TreeNodeView key={tnode.id} treeNode={tnode} pluginContext={this.props.pluginContext} /> + <TreeNodeView key={tnode.id} treeNode={tnode} /> ))} </div> ); diff --git a/packages/plugin-outline-pane/src/views/tree-node.tsx b/packages/plugin-outline-pane/src/views/tree-node.tsx index 331397a0b..882fe15b1 100644 --- a/packages/plugin-outline-pane/src/views/tree-node.tsx +++ b/packages/plugin-outline-pane/src/views/tree-node.tsx @@ -4,22 +4,24 @@ import TreeNode from '../controllers/tree-node'; import TreeTitle from './tree-title'; import TreeBranches from './tree-branches'; import { IconEyeClose } from '../icons/eye-close'; -import { IPublicModelPluginContext, IPublicModelModalNodesManager, IPublicTypeDisposable } from '@alilc/lowcode-types'; +import { IPublicModelModalNodesManager, IPublicTypeDisposable } from '@alilc/lowcode-types'; +import { IOutlinePanelPluginContext } from '../controllers/tree-master'; class ModalTreeNodeView extends PureComponent<{ treeNode: TreeNode; - pluginContext: IPublicModelPluginContext; }, { treeChildren: TreeNode[] | null; }> { private modalNodesManager: IPublicModelModalNodesManager | undefined | null; - readonly pluginContext: IPublicModelPluginContext; + readonly pluginContext: IOutlinePanelPluginContext; - constructor(props: any) { + constructor(props: { + treeNode: TreeNode; + }) { super(props); // 模态管理对象 - this.pluginContext = props.pluginContext; + this.pluginContext = props.treeNode.pluginContext; const { project } = this.pluginContext; this.modalNodesManager = project.currentDocument?.modalNodesManager; this.state = { @@ -72,7 +74,6 @@ class ModalTreeNodeView extends PureComponent<{ treeChildren={this.state.treeChildren} expanded={expanded} isModal - pluginContext={this.pluginContext} /> </div> </div> @@ -83,7 +84,6 @@ class ModalTreeNodeView extends PureComponent<{ export default class TreeNodeView extends PureComponent<{ treeNode: TreeNode; isModal?: boolean; - pluginContext: IPublicModelPluginContext; isRootNode?: boolean; }> { state: { @@ -134,8 +134,8 @@ export default class TreeNodeView extends PureComponent<{ } componentDidMount() { - const { treeNode, pluginContext } = this.props; - const { project } = pluginContext; + const { treeNode } = this.props; + const { project } = treeNode.pluginContext; const doc = project.currentDocument; @@ -178,14 +178,14 @@ export default class TreeNodeView extends PureComponent<{ } shouldShowModalTreeNode(): boolean { - const { treeNode, isRootNode, pluginContext } = this.props; + const { treeNode, isRootNode } = this.props; if (!isRootNode) { // 只在 当前树 的根节点展示模态节点 return false; } // 当指定了新的根节点时,要从原始的根节点去获取模态节点 - const { project } = pluginContext; + const { project } = treeNode.pluginContext; const rootNode = project.currentDocument?.root; const rootTreeNode = treeNode.tree.getTreeNode(rootNode!); const modalNodes = rootTreeNode.children?.filter((item) => { @@ -234,19 +234,16 @@ export default class TreeNodeView extends PureComponent<{ hidden={this.state.hidden} locked={this.state.locked} expandable={this.state.expandable} - pluginContext={this.props.pluginContext} /> {shouldShowModalTreeNode && <ModalTreeNodeView treeNode={treeNode} - pluginContext={this.props.pluginContext} /> } <TreeBranches treeNode={treeNode} isModal={false} expanded={this.state.expanded} - pluginContext={this.props.pluginContext} treeChildren={this.state.treeChildren} /> </div> diff --git a/packages/plugin-outline-pane/src/views/tree-title.tsx b/packages/plugin-outline-pane/src/views/tree-title.tsx index 6e1b14a46..96a3dfa7b 100644 --- a/packages/plugin-outline-pane/src/views/tree-title.tsx +++ b/packages/plugin-outline-pane/src/views/tree-title.tsx @@ -1,7 +1,7 @@ import { KeyboardEvent, FocusEvent, Fragment, PureComponent } from 'react'; import classNames from 'classnames'; import { createIcon } from '@alilc/lowcode-utils'; -import { IPublicModelPluginContext, IPublicApiEvent } from '@alilc/lowcode-types'; +import { IPublicApiEvent } from '@alilc/lowcode-types'; import TreeNode from '../controllers/tree-node'; import { IconLock, IconUnlock, IconArrowRight, IconEyeClose, IconEye, IconCond, IconLoop, IconRadioActive, IconRadio, IconSetting } from '../icons'; @@ -23,7 +23,6 @@ export default class TreeTitle extends PureComponent<{ hidden: boolean; locked: boolean; expandable: boolean; - pluginContext: IPublicModelPluginContext; }> { state: { editing: boolean; @@ -53,7 +52,7 @@ export default class TreeTitle extends PureComponent<{ const { treeNode } = this.props; const value = (e.target as HTMLInputElement).value || ''; treeNode.setTitleLabel(value); - emitOutlineEvent(this.props.pluginContext.event, 'rename', treeNode, { value }); + emitOutlineEvent(this.props.treeNode.pluginContext.event, 'rename', treeNode, { value }); this.cancelEdit(); }; @@ -90,7 +89,8 @@ export default class TreeTitle extends PureComponent<{ } render() { - const { treeNode, isModal, pluginContext } = this.props; + const { treeNode, isModal } = this.props; + const { pluginContext } = treeNode; const { editing } = this.state; const isCNode = !treeNode.isRoot(); const { node } = treeNode; @@ -153,7 +153,7 @@ export default class TreeTitle extends PureComponent<{ <IconRadio className="tree-node-modal-radio" /> </div> )} - {isCNode && <ExpandBtn expandable={this.props.expandable} expanded={this.props.expanded} treeNode={treeNode} pluginContext={this.props.pluginContext} />} + {isCNode && <ExpandBtn expandable={this.props.expandable} expanded={this.props.expanded} treeNode={treeNode} />} <div className="tree-node-icon">{createIcon(treeNode.icon)}</div> <div className="tree-node-title-label"> {editing ? ( @@ -166,6 +166,7 @@ export default class TreeTitle extends PureComponent<{ /> ) : ( <Fragment> + {/* @ts-ignore */} <Title title={this.state.title} match={filterWorking && matchSelf} @@ -175,6 +176,7 @@ export default class TreeTitle extends PureComponent<{ {node.slotFor && ( <a className="tree-node-tag slot"> {/* todo: click redirect to prop */} + {/* @ts-ignore */} <Tip>{intlNode('Slot for {prop}', { prop: node.slotFor.key })}</Tip> </a> )} @@ -182,6 +184,7 @@ export default class TreeTitle extends PureComponent<{ <a className="tree-node-tag loop"> {/* todo: click todo something */} <IconLoop /> + {/* @ts-ignore */} <Tip>{intlNode('Loop')}</Tip> </a> )} @@ -189,15 +192,16 @@ export default class TreeTitle extends PureComponent<{ <a className="tree-node-tag cond"> {/* todo: click todo something */} <IconCond /> + {/* @ts-ignore */} <Tip>{intlNode('Conditional')}</Tip> </a> )} </Fragment> )} </div> - {shouldShowHideBtn && <HideBtn hidden={this.props.hidden} treeNode={treeNode} pluginContext={this.props.pluginContext} />} - {shouldShowLockBtn && <LockBtn locked={this.props.locked} treeNode={treeNode} pluginContext={this.props.pluginContext} />} - {shouldEditBtn && <RenameBtn treeNode={treeNode} pluginContext={this.props.pluginContext} onClick={this.enableEdit} /> } + {shouldShowHideBtn && <HideBtn hidden={this.props.hidden} treeNode={treeNode} />} + {shouldShowLockBtn && <LockBtn locked={this.props.locked} treeNode={treeNode} />} + {shouldEditBtn && <RenameBtn treeNode={treeNode} onClick={this.enableEdit} /> } </div> ); @@ -206,11 +210,10 @@ export default class TreeTitle extends PureComponent<{ class RenameBtn extends PureComponent<{ treeNode: TreeNode; - pluginContext: IPublicModelPluginContext; onClick: (e: any) => void; }> { render() { - const { intl, common } = this.props.pluginContext; + const { intl, common } = this.props.treeNode.pluginContext; const Tip = common.editorCabin.Tip; return ( <div @@ -218,6 +221,7 @@ class RenameBtn extends PureComponent<{ onClick={this.props.onClick} > <IconSetting /> + {/* @ts-ignore */} <Tip>{intl('Rename')}</Tip> </div> ); @@ -226,12 +230,11 @@ class RenameBtn extends PureComponent<{ class LockBtn extends PureComponent<{ treeNode: TreeNode; - pluginContext: IPublicModelPluginContext; locked: boolean; }> { render() { const { treeNode, locked } = this.props; - const { intl, common } = this.props.pluginContext; + const { intl, common } = this.props.treeNode.pluginContext; const Tip = common.editorCabin.Tip; return ( <div @@ -242,6 +245,7 @@ class LockBtn extends PureComponent<{ }} > {locked ? <IconUnlock /> : <IconLock /> } + {/* @ts-ignore */} <Tip>{locked ? intl('Unlock') : intl('Lock')}</Tip> </div> ); @@ -251,24 +255,24 @@ class LockBtn extends PureComponent<{ class HideBtn extends PureComponent<{ treeNode: TreeNode; hidden: boolean; - pluginContext: IPublicModelPluginContext; }, { hidden: boolean; }> { render() { const { treeNode, hidden } = this.props; - const { intl, common } = this.props.pluginContext; + const { intl, common } = treeNode.pluginContext; const Tip = common.editorCabin.Tip; return ( <div className="tree-node-hide-btn" onClick={(e) => { e.stopPropagation(); - emitOutlineEvent(this.props.pluginContext.event, hidden ? 'show' : 'hide', treeNode); + emitOutlineEvent(treeNode.pluginContext.event, hidden ? 'show' : 'hide', treeNode); treeNode.setHidden(!hidden); }} > {hidden ? <IconEye /> : <IconEyeClose />} + {/* @ts-ignore */} <Tip>{hidden ? intl('Show') : intl('Hide')}</Tip> </div> ); @@ -277,7 +281,6 @@ class HideBtn extends PureComponent<{ class ExpandBtn extends PureComponent<{ treeNode: TreeNode; - pluginContext: IPublicModelPluginContext; expanded: boolean; expandable: boolean; }> { @@ -294,7 +297,7 @@ class ExpandBtn extends PureComponent<{ if (expanded) { e.stopPropagation(); } - emitOutlineEvent(this.props.pluginContext.event, expanded ? 'collapse' : 'expand', treeNode); + emitOutlineEvent(treeNode.pluginContext.event, expanded ? 'collapse' : 'expand', treeNode); treeNode.setExpanded(!expanded); }} > diff --git a/packages/plugin-outline-pane/src/views/tree.tsx b/packages/plugin-outline-pane/src/views/tree.tsx index 930c65cce..4bc502886 100644 --- a/packages/plugin-outline-pane/src/views/tree.tsx +++ b/packages/plugin-outline-pane/src/views/tree.tsx @@ -2,7 +2,7 @@ import { MouseEvent as ReactMouseEvent, PureComponent } from 'react'; import { isFormEvent, canClickNode, isShaken } from '@alilc/lowcode-utils'; import { Tree } from '../controllers/tree'; import TreeNodeView from './tree-node'; -import { IPublicEnumDragObjectType, IPublicModelPluginContext, IPublicModelNode } from '@alilc/lowcode-types'; +import { IPublicEnumDragObjectType, IPublicModelNode } from '@alilc/lowcode-types'; import TreeNode from '../controllers/tree-node'; function getTreeNodeIdByEvent(e: ReactMouseEvent, stop: Element): null | string { @@ -20,12 +20,21 @@ function getTreeNodeIdByEvent(e: ReactMouseEvent, stop: Element): null | string export default class TreeView extends PureComponent<{ tree: Tree; - pluginContext: IPublicModelPluginContext; }> { private shell: HTMLDivElement | null = null; + private ignoreUpSelected = false; + + private boostEvent?: MouseEvent; + + state: { + root: TreeNode | null; + } = { + root: null, + }; + private hover(e: ReactMouseEvent) { - const { project } = this.props.pluginContext; + const { project } = this.props.tree.pluginContext; const detecting = project.currentDocument?.detecting; if (detecting?.enable) { return; @@ -54,7 +63,7 @@ export default class TreeView extends PureComponent<{ return; } - const { project, event, canvas } = this.props.pluginContext; + const { project, event, canvas } = this.props.tree.pluginContext; const doc = project.currentDocument; const selection = doc?.selection; const focusNode = doc?.focusNode; @@ -109,10 +118,6 @@ export default class TreeView extends PureComponent<{ return tree.getTreeNodeById(id); } - private ignoreUpSelected = false; - - private boostEvent?: MouseEvent; - private onMouseDown = (e: ReactMouseEvent) => { if (isFormEvent(e.nativeEvent)) { return; @@ -127,7 +132,7 @@ export default class TreeView extends PureComponent<{ if (!canClickNode(node, e)) { return; } - const { project, canvas } = this.props.pluginContext; + const { project, canvas } = this.props.tree.pluginContext; const selection = project.currentDocument?.selection; const focusNode = project.currentDocument?.focusNode; @@ -166,22 +171,16 @@ export default class TreeView extends PureComponent<{ }; private onMouseLeave = () => { - const { pluginContext } = this.props; + const { pluginContext } = this.props.tree; const { project } = pluginContext; const doc = project.currentDocument; doc?.detecting.leave(); }; - state: { - root: TreeNode | null - } = { - root: null, - }; - componentDidMount() { - const { tree, pluginContext } = this.props; + const { tree } = this.props; const { root } = tree; - const { project } = pluginContext; + const { project } = tree.pluginContext; this.setState({ root }); const doc = project.currentDocument; doc?.onFocusNodeChanged(() => { @@ -208,7 +207,6 @@ export default class TreeView extends PureComponent<{ <TreeNodeView key={this.state.root?.id} treeNode={this.state.root} - pluginContext={this.props.pluginContext} isRootNode /> </div> diff --git a/packages/shell/src/model/editor-view.ts b/packages/shell/src/model/editor-view.ts new file mode 100644 index 000000000..31027a5de --- /dev/null +++ b/packages/shell/src/model/editor-view.ts @@ -0,0 +1,27 @@ +import { editorViewSymbol, pluginContextSymbol } from '../symbols'; +import { IPublicModelPluginContext } from '@alilc/lowcode-types'; +import { IViewContext } from '@alilc/lowcode-workspace'; + +export class EditorView { + [editorViewSymbol]: IViewContext; + + [pluginContextSymbol]: IPublicModelPluginContext; + + constructor(editorView: IViewContext) { + this[editorViewSymbol] = editorView; + this[pluginContextSymbol] = this[editorViewSymbol].innerPlugins._getLowCodePluginContext({ + pluginName: '', + }); + } + + toProxy() { + return new Proxy(this, { + get(target, prop, receiver) { + if ((target[pluginContextSymbol] as any)[prop as string]) { + return Reflect.get(target[pluginContextSymbol], prop, receiver); + } + return Reflect.get(target, prop, receiver); + }, + }); + } +} diff --git a/packages/shell/src/model/index.ts b/packages/shell/src/model/index.ts index cd481643e..8b668c947 100644 --- a/packages/shell/src/model/index.ts +++ b/packages/shell/src/model/index.ts @@ -19,3 +19,4 @@ export * from './active-tracker'; export * from './plugin-instance'; export * from './window'; export * from './clipboard'; +export * from './editor-view'; diff --git a/packages/shell/src/model/window.ts b/packages/shell/src/model/window.ts index 23bc5c06d..6af2534dd 100644 --- a/packages/shell/src/model/window.ts +++ b/packages/shell/src/model/window.ts @@ -2,6 +2,7 @@ import { windowSymbol } from '../symbols'; import { IPublicModelResource, IPublicModelWindow, IPublicTypeDisposable } from '@alilc/lowcode-types'; import { IEditorWindow } from '@alilc/lowcode-workspace'; import { Resource as ShellResource } from './resource'; +import { EditorView } from './editor-view'; export class Window implements IPublicModelWindow { private readonly [windowSymbol]: IEditorWindow; @@ -42,7 +43,11 @@ export class Window implements IPublicModelWindow { return await this[windowSymbol].save(); } - get plugins() { - return this[windowSymbol].plugins; + get currentEditorView() { + return new EditorView(this[windowSymbol].editorView).toProxy() as any; + } + + get editorViews() { + return Array.from(this[windowSymbol].editorViews.values()).map(d => new EditorView(d).toProxy() as any); } } diff --git a/packages/shell/src/symbols.ts b/packages/shell/src/symbols.ts index 4ba6ff236..48d6a9656 100644 --- a/packages/shell/src/symbols.ts +++ b/packages/shell/src/symbols.ts @@ -34,3 +34,5 @@ export const resourceSymbol = Symbol('resource'); export const clipboardSymbol = Symbol('clipboard'); export const configSymbol = Symbol('configSymbol'); export const conditionGroupSymbol = Symbol('conditionGroup'); +export const editorViewSymbol = Symbol('editorView'); +export const pluginContextSymbol = Symbol('pluginContext'); \ No newline at end of file diff --git a/packages/types/src/shell/enum/index.ts b/packages/types/src/shell/enum/index.ts index 506055825..f3d558011 100644 --- a/packages/types/src/shell/enum/index.ts +++ b/packages/types/src/shell/enum/index.ts @@ -2,4 +2,5 @@ export * from './event-names'; export * from './transition-type'; export * from './transform-stage'; export * from './drag-object-type'; -export * from './prop-value-changed-type'; \ No newline at end of file +export * from './prop-value-changed-type'; +export * from './plugin-register-level'; \ No newline at end of file diff --git a/packages/types/src/shell/enum/plugin-register-level.ts b/packages/types/src/shell/enum/plugin-register-level.ts new file mode 100644 index 000000000..a0d9b746b --- /dev/null +++ b/packages/types/src/shell/enum/plugin-register-level.ts @@ -0,0 +1,6 @@ +export enum IPublicEnumPluginRegisterLevel { + Default = 'default', + Workspace = 'workspace', + Resource = 'resource', + EditorView = 'editorView', +} \ No newline at end of file diff --git a/packages/types/src/shell/model/dragon.ts b/packages/types/src/shell/model/dragon.ts index 662eb6a00..917149faf 100644 --- a/packages/types/src/shell/model/dragon.ts +++ b/packages/types/src/shell/model/dragon.ts @@ -1,5 +1,5 @@ /* eslint-disable max-len */ -import { IPublicTypeDragNodeDataObject, IPublicTypeDragObject } from '../type'; +import { IPublicTypeDisposable, IPublicTypeDragNodeDataObject, IPublicTypeDragObject } from '../type'; import { IPublicModelDragObject, IPublicModelLocateEvent, IPublicModelNode } from './'; export interface IPublicModelDragon< @@ -19,7 +19,7 @@ export interface IPublicModelDragon< * @param func * @returns */ - onDragstart(func: (e: LocateEvent) => any): () => void; + onDragstart(func: (e: LocateEvent) => any): IPublicTypeDisposable; /** * 绑定 drag 事件 @@ -27,7 +27,7 @@ export interface IPublicModelDragon< * @param func * @returns */ - onDrag(func: (e: LocateEvent) => any): () => void; + onDrag(func: (e: LocateEvent) => any): IPublicTypeDisposable; /** * 绑定 dragend 事件 @@ -35,7 +35,7 @@ export interface IPublicModelDragon< * @param func * @returns */ - onDragend(func: (o: { dragObject: IPublicModelDragObject; copy?: boolean }) => any): () => void; + onDragend(func: (o: { dragObject: IPublicModelDragObject; copy?: boolean }) => any): IPublicTypeDisposable; /** * 设置拖拽监听的区域 shell,以及自定义拖拽转换函数 boost diff --git a/packages/types/src/shell/model/editor-view.ts b/packages/types/src/shell/model/editor-view.ts new file mode 100644 index 000000000..793417845 --- /dev/null +++ b/packages/types/src/shell/model/editor-view.ts @@ -0,0 +1,3 @@ +import { IPublicModelPluginContext } from './plugin-context'; + +export interface IPublicModelEditorView extends IPublicModelPluginContext {} \ No newline at end of file diff --git a/packages/types/src/shell/model/index.ts b/packages/types/src/shell/model/index.ts index b62fb76b9..e310128ca 100644 --- a/packages/types/src/shell/model/index.ts +++ b/packages/types/src/shell/model/index.ts @@ -30,3 +30,4 @@ export * from './sensor'; export * from './resource'; export * from './clipboard'; export * from './setting-field'; +export * from './editor-view'; diff --git a/packages/types/src/shell/model/plugin-context.ts b/packages/types/src/shell/model/plugin-context.ts index 5d97b5472..e670e54ea 100644 --- a/packages/types/src/shell/model/plugin-context.ts +++ b/packages/types/src/shell/model/plugin-context.ts @@ -12,18 +12,11 @@ import { IPublicApiPlugins, IPublicApiWorkspace, } from '../api'; +import { IPublicEnumPluginRegisterLevel } from '../enum'; import { IPublicModelEngineConfig } from './'; export interface IPublicModelPluginContext { - /** - * 对于插件开发者来说,可以在 context 挂载自定义的内容,作为插件内全局上下文使用 - * - * for plugin developers, costom properties can be add to plugin context - * from inside plugin for convenience. - */ - [key: string]: any; - /** * 可通过该对象读取插件初始化配置 * by using this, init options can be accessed from inside plugin @@ -108,6 +101,12 @@ export interface IPublicModelPluginContext { * @tutorial https://lowcode-engine.cn/site/docs/api/workspace */ get workspace(): IPublicApiWorkspace; + + /** + * 插件注册层级 + * @since v1.1.7 + */ + get registerLevel(): IPublicEnumPluginRegisterLevel; } /** diff --git a/packages/types/src/shell/model/window.ts b/packages/types/src/shell/model/window.ts index bb27ce317..5f77b0cbf 100644 --- a/packages/types/src/shell/model/window.ts +++ b/packages/types/src/shell/model/window.ts @@ -1,6 +1,7 @@ import { ReactElement } from 'react'; import { IPublicTypeDisposable, IPublicTypeNodeSchema } from '../type'; import { IPublicModelResource } from './resource'; +import { IPublicModelEditorView } from './editor-view'; export interface IPublicModelWindow< Resource = IPublicModelResource @@ -18,6 +19,18 @@ export interface IPublicModelWindow< /** 窗口资源类型 */ resource?: Resource; + /** + * 窗口当前视图 + * @since v1.1.7 + */ + currentEditorView: IPublicModelEditorView; + + /** + * 窗口全部视图实例 + * @since v1.1.7 + */ + editorViews: IPublicModelEditorView[]; + /** 当前窗口导入 schema */ importSchema(schema: IPublicTypeNodeSchema): void; diff --git a/packages/workspace/src/context/base-context.ts b/packages/workspace/src/context/base-context.ts index 57a38712b..b12a78183 100644 --- a/packages/workspace/src/context/base-context.ts +++ b/packages/workspace/src/context/base-context.ts @@ -44,6 +44,7 @@ import { IPublicApiProject, IPublicApiSetters, IPublicApiSkeleton, + IPublicEnumPluginRegisterLevel, IPublicModelPluginContext, IPublicTypePluginMeta, } from '@alilc/lowcode-types'; @@ -100,7 +101,7 @@ export class BasicContext implements IBasicContext { preference: IPluginPreferenceMananger; workspace: IWorkspace; - constructor(innerWorkspace: IWorkspace, viewName: string, public editorWindow?: IEditorWindow) { + constructor(innerWorkspace: IWorkspace, viewName: string, registerLevel: IPublicEnumPluginRegisterLevel, public editorWindow?: IEditorWindow) { const editor = new Editor(viewName, true); const innerSkeleton = new InnerSkeleton(editor, viewName); @@ -168,6 +169,7 @@ export class BasicContext implements IBasicContext { if (editorWindow) { context.editorWindow = new Window(editorWindow); } + context.registerLevel = registerLevel; }, }; diff --git a/packages/workspace/src/context/view-context.ts b/packages/workspace/src/context/view-context.ts index 393989850..7dfc66393 100644 --- a/packages/workspace/src/context/view-context.ts +++ b/packages/workspace/src/context/view-context.ts @@ -1,12 +1,16 @@ import { computed, makeObservable, obx } from '@alilc/lowcode-editor-core'; -import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types'; +import { IPublicEditorViewConfig, IPublicEnumPluginRegisterLevel, IPublicTypeEditorView } from '@alilc/lowcode-types'; import { flow } from 'mobx'; import { IWorkspace } from '../workspace'; -import { BasicContext } from './base-context'; +import { BasicContext, IBasicContext } from './base-context'; import { IEditorWindow } from '../window'; import { getWebviewPlugin } from '../inner-plugins/webview'; -export class Context extends BasicContext { +export interface IViewContext extends IBasicContext { + +} + +export class Context extends BasicContext implements IViewContext { viewName = 'editor-view'; instance: IPublicEditorViewConfig; @@ -30,7 +34,7 @@ export class Context extends BasicContext { }); constructor(public workspace: IWorkspace, public editorWindow: IEditorWindow, public editorView: IPublicTypeEditorView, options: Object | undefined) { - super(workspace, editorView.viewName, editorWindow); + super(workspace, editorView.viewName, IPublicEnumPluginRegisterLevel.EditorView, editorWindow); this.viewType = editorView.viewType || 'editor'; this.viewName = editorView.viewName; this.instance = editorView(this.innerPlugins._getLowCodePluginContext({ diff --git a/packages/workspace/src/index.ts b/packages/workspace/src/index.ts index 1f3b77a7a..6c437fad0 100644 --- a/packages/workspace/src/index.ts +++ b/packages/workspace/src/index.ts @@ -4,3 +4,4 @@ export * from './window'; export * from './layouts/workbench'; export { Resource } from './resource'; export type { IResource } from './resource'; +export type { IViewContext } from './context/view-context'; diff --git a/packages/workspace/src/resource.ts b/packages/workspace/src/resource.ts index 222cb1162..e51993c81 100644 --- a/packages/workspace/src/resource.ts +++ b/packages/workspace/src/resource.ts @@ -1,5 +1,5 @@ import { ISkeleton } from '@alilc/lowcode-editor-skeleton'; -import { IPublicTypeEditorView, IPublicResourceData, IPublicResourceTypeConfig, IBaseModelResource } from '@alilc/lowcode-types'; +import { IPublicTypeEditorView, IPublicResourceData, IPublicResourceTypeConfig, IBaseModelResource, IPublicEnumPluginRegisterLevel } from '@alilc/lowcode-types'; import { Logger } from '@alilc/lowcode-utils'; import { BasicContext, IBasicContext } from './context/base-context'; import { ResourceType, IResourceType } from './resource-type'; @@ -75,7 +75,7 @@ export class Resource implements IResource { } constructor(readonly resourceData: IPublicResourceData, readonly resourceType: IResourceType, readonly workspace: IWorkspace) { - this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`); + this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`, IPublicEnumPluginRegisterLevel.Resource); this.resourceTypeInstance = resourceType.resourceTypeModel(this.context.innerPlugins._getLowCodePluginContext({ pluginName: '', }), this.options); diff --git a/packages/workspace/src/window.ts b/packages/workspace/src/window.ts index 37a1622c0..92b707851 100644 --- a/packages/workspace/src/window.ts +++ b/packages/workspace/src/window.ts @@ -1,6 +1,6 @@ import { uniqueId } from '@alilc/lowcode-utils'; import { createModuleEventBus, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core'; -import { Context } from './context/view-context'; +import { Context, IViewContext } from './context/view-context'; import { IWorkspace } from './workspace'; import { IResource } from './resource'; import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable'; @@ -13,10 +13,12 @@ interface IWindowCOnfig { sleep?: boolean; } -export interface IEditorWindow extends Omit<IPublicModelWindow<IResource>, 'changeViewType'> { +export interface IEditorWindow extends Omit<IPublicModelWindow<IResource>, 'changeViewType' | 'currentEditorView' | 'editorViews'> { readonly resource: IResource; - editorViews: Map<string, Context>; + editorViews: Map<string, IViewContext>; + + editorView: IViewContext; changeViewType: (name: string, ignoreEmit?: boolean) => void; @@ -71,6 +73,9 @@ export class EditorWindow implements IEditorWindow { async save() { const value: any = {}; const editorViews = this.resource.editorViews; + if (!editorViews) { + return; + } for (let i = 0; i < editorViews.length; i++) { const name = editorViews[i].viewName; const saveResult = await this.editorViews.get(name)?.save(); diff --git a/packages/workspace/src/workspace.ts b/packages/workspace/src/workspace.ts index ea19ea0c0..37341cdc3 100644 --- a/packages/workspace/src/workspace.ts +++ b/packages/workspace/src/workspace.ts @@ -1,6 +1,6 @@ import { IDesigner, ILowCodePluginManager, LowCodePluginManager } from '@alilc/lowcode-designer'; import { createModuleEventBus, Editor, IEditor, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core'; -import { IPublicApiPlugins, IPublicApiWorkspace, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType, IShellModelFactory } from '@alilc/lowcode-types'; +import { IPublicApiPlugins, IPublicApiWorkspace, IPublicEnumPluginRegisterLevel, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType, IShellModelFactory } from '@alilc/lowcode-types'; import { BasicContext } from './context/base-context'; import { EditorWindow } from './window'; import type { IEditorWindow } from './window'; @@ -94,7 +94,7 @@ export class Workspace implements IWorkspace { readonly registryInnerPlugin: (designer: IDesigner, editor: IEditor, plugins: IPublicApiPlugins) => Promise<IPublicTypeDisposable>, readonly shellModelFactory: any, ) { - this.context = new BasicContext(this, ''); + this.context = new BasicContext(this, '', IPublicEnumPluginRegisterLevel.Workspace); makeObservable(this); }