# 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 { // 创建初始化任务 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 { 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 { 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 { // 优先从缓存获取 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 { 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 ```