/* * @Description: * @FilePath: \base-framework\apps\finance\src\store\modules\user.ts * @Author: freud * @Date: 2023-06-06 14:37:45 * @LastEditTime: 2024-01-05 13:54:48 * @LastEditors: freud * @Reference: */ 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 { isEmpty } from 'xe-utils'; import { getAllDict, getEnums, getOrganList } from '@/api'; import { GetUserInfoModel, LoginParams } from '@/api/sys/model/userModel'; import { 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 { useMultipleTabStore } from '@/store/modules/multipleTab'; import { usePermissionStore } from '@/store/modules/permission'; import { getCookie, resolveMapToOptions } from '@/utils'; import type { UserInfo } from '#/store'; interface UserState { userInfo: Nullable; token?: string; refreshToken?: string; roleList: RoleEnum[]; sessionTimeout?: boolean; lastUpdateTime: number; dict: Recordable; dictMap: Recordable; organList: LabelValueOptions; organId: number | null; cleanupBeforeunload: Fn; } export const useUserStore = defineStore({ id: 'finance-user', persist: { // 持久化 paths: ['token', 'refreshToken', 'roleList', 'userInfo', 'dict', 'dictMap', 'organId'], }, 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, dict: {}, dictMap: {}, organList: [], organId: null, cleanupBeforeunload() {}, }), getters: { getUserInfo(state): UserInfo { return state.userInfo || {}; }, getDict(state) { return state.dict; }, getDictMap(state) { return state.dictMap; }, getCompanyId(state) { return ( state.organId ?? state.userInfo?.oid ?? (resolveMapToOptions(state.userInfo?.orgs ?? {}) ?? [])?.[0] ); }, getCompanyOptions(state) { return resolveMapToOptions(state.userInfo?.orgs ?? {}, { keyToNumber: true }) ?? []; }, getCompanyName(state) { const company = (resolveMapToOptions(state.userInfo?.orgs ?? {}) ?? []).find( (item) => item.value == (state.organId ?? state.userInfo?.oid), ); return company?.label; }, isChineseCompany(state) { const isChineseCompanyList = state.organList .filter((item) => item.internal) .map((item) => item.value); return isChineseCompanyList.includes( state.organId ?? state.userInfo?.oid ?? (resolveMapToOptions(state.userInfo?.orgs ?? {}) ?? [])?.[0], ); }, langIsChinese(state) { return state.userInfo?.langType === LOCALE_TYPE.ZH_CN; }, 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; }, setCompanyId(companyId) { this.organId = Number(companyId); this.setUserInfo({ ...this.userInfo, oid: Number(companyId) }); }, setUserInfo(info: UserInfo | null) { if (!info) { this.userInfo = info; return; } this.userInfo = { ...info, }; this.lastUpdateTime = new Date().getTime(); }, setSessionTimeout(flag: boolean) { this.sessionTimeout = flag; }, setCleanupBeforeunload(fn: Fn) { this.cleanupBeforeunload = fn; }, 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); } }, setTokenByCookie() { const { tokenCookieKey, tempToken } = useGlobSetting(); const token = getCookie(tokenCookieKey) || tempToken; this.setToken(token); }, // 判断当前cookie值跟之前存的cookie值是否一样(出现差别则删除) async cookieLose() { const { tokenCookieKey, tempToken } = useGlobSetting(); // 之前存的cookie const beforeJavaCookie = this.token; // 当前最新cookie const currentJavaCookie = getCookie(tokenCookieKey) || tempToken; if (beforeJavaCookie && beforeJavaCookie !== currentJavaCookie) { await this.logout(); this.setTokenByCookie(); const homeUrl = this.userInfo?.homePath || PageEnum.BASE_HOME; location.replace(homeUrl); } }, async afterLoginAction(goHome?: boolean): Promise { if (!this.getToken) return null; // get user info const userInfo = await this.getUserInfoAction(); console.log('userInfo: ', userInfo); 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; let userInfo = await getUserInfo(); if (userInfo?.id !== this.getUserInfo?.id && window.self === window.top) { const _router = router || useRouter(); const tabStore = useMultipleTabStore(); tabStore.closeAllTab(_router); } this.loadAllDict(); this.loadOrganList(); userInfo = { ...userInfo, userId: userInfo.id, username: userInfo.displayName, realName: userInfo.displayName, avatar: '', roles: [], }; if (!this.organId || this.userInfo?.userId !== userInfo.userId) { this.organId = userInfo?.oid; } setTimeZone({ offsetHours: userInfo.timeZone.offsetHours, offsetMinutes: userInfo.timeZone.offsetMinutes, }); 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); 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; }, async loadAllDict() { const dict = await getAllDict(); const enums = await getEnums(); this.dict = { ...dict, ...enums }; this.dictMap = {}; Object.entries(enums).forEach(([key, value]) => { this.dictMap[key] = {}; value.forEach((item) => { this.dictMap[key][item.value] = item.label; }); }); return true; }, async loadOrganList() { this.organList = await getOrganList(); }, /** * @description: logout */ async logout(goLogin = false) { // !注销token不调用接口,前端删除缓存 // if (this.getToken) { // try { // await doLogout(); // } catch { // console.log('注销Token失败'); // } // } const _router = router || useRouter(); const tabStore = useMultipleTabStore(); tabStore.closeAllTab(_router); this.setToken(undefined); this.setRefreshToken(undefined); this.setSessionTimeout(false); this.organId = null; this.dict = {}; this.dictMap = {}; 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 () => { this.cleanupBeforeunload(); 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); }