Files
xh-medical-sign-web/clinical-web/src/api/auth.ts
T

128 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import axios from 'axios'
import {
ApiResponseError,
unwrapApiResponse,
unwrapNullableApiResponse,
} from '@/utils/api-response'
import { request } from '@/utils/request'
import type {
AuthenticatedUser,
CaptchaResponse,
CurrentAuthorization,
CurrentUserResponse,
LoginRequest,
LoginResponse,
PasswordChangeRequest,
ProfileUpdateRequest,
} from '@/types/auth'
import type { ApiResponse } from '@/types/common'
export { ApiResponseError } from '@/utils/api-response'
export async function getCaptcha(): Promise<CaptchaResponse> {
const response = await request.get<ApiResponse<CaptchaResponse>>('/v1/auth/captcha')
return unwrapApiResponse(response)
}
function normalizePermissions(value: unknown): string[] {
if (Array.isArray(value)) {
return value.filter((item): item is string => typeof item === 'string')
}
if (typeof value === 'string') {
try {
const parsed = JSON.parse(value) as unknown
return Array.isArray(parsed)
? parsed.filter((item): item is string => typeof item === 'string')
: []
} catch {
return []
}
}
return []
}
function normalizeAuthenticatedUser(user: AuthenticatedUser): AuthenticatedUser {
return {
...user,
permissions: normalizePermissions(user.permissions),
}
}
export async function login(payload: LoginRequest): Promise<LoginResponse> {
const response = await request.post<ApiResponse<LoginResponse>>('/v1/auth/login', payload)
const session = unwrapApiResponse(response)
if (!session.token || !session.user) {
throw new Error('登录接口响应缺少 token 或用户信息')
}
const normalizedSession: LoginResponse = {
...session,
expiresAt: session.expiresAt || '',
user: normalizeAuthenticatedUser(session.user),
}
return normalizedSession
}
export async function getCurrentUser(): Promise<CurrentUserResponse> {
const response = await request.get<ApiResponse<CurrentUserResponse>>('/v1/auth/me')
const user = unwrapApiResponse(response)
return {
...user,
permissions: normalizePermissions(user.permissions),
}
}
export async function getCurrentAuthorization(): Promise<CurrentAuthorization> {
const response = await request.get<ApiResponse<CurrentAuthorization>>('/v1/authorization/me')
return unwrapApiResponse(response)
}
export async function logout(): Promise<void> {
const response = await request.post<ApiResponse<Record<string, never>>>('/v1/auth/logout')
unwrapApiResponse(response)
}
export async function changePassword(payload: PasswordChangeRequest): Promise<void> {
const response = await request.post<ApiResponse<null>>('/v1/auth/password/change', payload)
unwrapNullableApiResponse(response)
}
export function getAuthErrorMessage(error: unknown) {
if (error instanceof ApiResponseError) {
return error.message
}
if (axios.isAxiosError(error)) {
if (!error.response) {
return '无法连接登录服务,请检查网络或接口地址'
}
if (error.response.status === 401) {
return '账号或密码错误'
}
return `登录失败(HTTP ${error.response.status})`
}
if (error instanceof Error && error.message) {
return error.message
}
return '登录失败,请稍后重试'
}
export async function updateProfile(payload: ProfileUpdateRequest): Promise<CurrentUserResponse> {
const response = await request.request<ApiResponse<CurrentUserResponse>>({
url: '/v1/auth/me',
method: 'PATCH',
data: payload,
})
return unwrapApiResponse(response)
}