- 新增登录失败异常分型统计:支持「必须绑定手机号」、「极验滑块」、「凭证错误」、「邮箱取码失败」、「邮箱配额已满」、「网络异常」分型识别、生命周期联动(待人工)与一键筛选; - 新增账号名单与明细导出功能:支持勾选多选或按当前筛选条件全选,可导出纯用户名名单 (TXT) 或 UTF-8 BOM 结构化明细报表 (CSV),并支持一键复制到剪贴板; - 优化筛选条件记忆机制:支持页面切换/返回后自动保留所有筛选与排序状态,新增顶部「重置全部筛选」快捷按钮; - 模块化拆分 AccountsPage:将 2100+ 行的大文件拆解至 pages/accounts/ 子目录(包含状态卡片、筛选面板、工具栏、操作弹窗与表格构建器),提升可维护性; - 验证方式:新增 5 个后端自动化单测 (test_account_failure_and_export.py),全量 694 个测试用例通过,前端 TypeScript 编译与 pre-commit 代码规范检查全部通过。
102 lines
4.6 KiB
TypeScript
102 lines
4.6 KiB
TypeScript
import api from './client';
|
|
import type {
|
|
AccountExchangeRecords,
|
|
AccountEventPage,
|
|
AccountItem,
|
|
AccountBulkSelection,
|
|
AccountBulkTagRequest,
|
|
AccountExportRequest,
|
|
AccountOverview,
|
|
AssignmentsSummary,
|
|
BasicSummary,
|
|
BatchAssignRequest,
|
|
MessageCountResponse,
|
|
MessageDeletedResponse,
|
|
MessageResponse,
|
|
PageParams,
|
|
PaginatedResponse,
|
|
} from './types';
|
|
|
|
export const accountApi = {
|
|
list: (params?: { assigned_only?: boolean; tag?: string; has_cookie?: boolean; include_sensitive?: boolean }) =>
|
|
api.get<AccountItem[], AccountItem[]>('/accounts', { params }),
|
|
listPaged: (
|
|
params: PageParams & {
|
|
assigned_only?: boolean;
|
|
assign_status?: string;
|
|
assigned_user_id?: number;
|
|
tag?: string;
|
|
has_cookie?: boolean;
|
|
include_sensitive?: boolean;
|
|
status?: string;
|
|
ck_status?: string;
|
|
failure_kind?: string;
|
|
bind_status?: string;
|
|
high_value_filter?: string;
|
|
min_points?: number;
|
|
max_points?: number;
|
|
min_gold?: number;
|
|
max_gold?: number;
|
|
elite_opened?: boolean;
|
|
esports_opened?: boolean;
|
|
role_bind_status?: string;
|
|
sort?: 'username' | 'status' | 'bind' | 'points' | 'high_value' | 'exchange' | 'tag';
|
|
order?: 'asc' | 'desc';
|
|
},
|
|
) =>
|
|
api.get<PaginatedResponse<AccountItem>, PaginatedResponse<AccountItem>>('/accounts', { params }),
|
|
export: (data: AccountExportRequest) =>
|
|
api.post('/accounts/export', data, { responseType: 'blob' }),
|
|
summary: () => api.get<BasicSummary, BasicSummary>('/accounts/summary'),
|
|
import: (text: string, tag?: string) =>
|
|
api.post<MessageCountResponse, MessageCountResponse>('/accounts/import', { text, tag: tag || '' }),
|
|
assign: (id: number, assigned_to: number | null) =>
|
|
api.put<MessageResponse, MessageResponse>(`/accounts/${id}/assign`, { assigned_to }),
|
|
batchAssign: (account_ids: number[], assigned_to: number | null) =>
|
|
api.post<MessageCountResponse, MessageCountResponse>('/accounts/batch-assign', { account_ids, assigned_to }),
|
|
// 同一接口的选择集版本:可带筛选条件(all_matching),供「按筛选全选」分配
|
|
batchAssignSelection: (data: BatchAssignRequest) =>
|
|
api.post<MessageCountResponse, MessageCountResponse>('/accounts/batch-assign', data),
|
|
assignmentsSummary: () =>
|
|
api.get<AssignmentsSummary, AssignmentsSummary>('/accounts/assignments/summary'),
|
|
setRemark: (id: number, remark: string) =>
|
|
api.put<MessageResponse, MessageResponse>(`/accounts/${id}/remark`, { remark }),
|
|
setTag: (id: number, tag: string) =>
|
|
api.put<MessageResponse, MessageResponse>(`/accounts/${id}/tag`, { tag }),
|
|
batchTag: (account_ids: number[], tag: string) =>
|
|
api.put<MessageCountResponse, MessageCountResponse>('/accounts/batch-tag', { account_ids, tag }),
|
|
batchTagSelection: (data: AccountBulkTagRequest) =>
|
|
api.put<MessageCountResponse, MessageCountResponse>('/accounts/batch-tag-selection', data),
|
|
listTags: () => api.get<string[], string[]>('/accounts/tags/list'),
|
|
delete: (id: number) => api.delete<MessageResponse, MessageResponse>(`/accounts/${id}`),
|
|
batchDelete: (account_ids: number[]) =>
|
|
api.delete<MessageDeletedResponse, MessageDeletedResponse>('/accounts/batch/delete', { params: { account_ids: account_ids.join(',') } }),
|
|
batchDeleteSelection: (data: AccountBulkSelection) =>
|
|
api.post<MessageDeletedResponse, MessageDeletedResponse>('/accounts/batch-delete', data),
|
|
// 生命周期:disabled / archived / auto(恢复自动推导)
|
|
setLifecycle: (id: number, status: string, reason = '') =>
|
|
api.put<MessageResponse, MessageResponse>(`/accounts/${id}/lifecycle`, { status, reason }),
|
|
// 自动化开关:false = 账号可用但自动化不碰它
|
|
setAutomation: (id: number, auto_managed: boolean) =>
|
|
api.put<MessageResponse, MessageResponse>(`/accounts/${id}/automation`, { auto_managed }),
|
|
// 详情页:状态卡 + 统计
|
|
overview: (id: number) => api.get<AccountOverview, AccountOverview>(`/accounts/${id}/overview`),
|
|
// 三个作用域的**官方**兑换记录(点列表那一格时按需拉取,不进列表响应)
|
|
exchangeRecords: (id: number) =>
|
|
api.get<AccountExchangeRecords, AccountExchangeRecords>(`/accounts/${id}/exchange-records`),
|
|
// 时间线(倒序分页),event_type 为空表示全部
|
|
events: (
|
|
id: number,
|
|
params: { page?: number; page_size?: number; event_type?: string; category?: string },
|
|
) =>
|
|
api.get<AccountEventPage, AccountEventPage>(`/accounts/${id}/events`, {
|
|
params: {
|
|
page: 1,
|
|
page_size: 50,
|
|
...params,
|
|
event_type: params.event_type || '',
|
|
category: params.category || '',
|
|
},
|
|
}),
|
|
};
|