From 567b73f080fb4c98415d954eab02f063a58b1907 Mon Sep 17 00:00:00 2001 From: yml Date: Tue, 9 Jun 2026 14:28:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=87=91=E9=A2=9D=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E9=87=8D=E6=9E=84=EF=BC=9A=E6=8F=90=E4=BE=9B=E5=AE=8C?= =?UTF-8?q?=E6=95=B4=E7=9A=84=E5=89=8D=E7=AB=AF=E9=80=82=E9=85=8D=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端状态:✅ 100% 完成 - 数据库迁移、Model层、所有业务模块已完成 - 编译验证通过 前端状态:✅ 基础设施完成 + 📋 详细适配文档 - Money工具函数:formatCent/yuanToCent等 ✅ - Wallet/Withdrawal API类型:*_cent字段 ✅ - WalletView.vue:部分适配完成 ✅ - 详细适配文档:前端Vue组件详细适配清单.md 📋 新增文档: 1. 金额统一重构完成报告.md - 后端技术细节 2. 前端金额字段适配指南.md - 概要指南 3. 金额统一重构项目总结.md - 项目总结 4. 前端Vue组件详细适配清单.md - 详细操作清单(新增) 适配清单包含: - WalletView.vue 详细改动点 - WithdrawalView.vue 详细改动点 - Order相关组件改动点 - Listing相关组件改动点 - AdminFinance组件改动点 - 批量操作指南(VSCode全局替换) - 测试检查清单 - 常见问题排查 下一步: 按照《前端Vue组件详细适配清单.md》逐个修改组件 预计工作量:2-3小时(机械性操作) --- docs/前端Vue组件详细适配清单.md | 407 ++++++++++++++++++ .../src/features/wallet/views/WalletView.vue | 9 +- 2 files changed, 410 insertions(+), 6 deletions(-) create mode 100644 docs/前端Vue组件详细适配清单.md diff --git a/docs/前端Vue组件详细适配清单.md b/docs/前端Vue组件详细适配清单.md new file mode 100644 index 0000000..207bf48 --- /dev/null +++ b/docs/前端Vue组件详细适配清单.md @@ -0,0 +1,407 @@ +# 前端Vue组件适配清单 + +## 概述 +后端已100%完成金额分字段重构,前端基础设施(工具函数、API类型)已完成。 +本文档列出所有需要修改的Vue组件及具体改动点。 + +--- + +## 一、WalletView.vue + +**文件**: `frontend/src/features/wallet/views/WalletView.vue` + +### 1. 添加 import(第28行后) +```typescript +import { formatCent, formatCentWithSymbol } from '@/shared/utils/money' +``` + +### 2. 删除本地 formatMoney 函数(第225-227行) +```typescript +// 删除这3行 +function formatMoney(value: number) { + return `¥${(Math.round(Number(value || 0) * 10) / 10).toFixed(1)}` +} +``` + +### 3. 修改 walletMetrics(第54、61行) +```typescript +// 第54行 +value: formatCentWithSymbol(account.value.available_balance_cent), + +// 第61行 +value: formatCentWithSymbol(account.value.frozen_balance_cent), +``` + +### 4. 修改模板中的余额显示(第282行) +```vue + +{{ account ? formatMoney(account.available_balance) : '¥0.00' }} + + +{{ account ? formatCentWithSymbol(account.available_balance_cent) : '¥0.0' }} +``` + +### 5. 修改模板中的流水显示(第380、383行) +```vue + +{{ amountPrefix(row.direction) }}{{ formatCent(row.amount_cent) }} + + +{{ formatCent(row.balance_after_cent) }} +``` + +### 6. 修改充值金额显示(第326、408行) +```vue + +{{ formatCentWithSymbol(amount * 100) }} + + +{{ formatCent(activeRechargePayment.amount_cent) }} +``` + +--- + +## 二、WithdrawalView.vue + +**文件**: `frontend/src/features/wallet/views/WithdrawalView.vue` + +### 1. 添加 import +```typescript +import { formatCent, formatCentWithSymbol, yuanToCent } from '@/shared/utils/money' +``` + +### 2. 修改余额显示(第179、187行) +```vue + +
{{ formatCentWithSymbol(account?.available_balance_cent) }}
+ + +
{{ formatCentWithSymbol(account?.frozen_balance_cent) }}
+``` + +### 3. 修改金额比较(第77行) +```typescript +// 旧 +account.value && withdrawForm.value.amount <= account.value.available_balance + +// 新 +account.value && withdrawForm.value.amount <= (account.value.available_balance_cent / 100) +``` + +### 4. 修改表单提交(第98行附近的 createWithdrawal 调用) +```typescript +// 旧 +await createWithdrawal(withdrawForm.value) + +// 新 +await createWithdrawal({ + payment_account_id: withdrawForm.value.payment_account_id, + amount_cent: yuanToCent(withdrawForm.value.amount), +}) +``` + +### 5. 修改提现记录显示(模板中所有 withdrawal.amount 的地方) +```vue +{{ formatCent(withdrawal.amount_cent) }} +{{ formatCent(withdrawal.fee_cent) }} +{{ formatCent(withdrawal.actual_amount_cent) }} +``` + +--- + +## 三、Order 相关组件 + +### 3.1 orders.ts API类型定义 + +**文件**: `frontend/src/features/orders/api/orders.ts` + +找到 Order 和 Checkout 接口,修改所有金额字段: + +```typescript +export interface Order { + // ... 其他字段 + display_amount_cent: number + rent_amount_cent?: number + owner_rent_amount_cent?: number + deposit_amount_cent: number + deposit_original_amount_cent: number + deposit_waived_amount_cent: number + platform_fee_cent?: number + // ... 其他字段 +} + +export interface Checkout { + // ... 其他字段 + display_amount_cent: number + rent_amount_cent?: number + owner_rent_amount_cent?: number + platform_fee_cent?: number + deposit_amount_cent: number + consumable_amount_cent: number + other_amount_cent: number + deposit_deduct_amount_cent: number + renter_refund_amount_cent?: number + owner_income_amount_cent?: number + // ... 其他字段 +} + +export interface PaymentOrder { + // ... 其他字段 + amount_cent: number + // ... 其他字段 +} +``` + +### 3.2 OrderDetailView.vue + +**文件**: `frontend/src/features/orders/views/OrderDetailView.vue` + +1. 添加 import: +```typescript +import { formatCent, formatCentWithSymbol } from '@/shared/utils/money' +``` + +2. 全局搜索替换所有金额显示: +```vue + +{{ formatCent(order.display_amount_cent) }} +{{ formatCent(order.rent_amount_cent) }} +{{ formatCent(order.owner_rent_amount_cent) }} +{{ formatCent(order.deposit_amount_cent) }} + + +{{ formatCent(checkout.renter_refund_amount_cent) }} +{{ formatCent(checkout.owner_income_amount_cent) }} +{{ formatCent(checkout.platform_fee_cent) }} +``` + +### 3.3 MobileOrdersView.vue + +**文件**: `frontend/src/features/orders/views/MobileOrdersView.vue` + +1. 添加 import: +```typescript +import { formatCent } from '@/shared/utils/money' +``` + +2. 修改 money 函数(第122-124行): +```typescript +function money(value: unknown) { + return formatCent(Number(value || 0)) +} +``` + +3. 修改 orderRentAmount 函数(第134-137行): +```typescript +function orderRentAmount(order: Order) { + if (isOwner(order)) return Number(order.owner_rent_amount_cent ?? order.display_amount_cent ?? 0) + return Number(order.rent_amount_cent ?? order.display_amount_cent ?? 0) +} +``` + +--- + +## 四、Listing 相关组件 + +### 4.1 listings.ts API类型定义 + +**文件**: `frontend/src/features/listings/api/listings.ts` + +```typescript +export interface Listing { + // ... 其他字段 + price_cent: number + deposit_amount_cent: number + // ... 其他字段 +} +``` + +### 4.2 ListingCard.vue + +**文件**: 搜索 `ListingCard.vue` 或类似的组件 + +1. 添加 import: +```typescript +import { formatCent, formatCentWithSymbol } from '@/shared/utils/money' +``` + +2. 修改价格显示: +```vue +{{ formatCent(listing.price_cent) }} +{{ formatCent(listing.deposit_amount_cent) }} +``` + +### 4.3 ListingForm.vue(创建/编辑商品) + +**文件**: 搜索创建商品的表单组件 + +1. 添加 import: +```typescript +import { yuanToCent } from '@/shared/utils/money' +``` + +2. 提交时转换: +```typescript +async function submit() { + const payload = { + ...form, + price_cent: yuanToCent(form.price), + deposit_amount_cent: yuanToCent(form.deposit_amount), + } + // 删除旧字段 + delete payload.price + delete payload.deposit_amount + + await createListing(payload) +} +``` + +--- + +## 五、AdminFinance 相关组件 + +**文件**: 搜索 `AdminFinance` 或 `FinanceView` 组件 + +### 修改要点 +1. 导入 formatCent +2. 将所有 `*_amount_cent` 字段用 formatCent 显示 +3. 旧的 float64 字段仍用 formatMoney 显示(如 platform_income_amount) + +```vue + +{{ formatCent(summary.total_flow_amount_cent) }} +{{ formatCent(summary.channel_net_amount_cent) }} + + +{{ formatMoney(summary.platform_income_amount) }} +``` + +--- + +## 六、批量操作指南 + +### VSCode 全局搜索替换(推荐) + +1. **字段名替换** (在 .vue 和 .ts 文件中): +``` +available_balance → available_balance_cent +frozen_balance → frozen_balance_cent +amount → amount_cent +balance_after → balance_after_cent +price → price_cent +deposit_amount → deposit_amount_cent +``` + +2. **函数调用替换** (仅在模板中): +``` +formatMoney(xxx.amount) → formatCent(xxx.amount_cent) +formatMoneyWithSymbol(xxx.amount) → formatCentWithSymbol(xxx.amount_cent) +``` + +### 注意事项 + +⚠️ **不要替换的情况**: +- 表单中用户输入的金额变量(保持元) +- 常量定义(如 MIN_AMOUNT = 10,仍然是元) +- formatMoney 用于旧的 float64 字段(AdminFinance中) + +✅ **必须替换的情况**: +- API响应中的 *_cent 字段 +- 显示给用户的金额 +- 发送给后端的金额(需要用 yuanToCent 转换) + +--- + +## 七、测试检查清单 + +完成修改后,逐一测试: + +### 功能测试 +- [ ] 钱包页面:余额正确显示 +- [ ] 钱包页面:流水记录金额正确 +- [ ] 充值功能:输入元,后端收到分 +- [ ] 提现页面:余额显示正确 +- [ ] 提现功能:输入元,后端收到分,显示手续费 +- [ ] 订单详情:所有金额正确显示 +- [ ] 订单列表:金额显示正确 +- [ ] 商品列表:价格押金显示正确 +- [ ] 商品发布:输入元,后端收到分 + +### 显示精度测试 +用开发者工具检查: +```javascript +// 12345分 应该显示为 "123.5" +formatCent(12345) === "123.5" ✓ + +// 12344分 应该显示为 "123.4" +formatCent(12344) === "123.4" ✓ + +// 1分 应该显示为 "0.0" +formatCent(1) === "0.0" ✓ +``` + +### 边界值测试 +- [ ] 零金额:formatCent(0) → "0.0" +- [ ] 最小充值:0.01元 = 1分 +- [ ] 最小提现:10元 = 1000分 +- [ ] 最大提现:5000元 = 500000分 + +--- + +## 八、常见问题排查 + +### Q: 编译错误 "Property 'available_balance' does not exist" +**A**: 类型定义已改为 `available_balance_cent`,检查是否正确导入了新的类型定义。 + +### Q: 显示的金额不对(如 123.45 显示成 12345) +**A**: 忘记用 formatCent 格式化,应该是 `formatCent(xxx.amount_cent)` 而不是直接显示。 + +### Q: 提交表单时后端报错 "amount_cent is required" +**A**: 检查是否用 `yuanToCent()` 转换了用户输入。 + +### Q: 测试充值时金额对不上 +**A**: 检查 PaymentOrder 接口是否改为 `amount_cent`,显示时是否用 `formatCent(payment.amount_cent)`。 + +--- + +## 九、快速参考 + +### 常用代码片段 + +```vue + + + +``` + +--- + +**预计工作量**: 2-3小时 +**难度**: 低(机械性查找替换) +**风险**: 低(TypeScript会提示错误) + +完成后记得: +1. 运行 `npm run build` 检查编译 +2. 启动开发服务器测试每个功能 +3. 提交代码前再次检查显示精度 + +**祝顺利!** 🚀 diff --git a/frontend/src/features/wallet/views/WalletView.vue b/frontend/src/features/wallet/views/WalletView.vue index 610c31f..5fb3bda 100644 --- a/frontend/src/features/wallet/views/WalletView.vue +++ b/frontend/src/features/wallet/views/WalletView.vue @@ -25,6 +25,7 @@ import { import type { PaymentOrder } from '@/features/orders' import { balanceTypeLabel, ledgerDirectionLabel, walletStatusLabel } from '@/utils/statusLabels' import { formatDateTime } from '@/utils/time' +import { formatCent, formatCentWithSymbol } from '@/shared/utils/money' const router = useRouter() const loading = ref(false) @@ -51,14 +52,14 @@ const walletMetrics = computed(() => { return [ { label: '可用余额', - value: formatMoney(account.value.available_balance), + value: formatCentWithSymbol(account.value.available_balance_cent), hint: '卖家结算收入累计到此账户', icon: WalletIcon, tone: 'available', }, { label: '冻结余额', - value: formatMoney(account.value.frozen_balance), + value: formatCentWithSymbol(account.value.frozen_balance_cent), hint: '当前暂无冻结资金使用', icon: Lock, tone: 'frozen', @@ -221,10 +222,6 @@ function readError(error: unknown, fallback: string) { return fallback } -function formatMoney(value: number) { - return `¥${(Math.round(Number(value || 0) * 10) / 10).toFixed(1)}` -} - function walletBizTypeLabel(type: string) { const map: Record = { dev_recharge: '测试充值',