231 lines
6.1 KiB
TypeScript
231 lines
6.1 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import request from '@/utils/request'
|
|
|
|
export interface MenuItem {
|
|
id: string
|
|
name: string
|
|
path: string
|
|
icon?: string
|
|
parentId?: string
|
|
sort: number
|
|
children?: MenuItem[]
|
|
}
|
|
|
|
interface BackendMenuItem {
|
|
id: string
|
|
menuName: string
|
|
parentId: string
|
|
orderNum: number
|
|
menuType: string
|
|
perms?: string
|
|
component?: string
|
|
status: number
|
|
children?: BackendMenuItem[]
|
|
}
|
|
|
|
function transformMenuData(backendMenus: BackendMenuItem[]): MenuItem[] {
|
|
const menuMap = new Map<string, MenuItem>()
|
|
const rootMenus: MenuItem[] = []
|
|
|
|
const componentToPathMap: Record<string, string> = {
|
|
'system/user/index': '/users',
|
|
'system/role/index': '/roles',
|
|
'system/menu/index': '/menus',
|
|
'system/coach/index': '/coach',
|
|
'system/dict/index': '/dict',
|
|
'system/config/index': '/sys/config',
|
|
'system/notice/index': '/notice',
|
|
'system/file/index': '/files',
|
|
'audit/operation/index': '/oplog',
|
|
'audit/login/index': '/loginlog',
|
|
'audit/exception/index': '/exceptionlog',
|
|
'gymCourse/course/index': '/courses',
|
|
'gymCourse/type/index': '/courses/types',
|
|
'gymCourse/label/index': '/courses/labels',
|
|
'gymCourse/recommend/index': '/courses/recommend',
|
|
'member/member/index': '/members',
|
|
'member/card/index': '/member-cards',
|
|
'statistics/dashboard/index': '/statistics',
|
|
'banner/index': '/banners',
|
|
'brand/index': '/brand',
|
|
}
|
|
|
|
const filteredMenus = backendMenus.filter(menu => menu.menuType !== 'F')
|
|
|
|
filteredMenus.forEach(menu => {
|
|
const menuItem: MenuItem = {
|
|
id: menu.id,
|
|
name: menu.menuName,
|
|
path: menu.component ? (componentToPathMap[menu.component] || `/${menu.component.replace('/index', '').replace('system/', '')}`) : '',
|
|
icon: getMenuIcon(menu.menuName),
|
|
parentId: menu.parentId === '0' ? undefined : menu.parentId,
|
|
sort: menu.orderNum
|
|
}
|
|
menuMap.set(menu.id, menuItem)
|
|
})
|
|
|
|
filteredMenus.forEach(menu => {
|
|
const menuItem = menuMap.get(menu.id)!
|
|
if (menu.parentId === '0') {
|
|
rootMenus.push(menuItem)
|
|
} else {
|
|
const parentMenu = menuMap.get(menu.parentId)
|
|
if (parentMenu) {
|
|
if (!parentMenu.children) {
|
|
parentMenu.children = []
|
|
}
|
|
parentMenu.children.push(menuItem)
|
|
}
|
|
}
|
|
})
|
|
|
|
rootMenus.forEach(menu => {
|
|
if (menu.children) {
|
|
menu.children.sort((a, b) => a.sort - b.sort)
|
|
}
|
|
})
|
|
|
|
return rootMenus.sort((a, b) => a.sort - b.sort)
|
|
}
|
|
|
|
function getMenuIcon(menuName: string): string {
|
|
const iconMap: Record<string, string> = {
|
|
'系统管理': 'Setting',
|
|
'审计日志': 'Document',
|
|
'系统监控': 'Monitor',
|
|
'用户管理': 'User',
|
|
'教练管理': 'Medal',
|
|
'角色管理': 'UserFilled',
|
|
'菜单管理': 'Menu',
|
|
'字典管理': 'Collection',
|
|
'参数配置': 'Tools',
|
|
'通知公告': 'Bell',
|
|
'文件管理': 'Folder',
|
|
'操作日志': 'Document',
|
|
'登录日志': 'Document',
|
|
'异常日志': 'Warning',
|
|
'团课管理': 'TrophyBase',
|
|
'团课类型': 'Grid',
|
|
'团课标签': 'Discount',
|
|
'团课推荐': 'Star',
|
|
'会员管理': 'Avatar',
|
|
'会员卡管理': 'CreditCard',
|
|
'数据统计': 'DataAnalysis',
|
|
'轮播图管理': 'Picture',
|
|
'品牌定制': 'Brush',
|
|
}
|
|
return iconMap[menuName] || 'Document'
|
|
}
|
|
|
|
interface PermissionState {
|
|
roles: string[]
|
|
permissions: string[]
|
|
menus: MenuItem[]
|
|
loaded: boolean
|
|
}
|
|
|
|
export const usePermissionStore = defineStore('permission', {
|
|
state: (): PermissionState => ({
|
|
roles: [],
|
|
permissions: [],
|
|
menus: [],
|
|
loaded: false
|
|
}),
|
|
|
|
getters: {
|
|
hasRole: (state) => (role: string | string[]) => {
|
|
if (Array.isArray(role)) {
|
|
return role.some(r => state.roles.includes(r))
|
|
}
|
|
return state.roles.includes(role)
|
|
},
|
|
|
|
hasPermission: (state) => (permission: string | string[]) => {
|
|
if (Array.isArray(permission)) {
|
|
return permission.some(p => state.permissions.includes(p))
|
|
}
|
|
return state.permissions.includes(permission)
|
|
}
|
|
},
|
|
|
|
actions: {
|
|
setPermissionData(data: {
|
|
roles: string[]
|
|
permissions: string[]
|
|
menus: MenuItem[]
|
|
}) {
|
|
this.roles = data.roles
|
|
this.permissions = data.permissions
|
|
this.menus = data.menus
|
|
this.loaded = true
|
|
|
|
this.saveToStorage()
|
|
},
|
|
|
|
clearPermissionData() {
|
|
this.roles = []
|
|
this.permissions = []
|
|
this.menus = []
|
|
this.loaded = false
|
|
|
|
localStorage.removeItem('permission')
|
|
},
|
|
|
|
saveToStorage() {
|
|
const data = {
|
|
roles: this.roles,
|
|
permissions: this.permissions,
|
|
menus: this.menus
|
|
}
|
|
localStorage.setItem('permission', JSON.stringify(data))
|
|
},
|
|
|
|
initFromStorage() {
|
|
const stored = localStorage.getItem('permission')
|
|
if (stored) {
|
|
try {
|
|
const data = JSON.parse(stored)
|
|
this.roles = data.roles || []
|
|
this.permissions = data.permissions || []
|
|
this.menus = data.menus || []
|
|
this.loaded = true
|
|
} catch (error) {
|
|
console.error('从 localStorage 恢复权限数据失败:', error)
|
|
}
|
|
}
|
|
},
|
|
|
|
async fetchUserMenus() {
|
|
try {
|
|
const res: any = await request.get('/menus')
|
|
|
|
if (res && Array.isArray(res)) {
|
|
const transformedMenus = transformMenuData(res)
|
|
|
|
const permissions: string[] = []
|
|
const extractPermissions = (menus: BackendMenuItem[]) => {
|
|
menus.forEach(menu => {
|
|
if (menu.perms) {
|
|
permissions.push(menu.perms)
|
|
}
|
|
if (menu.children && menu.children.length > 0) {
|
|
extractPermissions(menu.children)
|
|
}
|
|
})
|
|
}
|
|
extractPermissions(res)
|
|
|
|
this.setPermissionData({
|
|
roles: JSON.parse(localStorage.getItem('roles') || '[]'),
|
|
permissions: permissions,
|
|
menus: transformedMenus
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error('获取用户菜单失败:', error)
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
})
|