diff --git a/src/permission.ts b/src/permission.ts index 3991b8d..63a83ac 100644 --- a/src/permission.ts +++ b/src/permission.ts @@ -1,4 +1,4 @@ -import router from './router' +import router, { resetRouter } from './router' import { useAppStoreWithOut } from '@/store/modules/app' import type { RouteRecordRaw } from 'vue-router' import { useTitle } from '@/hooks/web/useTitle' @@ -25,10 +25,21 @@ router.beforeEach(async (to, from, next) => { next({ path: '/' }) } else { if (permissionStore.getIsAddRouters) { - next() - return + // 已加过路由:只有还是同一个账号才能直接放行。 + // 换账号时(例如超管退出后创作者登录)必须重建,否则侧边栏/路由会残留上一个账号的 + const username = userStore.getUserInfo?.username || '' + if (permissionStore.getRoutersOwner === username) { + next() + return + } + // 摘掉上一个账号动态加进去的路由,避免两套菜单并存 + resetRouter() + permissionStore.setIsAddRouters(false) } + const username = userStore.getUserInfo?.username || '' + const ownerChanged = permissionStore.getRoutersOwner !== username + // 开发者可根据实际情况进行修改 const roleRouters = userStore.getRoleRouters || [] @@ -38,7 +49,6 @@ router.beforeEach(async (to, from, next) => { // 每次进入应用都重新拉菜单与权限:后台改了菜单或角色权限,刷新即可生效,不必重新登录 let routers = (userStore.getRoleRouters || []) as AppCustomRouteRecordRaw[] try { - const username = userStore.getUserInfo?.username || '' const [profileRes, menuRes] = await Promise.all([ getProfileApi(), getAdminRoleApi({ roleName: username }) @@ -49,6 +59,9 @@ router.beforeEach(async (to, from, next) => { if (menuRes?.data?.length) { routers = menuRes.data userStore.setRoleRouters(routers) + } else if (ownerChanged) { + // 换账号后菜单拉不到就别沿用上一个账号的缓存,宁可先给空菜单 + routers = [] } } catch { // 拉取失败时退回上次缓存的菜单,不阻塞进入 @@ -64,6 +77,7 @@ router.beforeEach(async (to, from, next) => { permissionStore.getAddRouters.forEach((route) => { router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表 }) + permissionStore.setRoutersOwner(username) // 根路径按"这个账号能进的第一个菜单"落地:路由表里写死的 redirect 是 /dashboard/index, // 创作者没有运营后台权限,访问 '/' 会直接掉 404 diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts index c997306..4d80b64 100644 --- a/src/store/modules/permission.ts +++ b/src/store/modules/permission.ts @@ -13,6 +13,8 @@ export interface PermissionState { addRouters: AppRouteRecordRaw[] isAddRouters: boolean menuTabRouters: AppRouteRecordRaw[] + /** 当前这套菜单属于哪个账号:账号变了必须重建,不能沿用上一个账号的路由 */ + routersOwner: string } export const usePermissionStore = defineStore('permission', { @@ -20,7 +22,8 @@ export const usePermissionStore = defineStore('permission', { routers: [], addRouters: [], isAddRouters: false, - menuTabRouters: [] + menuTabRouters: [], + routersOwner: '' }), getters: { getRouters(): AppRouteRecordRaw[] { @@ -34,6 +37,9 @@ export const usePermissionStore = defineStore('permission', { }, getMenuTabRouters(): AppRouteRecordRaw[] { return this.menuTabRouters + }, + getRoutersOwner(): string { + return this.routersOwner } }, actions: { @@ -75,10 +81,21 @@ export const usePermissionStore = defineStore('permission', { }, setMenuTabRouters(routers: AppRouteRecordRaw[]): void { this.menuTabRouters = routers + }, + setRoutersOwner(owner: string): void { + this.routersOwner = owner + }, + /** 登出 / 切换账号时清空菜单与路由状态(由 userStore.reset 调用) */ + clearRoutes(): void { + this.routers = [] + this.addRouters = [] + this.menuTabRouters = [] + this.isAddRouters = false + this.routersOwner = '' } }, persist: { - paths: ['routers', 'addRouters', 'menuTabRouters'] + paths: ['routers', 'addRouters', 'menuTabRouters', 'routersOwner'] } }) diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index b29a2b7..480eab9 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -5,6 +5,7 @@ import { ElMessageBox } from 'element-plus' import { useI18n } from '@/hooks/web/useI18n' import { loginOutApi } from '@/api/login' import { useTagsViewStore } from './tagsView' +import { usePermissionStore } from './permission' import router from '@/router' interface UserState { @@ -78,10 +79,15 @@ export const useUserStore = defineStore('user', { }, reset() { const tagsViewStore = useTagsViewStore() - tagsViewStore.delAllViews() + const permissionStore = usePermissionStore() + // 顺序要紧:delAllVisitedViews() 会「保留 affix 标签」,而它判断的正是 userInfo 是否还在。 + // 先清账号信息再清标签,否则写死路由表里 affix 的「工作台」会在切换账号后残留。 this.setToken('') this.setUserInfo(undefined) this.setRoleRouters([]) + tagsViewStore.delAllViews() + // 菜单/路由一起清:否则换账号后 permissionStore 里还是上一个账号的路由表 + permissionStore.clearRoutes() router.replace('/login') }, logout() { diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue index 007d2b2..022f92f 100644 --- a/src/views/Login/components/LoginForm.vue +++ b/src/views/Login/components/LoginForm.vue @@ -231,6 +231,8 @@ const getRole = async () => { permissionStore.getAddRouters.forEach((route) => { addRoute(route as RouteRecordRaw) // 动态添加可访问路由表 }) + // 记住这套菜单属于哪个账号:换账号时守卫据此重建 + permissionStore.setRoutersOwner(params.roleName) permissionStore.setIsAddRouters(true) push({ path: redirect.value || landingPath() }) } diff --git a/src/views/common/DashboardView.vue b/src/views/common/DashboardView.vue index 405c962..6d69585 100644 --- a/src/views/common/DashboardView.vue +++ b/src/views/common/DashboardView.vue @@ -33,8 +33,9 @@ onMounted(async () => { loading.value = true try { const res = await pageDramasApi({ pageIndex: 1, pageSize: 200 }) - dramas.value = res.data?.list || [] - total.value = res.data?.total || 0 + // 接口失败时 axios 拦截器会把业务错误吞成 undefined,这里不能让页面跟着崩 + dramas.value = res?.data?.list || [] + total.value = res?.data?.total || 0 } finally { loading.value = false } diff --git a/src/views/creator/CreatorAuditView.vue b/src/views/creator/CreatorAuditView.vue index d83dfbf..dec84bd 100644 --- a/src/views/creator/CreatorAuditView.vue +++ b/src/views/creator/CreatorAuditView.vue @@ -167,7 +167,12 @@ const {