feat: 使App.vue和VirtualDirectory解耦
This commit is contained in:
1 parent
6d550505a0
commit
4aba71d451
8 files changed
+162
-66
No files matched your search
+12
-25
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, provide, reactive, ref, shallowRef, useTemplateRef } from 'vue'
|
import { computed, onMounted, provide, ref, shallowRef, useTemplateRef } from 'vue'
|
||||||
import { NIcon, NScrollbar, NDropdown } from 'naive-ui'
|
import { NIcon, NScrollbar, NDropdown } from 'naive-ui'
|
||||||
import {
|
import {
|
||||||
EyeOffOutline,
|
EyeOffOutline,
|
||||||
@@ -10,7 +10,8 @@ import {
|
|||||||
QrCodeOutline,
|
QrCodeOutline,
|
||||||
ExtensionPuzzleOutline
|
ExtensionPuzzleOutline
|
||||||
} from '@vicons/ionicons5'
|
} from '@vicons/ionicons5'
|
||||||
import VirtualDirectory, { VirtualFile } from './class/VirtualDirectory'
|
import type VirtualDirectory from './class/VirtualDirectory'
|
||||||
|
import type { VirtualFile } from './class/VirtualDirectory'
|
||||||
import MiaoMask from './components/miaoMask.vue'
|
import MiaoMask from './components/miaoMask.vue'
|
||||||
import MiaoMessageProvider from './components/miaoAlertTipProvider.vue'
|
import MiaoMessageProvider from './components/miaoAlertTipProvider.vue'
|
||||||
import config from './config'
|
import config from './config'
|
||||||
@@ -20,6 +21,7 @@ import usePluginCenter from './hooks/usePluginCenter'
|
|||||||
import PluginCenter, { PluginGroup } from './class/PluginCenter'
|
import PluginCenter, { PluginGroup } from './class/PluginCenter'
|
||||||
import { renderIcon } from './hooks/miaoTools'
|
import { renderIcon } from './hooks/miaoTools'
|
||||||
import { DropdownMixedOption } from 'naive-ui/es/dropdown/src/interface'
|
import { DropdownMixedOption } from 'naive-ui/es/dropdown/src/interface'
|
||||||
|
import useRootVDirectory from './hooks/useRootVDirectory'
|
||||||
|
|
||||||
const { baseUrl } = config
|
const { baseUrl } = config
|
||||||
|
|
||||||
@@ -37,17 +39,7 @@ const messageProviderRef = useTemplateRef('messageProviderRef')
|
|||||||
const views = useVirtualPages()
|
const views = useVirtualPages()
|
||||||
let pluginCenter = ref<PluginCenter>()
|
let pluginCenter = ref<PluginCenter>()
|
||||||
|
|
||||||
const rootDirectory = reactive(
|
const rootDirectory = useRootVDirectory()
|
||||||
new VirtualDirectory({
|
|
||||||
name: '根目录',
|
|
||||||
stats: {
|
|
||||||
atimeMs: 0,
|
|
||||||
birthtimeMs: 0,
|
|
||||||
ctimeMs: 0,
|
|
||||||
mtimeMs: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
// component就是一个vue组件,类似于miaoDirectory
|
// component就是一个vue组件,类似于miaoDirectory
|
||||||
const createView = (
|
const createView = (
|
||||||
@@ -62,9 +54,6 @@ const createView = (
|
|||||||
|
|
||||||
const deleteView = (index: number) => {
|
const deleteView = (index: number) => {
|
||||||
views.deleteView(index)
|
views.deleteView(index)
|
||||||
if (views.length === 0) {
|
|
||||||
pluginCenter.value && pluginCenter.value.usePlugin('miaoDirectory', [rootDirectory], [])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击标题是隐藏其他标签或显示其他标签,还挺好用的
|
// 点击标题是隐藏其他标签或显示其他标签,还挺好用的
|
||||||
@@ -127,8 +116,6 @@ onMounted(async () => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
await init(messageProviderRef.value?.alertTip)
|
await init(messageProviderRef.value?.alertTip)
|
||||||
pluginCenter.value = usePluginCenter()
|
pluginCenter.value = usePluginCenter()
|
||||||
// console.log({ pluginCenter })
|
|
||||||
pluginCenter.value.usePlugin('miaoDirectory', [rootDirectory], [])
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -188,12 +175,12 @@ provide('rootDirectory', rootDirectory)
|
|||||||
</div>
|
</div>
|
||||||
<div class="view-container">
|
<div class="view-container">
|
||||||
<!-- <transition-group name="page"> -->
|
<!-- <transition-group name="page"> -->
|
||||||
<div class="view-container-item" v-for="(view, index) of views._views"
|
<div class="view-container-item" v-for="(view, index) of views._views"
|
||||||
:class="!view.visible ? 'view-container-item-hidden' : ''" :key="view.id">
|
:class="!view.visible ? 'view-container-item-hidden' : ''" :key="view.id">
|
||||||
<component :is="view.component" v-model:current-directories="view.currentDirectories"
|
<component :is="view.component" v-model:current-directories="view.currentDirectories"
|
||||||
v-model:current-files="view.currentFiles" :id="view.id" :color="view.color" :view="view"
|
v-model:current-files="view.currentFiles" :id="view.id" :color="view.color" :view="view"
|
||||||
:views="views" @exit="deleteView(index)"></component>
|
:views="views" @exit="deleteView(index)"></component>
|
||||||
</div>
|
</div>
|
||||||
<!-- </transition-group> -->
|
<!-- </transition-group> -->
|
||||||
</div>
|
</div>
|
||||||
</miao-message-provider>
|
</miao-message-provider>
|
||||||
@@ -210,7 +197,7 @@ $controller-height: 25px;
|
|||||||
$tag-width: 170px;
|
$tag-width: 170px;
|
||||||
|
|
||||||
.view {
|
.view {
|
||||||
|
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ import VirtualDirectory, { VirtualFile } from "./VirtualDirectory";
|
|||||||
import { ShallowRef, shallowRef } from "vue";
|
import { ShallowRef, shallowRef } from "vue";
|
||||||
import { alertTipType, usePluginHooksType } from "@/types/type";
|
import { alertTipType, usePluginHooksType } from "@/types/type";
|
||||||
import VirtualPage, { VirtualPages } from "./VirtualPage";
|
import VirtualPage, { VirtualPages } from "./VirtualPage";
|
||||||
|
import useRootVDirectory from "@/hooks/useRootVDirectory";
|
||||||
|
|
||||||
export enum PluginGroup {
|
export enum PluginGroup {
|
||||||
default = "default",
|
default = "default",
|
||||||
mainMenu = "mainMenu"
|
mainMenu = "mainMenu",
|
||||||
|
// 导入的时候会立即执行函数一次
|
||||||
|
immediately = "immediately"
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface registerComponentOption {
|
export interface registerComponentOption {
|
||||||
@@ -53,6 +56,13 @@ export default class PluginCenter {
|
|||||||
|
|
||||||
register(key: string, plugin: Plugin) {
|
register(key: string, plugin: Plugin) {
|
||||||
this.pluginsMap[key] = plugin;
|
this.pluginsMap[key] = plugin;
|
||||||
|
if (plugin.group.includes(PluginGroup.immediately)) {
|
||||||
|
this.usePlugin(key, [], [], this.usePluginHook)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deregister(key: string) {
|
||||||
|
delete this.pluginsMap[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,18 +134,21 @@ export default class PluginCenter {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
usePlugin(key: string, VDirectories?: VirtualDirectory[], VFiles?: VirtualFile[], ...args: any[]): void;
|
get usePluginHook(): usePluginHooksType {
|
||||||
// usePlugin(key: string, VPages: VirtualPages, ...args: any[]) : void
|
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[]) {
|
usePlugin(key: string, VDirectories?: VirtualDirectory[], VFiles?: VirtualFile[], ...args: any[]) {
|
||||||
this.pluginsMap[key].func(
|
this.pluginsMap[key].func(
|
||||||
VDirectories ?? [],
|
VDirectories ?? [],
|
||||||
VFiles ?? [],
|
VFiles ?? [],
|
||||||
{
|
this.usePluginHook,
|
||||||
globalAlertTip: this.globalAlertTip,
|
|
||||||
getViews: useVirtualPages,
|
|
||||||
getPluginCenter: () => this
|
|
||||||
},
|
|
||||||
...args
|
...args
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,25 +6,19 @@ const initPlugin = async (globalAlertTip: alertTipType) => {
|
|||||||
initPluginCenter(globalAlertTip);
|
initPluginCenter(globalAlertTip);
|
||||||
const modulesFiles = import.meta.glob("@/plugins/**/export*.ts", { eager: true });
|
const modulesFiles = import.meta.glob("@/plugins/**/export*.ts", { eager: true });
|
||||||
const pluginCenter = usePluginCenter();
|
const pluginCenter = usePluginCenter();
|
||||||
const promiseArray = [];
|
|
||||||
for (let pluginConfig of Object.values(modulesFiles)) {
|
for (let pluginConfig of Object.values(modulesFiles)) {
|
||||||
promiseArray.push(
|
const _config = pluginConfig as {
|
||||||
new Promise(async resolve => {
|
default: registerComponentOption | Plugin;
|
||||||
const _config = pluginConfig as {
|
type: PluginExportType;
|
||||||
default: registerComponentOption | Plugin;
|
key?: string;
|
||||||
type: PluginExportType;
|
};
|
||||||
key?: string;
|
const { type, key } = _config;
|
||||||
};
|
if (type === PluginExportType.component) {
|
||||||
const { type, key } = _config;
|
pluginCenter.registerComponent(_config.default as registerComponentOption);
|
||||||
if (type === PluginExportType.component) {
|
} else if (type === PluginExportType.default) {
|
||||||
resolve(pluginCenter.registerComponent(_config.default as registerComponentOption));
|
pluginCenter.register(key as string, _config.default as Plugin);
|
||||||
} else if (type === PluginExportType.default) {
|
}
|
||||||
resolve(pluginCenter.register(key as string, _config.default as Plugin));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
await Promise.all(promiseArray);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default initPlugin;
|
export default initPlugin;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import VirtualDirectory from "@/class/VirtualDirectory";
|
||||||
|
import { reactive } from "vue";
|
||||||
|
|
||||||
|
const root = reactive(
|
||||||
|
new VirtualDirectory({
|
||||||
|
name: '根目录',
|
||||||
|
stats: {
|
||||||
|
atimeMs: 0,
|
||||||
|
birthtimeMs: 0,
|
||||||
|
ctimeMs: 0,
|
||||||
|
mtimeMs: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
export default function useRootVDirectory() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { Plugin, PluginGroup } from "@/class/PluginCenter";
|
||||||
|
import { PluginExportType } from "@/types/type";
|
||||||
|
import { watchEffect } from "vue";
|
||||||
|
|
||||||
|
const pluginConfig: Plugin = {
|
||||||
|
name: "初始化完成之后打开miaoDirectory",
|
||||||
|
filter: () => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
disable: false,
|
||||||
|
group: [PluginGroup.immediately],
|
||||||
|
func: (_, __, hooks) => {
|
||||||
|
const { getPluginCenter, getRootVDirectory, getViews } = hooks
|
||||||
|
const views = getViews();
|
||||||
|
const pc = getPluginCenter();
|
||||||
|
const root = getRootVDirectory();
|
||||||
|
setTimeout(() => {
|
||||||
|
// if (views.length === 0) {
|
||||||
|
// pc.usePlugin('miaoDirectory', [root])
|
||||||
|
// }
|
||||||
|
pc.deregister('miaoDirectory_onInit')
|
||||||
|
watchEffect(() => {
|
||||||
|
if(views.length === 0) {
|
||||||
|
pc.usePlugin('miaoDirectory', [root])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
priority: -1
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginConfig;
|
||||||
|
|
||||||
|
export const type = PluginExportType.default;
|
||||||
|
|
||||||
|
export const key = "miaoDirectory_onInit";
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import type { Plugin, registerComponentOption } from "@/class/PluginCenter";
|
||||||
|
|
||||||
|
export function checkNormalPlugin(obj: any): obj is Plugin {
|
||||||
|
return (
|
||||||
|
typeof obj === "object" &&
|
||||||
|
obj!== null &&
|
||||||
|
typeof obj.name === "string" &&
|
||||||
|
(obj.icon === undefined || typeof obj.icon === "object") &&
|
||||||
|
typeof obj.disable === "boolean" &&
|
||||||
|
Array.isArray(obj.group) &&
|
||||||
|
obj.group.every((group: any) => typeof group === "string") &&
|
||||||
|
typeof obj.priority === "number" &&
|
||||||
|
typeof obj.filter === "function" &&
|
||||||
|
typeof obj.func === "function"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function checkComponentPlugin(
|
||||||
|
obj: any
|
||||||
|
): obj is registerComponentOption {
|
||||||
|
return (
|
||||||
|
typeof obj === "object" &&
|
||||||
|
obj!== null &&
|
||||||
|
typeof obj.key === "string" &&
|
||||||
|
typeof obj.name === "string" &&
|
||||||
|
(obj.icon === undefined || typeof obj.icon === "object") &&
|
||||||
|
typeof obj.getComponent === "function" &&
|
||||||
|
((obj.group === undefined) || (Array.isArray(obj.group) && obj.group.every((item: any) => typeof item === "string"))) &&
|
||||||
|
typeof obj.filter === "function" &&
|
||||||
|
(obj.disable === undefined || typeof obj.disable === "boolean") &&
|
||||||
|
(obj.exitConfirm === undefined || typeof obj.exitConfirm === "boolean") &&
|
||||||
|
(obj.single === undefined || typeof obj.single === "boolean") &&
|
||||||
|
(obj.priority === undefined || typeof obj.priority === "number")
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,24 +2,35 @@ import VirtualDirectory, { VirtualFile } from "@/class/VirtualDirectory";
|
|||||||
// import useMiaoFetchApi from "@/hooks/useMiaoFetchApi";
|
// import useMiaoFetchApi from "@/hooks/useMiaoFetchApi";
|
||||||
import { PluginExportType, usePluginHooksType } from "@/types/type";
|
import { PluginExportType, usePluginHooksType } from "@/types/type";
|
||||||
import type { Plugin, registerComponentOption } from "@/class/PluginCenter";
|
import type { Plugin, registerComponentOption } from "@/class/PluginCenter";
|
||||||
|
import { checkComponentPlugin, checkNormalPlugin } from "./checkPluginAvailable";
|
||||||
|
|
||||||
// const miaoFetchApi = useMiaoFetchApi()
|
// const miaoFetchApi = useMiaoFetchApi()
|
||||||
|
|
||||||
export default async function registerExternalPlugin(_VDirectories: VirtualDirectory[], VFiles: VirtualFile[], hooks: usePluginHooksType) {
|
export default async function registerExternalPlugin(_VDirectories: VirtualDirectory[], VFiles: VirtualFile[], hooks: usePluginHooksType) {
|
||||||
const targetPluginVFile = VFiles[0] as VirtualFile
|
try {
|
||||||
// const pluginU8iArr = await miaoFetchApi.getFile(targetPluginVFile).response
|
const targetPluginVFile = VFiles[0] as VirtualFile
|
||||||
// const pluginText = new TextDecoder().decode(pluginU8iArr)
|
const plugin = await import(/* @vite-ignore */ targetPluginVFile.url) as {
|
||||||
// const plugin = await import(/* @vite-ignore */'')
|
default: registerComponentOption | Plugin;
|
||||||
const plugin = await import(/* @vite-ignore */ targetPluginVFile.url) as {
|
type: PluginExportType;
|
||||||
default: registerComponentOption | Plugin;
|
key?: string;
|
||||||
type: PluginExportType;
|
}
|
||||||
key?: string;
|
const pc = hooks.getPluginCenter()
|
||||||
}
|
if (plugin.type === PluginExportType.default) {
|
||||||
// console.log(plugin)
|
if (checkNormalPlugin(plugin.default) === false) {
|
||||||
const pc = hooks.getPluginCenter()
|
throw('插件不合法')
|
||||||
if(plugin.type === PluginExportType.default) {
|
}
|
||||||
pc.register(`${Math.random()}`, plugin.default as Plugin)
|
pc.register(plugin.key ?? `${Math.random()}`, plugin.default as Plugin)
|
||||||
} else {
|
} else {
|
||||||
pc.registerComponent(plugin.default as registerComponentOption)
|
if (checkComponentPlugin(plugin.default) === false) {
|
||||||
|
throw('插件不合法')
|
||||||
|
}
|
||||||
|
pc.registerComponent(plugin.default as registerComponentOption)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
hooks.globalAlertTip('导入外部插件失败', {
|
||||||
|
type: 'error',
|
||||||
|
timeout: 3000
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-1
@@ -1,5 +1,6 @@
|
|||||||
import PluginCenter from "@/class/PluginCenter";
|
import PluginCenter from "@/class/PluginCenter";
|
||||||
import { VirtualPages } from "@/class/VirtualPage";
|
import VirtualDirectory from "@/class/VirtualDirectory";
|
||||||
|
import type { VirtualPages } from "@/class/VirtualPage";
|
||||||
|
|
||||||
export type stats = {
|
export type stats = {
|
||||||
atimeMs: number; // 上次访问时间(毫秒)
|
atimeMs: number; // 上次访问时间(毫秒)
|
||||||
@@ -41,6 +42,7 @@ export interface usePluginHooksType {
|
|||||||
globalAlertTip: alertTipType;
|
globalAlertTip: alertTipType;
|
||||||
getViews: () => VirtualPages;
|
getViews: () => VirtualPages;
|
||||||
getPluginCenter: () => PluginCenter;
|
getPluginCenter: () => PluginCenter;
|
||||||
|
getRootVDirectory: () => VirtualDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Equals<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
|
export type Equals<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
|
||||||
Reference in new issue
Block a user