diff --git a/package.json b/package.json
index eff99c19..1428a303 100644
--- a/package.json
+++ b/package.json
@@ -26,8 +26,8 @@
],
"dependencies": {
"@halo-dev/admin-api": "^1.1.0",
- "@halo-dev/components": "workspace:*",
"@halo-dev/admin-shared": "workspace:*",
+ "@halo-dev/components": "workspace:*",
"@vueuse/core": "^8.6.0",
"filepond": "^4.30.4",
"filepond-plugin-image-preview": "^4.6.11",
@@ -72,6 +72,7 @@
"vite": "^2.9.12",
"vite-compression-plugin": "^0.0.4",
"vite-plugin-pwa": "^0.12.0",
+ "vite-plugin-vue-setup-extend": "^0.4.0",
"vitest": "^0.15.1",
"vue-tsc": "^0.34.17"
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 54484163..d134c54a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,6 +45,7 @@ importers:
vite: ^2.9.12
vite-compression-plugin: ^0.0.4
vite-plugin-pwa: ^0.12.0
+ vite-plugin-vue-setup-extend: ^0.4.0
vitest: ^0.15.1
vue: ^3.2.37
vue-filepond: ^7.0.3
@@ -98,6 +99,7 @@ importers:
vite: 2.9.12_sass@1.52.3
vite-compression-plugin: 0.0.4
vite-plugin-pwa: 0.12.0_vite@2.9.12
+ vite-plugin-vue-setup-extend: 0.4.0_vite@2.9.12
vitest: 0.15.1_fiumxgyk2tfafw3c4rsaverrnm
vue-tsc: 0.34.17_typescript@4.7.3
@@ -6783,6 +6785,16 @@ packages:
- supports-color
dev: true
+ /vite-plugin-vue-setup-extend/0.4.0_vite@2.9.12:
+ resolution: {integrity: sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==}
+ peerDependencies:
+ vite: '>=2.0.0'
+ dependencies:
+ '@vue/compiler-sfc': 3.2.37
+ magic-string: 0.25.9
+ vite: 2.9.12_sass@1.52.3
+ dev: true
+
/vite/2.9.12:
resolution: {integrity: sha512-suxC36dQo9Rq1qMB2qiRorNJtJAdxguu5TMvBHOc/F370KvqAe9t48vYp+/TbPKRNrMh/J55tOUmkuIqstZaew==}
engines: {node: '>=12.2.0'}
diff --git a/src/main.ts b/src/main.ts
index 35b236cb..530f9a71 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -2,16 +2,78 @@ import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
-
-const app = createApp(App);
-
+import type { Plugin } from "@halo-dev/admin-shared";
// setup
import "./setup/setupStyles";
import { setupComponents } from "./setup/setupComponents";
+import { registerMenu } from "@/router/menus.config";
+
+// modules
+import dashboardModule from "./modules/dashboard/module";
+import postModule from "./modules/contents/posts/module";
+import sheetModule from "./modules/contents/sheets/module";
+import commentModule from "./modules/contents/comments/module";
+import attachmentModule from "./modules/contents/attachments/module";
+import themeModule from "./modules/interface/themes/module";
+import menuModule from "./modules/interface/menus/module";
+import pluginModule from "./modules/system/plugins/module";
+import userModule from "./modules/system/users/module";
+import roleModule from "./modules/system/roles/module";
+import settingModule from "./modules/system/settings/module";
+
+const app = createApp(App);
setupComponents(app);
app.use(createPinia());
-app.use(router);
-app.mount("#app");
+async function registerModule(pluginModule: Plugin) {
+ if (pluginModule.components) {
+ for (const component of pluginModule.components) {
+ component.name && app.component(component.name, component);
+ }
+ }
+
+ if (pluginModule.routes) {
+ for (const route of pluginModule.routes) {
+ router.addRoute(route);
+ }
+ }
+
+ if (pluginModule.menus) {
+ for (const group of pluginModule.menus) {
+ for (const menu of group.items) {
+ registerMenu(group.name, menu);
+ }
+ }
+ }
+}
+
+function loadCoreModules() {
+ [
+ dashboardModule,
+ postModule,
+ sheetModule,
+ commentModule,
+ attachmentModule,
+ themeModule,
+ menuModule,
+ pluginModule,
+ userModule,
+ roleModule,
+ settingModule,
+ ].forEach(registerModule);
+}
+
+function loadPluginModules() {
+ // TODO: load plugin modules
+}
+
+initApp();
+
+async function initApp() {
+ loadCoreModules();
+ loadPluginModules();
+ app.use(router);
+ app.mount("#app");
+}
diff --git a/src/modules/contents/attachments/module.ts b/src/modules/contents/attachments/module.ts
new file mode 100644
index 00000000..2e9c1bee
--- /dev/null
+++ b/src/modules/contents/attachments/module.ts
@@ -0,0 +1,36 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout } from "@/layouts";
+import AttachmentList from "./AttachmentList.vue";
+import { IconFolder } from "@halo-dev/components";
+
+const attachmentModule: Plugin = {
+ name: "attachmentModule",
+ components: [],
+ routes: [
+ {
+ path: "/attachments",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Attachments",
+ component: AttachmentList,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "内容",
+ items: [
+ {
+ name: "附件",
+ path: "/attachments",
+ icon: IconFolder,
+ },
+ ],
+ },
+ ],
+};
+
+export default attachmentModule;
diff --git a/src/modules/contents/comments/module.ts b/src/modules/contents/comments/module.ts
new file mode 100644
index 00000000..c70d8a29
--- /dev/null
+++ b/src/modules/contents/comments/module.ts
@@ -0,0 +1,36 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout } from "@/layouts";
+import { IconMessage } from "@halo-dev/components";
+import CommentList from "./CommentList.vue";
+
+const commentModule: Plugin = {
+ name: "commentModule",
+ components: [],
+ routes: [
+ {
+ path: "/comments",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Comments",
+ component: CommentList,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "内容",
+ items: [
+ {
+ name: "评论",
+ path: "/comments",
+ icon: IconMessage,
+ },
+ ],
+ },
+ ],
+};
+
+export default commentModule;
diff --git a/src/modules/contents/posts/module.ts b/src/modules/contents/posts/module.ts
new file mode 100644
index 00000000..7ddf8f48
--- /dev/null
+++ b/src/modules/contents/posts/module.ts
@@ -0,0 +1,66 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout, BlankLayout } from "@/layouts";
+import { IconBookRead } from "@halo-dev/components";
+import PostList from "./PostList.vue";
+import PostEditor from "./PostEditor.vue";
+import CategoryList from "./categories/CategoryList.vue";
+import TagList from "./tags/TagList.vue";
+
+const postModule: Plugin = {
+ name: "postModule",
+ components: [],
+ routes: [
+ {
+ path: "/posts",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Posts",
+ component: PostList,
+ },
+ {
+ path: "editor",
+ name: "PostEditor",
+ component: PostEditor,
+ },
+ {
+ path: "categories",
+ component: BlankLayout,
+ children: [
+ {
+ path: "",
+ name: "Categories",
+ component: CategoryList,
+ },
+ ],
+ },
+ {
+ path: "tags",
+ component: BlankLayout,
+ children: [
+ {
+ path: "",
+ name: "Tags",
+ component: TagList,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "内容",
+ items: [
+ {
+ name: "文章",
+ path: "/posts",
+ icon: IconBookRead,
+ },
+ ],
+ },
+ ],
+};
+
+export default postModule;
diff --git a/src/modules/contents/sheets/module.ts b/src/modules/contents/sheets/module.ts
new file mode 100644
index 00000000..36eb1e42
--- /dev/null
+++ b/src/modules/contents/sheets/module.ts
@@ -0,0 +1,36 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout } from "@/layouts";
+import SheetList from "./SheetList.vue";
+import { IconPages } from "@halo-dev/components";
+
+const sheetModule: Plugin = {
+ name: "sheetModule",
+ components: [],
+ routes: [
+ {
+ path: "/sheets",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Sheets",
+ component: SheetList,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "内容",
+ items: [
+ {
+ name: "页面",
+ path: "/sheets",
+ icon: IconPages,
+ },
+ ],
+ },
+ ],
+};
+
+export default sheetModule;
diff --git a/src/modules/dashboard/module.ts b/src/modules/dashboard/module.ts
new file mode 100644
index 00000000..f48ac183
--- /dev/null
+++ b/src/modules/dashboard/module.ts
@@ -0,0 +1,55 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout } from "@/layouts";
+import Dashboard from "./Dashboard.vue";
+import { IconDashboard } from "@halo-dev/components";
+
+import CommentStatsWidget from "./widgets/CommentStatsWidget.vue";
+import JournalPublishWidget from "./widgets/JournalPublishWidget.vue";
+import PostStatsWidget from "./widgets/PostStatsWidget.vue";
+import QuickLinkWidget from "./widgets/QuickLinkWidget.vue";
+import RecentLoginWidget from "./widgets/RecentLoginWidget.vue";
+import RecentPublishedWidget from "./widgets/RecentPublishedWidget.vue";
+import UserStatsWidget from "./widgets/UserStatsWidget.vue";
+import ViewsStatsWidget from "./widgets/ViewsStatsWidget.vue";
+
+const dashboardModule: Plugin = {
+ name: "dashboardModule",
+ components: [
+ CommentStatsWidget,
+ JournalPublishWidget,
+ PostStatsWidget,
+ QuickLinkWidget,
+ RecentLoginWidget,
+ RecentPublishedWidget,
+ UserStatsWidget,
+ ViewsStatsWidget,
+ ],
+ routes: [
+ {
+ path: "/",
+ component: BasicLayout,
+ redirect: "/dashboard",
+ children: [
+ {
+ path: "dashboard",
+ name: "Dashboard",
+ component: Dashboard,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "",
+ items: [
+ {
+ name: "仪表盘",
+ path: "/dashboard",
+ icon: IconDashboard,
+ },
+ ],
+ },
+ ],
+};
+
+export default dashboardModule;
diff --git a/src/modules/dashboard/widgets/CommentStatsWidget.vue b/src/modules/dashboard/widgets/CommentStatsWidget.vue
index 8e920b14..634aac41 100644
--- a/src/modules/dashboard/widgets/CommentStatsWidget.vue
+++ b/src/modules/dashboard/widgets/CommentStatsWidget.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/dashboard/widgets/JournalPublishWidget.vue b/src/modules/dashboard/widgets/JournalPublishWidget.vue
index 6dcf27f1..e49ed8ad 100644
--- a/src/modules/dashboard/widgets/JournalPublishWidget.vue
+++ b/src/modules/dashboard/widgets/JournalPublishWidget.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/dashboard/widgets/PostStatsWidget.vue b/src/modules/dashboard/widgets/PostStatsWidget.vue
index 9b6b5b25..6b0dc4bb 100644
--- a/src/modules/dashboard/widgets/PostStatsWidget.vue
+++ b/src/modules/dashboard/widgets/PostStatsWidget.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/dashboard/widgets/QuickLinkWidget.vue b/src/modules/dashboard/widgets/QuickLinkWidget.vue
index 3d80ab59..fe6e5d6f 100644
--- a/src/modules/dashboard/widgets/QuickLinkWidget.vue
+++ b/src/modules/dashboard/widgets/QuickLinkWidget.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/dashboard/widgets/RecentPublishedWidget.vue b/src/modules/dashboard/widgets/RecentPublishedWidget.vue
index a7fd6ffe..0769b6ce 100644
--- a/src/modules/dashboard/widgets/RecentPublishedWidget.vue
+++ b/src/modules/dashboard/widgets/RecentPublishedWidget.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/dashboard/widgets/UserStatsWidget.vue b/src/modules/dashboard/widgets/UserStatsWidget.vue
index a7fae1d4..e283cd76 100644
--- a/src/modules/dashboard/widgets/UserStatsWidget.vue
+++ b/src/modules/dashboard/widgets/UserStatsWidget.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/dashboard/widgets/ViewsStatsWidget.vue b/src/modules/dashboard/widgets/ViewsStatsWidget.vue
index 88e34130..23dc7214 100644
--- a/src/modules/dashboard/widgets/ViewsStatsWidget.vue
+++ b/src/modules/dashboard/widgets/ViewsStatsWidget.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/modules/dashboard/widgets/index.ts b/src/modules/dashboard/widgets/index.ts
deleted file mode 100644
index 2293a71a..00000000
--- a/src/modules/dashboard/widgets/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { App } from "vue";
-
-import PostStatsWidget from "./PostStatsWidget.vue";
-import UserStatsWidget from "./UserStatsWidget.vue";
-import CommentStatsWidget from "./CommentStatsWidget.vue";
-import ViewsStatsWidget from "./ViewsStatsWidget.vue";
-import RecentLoginWidget from "./RecentLoginWidget.vue";
-import RecentPublishedWidget from "./RecentPublishedWidget.vue";
-import JournalPublishWidget from "./JournalPublishWidget.vue";
-import QuickLinkWidget from "./QuickLinkWidget.vue";
-
-const install = (app: App) => {
- app.component("PostStatsWidget", PostStatsWidget);
- app.component("UserStatsWidget", UserStatsWidget);
- app.component("CommentStatsWidget", CommentStatsWidget);
- app.component("ViewsStatsWidget", ViewsStatsWidget);
- app.component("RecentLoginWidget", RecentLoginWidget);
- app.component("RecentPublishedWidget", RecentPublishedWidget);
- app.component("JournalPublishWidget", JournalPublishWidget);
- app.component("QuickLinkWidget", QuickLinkWidget);
-};
-
-export default install;
diff --git a/src/modules/interface/menus/module.ts b/src/modules/interface/menus/module.ts
new file mode 100644
index 00000000..a463d5c8
--- /dev/null
+++ b/src/modules/interface/menus/module.ts
@@ -0,0 +1,36 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout } from "@/layouts";
+import MenuList from "./MenuList.vue";
+import { IconListSettings } from "@halo-dev/components";
+
+const menuModule: Plugin = {
+ name: "menuModule",
+ components: [],
+ routes: [
+ {
+ path: "/menus",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Menus",
+ component: MenuList,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "外观",
+ items: [
+ {
+ name: "菜单",
+ path: "/menus",
+ icon: IconListSettings,
+ },
+ ],
+ },
+ ],
+};
+
+export default menuModule;
diff --git a/src/modules/interface/themes/module.ts b/src/modules/interface/themes/module.ts
new file mode 100644
index 00000000..09493b1d
--- /dev/null
+++ b/src/modules/interface/themes/module.ts
@@ -0,0 +1,48 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout, BlankLayout } from "@/layouts";
+import ThemeDetail from "./ThemeDetail.vue";
+import Visual from "./Visual.vue";
+import { IconPalette } from "@halo-dev/components";
+
+const themeModule: Plugin = {
+ name: "themeModule",
+ components: [],
+ routes: [
+ {
+ path: "/theme",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Theme",
+ component: ThemeDetail,
+ },
+ ],
+ },
+ {
+ path: "/theme/visual",
+ component: BlankLayout,
+ children: [
+ {
+ path: "",
+ name: "ThemeVisual",
+ component: Visual,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "外观",
+ items: [
+ {
+ name: "主题",
+ path: "/theme",
+ icon: IconPalette,
+ },
+ ],
+ },
+ ],
+};
+
+export default themeModule;
diff --git a/src/modules/system/plugins/module.ts b/src/modules/system/plugins/module.ts
new file mode 100644
index 00000000..0844fcf6
--- /dev/null
+++ b/src/modules/system/plugins/module.ts
@@ -0,0 +1,42 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout } from "@/layouts";
+import PluginList from "./PluginList.vue";
+import PluginDetail from "./PluginDetail.vue";
+import { IconPlug } from "@halo-dev/components";
+
+const pluginModule: Plugin = {
+ name: "pluginModule",
+ components: [],
+ routes: [
+ {
+ path: "/plugins",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Plugins",
+ component: PluginList,
+ },
+ {
+ path: ":id",
+ name: "PluginDetail",
+ component: PluginDetail,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "系统",
+ items: [
+ {
+ name: "插件",
+ path: "/plugins",
+ icon: IconPlug,
+ },
+ ],
+ },
+ ],
+};
+
+export default pluginModule;
diff --git a/src/modules/system/roles/module.ts b/src/modules/system/roles/module.ts
new file mode 100644
index 00000000..cb5ba440
--- /dev/null
+++ b/src/modules/system/roles/module.ts
@@ -0,0 +1,30 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout } from "@/layouts";
+import RoleList from "./RoleList.vue";
+import RoleDetail from "./RoleDetail.vue";
+
+const roleModule: Plugin = {
+ name: "roleModule",
+ components: [],
+ routes: [
+ {
+ path: "/users",
+ component: BasicLayout,
+ children: [
+ {
+ path: "roles",
+ name: "Roles",
+ component: RoleList,
+ },
+ {
+ path: "roles/:id",
+ name: "RoleDetail",
+ component: RoleDetail,
+ },
+ ],
+ },
+ ],
+ menus: [],
+};
+
+export default roleModule;
diff --git a/src/modules/system/settings/module.ts b/src/modules/system/settings/module.ts
new file mode 100644
index 00000000..abce1b1b
--- /dev/null
+++ b/src/modules/system/settings/module.ts
@@ -0,0 +1,43 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { SystemSettingsLayout } from "@/layouts";
+import GeneralSettings from "./GeneralSettings.vue";
+import NotificationSettings from "./NotificationSettings.vue";
+import { IconSettings } from "@halo-dev/components";
+
+const settingModule: Plugin = {
+ name: "settingModule",
+ components: [],
+ routes: [
+ {
+ path: "/settings",
+ component: SystemSettingsLayout,
+ redirect: "/settings/general",
+ children: [
+ {
+ path: "general",
+ name: "GeneralSettings",
+ component: GeneralSettings,
+ },
+ {
+ path: "notification",
+ name: "NotificationSettings",
+ component: NotificationSettings,
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "系统",
+ items: [
+ {
+ name: "设置",
+ path: "/settings",
+ icon: IconSettings,
+ },
+ ],
+ },
+ ],
+};
+
+export default settingModule;
diff --git a/src/modules/system/users/module.ts b/src/modules/system/users/module.ts
new file mode 100644
index 00000000..76fe94eb
--- /dev/null
+++ b/src/modules/system/users/module.ts
@@ -0,0 +1,73 @@
+import type { Plugin } from "@halo-dev/admin-shared";
+import { BasicLayout, BlankLayout, UserProfileLayout } from "@/layouts";
+import UserList from "./UserList.vue";
+import UserDetail from "./UserDetail.vue";
+import ProfileModification from "./ProfileModification.vue";
+import PasswordChange from "./PasswordChange.vue";
+import PersonalAccessTokens from "./PersonalAccessTokens.vue";
+import { IconUserSettings } from "@halo-dev/components";
+
+const userModule: Plugin = {
+ name: "userModule",
+ components: [],
+ routes: [
+ {
+ path: "/users",
+ component: BlankLayout,
+ children: [
+ {
+ path: "",
+ component: BasicLayout,
+ children: [
+ {
+ path: "",
+ name: "Users",
+ component: UserList,
+ },
+ ],
+ },
+ {
+ path: ":username",
+ component: UserProfileLayout,
+ alias: ["profile"],
+ children: [
+ {
+ path: "detail",
+ name: "UserDetail",
+ component: UserDetail,
+ },
+ {
+ path: "profile-modification",
+ name: "ProfileModification",
+ component: ProfileModification,
+ },
+ {
+ path: "password-change",
+ name: "PasswordChange",
+ component: PasswordChange,
+ },
+ {
+ path: "tokens",
+ name: "PersonalAccessTokens",
+ component: PersonalAccessTokens,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ menus: [
+ {
+ name: "系统",
+ items: [
+ {
+ name: "用户",
+ path: "/users",
+ icon: IconUserSettings,
+ },
+ ],
+ },
+ ],
+};
+
+export default userModule;
diff --git a/src/router/menus.config.ts b/src/router/menus.config.ts
index bc00d399..ceac3fb4 100644
--- a/src/router/menus.config.ts
+++ b/src/router/menus.config.ts
@@ -2,98 +2,28 @@ import {
IconBookRead,
IconDashboard,
IconFolder,
- IconListSettings,
IconMessage,
- IconPages,
- IconPalette,
- IconPlug,
- IconSettings,
IconUserSettings,
} from "@halo-dev/components";
-import type { Component } from "vue";
-declare interface MenuGroupType {
- name?: string;
- items: MenuItemType[];
-}
-
-declare interface MenuItemType {
- name: string;
- path: string;
- icon?: Component;
- meta?: Record;
- children?: MenuItemType[];
-}
+import type { MenuGroupType, MenuItemType } from "@halo-dev/admin-shared";
export const menus: MenuGroupType[] = [
{
- items: [
- {
- name: "仪表盘",
- path: "/dashboard",
- icon: IconDashboard,
- },
- ],
+ name: "",
+ items: [],
},
{
name: "内容",
- items: [
- {
- name: "文章",
- path: "/posts",
- icon: IconBookRead,
- },
- {
- name: "页面",
- path: "/sheets",
- icon: IconPages,
- },
- {
- name: "评论",
- path: "/comments",
- icon: IconMessage,
- },
- {
- name: "附件",
- path: "/attachments",
- icon: IconFolder,
- },
- ],
+ items: [],
},
{
name: "外观",
- items: [
- {
- name: "主题",
- path: "/theme",
- icon: IconPalette,
- },
- {
- name: "菜单",
- path: "/menus",
- icon: IconListSettings,
- },
- ],
+ items: [],
},
{
name: "系统",
- items: [
- {
- name: "插件",
- path: "/plugins",
- icon: IconPlug,
- },
- {
- name: "用户",
- path: "/users",
- icon: IconUserSettings,
- },
- {
- name: "设置",
- path: "/settings",
- icon: IconSettings,
- },
- ],
+ items: [],
},
];
@@ -125,6 +55,18 @@ export const minimenus: MenuItemType[] = [
},
];
+export function registerMenu(group: string | undefined, menu: MenuItemType) {
+ const groupIndex = menus.findIndex((g) => g.name === group);
+ if (groupIndex !== -1) {
+ menus[groupIndex].items.push(menu);
+ return;
+ }
+ menus.push({
+ name: group,
+ items: [menu],
+ });
+}
+
export type { MenuItemType, MenuGroupType };
export default menus;
diff --git a/src/router/routes.config.ts b/src/router/routes.config.ts
index 59aefc59..23fb96de 100644
--- a/src/router/routes.config.ts
+++ b/src/router/routes.config.ts
@@ -1,246 +1,12 @@
import type { RouteRecordRaw } from "vue-router";
-import {
- BasicLayout,
- BlankLayout,
- SystemSettingsLayout,
- UserProfileLayout,
-} from "@/layouts";
-
-import Dashboard from "../modules/dashboard/Dashboard.vue";
-
-import PostList from "../modules/contents/posts/PostList.vue";
-import PostEditor from "../modules/contents/posts/PostEditor.vue";
-import SheetList from "../modules/contents/sheets/SheetList.vue";
-import CategoryList from "../modules/contents/posts/categories/CategoryList.vue";
-import TagList from "../modules/contents/posts/tags/TagList.vue";
-import CommentList from "../modules/contents/comments/CommentList.vue";
-import AttachmentList from "../modules/contents/attachments/AttachmentList.vue";
-
-import ThemeDetail from "../modules/interface/themes/ThemeDetail.vue";
-import MenuList from "../modules/interface/menus/MenuList.vue";
-import Visual from "../modules/interface/themes/Visual.vue";
-
-import PluginList from "../modules/system/plugins/PluginList.vue";
-import PluginDetail from "../modules/system/plugins/PluginDetail.vue";
-import UserList from "../modules/system/users/UserList.vue";
-import RoleList from "../modules/system/roles/RoleList.vue";
-import RoleDetail from "../modules/system/roles/RoleDetail.vue";
-import UserDetail from "../modules/system/users/UserDetail.vue";
-import ProfileModification from "../modules/system/users/ProfileModification.vue";
-import PasswordChange from "../modules/system/users/PasswordChange.vue";
-import PersonalAccessTokens from "../modules/system/users/PersonalAccessTokens.vue";
-import GeneralSettings from "../modules/system/settings/GeneralSettings.vue";
-import NotificationSettings from "../modules/system/settings/NotificationSettings.vue";
+import NotFound from "@/views/exceptions/NotFound.vue";
+import { BasicLayout } from "@/layouts";
export const routes: Array = [
{
- path: "/",
+ path: "/:pathMatch(.*)*",
component: BasicLayout,
- redirect: "/dashboard",
- children: [
- {
- path: "dashboard",
- name: "Dashboard",
- component: Dashboard,
- },
- ],
- },
- {
- path: "/posts",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Posts",
- component: PostList,
- },
- {
- path: "editor",
- name: "PostEditor",
- component: PostEditor,
- },
- {
- path: "categories",
- component: BlankLayout,
- children: [
- {
- path: "",
- name: "Categories",
- component: CategoryList,
- },
- ],
- },
- {
- path: "tags",
- component: BlankLayout,
- children: [
- {
- path: "",
- name: "Tags",
- component: TagList,
- },
- ],
- },
- ],
- },
- {
- path: "/sheets",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Sheets",
- component: SheetList,
- },
- ],
- },
- {
- path: "/comments",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Comments",
- component: CommentList,
- },
- ],
- },
- {
- path: "/attachments",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Attachments",
- component: AttachmentList,
- },
- ],
- },
- {
- path: "/theme",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Theme",
- component: ThemeDetail,
- },
- ],
- },
- {
- path: "/theme/visual",
- component: BlankLayout,
- children: [
- {
- path: "",
- name: "ThemeVisual",
- component: Visual,
- },
- ],
- },
- {
- path: "/menus",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Menus",
- component: MenuList,
- },
- ],
- },
- {
- path: "/plugins",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Plugins",
- component: PluginList,
- },
- {
- path: ":id",
- name: "PluginDetail",
- component: PluginDetail,
- },
- ],
- },
- {
- path: "/users",
- component: BlankLayout,
- children: [
- {
- path: "",
- component: BasicLayout,
- children: [
- {
- path: "",
- name: "Users",
- component: UserList,
- },
- ],
- },
- {
- path: ":username",
- component: UserProfileLayout,
- alias: ["profile"],
- children: [
- {
- path: "detail",
- name: "UserDetail",
- component: UserDetail,
- },
- {
- path: "profile-modification",
- name: "ProfileModification",
- component: ProfileModification,
- },
- {
- path: "password-change",
- name: "PasswordChange",
- component: PasswordChange,
- },
- {
- path: "tokens",
- name: "PersonalAccessTokens",
- component: PersonalAccessTokens,
- },
- ],
- },
- {
- path: "",
- component: BasicLayout,
- children: [
- {
- path: "roles",
- name: "Roles",
- component: RoleList,
- },
- {
- path: "roles/:id",
- name: "RoleDetail",
- component: RoleDetail,
- },
- ],
- },
- ],
- },
- {
- path: "/settings",
- component: SystemSettingsLayout,
- redirect: "/settings/general",
- children: [
- {
- path: "general",
- name: "GeneralSettings",
- component: GeneralSettings,
- },
- {
- path: "notification",
- name: "NotificationSettings",
- component: NotificationSettings,
- },
- ],
+ children: [{ path: "", name: "NotFound", component: NotFound }],
},
];
diff --git a/src/setup/setupComponents.ts b/src/setup/setupComponents.ts
index 76bbbe53..9b4a2dd4 100644
--- a/src/setup/setupComponents.ts
+++ b/src/setup/setupComponents.ts
@@ -3,11 +3,9 @@ import { Dropdown, Menu, Tooltip, VClosePopper, VTooltip } from "floating-vue";
import "floating-vue/dist/style.css";
// @ts-ignore
import VueGridLayout from "vue-grid-layout";
-import Widgets from "@/modules/dashboard/widgets";
export function setupComponents(app: App) {
app.use(VueGridLayout);
- app.use(Widgets);
app.directive("tooltip", VTooltip);
app.directive("close-popper", VClosePopper);
diff --git a/src/views/exceptions/NotFound.vue b/src/views/exceptions/NotFound.vue
new file mode 100644
index 00000000..2300138b
--- /dev/null
+++ b/src/views/exceptions/NotFound.vue
@@ -0,0 +1 @@
+404
diff --git a/vite.config.ts b/vite.config.ts
index 0139c96e..72aec0e3 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -3,14 +3,15 @@ import { fileURLToPath, URL } from "url";
import { defineConfig } from "vite";
import Vue from "@vitejs/plugin-vue";
import VueJsx from "@vitejs/plugin-vue-jsx";
+import VueSetupExtend from "vite-plugin-vue-setup-extend";
import Compression from "vite-compression-plugin";
import { VitePWA } from "vite-plugin-pwa";
-// https://vitejs.dev/config/
export default defineConfig({
plugins: [
Vue(),
VueJsx(),
+ VueSetupExtend(),
Compression(),
VitePWA({
manifest: {