fix: login landing from menu_access, silent optional Layout 403
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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 = '8';
|
||||
const MENU_SESSION_VERSION = '11';
|
||||
const DEFAULT_CLUB_ID = 'xq';
|
||||
|
||||
let menuAccessInflight = null;
|
||||
@@ -82,24 +82,145 @@ export function isMenuSessionFresh() {
|
||||
export function shouldShowAllMenus(access) {
|
||||
if (!isMenuSessionFresh()) return true;
|
||||
if (!access) return true;
|
||||
if (access.menu_ready === false) return true;
|
||||
if (!Array.isArray(access.visible_page_ids) || !Array.isArray(access.visible_paths)) return true;
|
||||
return false;
|
||||
if (Array.isArray(access.visible_page_ids) && access.visible_page_ids.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(access.visible_paths) && access.visible_paths.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(access.permission_codes) && access.permission_codes.length > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** ??? kefu_menu_definitions ???visible_paths ???? permission_codes ?? */
|
||||
const KEFU_MENU_ROWS = [
|
||||
{ page_id: 'finance.bankuai', parent_id: 'finance', path: '/finance/bankuai', sort_order: 11, perm_codes: ['bankuai'] },
|
||||
{ page_id: 'finance.data', parent_id: 'finance', path: '/finance/data', sort_order: 12, perm_codes: ['caiwu'] },
|
||||
{ page_id: 'assessment.examiner', parent_id: 'assessment', path: '/assessment/examiner', sort_order: 21, perm_codes: ['kaohepeizhi'] },
|
||||
{ page_id: 'assessment.config', parent_id: 'assessment', path: '/assessment/config', sort_order: 22, perm_codes: ['kaohepeizhi'] },
|
||||
{ page_id: 'assessment.record', parent_id: 'assessment', path: '/assessment/record', sort_order: 23, perm_codes: ['kaohepeizhi'] },
|
||||
{ page_id: 'order.platform', parent_id: 'order', path: '/order/platform', sort_order: 31, perm_codes: ['002ab'] },
|
||||
{ page_id: 'order.merchant', parent_id: 'order', path: '/order/merchant', sort_order: 32, perm_codes: ['002ac'] },
|
||||
{ page_id: 'cross-platform.order', parent_id: 'cross-platform', path: '/cross-order', sort_order: 41, perm_codes: ['003aa'] },
|
||||
{ page_id: 'cross-platform.settings', parent_id: 'cross-platform', path: '/cross-settings', sort_order: 42, perm_codes: ['003aa'] },
|
||||
{ page_id: 'cross-platform.data', parent_id: 'cross-platform', path: '/cross-data', sort_order: 43, perm_codes: ['003aa'] },
|
||||
{ page_id: 'cross-platform.pre', parent_id: 'cross-platform', path: '/cross-pre', sort_order: 44, perm_codes: ['003aa'] },
|
||||
{ page_id: 'user.player', parent_id: 'user', path: '/user/player', sort_order: 51, perm_codes: ['001aa', '001bb', '001cc', '001dd', '001ee', '001ff', '001gg'] },
|
||||
{ page_id: 'user.guanli', parent_id: 'user', path: '/user/guanli', sort_order: 52, perm_codes: ['4400a', '4400b', '4400c', '4400d', '4400e', '4400f'] },
|
||||
{ page_id: 'user.shangjia', parent_id: 'user', path: '/user/shangjia', sort_order: 53, perm_codes: ['1100a', '1100b'] },
|
||||
{ page_id: 'user.zuzhang', parent_id: 'user', path: '/user/zuzhang', sort_order: 54, perm_codes: ['6600a', '6600b', '6600c', '6600d', '6600e'] },
|
||||
{ page_id: 'user.identity-tag', parent_id: 'user', path: '/user/identity-tag', sort_order: 55, perm_codes: ['8080a', 'sfbq666'] },
|
||||
{ page_id: 'withdraw.audit', parent_id: 'withdraw', path: '/withdraw/audit', sort_order: 61, perm_codes: ['005bb'] },
|
||||
{ page_id: 'withdraw.data', parent_id: 'withdraw', path: '/withdraw/data', sort_order: 63, perm_codes: ['005bb'] },
|
||||
{ page_id: 'withdraw.settings', parent_id: 'withdraw', path: '/withdraw/settings', sort_order: 64, perm_codes: ['5500a', '5500b', '5500c'] },
|
||||
{ page_id: 'punishment', parent_id: '', path: '/punishment', sort_order: 80, perm_codes: ['005aa', '66693a', '66693b', '66693c', '66694c', '99933abs'] },
|
||||
{ page_id: 'product.list', parent_id: 'product', path: '/product/list', sort_order: 91, perm_codes: ['2200a'] },
|
||||
{ page_id: 'product.type-zone', parent_id: 'product', path: '/product/type-zone', sort_order: 92, perm_codes: ['7007a'] },
|
||||
{ page_id: 'product.data', parent_id: 'product', path: '/product/data', sort_order: 93, perm_codes: ['2200a'] },
|
||||
{ page_id: 'member.list', parent_id: 'member', path: '/member/list', sort_order: 101, perm_codes: ['3300a'] },
|
||||
{ page_id: 'member.data', parent_id: 'member', path: '/member/data', sort_order: 102, perm_codes: ['huiyuancaiwu'] },
|
||||
{ page_id: 'miniapp.carousel', parent_id: 'miniapp', path: '/miniapp/carousel', sort_order: 111, perm_codes: ['8080a'] },
|
||||
{ page_id: 'miniapp.assets', parent_id: 'miniapp', path: '/miniapp/assets', sort_order: 112, perm_codes: ['8080a'] },
|
||||
{ page_id: 'miniapp.popup', parent_id: 'miniapp', path: '/miniapp/popup-notice', sort_order: 113, perm_codes: ['8080a'] },
|
||||
{ page_id: 'miniapp.leixing', parent_id: 'miniapp', path: '/miniapp/leixing', sort_order: 115, perm_codes: ['8080a'] },
|
||||
{ page_id: 'miniapp.kaohe-tags', parent_id: 'miniapp', path: '/miniapp/kaohe-tags', sort_order: 116, perm_codes: ['8080a'] },
|
||||
{ page_id: 'miniapp.dashou-exam', parent_id: 'miniapp', path: '/miniapp/dashou-exam', sort_order: 117, perm_codes: ['dsks666', '8080a'] },
|
||||
{ page_id: 'shop.list', parent_id: 'shop', path: '/shop/list', sort_order: 121, perm_codes: ['999a', '999b', '999c', '999d', '999e'] },
|
||||
{ page_id: 'shop.withdraw', parent_id: 'shop', path: '/shop/withdraw-apply', sort_order: 122, perm_codes: ['999a', '999b', '999c', '999d', '999e'] },
|
||||
{ page_id: 'shop.products', parent_id: 'shop', path: '/shop/products', sort_order: 123, perm_codes: ['999a', '999b', '999c', '999d', '999e'] },
|
||||
{ page_id: 'chat.agent', parent_id: '', path: '/chat/agent', sort_order: 130, perm_codes: ['abca1', 'baac2', 'cabc3', 'cb3a2', 'bcaa4'] },
|
||||
];
|
||||
|
||||
const KEFU_MENU_PARENT_IDS = {
|
||||
finance: ['finance.bankuai', 'finance.data'],
|
||||
assessment: ['assessment.examiner', 'assessment.config', 'assessment.record'],
|
||||
order: ['order.platform', 'order.merchant'],
|
||||
'cross-platform': ['cross-platform.order', 'cross-platform.settings', 'cross-platform.data', 'cross-platform.pre'],
|
||||
user: ['user.player', 'user.guanli', 'user.shangjia', 'user.zuzhang', 'user.identity-tag'],
|
||||
withdraw: ['withdraw.audit', 'withdraw.data', 'withdraw.settings'],
|
||||
product: ['product.list', 'product.type-zone', 'product.data'],
|
||||
member: ['member.list', 'member.data'],
|
||||
miniapp: ['miniapp.carousel', 'miniapp.assets', 'miniapp.popup', 'miniapp.leixing', 'miniapp.kaohe-tags', 'miniapp.dashou-exam', 'miniapp.withdraw-settings'],
|
||||
shop: ['shop.list', 'shop.withdraw', 'shop.products'],
|
||||
};
|
||||
|
||||
function pathsFromPermissionCodes(codes) {
|
||||
if (!codes?.length) return [];
|
||||
const seen = new Set();
|
||||
const paths = [];
|
||||
for (const row of KEFU_MENU_ROWS) {
|
||||
if (!row.path) continue;
|
||||
const perms = row.perm_codes || [];
|
||||
if (!perms.some((p) => codes.includes(p))) continue;
|
||||
if (seen.has(row.path)) continue;
|
||||
seen.add(row.path);
|
||||
paths.push(row.path);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
function pageAllowedByCodes(pageId, codes) {
|
||||
const row = KEFU_MENU_ROWS.find((r) => r.page_id === pageId);
|
||||
if (row?.perm_codes?.some((p) => codes.includes(p))) return true;
|
||||
const children = KEFU_MENU_PARENT_IDS[pageId];
|
||||
if (!children) return false;
|
||||
return children.some((childId) => pageAllowedByCodes(childId, codes));
|
||||
}
|
||||
|
||||
export function getEffectiveVisiblePaths(access = null) {
|
||||
const a = access || getMenuAccess();
|
||||
const paths = a?.visible_paths;
|
||||
if (Array.isArray(paths) && paths.length > 0) {
|
||||
return paths;
|
||||
}
|
||||
return pathsFromPermissionCodes(a?.permission_codes || []);
|
||||
}
|
||||
|
||||
export function canShowMenuPage(pageId) {
|
||||
const access = getMenuAccess();
|
||||
if (shouldShowAllMenus(access)) return true;
|
||||
if (access.visible_page_ids.length === 0) return false;
|
||||
return access.visible_page_ids.includes(pageId);
|
||||
const ids = access?.visible_page_ids;
|
||||
if (Array.isArray(ids) && ids.length > 0) {
|
||||
if (ids.includes(pageId)) return true;
|
||||
const children = KEFU_MENU_PARENT_IDS[pageId];
|
||||
return children ? children.some((id) => ids.includes(id)) : false;
|
||||
}
|
||||
const codes = access?.permission_codes || [];
|
||||
if (!codes.length) return false;
|
||||
return pageAllowedByCodes(pageId, codes);
|
||||
}
|
||||
|
||||
export function getFirstVisiblePath() {
|
||||
const access = getMenuAccess();
|
||||
if (!access || !Array.isArray(access.visible_paths) || access.visible_paths.length === 0) {
|
||||
return null;
|
||||
const paths = getEffectiveVisiblePaths();
|
||||
return paths.length > 0 ? paths[0] : null;
|
||||
}
|
||||
|
||||
export function getDefaultLandingPath(access = null) {
|
||||
const paths = getEffectiveVisiblePaths(access);
|
||||
return paths.length > 0 ? paths[0] : null;
|
||||
}
|
||||
|
||||
/** menu_ready=false: server seed missing; empty codes: role not bound */
|
||||
export function formatNoMenuAccessMessage(access) {
|
||||
const codes = access?.permission_codes || [];
|
||||
const roles = access?.role_names || [];
|
||||
const uid = access?.yonghuid || '';
|
||||
const idHint = uid ? ` UserID=${uid}.` : '';
|
||||
if (access?.menu_ready === false && access?.menu_source === 'db') {
|
||||
return `Menu table empty.${idHint} Server: python manage.py migrate jituan && python manage.py seed_kefu_menu`;
|
||||
}
|
||||
return access.visible_paths[0];
|
||||
if (!codes.length) {
|
||||
if (roles.length) {
|
||||
return `No permissions.${idHint} Roles: [${roles.join(', ')}]. Add perm kaohepeizhi to these roles in Role Mgmt.`;
|
||||
}
|
||||
return `No role on account.${idHint} Admin Users -> open THIS user (check UserID) -> Add Role -> Save -> re-login.`;
|
||||
}
|
||||
if (!getEffectiveVisiblePaths(access).length) {
|
||||
return `Perms: [${codes.join(', ')}].${idHint} No menu path from server.`;
|
||||
}
|
||||
return `Perms: [${codes.join(', ')}].${idHint} Contact admin.`;
|
||||
}
|
||||
|
||||
export function canSwitchClubByMenu() {
|
||||
|
||||
Reference in New Issue
Block a user