import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { getToken, setToken, removeToken, setUserInfo, removeUserInfo, getUserInfo } from '@/utils/storage' import { login as loginApi, logout as logoutApi, getUserInfoApi } from '@/api/auth' /** * 用户状态 Store * 管理登录状态、用户信息、Token、权限路由列表 */ export const useUserStore = defineStore('user', () => { // 状态 const token = ref(getToken() || '') const userInfo = ref(getUserInfo() || {}) // 计算属性 const isLoggedIn = computed(() => !!token.value) const username = computed(() => userInfo.value?.username || '') const nickname = computed(() => userInfo.value?.nickname || userInfo.value?.username || '') const avatar = computed(() => userInfo.value?.avatar || '/default-avatar.png') /** * 管理员角色:1=超级管理员,2=设备管理员,3=圣手管理 * 超级管理员拥有所有菜单权限 */ const adminRole = computed(() => userInfo.value?.adminRole || null) /** * 权限路由路径列表(JSON字符串解析后的数组) * 超级管理员(adminRole=1)此值为 null,前端视为拥有全部权限 * 其他角色为可访问的路由路径数组,如 ['/dashboard', '/device'] */ const permissions = computed(() => { const raw = userInfo.value?.permissions if (raw === null || raw === undefined) return null // 超级管理员:全部权限 if (typeof raw === 'string') { try { return JSON.parse(raw).map(normalizePermissionPath).filter(Boolean) } catch { return [] } } if (Array.isArray(raw)) return raw.map(normalizePermissionPath).filter(Boolean) return [] }) /** * 判断是否有指定路由的权限 * @param {string} path 路由 path */ function hasPermission(path) { if (adminRole.value === 1) return true // 超级管理员全部通过 if (permissions.value === null) return true // null 也视为全部权限 return permissions.value.includes(normalizePermissionPath(path)) } /** * 登录 * @param {Object} loginData 登录参数 { username, password } */ async function login(loginData) { const res = await loginApi(loginData) const { token: newToken, ...info } = res.data // 保存 Token 到内存和 localStorage token.value = newToken setToken(newToken) // 保存用户基本信息(含 adminRole 和 permissions) userInfo.value = info setUserInfo(info) return res } /** * 退出登录 * 清除本地状态并调用后端退出接口 */ async function logout() { try { await logoutApi() } catch (e) { // 退出接口失败不影响本地清除 } clearUser() } /** * 获取最新用户信息(从后端刷新,含权限路由) */ async function fetchUserInfo() { const res = await getUserInfoApi() userInfo.value = res.data setUserInfo(res.data) return res.data } /** * 清除用户状态(退出登录时调用) */ function clearUser() { token.value = '' userInfo.value = {} removeToken() removeUserInfo() } return { token, userInfo, isLoggedIn, username, nickname, avatar, adminRole, permissions, hasPermission, login, logout, fetchUserInfo, clearUser } }) function normalizePermissionPath(path) { if (!path || typeof path !== 'string') return '' const cleanPath = path.split('?')[0].split('#')[0].trim() if (cleanPath === '/admin') return '/system/admin' if (cleanPath === '/log') return '/system/log' return cleanPath }