import { SYSTEM_SERVICE_PREFIX } from '@/constants/service'; import { request } from '../request'; import { clearUserRouteCache } from './route'; import type { ServiceRequestResult } from './shared'; /** 后端登录返回 */ interface BackendLoginToken { userId: number; accessToken: string; refreshToken: string; expiresTime: number; } interface BackendUserInfoDTO { userId: string | number; userName?: string | null; nickname?: string | null; roles?: string[] | null; buttons?: string[] | null; } let userInfoPromise: Promise> | null = null; /** 将后端 token 结构转换成前端现有结构 */ function mapLoginToken(data: BackendLoginToken): Api.Auth.LoginToken { return { token: data.accessToken, refreshToken: data.refreshToken }; } function mapUserInfo(data: BackendUserInfoDTO): Api.Auth.UserInfo { return { userId: String(data.userId ?? ''), userName: data.userName ?? '', nickname: data.nickname ?? '', roles: data.roles ?? [], buttons: data.buttons ?? [] }; } export function clearUserInfoCache() { userInfoPromise = null; } export function clearAuthApiCache() { clearUserInfoCache(); clearUserRouteCache(); } /** * 登录 * * @param userName 用户名 * @param password 密码 */ export async function fetchLogin( userName: string, password: string ): Promise> { clearAuthApiCache(); const result = await request({ url: `${SYSTEM_SERVICE_PREFIX}/auth/login`, method: 'post', data: { username: userName, password, rememberMe: true } }); if (result.error || !result.data) { return result as ServiceRequestResult; } return { ...result, data: mapLoginToken(result.data) }; } /** 获取用户信息 */ export async function fetchGetUserInfo(force = false): Promise> { if (!userInfoPromise || force) { userInfoPromise = request({ url: `${SYSTEM_SERVICE_PREFIX}/auth/get-user-info` }).then(result => result as ServiceRequestResult); } const result = await userInfoPromise; if (result.error || !result.data) { userInfoPromise = null; return result as ServiceRequestResult; } return { ...result, data: mapUserInfo(result.data) }; } /** * 刷新 token * * @param refreshToken 刷新 token */ export async function fetchRefreshToken(refreshToken: string): Promise> { // 后端要求 refreshToken 通过 query 参数传递,且 Content-Type 为 form-urlencoded // skipAuth: 不注入过期 access 头,否则会被网关拦下死循环(网关一律校验 Authorization,不看 PermitAll) const result = await request({ url: `${SYSTEM_SERVICE_PREFIX}/auth/refresh-token`, method: 'post', params: { refreshToken }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, skipAuth: true }); if (result.error || !result.data) { return result as ServiceRequestResult; } return { ...result, data: mapLoginToken(result.data) }; } /** * 返回自定义后端错误 * * @param code 错误码 * @param msg 错误信息 */ export function fetchCustomBackendError(code: string, msg: string) { return request({ url: '/auth/error', params: { code, msg } }); }