Files
vueapp/api/auth.ts
T

114 lines
2.8 KiB
TypeScript
Raw Normal View History

2026-06-01 14:49:14 +08:00
let apiBaseUrl = 'http://192.168.2.76:8000/api'
// #ifdef H5
apiBaseUrl = '/backend-api'
// #endif
export const API_BASE_URL = apiBaseUrl
export type SendCodePayload = {
phone: string
scene: 'register' | 'login' | 'reset'
}
export type SendCodeResponse = {
message: string
}
export type LoginCodePayload = {
phone: string
code: string
}
export type BackendUser = {
id: number
username: string
phone: string
real_name: string
role_type: string
institution: string | null
department: string | null
}
export type LoginResponse = {
message: string
user?: Partial<BackendUser> & Record<string, unknown>
tokens: {
access: string
refresh: string
}
}
export class ApiRequestError extends Error {
code?: string
statusCode?: number
constructor(message: string, code?: string, statusCode?: number) {
super(message)
this.name = 'ApiRequestError'
this.code = code
this.statusCode = statusCode
}
}
function readErrorMessage(data: unknown, fallback: string) {
if (data && typeof data === 'object') {
const payload = data as Record<string, unknown>
const message = payload.message || payload.detail || payload.error
if (typeof message === 'string' && message.trim()) return message
}
return fallback
}
function request<T>(url: string, data: unknown): Promise<T> {
return new Promise((resolve, reject) => {
uni.request({
url: `${API_BASE_URL}${url}`,
method: 'POST',
timeout: 10000,
header: {
'Content-Type': 'application/json'
},
data,
success: response => {
if (response.statusCode >= 200 && response.statusCode < 300) {
resolve(response.data as T)
return
}
const payload = response.data as Record<string, unknown> | undefined
const code = typeof payload?.code === 'string' ? payload.code : undefined
reject(new ApiRequestError(readErrorMessage(response.data, `请求失败(${response.statusCode}`), code, response.statusCode))
},
fail: error => {
reject(new ApiRequestError(error.errMsg || '无法连接服务'))
}
})
})
}
function isLoginResponse(data: unknown): data is LoginResponse {
if (!data || typeof data !== 'object') return false
const payload = data as Partial<LoginResponse>
const tokens = payload.tokens as Partial<LoginResponse['tokens']> | undefined
return Boolean(
payload.tokens &&
typeof tokens?.access === 'string' &&
typeof tokens?.refresh === 'string'
)
}
export function sendLoginCode(phone: string, scene: SendCodePayload['scene'] = 'login'): Promise<SendCodeResponse> {
return request<SendCodeResponse>('/user/auth/send-code/', {
phone,
scene
})
}
export function loginWithCode(payload: LoginCodePayload): Promise<LoginResponse> {
return request<LoginResponse>('/user/auth/login-code/', payload).then(response => {
if (isLoginResponse(response)) return response
throw new Error('登录接口返回数据格式异常')
})
}