196 lines
5.4 KiB
TypeScript
196 lines
5.4 KiB
TypeScript
import useVirtualPages from '@/hooks/useVirtualPages'
|
|
import VirtualDirectory, { VirtualFile } from './VirtualDirectory'
|
|
import { ShallowRef, shallowRef } from 'vue'
|
|
import { alertTipType, usePluginHooksType } from '@/types/type'
|
|
import VirtualPage, { VirtualPages } from './VirtualPage'
|
|
import useRootVDirectory from '@/hooks/useRootVDirectory'
|
|
|
|
export enum PluginGroup {
|
|
default = 'default',
|
|
mainMenu = 'mainMenu',
|
|
// 导入的时候会立即执行函数一次
|
|
immediately = 'immediately'
|
|
}
|
|
|
|
export interface registerComponentOption {
|
|
key: string
|
|
name: string
|
|
icon?: any
|
|
getComponent: () => Promise<any>
|
|
group?: PluginGroup[]
|
|
filter: (VDirectories: VirtualDirectory[], VFiles: VirtualFile[]) => boolean
|
|
disable?: boolean
|
|
exitConfirm?: boolean
|
|
// 若为true,则只会创建一个页面,当存在已创建页面则会直接将VFile和VDir加到curr里面
|
|
single?: boolean
|
|
priority?: number
|
|
}
|
|
|
|
export type Plugin = {
|
|
// 用于显示的名字
|
|
name: string
|
|
// 代表插件的icon
|
|
icon?: ShallowRef<any>
|
|
// 是否禁用插件
|
|
disable: boolean
|
|
// 插件所属的group,用于区分插件使用的场合
|
|
group: PluginGroup[]
|
|
// 插件优先级
|
|
priority: number
|
|
// 判断在未禁用时是否可以使用这个组件
|
|
// 使用组件即调用下面的func
|
|
filter: (
|
|
VDirectories: VirtualDirectory[],
|
|
VFiles: VirtualFile[],
|
|
VPages: VirtualPages
|
|
) => boolean
|
|
func: (
|
|
VDirectories: VirtualDirectory[],
|
|
VFiles: VirtualFile[],
|
|
hooks: usePluginHooksType,
|
|
...args: any[]
|
|
) => void
|
|
}
|
|
|
|
export default class PluginCenter {
|
|
constructor(globalAlertTip: alertTipType) {
|
|
this.pluginsMap = {}
|
|
this.globalAlertTip = globalAlertTip
|
|
}
|
|
pluginsMap: {
|
|
[key: string]: Plugin
|
|
}
|
|
|
|
globalAlertTip: alertTipType
|
|
|
|
register(key: string, plugin: Plugin) {
|
|
this.pluginsMap[key] = plugin
|
|
if (plugin.group.includes(PluginGroup.immediately)) {
|
|
this.usePlugin(key, [], [], this.usePluginHook)
|
|
}
|
|
}
|
|
|
|
deregister(key: string) {
|
|
delete this.pluginsMap[key]
|
|
}
|
|
|
|
/**
|
|
* 便捷地注册一个组件为插件,触发时直接用新页面打开,页面名为key
|
|
*/
|
|
registerComponent(option: registerComponentOption): void {
|
|
const {
|
|
key,
|
|
name,
|
|
getComponent,
|
|
icon,
|
|
filter,
|
|
group = [PluginGroup.default],
|
|
disable = false,
|
|
exitConfirm = false,
|
|
single = false,
|
|
priority = 0
|
|
} = option
|
|
let _component: any
|
|
const views = useVirtualPages()
|
|
this.register(key, {
|
|
name,
|
|
filter,
|
|
icon: shallowRef(icon),
|
|
group,
|
|
disable,
|
|
priority,
|
|
func: async (
|
|
VDirectories: VirtualDirectory[],
|
|
VFiles: VirtualFile[]
|
|
) => {
|
|
if (filter(VDirectories, VFiles) === false) {
|
|
return
|
|
}
|
|
|
|
if (_component === undefined) {
|
|
const setAlertTip = this.globalAlertTip(`加载 ${name} 插件中`)
|
|
_component = await getComponent()
|
|
setAlertTip &&
|
|
setAlertTip(`加载 ${name} 插件完成`, {
|
|
type: 'success',
|
|
timeout: 2000
|
|
})
|
|
}
|
|
const _findRes = views.find(_component) as VirtualPage[]
|
|
if (single && _findRes.length !== 0) {
|
|
const view = _findRes[0]
|
|
view.currentFiles = [...view.currentFiles, ...VFiles]
|
|
view.currentDirectories = [
|
|
...view.currentDirectories,
|
|
...VDirectories
|
|
]
|
|
} else {
|
|
views.push(_component, key, VDirectories, VFiles, {
|
|
VirtualPageOption: {
|
|
exitConfirm,
|
|
allowCopy: single === false
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
getUsablePlugin(
|
|
VDirectories: VirtualDirectory[],
|
|
VFiles: VirtualFile[],
|
|
option?: {
|
|
group?: PluginGroup[]
|
|
}
|
|
) {
|
|
const { group = [PluginGroup.default] } = option ?? {}
|
|
const usableList = []
|
|
const views = useVirtualPages()
|
|
for (let key of Object.keys(this.pluginsMap)) {
|
|
const _plugin = this.pluginsMap[key]
|
|
if (
|
|
!_plugin.disable &&
|
|
_plugin.group.filter((v) => group.includes(v)).length > 0 &&
|
|
_plugin.filter(VDirectories, VFiles, views)
|
|
) {
|
|
usableList.push(key)
|
|
}
|
|
}
|
|
const res = usableList.map((key) => ({
|
|
key,
|
|
...this.pluginsMap[key]
|
|
}))
|
|
res.sort((a, b) => b.priority - a.priority)
|
|
return res
|
|
}
|
|
|
|
get usePluginHook(): usePluginHooksType {
|
|
return {
|
|
globalAlertTip: this.globalAlertTip,
|
|
getViews: useVirtualPages,
|
|
getPluginCenter: () => this,
|
|
getRootVDirectory: () => useRootVDirectory()
|
|
}
|
|
}
|
|
|
|
// usePlugin(
|
|
// key: string,
|
|
// VDirectories?: VirtualDirectory[],
|
|
// VFiles?: VirtualFile[],
|
|
// ...args: any[]
|
|
// ): void
|
|
usePlugin(
|
|
key: string,
|
|
VDirectories?: VirtualDirectory[],
|
|
VFiles?: VirtualFile[],
|
|
...args: any[]
|
|
) {
|
|
this.pluginsMap[key].func(
|
|
VDirectories ?? [],
|
|
VFiles ?? [],
|
|
this.usePluginHook,
|
|
...args
|
|
)
|
|
}
|
|
}
|