修复登录注册验证码bug

This commit is contained in:
Eamon
2026-08-14 16:30:41 +08:00
parent 4235458bea
commit 1336a550fe
9 changed files with 593 additions and 371 deletions

View File

@@ -8,14 +8,31 @@ import { clearSession, getUserToken } from "./token"
type CallMode = "public" | "device" | "user"
const DEFAULT_TIMEOUT = 15_000
function captureHeaders(response: Response): Record<string, string> {
const headers: Record<string, string> = {}
response.headers.forEach((value, key) => {
headers[key.toLowerCase()] = value
})
return headers
}
async function request<R = undefined>(
endpoint: string,
init: {
method: "GET" | "POST"
body?: string
auth?: string
timeout?: number
},
): Promise<ApiResponse<R>> {
const controller = new AbortController()
const timer = setTimeout(
() => controller.abort(),
init.timeout ?? DEFAULT_TIMEOUT,
)
try {
const headers: HeadersInit = {}
if (init.body !== undefined) {
@@ -27,8 +44,10 @@ async function request<R = undefined>(
method: init.method,
headers,
body: init.body,
signal: controller.signal,
})
const responseHeaders = captureHeaders(response)
const contentType = response.headers.get("Content-Type") ?? "text/plain"
if (contentType.includes("text/plain")) {
@@ -40,7 +59,7 @@ async function request<R = undefined>(
message: text || "请求失败",
}
}
return { success: true, data: undefined as R }
return { success: true, data: undefined as R, headers: responseHeaders }
}
if (contentType.includes("application/json")) {
@@ -65,25 +84,36 @@ async function request<R = undefined>(
return {
success: true,
data: (json.Data ?? json.data ?? undefined) as R,
headers: responseHeaders,
}
}
return {
success: false,
status: response.status,
message: json.Message || "请求失败",
}
}
return { success: true, data: json }
return { success: true, data: json, headers: responseHeaders }
}
throw new Error(`无法解析响应数据: ${contentType}`)
} catch (e) {
if (controller.signal.aborted) {
return {
success: false,
status: 408,
message: "请求超时,请稍后重试",
}
}
console.error("后端请求异常:", e)
return {
success: false,
status: 500,
message: (e as Error).message || "网络错误",
}
} finally {
clearTimeout(timer)
}
}
@@ -141,40 +171,56 @@ async function call<R = undefined>(
const body = data === undefined ? undefined : JSON.stringify(data)
const run = async (): Promise<ApiResponse<R>> => {
let auth: string | undefined
if (mode === "user") {
const token = getUserToken()
if (!token) {
return {
success: false,
status: 401,
message: "未登录或会话已过期",
}
}
auth = `Bearer ${token}`
} else if (mode === "device") {
const token = await acquireDeviceToken()
if (!token) {
return {
success: false,
status: 401,
message: "设备凭证获取失败",
}
}
auth = `Bearer ${token}`
}
const maxAttempts = mode === "device" ? 2 : 1
const resp = await request<R>(endpoint, { method, body, auth })
if (!resp.success && resp.status === 401) {
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
let auth: string | undefined
if (mode === "user") {
clearSession()
const token = getUserToken()
if (!token) {
return {
success: false,
status: 401,
message: "未登录或会话已过期",
}
}
auth = `Bearer ${token}`
} else if (mode === "device") {
deviceToken = null
deviceTokenExpire = 0
if (attempt > 1) {
// 上次请求 401强制作废旧 token 再重新获取
deviceToken = null
deviceTokenExpire = 0
}
const token = await acquireDeviceToken()
if (!token) {
return {
success: false,
status: 401,
message: "设备凭证获取失败",
}
}
auth = `Bearer ${token}`
}
const resp = await request<R>(endpoint, { method, body, auth })
if (!resp.success && resp.status === 401) {
if (mode === "user") {
clearSession()
return resp
}
if (mode === "device" && attempt < maxAttempts) {
continue
}
}
return resp
}
return {
success: false,
status: 401,
message: "请求未授权",
}
return resp
}
if (method === "GET" && data === undefined) {