feat(account-events): 账号详情页与账号事件历史全链路支持

1. 新增账号事件数据表 AccountEvent 与迁移版本 20261002_0040_account_events,支持审计 Cookie 变更、自动重登、健康检查及任务执行事件;
2. 后端新增 account_events_service 并扩展 /api/accounts 路由,支持事件查询、过滤与上报;
3. 前端新增 AccountDetailPage 账号详情页组件,支持账号元信息展示、事件历史瀑布流与快捷重登操作;
4. 修复 CK 重登与自动化定时任务中事件关联逻辑,补充 test_account_events 单元测试;
5. 新增生产服务器高负载排查分析报告及相关设计文档。
This commit is contained in:
yml2213
2026-10-03 12:58:58 +08:00
parent 294c6cd058
commit 834bfdd1d0
29 changed files with 2321 additions and 1934 deletions
+9
View File
@@ -1,8 +1,10 @@
import api from './client';
import type {
AccountEventPage,
AccountItem,
AccountBulkSelection,
AccountBulkTagRequest,
AccountOverview,
AssignmentsSummary,
BasicSummary,
MessageCountResponse,
@@ -38,4 +40,11 @@ export const accountApi = {
api.delete<MessageDeletedResponse, MessageDeletedResponse>('/accounts/batch/delete', { params: { account_ids: account_ids.join(',') } }),
batchDeleteSelection: (data: AccountBulkSelection) =>
api.post<MessageDeletedResponse, MessageDeletedResponse>('/accounts/batch-delete', data),
// 详情页:状态卡 + 统计
overview: (id: number) => api.get<AccountOverview, AccountOverview>(`/accounts/${id}/overview`),
// 时间线(倒序分页),event_type 为空表示全部
events: (id: number, params: { page?: number; page_size?: number; event_type?: string }) =>
api.get<AccountEventPage, AccountEventPage>(`/accounts/${id}/events`, {
params: { page: 1, page_size: 50, ...params, event_type: params.event_type || '' },
}),
};
+76
View File
@@ -71,6 +71,82 @@ export interface BasicSummary {
tag_count?: number;
}
// ==================== 账号详情与事件历史 ====================
/** 事件类型(与后端 account_events_service 的常量保持一致)。 */
export type AccountEventType =
| 'imported'
| 'login_ok'
| 'ck_invalid'
| 'relogin_ok'
| 'relogin_failed'
| 'bind_ok'
| 'recharge'
| 'exchange'
| 'points_credit'
| 'elite_opened'
| 'esports_opened'
| 'assigned'
| 'tag_changed';
export interface AccountEventItem {
id: number;
event_type: AccountEventType | string;
occurred_at: string;
title: string;
/** 有符号:充值为正、兑换消耗为负 */
amount: number | null;
balance_after: number | null;
detail: Record<string, unknown> | null;
source: string;
}
export interface AccountEventPage {
items: AccountEventItem[];
total: number;
page: number;
page_size: number;
}
export interface AccountOverviewStats {
recharge_total: number;
exchange_count: number;
points_spent: number;
ck_invalid_count: number;
event_count: number;
login_count: number;
last_login_at: string | null;
last_ck_check_at: string | null;
}
export interface AccountOverview {
id: number;
username: string;
nickname: string;
uid: string;
tag: string;
remark: string;
assigned_to: number | null;
/** 导入时间 */
created_at: string | null;
points: number | null;
gold_balance: number | null;
exchange_balance: number | null;
game_name: string;
game_channel: string;
bind_status: string;
elite_opened: boolean | null;
elite_expire_time: number | null;
esports_points: number | null;
esports_bind_status: string;
esports_game_name: string;
esports_can_change_time: number | null;
auto_managed: boolean;
stats: AccountOverviewStats;
/** 开通时间来自事件表(上线后才开始记录,更早的不显示) */
opened_at: { elite: string | null; esports: string | null };
}
export interface TaskSummary {
total: number;
success: number;