diff --git a/docs/docs/api/model/node-children.md b/docs/docs/api/model/node-children.md index 219e6bbc1..5507fcbfb 100644 --- a/docs/docs/api/model/node-children.md +++ b/docs/docs/api/model/node-children.md @@ -62,11 +62,11 @@ delete(node: IPublicModelNode): boolean; ```typescript /** - * 删除指定节点 - * delete the node + * 插入一个节点 + * insert the node * @param node */ -delete(node: IPublicModelNode): boolean; +insert(node: IPublicModelNode): boolean; ``` 相关类型:[IPublicModelNode](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/node.ts) diff --git a/docs/docs/api/model/window.md b/docs/docs/api/model/window.md index 3cc8b5d5e..9db39996f 100644 --- a/docs/docs/api/model/window.md +++ b/docs/docs/api/model/window.md @@ -45,6 +45,8 @@ sidebar_position: 12 关联模型 [IPublicModelEditorView](./editor-view) +**@since v1.1.7** + ### editorViews 窗口所有视图 @@ -53,6 +55,7 @@ sidebar_position: 12 关联模型 [IPublicModelEditorView](./editor-view) +**@since v1.1.7** ## 方法 @@ -90,3 +93,15 @@ onChangeViewType(fn: (viewName: string) => void): IPublicTypeDisposable; ``` 相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts) + +### onSave + +窗口视图保存事件 + +``` +onSave(fn: () => void): IPublicTypeDisposable; +``` + +相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts) + +**@since v1.1.7** diff --git a/modules/code-generator/src/parser/SchemaParser.ts b/modules/code-generator/src/parser/SchemaParser.ts index c6263877c..b4f7424ce 100644 --- a/modules/code-generator/src/parser/SchemaParser.ts +++ b/modules/code-generator/src/parser/SchemaParser.ts @@ -106,6 +106,11 @@ function processChildren(schema: IPublicTypeNodeSchema): void { } } +function getInternalDep(internalDeps: Record, depName: string) { + const dep = internalDeps[depName]; + return (dep && dep.type !== InternalDependencyType.PAGE) ? dep : null; +} + export class SchemaParser implements ISchemaParser { validate(schema: IPublicTypeProjectSchema): boolean { if (SUPPORT_SCHEMA_VERSION_LIST.indexOf(schema.version) < 0) { @@ -221,12 +226,11 @@ export class SchemaParser implements ISchemaParser { } }); - // 分析容器内部组件依赖 containers.forEach((container) => { const depNames = this.getComponentNames(container); // eslint-disable-next-line no-param-reassign container.deps = uniqueArray(depNames, (i: string) => i) - .map((depName) => internalDeps[depName] || compDeps[depName]) + .map((depName) => getInternalDep(internalDeps, depName) || compDeps[depName]) .filter(Boolean); // container.deps = Object.keys(compDeps).map((depName) => compDeps[depName]); }); diff --git a/modules/code-generator/src/plugins/common/styleImport.ts b/modules/code-generator/src/plugins/common/styleImport.ts index c340900ea..23e129302 100644 --- a/modules/code-generator/src/plugins/common/styleImport.ts +++ b/modules/code-generator/src/plugins/common/styleImport.ts @@ -21,6 +21,7 @@ const pluginFactory: BuilderComponentPluginFactory = () => { if (ir && ir.deps && ir.deps.length > 0) { let lowcodeMaterialsStyleAdded = false; + let fusionUIStyleAdded = false; let nextStyleAddedMap: Record = {}; ir.deps.forEach((dep: any) => { if (dep.package === '@alifd/next' && !nextStyleAddedMap[dep.exportName]) { @@ -41,6 +42,15 @@ const pluginFactory: BuilderComponentPluginFactory = () => { linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], }); lowcodeMaterialsStyleAdded = true; + } else if (dep.package === '@alifd/fusion-ui' && !fusionUIStyleAdded) { + chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.InternalDepsImport, + content: 'import \'@alifd/fusion-ui/lib/style\';', + linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport], + }); + fusionUIStyleAdded = true; } }); } diff --git a/packages/plugin-outline-pane/src/index.tsx b/packages/plugin-outline-pane/src/index.tsx index 95b219a4b..180b424ea 100644 --- a/packages/plugin-outline-pane/src/index.tsx +++ b/packages/plugin-outline-pane/src/index.tsx @@ -4,7 +4,7 @@ import { IPublicModelPluginContext, IPublicModelDocumentModel } from '@alilc/low import { MasterPaneName, BackupPaneName } from './helper/consts'; import { TreeMaster } from './controllers/tree-master'; import { PaneController } from './controllers/pane-controller'; -import { useState } from 'react'; +import { useState, useEffect } from 'react'; export function OutlinePaneContext(props: { treeMaster?: TreeMaster; @@ -19,9 +19,11 @@ export function OutlinePaneContext(props: { }) { const treeMaster = props.treeMaster || new TreeMaster(props.pluginContext, props.options); const [masterPaneController, setMasterPaneController] = useState(new PaneController(props.paneName || MasterPaneName, treeMaster)); - treeMaster.onPluginContextChange(() => { - setMasterPaneController(new PaneController(props.paneName || MasterPaneName, treeMaster)); - }); + useEffect(() => { + return treeMaster.onPluginContextChange(() => { + setMasterPaneController(new PaneController(props.paneName || MasterPaneName, treeMaster)); + }); + }, []); return ( { private controller; - private dispose: IPublicTypeDisposable; + private simulatorRendererReadyDispose: IPublicTypeDisposable; + private changeDocumentDispose: IPublicTypeDisposable; + private removeDocumentDispose: IPublicTypeDisposable; constructor(props: any) { super(props); @@ -26,16 +28,22 @@ export class Pane extends PureComponent<{ this.state = { tree: treeMaster.currentTree, }; - this.dispose = this.props.treeMaster.pluginContext?.project?.onSimulatorRendererReady(() => { - this.setState({ - tree: this.props.treeMaster.currentTree, - }); - }); + this.simulatorRendererReadyDispose = this.props.treeMaster.pluginContext?.project?.onSimulatorRendererReady(this.changeTree); + this.changeDocumentDispose = this.props.treeMaster.pluginContext?.project?.onChangeDocument(this.changeTree); + this.removeDocumentDispose = this.props.treeMaster.pluginContext?.project?.onRemoveDocument(this.changeTree); } + changeTree = () => { + this.setState({ + tree: this.props.treeMaster.currentTree, + }); + }; + componentWillUnmount() { this.controller.purge(); - this.dispose && this.dispose(); + this.simulatorRendererReadyDispose?.(); + this.changeDocumentDispose?.(); + this.removeDocumentDispose?.(); } render() { diff --git a/packages/shell/src/model/active-tracker.ts b/packages/shell/src/model/active-tracker.ts index e6170b7a6..32d4c04eb 100644 --- a/packages/shell/src/model/active-tracker.ts +++ b/packages/shell/src/model/active-tracker.ts @@ -13,7 +13,13 @@ export class ActiveTracker implements IPublicModelActiveTracker { } get target() { - const { node: innerNode, detail, instance } = this[activeTrackerSymbol]._target; + const _target = this[activeTrackerSymbol]._target; + + if (!_target) { + return null; + } + + const { node: innerNode, detail, instance } = _target; const publicNode = ShellNode.create(innerNode); return { node: publicNode!, diff --git a/packages/shell/src/model/window.ts b/packages/shell/src/model/window.ts index f539e9567..3e6bd6450 100644 --- a/packages/shell/src/model/window.ts +++ b/packages/shell/src/model/window.ts @@ -43,6 +43,10 @@ export class Window implements IPublicModelWindow { return await this[windowSymbol].save(); } + onSave(fn: () => void) { + return this[windowSymbol].onSave(fn); + } + get currentEditorView() { if (this[windowSymbol].editorView) { return new EditorView(this[windowSymbol].editorView).toProxy() as any; diff --git a/packages/types/src/shell/model/active-tracker.ts b/packages/types/src/shell/model/active-tracker.ts index 2538a2601..ac116a947 100644 --- a/packages/types/src/shell/model/active-tracker.ts +++ b/packages/types/src/shell/model/active-tracker.ts @@ -6,7 +6,7 @@ export interface IPublicModelActiveTracker { /** * @since 1.1.7 */ - target: IPublicTypeActiveTarget; + target: IPublicTypeActiveTarget | null; onChange(fn: (target: IPublicTypeActiveTarget) => void): () => void; diff --git a/packages/types/src/shell/model/plugin-context.ts b/packages/types/src/shell/model/plugin-context.ts index ea6fb7102..1f3d3b5e8 100644 --- a/packages/types/src/shell/model/plugin-context.ts +++ b/packages/types/src/shell/model/plugin-context.ts @@ -13,7 +13,7 @@ import { IPublicApiWorkspace, } from '../api'; import { IPublicEnumPluginRegisterLevel } from '../enum'; -import { IPublicModelEngineConfig, IPublicModelEditorView } from './'; +import { IPublicModelEngineConfig, IPublicModelWindow } from './'; export interface IPublicModelPluginContext { @@ -108,7 +108,7 @@ export interface IPublicModelPluginContext { */ get registerLevel(): IPublicEnumPluginRegisterLevel; - get editorWindow(): IPublicModelEditorView; + get editorWindow(): IPublicModelWindow; } /** diff --git a/packages/types/src/shell/model/window.ts b/packages/types/src/shell/model/window.ts index a33be6ceb..95ab738bc 100644 --- a/packages/types/src/shell/model/window.ts +++ b/packages/types/src/shell/model/window.ts @@ -42,4 +42,10 @@ export interface IPublicModelWindow< /** 窗口视图变更事件 */ onChangeViewType(fn: (viewName: string) => void): IPublicTypeDisposable; + + /** + * 窗口视图保存事件 + * @since 1.1.7 + */ + onSave(fn: () => void): IPublicTypeDisposable; } \ No newline at end of file diff --git a/packages/workspace/src/window.ts b/packages/workspace/src/window.ts index 0e37b4986..6fb706632 100644 --- a/packages/workspace/src/window.ts +++ b/packages/workspace/src/window.ts @@ -77,7 +77,18 @@ export class EditorWindow implements IEditorWindow { const saveResult = await this.editorViews.get(name)?.save(); value[name] = saveResult; } - return await this.resource.save(value); + const result = await this.resource.save(value); + this.emitter.emit('handle.save'); + + return result; + } + + onSave(fn: () => void) { + this.emitter.on('handle.save', fn); + + return () => { + this.emitter.off('handle.save', fn); + }; } async init() {