Skip to content

Commit dae0dca

Browse files
committed
feat: inject plugin suport workspace mode
1 parent a61fe7a commit dae0dca

8 files changed

Lines changed: 487 additions & 24 deletions

File tree

packages/lowcode-plugin-inject/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@alilc/lowcode-plugin-inject",
33
"author": "ens",
4-
"version": "1.2.2",
4+
"version": "1.2.3",
55
"description": "lowcode-plugin-inject",
66
"main": "lib/index.js",
77
"module": "es/index.js",
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { IPublicModelPluginContext, IPublicEnumPluginRegisterLevel } from '@alilc/lowcode-types';
2+
import { getInjectedResource, injectAssets } from './utils';
3+
import Icon from './icon';
4+
import { Pane } from './pane';
5+
import React from 'react';
6+
import { InjectConfig } from './controller';
7+
8+
const injectConfig = new InjectConfig();
9+
10+
let injectedPluginConfigMap = null;
11+
let injectedPlugins = [];
12+
13+
export async function getInjectedPlugin(name: string, ctx: IPublicModelPluginContext) {
14+
if (!injectedPluginConfigMap) {
15+
injectedPluginConfigMap = {};
16+
injectedPlugins = await getInjectedResource('plugin');
17+
if (injectedPlugins && injectedPlugins.length > 0) {
18+
injectedPlugins.forEach((item: any) => {
19+
const config = item.module(ctx);
20+
injectedPluginConfigMap[config.name || item.module.pluginName] = item.module;
21+
});
22+
}
23+
}
24+
return injectedPluginConfigMap[name];
25+
}
26+
27+
export function AppInject(ctx: IPublicModelPluginContext, options: any) {
28+
29+
const { workspace } = ctx;
30+
31+
const getInjectPlugin = async (plugin: any, pluginOptions: any, ctx?: IPublicModelPluginContext) => {
32+
let pluginName = plugin.pluginName;
33+
if (!pluginName) {
34+
const pluginConfig = plugin(ctx, pluginOptions);
35+
pluginName = pluginConfig.name;
36+
}
37+
38+
const injectedSameNamePlugin = await getInjectedPlugin(pluginName, ctx);
39+
const resourceName = ctx.editorWindow?.resource?.name;
40+
const viewName = (ctx?.editorWindow?.currentEditorView as any)?.viewName;
41+
const isGlobal = ctx?.registerLevel === IPublicEnumPluginRegisterLevel.Workspace;
42+
if (!injectedSameNamePlugin) {
43+
return plugin;
44+
}
45+
46+
if (isGlobal) {
47+
if (injectConfig.has(pluginName, 'global')) {
48+
return injectConfig.get(pluginName, 'global') ? injectedSameNamePlugin : plugin;
49+
}
50+
51+
injectConfig.set(pluginName, 'global', undefined, true)
52+
return injectedSameNamePlugin;
53+
}
54+
55+
if (!viewName || !resourceName) {
56+
return injectedSameNamePlugin;
57+
}
58+
59+
if (injectConfig.has(pluginName, resourceName, viewName)) {
60+
return injectConfig.get(pluginName, resourceName, viewName) ? injectedSameNamePlugin : plugin;
61+
}
62+
63+
injectConfig.set(pluginName, resourceName, viewName, true);
64+
65+
return injectedSameNamePlugin;
66+
}
67+
68+
ctx.config.set('customPluginTransducer', async (originPlugin: any, ctx: IPublicModelPluginContext, options) => {
69+
const injectedSameNamePlugin = await getInjectPlugin(originPlugin, options, ctx);
70+
return injectedSameNamePlugin;
71+
});
72+
73+
return {
74+
// 插件名,注册环境下唯一
75+
name: 'LowcodePluginInjectAlt',
76+
// 依赖的插件(插件名数组)
77+
dep: [],
78+
79+
async init() {
80+
const subPluginName = '___injectPlugins___';
81+
82+
const subPlugin = (ctx: IPublicModelPluginContext) => {
83+
injectAssets(ctx)
84+
return {
85+
async init() {
86+
}
87+
}
88+
}
89+
90+
subPlugin.pluginName = subPluginName;
91+
subPlugin.meta = {
92+
dependencies: [],
93+
engines: {
94+
lowcodeEngine: '^1.0.0', // 插件需要配合 ^1.0.0 的引擎才可运行
95+
},
96+
};
97+
98+
workspace.onChangeActiveWindow(async () => {
99+
for (const pluginName in injectedPluginConfigMap) {
100+
const injectedSameNamePlugin = await getInjectedPlugin(pluginName, ctx);
101+
if (!injectedSameNamePlugin) {
102+
continue;
103+
}
104+
105+
const resourceName = workspace.window?.resource?.name;
106+
const currentEditorView = workspace.window?.currentEditorView;
107+
const viewName = (currentEditorView as any)?.viewName;
108+
if (injectConfig.get(pluginName, resourceName, viewName) && !currentEditorView?.plugins.has(pluginName)) {
109+
await currentEditorView?.plugins.register(injectedPluginConfigMap[pluginName], {
110+
autoInit: true,
111+
});
112+
}
113+
114+
if (injectConfig.get(pluginName, 'global') && !workspace.plugins.has(pluginName)) {
115+
await workspace.plugins.register(injectedPluginConfigMap[pluginName], {
116+
autoInit: true,
117+
});
118+
}
119+
}
120+
121+
if (workspace.window?.currentEditorView && !workspace.window?.currentEditorView.plugins?.has(subPlugin.pluginName)) {
122+
await workspace.window?.currentEditorView.plugins.register(subPlugin)
123+
}
124+
});
125+
126+
await getInjectedPlugin(undefined, ctx);
127+
128+
ctx.skeleton.add({
129+
area: 'leftArea',
130+
name: 'inject-pane',
131+
type: 'PanelDock',
132+
props: {
133+
icon: <Icon />,
134+
description: '调试',
135+
className: 'inject-pane-icon',
136+
},
137+
index: 2,
138+
panelProps: {
139+
width: '600px',
140+
canSetFixed: false,
141+
},
142+
content: (props) => {
143+
return <Pane {...props} injectConfig={injectConfig} />
144+
},
145+
contentProps: {
146+
pluginContext: ctx,
147+
injectConfig,
148+
injectedPluginConfigMap,
149+
getInjectInfo: async () => {
150+
const injectedSetters = await getInjectedResource('vs');
151+
return {
152+
injectedSetters,
153+
}
154+
},
155+
updateInjectConfig: (pluginName: string, resourceName: string, viewName: string, check: boolean) => {
156+
injectConfig.set(pluginName, resourceName, viewName, check)
157+
injectConfig.save()
158+
}
159+
},
160+
});
161+
}
162+
}
163+
164+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { set, get, has } from 'lodash';
2+
import { EventEmitter } from 'events';
3+
4+
export type IInjectConfig = {
5+
[pluginName: string]: {
6+
[resourceName: string]: {
7+
[viewName: string]: boolean;
8+
} | boolean;
9+
10+
global?: boolean;
11+
};
12+
};
13+
14+
export class InjectConfig {
15+
_config: IInjectConfig = JSON.parse(localStorage.getItem('___inject_config___') || '{}');
16+
17+
event: EventEmitter = new EventEmitter()
18+
19+
get config() {
20+
return this._config;
21+
}
22+
23+
onChange(fn: (config: IInjectConfig) => void) {
24+
this.event.on('changeConfig', fn);
25+
return () => {
26+
this.event.off('changeConfig', fn)
27+
}
28+
}
29+
30+
set(pluginName, resourceName, viewName, injected: boolean) {
31+
if (!viewName) {
32+
set(this._config, [pluginName, resourceName], injected);
33+
this._config = {
34+
...this._config,
35+
}
36+
this.event.emit('changeConfig', this.config);
37+
return;
38+
}
39+
40+
set(this._config, [pluginName, resourceName, viewName], injected);
41+
42+
this._config = {
43+
...this._config,
44+
}
45+
46+
this.event.emit('changeConfig', this.config);
47+
}
48+
49+
get(pluginName, resourceName, viewName?) {
50+
if (!viewName) {
51+
return get(this._config, [pluginName, resourceName], false)
52+
}
53+
return get(this._config, [pluginName, resourceName, viewName], false)
54+
}
55+
56+
has(pluginName, resourceName, viewName?) {
57+
if (!viewName) {
58+
return has(this._config, [pluginName, resourceName])
59+
}
60+
return has(this._config, [pluginName, resourceName, viewName])
61+
}
62+
63+
clearAll() {
64+
this._config = {};
65+
}
66+
67+
save() {
68+
localStorage.setItem('___inject_config___', JSON.stringify(this._config));
69+
}
70+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as React from 'react';
2+
3+
export default function Icon() {
4+
return (
5+
<div>
6+
<div>
7+
<svg fill="currentColor" width={14} height={14} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2330">
8+
<path d="M1022.06544 583.40119c0 11.0558-4.034896 20.61962-12.111852 28.696576-8.077979 8.077979-17.639752 12.117992-28.690436 12.117992L838.446445 624.215758c0 72.690556-14.235213 134.320195-42.718941 184.89915l132.615367 133.26312c8.076956 8.065699 12.117992 17.634636 12.117992 28.690436 0 11.050684-4.034896 20.614503-12.117992 28.691459-7.653307 8.065699-17.209964 12.106736-28.690436 12.106736-11.475356 0-21.040199-4.041036-28.690436-12.106736L744.717737 874.15318c-2.124384 2.118244-5.308913 4.88424-9.558703 8.283664-4.259 3.3984-13.180184 9.463536-26.78504 18.171871-13.598716 8.715499-27.415396 16.473183-41.439808 23.276123-14.029528 6.797823-31.462572 12.966313-52.289923 18.49319-20.827351 5.517667-41.446971 8.28571-61.842487 8.28571L552.801776 379.38668l-81.611739 0 0 571.277058c-21.668509 0-43.250036-2.874467-64.707744-8.615215-21.473057-5.734608-39.960107-12.749372-55.476499-21.039175-15.518438-8.289804-29.541827-16.572444-42.077328-24.867364-12.541641-8.290827-21.781072-15.193027-27.739784-20.714787l-9.558703-8.93244L154.95056 998.479767c-8.500605 8.921183-18.699897 13.386892-30.606065 13.386892-10.201339 0-19.335371-3.40454-27.409257-10.202363-8.079002-7.652284-12.437264-17.10968-13.080923-28.372188-0.633427-11.263531 2.659573-21.143553 9.893324-29.647227l128.787178-144.727219c-24.650423-48.464805-36.980239-106.699114-36.980239-174.710091L42.738895 624.207571c-11.057847 0-20.61655-4.041036-28.690436-12.111852-8.079002-8.082072-12.120039-17.640776-12.120039-28.696576 0-11.050684 4.041036-20.61962 12.120039-28.689413 8.073886-8.072863 17.632589-12.107759 28.690436-12.107759l142.81466 0L185.553555 355.156836l-110.302175-110.302175c-8.074909-8.077979-12.113899-17.640776-12.113899-28.691459 0-11.04966 4.044106-20.61962 12.113899-28.690436 8.071839-8.076956 17.638729-12.123109 28.691459-12.123109 11.056823 0 20.612457 4.052293 28.692482 12.123109l110.302175 110.302175 538.128077 0 110.303198-110.302175c8.070816-8.076956 17.632589-12.123109 28.690436-12.123109 11.050684 0 20.617573 4.052293 28.689413 12.123109 8.077979 8.070816 12.119015 17.640776 12.119015 28.690436 0 11.050684-4.041036 20.614503-12.119015 28.691459l-110.302175 110.302175 0 187.448206 142.815683 0c11.0558 0 20.618597 4.034896 28.690436 12.113899 8.076956 8.069793 12.117992 17.638729 12.117992 28.683273l0 0L1022.06544 583.40119 1022.06544 583.40119zM716.021162 216.158085 307.968605 216.158085c0-56.526411 19.871583-104.667851 59.616796-144.414087 39.733956-39.746236 87.88256-59.611679 144.411017-59.611679 56.529481 0 104.678084 19.865443 144.413064 59.611679C696.156742 111.48921 716.021162 159.631674 716.021162 216.158085L716.021162 216.158085 716.021162 216.158085 716.021162 216.158085z" p-id="2331"></path>
9+
</svg>
10+
</div>
11+
<div>
12+
<span>调试</span>
13+
</div>
14+
</div>
15+
);
16+
}

packages/lowcode-plugin-inject/src/index.tsx

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as React from 'react';
22
import { plugins, setters } from '@alilc/lowcode-engine';
3-
import { IPublicModelPluginContext, IPublicTypePlugin } from '@alilc/lowcode-types';
3+
import { IPublicModelPluginContext, IPublicEnumPluginRegisterLevel, IPublicTypePlugin } from '@alilc/lowcode-types';
44
import { getInjectedResource, injectAssets, needInject, injectComponents, filterPackages, setInjectServerHost } from './utils';
55
import { Notification } from '@alifd/next';
6-
6+
import { AppInject } from './appInject';
77

88
let injectedPluginConfigMap = null;
99
let injectedPlugins = [];
@@ -32,39 +32,46 @@ interface IOptions {
3232
}
3333

3434
const Inject = (ctx: IPublicModelPluginContext, options: IOptions = {}) => {
35+
if (!needInject) {
36+
return {
37+
init() {}
38+
}
39+
}
40+
41+
if (ctx.registerLevel === IPublicEnumPluginRegisterLevel.Workspace) {
42+
return AppInject(ctx, options);
43+
}
44+
3545
if (options?.injectServerHost) {
3646
setInjectServerHost(options.injectServerHost);
3747
}
48+
3849
// inject 已有的设计器插件
39-
if (needInject) {
40-
// 覆盖后续的插件注册逻辑,所有只有本插件后面注册的插件才可以支持 inject 逻辑
41-
const originalRegister = plugins.register;
42-
plugins.register = async function (plugin: IPublicTypePlugin, pluginOptions: any, options: any) {
43-
let pluginName = plugin.pluginName;
44-
if (!pluginName) {
45-
const pluginConfig = plugin(ctx, pluginOptions);
46-
// 兼容逻辑
47-
pluginName = (pluginConfig as any).name;
48-
}
49-
const injectedSameNamePlugin = await getInjectedPlugin(pluginName, ctx);
50-
if (injectedSameNamePlugin) {
51-
injectedPluginConfigMap[pluginName] = null;
52-
return originalRegister.call(this, injectedSameNamePlugin, pluginOptions, options);
53-
} else {
54-
return originalRegister.call(this, plugin, pluginOptions, options);
55-
}
50+
// 覆盖后续的插件注册逻辑,所有只有本插件后面注册的插件才可以支持 inject 逻辑
51+
const originalRegister = plugins.register;
52+
plugins.register = async function (plugin: IPublicTypePlugin, pluginOptions: any, options: any) {
53+
let pluginName = plugin.pluginName;
54+
if (!pluginName) {
55+
const pluginConfig = plugin(ctx, pluginOptions);
56+
// 兼容逻辑
57+
pluginName = (pluginConfig as any).name;
58+
}
59+
const injectedSameNamePlugin = await getInjectedPlugin(pluginName, ctx);
60+
if (injectedSameNamePlugin) {
61+
injectedPluginConfigMap[pluginName] = null;
62+
return originalRegister.call(this, injectedSameNamePlugin, pluginOptions, options);
63+
} else {
64+
return originalRegister.call(this, plugin, pluginOptions, options);
5665
}
5766
}
67+
5868
return {
5969
// 插件名,注册环境下唯一
6070
name: 'LowcodePluginInjectAlt',
6171
// 依赖的插件(插件名数组)
6272
dep: [],
6373
// 插件的初始化函数,在引擎初始化之后会立刻调用
6474
async init() {
65-
if (!needInject) {
66-
return;
67-
}
6875

6976
// inject 新的设计器插件
7077
if (injectedPluginConfigMap) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
.inject-pane-icon {
2+
height: 60px !important;
3+
font-size: 12px;
4+
text-align: center;
5+
margin-bottom: 10px;
6+
}
7+
8+
.inject-setting-panel {
9+
padding: 10px 20px;
10+
11+
&-title {
12+
font-size: 14px;
13+
margin-bottom: 10px;
14+
display: inline-block;
15+
font-weight: bold;
16+
}
17+
18+
&-label {
19+
width: 100px;
20+
text-align: right;
21+
margin-bottom: 10px;
22+
margin-right: 15px;
23+
display: inline-block;
24+
}
25+
26+
&-inject-item {
27+
margin-left: 10px;
28+
margin-bottom: 10px;
29+
}
30+
31+
&-table {
32+
margin-bottom: 10px;
33+
}
34+
35+
&-empty {
36+
padding: 20px;
37+
38+
&-title {
39+
font-weight: bold;
40+
font-size: 14px;
41+
}
42+
43+
&-tips {
44+
font-size: 12px;
45+
margin-top: 10px;
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)