mirror of https://github.com/halo-dev/halo-admin
feat: add plugin loading status panel
Signed-off-by: Ryan Wang <i@ryanc.cc>pull/591/head
parent
2a1be5603d
commit
f99deaec83
|
@ -26,6 +26,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@formkit/addons": "1.0.0-beta.9",
|
||||
"@formkit/auto-animate": "1.0.0-beta.1",
|
||||
"@formkit/core": "1.0.0-beta.9",
|
||||
"@formkit/i18n": "1.0.0-beta.9",
|
||||
"@formkit/inputs": "1.0.0-beta.9",
|
||||
|
|
|
@ -6,6 +6,7 @@ importers:
|
|||
specifiers:
|
||||
'@changesets/cli': ^2.24.0
|
||||
'@formkit/addons': 1.0.0-beta.9
|
||||
'@formkit/auto-animate': 1.0.0-beta.1
|
||||
'@formkit/core': 1.0.0-beta.9
|
||||
'@formkit/i18n': 1.0.0-beta.9
|
||||
'@formkit/inputs': 1.0.0-beta.9
|
||||
|
@ -75,6 +76,7 @@ importers:
|
|||
yaml: ^2.1.1
|
||||
dependencies:
|
||||
'@formkit/addons': 1.0.0-beta.9_vue@3.2.37
|
||||
'@formkit/auto-animate': 1.0.0-beta.1_vue@3.2.37
|
||||
'@formkit/core': 1.0.0-beta.9
|
||||
'@formkit/i18n': 1.0.0-beta.9
|
||||
'@formkit/inputs': 1.0.0-beta.9
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<script lang="ts" setup>
|
||||
import type { PropType } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import AutoAnimate from "@formkit/auto-animate";
|
||||
import type { LoadingMessage } from "@/loading-message";
|
||||
|
||||
defineProps({
|
||||
messages: {
|
||||
type: Array as PropType<LoadingMessage[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const list = ref<HTMLElement>();
|
||||
|
||||
onMounted(() => {
|
||||
if (list.value) {
|
||||
AutoAnimate(list.value, {});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div id="loader"></div>
|
||||
<div class="absolute right-0 bottom-10 w-96">
|
||||
<ul ref="list" class="space-y-2 text-gray-500">
|
||||
<li
|
||||
v-for="(message, index) in messages"
|
||||
:key="index"
|
||||
:class="{
|
||||
'text-red-600': message.type === 'error',
|
||||
}"
|
||||
>
|
||||
{{ message.message }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
body {
|
||||
height: 100%;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
#loader {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
border: solid 3px #e5e5e5;
|
||||
border-top-color: #333;
|
||||
border-radius: 50%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
animation: spin 0.6s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,4 @@
|
|||
export interface LoadingMessage {
|
||||
type: "error" | "info";
|
||||
message: string;
|
||||
}
|
76
src/main.ts
76
src/main.ts
|
@ -1,7 +1,8 @@
|
|||
import type { DirectiveBinding } from "vue";
|
||||
import { createApp } from "vue";
|
||||
import { createApp, ref } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import App from "./App.vue";
|
||||
import LoadingMessageContainer from "./LoadingMessageContainer.vue";
|
||||
import router from "./router";
|
||||
import type {
|
||||
MenuGroupType,
|
||||
|
@ -10,10 +11,10 @@ import type {
|
|||
} from "@halo-dev/admin-shared";
|
||||
import { apiClient, setApiUrl } from "@halo-dev/admin-shared";
|
||||
import { menus, minimenus, registerMenu } from "./router/menus.config";
|
||||
import type { LoadingMessage } from "@/loading-message";
|
||||
// setup
|
||||
import "./setup/setupStyles";
|
||||
import { setupComponents } from "./setup/setupComponents";
|
||||
|
||||
// core modules
|
||||
import { coreModules } from "./modules";
|
||||
import { useScriptTag } from "@vueuse/core";
|
||||
|
@ -22,6 +23,20 @@ import type { User } from "@halo-dev/api-client";
|
|||
import { hasPermission } from "@/utils/permission";
|
||||
import { useRoleStore } from "@/stores/role";
|
||||
|
||||
// TODO 实验性
|
||||
const messages = ref<LoadingMessage[]>([]);
|
||||
const messageContainerApp = createApp({
|
||||
data: () => ({
|
||||
messages: messages,
|
||||
}),
|
||||
components: {
|
||||
LoadingMessageContainer,
|
||||
},
|
||||
template: `
|
||||
<LoadingMessageContainer :messages="messages"/>`,
|
||||
});
|
||||
messageContainerApp.mount("#app");
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
setupComponents(app);
|
||||
|
@ -67,7 +82,16 @@ function registerModule(pluginModule: Plugin) {
|
|||
}
|
||||
|
||||
function loadCoreModules() {
|
||||
const coreLoadStartTime = Date.now();
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: "Loading core modules...",
|
||||
});
|
||||
coreModules.forEach(registerModule);
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: `All core modules loaded(${Date.now() - coreLoadStartTime}ms)`,
|
||||
});
|
||||
}
|
||||
|
||||
const pluginStore = usePluginStore();
|
||||
|
@ -103,6 +127,11 @@ function loadStyle(href: string) {
|
|||
const pluginErrorMessages: Array<string> = [];
|
||||
|
||||
async function loadPluginModules() {
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: "Loading plugins...",
|
||||
});
|
||||
|
||||
const { data } =
|
||||
await apiClient.extension.plugin.listpluginHaloRunV1alpha1Plugin();
|
||||
|
||||
|
@ -119,10 +148,26 @@ async function loadPluginModules() {
|
|||
|
||||
if (entry) {
|
||||
try {
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: `${plugin.metadata.name}: Loading entry module...`,
|
||||
});
|
||||
|
||||
const { load } = useScriptTag(
|
||||
`${import.meta.env.VITE_API_URL}${plugin.status?.entry}`
|
||||
);
|
||||
|
||||
const entryLoadStartTime = Date.now();
|
||||
|
||||
await load();
|
||||
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: `${plugin.metadata.name}: Loaded entry module(${
|
||||
Date.now() - entryLoadStartTime
|
||||
}ms)`,
|
||||
});
|
||||
|
||||
const pluginModule = window[plugin.metadata.name];
|
||||
|
||||
if (pluginModule) {
|
||||
|
@ -132,6 +177,10 @@ async function loadPluginModules() {
|
|||
}
|
||||
} catch (e) {
|
||||
const message = `${plugin.metadata.name}: Failed load plugin entry module`;
|
||||
messages.value.push({
|
||||
type: "error",
|
||||
message,
|
||||
});
|
||||
console.error(message, e);
|
||||
pluginErrorMessages.push(message);
|
||||
}
|
||||
|
@ -139,9 +188,26 @@ async function loadPluginModules() {
|
|||
|
||||
if (stylesheet) {
|
||||
try {
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: `${plugin.metadata.name}: Loading stylesheet...`,
|
||||
});
|
||||
const styleLoadStartTime = Date.now();
|
||||
|
||||
await loadStyle(`${import.meta.env.VITE_API_URL}${stylesheet}`);
|
||||
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: `${plugin.metadata.name}: Loaded stylesheet(${
|
||||
Date.now() - styleLoadStartTime
|
||||
}ms)`,
|
||||
});
|
||||
} catch (e) {
|
||||
const message = `${plugin.metadata.name}: Failed load plugin stylesheet`;
|
||||
messages.value.push({
|
||||
type: "error",
|
||||
message,
|
||||
});
|
||||
console.error(message, e);
|
||||
pluginErrorMessages.push(message);
|
||||
}
|
||||
|
@ -150,6 +216,11 @@ async function loadPluginModules() {
|
|||
pluginStore.registerPlugin(plugin);
|
||||
}
|
||||
|
||||
messages.value.push({
|
||||
type: "info",
|
||||
message: "All plugins loaded",
|
||||
});
|
||||
|
||||
if (pluginErrorMessages.length > 0) {
|
||||
alert(pluginErrorMessages.join("\n"));
|
||||
}
|
||||
|
@ -199,6 +270,7 @@ async function initApp() {
|
|||
await loadCurrentUser();
|
||||
app.provide<MenuGroupType[]>("menus", menus);
|
||||
app.provide<MenuItemType[]>("minimenus", minimenus);
|
||||
messageContainerApp.unmount();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
|
|
Loading…
Reference in New Issue