From 75173553a135d29f0de07076cf77577cb87443ac Mon Sep 17 00:00:00 2001 From: XingQue Date: Mon, 6 Jul 2026 19:28:36 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=B6=88=E9=99=A4welcome=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E6=AD=BB=E5=BE=AA=E7=8E=AF=EF=BC=8C=E5=95=86=E5=AE=B6?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E8=BF=9B=E9=A1=B5=E5=88=B7=E6=96=B0=E6=9D=83?= =?UTF-8?q?=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/index.js | 18 ++++++++++++++---- src/utils/club-context.js | 17 +++++------------ src/views/Login.vue | 7 ++++--- src/views/Welcome.vue | 5 ++--- src/views/order/MerchantOrder.vue | 8 ++++++-- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/router/index.js b/src/router/index.js index 9333059..be75892 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -8,6 +8,7 @@ import { getDefaultLandingPath, getEffectiveVisiblePaths, isMenuSessionFresh, + hasMerchantOrderPerm, JITUAN_API, } from '@/utils/club-context' @@ -324,8 +325,12 @@ const router = createRouter({ }) /** 详情页等子路由:父模块在 visible_paths 中即允许访问 */ -function isRouteAllowed(path, visiblePaths) { +function isRouteAllowed(path, access) { + const visiblePaths = getEffectiveVisiblePaths(access) if (!visiblePaths?.length) return false + if (path === '/order/merchant' || path.startsWith('/order/merchant/')) { + if (!hasMerchantOrderPerm(access)) return false + } if (visiblePaths.some((p) => p && (path === p || path.startsWith(`${p}/`)))) { return true } @@ -367,10 +372,11 @@ router.beforeEach(async (to, from, next) => { const res = await request.get(JITUAN_API.meContext, { skipErrorToast: true }) return res.code === 0 ? res.data : null }) + const needFreshMenu = !isMenuSessionFresh() || !getMenuAccess() await ensureMenuAccess(async () => { - const res = await request.get(JITUAN_API.menuAccess) + const res = await request.get(JITUAN_API.menuAccess, { skipErrorToast: true }) return res.code === 0 ? res.data : null - }, { force: true }) + }, { force: needFreshMenu }) } catch (e) { console.error('路由加载菜单权限失败:', e) } @@ -401,8 +407,12 @@ router.beforeEach(async (to, from, next) => { } const path = to.path - if (!isRouteAllowed(path, getEffectiveVisiblePaths(access))) { + if (!isRouteAllowed(path, access)) { const fallback = getDefaultLandingPath(access) || '/welcome' + if (fallback === path) { + next('/welcome') + return + } next(fallback) return } diff --git a/src/utils/club-context.js b/src/utils/club-context.js index 7c04bf1..8d848c2 100644 --- a/src/utils/club-context.js +++ b/src/utils/club-context.js @@ -3,7 +3,7 @@ const CLUB_SCOPE_KEY = 'admin_club_scope'; const CLUB_CONTEXT_KEY = 'admin_club_context'; const MENU_ACCESS_KEY = 'kefu_menu_access'; const MENU_SESSION_KEY = 'kefu_menu_session_v'; -const MENU_SESSION_VERSION = '23'; +const MENU_SESSION_VERSION = '24'; const DEFAULT_CLUB_ID = 'xq'; let menuAccessInflight = null; @@ -220,15 +220,10 @@ export function canShowMenuPage(pageId) { const ids = access?.visible_page_ids; if (!Array.isArray(ids) || ids.length === 0) return false; - const row = KEFU_MENU_ROWS.find((r) => r.page_id === pageId); - if (row?.path && row.perm_codes?.length) { - if (!ids.includes(pageId)) return false; - return hasPermCode(access, ...row.perm_codes); - } - + // 侧栏以服务端 visible_page_ids 为准;permission_codes 由页面/API 二次校验 if (ids.includes(pageId)) return true; const children = KEFU_MENU_PARENT_IDS[pageId]; - return children ? children.some((id) => canShowMenuPage(id)) : false; + return children ? children.some((id) => ids.includes(id)) : false; } /** 写入菜单缓存,并同步服务端校正后的 effective_club_id */ @@ -315,12 +310,10 @@ export async function ensureMenuAccess(fetcher, { force = false } = {}) { try { const data = await fetcher(); if (data) return applyMenuAccessPayload(data); - if (force) clearMenuAccess(); - return null; + return getMenuAccess(); } catch (e) { console.error('ensureMenuAccess failed:', e); - if (force) clearMenuAccess(); - return null; + return getMenuAccess(); } finally { menuAccessInflight = null; } diff --git a/src/views/Login.vue b/src/views/Login.vue index 54a448c..efe96d0 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -65,7 +65,7 @@ import { useRouter } from 'vue-router' import { ElMessage } from 'element-plus' import { User, Lock, Key } from '@element-plus/icons-vue' import axios from 'axios' // 直接使用 axios,不经过封装的 request -import { JITUAN_API, getDefaultLandingPath, setAdminClubContext, setMenuAccess, resetAdminClubContextOnLogin } from '@/utils/club-context' +import { JITUAN_API, getDefaultLandingPath, setAdminClubContext, applyMenuAccessPayload, resetAdminClubContextOnLogin } from '@/utils/club-context' const router = useRouter() const loading = ref(false) @@ -117,12 +117,13 @@ const handleLogin = async () => { if (res.data.club_context) { const ctx = { ...res.data.club_context } if (res.data.menu_access) { - setMenuAccess(res.data.menu_access) + applyMenuAccessPayload(res.data.menu_access) + sessionStorage.setItem('kefu_menu_session_v', '24') ctx.can_switch_club = res.data.menu_access.can_switch_club } setAdminClubContext(ctx) } else if (res.data.menu_access) { - setMenuAccess(res.data.menu_access) + applyMenuAccessPayload(res.data.menu_access) } const ma = res.data.menu_access || {} const landing = getDefaultLandingPath(ma) diff --git a/src/views/Welcome.vue b/src/views/Welcome.vue index e87e97c..c6c00f1 100644 --- a/src/views/Welcome.vue +++ b/src/views/Welcome.vue @@ -76,9 +76,8 @@ const logout = () => { router.replace('/login') } -onMounted(() => { - const landing = getDefaultLandingPath() - if (landing) router.replace(landing) +onMounted(async () => { + // 不再自动跳转,避免与路由守卫形成 welcome ↔ 业务页 死循环 }) diff --git a/src/views/order/MerchantOrder.vue b/src/views/order/MerchantOrder.vue index 1273a39..fa90d7f 100644 --- a/src/views/order/MerchantOrder.vue +++ b/src/views/order/MerchantOrder.vue @@ -143,7 +143,7 @@ import { ElMessage } from 'element-plus' import { Refresh } from '@element-plus/icons-vue' import request from '@/utils/request' import ClubScopeHint from '@/components/ClubScopeHint.vue' -import { getMenuAccess, hasMerchantOrderPerm } from '@/utils/club-context' +import { getMenuAccess, hasMerchantOrderPerm, ensureMenuAccess, applyMenuAccessPayload, JITUAN_API } from '@/utils/club-context' const route = useRoute() const router = useRouter() @@ -363,7 +363,11 @@ const getStatusType = (code) => { watch(() => route.query, () => { restoreFromQuery(); fetchOrders() }, { deep: true }) -onMounted(() => { +onMounted(async () => { + await ensureMenuAccess(async () => { + const res = await request.get(JITUAN_API.menuAccess, { skipErrorToast: true }) + return res.code === 0 ? res.data : null + }, { force: true }) hasPermission.value = hasMerchantOrderPerm(getMenuAccess()) if (!hasPermission.value) return restoreFromQuery()