Files
crawler-plugin/admin-frontend-vue/src/api/user-secrets.ts
T
huangzd1997 864c22ffc7 fix(密钥检测): 直连失败重试一次,超时/网络提示中文化
上游 ai.t8star.org 实测约 1/8 单请求完全不应答(主机 A 上 JDK 客户端
HTTP/1.1 与 HTTP/2 均复现),检测只有一次机会时用户会看到
「网络不可达:HttpTimeoutException: request timed out」。

- 传输层失败(超时/网络不可达)对直连最后一跳重试一次(800ms 间隔);
  代理模块不重试——jikip 按提取次数计费,重试会多扣一次
- 失败文案中文化(新增 CODE_TIMEOUT),英文异常串只进服务端日志
- 探测提问改「你好」(最简一次调用)
- 检测面板标明检测对象(配置密钥 sk-**** / 输入值(未保存)),
  检测接口超时单独放宽(客户端 60s / 后台 180s),避免重试期间前端先超时
2026-09-14 00:28:35 +08:00

91 lines
3.0 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 { http } from './http'
import { unwrap } from './envelope'
/** 单模块状态(脱敏值 + 连通性)。 */
export interface AdminUserSecretModule {
moduleKey: string
moduleLabel: string
masked: string
/** 完整明文值:仅代理列有值(后端对密钥列不下发明文)。 */
full: string
exists: boolean
checkStatus: string
checkCode: string
checkMessage: string
checkLatencyMs: number | null
checkedAt: string | null
updatedAt: string | null
}
/** 一行一用户:三个字段列 + 行级状态(三类都检测通过才算 passed)。 */
export interface AdminUserSecretRow {
userId: number
username: string
/** 所属数据权限分组名(可能多个)。 */
groups: string[]
/** 所属主管(创建人)用户名;无分组时的兜底展示。 */
leaderUsername: string
similarAsin: AdminUserSecretModule
appearancePatent: AdminUserSecretModule
proxy: AdminUserSecretModule
status: string
statusMessage: string
updatedAt: string | null
}
export interface AdminUserSecretPage {
items: AdminUserSecretRow[]
total: number
page: number
pageSize: number
/** 分组筛选项(超管=全部;主管=自己带的分组)。 */
groupOptions?: GroupOption[]
}
export interface GroupOption {
id: number
groupName: string
}
export interface UserSecretQuery {
keyword?: string
checkStatus?: string
/** 按数据权限分组筛选(仅超管生效);后端参数为 snake_case。 */
groupId?: number
page: number
pageSize: number
}
/** 分页查询用户密钥(一行一用户):GET /api/admin/user-secrets(筛选参数必须 snake_casecamel 会被后端静默忽略)。 */
export async function fetchUserSecretList(params: UserSecretQuery): Promise<AdminUserSecretPage> {
const query: Record<string, string | number> = { page: params.page, pageSize: params.pageSize }
if (params.keyword) query.keyword = params.keyword
if (params.checkStatus) query.checkStatus = params.checkStatus
if (params.groupId) query.group_id = params.groupId
const { data } = await http.get('/api/admin/user-secrets', { params: query })
return unwrap<AdminUserSecretPage>(data)
}
/** 立即检测该用户全部已配置项:POST /api/admin/user-secrets/{userId}/check
* 逐模块检测(每项最多「首查 + 传输层失败重试一次」,最坏约 31s/项),故放宽超时到 180s。 */
export async function checkUserSecret(userId: number) {
const { data } = await http.post(`/api/admin/user-secrets/${userId}/check`, undefined, { timeout: 180_000 })
return unwrap<
Array<{
moduleKey: string
checkStatus: string
checkCode: string
checkMessage: string
checkLatencyMs: number | null
checkedAt: string | null
viaProxy: boolean
}>
>(data)
}
/** 清空该用户全部密钥与代理配置:DELETE /api/admin/user-secrets/{userId} */
export async function deleteUserSecret(userId: number): Promise<void> {
const { data } = await http.delete(`/api/admin/user-secrets/${userId}`)
unwrap<unknown>(data)
}