foreign-admin-ui/src/stores/modules/user.ts

182 lines
4.4 KiB
TypeScript

import { getStorage, setStorage, removeStorage } from '@/utils/storage';
import { loginApi, registerApi, logoutApi, forgotPasswordApi, changePasswordApi, sendCodeApi } from '@/api/modules/user';
import type { LoginParams, RegisterParams, ForgotPasswordParams, ChangePasswordParams, SendCodeParams } from '@/api/types/user';
import type { UserInfo, MenuItem, PermissionItem } from '@/stores/types/user';
import { formatMenuToElMenu, type ElMenuItem } from '@/utils/menuFormat';
// 定义用户 Store
export const useUserStore = defineStore('user', () => {
const router = useRouter();
// ========== 状态定义(与后端返回数据对应) ==========
// 用户/菜单和权限状态
const userInfo = ref<UserInfo | null>(getStorage('userInfo') || null);
const token = ref<string>(getStorage('token') || '');
const menusInfo = ref<MenuItem[]>(getStorage('menusInfo') || []);
const permissionsInfo = ref<PermissionItem[]>(getStorage('permissionsInfo') || []);
// ========== 计算属性 ==========
const isLoggedIn = computed(() => !!token.value);
// const permissionKeys = computed(() => permissions.value.map(item => item.name));
// 格式化后的 el-menu 数据(自动更新)
const sideMenu = computed<ElMenuItem[]>(() => formatMenuToElMenu(menusInfo.value));
/**
* 设置用户信息
* 作用:根据后端返回数据设置用户状态 + 本地存储
*/
const setUserInfo = (set: any) => {
token.value = set.user.token;
userInfo.value = set.user;
menusInfo.value = set.menus_info;
permissionsInfo.value = set.permissions_info;
// 保存到本地存储
setStorage('token', set.user.token);
setStorage('userInfo', set.user);
setStorage('menusInfo', set.menus_info);
setStorage('permissionsInfo', set.permissions_info);
console.log('用户信息保存成功');
};
/**
* 清空用户信息(核心复用方法)
* 作用:重置所有用户相关状态 + 清除本地存储
*/
const clearUserInfo = () => {
// 重置 Pinia 中的状态
token.value = '';
userInfo.value = null;
menusInfo.value = [];
permissionsInfo.value = [];
// 清除本地存储的用户数据
removeStorage('token');
removeStorage('userInfo');
removeStorage('menusInfo');
removeStorage('permissionsInfo');
console.log('用户信息已清空');
};
/**
* 登录方法
* @param params 登录参数
*/
const login = async (params: LoginParams) => {
try {
const res = await loginApi(params);
if (res.isUserNotExist) {
// 用户不存在,跳转到注册页面
router.push('/user/register');
return;
}
setUserInfo(res);
// 跳转到首页
router.push('/');
} catch (error) {
console.error('登录失败', error);
throw error;
}
};
/**
* 注册方法
* @param params 登录参数
*/
const register = async (params: RegisterParams) => {
try {
const res = await registerApi(params);
//跳转登录页面
router.push('/user/login');
} catch (error) {
console.error('注册失败', error);
throw error;
}
};
/**
* 退出登录
*/
const logout = async () => {
try {
await logoutApi();
} catch (error) {
console.error('退出登录接口调用失败', error);
} finally {
clearUserInfo();
// 跳转到登录页面
router.push('/user/login');
}
};
/**
* 忘记密码
*/
const forgotPassword = async (params: ForgotPasswordParams) => {
try {
await forgotPasswordApi(params);
// 跳转登录页面
router.push('/user/login');
} catch (error) {
console.error('重置密码失败', error);
throw error;
}
};
/**
* 修改密码
*/
const changePassword = async (params: ChangePasswordParams) => {
try {
await changePasswordApi(params);
// 跳转登录页面
clearUserInfo();
router.push('/user/login');
} catch (error) {
console.error('修改密码失败', error);
throw error;
}
};
/**
* 发送验证码
*/
const sendCode = async (params: SendCodeParams) => {
try {
const res = await sendCodeApi(params);
} catch (error) {
console.error('发送验证码失败', error);
throw error;
}
};
/**
* 切换账户
*/
const switchAccount = async () => {
clearUserInfo();
router.push('/user/login');
};
return {
// 状态
token,
userInfo,
menusInfo,
permissionsInfo,
// 计算属性
isLoggedIn,
sideMenu,
// 方法(箭头函数)
login,
register,
logout,
forgotPassword,
changePassword,
sendCode,
switchAccount
};
});