diff --git a/src/utils/permissionManager.js b/src/utils/permissionManager.js index afc534d..c19673d 100644 --- a/src/utils/permissionManager.js +++ b/src/utils/permissionManager.js @@ -1,6 +1,6 @@ /** - * 权限管理中心 - * 负责用户身份检查、权限验证、页面路由等核心功能 + * 基于身份的权限管理中心 + * 给定某一个身份用户有某些页面的权限 */ // 用户身份类型 @@ -22,20 +22,60 @@ export const PAGES = { MESSAGE: '/message', TRANSFER: '/transfer', EXCHANGE: '/exchange-gold-coins', + PERSONAL_SALARY: '/platform-policy', + HOST_SETTING: '/host-setting', NOT_APP: '/not_app' } -// 页面权限映射表(根据你的需求) -export const PAGE_PERMISSIONS = { - [PAGES.COIN_SELLER]: [USER_ROLES.FREIGHT_AGENT], - [PAGES.AGENCY_CENTER]: [USER_ROLES.AGENT], - [PAGES.BD_CENTER]: [USER_ROLES.BD], - [PAGES.HOST_CENTER]: [USER_ROLES.ANCHOR], - [PAGES.APPLY]: [USER_ROLES.GUEST], - [PAGES.MESSAGE]: [USER_ROLES.AGENT], - [PAGES.TRANSFER]: [USER_ROLES.AGENT, USER_ROLES.BD, USER_ROLES.ANCHOR], - [PAGES.EXCHANGE]: [USER_ROLES.AGENT, USER_ROLES.BD, USER_ROLES.ANCHOR], - [PAGES.NOT_APP]: [] // 所有人都可以访问 +// 🎯 核心改变:基于身份的权限配置 +// 每个身份拥有的页面权限列表 +export const ROLE_PERMISSIONS = { + // Freight Agent (货运代理/金币销售员) + [USER_ROLES.FREIGHT_AGENT]: [ + PAGES.COIN_SELLER, // 主页面 + '/seller-records', + '/coin-seller-search' + ], + + // Agent (代理商) + [USER_ROLES.AGENT]: [ + PAGES.AGENCY_CENTER, // 主页面 + PAGES.TRANSFER, // 转账功能 + PAGES.EXCHANGE, // 兑换功能 + PAGES.MESSAGE, // 消息功能 + PAGES.PERSONAL_SALARY, // 个人薪资查看 + PAGES.COIN_SELLER, // 可以查看金币销售页面 + ], + + // BD (商务拓展) + [USER_ROLES.BD]: [ + PAGES.BD_CENTER, // 主页面 + PAGES.TRANSFER, // 转账功能 + PAGES.EXCHANGE, // 兑换功能 + PAGES.MESSAGE, // 消息功能 + PAGES.PERSONAL_SALARY, // 个人薪资查看 + PAGES.AGENCY_CENTER, // 可以查看代理页面 + ], + + // Anchor (主播) + [USER_ROLES.ANCHOR]: [ + PAGES.HOST_CENTER, // 主页面 + PAGES.TRANSFER, // 转账功能 + PAGES.EXCHANGE, // 兑换功能 + PAGES.MESSAGE, // 消息功能 + PAGES.PERSONAL_SALARY, // 个人薪资查看 + PAGES.HOST_SETTING, // 主播设置 + ], + + // Guest (访客/申请者) + [USER_ROLES.GUEST]: [ + PAGES.APPLY, // 申请页面 + ], + + // 公共页面(所有身份都可以访问) + PUBLIC_PAGES: [ + PAGES.NOT_APP, // 错误页面 + ] } // 身份优先级(数字越大优先级越高) @@ -56,13 +96,48 @@ export const ROLE_DEFAULT_PAGES = { [USER_ROLES.GUEST]: PAGES.APPLY } +// 身份显示配置 +export const ROLE_DISPLAY_CONFIG = { + [USER_ROLES.FREIGHT_AGENT]: { + name: 'Freight Agent', + tag: '💰 Coin Seller', + color: '#FCD34D', + bgColor: '#FEF3C7' + }, + [USER_ROLES.AGENT]: { + name: 'Agent', + tag: '🏢 Agency', + color: '#1E40AF', + bgColor: '#DBEAFE' + }, + [USER_ROLES.BD]: { + name: 'BD', + tag: '📈 BD', + color: '#059669', + bgColor: '#D1FAE5' + }, + [USER_ROLES.ANCHOR]: { + name: 'Anchor', + tag: '👑 Host', + color: '#5B21B6', + bgColor: '#E0E7FF' + }, + [USER_ROLES.GUEST]: { + name: 'Guest', + tag: '👤 Guest', + color: '#6B7280', + bgColor: '#F3F4F6' + } +} + /** - * 权限管理类 + * 基于身份的权限管理类 */ -class PermissionManager { +class RoleBasedPermissionManager { constructor() { this.userIdentity = null this.primaryRole = null + this.allRoles = [] this.isIdentityLoaded = false this.allowedPages = [] } @@ -73,49 +148,72 @@ class PermissionManager { */ setUserIdentity(identity) { this.userIdentity = identity - this.primaryRole = this.calculatePrimaryRole(identity) - this.allowedPages = this.calculateAllowedPages(this.primaryRole) + this.allRoles = this.calculateAllRoles(identity) + this.primaryRole = this.calculatePrimaryRole(this.allRoles) + this.allowedPages = this.calculateAllowedPages(this.allRoles) this.isIdentityLoaded = true console.debug('🔐 User identity updated:', { identity: this.userIdentity, + allRoles: this.allRoles, primaryRole: this.primaryRole, allowedPages: this.allowedPages }) } /** - * 计算用户主要身份(优先级最高的身份) + * 计算用户所有身份 * @param {Object} identity - 身份信息 - * @returns {string} 主要身份 + * @returns {Array} 所有身份列表 */ - calculatePrimaryRole(identity) { - if (!identity) return USER_ROLES.GUEST + calculateAllRoles(identity) { + if (!identity) return [USER_ROLES.GUEST] - // 按优先级检查身份 - if (identity.freightAgent) return USER_ROLES.FREIGHT_AGENT - if (identity.agent) return USER_ROLES.AGENT - if (identity.bd) return USER_ROLES.BD - if (identity.anchor) return USER_ROLES.ANCHOR + const roles = [] + if (identity.freightAgent) roles.push(USER_ROLES.FREIGHT_AGENT) + if (identity.agent) roles.push(USER_ROLES.AGENT) + if (identity.bd) roles.push(USER_ROLES.BD) + if (identity.anchor) roles.push(USER_ROLES.ANCHOR) - return USER_ROLES.GUEST + return roles.length > 0 ? roles : [USER_ROLES.GUEST] } /** - * 计算用户允许访问的页面 - * @param {string} primaryRole - 主要身份 + * 计算用户主要身份(优先级最高的身份) + * @param {Array} roles - 所有身份 + * @returns {string} 主要身份 + */ + calculatePrimaryRole(roles) { + if (!roles || roles.length === 0) return USER_ROLES.GUEST + + // 按优先级排序,返回优先级最高的身份 + return roles.reduce((highest, current) => { + return ROLE_PRIORITY[current] > ROLE_PRIORITY[highest] ? current : highest + }, USER_ROLES.GUEST) + } + + /** + * 🎯 核心方法:基于身份计算允许访问的页面 + * @param {Array} roles - 用户拥有的所有身份 * @returns {Array} 允许访问的页面列表 */ - calculateAllowedPages(primaryRole) { - const allowedPages = [] + calculateAllowedPages(roles) { + const allowedPages = new Set() - Object.entries(PAGE_PERMISSIONS).forEach(([page, roles]) => { - if (roles.length === 0 || roles.includes(primaryRole)) { - allowedPages.push(page) - } + // 添加公共页面 + ROLE_PERMISSIONS.PUBLIC_PAGES.forEach(page => { + allowedPages.add(page) }) - return allowedPages + // 根据用户拥有的每个身份,添加对应的页面权限 + roles.forEach(role => { + const rolePages = ROLE_PERMISSIONS[role] || [] + rolePages.forEach(page => { + allowedPages.add(page) + }) + }) + + return Array.from(allowedPages) } /** @@ -129,11 +227,11 @@ class PermissionManager { return false } - // 检查是否在允许列表中 const hasPermission = this.allowedPages.includes(page) console.debug('🔍 Permission check:', { page, + allRoles: this.allRoles, primaryRole: this.primaryRole, hasPermission }) @@ -141,6 +239,31 @@ class PermissionManager { return hasPermission } + /** + * 检查特定身份是否有页面权限 + * @param {string} role - 身份 + * @param {string} page - 页面路径 + * @returns {boolean} 是否有权限 + */ + hasRolePagePermission(role, page) { + const rolePages = ROLE_PERMISSIONS[role] || [] + const publicPages = ROLE_PERMISSIONS.PUBLIC_PAGES || [] + + return rolePages.includes(page) || publicPages.includes(page) + } + + /** + * 获取指定身份的所有页面权限 + * @param {string} role - 身份 + * @returns {Array} 页面权限列表 + */ + getRolePermissions(role) { + const rolePages = ROLE_PERMISSIONS[role] || [] + const publicPages = ROLE_PERMISSIONS.PUBLIC_PAGES || [] + + return [...new Set([...rolePages, ...publicPages])] + } + /** * 获取用户默认首页 * @returns {string} 默认页面路径 @@ -150,43 +273,89 @@ class PermissionManager { } /** - * 获取当前用户身份 - * @returns {string} 当前身份 + * 获取当前用户主要身份 + * @returns {string} 当前主要身份 */ getPrimaryRole() { return this.primaryRole } /** - * 获取身份显示名称 - * @param {string} role - 身份标识 - * @returns {string} 显示名称 + * 获取当前用户所有身份 + * @returns {Array} 所有身份 */ - getRoleDisplayName(role = this.primaryRole) { - const roleNames = { - [USER_ROLES.FREIGHT_AGENT]: 'Freight Agent', - [USER_ROLES.AGENT]: 'Agent', - [USER_ROLES.BD]: 'BD', - [USER_ROLES.ANCHOR]: 'Anchor', - [USER_ROLES.GUEST]: 'Guest' - } - return roleNames[role] || 'Unknown' + getAllRoles() { + return this.allRoles + } + + /** + * 获取身份显示信息 + * @param {string} role - 身份标识 + * @returns {Object} 显示信息 + */ + getRoleDisplayInfo(role = this.primaryRole) { + return ROLE_DISPLAY_CONFIG[role] || ROLE_DISPLAY_CONFIG[USER_ROLES.GUEST] } /** * 检查是否有多重身份 - * @returns {Array} 拥有的所有身份 + * @returns {boolean} 是否有多重身份 */ - getAllRoles() { - if (!this.userIdentity) return [USER_ROLES.GUEST] + hasMultipleRoles() { + return this.allRoles.length > 1 + } - const roles = [] - if (this.userIdentity.freightAgent) roles.push(USER_ROLES.FREIGHT_AGENT) - if (this.userIdentity.agent) roles.push(USER_ROLES.AGENT) - if (this.userIdentity.bd) roles.push(USER_ROLES.BD) - if (this.userIdentity.anchor) roles.push(USER_ROLES.ANCHOR) + /** + * 切换到指定身份的默认页面 + * @param {string} role - 目标身份 + * @returns {string} 目标页面路径 + */ + switchToRole(role) { + if (!this.allRoles.includes(role)) { + console.warn(`⚠️ User does not have role: ${role}`) + return this.getDefaultPage() + } - return roles.length > 0 ? roles : [USER_ROLES.GUEST] + return ROLE_DEFAULT_PAGES[role] || PAGES.APPLY + } + + /** + * 获取身份导航菜单 + * @returns {Array} 可访问的页面菜单 + */ + getNavigationMenu() { + const menu = [] + + this.allowedPages.forEach(page => { + const menuItem = this.getPageMenuInfo(page) + if (menuItem) { + menu.push(menuItem) + } + }) + + return menu + } + + /** + * 获取页面菜单信息 + * @param {string} page - 页面路径 + * @returns {Object|null} 菜单项信息 + */ + getPageMenuInfo(page) { + const pageMenuConfig = { + [PAGES.COIN_SELLER]: { title: 'Coin Seller', icon: '💰', order: 1 }, + [PAGES.AGENCY_CENTER]: { title: 'Agency Center', icon: '🏢', order: 2 }, + [PAGES.BD_CENTER]: { title: 'BD Center', icon: '📈', order: 3 }, + [PAGES.HOST_CENTER]: { title: 'Host Center', icon: '👑', order: 4 }, + [PAGES.TRANSFER]: { title: 'Transfer', icon: '💸', order: 5 }, + [PAGES.EXCHANGE]: { title: 'Exchange', icon: '🔄', order: 6 }, + [PAGES.MESSAGE]: { title: 'Messages', icon: '💬', order: 7 }, + [PAGES.PERSONAL_SALARY]: { title: 'Salary', icon: '💵', order: 8 }, + [PAGES.HOST_SETTING]: { title: 'Settings', icon: '⚙️', order: 9 } + } + + const config = pageMenuConfig[page] + return config ? { ...config, path: page } : null } /** @@ -195,6 +364,7 @@ class PermissionManager { reset() { this.userIdentity = null this.primaryRole = null + this.allRoles = [] this.isIdentityLoaded = false this.allowedPages = [] console.debug('🔄 Permission manager reset') @@ -207,14 +377,62 @@ class PermissionManager { isLoaded() { return this.isIdentityLoaded } + + /** + * 调试方法:打印当前权限状态 + */ + debugPermissions() { + console.group('🔐 Current Permission State') + console.log('User Identity:', this.userIdentity) + console.log('All Roles:', this.allRoles) + console.log('Primary Role:', this.primaryRole) + console.log('Allowed Pages:', this.allowedPages) + console.log('Default Page:', this.getDefaultPage()) + console.log('Navigation Menu:', this.getNavigationMenu()) + console.groupEnd() + } } // 创建全局权限管理实例 -export const permissionManager = new PermissionManager() +export const permissionManager = new RoleBasedPermissionManager() // 便捷方法 export const hasPermission = (page) => permissionManager.hasPagePermission(page) +export const hasRolePermission = (role, page) => permissionManager.hasRolePagePermission(role, page) +export const getRolePermissions = (role) => permissionManager.getRolePermissions(role) export const getDefaultPage = () => permissionManager.getDefaultPage() export const getPrimaryRole = () => permissionManager.getPrimaryRole() +export const getAllRoles = () => permissionManager.getAllRoles() +export const getRoleDisplayInfo = (role) => permissionManager.getRoleDisplayInfo(role) export const setUserIdentity = (identity) => permissionManager.setUserIdentity(identity) export const resetPermissions = () => permissionManager.reset() +export const switchToRole = (role) => permissionManager.switchToRole(role) +export const getNavigationMenu = () => permissionManager.getNavigationMenu() +export const debugPermissions = () => permissionManager.debugPermissions() + +// 🎯 新增:快速查询某个身份的权限 +export const QUICK_ROLE_CHECK = { + // 检查 Freight Agent 的权限 + freightAgent: { + pages: getRolePermissions(USER_ROLES.FREIGHT_AGENT), + canAccess: (page) => hasRolePermission(USER_ROLES.FREIGHT_AGENT, page) + }, + + // 检查 Agent 的权限 + agent: { + pages: getRolePermissions(USER_ROLES.AGENT), + canAccess: (page) => hasRolePermission(USER_ROLES.AGENT, page) + }, + + // 检查 BD 的权限 + bd: { + pages: getRolePermissions(USER_ROLES.BD), + canAccess: (page) => hasRolePermission(USER_ROLES.BD, page) + }, + + // 检查 Anchor 的权限 + anchor: { + pages: getRolePermissions(USER_ROLES.ANCHOR), + canAccess: (page) => hasRolePermission(USER_ROLES.ANCHOR, page) + } +} diff --git a/src/views/CoinSellerSearchView.vue b/src/views/CoinSellerSearchView.vue index e65643a..334f5ae 100644 --- a/src/views/CoinSellerSearchView.vue +++ b/src/views/CoinSellerSearchView.vue @@ -12,7 +12,8 @@ type="text" placeholder="Please enter the host ID" class="search-input" - @keyup.enter="performSearch" +@keyup.enter="handleEnterPress" + @input="handleInputChange" /> @@ -36,7 +39,8 @@ v-for="user in searchResults" :key="user.id" class="user-item" - @click="selectUser(user)" + :class="{ 'selected': selectedUser?.id === user.id }" + @click="toggleUserSelection(user)" >
@@ -84,7 +88,7 @@ @@ -249,6 +286,18 @@ const selectUser = (user) => { color: #7C3AED; } +.action-btn.confirm { + background-color: #8B5CF6; + color: white; + border-radius: 6px; + padding: 6px 12px; +} + +.action-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + /* 搜索结果 */ .results-section { display: flex; @@ -272,6 +321,16 @@ const selectUser = (user) => { transform: scale(0.98); } +.user-item.selected { + border: 2px solid #8B5CF6; + background-color: #F3F4F6; +} + +.user-item.selected .add-icon { + color: #8B5CF6; + font-weight: bold; +} + .user-info { display: flex; align-items: center; diff --git a/src/views/CoinSellerView.vue b/src/views/CoinSellerView.vue index afa2145..118ea7c 100644 --- a/src/views/CoinSellerView.vue +++ b/src/views/CoinSellerView.vue @@ -28,7 +28,7 @@

ID: {{ userInfo.id || userInfo.id }}

@@ -97,7 +97,7 @@ import { useRouter } from 'vue-router' import MobileHeader from '../components/MobileHeader.vue' import { getSelectedUser } from '../utils/coinSellerStore.js' import { checkFreightDealer, getTeamEntry, getFreightBalance, freightRecharge } from '../api/wallet.js' -import {showError} from "@/utils/toast.js"; +import {showError, showSuccess} from "@/utils/toast.js"; import {usePageInitializationWithConfig} from "@/utils/pageConfig.js"; const router = useRouter() @@ -215,14 +215,14 @@ const rechargeNow = async () => { const amount = parseFloat(rechargeAmount.value) if (amount <= 0) { - showError('请输入正确的充值金额') + showError('Please enter the correct recharge amount') return } // 需要获取接收用户的ID(从用户搜索结果中获取) const acceptUserId = selectedUser.value.userId || selectedUser.value.id if (!acceptUserId) { - showError('无法获取用户ID,请重新选择用户') + showError('The user ID cannot be obtained. Please select the user again') return } @@ -242,7 +242,7 @@ const rechargeNow = async () => { coinsAmount.value = response.body.toString() } - showError(`成功向 ${selectedUser.value.name} 充值 ${amount} 金币`) + showSuccess(`成功向 ${selectedUser.value.name} 充值 ${amount} 金币`) // 重置表单 rechargeAmount.value = '' @@ -261,10 +261,9 @@ const { userInfo } = usePageInitializationWithConfig('COIN_SELLER', { onDataLoaded: (data) => { - console.log('ddddddddddddddddddddddddd') - console.log(data) checkDealerAccess() fetchFreightBalance() + initializeUser() } }) diff --git a/src/views/SellerRecordsView.vue b/src/views/SellerRecordsView.vue index 9789830..680cc60 100644 --- a/src/views/SellerRecordsView.vue +++ b/src/views/SellerRecordsView.vue @@ -9,8 +9,8 @@
-
@@ -42,40 +42,14 @@