27 KiB
27 KiB
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 核心表结构
-- ============================================
-- 系统配置表
-- ============================================
-- 通用配置表(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 老用户算力初始化
/**
* 初始化老用户算力
* 这是系统上线时的一次性任务
*/
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 配置管理
/**
* 更新系统配置
* 所有配置更新都需要记录审计日志
*/
@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 仪表盘统计
/**
* 获取仪表盘统计数据
*/
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 用户详情查询
/**
* 查询用户算力和挖矿详情
*/
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 调用其他服务
// 调用 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. 审计日志装饰器
/**
* 审计日志装饰器
* 自动记录操作前后的值变化
*/
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. 启动命令
# 开发环境
npm run start:dev
# 生成 Prisma Client
npx prisma generate
# 运行迁移
npx prisma migrate dev
# 生产环境
npm run build && npm run start:prod