diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md index d86650252a277c7a02782f8eb1e42e730b765426..44758e4cf4826fa0637a717edbd54506e5dc45c9 100644 --- a/CHANGELOG.zh_CN.md +++ b/CHANGELOG.zh_CN.md @@ -2,6 +2,8 @@ - **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能 - **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致 +- 可以为不同的用户指定不同的后台首页: + - 在`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径 ### 🐛 Bug Fixes @@ -18,6 +20,7 @@ - 修复左侧混合菜单的悬停触发逻辑 - 修复顶栏菜单在显示包含需要隐藏的菜单项目时出错的问题 - 修复悬停触发模式下左侧混合菜单会在没有子菜单且被激活时直接跳转路由 +- **Breadcrumb** 修复带有重定向的菜单点击无法跳转的问题 - **其它** - 修复菜单默认折叠的配置不起作用的问题 - 修复`safari`浏览器报错导致网站打不开 diff --git a/mock/sys/user.ts b/mock/sys/user.ts index f54472224433b10ef640d1ac11af7b4148f51871..a8608f1b9e1a2db4a93b675733fae236bf835929 100644 --- a/mock/sys/user.ts +++ b/mock/sys/user.ts @@ -11,6 +11,7 @@ export function createFakeUserList() { desc: 'manager', password: '123456', token: 'fakeToken1', + homePath: '/dashboard/analysis', roles: [ { roleName: 'Super Admin', @@ -26,6 +27,7 @@ export function createFakeUserList() { avatar: 'https://q1.qlogo.cn/g?b=qq&nk=339449197&s=640', desc: 'tester', token: 'fakeToken2', + homePath: '/dashboard/workbench', roles: [ { roleName: 'Tester', diff --git a/src/components/Application/src/AppLogo.vue b/src/components/Application/src/AppLogo.vue index 927000ebdbe0f64aec538dfa058700daa4463f24..d1cdeb57f17ce0ec0f74d4b62d5d461d81c7be91 100644 --- a/src/components/Application/src/AppLogo.vue +++ b/src/components/Application/src/AppLogo.vue @@ -17,6 +17,7 @@ import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; import { useDesign } from '/@/hooks/web/useDesign'; import { PageEnum } from '/@/enums/pageEnum'; + import { useUserStore } from '/@/store/modules/user'; const props = { /** @@ -39,6 +40,7 @@ setup(props) { const { prefixCls } = useDesign('app-logo'); const { getCollapsedShowTitle } = useMenuSetting(); + const userStore = useUserStore(); const { title } = useGlobSetting(); const go = useGo(); @@ -56,7 +58,7 @@ ]); function goHome() { - go(PageEnum.BASE_HOME); + go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); } return { diff --git a/src/router/guard/permissionGuard.ts b/src/router/guard/permissionGuard.ts index 5b731305d8685acbeb7ec6abdf8903ad5e73fe21..fb680b1fb5774a3ac02bd3f979d79f9ca6c4cb28 100644 --- a/src/router/guard/permissionGuard.ts +++ b/src/router/guard/permissionGuard.ts @@ -7,8 +7,12 @@ import { useUserStoreWithOut } from '/@/store/modules/user'; import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; +import { RootRoute } from '/@/router/routes'; + const LOGIN_PATH = PageEnum.BASE_LOGIN; +const ROOT_PATH = RootRoute.path; + const whitePathList: PageEnum[] = [LOGIN_PATH]; export function createPermissionGuard(router: Router) { @@ -17,7 +21,17 @@ export function createPermissionGuard(router: Router) { router.beforeEach(async (to, from, next) => { // Jump to the 404 page after processing the login if (from.path === LOGIN_PATH && to.name === PAGE_NOT_FOUND_ROUTE.name) { - next(PageEnum.BASE_HOME); + next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); + return; + } + + if ( + from.path === ROOT_PATH && + to.path === PageEnum.BASE_HOME && + userStore.getUserInfo.homePath && + userStore.getUserInfo.homePath !== PageEnum.BASE_HOME + ) { + next(userStore.getUserInfo.homePath); return; } diff --git a/src/router/routes/modules/dashboard.ts b/src/router/routes/modules/dashboard.ts index 12df83cd3b0b349c36d73a274e86d36f158ac3a6..f532ec74f143d61d55dbb2f8050c730dbad130e0 100644 --- a/src/router/routes/modules/dashboard.ts +++ b/src/router/routes/modules/dashboard.ts @@ -19,7 +19,7 @@ const dashboard: AppRouteModule = { name: 'Analysis', component: () => import('/@/views/dashboard/analysis/index.vue'), meta: { - affix: true, + // affix: true, title: t('routes.dashboard.analysis'), }, }, diff --git a/src/store/modules/multipleTab.ts b/src/store/modules/multipleTab.ts index 3dcb188a7bcad7ee101ec39cec2e8598d69176af..0c5fbc1bb8eec56767232fe63d7a28641162e4f5 100644 --- a/src/store/modules/multipleTab.ts +++ b/src/store/modules/multipleTab.ts @@ -13,6 +13,7 @@ import { getRawRoute } from '/@/utils'; import { MULTIPLE_TABS_KEY } from '/@/enums/cacheEnum'; import projectSetting from '/@/settings/projectSetting'; +import { useUserStore } from '/@/store/modules/user'; export interface MultipleTabState { cacheTabList: Set; @@ -181,7 +182,8 @@ export const useMultipleTabStore = defineStore({ if (index === 0) { // There is only one tab, then jump to the homepage, otherwise jump to the right tab if (this.tabList.length === 1) { - toTarget = PageEnum.BASE_HOME; + const userStore = useUserStore(); + toTarget = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; } else { // Jump to the right tab const page = this.tabList[index + 1]; diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts index f08b9f9943353a1aff7208e6dbf5ef9290dbec05..a365f56c3d1c31a4fbec33d92a7bec8c820e85bc 100644 --- a/src/store/modules/permission.ts +++ b/src/store/modules/permission.ts @@ -22,6 +22,7 @@ import { getMenuList } from '/@/api/sys/menu'; import { getPermCode } from '/@/api/sys/user'; import { useMessage } from '/@/hooks/web/useMessage'; +import { PageEnum } from '/@/enums/pageEnum'; interface PermissionState { // Permission code list @@ -117,6 +118,32 @@ export const usePermissionStore = defineStore({ return !ignoreRoute; }; + /** + * @description 根据设置的首页path,修正routes中的affix标记(固定首页) + * */ + const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { + if (!routes || routes.length === 0) return; + const homePath = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; + function patcher(routes: AppRouteRecordRaw[], parentPath = '') { + if (parentPath) parentPath = parentPath + '/'; + routes.forEach((route: AppRouteRecordRaw) => { + const { path, children } = route; + const currentPath = path.startsWith('/') ? path : parentPath + path; + if (currentPath === homePath) { + route.meta = Object.assign({}, route.meta, { affix: true }); + throw new Error('end'); + } + children && children.length > 0 && patcher(children, currentPath); + }); + } + try { + patcher(routes); + } catch (e) { + // 已处理完毕跳出循环 + } + return; + }; + switch (permissionMode) { case PermissionModeEnum.ROLE: routes = filter(asyncRoutes, routeFilter); @@ -176,6 +203,7 @@ export const usePermissionStore = defineStore({ } routes.push(ERROR_LOG_ROUTE); + patchHomeAffix(routes); return routes; }, }, diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 2c5bed6697dd4a787371f6637b23f9d270a4cd44..a6bad003748bff720fe8696fce132321b9525737 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -88,13 +88,15 @@ export const useUserStore = defineStore({ const sessionTimeout = this.sessionTimeout; sessionTimeout && this.setSessionTimeout(false); - !sessionTimeout && goHome && (await router.replace(PageEnum.BASE_HOME)); + !sessionTimeout && + goHome && + (await router.replace(userInfo.homePath || PageEnum.BASE_HOME)); return userInfo; } catch (error) { return Promise.reject(error); } }, - async getUserInfoAction() { + async getUserInfoAction(): Promise { const userInfo = await getUserInfo(); const { roles } = userInfo; const roleList = roles.map((item) => item.value) as RoleEnum[]; diff --git a/types/store.d.ts b/types/store.d.ts index 0f34d06b7bb0fc3549e77da488d418e6412b51e4..36a6025fc58cd4999ec4fc0d1a2ead3a35da942a 100644 --- a/types/store.d.ts +++ b/types/store.d.ts @@ -1,5 +1,6 @@ import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; +import { RoleInfo } from '/@/api/sys/model/userModel'; // Lock screen information export interface LockInfo { @@ -35,6 +36,8 @@ export interface UserInfo { realName: string; avatar: string; desc?: string; + homePath?: string; + roles: RoleInfo[]; } export interface BeforeMiniState {