/** * 全局双身份与角色守卫管理模块 (Role Guard Manager) * 覆盖四大核心角色: * 1. PLAYER: 普通买家/玩家 * 2. EXPERT: 陪玩大神/接单人 * 3. HOST: 车队房主/局长 * 4. ADMIN: 平台管理员/运营端 */ export const ROLE_TYPES = { PLAYER: 'PLAYER', // 发单人端(普通玩家/发起活动/找陪玩) EXPERT: 'EXPERT', // 接单人端(大神接单/5km雷达定位/核销) HOST: 'HOST', // 车队房主/局长(发起AA组局/动态调价/解散退款/到场核销) ADMIN: 'ADMIN', // 平台管理员(资质审核/争议仲裁/大盘监管) }; export const CERT_STATUS = { NONE: 0, // 未提交 PENDING: 1, // 待审核 APPROVED: 2, // 审核通过 REJECTED: 3, // 驳回 }; const STORAGE_KEY_ROLE = 'PW_CURRENT_USER_ROLE'; const STORAGE_KEY_CERT = 'PW_EXPERT_CERT_STATUS'; export function getExpertCertStatus() { try { const saved = uni.getStorageSync(STORAGE_KEY_CERT); if (saved !== '' && saved !== null && saved !== undefined) { return Number(saved); } return CERT_STATUS.NONE; } catch (e) { return CERT_STATUS.NONE; } } export function setExpertCertStatus(status) { const target = Number(status); try { uni.setStorageSync(STORAGE_KEY_CERT, target); } catch (e) { console.error('Failed to persist cert status', e); } uni.$emit('cert-status-change', target); if (target !== CERT_STATUS.APPROVED) { setCurrentRole(ROLE_TYPES.PLAYER); } return target; } export function isExpertCertified() { return getExpertCertStatus() === CERT_STATUS.APPROVED; } export function canSwitchToRole(targetRole) { if (targetRole === ROLE_TYPES.EXPERT) { if (!isExpertCertified()) { return { allowed: false, reason: '尚未开通或通过大神实名认证,无法切换至接单模式', }; } } return { allowed: true }; } export function getCurrentRole() { try { const saved = uni.getStorageSync(STORAGE_KEY_ROLE); if (saved === ROLE_TYPES.EXPERT) { if (isExpertCertified()) { return ROLE_TYPES.EXPERT; } return ROLE_TYPES.PLAYER; } return ROLE_TYPES.PLAYER; } catch (e) { return ROLE_TYPES.PLAYER; } } export function setCurrentRole(role) { let target = role === ROLE_TYPES.EXPERT ? ROLE_TYPES.EXPERT : ROLE_TYPES.PLAYER; if (target === ROLE_TYPES.EXPERT && !isExpertCertified()) { console.warn('[RoleGuard] 未认证大神禁止切换至接单端,已自动降级回玩家端'); target = ROLE_TYPES.PLAYER; } try { uni.setStorageSync(STORAGE_KEY_ROLE, target); } catch (e) { console.error('Failed to persist user role', e); } uni.$emit('role-change', target); return target; } export function toggleRole() { const current = getCurrentRole(); if (current === ROLE_TYPES.PLAYER) { if (!isExpertCertified()) { return { success: false, currentRole: ROLE_TYPES.PLAYER, message: '尚未通过大神实名认证,请先提交入驻认证', }; } setCurrentRole(ROLE_TYPES.EXPERT); return { success: true, currentRole: ROLE_TYPES.EXPERT, message: '已切换至大神接单模式', }; } else { setCurrentRole(ROLE_TYPES.PLAYER); return { success: true, currentRole: ROLE_TYPES.PLAYER, message: '已切回发单人端', }; } } // 非大神禁止访问的受保护页面清单 export const EXPERT_GUARD_PAGES = [ '/pages/expert/workspace', '/pages/expert/radar', '/pages/expert/hall', ]; export function checkRoleGuard(pageUrl) { if (!pageUrl) return { allowed: true }; const pureUrl = pageUrl.split('?')[0]; if (EXPERT_GUARD_PAGES.includes(pureUrl)) { if (!isExpertCertified()) { return { allowed: false, code: 'FORBIDDEN_NOT_EXPERT', redirectUrl: '/pages/user/index', message: '非大神禁止访问接单工作台与雷达,请先在个人中心完成实名认证', }; } } return { allowed: true }; } let guardInstalled = false; export function installRoleGuard() { if (guardInstalled) return; guardInstalled = true; const routeMethods = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab']; routeMethods.forEach((method) => { try { if (typeof uni !== 'undefined' && typeof uni.addInterceptor === 'function') { uni.addInterceptor(method, { invoke(args) { if (!args || !args.url) return true; const check = checkRoleGuard(args.url); if (!check.allowed) { uni.showToast({ title: check.message || '非大神禁止访问接单页面', icon: 'none', duration: 2000, }); return false; } return true; }, }); } } catch (e) {} }); }