import type { UserType } from '@af-mobile-client-vue3/types/auth' import type { RouteRecordRaw } from 'vue-router' import { doLogout, login, OALogin } from '@af-mobile-client-vue3/api/user' import router from '@af-mobile-client-vue3/router/index' import { useSettingStore } from '@af-mobile-client-vue3/stores/modules/setting' import { ACCESS_TOKEN, APP_LOGIN_KEY, APP_PERMISSIONS_KEY, APP_ROLES_KEY, APP_ROUTES_KEY, APP_WEB_CONFIG_KEY, CURRENT_USER, EXTERNAL_USER_INFO, PLATFORM_TYPE, USER_TYPE, } from '@af-mobile-client-vue3/stores/mutation-type' import { getPlatformRoutePrefix } from '@af-mobile-client-vue3/types/platform' import crypto from '@af-mobile-client-vue3/utils/crypto' import { encryptUtil } from '@af-mobile-client-vue3/utils/EncryptUtil' import { indexedDB } from '@af-mobile-client-vue3/utils/indexedDB' import { secureStorageWrite } from '@af-mobile-client-vue3/utils/secureStorage' import { createStorage } from '@af-mobile-client-vue3/utils/Storage' import { defineStore } from 'pinia' import { ref } from 'vue' const Storage = createStorage({ storage: localStorage }) export interface UserInfo { id: number username: string password: string name: string avatar: string functions: Array rolestr: string f_operator: string f_operatorid: string f_orgid: string f_orgname: string f_depid: string f_depname: string nickname: string [key: string]: any } interface IUserState { token?: string userInfo: any lastUpdateTime: number permissions: string[] roles: [{ id: string, operation: string[] }] routesConfig: Array single: Array login: any tenantName: string // 用户类型相关字段 userType?: UserType | null platformType?: string | null } type ExtraRouteRecordRaw = RouteRecordRaw & { delete: boolean fullPath: string } interface LoginParams { username: string password: string resourceName: string } interface FaceLoginParams { resourceName: string embedding: string // 面别识别信息 isMobile: boolean } interface WxParams { unifiedCode: string tenantName: string loginMode: string resourceName: string } interface ExternalLoginParams { platformType: string platformUserId: string tenantName: string resourceName?: string isMobile?: boolean } export const useUserStore = defineStore('app-user', () => { const userState = ref({ userInfo: null, token: undefined, lastUpdateTime: 0, // 旧营收产品$login对象 login: undefined, permissions: null, roles: null, routesConfig: null, single: [], tenantName: '', // 用户类型相关字段 userType: null, platformType: null, } as IUserState) const getUserInfo = () => { return userState.value.userInfo || Storage.get(CURRENT_USER, {}) || {} } const getLogin = () => { return userState.value.login || Storage.get(APP_LOGIN_KEY, []) || {} } const getPermissions = () => { return userState.value.permissions || Storage.get(APP_PERMISSIONS_KEY, []) || [] } const getRoles = () => { return userState.value.roles || Storage.get(APP_ROLES_KEY, []) || [] } const getRoutesConfig = () => { return userState.value.routesConfig || Storage.get(APP_ROUTES_KEY, []) || [] } const getToken = () => { return userState.value.token || Storage.get(ACCESS_TOKEN, '') as string } const getLastUpdateTime = () => { return userState.value.lastUpdateTime } const setToken = (token: string | undefined) => { Storage.set(ACCESS_TOKEN, token) } const setUserInfo = (info: any | null) => { userState.value.userInfo = info userState.value.lastUpdateTime = new Date().getTime() Storage.set(CURRENT_USER, info) } const setLogin = (login: any) => { userState.value.login = login Storage.set(APP_LOGIN_KEY, login) } const setTenantName = (tenantName: string) => { userState.value.tenantName = tenantName } const getTenantName = () => { return userState.value.tenantName } // 用户类型相关方法 const getUserType = (): UserType | null => { return userState.value.userType || Storage.get(USER_TYPE, null) } const setUserType = (userType: UserType | null) => { userState.value.userType = userType Storage.set(USER_TYPE, userType) } const isSystemUser = (): boolean => { const userType = getUserType() return userType === 'SYSTEM' || userType === null // null 默认为系统用户 } const isExternalUser = (): boolean => { return getUserType() === 'EXTERNAL' } // 平台类型相关方法 const getPlatformType = (): string | null => { return userState.value.platformType || Storage.get(PLATFORM_TYPE, null) } const setPlatformType = (platformType: string | null) => { userState.value.platformType = platformType Storage.set(PLATFORM_TYPE, platformType) } const getDefaultRoute = (): string => { if (isExternalUser()) { const platformType = getPlatformType() return getPlatformRoutePrefix(platformType) } return '/' } const setSingle = (page: ExtraRouteRecordRaw) => { if (page.path && page.delete) { // 删除 userState.value.single = userState.value.single.filter(item => item.fullPath !== page.path) } else if (userState.value.single.filter(item => item.meta.singlePage === page.meta.singlePage).length === 0) { // 添加 userState.value.single.push(page) } } const setPermissions = (permissions: []) => { userState.value.permissions = permissions Storage.set(APP_PERMISSIONS_KEY, permissions) } const setRoles = (roles: [{ id: string, operation: string[] }]) => { userState.value.roles = roles Storage.set(APP_ROLES_KEY, roles) } const setRoutesConfig = (routesConfig: Array) => { userState.value.routesConfig = routesConfig Storage.set(APP_ROUTES_KEY, routesConfig) } const Login = async (params: LoginParams) => { try { let data: any const compatible = import.meta.env.VITE_APP_COMPATIBLE if (compatible === 'OA') { data = await OALogin(params) // save token setToken(params.password) } else { data = await login(params) if (data.resources && data.resources.msg && data.resources.code && data.resources.code !== 200) { return Promise.reject(new Error(data.resources.msg)) } // save token setToken(data.access_token) // 第三方教培系统鉴权兼容 const LoginTicket = crypto.AESEncrypt(JSON.stringify(params), '3KMKqvgwR8ULbR8Z') if (data.session && useSettingStore().getSetting().requestEncrypt) { const k = encryptUtil.RSADecrypt(data.session as string) localStorage.setItem('v4-session-key', k) secureStorageWrite('v4-session-key', k) } Storage.set('LoginTicket', LoginTicket) } return Promise.resolve(data) } catch (error) { return Promise.reject(error) } } const faceLogin = async (params: FaceLoginParams) => { try { const data = await login(params) if (data.resources && data.resources.msg && data.resources.code && data.resources.code !== 200) { return Promise.reject(new Error(data.resources.msg)) } // save token setToken(data.access_token) return Promise.resolve(data) } catch (error) { return Promise.reject(error) } } const loginUnified = async (params: WxParams) => { try { const data: any = await login(params) setToken(data.access_token) const LoginTicket = crypto.AESEncrypt(JSON.stringify(params), '3KMKqvgwR8ULbR8Z') Storage.set('LoginTicket', LoginTicket) return Promise.resolve(data) } catch (error) { return Promise.reject(error) } } const loginExternal = async (params: ExternalLoginParams) => { try { const data: any = await login(params) if (data.resources && data.resources.msg && data.resources.code && data.resources.code !== 200) { return Promise.reject(new Error(data.resources.msg)) } // 设置Token setToken(data.access_token) // 加密存储登录票据 const LoginTicket = crypto.AESEncrypt(JSON.stringify(params), '3KMKqvgwR8ULbR8Z') Storage.set('LoginTicket', LoginTicket) if (data.session && useSettingStore().getSetting().requestEncrypt) { const k = encryptUtil.RSADecrypt(data.session as string) localStorage.setItem('v4-session-key', k) secureStorageWrite('v4-session-key', k) } return Promise.resolve(data) } catch (error) { return Promise.reject(error) } } const loginExternalMini = async (data: any) => { try { // 设置Token setToken(data.access_token) // 加密存储登录票据 const LoginTicket = crypto.AESEncrypt(JSON.stringify(data), '3KMKqvgwR8ULbR8Z') if (data.session && useSettingStore().getSetting().requestEncrypt) { const k = encryptUtil.RSADecrypt(data.session as string) localStorage.setItem('v4-session-key', k) secureStorageWrite('v4-session-key', k) } Storage.set('LoginTicket', LoginTicket) return Promise.resolve(data) } catch (error) { return Promise.reject(error) } } const logout = async () => { if (getToken()) { try { await doLogout() } catch { console.error('注销Token失败') } } setToken(undefined) setUserInfo(null) setUserType(null) setPlatformType(null) Storage.remove(CURRENT_USER) Storage.remove(ACCESS_TOKEN) Storage.remove(APP_LOGIN_KEY) Storage.remove(APP_PERMISSIONS_KEY) Storage.remove(APP_ROLES_KEY) Storage.remove(APP_ROUTES_KEY) Storage.remove(APP_WEB_CONFIG_KEY) Storage.remove(USER_TYPE) Storage.remove(PLATFORM_TYPE) Storage.remove(EXTERNAL_USER_INFO) Storage.remove('LoginTicket') // 清除本地加密秘钥 localStorage.removeItem('v4-session-key') secureStorageWrite('v4-session-key', '') await indexedDB.clearDB() await useSettingStore().init() try { // 添加页面刷新 await router.replace('/login') window.location.reload() } catch (e) { console.error(e) } } const registerClean = async () => { setToken(undefined) setUserInfo(null) setUserType(null) setPlatformType(null) Storage.remove(CURRENT_USER) Storage.remove(ACCESS_TOKEN) Storage.remove(APP_LOGIN_KEY) Storage.remove(APP_PERMISSIONS_KEY) Storage.remove(APP_ROLES_KEY) Storage.remove(APP_ROUTES_KEY) Storage.remove(APP_WEB_CONFIG_KEY) Storage.remove(USER_TYPE) Storage.remove(PLATFORM_TYPE) Storage.remove(EXTERNAL_USER_INFO) Storage.remove('LoginTicket') localStorage.removeItem('v4-session-key') secureStorageWrite('v4-session-key', '') await indexedDB.clearDB() await useSettingStore().init() } const getCode = (tenantName: string) => { window.location.replace(`api/af-system/user/getcode?state=${tenantName}`) } return { Login, faceLogin, loginUnified, loginExternal, loginExternalMini, getToken, getLastUpdateTime, logout, registerClean, setUserInfo, getUserInfo, getLogin, getPermissions, getRoles, getRoutesConfig, setLogin, setSingle, setPermissions, setRoles, setRoutesConfig, setTenantName, getTenantName, getCode, // 用户类型相关方法 getUserType, setUserType, isSystemUser, isExternalUser, getDefaultRoute, // 平台类型相关方法 getPlatformType, setPlatformType, } }) export default useUserStore