mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 11:20:11 +00:00
feat: support webview type resource in workspace mode
This commit is contained in:
parent
8c82fe8f00
commit
36d1d3bef1
@ -32,4 +32,12 @@ export class Resource implements IPublicModelResource {
|
|||||||
get category() {
|
get category() {
|
||||||
return this[resourceSymbol].category;
|
return this[resourceSymbol].category;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get children() {
|
||||||
|
return this[resourceSymbol].children.map((child) => new Resource(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
get viewType() {
|
||||||
|
return this[resourceSymbol].viewType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ export interface IPublicApiWorkspace {
|
|||||||
setResourceList(resourceList: IPublicResourceList): void;
|
setResourceList(resourceList: IPublicResourceList): void;
|
||||||
|
|
||||||
/** 资源树列表更新事件 */
|
/** 资源树列表更新事件 */
|
||||||
onResourceListChange(fn: (resourceList: IPublicResourceList) => void): () => IPublicTypeDisposable;
|
onResourceListChange(fn: (resourceList: IPublicResourceList) => void): IPublicTypeDisposable;
|
||||||
|
|
||||||
/** 注册资源 */
|
/** 注册资源 */
|
||||||
registerResourceType(resourceTypeModel: IPublicTypeResourceType): void;
|
registerResourceType(resourceTypeModel: IPublicTypeResourceType): void;
|
||||||
|
|||||||
@ -5,4 +5,7 @@ export interface IPublicEditorViewConfig {
|
|||||||
|
|
||||||
/** 资源保存时,会调用视图的钩子 */
|
/** 资源保存时,会调用视图的钩子 */
|
||||||
save?: () => Promise<void>;
|
save?: () => Promise<void>;
|
||||||
|
|
||||||
|
/** viewType 类型为 'webview' 时渲染的地址 */
|
||||||
|
url?: () => Promise<string>;
|
||||||
}
|
}
|
||||||
@ -1,10 +1,15 @@
|
|||||||
|
import { ReactElement } from 'react';
|
||||||
|
|
||||||
export interface IPublicResourceData {
|
export interface IPublicResourceData {
|
||||||
resourceName: string;
|
resourceName: string;
|
||||||
title: string;
|
title: string;
|
||||||
category?: string;
|
category?: string;
|
||||||
|
viewType?: string;
|
||||||
|
icon?: ReactElement;
|
||||||
options: {
|
options: {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
children?: IPublicResourceData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IPublicResourceList = IPublicResourceData[];
|
export type IPublicResourceList = IPublicResourceData[];
|
||||||
@ -28,4 +28,7 @@ export interface IPublicResourceTypeConfig {
|
|||||||
|
|
||||||
/** 默认标题 */
|
/** 默认标题 */
|
||||||
defaultTitle?: string;
|
defaultTitle?: string;
|
||||||
|
|
||||||
|
/** resourceType 类型为 'webview' 时渲染的地址 */
|
||||||
|
url?: () => Promise<string>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { IPublicResourceTypeConfig } from './resource-type-config';
|
|||||||
export interface IPublicTypeResourceType {
|
export interface IPublicTypeResourceType {
|
||||||
resourceName: string;
|
resourceName: string;
|
||||||
|
|
||||||
resourceType: string;
|
resourceType: 'editor' | 'webview';
|
||||||
|
|
||||||
(ctx: IPublicModelPluginContext): IPublicResourceTypeConfig;
|
(ctx: IPublicModelPluginContext, options: Object): IPublicResourceTypeConfig;
|
||||||
}
|
}
|
||||||
@ -28,18 +28,22 @@ import {
|
|||||||
Canvas,
|
Canvas,
|
||||||
} from '@alilc/lowcode-shell';
|
} from '@alilc/lowcode-shell';
|
||||||
import {
|
import {
|
||||||
|
IPluginPreferenceMananger,
|
||||||
|
IPublicApiEvent,
|
||||||
|
IPublicModelPluginContext,
|
||||||
IPublicTypePluginMeta,
|
IPublicTypePluginMeta,
|
||||||
} from '@alilc/lowcode-types';
|
} from '@alilc/lowcode-types';
|
||||||
import { getLogger } from '@alilc/lowcode-utils';
|
import { getLogger } from '@alilc/lowcode-utils';
|
||||||
import { Workspace as InnerWorkspace } from '../workspace';
|
import { Workspace as InnerWorkspace } from '../workspace';
|
||||||
import { EditorWindow } from '../window';
|
import { EditorWindow } from '../window';
|
||||||
|
|
||||||
export class BasicContext {
|
export class BasicContext implements IPublicModelPluginContext {
|
||||||
skeleton: Skeleton;
|
skeleton: Skeleton;
|
||||||
plugins: Plugins;
|
plugins: Plugins;
|
||||||
project: Project;
|
project: Project;
|
||||||
setters: Setters;
|
setters: Setters;
|
||||||
material: Material;
|
material: Material;
|
||||||
|
common: Common;
|
||||||
config;
|
config;
|
||||||
event;
|
event;
|
||||||
logger;
|
logger;
|
||||||
@ -53,6 +57,8 @@ export class BasicContext {
|
|||||||
innerHotkey: InnerHotkey;
|
innerHotkey: InnerHotkey;
|
||||||
innerPlugins: LowCodePluginManager;
|
innerPlugins: LowCodePluginManager;
|
||||||
canvas: Canvas;
|
canvas: Canvas;
|
||||||
|
pluginEvent: IPublicApiEvent;
|
||||||
|
preference: IPluginPreferenceMananger;
|
||||||
|
|
||||||
constructor(innerWorkspace: InnerWorkspace, viewName: string, public editorWindow?: EditorWindow) {
|
constructor(innerWorkspace: InnerWorkspace, viewName: string, public editorWindow?: EditorWindow) {
|
||||||
const editor = new Editor(viewName, true);
|
const editor = new Editor(viewName, true);
|
||||||
@ -101,6 +107,7 @@ export class BasicContext {
|
|||||||
this.designer = designer;
|
this.designer = designer;
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
const common = new Common(editor, innerSkeleton);
|
const common = new Common(editor, innerSkeleton);
|
||||||
|
this.common = common;
|
||||||
let plugins: any;
|
let plugins: any;
|
||||||
|
|
||||||
const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { makeObservable, obx } from '@alilc/lowcode-editor-core';
|
import { computed, makeObservable, obx } from '@alilc/lowcode-editor-core';
|
||||||
import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types';
|
import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types';
|
||||||
import { flow } from 'mobx';
|
import { flow } from 'mobx';
|
||||||
import { Workspace as InnerWorkspace } from '../workspace';
|
import { Workspace as InnerWorkspace } from '../workspace';
|
||||||
@ -17,7 +17,7 @@ export class Context extends BasicContext {
|
|||||||
|
|
||||||
@obx isInit: boolean = false;
|
@obx isInit: boolean = false;
|
||||||
|
|
||||||
get active() {
|
@computed get active() {
|
||||||
return this._activate;
|
return this._activate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ export class Context extends BasicContext {
|
|||||||
this.isInit = true;
|
this.isInit = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(public workspace: InnerWorkspace, public editorWindow: EditorWindow, public editorView: IPublicTypeEditorView, options: Object) {
|
constructor(public workspace: InnerWorkspace, public editorWindow: EditorWindow, public editorView: IPublicTypeEditorView, options: Object | undefined) {
|
||||||
super(workspace, editorView.viewName, editorWindow);
|
super(workspace, editorView.viewName, editorWindow);
|
||||||
this.viewType = editorView.viewType || 'editor';
|
this.viewType = editorView.viewType || 'editor';
|
||||||
this.viewName = editorView.viewName;
|
this.viewName = editorView.viewName;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { IPublicModelPluginContext } from '@alilc/lowcode-types';
|
import { IPublicModelPluginContext } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
function DesignerView(props: {
|
export function DesignerView(props: {
|
||||||
url: string;
|
url: string;
|
||||||
viewName: string;
|
viewName: string;
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@ -17,12 +17,16 @@ export class Resource implements IPublicModelResource {
|
|||||||
return this.resourceType.name;
|
return this.resourceType.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get viewType() {
|
||||||
|
return this.resourceData.viewType;
|
||||||
|
}
|
||||||
|
|
||||||
get description() {
|
get description() {
|
||||||
return this.resourceTypeInstance?.description;
|
return this.resourceTypeInstance?.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
get icon() {
|
get icon() {
|
||||||
return this.resourceTypeInstance?.icon;
|
return this.resourceData.icon || this.resourceTypeInstance?.icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
get type() {
|
get type() {
|
||||||
@ -45,9 +49,13 @@ export class Resource implements IPublicModelResource {
|
|||||||
return this.context.innerSkeleton;
|
return this.context.innerSkeleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType, workspace: InnerWorkSpace) {
|
get children(): Resource[] {
|
||||||
|
return this.resourceData?.children?.map(d => new Resource(d, this.resourceType, this.workspace)) || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType, readonly workspace: InnerWorkSpace) {
|
||||||
this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`);
|
this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`);
|
||||||
this.resourceTypeInstance = resourceType.resourceTypeModel(this.context, {});
|
this.resourceTypeInstance = resourceType.resourceTypeModel(this.context, this.options);
|
||||||
this.init();
|
this.init();
|
||||||
if (this.resourceTypeInstance.editorViews) {
|
if (this.resourceTypeInstance.editorViews) {
|
||||||
this.resourceTypeInstance.editorViews.forEach((d: any) => {
|
this.resourceTypeInstance.editorViews.forEach((d: any) => {
|
||||||
@ -68,6 +76,10 @@ export class Resource implements IPublicModelResource {
|
|||||||
return await this.resourceTypeInstance.import?.(schema);
|
return await this.resourceTypeInstance.import?.(schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async url() {
|
||||||
|
return await this.resourceTypeInstance.url?.();
|
||||||
|
}
|
||||||
|
|
||||||
async save(value: any) {
|
async save(value: any) {
|
||||||
return await this.resourceTypeInstance.save?.(value);
|
return await this.resourceTypeInstance.save?.(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { ResourceView } from './resource-view';
|
|||||||
import { engineConfig, observer } from '@alilc/lowcode-editor-core';
|
import { engineConfig, observer } from '@alilc/lowcode-editor-core';
|
||||||
import { EditorWindow } from '../window';
|
import { EditorWindow } from '../window';
|
||||||
import { BuiltinLoading } from '@alilc/lowcode-designer';
|
import { BuiltinLoading } from '@alilc/lowcode-designer';
|
||||||
|
import { DesignerView } from '../inner-plugins/webview';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class WindowView extends PureComponent<{
|
export class WindowView extends PureComponent<{
|
||||||
@ -11,16 +12,21 @@ export class WindowView extends PureComponent<{
|
|||||||
}, any> {
|
}, any> {
|
||||||
render() {
|
render() {
|
||||||
const { active } = this.props;
|
const { active } = this.props;
|
||||||
const { editorView, resource } = this.props.window;
|
const { resource, initReady, url } = this.props.window;
|
||||||
if (!editorView) {
|
|
||||||
|
if (!initReady) {
|
||||||
const Loading = engineConfig.get('loadingComponent', BuiltinLoading);
|
const Loading = engineConfig.get('loadingComponent', BuiltinLoading);
|
||||||
return (
|
return (
|
||||||
<div className={`workspace-engine-main ${active ? 'active' : ''}`}>
|
<div className={`workspace-engine-main 111 ${active ? 'active' : ''}`}>
|
||||||
<Loading />
|
<Loading />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resource.type === 'webview' && url) {
|
||||||
|
return <DesignerView url={url} viewName={resource.name} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`workspace-engine-main ${active ? 'active' : ''}`}>
|
<div className={`workspace-engine-main ${active ? 'active' : ''}`}>
|
||||||
<ResourceView
|
<ResourceView
|
||||||
|
|||||||
@ -5,19 +5,32 @@ import { Workspace } from './workspace';
|
|||||||
import { Resource } from './resource';
|
import { Resource } from './resource';
|
||||||
import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable';
|
import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable';
|
||||||
|
|
||||||
|
interface IWindowCOnfig {
|
||||||
|
title: string | undefined;
|
||||||
|
options?: Object;
|
||||||
|
viewType?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export class EditorWindow {
|
export class EditorWindow {
|
||||||
id: string = uniqueId('window');
|
id: string = uniqueId('window');
|
||||||
icon: React.ReactElement | undefined;
|
icon: React.ReactElement | undefined;
|
||||||
|
|
||||||
private emitter: IEventBus = createModuleEventBus('Project');
|
private emitter: IEventBus = createModuleEventBus('Project');
|
||||||
|
|
||||||
|
title: string | undefined;
|
||||||
|
|
||||||
|
url: string | undefined;
|
||||||
|
|
||||||
@obx.ref editorView: Context;
|
@obx.ref editorView: Context;
|
||||||
|
|
||||||
@obx editorViews: Map<string, Context> = new Map<string, Context>();
|
@obx editorViews: Map<string, Context> = new Map<string, Context>();
|
||||||
|
|
||||||
constructor(readonly resource: Resource, readonly workspace: Workspace, public title: string | undefined = '', private options: Object = {}) {
|
@obx initReady = false;
|
||||||
|
|
||||||
|
constructor(readonly resource: Resource, readonly workspace: Workspace, private config: IWindowCOnfig) {
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
this.init();
|
this.init();
|
||||||
|
this.title = config.title;
|
||||||
this.icon = resource.icon;
|
this.icon = resource.icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,11 +61,16 @@ export class EditorWindow {
|
|||||||
async init() {
|
async init() {
|
||||||
await this.initViewTypes();
|
await this.initViewTypes();
|
||||||
await this.execViewTypesInit();
|
await this.execViewTypesInit();
|
||||||
|
this.url = await this.resource.url();
|
||||||
this.setDefaultViewType();
|
this.setDefaultViewType();
|
||||||
|
this.initReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
initViewTypes = async () => {
|
initViewTypes = async () => {
|
||||||
const editorViews = this.resource.editorViews;
|
const editorViews = this.resource.editorViews;
|
||||||
|
if (!editorViews) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (let i = 0; i < editorViews.length; i++) {
|
for (let i = 0; i < editorViews.length; i++) {
|
||||||
const name = editorViews[i].viewName;
|
const name = editorViews[i].viewName;
|
||||||
await this.initViewType(name);
|
await this.initViewType(name);
|
||||||
@ -72,6 +90,9 @@ export class EditorWindow {
|
|||||||
|
|
||||||
execViewTypesInit = async () => {
|
execViewTypesInit = async () => {
|
||||||
const editorViews = this.resource.editorViews;
|
const editorViews = this.resource.editorViews;
|
||||||
|
if (!editorViews) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (let i = 0; i < editorViews.length; i++) {
|
for (let i = 0; i < editorViews.length; i++) {
|
||||||
const name = editorViews[i].viewName;
|
const name = editorViews[i].viewName;
|
||||||
this.changeViewType(name);
|
this.changeViewType(name);
|
||||||
@ -80,15 +101,19 @@ export class EditorWindow {
|
|||||||
};
|
};
|
||||||
|
|
||||||
setDefaultViewType = () => {
|
setDefaultViewType = () => {
|
||||||
this.changeViewType(this.resource.defaultViewType);
|
this.changeViewType(this.config.viewType ?? this.resource.defaultViewType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
get resourceType() {
|
||||||
|
return this.resource.resourceType.type;
|
||||||
|
}
|
||||||
|
|
||||||
initViewType = async (name: string) => {
|
initViewType = async (name: string) => {
|
||||||
const viewInfo = this.resource.getEditorView(name);
|
const viewInfo = this.resource.getEditorView(name);
|
||||||
if (this.editorViews.get(name)) {
|
if (this.editorViews.get(name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const editorView = new Context(this.workspace, this, viewInfo as any, this.options);
|
const editorView = new Context(this.workspace, this, viewInfo as any, this.config.options);
|
||||||
this.editorViews.set(name, editorView);
|
this.editorViews.set(name, editorView);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -96,6 +121,10 @@ export class EditorWindow {
|
|||||||
this.editorView?.setActivate(false);
|
this.editorView?.setActivate(false);
|
||||||
this.editorView = this.editorViews.get(name)!;
|
this.editorView = this.editorViews.get(name)!;
|
||||||
|
|
||||||
|
if (!this.editorView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ignoreEmit) {
|
if (!ignoreEmit) {
|
||||||
this.emitter.emit('window.change.view.type', name);
|
this.emitter.emit('window.change.view.type', name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@ export class Workspace implements IPublicApiWorkspace {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
windows: EditorWindow[] = [];
|
@obx.ref windows: EditorWindow[] = [];
|
||||||
|
|
||||||
editorWindowMap: Map<string, EditorWindow> = new Map<string, EditorWindow>();
|
editorWindowMap: Map<string, EditorWindow> = new Map<string, EditorWindow>();
|
||||||
|
|
||||||
@ -71,7 +71,9 @@ export class Workspace implements IPublicApiWorkspace {
|
|||||||
}
|
}
|
||||||
const title = this.defaultResourceType.name;
|
const title = this.defaultResourceType.name;
|
||||||
const resource = new Resource({}, this.defaultResourceType, this);
|
const resource = new Resource({}, this.defaultResourceType, this);
|
||||||
this.window = new EditorWindow(resource, this, title);
|
this.window = new EditorWindow(resource, this, {
|
||||||
|
title,
|
||||||
|
});
|
||||||
this.editorWindowMap.set(this.window.id, this.window);
|
this.editorWindowMap.set(this.window.id, this.window);
|
||||||
this.windows.push(this.window);
|
this.windows.push(this.window);
|
||||||
this.emitChangeWindow();
|
this.emitChangeWindow();
|
||||||
@ -83,7 +85,6 @@ export class Workspace implements IPublicApiWorkspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async registerResourceType(resourceTypeModel: IPublicTypeResourceType): Promise<void> {
|
async registerResourceType(resourceTypeModel: IPublicTypeResourceType): Promise<void> {
|
||||||
if (resourceTypeModel.resourceType === 'editor') {
|
|
||||||
const resourceType = new ResourceType(resourceTypeModel);
|
const resourceType = new ResourceType(resourceTypeModel);
|
||||||
this.resourceTypeMap.set(resourceTypeModel.resourceName, resourceType);
|
this.resourceTypeMap.set(resourceTypeModel.resourceName, resourceType);
|
||||||
|
|
||||||
@ -91,7 +92,6 @@ export class Workspace implements IPublicApiWorkspace {
|
|||||||
this.initWindow();
|
this.initWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
getResourceList() {
|
getResourceList() {
|
||||||
return this.resourceList;
|
return this.resourceList;
|
||||||
@ -150,7 +150,7 @@ export class Workspace implements IPublicApiWorkspace {
|
|||||||
openEditorWindow(name: string, title: string, options: Object, viewType?: string) {
|
openEditorWindow(name: string, title: string, options: Object, viewType?: string) {
|
||||||
const resourceType = this.resourceTypeMap.get(name);
|
const resourceType = this.resourceTypeMap.get(name);
|
||||||
if (!resourceType) {
|
if (!resourceType) {
|
||||||
console.error(`${name} is not available`);
|
console.error(`${name} resourceType is not available`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const filterWindows = this.windows.filter(d => (d.resource.name === name && d.resource.title == title));
|
const filterWindows = this.windows.filter(d => (d.resource.name === name && d.resource.title == title));
|
||||||
@ -164,8 +164,12 @@ export class Workspace implements IPublicApiWorkspace {
|
|||||||
title,
|
title,
|
||||||
options,
|
options,
|
||||||
}, resourceType, this);
|
}, resourceType, this);
|
||||||
this.window = new EditorWindow(resource, this, title, options);
|
this.window = new EditorWindow(resource, this, {
|
||||||
this.windows.push(this.window);
|
title,
|
||||||
|
options,
|
||||||
|
viewType,
|
||||||
|
});
|
||||||
|
this.windows = [...this.windows, this.window];
|
||||||
this.editorWindowMap.set(this.window.id, this.window);
|
this.editorWindowMap.set(this.window.id, this.window);
|
||||||
this.emitChangeWindow();
|
this.emitChangeWindow();
|
||||||
this.emitChangeActiveWindow();
|
this.emitChangeActiveWindow();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user