diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000..13102b3
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,4 @@
+# 参见 .env
+
+VITE_BASE = ./
+VITE_HISTORY = hash
\ No newline at end of file
diff --git a/.gitea/stat.html b/.gitea/stat.html
index 53a1228..0ed7872 100644
--- a/.gitea/stat.html
+++ b/.gitea/stat.html
@@ -4822,7 +4822,7 @@ var drawChart = (function (exports) {
+
+{
+ "meta": {
+ // 组件名字
+ "name": "MyPage",
+ // 开启缓存
+ "cache": true
}
}
diff --git a/image.png b/image.png
new file mode 100644
index 0000000..f5970a8
Binary files /dev/null and b/image.png differ
diff --git a/index.html b/index.html
index 3791bd9..7433905 100644
--- a/index.html
+++ b/index.html
@@ -38,6 +38,7 @@
display: flex;
align-items: center;
justify-content: center;
+ user-select: none;
}
.loading {
display: flex;
diff --git a/src/pages/_layout/Menu.vue b/src/pages/_layout/Menu.vue
index e62de33..a6407d5 100644
--- a/src/pages/_layout/Menu.vue
+++ b/src/pages/_layout/Menu.vue
@@ -13,9 +13,11 @@ export default defineComponent({
watch(
() => route.path,
() => {
- selectedKeys.value = route.matched.map(i => i.path);
+ selectedKeys.value = route.matched.map(i => i.aliasOf?.path ?? i.path);
},
- { immediate: true }
+ {
+ immediate: true,
+ }
);
function goto(route: MenuItem) {
diff --git a/src/pages/_layout/index.vue b/src/pages/_layout/index.vue
index fbe795e..bbe1905 100644
--- a/src/pages/_layout/index.vue
+++ b/src/pages/_layout/index.vue
@@ -204,6 +204,7 @@ const buttons = [
{
+ "redirect": "/",
"meta": {
"name": "LayoutPage",
"sort": 101,
diff --git a/src/pages/home/index.vue b/src/pages/home/index.vue
index b05ce74..6018eca 100644
--- a/src/pages/home/index.vue
+++ b/src/pages/home/index.vue
@@ -108,6 +108,7 @@ const stat = {
{
+ "alias": "/",
"meta": {
"sort": 1000,
"title": "首页",
diff --git a/src/pages/system/department/index.vue b/src/pages/system/department/index.vue
index 2e12523..5a5d8a0 100644
--- a/src/pages/system/department/index.vue
+++ b/src/pages/system/department/index.vue
@@ -173,7 +173,6 @@ const { component: UserTable } = useTable({
{
"meta": {
"name": "SystemDepartmentPage",
- "keepAlive": true,
"sort": 10301,
"title": "部门管理",
"icon": "icon-park-outline-group"
diff --git a/src/pages/system/role/index.vue b/src/pages/system/role/index.vue
index a1a3f9e..d6a1e19 100644
--- a/src/pages/system/role/index.vue
+++ b/src/pages/system/role/index.vue
@@ -106,6 +106,7 @@ const { component: RoleTable } = useTable({
"name": "SystemRolePage",
"sort": 10302,
"title": "角色管理",
+ "auth": ["role"],
"icon": "icon-park-outline-shield"
}
}
diff --git a/src/pages/system/user/index.vue b/src/pages/system/user/index.vue
index f47762d..1fb5f32 100644
--- a/src/pages/system/user/index.vue
+++ b/src/pages/system/user/index.vue
@@ -176,7 +176,6 @@ const { component: UserTable } = useTable({
"cache": true,
"sort": 10301,
"title": "用户管理",
- "auth": ["*"],
"icon": "icon-park-outline-user"
}
}
diff --git a/src/router/guards/auth.ts b/src/router/guards/auth.ts
index cbc1e2e..9330e5d 100644
--- a/src/router/guards/auth.ts
+++ b/src/router/guards/auth.ts
@@ -2,18 +2,16 @@ import { api } from '@/api';
import { env } from '@/config/env';
import { store, useUserStore } from '@/store';
import { useMenuStore } from '@/store/menu';
-import { treeEach, treeFilter, treeFind } from '@/utils/listToTree';
+import { treeEach } from '@/utils/listToTree';
import { Notification } from '@arco-design/web-vue';
import { Router } from 'vue-router';
import { menus } from '../menus';
-import { APP_HOME_NAME } from '../routes/base';
-import { APP_ROUTE_NAME, routes } from '../routes/page';
+import { appRoutes } from '../routes/page';
/**
* 权限守卫
* @param to 路由
* @description store不能放在外面,否则 pinia-plugin-peristedstate 插件会失效
- * @returns
*/
export function useAuthGuard(router: Router) {
api.expireHandler = () => {
@@ -39,17 +37,17 @@ export function useAuthGuard(router: Router) {
return true;
}
+ // 直接访问跳转回首页(非路由跳转)
+ if (!from.matched.length) {
+ return '/';
+ }
+
// 提示已登陆
Notification.warning({
title: '跳转提示',
content: `您已登陆,如需重新登陆请退出后再操作!`,
});
- // 直接访问跳转回首页(不是从路由跳转)
- if (!from.matched.length) {
- return '/';
- }
-
// 已登陆不允许
return false;
}
@@ -64,37 +62,24 @@ export function useAuthGuard(router: Router) {
// 未获取权限进行获取
if (!menuStore.menus.length) {
- // 菜单处理
- const authMenus = treeFilter(menus, item => {
- if (item.path === env.homePath) {
- item.path = '/';
- }
- return true;
- });
- menuStore.setMenus(authMenus);
+ menuStore.setMenus(menus);
menuStore.setHome(env.homePath);
- // 路由处理
- for (const route of routes) {
- router.addRoute(route);
- }
-
- // 缓存处理
- treeEach(routes, (item, level) => {
+ treeEach(appRoutes, item => {
const { cache, name } = item.meta ?? {};
if (cache && name) {
menuStore.caches.push(name);
}
+ // if (item.path === menuStore.home) {
+ // item.alias = '/';
+ // }
+ // if (!router.hasRoute(item.name!)) {
+ // const route = { ...item, children: undefined } as any;
+ // router.addRoute(route.parentName!, route);
+ // }
});
- // 首页处理
- const home = treeFind(routes, i => i.path === menuStore.home);
- if (home) {
- const route = { ...home, name: APP_HOME_NAME, alias: '/' };
- router.removeRoute(home.name!);
- router.addRoute(APP_ROUTE_NAME, route);
- return router.replace(to.path);
- }
+ return to.fullPath;
}
// 兜底处理
diff --git a/src/router/router/index.ts b/src/router/router/index.ts
index b9d65af..518f3a1 100644
--- a/src/router/router/index.ts
+++ b/src/router/router/index.ts
@@ -2,7 +2,6 @@ import { createRouter } from 'vue-router';
import { useAuthGuard } from '../guards/auth';
import { useProgressGard } from '../guards/progress';
import { useTitleGuard } from '../guards/title';
-import { baseRoutes } from '../routes/base';
import { historyMode } from './util';
import { routes } from '../routes/page';
@@ -11,7 +10,7 @@ import { routes } from '../routes/page';
*/
export const router = createRouter({
history: historyMode(),
- routes: [...baseRoutes, ...routes],
+ routes: routes,
});
/**
diff --git a/src/router/routes/base.ts b/src/router/routes/base.ts
deleted file mode 100644
index 98ebeb7..0000000
--- a/src/router/routes/base.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { RouteRecordRaw } from 'vue-router';
-
-export const APP_HOME_NAME = '__APP_HOME__';
-
-/**
- * 基本路由
- */
-export const baseRoutes: RouteRecordRaw[] = [
- {
- path: '/',
- name: APP_HOME_NAME,
- component: () => 'Home Page',
- },
-];
diff --git a/src/router/routes/page.ts b/src/router/routes/page.ts
index 7684417..3b8c95f 100644
--- a/src/router/routes/page.ts
+++ b/src/router/routes/page.ts
@@ -15,8 +15,8 @@ function treeRoutes(list: RouteRecordRaw[]) {
for (const item of list) {
const parentPath = item.path.split('/').slice(0, -1).join('/');
const parent = map[parentPath];
+ item.parentName = (parent?.name as string) || APP_ROUTE_NAME;
if (parent) {
- (item as any).parentPath = parentPath;
(parent.children || (parent.children = [])).push(item);
} else {
tree.push(item);
@@ -47,12 +47,14 @@ function sortRoutes(routes: RouteRecordRaw[]) {
const transformRoutes = (routes: RouteRecordRaw[]) => {
const topRoutes: RouteRecordRaw[] = [];
const appRoutes: RouteRecordRaw[] = [];
+ let app: RouteRecordRaw;
for (const route of routes) {
+ if (route.name === APP_ROUTE_NAME) {
+ app = route;
+ route.children = appRoutes;
+ }
if ((route.name as string)?.startsWith(TOP_ROUTE_PREF)) {
- if (route.name === APP_ROUTE_NAME) {
- route.children = appRoutes;
- }
route.path = route.path.replace(TOP_ROUTE_PREF, '');
topRoutes.push(route);
continue;
@@ -60,7 +62,8 @@ const transformRoutes = (routes: RouteRecordRaw[]) => {
appRoutes.push(route);
}
- return [topRoutes, sortRoutes(treeRoutes(appRoutes))];
+ app!.children = sortRoutes(treeRoutes(appRoutes));
+ return [topRoutes, app!.children];
};
export const [routes, appRoutes] = transformRoutes(generatedRoutes);
diff --git a/src/store/user/index.ts b/src/store/user/index.ts
index 76a72ce..29229cf 100644
--- a/src/store/user/index.ts
+++ b/src/store/user/index.ts
@@ -1,16 +1,16 @@
-import { defineStore } from "pinia";
+import { defineStore } from 'pinia';
export const useUserStore = defineStore({
- id: "user",
+ id: 'user',
state: (): UserStore => {
return {
id: 0,
- username: "juetan",
- nickname: "绝弹",
- avatar: "https://github.com/juetan.png",
- accessToken: "",
+ username: 'juetan',
+ nickname: '绝弹',
+ avatar: 'https://github.com/juetan.png',
+ accessToken: '',
refreshToken: undefined,
- auth: []
+ auth: [],
};
},
actions: {
@@ -48,7 +48,10 @@ export const useUserStore = defineStore({
accessToken && (this.accessToken = accessToken);
},
},
- persist: true,
+ persist: {
+ key: '__APP_USER__',
+ paths: ['accessToken'],
+ },
});
export interface UserStore {
@@ -65,11 +68,11 @@ export interface UserStore {
*/
nickname: string;
/**
- * 用户头像地址
+ * 头像地址
*/
avatar?: string;
/**
- * JWT令牌
+ * 访问令牌
*/
accessToken?: string;
/**
diff --git a/src/types/vue-router.d.ts b/src/types/vue-router.d.ts
index 34f461c..e8048a5 100644
--- a/src/types/vue-router.d.ts
+++ b/src/types/vue-router.d.ts
@@ -1,6 +1,30 @@
-import "vue-router";
+import 'vue-router';
+
+declare module 'vue-router' {
+ interface RouteRecordRaw {
+ parentName?: string;
+ }
+
+ interface RouteRecordSingleViewWithChildren {
+ parentName?: string;
+ }
+
+ interface RouteRecordSingleView {
+ parentName?: string;
+ }
+
+ interface RouteRecordMultipleViews {
+ parentName?: string;
+ }
+
+ interface RouteRecordMultipleViewsWithChildren {
+ parentName?: string;
+ }
+
+ interface RouteRecordRedirect {
+ parentName?: string;
+ }
-declare module "vue-router" {
interface RouteMeta {
/**
* 页面标题