rwadurian/backend/services/mining-admin-service/DEVELOPMENT_GUIDE.md

895 lines
27 KiB
Markdown
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.

# Mining Admin Service (挖矿管理服务) 开发指导
## 1. 服务概述
### 1.1 核心职责
Mining Admin Service 是挖矿系统的管理中枢,负责配置管理、系统监控、数据报表等后台管理功能。
**主要功能:**
- 系统参数配置(贡献值递增比例、分配比例等)
- 系统开关控制(转账开关等)
- 系统账户管理(运营/省/市/总部账户)
- 全局状态监控与报表
- 用户算力/积分股查询
- 历史数据初始化(老用户算力计算)
- 操作日志与审计
### 1.2 技术栈
- **框架**: NestJS + TypeScript
- **数据库**: PostgreSQL (CRUD为主)
- **ORM**: Prisma
- **消息队列**: Kafka (接收其他服务事件)
- **缓存**: Redis
### 1.3 端口分配
- HTTP: 3023
- 数据库: rwa_mining_admin
---
## 2. 架构设计
### 2.1 目录结构
```
mining-admin-service/
├── src/
│ ├── api/
│ │ ├── controllers/
│ │ │ ├── config.controller.ts # 配置管理API
│ │ │ ├── system-account.controller.ts # 系统账户API
│ │ │ ├── user-query.controller.ts # 用户查询API
│ │ │ ├── dashboard.controller.ts # 仪表盘API
│ │ │ ├── report.controller.ts # 报表API
│ │ │ ├── initialization.controller.ts # 初始化API
│ │ │ ├── audit-log.controller.ts # 审计日志API
│ │ │ └── health.controller.ts
│ │ └── dto/
│ │ ├── request/
│ │ │ ├── update-config.request.ts
│ │ │ ├── query-user.request.ts
│ │ │ └── initialize-users.request.ts
│ │ └── response/
│ │ ├── config.response.ts
│ │ ├── dashboard.response.ts
│ │ ├── user-detail.response.ts
│ │ └── report.response.ts
│ │
│ ├── application/
│ │ ├── commands/
│ │ │ ├── update-contribution-config.command.ts
│ │ │ ├── update-distribution-config.command.ts
│ │ │ ├── toggle-transfer.command.ts
│ │ │ ├── initialize-legacy-users.command.ts
│ │ │ ├── create-system-account.command.ts
│ │ │ └── manual-adjustment.command.ts
│ │ ├── queries/
│ │ │ ├── get-dashboard-stats.query.ts
│ │ │ ├── get-user-contribution-detail.query.ts
│ │ │ ├── get-user-mining-detail.query.ts
│ │ │ ├── get-global-state.query.ts
│ │ │ ├── get-system-accounts.query.ts
│ │ │ ├── get-audit-logs.query.ts
│ │ │ └── generate-report.query.ts
│ │ ├── services/
│ │ │ ├── config-management.service.ts
│ │ │ ├── initialization.service.ts
│ │ │ ├── report-generator.service.ts
│ │ │ └── audit.service.ts
│ │ └── event-handlers/
│ │ ├── contribution-calculated.handler.ts
│ │ ├── shares-distributed.handler.ts
│ │ ├── trade-completed.handler.ts
│ │ └── price-updated.handler.ts
│ │
│ ├── domain/
│ │ ├── aggregates/
│ │ │ ├── system-config.aggregate.ts
│ │ │ ├── system-account.aggregate.ts
│ │ │ └── audit-log.aggregate.ts
│ │ ├── repositories/
│ │ │ ├── system-config.repository.interface.ts
│ │ │ ├── system-account.repository.interface.ts
│ │ │ ├── audit-log.repository.interface.ts
│ │ │ └── synced-data.repository.interface.ts
│ │ ├── value-objects/
│ │ │ ├── config-key.vo.ts
│ │ │ └── audit-action.vo.ts
│ │ └── events/
│ │ ├── config-updated.event.ts
│ │ └── initialization-completed.event.ts
│ │
│ ├── infrastructure/
│ │ ├── persistence/
│ │ │ ├── prisma/
│ │ │ │ └── prisma.service.ts
│ │ │ ├── repositories/
│ │ │ │ ├── system-config.repository.impl.ts
│ │ │ │ ├── system-account.repository.impl.ts
│ │ │ │ ├── audit-log.repository.impl.ts
│ │ │ │ └── synced-data.repository.impl.ts
│ │ │ └── unit-of-work/
│ │ │ └── unit-of-work.service.ts
│ │ ├── kafka/
│ │ │ ├── contribution-event-consumer.service.ts
│ │ │ ├── mining-event-consumer.service.ts
│ │ │ ├── trading-event-consumer.service.ts
│ │ │ ├── event-publisher.service.ts
│ │ │ └── kafka.module.ts
│ │ ├── redis/
│ │ │ ├── config-cache.service.ts
│ │ │ └── stats-cache.service.ts
│ │ ├── external/
│ │ │ ├── contribution-client.service.ts
│ │ │ ├── mining-client.service.ts
│ │ │ └── trading-client.service.ts
│ │ └── infrastructure.module.ts
│ │
│ ├── shared/
│ │ ├── guards/
│ │ │ └── admin-auth.guard.ts
│ │ └── decorators/
│ │ └── audit-log.decorator.ts
│ ├── config/
│ ├── app.module.ts
│ └── main.ts
├── prisma/
│ ├── schema.prisma
│ └── migrations/
├── package.json
├── tsconfig.json
├── Dockerfile
└── docker-compose.yml
```
---
## 3. 数据库设计
### 3.1 数据库类型
Mining Admin Service 以**查询和配置管理**为主,使用 PostgreSQL 作为主数据库,大部分表为 CRUD 操作。
### 3.2 核心表结构
```sql
-- ============================================
-- 系统配置表
-- ============================================
-- 通用配置表Key-Value
CREATE TABLE system_configs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
config_key VARCHAR(100) NOT NULL UNIQUE,
config_value TEXT NOT NULL,
config_type VARCHAR(20) NOT NULL, -- STRING / NUMBER / BOOLEAN / JSON
description VARCHAR(200),
is_active BOOLEAN DEFAULT TRUE,
version INT DEFAULT 1,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_by VARCHAR(50) -- 操作人
);
-- 初始化配置数据
INSERT INTO system_configs (config_key, config_value, config_type, description) VALUES
('contribution.base_value', '22617', 'NUMBER', '基础贡献值'),
('contribution.increment_percentage', '0.003', 'NUMBER', '递增百分比 0.3%'),
('contribution.unit_size', '100', 'NUMBER', '单位大小(100棵)'),
('contribution.start_tree_number', '1000', 'NUMBER', '起始树编号'),
('distribution.personal_rate', '0.70', 'NUMBER', '个人分配比例 70%'),
('distribution.operation_rate', '0.12', 'NUMBER', '运营账户比例 12%'),
('distribution.province_rate', '0.01', 'NUMBER', '省公司比例 1%'),
('distribution.city_rate', '0.02', 'NUMBER', '市公司比例 2%'),
('distribution.team_rate', '0.15', 'NUMBER', '团队比例 15%'),
('distribution.level_rate_per', '0.005', 'NUMBER', '每级比例 0.5%'),
('distribution.bonus_rate_per', '0.025', 'NUMBER', '每档奖励比例 2.5%'),
('mining.transfer_enabled', 'false', 'BOOLEAN', '转账功能开关'),
('trading.buy_fee_rate', '0.10', 'NUMBER', '买入手续费率 10%'),
('trading.sell_fee_rate', '0.10', 'NUMBER', '卖出手续费率 10%');
-- 贡献值递增配置表(历史记录)
CREATE TABLE contribution_increment_configs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
base_contribution DECIMAL(20,10) NOT NULL,
increment_percentage DECIMAL(10,6) NOT NULL,
unit_size INT NOT NULL,
start_tree_number INT NOT NULL,
effective_from DATE NOT NULL,
effective_to DATE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_by VARCHAR(50)
);
-- 分配比例配置表(历史记录)
CREATE TABLE distribution_rate_configs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
rate_type VARCHAR(30) NOT NULL, -- PERSONAL/OPERATION/PROVINCE/CITY/TEAM_LEVEL/TEAM_BONUS
rate_value DECIMAL(10,6) NOT NULL,
level_depth INT, -- TEAM_LEVEL时使用
bonus_tier INT, -- TEAM_BONUS时使用
effective_from DATE NOT NULL,
effective_to DATE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_by VARCHAR(50)
);
-- ============================================
-- 系统账户表
-- ============================================
CREATE TABLE system_accounts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
account_type VARCHAR(20) NOT NULL, -- OPERATION / PROVINCE / CITY / HEADQUARTERS
account_name VARCHAR(100) NOT NULL,
account_code VARCHAR(50) UNIQUE, -- 账户编码
-- 关联信息(省/市公司时使用)
region_code VARCHAR(20),
region_name VARCHAR(100),
-- 余额(从其他服务同步)
contribution_balance DECIMAL(30,10) DEFAULT 0,
share_balance DECIMAL(30,10) DEFAULT 0,
green_points_balance DECIMAL(30,10) DEFAULT 0,
-- 特殊标记
contribution_never_expires BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 初始化数据
INSERT INTO system_accounts (account_type, account_name, account_code, contribution_never_expires) VALUES
('OPERATION', '运营账户', 'SYS_OPERATION', TRUE),
('HEADQUARTERS', '总部账户', 'SYS_HEADQUARTERS', TRUE),
('PROVINCE', '省公司账户', 'SYS_PROVINCE', FALSE),
('CITY', '市公司账户', 'SYS_CITY', FALSE);
-- ============================================
-- 仪表盘统计快照表
-- ============================================
CREATE TABLE dashboard_snapshots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
snapshot_time TIMESTAMP WITH TIME ZONE NOT NULL,
-- 全局状态
total_users INT DEFAULT 0,
total_adopted_users INT DEFAULT 0,
total_trees INT DEFAULT 0,
-- 算力统计
total_contribution DECIMAL(30,10) DEFAULT 0,
effective_contribution DECIMAL(30,10) DEFAULT 0,
-- 积分股统计
total_supply DECIMAL(30,10),
black_hole_amount DECIMAL(30,10),
circulation_pool DECIMAL(30,10),
current_price DECIMAL(30,18),
-- 交易统计
total_trade_volume DECIMAL(30,10) DEFAULT 0,
today_trade_volume DECIMAL(30,10) DEFAULT 0,
total_trade_count INT DEFAULT 0,
today_trade_count INT DEFAULT 0,
-- 分配统计
total_distributed DECIMAL(30,10) DEFAULT 0,
today_distributed DECIMAL(30,10) DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_dashboard_snapshots_time ON dashboard_snapshots(snapshot_time);
-- ============================================
-- 同步数据表(从其他服务汇总)
-- ============================================
-- 用户汇总视图表(定期同步)
CREATE TABLE synced_user_summaries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
account_sequence VARCHAR(20) NOT NULL UNIQUE,
-- 基本信息
phone VARCHAR(20),
status VARCHAR(20),
-- 认种信息
total_trees INT DEFAULT 0,
first_adoption_date DATE,
last_adoption_date DATE,
-- 推荐信息
referrer_account_sequence VARCHAR(20),
direct_referral_count INT DEFAULT 0,
direct_referral_adopted_count INT DEFAULT 0,
total_team_size INT DEFAULT 0,
-- 算力信息
personal_contribution DECIMAL(30,10) DEFAULT 0,
team_level_contribution DECIMAL(30,10) DEFAULT 0,
team_bonus_contribution DECIMAL(30,10) DEFAULT 0,
total_contribution DECIMAL(30,10) DEFAULT 0,
effective_contribution DECIMAL(30,10) DEFAULT 0,
-- 积分股信息
share_balance DECIMAL(30,10) DEFAULT 0,
total_mined DECIMAL(30,10) DEFAULT 0,
total_sold DECIMAL(30,10) DEFAULT 0,
total_bought DECIMAL(30,10) DEFAULT 0,
-- 同步状态
last_synced_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_synced_user_summaries_phone ON synced_user_summaries(phone);
-- ============================================
-- 审计日志表
-- ============================================
CREATE TABLE audit_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- 操作信息
action_type VARCHAR(50) NOT NULL, -- CONFIG_UPDATE / ACCOUNT_CREATE / MANUAL_ADJUST / INIT_USERS / TOGGLE_SWITCH
action_target VARCHAR(100), -- 操作目标如配置key、账户ID等
action_detail JSONB, -- 操作详情
-- 操作前后值
before_value JSONB,
after_value JSONB,
-- 操作人
operator_id VARCHAR(50) NOT NULL,
operator_name VARCHAR(100),
operator_ip VARCHAR(50),
-- 操作结果
result VARCHAR(20) NOT NULL, -- SUCCESS / FAILED
error_message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_audit_logs_action ON audit_logs(action_type);
CREATE INDEX idx_audit_logs_time ON audit_logs(created_at);
CREATE INDEX idx_audit_logs_operator ON audit_logs(operator_id);
-- ============================================
-- 初始化任务表
-- ============================================
CREATE TABLE initialization_tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
task_type VARCHAR(50) NOT NULL, -- LEGACY_USER_CONTRIBUTION / GLOBAL_STATE / SYSTEM_ACCOUNTS
task_status VARCHAR(20) NOT NULL, -- PENDING / RUNNING / COMPLETED / FAILED
-- 进度
total_count INT DEFAULT 0,
processed_count INT DEFAULT 0,
failed_count INT DEFAULT 0,
-- 参数
task_params JSONB,
-- 结果
result_summary JSONB,
error_message TEXT,
started_at TIMESTAMP WITH TIME ZONE,
completed_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_by VARCHAR(50)
);
-- ============================================
-- 已处理事件(幂等性)
-- ============================================
CREATE TABLE processed_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
event_id VARCHAR(100) NOT NULL UNIQUE,
event_type VARCHAR(50) NOT NULL,
source_service VARCHAR(50),
processed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
```
---
## 4. 核心业务逻辑
### 4.1 老用户算力初始化
```typescript
/**
* 初始化老用户算力
* 这是系统上线时的一次性任务
*/
async initializeLegacyUserContributions(): Promise<InitializationResult> {
// 创建初始化任务
const task = await this.initTaskRepo.create({
taskType: 'LEGACY_USER_CONTRIBUTION',
taskStatus: 'RUNNING',
startedAt: new Date(),
});
try {
// 1. 获取所有已认种用户
const adoptedUsers = await this.userRepo.findAllAdoptedUsers();
await this.initTaskRepo.updateProgress(task.id, {
totalCount: adoptedUsers.length,
});
let processedCount = 0;
let failedCount = 0;
// 2. 批量处理用户
for (const user of adoptedUsers) {
try {
// 调用 contribution-service 计算算力
await this.contributionClient.calculateUserContribution(user.accountSequence);
processedCount++;
} catch (error) {
this.logger.error(`Failed to initialize user ${user.accountSequence}`, error);
failedCount++;
}
// 更新进度
if ((processedCount + failedCount) % 100 === 0) {
await this.initTaskRepo.updateProgress(task.id, {
processedCount,
failedCount,
});
}
}
// 3. 完成任务
await this.initTaskRepo.complete(task.id, {
processedCount,
failedCount,
resultSummary: {
totalUsers: adoptedUsers.length,
successCount: processedCount,
failedCount,
},
});
// 4. 记录审计日志
await this.auditService.log({
actionType: 'INIT_USERS',
actionDetail: { taskId: task.id },
afterValue: { processedCount, failedCount },
result: 'SUCCESS',
});
return { taskId: task.id, processedCount, failedCount };
} catch (error) {
await this.initTaskRepo.fail(task.id, error.message);
throw error;
}
}
```
### 4.2 配置管理
```typescript
/**
* 更新系统配置
* 所有配置更新都需要记录审计日志
*/
@AuditLog('CONFIG_UPDATE')
async updateConfig(key: string, value: string, operatorId: string): Promise<void> {
const existing = await this.configRepo.findByKey(key);
if (!existing) {
throw new ConfigNotFoundException(key);
}
const beforeValue = existing.configValue;
// 验证值格式
this.validateConfigValue(key, value, existing.configType);
// 更新配置
await this.configRepo.update(key, {
configValue: value,
updatedBy: operatorId,
version: existing.version + 1,
});
// 清除缓存
await this.configCache.invalidate(key);
// 发布配置更新事件
await this.eventPublisher.publish('mining-admin.config-updated', {
eventId: uuid(),
configKey: key,
beforeValue,
afterValue: value,
updatedBy: operatorId,
updatedAt: new Date().toISOString(),
});
}
/**
* 切换转账开关
*/
@AuditLog('TOGGLE_SWITCH')
async toggleTransfer(enabled: boolean, operatorId: string): Promise<void> {
const key = 'mining.transfer_enabled';
await this.updateConfig(key, String(enabled), operatorId);
// 通知 mining-service
await this.miningClient.updateTransferSwitch(enabled);
}
```
### 4.3 仪表盘统计
```typescript
/**
* 获取仪表盘统计数据
*/
async getDashboardStats(): Promise<DashboardStatsDto> {
// 优先从缓存获取
const cached = await this.statsCache.get('dashboard');
if (cached) {
return cached;
}
// 聚合各服务数据
const [
globalState,
contributionStats,
tradingStats,
userStats,
] = await Promise.all([
this.miningClient.getGlobalState(),
this.contributionClient.getNetworkStats(),
this.tradingClient.getTodayStats(),
this.getUserStats(),
]);
const stats: DashboardStatsDto = {
// 全局状态
currentPrice: globalState.currentPrice,
blackHoleAmount: globalState.blackHoleAmount,
circulationPool: globalState.circulationPool,
minuteBurnRate: globalState.minuteBurnRate,
// 算力统计
networkTotalContribution: contributionStats.totalContribution,
networkEffectiveContribution: contributionStats.effectiveContribution,
// 用户统计
totalUsers: userStats.totalUsers,
adoptedUsers: userStats.adoptedUsers,
totalTrees: userStats.totalTrees,
// 交易统计
todayTradeVolume: tradingStats.volume,
todayTradeCount: tradingStats.count,
// 分配统计
totalDistributed: globalState.totalDistributed,
distributionPhase: globalState.distributionPhase,
dailyDistribution: globalState.dailyDistribution,
updatedAt: new Date().toISOString(),
};
// 缓存 30 秒
await this.statsCache.set('dashboard', stats, 30);
// 保存快照
await this.dashboardSnapshotRepo.create(stats);
return stats;
}
```
### 4.4 用户详情查询
```typescript
/**
* 查询用户算力和挖矿详情
*/
async getUserDetail(accountSequence: string): Promise<UserDetailDto> {
const [
contribution,
shareAccount,
miningRecords,
tradeOrders,
referralInfo,
] = await Promise.all([
this.contributionClient.getUserContribution(accountSequence),
this.miningClient.getUserShareAccount(accountSequence),
this.miningClient.getUserMiningRecords(accountSequence, { limit: 30 }),
this.tradingClient.getUserOrders(accountSequence, { limit: 30 }),
this.getUserReferralInfo(accountSequence),
]);
return {
accountSequence,
// 算力信息
contribution: {
personal: contribution.personalContribution,
teamLevel: contribution.teamLevelContribution,
teamBonus: contribution.teamBonusContribution,
total: contribution.totalContribution,
effective: contribution.effectiveContribution,
hasAdopted: contribution.hasAdopted,
directReferralAdoptedCount: contribution.directReferralAdoptedCount,
unlockedLevelDepth: contribution.unlockedLevelDepth,
unlockedBonusTiers: contribution.unlockedBonusTiers,
},
// 积分股信息
shares: {
available: shareAccount.availableBalance,
frozen: shareAccount.frozenBalance,
totalMined: shareAccount.totalMined,
totalSold: shareAccount.totalSold,
totalBought: shareAccount.totalBought,
perSecondEarning: shareAccount.perSecondEarning,
},
// 推荐信息
referral: referralInfo,
// 最近挖矿记录
recentMiningRecords: miningRecords,
// 最近交易记录
recentTradeOrders: tradeOrders,
};
}
```
---
## 5. 服务间通信
### 5.1 订阅的事件
| Topic | 来源服务 | 数据内容 | 处理方式 |
|-------|---------|---------|---------|
| `contribution.contribution-calculated` | contribution-service | 用户算力计算完成 | 更新本地用户汇总 |
| `mining.shares-distributed` | mining-service | 积分股分配完成 | 更新分配统计 |
| `mining.price-updated` | mining-service | 价格更新 | 更新仪表盘 |
| `trading.trade-completed` | trading-service | 交易完成 | 更新交易统计 |
### 5.2 发布的事件
| Topic | 事件类型 | 订阅者 |
|-------|---------|-------|
| `mining-admin.config-updated` | ConfigUpdated | contribution/mining/trading |
### 5.3 调用其他服务
```typescript
// 调用 contribution-service
this.contributionClient.getUserContribution(accountSequence);
this.contributionClient.calculateUserContribution(accountSequence);
this.contributionClient.getNetworkStats();
// 调用 mining-service
this.miningClient.getGlobalState();
this.miningClient.getUserShareAccount(accountSequence);
this.miningClient.getUserMiningRecords(accountSequence);
this.miningClient.updateTransferSwitch(enabled);
// 调用 trading-service
this.tradingClient.getUserOrders(accountSequence);
this.tradingClient.getTodayStats();
this.tradingClient.getKlineData(period);
```
---
## 6. API 设计
### 6.1 配置管理 API
```
GET /api/admin/configs # 获取所有配置
GET /api/admin/configs/:key # 获取单个配置
PUT /api/admin/configs/:key # 更新配置
POST /api/admin/configs/toggle-transfer # 切换转账开关
```
### 6.2 系统账户 API
```
GET /api/admin/system-accounts # 获取所有系统账户
GET /api/admin/system-accounts/:id # 获取单个账户详情
POST /api/admin/system-accounts # 创建系统账户
PUT /api/admin/system-accounts/:id # 更新系统账户
```
### 6.3 用户查询 API
```
GET /api/admin/users # 用户列表(分页)
GET /api/admin/users/:accountSequence # 用户详情
GET /api/admin/users/:accountSequence/contribution-records # 算力明细
GET /api/admin/users/:accountSequence/mining-records # 挖矿明细
GET /api/admin/users/:accountSequence/trade-orders # 交易记录
```
### 6.4 仪表盘 API
```
GET /api/admin/dashboard # 仪表盘统计
GET /api/admin/dashboard/realtime # 实时数据WebSocket推送
GET /api/admin/dashboard/charts # 图表数据
```
### 6.5 报表 API
```
GET /api/admin/reports/daily # 日报表
GET /api/admin/reports/contribution # 算力报表
GET /api/admin/reports/mining # 挖矿报表
GET /api/admin/reports/trading # 交易报表
POST /api/admin/reports/export # 导出报表
```
### 6.6 初始化 API
```
POST /api/admin/initialization/legacy-users # 初始化老用户算力
POST /api/admin/initialization/global-state # 初始化全局状态
GET /api/admin/initialization/tasks # 获取初始化任务列表
GET /api/admin/initialization/tasks/:id # 获取任务详情
```
### 6.7 审计日志 API
```
GET /api/admin/audit-logs # 审计日志列表
GET /api/admin/audit-logs/:id # 审计日志详情
```
---
## 7. 审计日志装饰器
```typescript
/**
* 审计日志装饰器
* 自动记录操作前后的值变化
*/
export function AuditLog(actionType: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const auditService = this.auditService;
const operatorId = this.getCurrentOperatorId();
// 记录操作前状态(如果需要)
let beforeValue = null;
if (actionType === 'CONFIG_UPDATE') {
beforeValue = await this.getBeforeValue(args);
}
try {
const result = await originalMethod.apply(this, args);
// 记录成功日志
await auditService.log({
actionType,
actionTarget: this.getActionTarget(args),
actionDetail: this.getActionDetail(args),
beforeValue,
afterValue: this.getAfterValue(args, result),
operatorId,
result: 'SUCCESS',
});
return result;
} catch (error) {
// 记录失败日志
await auditService.log({
actionType,
actionTarget: this.getActionTarget(args),
actionDetail: this.getActionDetail(args),
beforeValue,
operatorId,
result: 'FAILED',
errorMessage: error.message,
});
throw error;
}
};
return descriptor;
};
}
```
---
## 8. 关键注意事项
### 8.1 权限控制
- 所有 API 需要管理员认证
- 敏感操作需要二次确认
- 配置修改需要记录操作人
### 8.2 数据一致性
- 本地汇总数据定期与源服务同步
- 仪表盘数据缓存有 TTL
- 重要操作使用事务
### 8.3 审计要求
- 所有配置变更记录审计日志
- 记录操作前后值
- 保留操作人信息和 IP
### 8.4 性能优化
- 使用 Redis 缓存频繁查询的数据
- 仪表盘统计定期快照
- 用户列表查询分页
---
## 9. 开发检查清单
- [ ] 实现配置管理 API
- [ ] 实现系统账户管理
- [ ] 实现用户查询 API
- [ ] 实现仪表盘统计
- [ ] 实现老用户初始化功能
- [ ] 实现审计日志记录
- [ ] 配置与其他服务的 HTTP 客户端
- [ ] 配置 Kafka Consumer
- [ ] 实现管理员认证
- [ ] 编写测试
---
## 10. 启动命令
```bash
# 开发环境
npm run start:dev
# 生成 Prisma Client
npx prisma generate
# 运行迁移
npx prisma migrate dev
# 生产环境
npm run build && npm run start:prod
```