import { useStorage } from '@vueuse/core' import { acceptHMRUpdate, defineStore } from 'pinia' import { ref } from 'vue' import router from '@/router' import { resolveMenu, resolveRoute } from '@/router/helper' import { routeRecordRaw } from '@/router/record' import type { MergeMenuMixedOptions } from '@/router/helper' import type { MenuProps } from 'naive-ui' import type { RouteRecordRaw } from 'vue-router' import { parseJwtToken, type JwtPayload } from '@/utils/casdoor/token' interface User { avatar?: string id?: string name?: string role?: 'admin' | 'user' permissions: UserPermissions } interface UserPermissions { isAdmin: boolean items: UserPermissionsItems } interface UserPermissionsItems { xlog?: boolean // xlog操作权限 autoUpdate?: boolean // 自动升级配置页面操作权限 faultRecord?: boolean // 故障录波操作权限 } const DEFAULT_USER: User = { avatar: '', id: '2000', name: 'FWH User', role: 'user', permissions: { isAdmin: false, items: {}, }, } // 特权菜单定义 const adminMenuNames: string[] = [ 'backgroundTask', // 后台任务管理 ] as const const xlogMenuNames: string[] = [ 'xlogManage', // XLOG管理 'xlogTerminal', // XLOG终端 ] as const const autoUpdateMenuNames: string[] = [ 'autoUpdate', // 自动升级 'autoUpdatePackage', // 升级包管理 'autoUpdateAPowerVersion', // aPower版本管理 'autoUpdateConfig', // 自动升级配置 'autoUpdateConfigFile', // 配置文件管理 ] as const const faultRecordMenuNames: string[] = [ 'faultRecord', // 故障录波主菜单 'faultRecordRead', // 故障录波参数读界面 'faultRecordWrite', // 故障录波参数写界面 ] as const const parsePermissions = (payload: JwtPayload): User => { return { avatar: '', id: payload.id, name: payload.name, role: payload.isAdmin ? 'admin' : 'user', permissions: { isAdmin: payload.isAdmin, items: payload.permissions.reduce((acc, cur) => { switch (cur.name) { case 'xlog': acc.xlog = true break case 'autoUpdate': acc.autoUpdate = true break case 'faultRecord': acc.faultRecord = true break } return acc }, {}), }, } } export const useUserStore = defineStore('userStore', () => { const user = useStorage('user', DEFAULT_USER) const token = useStorage('token', undefined) const tokenPayload = useStorage('tokenPayload', undefined, undefined, { serializer: { read: (v: string) => (v ? (v !== '' ? JSON.parse(v) : undefined) : undefined), write: (v: JwtPayload | undefined) => (v ? JSON.stringify(v) : ''), }, }) const menuList = ref([]) const routeList = ref([]) const getUserInfo = (): User => { return user.value } const setToken = (value: string | undefined) => { token.value = value if (value !== undefined) { const jwtData = parseJwtToken(value) console.log({ jwtData, jwtDataStr: JSON.stringify(jwtData) }) tokenPayload.value = jwtData user.value = parsePermissions(jwtData) } else { tokenPayload.value = undefined user.value = DEFAULT_USER } } async function resolveMenuList() { const res = await new Promise((resolve) => { if (tokenPayload.value !== undefined) { if (user.value.permissions.isAdmin) { resolve(routeRecordRaw) } else { // const allowedRoutes = tokenPayload.value.roles.map((role) => role.domains).flat() // const filterRoutes = (routeRecord: MergeMenuMixedOptions[]) => { // return routeRecord // .map((route): MergeMenuMixedOptions | undefined => { // const selfAllowed = // !route.type && route.name && allowedRoutes.includes(route.name as string) // if (selfAllowed) return route // // 先递归处理 children // if (!('children' in route) || route.children === undefined) { // return undefined // } // const result = { ...route } // result.children = filterRoutes(route.children) // return result // }) // .filter((item): item is MergeMenuMixedOptions => Boolean(item)) // } // resolve(filterRoutes(routeRecordRaw)) const permissionsItems = user.value.permissions.items resolve( routeRecordRaw.filter((route) => { if (route.type === undefined && typeof route.name === 'string') { // 清除admin权限页面 if (adminMenuNames.includes(route.name)) { return false } // xlog界面控制 if (permissionsItems.xlog !== true) { if (xlogMenuNames.includes(route.name)) { return false } } // autoUpdate界面控制 if (permissionsItems.autoUpdate !== true) { if (autoUpdateMenuNames.includes(route.name)) { return false } } // faultRecord界面控制 if (permissionsItems.faultRecord !== true) { if (faultRecordMenuNames.includes(route.name)) { return false } } } return true }), ) } } else { cleanup() resolve([]) } // if (token.value?.includes('admin')) { // resolve(routeRecordRaw) // } else { // const allowedRoutes = ['dashboard', 'dataShow', 'notfoundPage', 'about'] // const filteredRoutes = routeRecordRaw.filter((route) => { // return !route.type && route.name && allowedRoutes.includes(route.name as string) // }) // resolve(filteredRoutes) // } // 暂时没有管理员权限 // resolve(routeRecordRaw) }) menuList.value = resolveMenu(res) || [] routeList.value = resolveRoute(res) || [] } function cleanup(redirectPath?: string) { router.replace({ name: 'signin', ...(redirectPath ? { query: { r: redirectPath } } : {}), }) token.value = undefined if (router.hasRoute('layout')) { router.removeRoute('layout') } menuList.value = [] routeList.value = [] } return { user, token, tokenPayload, menuList, routeList, resolveMenuList, getUserInfo, setToken, cleanup, } }) if (import.meta.hot) { import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot)) }