import { defineStore } from 'pinia'; import { ref } from 'vue'; import { CACHE_KEY } from '@/constants/index'; // @ts-ignore 因为 utils 可能还没做完整的 ts 设置 import { Local, Session } from '@/utils/storage'; import { useLoginApi } from '@/api/system/login'; import { useSystemApi } from '@/api/system/index'; import { useUserApi } from '@/api/user/index'; import type { LoginParams, UserInfo } from '@/types/user'; import { sm3 } from 'sm-crypto'; import to from 'await-to-js'; const loginApi = useLoginApi(); const systemApi = useSystemApi(); const userApi = useUserApi(); export const useUserStore = defineStore('user', () => { // ==================== State ==================== const token = ref(Local.get(CACHE_KEY.TOKEN) || ''); const userInfo = ref(Local.get(CACHE_KEY.USER_INFO) || ({} as UserInfo)); const perms = ref([]); const roles = ref([]); const configSetting = ref({}); // 页面请求加载状态 const loadings = { loginLoading: ref(false), fetchUserInfoLoading: ref(false), logoutLoading: ref(false), } as const; // ==================== Actions ==================== /** * 设置请求加载状态 */ function setRequestLoading(field: keyof typeof loadings, value: boolean) { loadings[field].value = value; } /** * 检查验证码配置 */ async function checkCaptcha() { const [err, res] = await to(systemApi.getEntityMapByKeys({ configKeys: ['isCaptcha'] })); if (err) return; if (res?.data) { configSetting.value = res.data; } } /** * 清理用户状态和本地缓存 */ function clearUserStatus() { token.value = ''; roles.value = []; perms.value = []; userInfo.value = {} as UserInfo; Local.remove(CACHE_KEY.TOKEN); Local.remove(CACHE_KEY.USER_INFO); Local.remove(CACHE_KEY.PERMS); Local.remove(CACHE_KEY.ROLES); Session.clear(); } /** * 用户登录 */ async function login(loginParams: LoginParams) { setRequestLoading('loginLoading', true); // 使用 sm3 加密密码 const encryptedPassword = loginParams.password ? sm3(loginParams.password) : ''; const [err, res] = await to( loginApi.signIn({ userName: loginParams.userName, password: encryptedPassword, idValueC: loginParams.idValueC, idKeyC: loginParams.idKeyC, saltValue: loginParams.saltValue, }) ); setRequestLoading('loginLoading', false); if (err) { return Promise.reject(err); } const resToken = res?.data?.token; if (resToken) { token.value = resToken; Local.set(CACHE_KEY.TOKEN, resToken); // 登录成功后主动获取用户信息 await fetchUserInfo(); } return res; } /** * 获取用户信息 */ async function fetchUserInfo() { setRequestLoading('fetchUserInfoLoading', true); const [err, res] = await to(userApi.getUserByUserName()); setRequestLoading('fetchUserInfoLoading', false); if (err) { return Promise.reject(err); } // 解决解构变量和 ref 变量重名问题 const { userInfo: resUserInfo, perms: resPerms, roles: resRoles, } = res?.data || {}; userInfo.value = resUserInfo || ({} as UserInfo); perms.value = resPerms || []; roles.value = resRoles || []; Local.set(CACHE_KEY.USER_INFO, userInfo.value); Local.set(CACHE_KEY.PERMS, perms.value); Local.set(CACHE_KEY.ROLES, roles.value); } /** * 用户登出 */ async function logout() { setRequestLoading('logoutLoading', true); const [err] = await to(loginApi.signOut()); setRequestLoading('logoutLoading', false); // 即便接口报错也要清空本地缓存和状态 clearUserStatus(); if (err) { console.warn('退出登录异常', err); } } return { ...loadings, token, userInfo, perms, roles, configSetting, login, fetchUserInfo, logout, clearUserStatus, setRequestLoading, checkCaptcha, }; });