feat(All):Initial
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @author ErSan
|
||||
* @email mlt131220@163.com
|
||||
* @date 2024/9/16 23:18
|
||||
* @description 在此处注册内置插件
|
||||
*/
|
||||
import {PluginManager} from "../plugin";
|
||||
|
||||
export default class Builtin{
|
||||
// @ts-ignore
|
||||
constructor(pluginManager:PluginManager) {
|
||||
// 注册内置插件
|
||||
// pluginManager.use(new XXX());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
import {loadPluginAsync} from "./pluginLoader";
|
||||
import Builtin from "./builtin/builtin";
|
||||
import {useDispatchSignal} from "@/hooks";
|
||||
|
||||
// 所有插件都必须实现此接口
|
||||
export interface Plugin {
|
||||
name: string; // 插件名称,插件的唯一标识
|
||||
version:number; // 插件版本号
|
||||
icon:string; // 插件图标
|
||||
install(config?: any): void; // 插件安装
|
||||
uninstall(): void; // 卸载插件
|
||||
run(): void; // 从插件盒子面板点击插件时的运行方法
|
||||
}
|
||||
|
||||
export class PluginManager {
|
||||
public plugins: Map<string, Plugin> = new Map(); // 已加载插件
|
||||
|
||||
constructor() {
|
||||
// 载入内置插件
|
||||
new Builtin(this);
|
||||
}
|
||||
|
||||
get list(){
|
||||
const list:IPlugin.Item[] = [];
|
||||
for (const plugin of this.plugins.values()) {
|
||||
list.push({
|
||||
name:plugin.name,
|
||||
icon:plugin.icon
|
||||
})
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载插件
|
||||
* @param pluginPaths 插件地址
|
||||
* @param autoUse 插件是否自动注册
|
||||
*/
|
||||
async loadAsync(pluginPaths: string | string[],autoUse = false){
|
||||
let plugins:Plugin[] = [];
|
||||
|
||||
for (const src of pluginPaths) {
|
||||
const plugin = await loadPluginAsync(src);
|
||||
|
||||
if(!plugin) {
|
||||
console.error(`插件加载失败: ${src},该插件不存在!`);
|
||||
return;
|
||||
}
|
||||
|
||||
if(autoUse){
|
||||
this.use(plugin);
|
||||
}
|
||||
|
||||
plugins.push(plugin);
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册、配置并安装插件的方法
|
||||
* @param plugin 新注册插件
|
||||
* @param config 插件配置
|
||||
* @return PluginManager
|
||||
*/
|
||||
use(plugin: Plugin, config?: any): this {
|
||||
// 防止重复注册
|
||||
if (this.plugins.has(plugin.name)) return this;
|
||||
|
||||
// 注册插件
|
||||
plugin.install(config);
|
||||
this.plugins.set(plugin.name, plugin);
|
||||
useDispatchSignal("pluginInstall",plugin);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件实例
|
||||
* @param pluginName 插件名称
|
||||
*/
|
||||
getPlugin<T extends Plugin>(pluginName: string): T | undefined {
|
||||
return this.plugins.get(pluginName) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多个插件实例
|
||||
* @param pluginNames 插件名称数组
|
||||
*/
|
||||
getPlugins<T extends Plugin[]>(pluginNames: string[]): T | undefined {
|
||||
return pluginNames.map((pluginName) => this.getPlugin(pluginName)) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为数组对象
|
||||
* @param names 插件名称/插件名称数组
|
||||
*/
|
||||
getStrings(names: string | string[]): string[] {
|
||||
if (!Array.isArray(names)) {
|
||||
names = [names];
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历插件执行callback
|
||||
* @param pluginNames 插件名称/插件名称数组
|
||||
* @param callback 遍历执行的方法
|
||||
*/
|
||||
traverse(pluginNames: string | string[], callback: (data: { name: string, plugin: Plugin }) => void) {
|
||||
this.getStrings(pluginNames).forEach(name => {
|
||||
if (!this.plugins.has(name)) return;
|
||||
|
||||
callback({
|
||||
name,
|
||||
plugin: <Plugin>this.getPlugin(name)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行插件
|
||||
* @param pluginNames 插件名称/插件名称数组
|
||||
*/
|
||||
run(pluginNames: string | string[]) {
|
||||
this.traverse(pluginNames, ({plugin}) => {
|
||||
if (typeof plugin.run === 'function') {
|
||||
plugin.run();
|
||||
}
|
||||
})
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 卸载插件
|
||||
* @param pluginNames 插件名称/插件名称数组
|
||||
*/
|
||||
uninstall(pluginNames: string | string[]): this {
|
||||
this.traverse(pluginNames, ({name, plugin}) => {
|
||||
// 获取插件的卸载函数并执行
|
||||
if (typeof plugin.uninstall === 'function') {
|
||||
plugin.uninstall();
|
||||
}
|
||||
|
||||
this.plugins.delete(name);
|
||||
useDispatchSignal("pluginUninstall",name);
|
||||
|
||||
})
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @author ErSan
|
||||
* @email mlt131220@163.com
|
||||
* @date 2024/9/16 2:57
|
||||
* @description 插件加载
|
||||
*/
|
||||
import App from "@/core/app/App";
|
||||
|
||||
export async function loadPluginAsync(src: string): Promise<any> {
|
||||
try {
|
||||
// 动态导入插件模块
|
||||
const pluginModule = await import(/* @vite-ignore */src);
|
||||
|
||||
// 返回模块的默认导出
|
||||
return pluginModule.default;
|
||||
} catch (error:any) {
|
||||
App.log.error(`插件加载失败: ${error?.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user