Files
makemd/docs/06_Reports/02_Code_Review.md

510 lines
13 KiB
Markdown
Raw Normal View History

# 代码审查报告
> **审查日期**: 2026-03-19
> **审查范围**: 全代码库深度检查
> **审查目标**: 逻辑统一性、冗余代码、潜在冲突
---
## 📊 审查概览
| 类别 | 问题数量 | 严重程度 | 状态 |
|------|----------|----------|------|
| 🔴 严重问题 | 3 | 高 | 需立即修复 |
| 🟡 中等问题 | 5 | 中 | 需计划修复 |
| 🟢 轻微问题 | 4 | 低 | 建议优化 |
---
## 🔴 严重问题
### 1. 服务层逻辑重复与不一致
**问题描述**:
`ArbitrageService``PriceComparisonService` 存在高度重复的逻辑,但实现细节不一致。
**涉及文件**:
- `server/src/services/ArbitrageService.ts`
- `server/src/services/PriceComparisonService.ts`
**具体问题**:
#### 1.1 汇率数据不一致
```typescript
// 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 机会评分算法不一致
```typescript
// 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` (有自己的检查逻辑)
**现有实现**:
```typescript
// 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' };
}
```
**问题代码**:
```typescript
// 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()
**问题代码**:
```typescript
// 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.ts`
- `dashboard/src/services/arbitrageDataSource.ts`
- `dashboard/src/services/shopReportDataSource.ts`
**重复模式**:
```typescript
// 每个文件都有相同的结构
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.ts`
- `server/src/services/DynamicPricingService.ts`
- `server/src/database/DatabaseSchema.ts`
**示例**:
```typescript
// 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_TTL
- `server/src/services/CompetitorPriceService.ts` - CACHE_PREFIX, CACHE_TTL
**建议**: 统一缓存配置管理。
---
## 🟢 轻微问题
### 9. 日志格式不统一
**问题描述**:
不同服务的日志前缀格式不一致。
```typescript
// ArbitrageService.ts
logger.info(`[ArbitrageService] ...`);
// PriceComparisonService.ts
logger.info(`[PriceComparisonService] ...`);
// DynamicPricingService.ts
logger.info(`[DynamicPricing] ...`); // 缩写
```
---
### 10. 类型导出方式不一致
**问题描述**:
类型导出方式混用。
```typescript
// 方式1: 先定义后导出
export interface ArbitrageOpportunity { ... }
// 方式2: 定义时导出
interface PriceComparison { ... }
export interface PriceComparison { ... } // 重复声明
```
---
### 11. 错误处理不一致
**问题描述**:
部分服务有详细的错误处理,部分直接抛出异常。
---
### 12. 注释语言混用
**问题描述**:
代码注释中中英文混用,不统一。
---
## 📋 修复方案
### 方案一:统一汇率服务
**优先级**: P0
**预计工时**: 4h
**实施步骤**:
1. 创建 `ExchangeRateService.ts` 统一管理汇率
2. 从外部 API 或配置获取实时汇率
3. 修改 `ArbitrageService``PriceComparisonService` 调用统一服务
```typescript
// 新建 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
**实施步骤**:
1.`PricingService` 中添加 `calculateOpportunityScore` 方法
2. 修改 `ArbitrageService``PriceComparisonService` 调用统一方法
```typescript
// 在 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
**实施步骤**:
1. 修改 `ArbitrageService` 调用 `PricingService.checkRisk()`
2. 修改 `PriceComparisonService` 调用 `PricingService.checkRisk()`
3. 修改 `DynamicPricingService` 使用统一检查
```typescript
// 修改 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
**实施步骤**:
1.`DynamicPricingService.initTables()` 中的表定义移至 `DatabaseSchema.ts`
2.`DatabaseSchema.initializeAll()` 中统一调用
3. 删除服务中的表创建代码
---
### 方案五:统一状态枚举定义
**优先级**: P1
**预计工时**: 2h
**实施步骤**:
1. 创建 `server/src/shared/types/status.ts`
2. 定义所有业务状态枚举
3. 修改各服务引用统一枚举
```typescript
// 新建 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
**实施步骤**:
1. 创建 `dashboard/src/services/DataSourceFactory.ts`
2. 抽取公共 Mock/API 切换逻辑
3. 重构现有 DataSource 文件
---
## 📊 修复优先级矩阵
| 方案 | 优先级 | 影响范围 | 风险 | 预计工时 |
|------|--------|----------|------|----------|
| 方案一:统一汇率服务 | P0 | 高 | 低 | 4h |
| 方案二:统一机会评分 | P0 | 中 | 低 | 2h |
| 方案三:统一利润红线 | P0 | 高 | 中 | 3h |
| 方案四:集中表定义 | P1 | 中 | 中 | 4h |
| 方案五:统一状态枚举 | P1 | 低 | 低 | 2h |
| 方案六DataSource工厂 | P2 | 低 | 低 | 3h |
**总预计工时**: 18h
---
## ✅ 验收标准
### 修复后需满足:
1. **汇率统一**: 所有服务使用同一汇率源
2. **评分一致**: 相同输入产生相同的机会评分
3. **红线统一**: 所有利润检查调用 `PricingService.checkRisk()`
4. **表定义集中**: 所有表定义在 `DatabaseSchema.ts`
5. **类型统一**: 状态枚举在 `shared/types/` 统一定义
6. **文档同步**: 文档与代码一致
---
## 📝 执行建议
### 阶段一:紧急修复 (P0)
- 先修复汇率、评分、利润红线三个核心问题
- 预计工时9h
- 风险:低
### 阶段二:架构优化 (P1)
- 集中表定义、统一状态枚举
- 预计工时6h
- 风险:中
### 阶段三:代码规范 (P2)
- DataSource 工厂、日志格式、注释语言
- 预计工时3h
- 风险:低
---
*本报告由代码审查工具生成,建议按优先级逐步修复。*