# 金额精度统一优化说明

## 修改内容

### 1. 后端改动

**新增统一金额处理包：**
- `backend/pkg/money/format.go` - 提供统一的金额处理函数

**核心函数：**
```go
// Round 将金额四舍五入到角（0.1元）
func Round(value float64) float64 {
    return math.Round(value*10) / 10
}

// Min/Max 返回较小/较大金额（角精度）
func Min(a, b float64) float64
func Max(a, b float64) float64

// Format 格式化金额为字符串（保留1位小数）
func Format(value float64) string  // 例如：12.3 -> "12.3"

// FormatWithSymbol 格式化金额并添加货币符号
func FormatWithSymbol(value float64) string  // 例如：12.3 -> "¥12.3"
```

**修改的模块：**
- `backend/internal/modules/order/repository.go` - 订单金额计算
- `backend/internal/modules/dispute/repository.go` - 纠纷金额处理
- `backend/internal/modules/listing/service.go` - 商品定价
- `backend/internal/modules/listing/repository.go` - 商品金额存储

所有 `roundMoney` 函数从 `Math.Round(value)` 改为 `money.Round(value)`

### 2. 前端改动

**新增统一金额工具：**
- `frontend/src/shared/utils/money.ts` - 统一金额处理

**核心函数：**
```typescript
// roundMoney 将金额四舍五入到角（0.1元）
export function roundMoney(value: number): number {
  return Math.round(value * 10) / 10
}

// formatMoney 格式化金额为字符串（保留1位小数）
export function formatMoney(value: number | undefined | null): string {
  const num = Number(value || 0)
  return roundMoney(num).toFixed(1)  // 例如：12.3 -> "12.3"
}

// formatMoneyWithSymbol 格式化金额并添加货币符号
export function formatMoneyWithSymbol(value: number | undefined | null): string {
  return `¥${formatMoney(value)}`  // 例如：12.3 -> "¥12.3"
}
```

**修改的文件：**
- `frontend/src/shared/utils/pricing.ts` - 定价计算逻辑
- `frontend/src/shared/utils/listingDisplay.ts` - 商品显示逻辑
- `frontend/src/shared/composables/useMoney.ts` - 金额组合式函数
- `frontend/src/features/listings/views/*.vue` - 商品详情页
- `frontend/src/features/seller/views/*.vue` - 卖家管理页

所有 `Math.round(value)` 改为 `roundMoney(value)`（角精度）
所有 `Math.round(value * 10) / 10` 统一为 `roundMoney(value)`

### 3. 数据库字段

**现有字段定义保持不变：**
```sql
DECIMAL(12,2)  -- 仍然支持分精度存储
```

虽然数据库支持分精度，但业务层统一使用角精度（0.1元），确保：
- 用户界面显示一致
- 金额计算规则统一
- 避免浮点数累积误差

## 影响范围

### 价格显示变化

**优化前：**
- 商品价格：¥123（整元四舍五入）
- 押金：¥50（整元）
- 租金：¥100（整元）

**优化后：**
- 商品价格：¥123.5（角精度）
- 押金：¥50.0（保留1位小数）
- 租金：¥100.3（角精度）

### 计算逻辑变化

**示例：消耗品金额计算**

优化前：
```typescript
// 12.34 + 8.67 = 21.01 -> Math.round(21.01) = 21
```

优化后：
```typescript
// 12.34 + 8.67 = 21.01 -> roundMoney(21.01) = 21.0
```

### 测试用例需要更新

**后端测试：**
```go
// 旧断言
if settlement.ActualRentAmount != 244.00 { ... }

// 新断言（角精度）
if settlement.ActualRentAmount != 244.0 { ... }
```

**前端测试：**
```typescript
// 旧期望值：整数
expect(total).toBe(123)

// 新期望值：保留1位小数
expect(total).toBe('123.0')
```

## 验证方法

### 1. 后端编译测试

```bash
cd backend
go build ./pkg/money/...
go test ./internal/modules/order/...
go test ./internal/modules/dispute/...
go test ./internal/modules/listing/...
```

### 2. 前端类型检查

```bash
cd frontend
npm run typecheck
npm run build
```

### 3. 手动测试场景

1. 创建商品，价格输入 123.45 → 显示 ¥123.5
2. 下单支付，总价显示角精度
3. 押金计算，支持 0.1 元精度
4. 订单结算，租金/押金退款显示角精度
5. 后台管理，所有金额列显示统一格式

## 注意事项

1. **向下兼容**：数据库已有数据自动适配，首次读取时会被 `roundMoney` 调整为角精度
2. **边界情况**：12.35 会四舍五入为 12.4（银行家舍入法）
3. **显示一致性**：前端所有金额都使用 `.toFixed(1)` 保证显示格式统一
4. **API 响应**：后端返回的金额字段保持 `DECIMAL(12,2)`，但计算逻辑已改为角精度

## 后续优化建议

1. 补充单元测试覆盖金额边界情况
2. 添加 E2E 测试验证支付流程金额正确性
3. 考虑是否需要配置化精度（方便未来调整）
4. 监控生产环境金额误差（理论上不应有差异）
