/* * @Description: * @FilePath: \partner-portal-web\src\store\modules\user.ts * @Author: freud * @Date: 2023-06-06 14:37:45 * @LastEditTime: 2023-12-25 14:20:03 * @LastEditors: freud * @Reference: */ import { LanguageType } from '@ue/i18n'; import { date } from '@ue/utils'; import { useMessage } from '@eciol/ant-ui'; import { useI18n, useLocale } from '@eciol/locale'; import { router } from '@eciol/router'; import { isArray, LOCALE, LOCALE_TYPE, 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 { getIsOuterRead } from '@/api'; import { GetUserInfoModel, LoginParams } from '@/api/sys/model/userModel'; import { getTimeZone, getUserInfo, loginApi, refreshLogin } 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 { imageExists } from '@/utils'; import I18n from '@/utils/i18n'; import type { UserInfo } from '#/store'; interface UserState { userInfo: Nullable; token?: string; refreshToken?: string; roleList: RoleEnum[]; sessionTimeout?: boolean; lastUpdateTime: number; } export const useUserStore = defineStore({ id: 'partner-portal-user', persist: { // 持久化 paths: ['token', 'refreshToken', 'roleList', 'userInfo'], }, 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, }), getters: { getUserInfo(state): UserInfo { return state.userInfo || {}; }, langIsChinese(state) { return state.userInfo?.langType === LOCALE_TYPE.ZH_CN; }, isReadUpdate(state) { return state.userInfo?.isReadUpdate; }, 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; }, }, 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; }, async setUserInfo(info: UserInfo | null) { const { imageUploadUrl } = useGlobSetting(); if (!info) { this.userInfo = info; return; } let avatar = ''; const _t = new Date().getTime(); if (await imageExists(`${imageUploadUrl}/ImageFile/Partner${info.id}.png?_t=${_t}`)) { avatar = `${imageUploadUrl}/ImageFile/Partner${info.id}.png?_t=${_t}`; } else if (await imageExists(`${imageUploadUrl}/ImageFile/Partner${info.id}.jpg?_t=${_t}`)) { avatar = `${imageUploadUrl}/ImageFile/Partner${info.id}.jpg?_t=${_t}`; } this.userInfo = { ...info, avatar, }; 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: 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); } }, 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 || (userInfo?.isReadUpdate ? PageEnum.BASE_HOME : PageEnum.IMPORTANT_NOTE); goHome && (await router.replace(homeUrl)); } return userInfo; }, async getUserInfoAction(): Promise { if (!this.getToken) return null; const { offsetHours, offsetMinutes } = await getTimeZone(); setTimeZone({ offsetHours, offsetMinutes, }); // 设置时区偏移值 date.setOffset(offsetHours * 60 + offsetMinutes); let userInfo = await getUserInfo(); const isReadUpdate = await getIsOuterRead(userInfo.id); userInfo = { ...userInfo, userId: userInfo.id, username: userInfo.resName, realName: userInfo.resName, avatar: '', roles: [], isReadUpdate, }; const { roles = [] } = userInfo; if (isArray(roles)) { const roleList = roles.map((item) => item.value) as RoleEnum[]; this.setRoleList(roleList); } else { userInfo.roles = []; this.setRoleList([]); } await this.setUserInfo(userInfo as UserInfo); const isChina = [7].includes(userInfo.nativeLanguage); setUserCountry(isChina); const { changeLocale } = useLocale(); const locale = isChina ? LOCALE.ZH_CN : LOCALE.EN_US; I18n.setLanguage(isChina ? LanguageType.cn : LanguageType.en); await changeLocale(locale); return userInfo as UserInfo; }, /** * @description: logout */ async logout(goLogin = false) { // !注销token不调用接口,前端删除缓存 // if (this.getToken) { // try { // await doLogout(); // } catch { // console.log('注销Token失败'); // } // } const { changeLocale } = useLocale(); await changeLocale(LOCALE.EN_US); I18n.setLanguage(LanguageType.en); this.setToken(undefined); this.setRefreshToken(undefined); this.setSessionTimeout(false); await this.setUserInfo(null); goLogin && router.push(PageEnum.BASE_LOGIN); }, /** * @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); }