fix: 消除welcome路由死循环,商家订单进页刷新权限
This commit is contained in:
1 parent
ab91d9a363
commit
75173553a1
5 files changed
+31
-24
No files matched your search
+14
-4
@@ -8,6 +8,7 @@ import {
|
|||||||
getDefaultLandingPath,
|
getDefaultLandingPath,
|
||||||
getEffectiveVisiblePaths,
|
getEffectiveVisiblePaths,
|
||||||
isMenuSessionFresh,
|
isMenuSessionFresh,
|
||||||
|
hasMerchantOrderPerm,
|
||||||
JITUAN_API,
|
JITUAN_API,
|
||||||
} from '@/utils/club-context'
|
} from '@/utils/club-context'
|
||||||
|
|
||||||
@@ -324,8 +325,12 @@ const router = createRouter({
|
|||||||
})
|
})
|
||||||
|
|
||||||
/** 详情页等子路由:父模块在 visible_paths 中即允许访问 */
|
/** 详情页等子路由:父模块在 visible_paths 中即允许访问 */
|
||||||
function isRouteAllowed(path, visiblePaths) {
|
function isRouteAllowed(path, access) {
|
||||||
|
const visiblePaths = getEffectiveVisiblePaths(access)
|
||||||
if (!visiblePaths?.length) return false
|
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}/`)))) {
|
if (visiblePaths.some((p) => p && (path === p || path.startsWith(`${p}/`)))) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -367,10 +372,11 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
const res = await request.get(JITUAN_API.meContext, { skipErrorToast: true })
|
const res = await request.get(JITUAN_API.meContext, { skipErrorToast: true })
|
||||||
return res.code === 0 ? res.data : null
|
return res.code === 0 ? res.data : null
|
||||||
})
|
})
|
||||||
|
const needFreshMenu = !isMenuSessionFresh() || !getMenuAccess()
|
||||||
await ensureMenuAccess(async () => {
|
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
|
return res.code === 0 ? res.data : null
|
||||||
}, { force: true })
|
}, { force: needFreshMenu })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('路由加载菜单权限失败:', e)
|
console.error('路由加载菜单权限失败:', e)
|
||||||
}
|
}
|
||||||
@@ -401,8 +407,12 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const path = to.path
|
const path = to.path
|
||||||
if (!isRouteAllowed(path, getEffectiveVisiblePaths(access))) {
|
if (!isRouteAllowed(path, access)) {
|
||||||
const fallback = getDefaultLandingPath(access) || '/welcome'
|
const fallback = getDefaultLandingPath(access) || '/welcome'
|
||||||
|
if (fallback === path) {
|
||||||
|
next('/welcome')
|
||||||
|
return
|
||||||
|
}
|
||||||
next(fallback)
|
next(fallback)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const CLUB_SCOPE_KEY = 'admin_club_scope';
|
|||||||
const CLUB_CONTEXT_KEY = 'admin_club_context';
|
const CLUB_CONTEXT_KEY = 'admin_club_context';
|
||||||
const MENU_ACCESS_KEY = 'kefu_menu_access';
|
const MENU_ACCESS_KEY = 'kefu_menu_access';
|
||||||
const MENU_SESSION_KEY = 'kefu_menu_session_v';
|
const MENU_SESSION_KEY = 'kefu_menu_session_v';
|
||||||
const MENU_SESSION_VERSION = '23';
|
const MENU_SESSION_VERSION = '24';
|
||||||
const DEFAULT_CLUB_ID = 'xq';
|
const DEFAULT_CLUB_ID = 'xq';
|
||||||
|
|
||||||
let menuAccessInflight = null;
|
let menuAccessInflight = null;
|
||||||
@@ -220,15 +220,10 @@ export function canShowMenuPage(pageId) {
|
|||||||
const ids = access?.visible_page_ids;
|
const ids = access?.visible_page_ids;
|
||||||
if (!Array.isArray(ids) || ids.length === 0) return false;
|
if (!Array.isArray(ids) || ids.length === 0) return false;
|
||||||
|
|
||||||
const row = KEFU_MENU_ROWS.find((r) => r.page_id === pageId);
|
// 侧栏以服务端 visible_page_ids 为准;permission_codes 由页面/API 二次校验
|
||||||
if (row?.path && row.perm_codes?.length) {
|
|
||||||
if (!ids.includes(pageId)) return false;
|
|
||||||
return hasPermCode(access, ...row.perm_codes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ids.includes(pageId)) return true;
|
if (ids.includes(pageId)) return true;
|
||||||
const children = KEFU_MENU_PARENT_IDS[pageId];
|
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 */
|
/** 写入菜单缓存,并同步服务端校正后的 effective_club_id */
|
||||||
@@ -315,12 +310,10 @@ export async function ensureMenuAccess(fetcher, { force = false } = {}) {
|
|||||||
try {
|
try {
|
||||||
const data = await fetcher();
|
const data = await fetcher();
|
||||||
if (data) return applyMenuAccessPayload(data);
|
if (data) return applyMenuAccessPayload(data);
|
||||||
if (force) clearMenuAccess();
|
return getMenuAccess();
|
||||||
return null;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('ensureMenuAccess failed:', e);
|
console.error('ensureMenuAccess failed:', e);
|
||||||
if (force) clearMenuAccess();
|
return getMenuAccess();
|
||||||
return null;
|
|
||||||
} finally {
|
} finally {
|
||||||
menuAccessInflight = null;
|
menuAccessInflight = null;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -65,7 +65,7 @@ import { useRouter } from 'vue-router'
|
|||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { User, Lock, Key } from '@element-plus/icons-vue'
|
import { User, Lock, Key } from '@element-plus/icons-vue'
|
||||||
import axios from 'axios' // 直接使用 axios,不经过封装的 request
|
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 router = useRouter()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@@ -117,12 +117,13 @@ const handleLogin = async () => {
|
|||||||
if (res.data.club_context) {
|
if (res.data.club_context) {
|
||||||
const ctx = { ...res.data.club_context }
|
const ctx = { ...res.data.club_context }
|
||||||
if (res.data.menu_access) {
|
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
|
ctx.can_switch_club = res.data.menu_access.can_switch_club
|
||||||
}
|
}
|
||||||
setAdminClubContext(ctx)
|
setAdminClubContext(ctx)
|
||||||
} else if (res.data.menu_access) {
|
} else if (res.data.menu_access) {
|
||||||
setMenuAccess(res.data.menu_access)
|
applyMenuAccessPayload(res.data.menu_access)
|
||||||
}
|
}
|
||||||
const ma = res.data.menu_access || {}
|
const ma = res.data.menu_access || {}
|
||||||
const landing = getDefaultLandingPath(ma)
|
const landing = getDefaultLandingPath(ma)
|
||||||
|
|||||||
@@ -76,9 +76,8 @@ const logout = () => {
|
|||||||
router.replace('/login')
|
router.replace('/login')
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
const landing = getDefaultLandingPath()
|
// 不再自动跳转,避免与路由守卫形成 welcome ↔ 业务页 死循环
|
||||||
if (landing) router.replace(landing)
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ import { ElMessage } from 'element-plus'
|
|||||||
import { Refresh } from '@element-plus/icons-vue'
|
import { Refresh } from '@element-plus/icons-vue'
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import ClubScopeHint from '@/components/ClubScopeHint.vue'
|
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 route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -363,7 +363,11 @@ const getStatusType = (code) => {
|
|||||||
|
|
||||||
watch(() => route.query, () => { restoreFromQuery(); fetchOrders() }, { deep: true })
|
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())
|
hasPermission.value = hasMerchantOrderPerm(getMenuAccess())
|
||||||
if (!hasPermission.value) return
|
if (!hasPermission.value) return
|
||||||
restoreFromQuery()
|
restoreFromQuery()
|
||||||
|
|||||||
Reference in new issue
Block a user