diff --git a/packages/amis-editor-core/src/component/Editor.tsx b/packages/amis-editor-core/src/component/Editor.tsx index 3a0588c84..bf631ff44 100644 --- a/packages/amis-editor-core/src/component/Editor.tsx +++ b/packages/amis-editor-core/src/component/Editor.tsx @@ -66,7 +66,10 @@ export interface EditorProps extends PluginEventListener { | Array | ((id: string, plugin: PluginClass) => boolean); - plugins?: Array; + plugins?: Array< + | PluginClass + | [PluginClass, Record | (() => Record)] + >; /** * 传给预览器的其他属性 diff --git a/packages/amis-editor-core/src/component/factory.tsx b/packages/amis-editor-core/src/component/factory.tsx index 6bd88c3e6..7db6371e8 100644 --- a/packages/amis-editor-core/src/component/factory.tsx +++ b/packages/amis-editor-core/src/component/factory.tsx @@ -221,7 +221,10 @@ function SchemaFrom({ submitOnChange, node, manager, - justify + justify, + ctx, + pipeIn, + pipeOut }: { propKey: string; env: any; @@ -240,6 +243,9 @@ function SchemaFrom({ manager: EditorManager; panelById?: string; justify?: boolean; + ctx?: any; + pipeIn?: (value: any) => any; + pipeOut?: (value: any) => any; }) { let containerKey = 'body'; @@ -290,14 +296,17 @@ function SchemaFrom({ }; } + value = pipeIn ? pipeIn(value) : value; + return render( schema, { - onFinished: (newValue: any) => { + onFinished: async (newValue: any) => { + newValue = pipeOut ? await pipeOut(newValue) : newValue; const diffValue = diff(value, newValue); onChange(newValue, diffValue); }, - data: value, + data: ctx ? createObject(ctx, value) : value, node: node, manager: manager, popOverContainer @@ -320,6 +329,8 @@ export function makeSchemaFormRender( justify?: boolean; panelById?: string; formKey?: string; + pipeIn?: (value: any) => any; + pipeOut?: (value: any) => any; } ) { const env = {...manager.env, session: 'schema-form'}; @@ -366,7 +377,10 @@ export function makeSchemaFormRender( ) : undefined } - value={createObject(ctx, value)} + value={value} + ctx={ctx} + pipeIn={schema.pipeIn} + pipeOut={schema.pipeOut} submitOnChange={schema.submitOnChange} onChange={onChange} env={env} diff --git a/packages/amis-editor-core/src/manager.ts b/packages/amis-editor-core/src/manager.ts index b5795fb37..8ee9a8ee5 100644 --- a/packages/amis-editor-core/src/manager.ts +++ b/packages/amis-editor-core/src/manager.ts @@ -75,11 +75,13 @@ export interface EditorManagerConfig extends Omit {} export interface PluginClass { - new (manager: EditorManager): PluginInterface; + new (manager: EditorManager, options?: any): PluginInterface; id?: string; } -const builtInPlugins: Array = []; +const builtInPlugins: Array< + PluginClass | [PluginClass, Record | (() => Record)] +> = []; declare const window: Window & {AMISEditorCustomPlugins: any}; @@ -105,8 +107,10 @@ export function autoPreRegisterEditorCustomPlugins() { export function registerEditorPlugin(klass: PluginClass) { let isExitPlugin: any = null; if (klass.prototype && klass.prototype.isNpmCustomWidget) { - isExitPlugin = builtInPlugins.find( - item => item.prototype.name === klass.prototype.name + isExitPlugin = builtInPlugins.find(item => + Array.isArray(item) + ? item[0].prototype.name === klass.prototype.name + : item.prototype.name === klass.prototype.name ); } else { // 待进一步优化 @@ -130,7 +134,9 @@ export function getEditorPlugins() { * 注销插件 */ export function unRegisterEditorPlugin(id: string) { - const idx = findIndex(builtInPlugins, item => item.id === id); + const idx = findIndex(builtInPlugins, item => + Array.isArray(item) ? item[0].id === id : item.id === id + ); ~idx && builtInPlugins.splice(idx, 1); } @@ -191,15 +197,23 @@ export class EditorManager { parent?.plugins || (config.disableBultinPlugin ? [] : builtInPlugins) // 页面设计器注册的插件列表 .concat(config.plugins || []) - .filter(p => - config.disablePluginList + .filter(p => { + p = Array.isArray(p) ? p[0] : p; + return config.disablePluginList ? typeof config.disablePluginList === 'function' ? !config.disablePluginList(p.id || '', p) : !config.disablePluginList.includes(p.id || 'unkown') - : true - ) + : true; + }) .map(Editor => { - const plugin = new Editor(this); // 进行一次实例化 + let pluginOptions: Record = {}; + if (Array.isArray(Editor)) { + pluginOptions = + typeof Editor[1] === 'function' ? Editor[1]() : Editor[1]; + Editor = Editor[0]; + } + + const plugin = new Editor(this, pluginOptions); // 进行一次实例化 plugin.order = plugin.order ?? 0; // 记录动作定义 @@ -538,7 +552,7 @@ export class EditorManager { // 此处换成for是为了解决异步问题 for (let index = 0, size = this.plugins.length; index < size; index++) { const pluginItem = this.plugins[index]; - let subRenderer = pluginItem.buildSubRenderers?.( + let subRenderer = await pluginItem.buildSubRenderers?.( contxt, subRenderers, getRenderers() @@ -1697,6 +1711,8 @@ export class EditorManager { justify?: boolean; panelById?: string; formKey?: string; + pipeIn?: (value: any) => any; + pipeOut?: (value: any) => any; }) { return makeSchemaFormRender(this, schema); } @@ -1915,8 +1931,14 @@ export class EditorManager { * 销毁函数 */ dispose() { + // 有些插件需要销毁,靠这个事件 + this.trigger('dispose', { + data: this + }); this.toDispose.forEach(fn => fn()); this.toDispose = []; + this.plugins.forEach(p => p.dispose?.()); + this.plugins.splice(0, this.plugins.length); this.listeners.splice(0, this.listeners.length); this.broadcasts.splice(0, this.broadcasts.length); this.lazyPatchSchema.cancel(); diff --git a/packages/amis-editor-core/src/plugin.ts b/packages/amis-editor-core/src/plugin.ts index 4e99a043f..ddeb774ef 100644 --- a/packages/amis-editor-core/src/plugin.ts +++ b/packages/amis-editor-core/src/plugin.ts @@ -863,7 +863,11 @@ export interface PluginInterface context: RendererEventContext, subRenderers: Array, renderers: Array - ) => BasicSubRenderInfo | Array | void; + ) => + | BasicSubRenderInfo + | Array + | void + | Promise | void>; /** * 更新NPM自定义组件分类和排序[异步方法] @@ -894,6 +898,8 @@ export interface PluginInterface e: any, data: any ) => void; + + dispose?: () => void; } export interface RendererPluginEvent { @@ -1132,62 +1138,6 @@ export abstract class BasePlugin implements PluginInterface { } } - /** - * 构建当前选中组件的右键菜单 - * @param id - * @param schema - * @param region - * @param info - * @param menus - */ - buildEditorContextMenu( - {id, schema, region, info, selections}: ContextMenuEventContext, - menus: Array - ) { - const plugin: PluginInterface = this; - if ( - info.plugin === plugin && - !selections.length && - (plugin.scaffoldForm?.canRebuild || info.scaffoldForm?.canRebuild) - ) { - menus.push({ - label: `快速构建「${info.plugin.name}」`, - disabled: schema.$$commonSchema, - onSelect: () => - this.manager.reScaffold( - id, - info.scaffoldForm || plugin.scaffoldForm!, - schema - ) - }); - } - } - - buildEditorToolbar( - {id, schema, info}: BaseEventContext, - toolbars: Array - ) { - const plugin: PluginInterface = this; - if ( - info.plugin === plugin && - (info.scaffoldForm?.canRebuild ?? plugin.scaffoldForm?.canRebuild) - ) { - toolbars.push({ - iconSvg: 'harmmer', - tooltip: `快速构建「${info.plugin.name}」`, - placement: 'bottom', - onClick: () => this.manager.reScaffoldV2(id) - /* - this.manager.reScaffold( - id, - info.scaffoldForm || plugin.scaffoldForm!, - schema - ) - */ - }); - } - } - renderPlaceholder(text: string, key?: any, style?: any) { return React.createElement('div', { key, @@ -1209,12 +1159,10 @@ export abstract class BasePlugin implements PluginInterface { } } - /** * 布局相关组件基类,带宽高可拖拽功能。 */ export class LayoutBasePlugin extends BasePlugin { - onActive(event: PluginEvent) { const context = event.context; @@ -1350,4 +1298,4 @@ export class LayoutBasePlugin extends BasePlugin { } }); } -} \ No newline at end of file +} diff --git a/packages/amis-editor-core/src/plugin/BasicToolbar.tsx b/packages/amis-editor-core/src/plugin/BasicToolbar.tsx index 1fb7337ee..a56eaef9f 100644 --- a/packages/amis-editor-core/src/plugin/BasicToolbar.tsx +++ b/packages/amis-editor-core/src/plugin/BasicToolbar.tsx @@ -7,7 +7,8 @@ import { BasicPanelItem, BuildPanelEventContext, PluginEvent, - InsertEventContext + InsertEventContext, + PluginInterface } from '../plugin'; import {registerEditorPlugin} from '../manager'; import type {MenuItem} from 'amis-ui/lib/components/ContextMenu'; @@ -20,7 +21,7 @@ export class BasicToolbarPlugin extends BasePlugin { order = -9999; buildEditorToolbar( - {id, schema}: BaseEventContext, + {id, schema, info}: BaseEventContext, toolbars: Array ) { const store = this.manager.store; @@ -218,10 +219,19 @@ export class BasicToolbarPlugin extends BasePlugin { } } }); + + if (info.scaffoldForm?.canRebuild ?? info.plugin.scaffoldForm?.canRebuild) { + toolbars.push({ + iconSvg: 'harmmer', + tooltip: `快速构建「${info.plugin.name}」`, + placement: 'bottom', + onClick: () => this.manager.reScaffoldV2(id) + }); + } } buildEditorContextMenu( - {id, schema, region, selections}: ContextMenuEventContext, + {id, schema, region, info, selections}: ContextMenuEventContext, menus: Array ) { const manager = this.manager; @@ -522,6 +532,22 @@ export class BasicToolbarPlugin extends BasePlugin { }); */ } + + if ( + !selections.length && + (info.plugin.scaffoldForm?.canRebuild || info.scaffoldForm?.canRebuild) + ) { + menus.push({ + label: `快速构建「${info.plugin.name}」`, + disabled: schema.$$commonSchema, + onSelect: () => + this.manager.reScaffold( + id, + info.scaffoldForm || info.plugin.scaffoldForm!, + schema + ) + }); + } } buildEditorPanel(