/* * @Description: * @FilePath: \base-framework\apps\starter-template\src\store\modules\user.ts * @Author: freud * @Date: 2023-06-06 14:37:45 * @LastEditTime: 2024-01-12 11:01:58 * @LastEditors: freud * @Reference: */ import { useMessage } from '@eciol/ant-ui'; import { dictionaryApi, DictionaryService, userApi } from '@eciol/api'; import { useI18n, useLocale } from '@eciol/locale'; import { router } from '@eciol/router'; import { isArray, LOCALE, setTimeZone, setUserCountry } from '@eciol/shared'; import { acceptHMRUpdate, defineStore, pinia } from '@eciol/store'; import type { ErrorMessageMode, Nullable } from '@eciol/types'; import { h } from 'vue'; import { RouteRecordRaw } from 'vue-router'; import { loginApi, refreshLogin, type UserService } from '@/api/sys/user'; import { PageEnum } from '@/enums/pageEnum'; import { RoleEnum } from '@/enums/roleEnum'; import { useGlobSetting } from '@/hooks/setting'; import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic'; import { usePermissionStore } from '@/store/modules/permission'; import { getCookie } from '@/utils'; import type { UserInfo } from '#/store'; interface UserState { userInfo: Nullable; token?: string; refreshToken?: string; roleList: RoleEnum[]; sessionTimeout?: boolean; lastUpdateTime: number; dictItems: DictionaryService.GetDatadictsResult; } export const useUserStore = defineStore({ id: 'template-user', persist: { // 持久化 paths: ['token', 'refreshToken', 'roleList', 'userInfo', 'dictItems'], }, state: (): UserState => ({ // user info userInfo: null, // token token: undefined, // refreshToken refreshToken: undefined, // roleList roleList: [], // Whether the login expired sessionTimeout: false, // Last fetch time lastUpdateTime: 0, // 字典 dictItems: { en_Us: {}, zh_CN: {}, }, }), getters: { getUserInfo(state): UserInfo { return state.userInfo || {}; }, getToken(state): string { return state.token ?? ''; }, getRefreshToken(state): string { return state.refreshToken ?? ''; }, getRoleList(state): RoleEnum[] { return state.roleList; }, getSessionTimeout(state): boolean { return !!state.sessionTimeout; }, getLastUpdateTime(state): number { return state.lastUpdateTime; }, getAllDictItems(state): DictionaryService.DataDicts { const { getLocale } = useLocale(); const langType = getLocale.value === LOCALE.ZH_CN ? 'zh_CN' : 'en_Us'; return state.dictItems[langType] ?? {}; }, getLangType() { const { getLocale } = useLocale(); return getLocale.value === LOCALE.ZH_CN ? 'zh_CN' : 'en_Us'; }, }, actions: { setToken(info: string | undefined) { this.token = info ? info : ''; // for null or undefined value }, setRefreshToken(info: string | undefined) { this.refreshToken = info ? info : ''; // for null or undefined value }, setRoleList(roleList: RoleEnum[]) { this.roleList = roleList; }, setAllDictItems(dictItems) { this.dictItems = dictItems; }, setUserInfo(info: UserInfo | null) { if (!info) { this.userInfo = info; return; } this.userInfo = { ...info, }; this.lastUpdateTime = new Date().getTime(); }, setSessionTimeout(flag: boolean) { this.sessionTimeout = flag; }, resetState() { this.userInfo = null; this.token = ''; this.refreshToken = ''; this.roleList = []; this.sessionTimeout = false; }, /** * @description: login */ async login( params: UserService.LoginParams & { goHome?: boolean; mode?: ErrorMessageMode; }, ): Promise { try { const { goHome = true, mode, ...loginParams } = params; const data = await loginApi(loginParams, mode); const { tokenHead, token, refreshToken } = data ?? {}; // save token this.setToken(tokenHead + token); this.setRefreshToken(refreshToken); return this.afterLoginAction(goHome); } catch (error) { return Promise.reject(error); } }, setTokenByCookie() { const { tokenCookieKey, tempToken } = useGlobSetting(); const token = getCookie(tokenCookieKey) || tempToken; this.setToken(token); }, async afterLoginAction(goHome?: boolean): Promise { if (!this.getToken) return null; // get user info const userInfo = await this.getUserInfoAction(); const sessionTimeout = this.sessionTimeout; if (sessionTimeout) { this.setSessionTimeout(false); } else { const permissionStore = usePermissionStore(); if (!permissionStore.isDynamicAddedRoute) { const routes = await permissionStore.buildRoutesAction(); routes.forEach((route) => { router.addRoute(route as unknown as RouteRecordRaw); }); router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw); permissionStore.setDynamicAddedRoute(true); } const homeUrl = userInfo?.homePath || PageEnum.BASE_HOME; goHome && (await router.replace(homeUrl)); } return userInfo; }, async getUserInfoAction(): Promise { if (!this.getToken) return null; const sysAllDictItems = await dictionaryApi.getDatadicts(); /** * @description 添加字典信息到缓存 */ if (sysAllDictItems) { this.setAllDictItems(sysAllDictItems); } let userInfo = await userApi.getJwtInfo(); userInfo = { ...userInfo, userId: userInfo.oldid, username: userInfo.user_name, realName: userInfo.dname, avatar: '', roles: userInfo.authorities, }; setTimeZone({ offsetHours: 0, offsetMinutes: getCookie('tk') ? Number(getCookie('tk')) : 0, }); const { roles = [] } = userInfo; if (isArray(roles)) { const roleList = roles as unknown as RoleEnum[]; this.setRoleList(roleList); } else { userInfo.roles = []; this.setRoleList([]); } await this.setUserInfo(userInfo as UserInfo); setUserCountry(true); // const { changeLocale } = useLocale(); // const locale = userInfo.langType === LOCALE_TYPE.ZH_CN ? LOCALE.ZH_CN : LOCALE.EN_US; // await changeLocale(LOCALE.ZH_CN); return userInfo as UserInfo; }, /** * @description: logout */ async logout(goLogin = false) { // !注销token不调用接口,前端删除缓存 // if (this.getToken) { // try { // await doLogout(); // } catch { // console.log('注销Token失败'); // } // } this.setToken(undefined); this.setRefreshToken(undefined); this.setSessionTimeout(false); await this.setUserInfo(null); goLogin && (window.location.href = PageEnum.ERP_HOME as string); }, /** * @description: Confirm before logging out */ confirmLoginOut(App?: any) { const { createConfirm } = useMessage(App); const { t } = useI18n(); createConfirm({ iconType: 'warning', title: () => h('span', t('sys.app.logoutTip')), content: () => h('span', t('sys.app.logoutMessage')), onOk: async () => { await this.logout(true); }, }); }, // 刷新token async refreshLogin() { try { const res = await refreshLogin(); const { token, tokenHead, refreshToken } = res ?? {}; // save token this.setToken(tokenHead + token); this.setRefreshToken(refreshToken); } catch {} }, }, }); // 解决热更新问题 const hot = import.meta.hot; if (hot) { hot.accept(acceptHMRUpdate(useUserStore, hot)); } // Need to be used outside the setup export function useUserStoreWithOut() { return useUserStore(pinia); }