2025-11-05 16:51:07 +08:00
|
|
|
|
import { defineStore } from 'pinia'
|
2025-11-26 17:47:12 +08:00
|
|
|
|
import { ADMIN_ROLES, normalizePermissions } from '@/utils/permission'
|
2025-11-26 15:59:57 +08:00
|
|
|
|
|
2025-11-05 16:51:07 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 用户信息 Store
|
|
|
|
|
|
* 用于管理用户登录状态、token等信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const useUserStore = defineStore('user', {
|
|
|
|
|
|
state: () => {
|
2025-11-12 17:09:46 +08:00
|
|
|
|
const storedPrivateView = uni.getStorageSync('privateView')
|
|
|
|
|
|
const normalizePrivateView = () => {
|
|
|
|
|
|
if (typeof storedPrivateView === 'boolean') return storedPrivateView
|
|
|
|
|
|
if (storedPrivateView === '' || storedPrivateView === undefined || storedPrivateView === null) {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
return !!storedPrivateView
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-05 16:51:07 +08:00
|
|
|
|
return {
|
|
|
|
|
|
// 用户 token
|
|
|
|
|
|
token: uni.getStorageSync('token') || '',
|
|
|
|
|
|
// 用户信息
|
|
|
|
|
|
userInfo: uni.getStorageSync('userInfo') || null,
|
|
|
|
|
|
// token 过期时间(可选)
|
2025-11-12 17:09:46 +08:00
|
|
|
|
tokenExpireTime: uni.getStorageSync('tokenExpireTime') || null,
|
|
|
|
|
|
// 是否启用私有视角
|
|
|
|
|
|
privateView: normalizePrivateView()
|
2025-11-05 16:51:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getters: {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否已登录
|
|
|
|
|
|
*/
|
|
|
|
|
|
isLogin: (state) => {
|
|
|
|
|
|
return !!state.token
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户 token
|
|
|
|
|
|
*/
|
|
|
|
|
|
getToken: (state) => {
|
|
|
|
|
|
return state.token
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
getUserInfo: (state) => {
|
|
|
|
|
|
return state.userInfo
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-12 17:09:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取私有视角设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
getPrivateView: (state) => {
|
|
|
|
|
|
return state.privateView
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-26 15:59:57 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户角色列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
getRoles: (state) => {
|
|
|
|
|
|
return Array.isArray(state.userInfo?.roles) ? state.userInfo.roles : []
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 是否拥有管理员角色
|
|
|
|
|
|
*/
|
|
|
|
|
|
isAdmin: (state) => {
|
|
|
|
|
|
const roles = Array.isArray(state.userInfo?.roles) ? state.userInfo.roles : []
|
|
|
|
|
|
return roles.some((role) => ADMIN_ROLES.includes(role))
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取权限列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
getPermissions: (state) => {
|
|
|
|
|
|
return normalizePermissions(state.userInfo?.permissions)
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否拥有指定权限
|
|
|
|
|
|
* 支持字符串、数组或以逗号分隔的字符串
|
|
|
|
|
|
* @param {string|string[]} requiredPermissions
|
|
|
|
|
|
* @param {object} options - { requireAll?: boolean }
|
|
|
|
|
|
*/
|
|
|
|
|
|
hasPermission: (state) => (requiredPermissions, options = {}) => {
|
|
|
|
|
|
const permissionsToCheck = (() => {
|
|
|
|
|
|
if (!requiredPermissions) return []
|
|
|
|
|
|
if (Array.isArray(requiredPermissions)) {
|
|
|
|
|
|
return requiredPermissions.filter(Boolean)
|
|
|
|
|
|
}
|
|
|
|
|
|
if (typeof requiredPermissions === 'string') {
|
|
|
|
|
|
return requiredPermissions
|
|
|
|
|
|
.split(',')
|
|
|
|
|
|
.map((perm) => perm.trim())
|
|
|
|
|
|
.filter(Boolean)
|
|
|
|
|
|
}
|
|
|
|
|
|
return []
|
|
|
|
|
|
})()
|
|
|
|
|
|
|
|
|
|
|
|
if (permissionsToCheck.length === 0) return false
|
|
|
|
|
|
if (Array.isArray(state.userInfo?.roles) && state.userInfo.roles.some((role) => ADMIN_ROLES.includes(role))) {
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const userPermissions = normalizePermissions(state.userInfo?.permissions)
|
|
|
|
|
|
if (userPermissions.length === 0) return false
|
|
|
|
|
|
|
|
|
|
|
|
const requireAll = options.requireAll || options.all
|
|
|
|
|
|
return requireAll
|
|
|
|
|
|
? permissionsToCheck.every((permission) => userPermissions.includes(permission))
|
|
|
|
|
|
: permissionsToCheck.some((permission) => userPermissions.includes(permission))
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-05 16:51:07 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 判断 token 是否过期(如果设置了过期时间)
|
|
|
|
|
|
*/
|
|
|
|
|
|
isTokenExpired: (state) => {
|
|
|
|
|
|
if (!state.tokenExpireTime) return false
|
|
|
|
|
|
return Date.now() > state.tokenExpireTime
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
actions: {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置 token
|
|
|
|
|
|
* @param {string} token - 用户 token
|
|
|
|
|
|
* @param {number} expireTime - 过期时间(可选,时间戳)
|
|
|
|
|
|
*/
|
|
|
|
|
|
setToken(token, expireTime = null) {
|
|
|
|
|
|
this.token = token
|
|
|
|
|
|
this.tokenExpireTime = expireTime
|
|
|
|
|
|
|
|
|
|
|
|
// 同步到本地存储
|
|
|
|
|
|
uni.setStorageSync('token', token)
|
|
|
|
|
|
if (expireTime) {
|
|
|
|
|
|
uni.setStorageSync('tokenExpireTime', expireTime)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置用户信息
|
|
|
|
|
|
* @param {object} userInfo - 用户信息对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
setUserInfo(userInfo) {
|
|
|
|
|
|
this.userInfo = userInfo
|
|
|
|
|
|
uni.setStorageSync('userInfo', userInfo)
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 登录
|
|
|
|
|
|
* @param {string} token - 用户 token
|
|
|
|
|
|
* @param {object} userInfo - 用户信息(可选)
|
|
|
|
|
|
* @param {number} expireTime - 过期时间(可选)
|
|
|
|
|
|
*/
|
|
|
|
|
|
login(token, userInfo = null, expireTime = null) {
|
|
|
|
|
|
this.setToken(token, expireTime)
|
|
|
|
|
|
if (userInfo) {
|
|
|
|
|
|
this.setUserInfo(userInfo)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 退出登录
|
|
|
|
|
|
*/
|
|
|
|
|
|
logout() {
|
|
|
|
|
|
this.token = ''
|
|
|
|
|
|
this.userInfo = null
|
|
|
|
|
|
this.tokenExpireTime = null
|
2025-11-12 17:09:46 +08:00
|
|
|
|
this.privateView = false
|
2025-11-05 16:51:07 +08:00
|
|
|
|
|
|
|
|
|
|
// 清除本地存储
|
|
|
|
|
|
uni.removeStorageSync('token')
|
|
|
|
|
|
uni.removeStorageSync('userInfo')
|
|
|
|
|
|
uni.removeStorageSync('tokenExpireTime')
|
2025-11-12 17:09:46 +08:00
|
|
|
|
uni.removeStorageSync('privateView')
|
2025-11-05 16:51:07 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新 token(用于 token 刷新)
|
|
|
|
|
|
* @param {string} token - 新的 token
|
|
|
|
|
|
* @param {number} expireTime - 过期时间(可选)
|
|
|
|
|
|
*/
|
|
|
|
|
|
updateToken(token, expireTime = null) {
|
|
|
|
|
|
this.setToken(token, expireTime)
|
2025-11-12 17:09:46 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置私有视角
|
|
|
|
|
|
* @param {boolean} value
|
|
|
|
|
|
*/
|
|
|
|
|
|
setPrivateView(value) {
|
|
|
|
|
|
this.privateView = value
|
|
|
|
|
|
uni.setStorageSync('privateView', value)
|
2025-11-05 16:51:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|