13 KiB
代码审查报告
审查日期: 2026-03-19 审查范围: 全代码库深度检查 审查目标: 逻辑统一性、冗余代码、潜在冲突
📊 审查概览
| 类别 | 问题数量 | 严重程度 | 状态 |
|---|---|---|---|
| 🔴 严重问题 | 3 | 高 | 需立即修复 |
| 🟡 中等问题 | 5 | 中 | 需计划修复 |
| 🟢 轻微问题 | 4 | 低 | 建议优化 |
🔴 严重问题
1. 服务层逻辑重复与不一致
问题描述:
ArbitrageService 和 PriceComparisonService 存在高度重复的逻辑,但实现细节不一致。
涉及文件:
server/src/services/ArbitrageService.tsserver/src/services/PriceComparisonService.ts
具体问题:
1.1 汇率数据不一致
// ArbitrageService.ts (第62行)
private static readonly EXCHANGE_RATE = 7.2; // 硬编码单一汇率
// PriceComparisonService.ts (第65-71行)
private static readonly EXCHANGE_RATES: Record<string, number> = {
'CNY-USD': 0.14,
'USD-CNY': 7.2,
'CNY-EUR': 0.13,
'EUR-CNY': 7.7,
'USD-EUR': 0.92,
'EUR-USD': 1.09
};
影响: 两个服务对相同货币对可能计算出不同的汇率结果。
1.2 机会评分算法不一致
// ArbitrageService.ts (第465-470行)
private calculateOpportunityScore(profitSnapshot: ProfitSnapshot): number {
const profitRateScore = Math.min(profitSnapshot.profitRate * 200, 40);
const roiScore = Math.min(profitSnapshot.roi * 50, 30);
const netProfitScore = Math.min(profitSnapshot.netProfit / 10, 30);
return Math.round(profitRateScore + roiScore + netProfitScore);
}
// PriceComparisonService.ts (第381-386行)
private calculateOpportunityScore(profitSnapshot: ProfitSnapshot, priceDiffPercent: number): number {
const profitRateScore = Math.min(profitSnapshot.profitRate * 200, 40);
const roiScore = Math.min(profitSnapshot.roi * 50, 30);
const priceDiffScore = Math.min(priceDiffPercent, 30); // 不同!
return Math.round(profitRateScore + roiScore + priceDiffScore);
}
影响: 相同的利润数据可能产生不同的机会评分。
2. 利润红线检查未统一调用
问题描述:
PricingService.checkRisk() 已实现完整的利润红线检查逻辑,但其他服务未调用此方法。
涉及文件:
server/src/services/PricingService.ts(定义了 checkRisk)server/src/services/ArbitrageService.ts(未调用)server/src/services/PriceComparisonService.ts(未调用)server/src/services/DynamicPricingService.ts(有自己的检查逻辑)
现有实现:
// PricingService.ts (第116-135行) - 正确实现
static checkRisk(snapshot: ProfitSnapshot, isB2B: boolean): {
isRisk: boolean;
message?: string;
level: 'BLOCK' | 'WARN' | 'PASS'
} {
const profitRate = snapshot.profitRate;
if (isB2B) {
if (profitRate < 0.15) { // B2B < 15% 阻止
return { isRisk: true, message: `...`, level: 'BLOCK' };
}
} else {
if (profitRate < 0.20) { // B2C < 20% 预警
return { isRisk: true, message: `...`, level: 'WARN' };
}
}
return { isRisk: false, level: 'PASS' };
}
问题代码:
// ArbitrageService.ts (第107-111行) - 自己实现的检查
if (profitSnapshot.profitRate < 0.05) {
riskLevel = 'BLOCK';
} else if (profitSnapshot.profitRate < 0.15 || profitSnapshot.roi < 0.2) {
riskLevel = 'HIGH';
} else if (profitSnapshot.profitRate < 0.25) {
riskLevel = 'MEDIUM';
}
影响:
- 违反项目规则中的利润红线约束
- 不同服务的风险判断标准不一致
3. 数据库表定义分散
问题描述: 数据库表定义分散在两个地方,违反单一职责原则。
涉及文件:
server/src/database/DatabaseSchema.ts- 主数据库架构server/src/services/DynamicPricingService.ts- 内部定义 initTables()
问题代码:
// DynamicPricingService.ts (第216-299行)
static async initTables() {
// 在服务内部创建表定义
const hasConfigTable = await db.schema.hasTable(this.CONFIG_TABLE);
if (!hasConfigTable) {
await db.schema.createTable(this.CONFIG_TABLE, (table) => { ... });
}
// ...
}
影响:
- 表定义难以统一管理
- 初始化顺序可能出问题
- 违反项目架构规范
🟡 中等问题
4. 文档与代码不一致
问题描述:
Business_ClosedLoops.md 中提到的表名与实际代码不匹配。
涉及文件:
docs/00_Business/Business_ClosedLoops.md
不一致内容:
| 文档中的表名 | 实际代码中的表名 | 状态 |
|---|---|---|
| cf_arbitrage_products | ❌ 不存在 | 需补充或删除文档 |
| cf_arbitrage_orders | ❌ 不存在 | 需补充或删除文档 |
| cf_arbitrage_profits | ❌ 不存在 | 需补充或删除文档 |
| cf_pricing_metrics | ❌ 不存在 | 需补充或删除文档 |
5. 前端 DataSource 模式重复
问题描述: 多个 DataSource 文件实现了相同的 Mock/API 切换模式。
涉及文件:
dashboard/src/services/dynamicPricingDataSource.tsdashboard/src/services/arbitrageDataSource.tsdashboard/src/services/shopReportDataSource.ts
重复模式:
// 每个文件都有相同的结构
interface IXxxDataSource { ... }
class MockXxxDataSource implements IXxxDataSource { ... }
class ApiXxxDataSource implements IXxxDataSource { ... }
export const xxxDataSource: IXxxDataSource = USE_MOCK
? new MockXxxDataSource()
: new ApiXxxDataSource();
建议: 抽取为通用的 DataSource 工厂模式。
6. 状态枚举定义分散
问题描述: 相同业务概念的状态枚举在多处重复定义。
涉及文件:
server/src/services/ArbitrageService.tsserver/src/services/DynamicPricingService.tsserver/src/database/DatabaseSchema.ts
示例:
// ArbitrageService.ts
status: 'PENDING' | 'APPROVED' | 'REJECTED' | 'EXECUTING' | 'EXECUTED' | 'FAILED';
// DynamicPricingService.ts
status: 'PENDING' | 'EXECUTED' | 'REJECTED' | 'EXPIRED';
// DatabaseSchema.ts (cf_arbitrage_opportunities)
table.enum('status', ['PENDING', 'APPROVED', 'REJECTED', 'EXECUTING', 'EXECUTED', 'FAILED']);
建议: 统一定义在 shared/types/ 目录下。
7. 服务实例化模式不一致
问题描述: 部分服务使用单例模式,部分不使用。
涉及文件:
server/src/services/ArbitrageService.ts- 使用单例server/src/services/PriceComparisonService.ts- 使用单例server/src/services/DynamicPricingService.ts- 不使用单例server/src/services/PricingService.ts- 静态方法,无实例
影响: 服务调用方式不统一,增加理解成本。
8. 缓存策略分散
问题描述: 各服务独立定义缓存策略,未统一管理。
涉及文件:
server/src/services/DynamicPricingService.ts- CACHE_PREFIX, CACHE_TTLserver/src/services/CompetitorPriceService.ts- CACHE_PREFIX, CACHE_TTL
建议: 统一缓存配置管理。
🟢 轻微问题
9. 日志格式不统一
问题描述: 不同服务的日志前缀格式不一致。
// ArbitrageService.ts
logger.info(`[ArbitrageService] ...`);
// PriceComparisonService.ts
logger.info(`[PriceComparisonService] ...`);
// DynamicPricingService.ts
logger.info(`[DynamicPricing] ...`); // 缩写
10. 类型导出方式不一致
问题描述: 类型导出方式混用。
// 方式1: 先定义后导出
export interface ArbitrageOpportunity { ... }
// 方式2: 定义时导出
interface PriceComparison { ... }
export interface PriceComparison { ... } // 重复声明
11. 错误处理不一致
问题描述: 部分服务有详细的错误处理,部分直接抛出异常。
12. 注释语言混用
问题描述: 代码注释中中英文混用,不统一。
📋 修复方案
方案一:统一汇率服务
优先级: P0 预计工时: 4h
实施步骤:
- 创建
ExchangeRateService.ts统一管理汇率 - 从外部 API 或配置获取实时汇率
- 修改
ArbitrageService和PriceComparisonService调用统一服务
// 新建 server/src/services/ExchangeRateService.ts
export class ExchangeRateService {
private static rates: Record<string, number> = { ... };
private static lastUpdate: Date;
static async getRate(from: string, to: string): Promise<number> {
await this.ensureFresh();
return this.rates[`${from}-${to}`] || 1;
}
private static async ensureFresh(): Promise<void> {
// 每小时更新一次
if (!this.lastUpdate || Date.now() - this.lastUpdate.getTime() > 3600000) {
await this.fetchLatestRates();
}
}
}
方案二:统一机会评分算法
优先级: P0 预计工时: 2h
实施步骤:
- 在
PricingService中添加calculateOpportunityScore方法 - 修改
ArbitrageService和PriceComparisonService调用统一方法
// 在 PricingService.ts 中添加
static calculateOpportunityScore(
profitSnapshot: ProfitSnapshot,
options?: { priceDiffPercent?: number; netProfit?: number }
): number {
const profitRateScore = Math.min(profitSnapshot.profitRate * 200, 40);
const roiScore = Math.min(profitSnapshot.roi * 50, 30);
// 优先使用价格差异,其次使用净利润
const thirdScore = options?.priceDiffPercent
? Math.min(options.priceDiffPercent, 30)
: Math.min((options?.netProfit || profitSnapshot.netProfit) / 10, 30);
return Math.round(profitRateScore + roiScore + thirdScore);
}
方案三:统一利润红线检查
优先级: P0 预计工时: 3h
实施步骤:
- 修改
ArbitrageService调用PricingService.checkRisk() - 修改
PriceComparisonService调用PricingService.checkRisk() - 修改
DynamicPricingService使用统一检查
// 修改 ArbitrageService.ts
import { PricingService } from './PricingService';
async createOpportunity(...): Promise<ArbitrageOpportunity> {
// ... 计算利润
// 使用统一的利润红线检查
const riskCheck = PricingService.checkRisk(profitSnapshot, options?.isB2B || false);
let riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'BLOCK';
switch (riskCheck.level) {
case 'BLOCK':
riskLevel = 'BLOCK';
break;
case 'WARN':
riskLevel = 'HIGH';
break;
default:
riskLevel = profitSnapshot.profitRate >= 0.25 ? 'LOW' : 'MEDIUM';
}
// ...
}
方案四:集中数据库表定义
优先级: P1 预计工时: 4h
实施步骤:
- 将
DynamicPricingService.initTables()中的表定义移至DatabaseSchema.ts - 在
DatabaseSchema.initializeAll()中统一调用 - 删除服务中的表创建代码
方案五:统一状态枚举定义
优先级: P1 预计工时: 2h
实施步骤:
- 创建
server/src/shared/types/status.ts - 定义所有业务状态枚举
- 修改各服务引用统一枚举
// 新建 server/src/shared/types/status.ts
export enum ArbitrageStatus {
PENDING = 'PENDING',
APPROVED = 'APPROVED',
REJECTED = 'REJECTED',
EXECUTING = 'EXECUTING',
EXECUTED = 'EXECUTED',
FAILED = 'FAILED'
}
export enum PricingDecisionStatus {
PENDING = 'PENDING',
EXECUTED = 'EXECUTED',
REJECTED = 'REJECTED',
EXPIRED = 'EXPIRED'
}
方案六:统一 DataSource 工厂
优先级: P2 预计工时: 3h
实施步骤:
- 创建
dashboard/src/services/DataSourceFactory.ts - 抽取公共 Mock/API 切换逻辑
- 重构现有 DataSource 文件
📊 修复优先级矩阵
| 方案 | 优先级 | 影响范围 | 风险 | 预计工时 |
|---|---|---|---|---|
| 方案一:统一汇率服务 | P0 | 高 | 低 | 4h |
| 方案二:统一机会评分 | P0 | 中 | 低 | 2h |
| 方案三:统一利润红线 | P0 | 高 | 中 | 3h |
| 方案四:集中表定义 | P1 | 中 | 中 | 4h |
| 方案五:统一状态枚举 | P1 | 低 | 低 | 2h |
| 方案六:DataSource工厂 | P2 | 低 | 低 | 3h |
总预计工时: 18h
✅ 验收标准
修复后需满足:
- 汇率统一: 所有服务使用同一汇率源
- 评分一致: 相同输入产生相同的机会评分
- 红线统一: 所有利润检查调用
PricingService.checkRisk() - 表定义集中: 所有表定义在
DatabaseSchema.ts - 类型统一: 状态枚举在
shared/types/统一定义 - 文档同步: 文档与代码一致
📝 执行建议
阶段一:紧急修复 (P0)
- 先修复汇率、评分、利润红线三个核心问题
- 预计工时:9h
- 风险:低
阶段二:架构优化 (P1)
- 集中表定义、统一状态枚举
- 预计工时:6h
- 风险:中
阶段三:代码规范 (P2)
- DataSource 工厂、日志格式、注释语言
- 预计工时:3h
- 风险:低
本报告由代码审查工具生成,建议按优先级逐步修复。