# 金额精度统一优化说明 ## 修改内容 ### 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. 监控生产环境金额误差(理论上不应有差异)