From b7ec5e2755b98c699cc1b117e05d344aa812d5ba Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 5 Jun 2026 03:20:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/CLEANUP_PROGRESS.md | 152 ---- docs/FEATURES_ARCHITECTURE_PLAN.md | 382 --------- docs/FEATURES_MIGRATION_COMPLETE.md | 309 ------- docs/FEATURES_MIGRATION_PROGRESS.md | 240 ------ docs/FINAL_SUMMARY.md | 221 ----- docs/MONEY_PRECISION_COMPLETED.md | 204 ----- docs/MONEY_PRECISION_REFACTOR.md | 170 ---- docs/MONEY_PRECISION_SUMMARY.md | 133 --- docs/OPTIMIZATION_PLAN.md | 802 ++++++++++++++++++ docs/P1_COMPLETION_SUMMARY.md | 310 ------- docs/P2_COMPLETION_SUMMARY.md | 274 ------- docs/PROJECT_ANALYSIS.md | 472 ----------- docs/business-rules.md | 191 ----- docs/database.md | 25 - docs/order-payment-implementation-plan.md | 107 --- docs/order-testing-messaging-analysis.md | 511 ------------ docs/project-plan.md | 945 ---------------------- 17 files changed, 802 insertions(+), 4646 deletions(-) delete mode 100644 docs/CLEANUP_PROGRESS.md delete mode 100644 docs/FEATURES_ARCHITECTURE_PLAN.md delete mode 100644 docs/FEATURES_MIGRATION_COMPLETE.md delete mode 100644 docs/FEATURES_MIGRATION_PROGRESS.md delete mode 100644 docs/FINAL_SUMMARY.md delete mode 100644 docs/MONEY_PRECISION_COMPLETED.md delete mode 100644 docs/MONEY_PRECISION_REFACTOR.md delete mode 100644 docs/MONEY_PRECISION_SUMMARY.md create mode 100644 docs/OPTIMIZATION_PLAN.md delete mode 100644 docs/P1_COMPLETION_SUMMARY.md delete mode 100644 docs/P2_COMPLETION_SUMMARY.md delete mode 100644 docs/PROJECT_ANALYSIS.md delete mode 100644 docs/business-rules.md delete mode 100644 docs/database.md delete mode 100644 docs/order-payment-implementation-plan.md delete mode 100644 docs/order-testing-messaging-analysis.md delete mode 100644 docs/project-plan.md diff --git a/docs/CLEANUP_PROGRESS.md b/docs/CLEANUP_PROGRESS.md deleted file mode 100644 index 4a40ef0..0000000 --- a/docs/CLEANUP_PROGRESS.md +++ /dev/null @@ -1,152 +0,0 @@ -# Features 架构迁移 - 清理工作总结 - -**完成时间:** 2026-06-04 -**分支:** refactor/features-architecture -**当前状态:** 清理进行中 - ---- - -## ✅ 已完成的清理工作 - -### 1. 路由配置更新 ✅ -**提交:** 3d5db9d - -更新了所有路由文件,将 `@/views/` 改为 `@/features/*/views/`: -- accountRoutes.ts - 10个路由 -- publicRoutes.ts - 2个路由 -- mobileRoutes.ts - 13个路由 -- sellerRoutes.ts - 4个路由 -- adminRoutes.ts - 15个路由 -- router/index.ts - 更新 authStorage 导入 - -**总计:** 44个路由已更新 - ---- - -### 2. 删除旧文件 ✅ -**提交:** 5e87858 - -删除了旧的目录结构: -- ❌ api/ - 21个文件 -- ❌ views/ - 57个文件 -- ❌ composables/ - 33个文件 - -**总计:** 111个旧文件已删除,33,317行代码移除 - ---- - -### 3. 批量更新导入路径 ✅ -**提交:** 待提交 - -更新了所有 features 中的导入路径: -- 8个 admin API 文件 -- 所有 admin 组件和视图 -- 所有 features 中的 Vue 文件 -- ChatAttachmentImage 组件 - ---- - -## 📊 清理进度 - -| 任务 | 状态 | 说明 | -|------|------|------| -| 更新路由配置 | ✅ | 44个路由全部更新 | -| 删除旧文件 | ✅ | 111个文件已删除 | -| 更新导入路径 | 🔄 | 大部分完成,剩余~190个错误 | -| 类型检查 | 🔄 | 从272个错误降到190个 | -| 功能测试 | ⏳ | 待完成 | - ---- - -## 🔧 剩余工作 - -### 类型错误修复(~190个) - -主要问题类型: - -#### 1. 缺失的模块 -- `@/shared/api/files` - files API 未迁移到 shared -- `@/api/auth` - 部分文件还在使用旧路径 -- `@/api/wallet` - 部分文件还在使用旧路径 -- `@/api/realname` - 部分文件还在使用旧路径 - -#### 2. Composables 导入 -- `@/composables/useAdminTable` → `@/features/admin/composables/` -- `@/composables/useMoney` → `@/shared/composables/` -- `@/composables/useSmsCountdown` → `@/shared/composables/` - -#### 3. 相对路径问题 -- admin 组件之间的导入需要使用相对路径 -- auth API 内部导入路径 - -#### 4. 类型导出冲突 -- `features/admin/index.ts` 中 AdminRole 重复导出 - ---- - -## 📁 当前目录结构 - -``` -frontend/src/ -├── features/ ✅ 新架构 -│ ├── wallet/ -│ ├── chats/ -│ ├── orders/ -│ ├── listings/ -│ ├── auth/ -│ ├── seller/ -│ ├── disputes/ -│ └── admin/ -├── shared/ ✅ 共享层 -├── components/ ✅ 保留(全局组件) -├── layouts/ ✅ 保留(布局模板) -├── router/ ✅ 已更新 -├── stores/ ✅ 保留(全局状态) -├── styles/ ✅ 保留(全局样式) -├── types/ ✅ 保留(全局类型) -└── utils/ ✅ 保留(工具函数) -``` - ---- - -## Git 提交历史 - -1. **3d5db9d** - chore: 更新路由配置,使用 features 架构路径 -2. **5e87858** - chore: 删除旧的 api/, views/, composables/ 目录 -3. **待提交** - chore: 批量更新导入路径到 features 架构 - ---- - -## ⏭️ 下一步计划 - -### 1. 完成类型错误修复 -- 迁移 files API 到 shared -- 修复所有剩余导入路径 -- 解决类型导出冲突 -- 目标:0个类型错误 - -### 2. 功能测试 -```bash -npm run dev -# 测试各个模块: -# - 首页浏览 -# - 登录/注册 -# - 订单创建 -# - 聊天功能 -# - 管理后台 -``` - -### 3. 更新文档 -- 更新 README.md -- 添加新架构说明 -- 更新开发指南 - -### 4. 创建 PR -- 推送到远程 -- 创建 Pull Request -- 等待团队审核 - ---- - -**当前状态:** 清理工作 70% 完成 -**预计剩余时间:** ~1小时 diff --git a/docs/FEATURES_ARCHITECTURE_PLAN.md b/docs/FEATURES_ARCHITECTURE_PLAN.md deleted file mode 100644 index e60a6fd..0000000 --- a/docs/FEATURES_ARCHITECTURE_PLAN.md +++ /dev/null @@ -1,382 +0,0 @@ -# Features 架构迁移计划 - -## 目标架构设计 - -### 目录结构 - -``` -frontend/src/ -├── features/ # 业务功能模块(按业务领域组织) -│ ├── auth/ # 认证与账户 -│ │ ├── api/ # API 调用 -│ │ ├── components/ # 该模块专属组件 -│ │ ├── composables/ # 业务逻辑 -│ │ ├── views/ # 页面视图 -│ │ ├── types.ts # 类型定义 -│ │ └── index.ts # 模块导出 -│ ├── listings/ # 商品浏览与搜索 -│ ├── orders/ # 订单管理 -│ ├── chats/ # 聊天消息 -│ ├── wallet/ # 钱包支付 -│ ├── disputes/ # 争议仲裁 -│ ├── seller/ # 卖家中心 -│ └── admin/ # 管理后台 -├── shared/ # 跨模块共享资源 -│ ├── components/ # 通用UI组件 -│ │ ├── ui/ # 基础组件 (Button, Input...) -│ │ ├── business/ # 业务组件 (ListingCard, OrderStatus...) -│ │ └── layout/ # 布局组件 -│ ├── composables/ # 通用工具函数 -│ │ ├── useDebounce.ts -│ │ ├── useLazyLoad.ts -│ │ └── useMoney.ts -│ ├── utils/ # 工具函数 -│ ├── types/ # 全局类型定义 -│ ├── styles/ # 全局样式 -│ └── api/ # API 基础设施 -│ ├── client.ts # axios 实例 -│ └── types.ts # 通用 API 类型 -├── stores/ # 全局状态管理(仅全局状态) -├── router/ # 路由配置 -├── layouts/ # 布局模板 -├── App.vue -└── main.ts -``` - ---- - -## 渐进式迁移策略 - -### 阶段 1:基础设施准备(P0) -**目标:** 创建新的目录结构,建立共享层 - -**任务:** -1. 创建 `features/` 和 `shared/` 目录 -2. 迁移共享资源到 `shared/`: - - `shared/api/` ← `api/client.ts`, `api/types.ts` - - `shared/utils/` ← `utils/` - - `shared/types/` ← `types/` - - `shared/composables/` ← 通用 composables -3. 保持原有路径的 re-export 兼容层 - ---- - -### 阶段 2:第一批核心模块迁移(P1) -**优先级排序依据:** 边界清晰 + 高复用 + 当前开发热点 - -#### 2.1 订单模块(orders)- 最高优先级 -**理由:** 当前开发重点,边界清晰,依赖关系多 - -**迁移内容:** -``` -features/orders/ -├── api/ -│ └── orders.ts ← api/orders.ts -├── components/ -│ ├── OrderCard.vue ← views/account/components/ -│ ├── OrderStatusBadge.vue -│ └── PaymentQRCode.vue -├── composables/ -│ ├── useOrderDetail.ts ← composables/order/useOrderDetail.ts(需拆分) -│ ├── useOrderSnapshot.ts ← composables/order/useOrderSnapshot.ts -│ ├── usePaymentPolling.ts # 新:从 useOrderDetail 拆分 -│ └── useSettlement.ts # 新:从 useOrderDetail 拆分 -├── views/ -│ ├── OrdersView.vue ← views/account/OrdersView.vue -│ ├── OrderDetailView.vue ← views/account/OrderDetailView.vue -│ ├── OrderCreateView.vue ← views/account/OrderCreateView.vue -│ ├── MobileOrdersView.vue ← views/mobile/MobileOrdersView.vue -│ └── MobileOrderDetailView.vue -├── types.ts -└── index.ts -``` - -**重构点:** -- 拆分 `useOrderDetail.ts`(目前混合了订单、支付、结算、争议逻辑) -- 提取支付轮询逻辑到独立 composable -- 提取结算逻辑到独立 composable - ---- - -#### 2.2 钱包模块(wallet) -**理由:** 边界清晰,被订单依赖 - -**迁移内容:** -``` -features/wallet/ -├── api/ -│ └── wallet.ts ← api/wallet.ts -├── composables/ -│ ├── useWallet.ts # 新:封装钱包状态 -│ ├── useMoney.ts ← composables/useMoney.ts -│ └── usePricingCalculator.ts ← composables/usePricingCalculator.ts -├── views/ -│ └── WalletView.vue ← views/account/WalletView.vue -├── types.ts -└── index.ts -``` - ---- - -#### 2.3 聊天模块(chats) -**理由:** 边界清晰,独立性强 - -**迁移内容:** -``` -features/chats/ -├── api/ -│ └── chats.ts ← api/chats.ts -├── components/ -│ ├── ChatBubble.vue ← views/account/components/ -│ ├── MessageInput.vue -│ └── ChatAttachmentImage.vue ← components/ChatAttachmentImage.vue -├── composables/ -│ └── useChatSSE.ts ← composables/useChatSSE.ts -├── views/ -│ ├── ChatView.vue ← views/account/ChatView.vue -│ ├── MessagesView.vue ← views/account/MessagesView.vue -│ ├── MobileChatView.vue ← views/mobile/MobileChatView.vue -│ └── MobileMessagesView.vue -├── types.ts -└── index.ts -``` - ---- - -### 阶段 3:第二批模块迁移(P2) - -#### 3.1 商品浏览模块(listings) -``` -features/listings/ -├── api/ -│ ├── listings.ts ← api/listings.ts -│ ├── listingOptions.ts ← api/listingOptions.ts -│ └── homeConfig.ts ← api/homeConfig.ts -├── components/ -│ ├── ListingCard.vue ← views/public/components/ -│ ├── HomeFilters.vue -│ ├── RangeFilter.vue -│ └── SkinFilter.vue -├── composables/ -│ ├── useHomeFilters.ts ← composables/home/useHomeFilters.ts -│ ├── useFilterOptions.ts ← composables/home/useFilterOptions.ts -│ └── useListingQuery.ts ← composables/home/useListingQuery.ts -├── views/ -│ ├── HomeView.vue ← views/public/HomeView.vue -│ ├── ListingsView.vue ← views/public/ListingsView.vue -│ ├── ListingDetailView.vue ← views/public/ListingDetailView.vue -│ ├── MobileHomeView.vue ← views/mobile/MobileHomeView.vue -│ └── MobileListingDetailView.vue -├── types.ts -└── index.ts -``` - -#### 3.2 用户认证模块(auth) -``` -features/auth/ -├── api/ -│ ├── auth.ts ← api/auth.ts -│ ├── realname.ts ← api/realname.ts -│ └── notifications.ts ← api/notifications.ts -├── composables/ -│ ├── useSmsCountdown.ts ← composables/useSmsCountdown.ts -│ └── useAuth.ts # 新:封装认证逻辑 -├── views/ -│ ├── LoginView.vue ← views/public/LoginView.vue -│ ├── ProfileView.vue ← views/account/ProfileView.vue -│ ├── RealnameView.vue ← views/account/RealnameView.vue -│ ├── NotificationsView.vue ← views/account/NotificationsView.vue -│ └── Mobile*.vue -├── types.ts -└── index.ts -``` - ---- - -### 阶段 4:剩余模块迁移(P3) - -#### 4.1 卖家中心(seller) -``` -features/seller/ -├── api/ # 复用 listings.ts -├── composables/ -│ ├── usePublishForm.ts ← composables/usePublishForm.ts -│ └── usePublishDraft.ts ← composables/usePublishDraft.ts -├── views/ -│ ├── SellerListingsView.vue -│ ├── SellerListingCreateView.vue -│ ├── SellerHandoffsView.vue -│ └── SellerEarningsView.vue -└── index.ts -``` - -#### 4.2 争议模块(disputes) -``` -features/disputes/ -├── api/ -│ └── disputes.ts ← api/disputes.ts -├── components/ -│ └── DisputeDialog.vue # 从 OrderDetail 拆分 -├── composables/ -│ └── useDispute.ts # 从 useOrderDetail 拆分 -└── index.ts -``` - -#### 4.3 管理后台(admin) -``` -features/admin/ -├── api/ -│ ├── adminAuth.ts -│ ├── adminDashboard.ts -│ ├── adminUsers.ts -│ └── ...(其他admin API) -├── components/ -│ └── (管理端组件) -├── composables/ -│ ├── useAdminTable.ts ← composables/useAdminTable.ts -│ └── useAdminPaginatedTable.ts -├── views/ -│ └── Admin*.vue ← views/admin/ -└── index.ts -``` - ---- - -## 迁移实施步骤(单个模块) - -### Step 1: 创建目标目录结构 -```bash -mkdir -p features/{module}/api -mkdir -p features/{module}/components -mkdir -p features/{module}/composables -mkdir -p features/{module}/views -``` - -### Step 2: 移动文件 -```bash -# API -mv src/api/{module}.ts features/{module}/api/ - -# Views -mv src/views/account/{Module}*.vue features/{module}/views/ -mv src/views/mobile/Mobile{Module}*.vue features/{module}/views/ - -# Composables -mv src/composables/{module}/ features/{module}/composables/ -``` - -### Step 3: 更新导入路径 -```typescript -// 旧路径 -import { getOrders } from '@/api/orders' -import { useOrderDetail } from '@/composables/order/useOrderDetail' - -// 新路径 -import { getOrders } from '@/features/orders/api/orders' -import { useOrderDetail } from '@/features/orders/composables/useOrderDetail' - -// 或通过模块入口 -import { getOrders, useOrderDetail } from '@/features/orders' -``` - -### Step 4: 创建模块 index.ts -```typescript -// features/orders/index.ts -export * from './api/orders' -export * from './composables/useOrderDetail' -export * from './composables/useOrderSnapshot' -export type * from './types' -``` - -### Step 5: 更新路由配置 -```typescript -// router/orderRoutes.ts -import OrdersView from '@/features/orders/views/OrdersView.vue' -import OrderDetailView from '@/features/orders/views/OrderDetailView.vue' -``` - -### Step 6: 建立兼容层(可选) -在旧路径保留 re-export,逐步迁移其他模块的导入: -```typescript -// api/orders.ts(旧路径) -export * from '@/features/orders/api/orders' -``` - -### Step 7: 验证与测试 -- 运行 `npm run typecheck` 检查类型错误 -- 运行 `npm run dev` 验证运行时无误 -- 手动测试迁移模块的功能 - ---- - -## 迁移优先级总结 - -| 阶段 | 模块 | 优先级 | 预计工作量 | 依赖关系 | -|------|------|--------|-----------|---------| -| P0 | 基础设施 | 最高 | 2小时 | 无 | -| P1 | orders | 最高 | 4小时 | 依赖 wallet, chats | -| P1 | wallet | 高 | 2小时 | 无 | -| P1 | chats | 高 | 2小时 | 无 | -| P2 | listings | 中 | 3小时 | 无 | -| P2 | auth | 中 | 3小时 | 无 | -| P3 | seller | 低 | 2小时 | 依赖 listings | -| P3 | disputes | 低 | 1小时 | 依赖 orders | -| P3 | admin | 低 | 4小时 | 依赖所有模块 | - -**总计:** ~23小时工作量 - ---- - -## 迁移检查清单 - -### 每个模块完成后需要验证: -- [ ] 类型检查通过 (`npm run typecheck`) -- [ ] 开发服务器启动正常 (`npm run dev`) -- [ ] 路由访问正常 -- [ ] API 调用正常 -- [ ] 页面功能正常 -- [ ] 移动端兼容性正常 -- [ ] 无 console 错误 - -### 全部迁移完成后: -- [ ] 删除旧的 `api/`、`views/`、部分 `composables/` 目录 -- [ ] 删除兼容层 re-export -- [ ] 更新 `tsconfig.json` 路径别名(如需要) -- [ ] 更新团队文档 - ---- - -## 风险与注意事项 - -### 高风险点: -1. **循环依赖问题:** features 间互相导入可能导致循环依赖 - - **解决方案:** 将共享类型提取到 `shared/types/`,严格控制跨 feature 导入 - -2. **导入路径大量变更:** 可能引入遗漏的导入错误 - - **解决方案:** 每迁移一个模块立即运行 typecheck,使用 VS Code 的"查找所有引用" - -3. **移动端与桌面端组件复用:** 同一 feature 内可能有多个平台的 view - - **解决方案:** 在 `views/` 下按平台分组或使用文件命名区分 - -### 中风险点: -1. **路由配置分散:** 当前路由已按模块分离,需同步更新 -2. **Stores 依赖:** session/adminSession 是全局状态,保留在 `stores/` -3. **composables 拆分:** `useOrderDetail.ts` 需要拆分,可能影响现有功能 - ---- - -## 后续优化建议 - -迁移完成后可以进一步优化: - -1. **模块懒加载优化:** 利用 Vite 的动态导入,按 feature 分包 -2. **类型安全增强:** 为每个 feature 定义严格的类型边界 -3. **测试覆盖:** 为每个 feature 添加单元测试和集成测试 -4. **文档完善:** 为每个 feature 添加 README.md 说明职责和使用方法 -5. **性能监控:** 利用 `composables/performance/` 对每个 feature 进行性能监控 - ---- - -**创建时间:** 2026-06-04 -**负责人:** yml -**状态:** 待执行 diff --git a/docs/FEATURES_MIGRATION_COMPLETE.md b/docs/FEATURES_MIGRATION_COMPLETE.md deleted file mode 100644 index 5ee8852..0000000 --- a/docs/FEATURES_MIGRATION_COMPLETE.md +++ /dev/null @@ -1,309 +0,0 @@ -# 🎉 Features 架构迁移完成总结 - -**完成时间:** 2026-06-04 -**分支:** refactor/features-architecture -**最终提交:** c939763 - ---- - -## 🏆 完成情况 - -### 全部 9 个模块迁移完成 - -| 阶段 | 模块 | 文件数 | 状态 | -|------|------|--------|------| -| **P0** | shared(基础设施) | 22 | ✅ | -| **P1** | wallet(钱包) | 5 | ✅ | -| **P1** | chats(聊天) | 8 | ✅ | -| **P1** | orders(订单) | 11 | ✅ 已重构 | -| **P2** | listings(商品浏览) | 23 | ✅ | -| **P2** | auth(用户认证) | 12 | ✅ | -| **P3** | seller(卖家中心) | 7 | ✅ | -| **P3** | disputes(争议仲裁) | 2 | ✅ | -| **P3** | admin(管理后台) | 38 | ✅ | -| **总计** | **9个模块** | **128** | **✅** | - ---- - -## 📁 最终架构 - -``` -frontend/src/ -├── features/ # 业务功能模块(按领域组织)✅ -│ ├── wallet/ # 钱包支付 ✅ -│ │ ├── api/ -│ │ ├── composables/ -│ │ ├── views/ -│ │ └── index.ts -│ ├── chats/ # 聊天消息 ✅ -│ │ ├── api/ -│ │ ├── components/ -│ │ ├── composables/ -│ │ ├── views/ -│ │ └── index.ts -│ ├── orders/ # 订单管理 ✅ (已重构) -│ │ ├── api/ -│ │ ├── composables/ -│ │ │ ├── useOrderDetail.ts # 核心订单 -│ │ │ ├── useOrderSnapshot.ts # 订单快照 -│ │ │ ├── usePaymentPolling.ts # 支付轮询 -│ │ │ └── useSettlement.ts # 结算流程 -│ │ ├── views/ -│ │ └── index.ts -│ ├── listings/ # 商品浏览 ✅ -│ │ ├── api/ -│ │ ├── components/ -│ │ ├── composables/ -│ │ ├── views/ -│ │ └── index.ts -│ ├── auth/ # 用户认证 ✅ -│ │ ├── api/ -│ │ ├── views/ -│ │ └── index.ts -│ ├── seller/ # 卖家中心 ✅ -│ │ ├── composables/ -│ │ ├── views/ -│ │ └── index.ts -│ ├── disputes/ # 争议仲裁 ✅ -│ │ ├── api/ -│ │ └── index.ts -│ └── admin/ # 管理后台 ✅ -│ ├── api/ -│ ├── components/ -│ ├── composables/ -│ ├── views/ -│ └── index.ts -└── shared/ # 跨模块共享层 ✅ - ├── api/ # API 客户端 - ├── composables/ # 通用 hooks - ├── components/ # 共享组件 - ├── utils/ # 工具函数 - ├── types/ # 全局类型 - └── styles/ # 全局样式 -``` - ---- - -## 📊 工作量统计 - -### 代码变更 -- **文件总数:** 128 个 -- **代码行数:** ~32,000 行 -- **Git 提交:** 7 次 - -### 时间分布 -- **P0(基础设施):** ~2小时 -- **P1(核心模块):** ~4小时(包括订单重构) -- **P2(扩展模块):** ~3小时 -- **P3(剩余模块):** ~1小时 -- **总耗时:** ~10小时 - -### Git 提交历史 -1. **b5903a1** - P0 + P1 部分(wallet, chats) -2. **125d83f** - P1 订单模块迁移与重构 -3. **f415832** - P1 完成总结文档 -4. **405abfa** - P2(listings, auth) -5. **3534cff** - P2 完成总结文档 -6. **c939763** - P3(seller, disputes, admin) - ---- - -## ⭐ 核心成果 - -### 1. 建立 Features 架构基础 - -**shared/ 共享层(22个文件)** -- ✅ API 基础设施 -- ✅ 通用工具函数(8个模块) -- ✅ 全局类型定义 -- ✅ 通用 composables -- ✅ 全局样式 - -**features/ 业务层(106个文件)** -- ✅ 9个独立业务模块 -- ✅ 清晰的模块边界 -- ✅ 标准化结构 -- ✅ 统一导出规范 - ---- - -### 2. 订单模块重构(核心亮点) - -**原始问题:** useOrderDetail.ts 405行,混合多个领域 - -**重构方案:** 拆分为3个独立 composables -- **usePaymentPolling.ts**(65行)- 支付轮询 -- **useSettlement.ts**(170行)- 结算流程 -- **useOrderDetail.ts**(215行)- 核心订单 - -**优势:** -- ✅ 单一职责,职责清晰 -- ✅ 可复用,支付和结算逻辑可独立使用 -- ✅ 易测试,小文件更容易测试 -- ✅ 易维护,从405行拆分为3个文件 - ---- - -### 3. 技术改进 - -#### 导入路径规范化 -```typescript -// ✅ 模块内部使用相对路径 -import { fetchListings } from '../api/listings' - -// ✅ 跨模块引用使用绝对路径 -import { apiClient } from '@/shared/api/client' -import type { ApiResponse } from '@/shared/types/types' -``` - -#### 模块化导出体系 -```typescript -// features/orders/index.ts -export * from './api/orders' -export * from './composables/useOrderDetail' -export * from './composables/usePaymentPolling' -export * from './composables/useSettlement' -``` - -#### 类型安全 -```typescript -// shared/types/ 统一管理 -import type { ApiResponse } from '@/shared/types/types' -import type { OrderStatus } from '@/shared/types/status' -``` - ---- - -## 🎯 架构优势 - -### 1. 可维护性 -- **模块独立:** 每个 feature 可独立开发、测试、部署 -- **职责清晰:** 代码按业务领域组织 -- **易于定位:** 找功能直接看对应 feature - -### 2. 可扩展性 -- **水平扩展:** 新增功能模块不影响现有模块 -- **垂直扩展:** 单个模块内部可灵活拆分 - -### 3. 可复用性 -- **shared/ 层:** 通用能力全局复用 -- **独立 composables:** 如 usePaymentPolling 可在任何需要支付的地方使用 - -### 4. 开发体验 -- **心智负担低:** 开发订单功能只需关注 features/orders/ -- **导入清晰:** `import { useOrderDetail } from '@/features/orders'` -- **易于协作:** 不同开发者可并行开发不同 feature - ---- - -## 📖 经验总结 - -### 1. 渐进式迁移策略有效 -- ✅ 先建立 shared/ 基础设施 -- ✅ 从简单模块入手(wallet, chats) -- ✅ 最后处理复杂模块(orders, admin) - -### 2. 重构时机把握 -- ✅ 发现臃肿代码立即重构 -- ✅ 避免技术债务累积 - -### 3. 保持小步前进 -- ✅ 每完成一个阶段立即提交 -- ✅ 便于回滚和问题定位 - -### 4. 文档记录重要 -- ✅ 每个阶段完成后记录总结 -- ✅ 便于团队理解和审核 - ---- - -## ⏭️ 下一步工作 - -### 清理阶段(必须) - -#### 1. 更新路由配置 -- 修改 router/*.ts 文件 -- 更新所有页面导入路径 -- 从 `@/views/` 改为 `@/features/*/views/` - -#### 2. 删除旧文件 -```bash -# 备份后删除 -rm -rf api/ views/ composables/ -# 保留 stores/(全局状态) -# 保留 layouts/(布局模板) -``` - -#### 3. 类型检查与修复 -```bash -npm run typecheck -# 修复所有类型错误 -``` - -#### 4. 全面测试 -- 启动开发服务器 -- 测试每个模块的核心功能 -- 确保无回归问题 - -#### 5. 更新文档 -- 更新 README.md -- 添加新架构说明 -- 更新开发指南 - ---- - -## ✅ 验证清单 - -**已完成:** -- [x] 所有模块迁移完成(9/9) -- [x] shared/ 共享层建立 -- [x] 订单模块重构 -- [x] 导入路径规范化 -- [x] 模块导出体系建立 -- [x] 提交到 Git - -**待完成:** -- [ ] 更新路由配置 -- [ ] 删除旧文件 -- [ ] 类型检查通过 -- [ ] 开发服务器验证 -- [ ] 全面功能测试 -- [ ] 更新文档 -- [ ] 推送到远程 -- [ ] 创建 Pull Request - ---- - -## 🚀 如何继续 - -### 选项 1:继续清理工作 -开始更新路由配置和删除旧文件 - -### 选项 2:先推送当前成果 -```bash -git push origin refactor/features-architecture -``` - -### 选项 3:创建 PR 让团队审核 -等待团队审核架构设计后再继续清理 - ---- - -## 🎉 庆祝成就 - -**Features 架构迁移全部完成!** - -- ✅ 9个业务模块 -- ✅ 128个文件 -- ✅ ~32,000行代码 -- ✅ 清晰的架构边界 -- ✅ 可维护、可扩展、可复用 - -这是一个重要的里程碑,为项目的长期发展奠定了坚实的基础! - ---- - -**项目:** hfb_sys -**分支:** refactor/features-architecture -**状态:** 迁移完成,待清理 -**进度:** 90%(9/10 步骤,剩余清理工作) diff --git a/docs/FEATURES_MIGRATION_PROGRESS.md b/docs/FEATURES_MIGRATION_PROGRESS.md deleted file mode 100644 index b27e400..0000000 --- a/docs/FEATURES_MIGRATION_PROGRESS.md +++ /dev/null @@ -1,240 +0,0 @@ -# Features 架构迁移进度报告 - 更新 - -**日期:** 2026-06-04 -**分支:** refactor/features-architecture -**状态:** P1 阶段完成 ✅ - ---- - -## ✅ 已完成的工作(P0 + P1) - -### P0: 基础设施准备 ✅ -创建了新的目录结构并迁移共享资源(22个文件) - -### P1.1: 钱包模块(wallet) ✅ -完整迁移钱包模块到 `features/wallet/`(5个文件) - -### P1.2: 聊天模块(chats) ✅ -完整迁移聊天模块到 `features/chats/`(8个文件) - -### P1.3: 订单模块(orders) ✅ 新增 -**完整迁移并重构订单模块到 `features/orders/`(11个文件)** - -``` -features/orders/ -├── api/ -│ └── orders.ts # 订单 API(已更新导入路径) -├── composables/ -│ ├── useOrderDetail.ts # 核心订单逻辑(重构后) -│ ├── useOrderSnapshot.ts # 订单快照 -│ ├── usePaymentPolling.ts # ✨ 新:支付轮询逻辑 -│ └── useSettlement.ts # ✨ 新:结算流程逻辑 -├── views/ -│ ├── OrdersView.vue # 订单列表 -│ ├── OrderDetailView.vue # 订单详情 -│ ├── OrderCreateView.vue # 创建订单 -│ ├── MobileOrdersView.vue # 移动端订单列表 -│ └── MobileOrderDetailView.vue # 移动端订单详情 -├── types.ts # 类型定义 -└── index.ts # 模块统一导出 -``` - ---- - -## 🎯 核心重构成果 - -### 1. useOrderDetail.ts 拆分重构 - -**原始问题:** 405行代码混合了订单、支付、结算、争议等多个领域 - -**重构方案:** 按职责拆分为3个独立 composables - -#### ① usePaymentPolling.ts(支付轮询) -**职责:** 轮询查询支付状态,直到支付完成 -```typescript -export function usePaymentPolling() { - // 支付轮询逻辑 - // - 开始/停止轮询 - // - 检查支付状态 - // - 自动重新加载订单 -} -``` - -#### ② useSettlement.ts(结算流程) -**职责:** 处理订单结算的完整流程 -```typescript -export function useSettlement(order) { - // 结算流程逻辑 - // - 提交结算单 - // - 接受/反驳结算 - // - 确认最终结算 - // - 结算表单管理 -} -``` - -#### ③ useOrderDetail.ts(核心订单) -**职责:** 订单的核心流程,组合使用上面两个 composables -```typescript -export function useOrderDetail() { - const paymentPolling = usePaymentPolling() - const settlement = useSettlement(order) - - return { - // 订单核心逻辑 - // + 支付轮询能力 - // + 结算流程能力 - } -} -``` - -**重构优势:** -- ✅ 职责清晰:每个 composable 专注单一领域 -- ✅ 可复用:支付轮询和结算逻辑可独立使用 -- ✅ 易测试:独立 composables 更容易编写单元测试 -- ✅ 易维护:从 405 行拆分为 3 个文件,每个 ~150 行 - ---- - -## 📊 迁移统计 - -| 阶段 | 模块 | 状态 | 文件数 | 重构点 | -|------|------|------|--------|--------| -| **P0** | shared | ✅ | 22 | 建立共享层 | -| **P1** | wallet | ✅ | 5 | 新增 useWallet | -| **P1** | chats | ✅ | 8 | - | -| **P1** | orders | ✅ | 11 | 拆分 useOrderDetail | -| **总计** | **4个模块** | ✅ | **46** | **3个新 composables** | - ---- - -## 🏗️ 已建立的架构 - -``` -frontend/src/ -├── features/ ← 业务功能模块 -│ ├── wallet/ ✅ P1 -│ ├── chats/ ✅ P1 -│ ├── orders/ ✅ P1 (已重构) -│ ├── listings/ ⏳ P2 -│ ├── auth/ ⏳ P2 -│ ├── seller/ ⏸️ P3 -│ ├── disputes/ ⏸️ P3 -│ └── admin/ ⏸️ P3 -└── shared/ ← 跨模块共享层 ✅ - ├── api/ - ├── composables/ - ├── components/ - ├── utils/ - ├── types/ - └── styles/ -``` - ---- - -## 🔧 技术改进 - -1. **导入路径规范化** - - ✅ 所有 features 内部使用相对路径 - - ✅ 跨模块引用使用 `@/shared/` 或 `@/features/` - - ✅ 避免循环依赖 - -2. **模块化导出体系** - - ✅ 每个 feature 有 `index.ts` 统一导出 - - ✅ API、composables、types 分层导出 - -3. **代码质量提升** - - ✅ 拆分臃肿的 composables(405行 → 3个文件) - - ✅ 单一职责原则 - - ✅ 提高可测试性 - ---- - -## 📝 文档 - -1. **迁移计划** (`docs/FEATURES_ARCHITECTURE_PLAN.md`) - - 完整的9阶段迁移路线图 - - 详细的单模块迁移步骤 - -2. **进度报告** (本文档) - - 实时进度跟踪 - - 重构成果记录 - ---- - -## ⏭️ 下一步:P2 阶段 - -### P2.1: 商品浏览模块(listings) - 待开始 -**预计文件:** ~12个 -- API: listings.ts, listingOptions.ts, homeConfig.ts -- Views: 5个页面(桌面+移动) -- Composables: home/ 目录下的3个文件 -- Components: ListingCard, 多个过滤器组件 - -### P2.2: 用户认证模块(auth) - 待开始 -**预计文件:** ~10个 -- API: auth.ts, realname.ts, notifications.ts -- Views: 登录、注册、个人资料等 -- Composables: useSmsCountdown 等 - ---- - -## ⚠️ 已知问题(待 P2 时修复) - -### 类型错误 -``` -src/composables/order/useOrderDetail.ts - evidence 属性类型不匹配 -src/composables/order/useOrderSnapshot.ts - listing_snapshot 属性缺失 -``` -**原因:** 旧的 composables 目录中的文件尚未更新 -**解决:** P2 阶段更新路由和导入后统一清理 - -### 测试依赖 -``` -src/composables/home/__tests__/*.spec.ts - 缺少 vitest -``` -**解决:** 安装 vitest 或移动测试文件到对应 feature - ---- - -## 🎉 里程碑成就 - -✅ **P1 阶段完成!** - -- 核心业务模块(订单、钱包、聊天)已完成迁移 -- 完成了最复杂的重构(useOrderDetail 拆分) -- 建立了可复用的架构模式 -- 为 P2/P3 阶段奠定基础 - -**总代码变更:** 预计 60+ 文件,10000+ 行代码 - ---- - -## 📅 预计剩余工作量 - -| 阶段 | 模块 | 预计时间 | 复杂度 | -|------|------|----------|--------| -| P2 | listings | 3小时 | 中 | -| P2 | auth | 3小时 | 中 | -| P3 | seller | 2小时 | 低 | -| P3 | disputes | 1小时 | 低 | -| P3 | admin | 4小时 | 高 | -| **清理** | 删除旧文件、更新路由 | 2小时 | - | -| **总计** | - | **15小时** | - | - ---- - -**当前提交:** 准备提交 P1 完整成果 -**下次继续:** P2.1 商品浏览模块(listings) - ---- - -## 验证清单 - -- [x] P0 基础设施完成 -- [x] P1.1 钱包模块完成 -- [x] P1.2 聊天模块完成 -- [x] P1.3 订单模块完成并重构 -- [ ] 运行类型检查(待 P2 清理旧文件后) -- [ ] 启动开发服务器验证 -- [ ] 更新路由配置 -- [ ] 端到端功能测试 diff --git a/docs/FINAL_SUMMARY.md b/docs/FINAL_SUMMARY.md deleted file mode 100644 index 188b561..0000000 --- a/docs/FINAL_SUMMARY.md +++ /dev/null @@ -1,221 +0,0 @@ -# 🎉 Features 架构迁移与清理 - 最终总结 - -**完成时间:** 2026-06-04 -**分支:** refactor/features-architecture -**最终提交:** 99e537c - ---- - -## ✅ 完成的工作 - -### 阶段 1-3:模块迁移(100% 完成)✅ - -| 阶段 | 模块 | 文件数 | 状态 | -|------|------|--------|------| -| P0 | shared | 22 | ✅ | -| P1 | wallet, chats, orders | 24 | ✅ (含重构) | -| P2 | listings, auth | 35 | ✅ | -| P3 | seller, disputes, admin | 47 | ✅ | -| **总计** | **9个模块** | **128** | **✅** | - -### 阶段 4:清理工作(90% 完成)✅ - -| 任务 | 状态 | 详情 | -|------|------|------| -| 更新路由配置 | ✅ | 44个路由已更新 | -| 删除旧文件 | ✅ | 111个文件,33,317行代码 | -| 批量更新导入路径 | ✅ | 所有 features 已更新 | -| 类型错误修复 | 🔄 | 272 → 106(减少61%)| -| 功能测试 | ⏳ | 待验证 | - ---- - -## 📊 类型错误修复进度 - -### 修复历程 -- **初始:** 272个错误 -- **第一轮:** 272 → 190(-82,修复 admin API) -- **第二轮:** 190 → 135(-55,修复 features Vue 文件) -- **第三轮:** 135 → 113(-22,迁移 files API) -- **第四轮:** 113 → 106(-7,修复剩余导入) - -**总进步:** 减少166个错误,修复率 61% - -### 剩余错误分类(106个) - -#### 1. 模块找不到错误(47个) -- 主要是一些 Vue 文件还在使用旧的 `@/api/` 路径 -- `vitest` 测试库未安装(2个) -- 缺失组件文件(1个 MobileHomeFilterSheet.vue) - -#### 2. 类型注解错误(~50个) -- Parameter implicitly 'any' type(约30个) -- 属性不存在错误(约10个) -- 类型不匹配(约10个) - -这些都是次要错误,不影响运行时功能。 - ---- - -## 📁 最终架构 - -``` -frontend/src/ -├── features/ # 9个业务模块 ✅ -│ ├── wallet/ # 钱包支付 -│ ├── chats/ # 聊天消息 -│ ├── orders/ # 订单管理(已重构) -│ ├── listings/ # 商品浏览 -│ ├── auth/ # 用户认证 -│ ├── seller/ # 卖家中心 -│ ├── disputes/ # 争议仲裁 -│ └── admin/ # 管理后台 -├── shared/ # 共享资源层 ✅ -│ ├── api/ # API客户端 + files -│ ├── composables/ # 通用hooks -│ ├── utils/ # 工具函数 -│ ├── types/ # 全局类型 -│ └── styles/ # 全局样式 -├── components/ # 全局组件 ✅ -├── layouts/ # 布局模板 ✅ -├── router/ # 路由配置 ✅ (已更新) -├── stores/ # 全局状态 ✅ -└── utils/ # 工具函数 ✅ -``` - ---- - -## Git 提交历史(15次提交) - -### 迁移阶段(7次) -1. b5903a1 - P0 + P1 部分 -2. 125d83f - P1 订单重构 -3. f415832 - P1 文档 -4. 405abfa - P2 完成 -5. 3534cff - P2 文档 -6. c939763 - P3 完成 -7. d5abb99 - 完成文档 - -### 清理阶段(8次) -8. 3d5db9d - 更新路由配置 -9. 5e87858 - 删除旧文件(-33,317行) -10. e010f2c - 批量更新导入路径 -11. 956c2ec - 修复大量导入错误(+files API) -12. 29e79ff - 继续修复导入 -13. 5ba154c - 修复最后一批导入 -14. 99e537c - 修复 admin index 导出 - -**总变更:** ~32,000行代码 - ---- - -## 🎯 核心成果 - -### 1. 完整的 Features 架构 -- ✅ 9个独立业务模块 -- ✅ 清晰的模块边界 -- ✅ 统一的导出规范 -- ✅ 共享资源层 - -### 2. 订单模块重构 -- ✅ 405行拆分为3个 composables -- ✅ usePaymentPolling(支付轮询) -- ✅ useSettlement(结算流程) -- ✅ useOrderDetail(核心订单) - -### 3. 大幅减少技术债 -- ✅ 删除111个重复文件 -- ✅ 统一导入路径 -- ✅ 修复166个类型错误 - ---- - -## ⏭️ 剩余工作(~10%) - -### 1. 修复剩余导入路径(约47个) -主要在这些文件: -- `features/admin/views/AdminLoginView.vue` -- `features/auth/views/*.vue`(5个文件) -- `features/listings/views/*.vue`(5个文件) -- `features/orders/views/*.vue`(2个文件) - -**预计时间:** 30分钟 - -### 2. 修复类型注解(约50个,可选) -这些是代码质量问题,不影响运行: -- 添加参数类型注解 -- 修复属性访问 -- 调整函数签名 - -**预计时间:** 1-2小时(可选) - -### 3. 功能测试 -```bash -npm run dev -# 测试关键功能 -``` - -**预计时间:** 30分钟 - ---- - -## 📈 量化指标 - -| 指标 | 数值 | -|------|------| -| 迁移文件数 | 128个 | -| 删除文件数 | 111个 | -| 代码行数变更 | ~32,000行 | -| Git 提交数 | 15次 | -| 类型错误修复 | 166个(61%)| -| 路由更新 | 44个 | -| 工作时长 | ~12小时 | - ---- - -## 🎉 项目状态 - -**架构迁移进度:** 95% -**类型安全进度:** 61% -**功能完整性:** 100% - -### 可以做的事: -1. ✅ 推送到远程分支 -2. ✅ 创建 Pull Request -3. ⏳ 修复剩余的47个导入错误(可选) -4. ⏳ 启动开发服务器测试 - -### 架构优势已体现: -- ✅ 模块独立性 -- ✅ 清晰的依赖关系 -- ✅ 易于维护和扩展 -- ✅ 更好的开发体验 - ---- - -## 💡 建议 - -### 选项 1:立即推送和审核 -当前状态已经非常好,虽然还有106个类型错误,但: -- 61%的错误已修复 -- 剩余错误不影响运行 -- 架构已经完整建立 - -**建议:** 推送到远程,创建PR,让团队审核架构设计 - -### 选项 2:继续修复到0错误 -继续花30分钟-2小时修复剩余错误 - -**建议:** 如果不赶时间,可以做到完美 - -### 选项 3:功能测试后再推送 -先启动项目,测试核心功能,确保没有破坏 - -**建议:** 最稳妥的方案 - ---- - -**当前分支:** refactor/features-architecture -**建议下一步:** 启动开发服务器测试,然后推送到远程 - -需要我继续修复剩余的47个导入错误,还是先测试功能? diff --git a/docs/MONEY_PRECISION_COMPLETED.md b/docs/MONEY_PRECISION_COMPLETED.md deleted file mode 100644 index 1450fbd..0000000 --- a/docs/MONEY_PRECISION_COMPLETED.md +++ /dev/null @@ -1,204 +0,0 @@ -# 金额精度统一优化 - 最终完成报告 - -## ✅ 优化完成 - -**时间**: 2026-06-04 -**状态**: 已完成并验证通过 - ---- - -## 📋 改动总结 - -### 核心变更 -将全项目金额处理从**整元四舍五入**统一为**角精度(0.1元)** - -### 后端改动 ✅ - -**新增模块** -``` -backend/pkg/money/format.go -├── Round(value float64) float64 // 角精度四舍五入 -├── Min(a, b float64) float64 // 返回较小金额 -├── Max(a, b float64) float64 // 返回较大金额 -├── Format(value float64) string // 格式化为字符串 -└── FormatWithSymbol(value float64) string // 添加货币符号 -``` - -**更新的业务模块** -- ✅ `internal/modules/order/repository.go` - 订单结算 -- ✅ `internal/modules/dispute/repository.go` - 纠纷仲裁 -- ✅ `internal/modules/listing/service.go` - 商品定价 -- ✅ `internal/modules/listing/repository.go` - 商品存储 - -**测试验证** -```bash -✅ PASS: TestCalculateCheckoutSettlementRefundsUnusedRent -✅ PASS: TestCalculateCheckoutSettlementUsesBuyerAndSellerRatiosSeparately -✅ PASS: TestCalculateCheckoutSettlementAddsDepositCompensation -✅ PASS: TestArchiveListingAfterCheckoutMovesListingOffline -``` - -### 前端改动 ✅ - -**新增工具模块** -``` -frontend/src/shared/utils/money.ts -├── roundMoney(value: number): number // 角精度四舍五入 -├── formatMoney(value: number | undefined | null): string // 格式化金额 -└── formatMoneyWithSymbol(value: number | undefined | null): string // 添加¥符号 -``` - -**更新的模块** -- ✅ `shared/utils/pricing.ts` - 定价计算逻辑 -- ✅ `shared/utils/listingDisplay.ts` - 商品显示 -- ✅ `shared/composables/useMoney.ts` - 组合式函数 -- ✅ `features/listings/views/ListingDetailView.vue` - PC商品详情 -- ✅ `features/listings/views/MobileListingDetailView.vue` - 移动端详情 -- ✅ `features/seller/views/SellerHandoffsView.vue` - 卖家管理 - -### 文档 ✅ - -- ✅ `docs/MONEY_PRECISION_REFACTOR.md` - 技术详细说明 -- ✅ `docs/MONEY_PRECISION_SUMMARY.md` - 完成总结 -- ✅ `docs/PROJECT_ANALYSIS.md` - 项目整体分析 - ---- - -## 🎯 效果对比 - -| 场景 | 优化前 | 优化后 | 说明 | -|------|--------|--------|------| -| 商品定价 | ¥123 | ¥123.0 | 统一显示1位小数 | -| 租金计算 | ¥100 | ¥100.5 | 支持角精度 | -| 押金显示 | ¥50 | ¥50.0 | 格式统一 | -| 结算金额 | ¥243.7 (误差) | ¥243.7 (精确) | 减少累积误差 | - -### 计算示例 - -**示例1: 消耗品金额** -```typescript -// 优化前 -12.34 + 8.67 = 21.01 -> Math.round(21.01) = 21 ❌ 损失0.01 - -// 优化后 -12.34 + 8.67 = 21.01 -> roundMoney(21.01) = 21.0 ✅ 精度保持 -``` - -**示例2: 订单结算** -```go -// 优化前: 整元四舍五入 -ActualRentAmount: 244.0 // 243.7 被四舍五入,损失0.3元 - -// 优化后: 角精度 -ActualRentAmount: 243.7 // 精确到角 -``` - ---- - -## 🚀 验证结果 - -### 编译测试 ✅ -```bash -✅ 后端编译通过: go build ./cmd/api -✅ 后端测试通过: go test ./internal/modules/order/... -✅ 开发环境启动成功 -``` - -### 运行状态 ✅ -``` -✅ MySQL 已就绪 -✅ Redis 已就绪 -✅ MinIO 已就绪 -✅ 后端服务运行中: http://localhost:8080 -✅ 前端服务运行中: http://localhost:5173 -✅ API 请求正常响应 -``` - -### 实际请求验证 -``` -2026-06-04 16:31:17 GET /api/listings -> 200 OK (1.115ms) -2026-06-04 16:31:17 GET /api/wallet/balance -> 200 OK (7.841ms) -2026-06-04 16:31:16 GET /api/orders -> 200 OK (0.682ms) -``` - ---- - -## 📊 数据兼容性 - -### 数据库层面 -- **字段定义**: `DECIMAL(12,2)` 保持不变 -- **存储精度**: 仍支持分精度(0.01元) -- **业务精度**: 统一使用角精度(0.1元) -- **向下兼容**: 已有数据自动适配 - -### API 层面 -- **请求参数**: 支持任意精度输入 -- **响应数据**: 浮点数格式,业务层已角精度处理 -- **前端显示**: 统一 `.toFixed(1)` 格式化 - ---- - -## 📝 待手动验证项 - -### 高优先级 -1. ⏳ 前端类型检查: `cd frontend && npm run typecheck` -2. ⏳ 前端构建测试: `npm run build` -3. ⏳ 手动测试完整支付流程 -4. ⏳ 检查后台管理页面金额显示 - -### 建议场景 -- 创建新商品,验证价格显示 -- 下单支付,验证金额计算 -- 订单结算,验证退款金额 -- 钱包流水,验证余额变动 - ---- - -## 💡 技术细节 - -### 角精度算法 -```go -func Round(value float64) float64 { - return math.Round(value*10) / 10 -} - -// 示例: -// 12.34 -> 12.3 -// 12.36 -> 12.4 -// 12.35 -> 12.4 (银行家舍入) -``` - -### 前端格式化 -```typescript -formatMoney(123.4) // "123.4" -formatMoney(100.0) // "100.0" ← 保持1位小数 -formatMoney(null) // "0.0" ← 处理空值 -``` - ---- - -## 🎉 优化成果 - -### 问题解决 -- ✅ **统一精度**: 全项目金额精度规范一致 -- ✅ **减少误差**: 从整元改为角精度,更精确 -- ✅ **显示规范**: 前端统一 `.toFixed(1)` 格式 -- ✅ **测试通过**: 所有单元测试已更新并通过 - -### 质量提升 -- **代码一致性**: 所有金额处理使用统一函数 -- **可维护性**: 集中管理,易于未来调整精度 -- **用户体验**: 金额显示更准确,避免"少了几毛钱"的疑惑 - ---- - -## 📚 相关文档 - -- [项目整体分析报告](./PROJECT_ANALYSIS.md) -- [金额精度重构详细说明](./MONEY_PRECISION_REFACTOR.md) - ---- - -**优化完成人**: Claude Code -**完成时间**: 2026-06-04 16:31 -**系统状态**: ✅ 正常运行 diff --git a/docs/MONEY_PRECISION_REFACTOR.md b/docs/MONEY_PRECISION_REFACTOR.md deleted file mode 100644 index b96ff99..0000000 --- a/docs/MONEY_PRECISION_REFACTOR.md +++ /dev/null @@ -1,170 +0,0 @@ -# 金额精度统一优化说明 - -## 修改内容 - -### 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. 监控生产环境金额误差(理论上不应有差异) diff --git a/docs/MONEY_PRECISION_SUMMARY.md b/docs/MONEY_PRECISION_SUMMARY.md deleted file mode 100644 index 4df0f0b..0000000 --- a/docs/MONEY_PRECISION_SUMMARY.md +++ /dev/null @@ -1,133 +0,0 @@ -# 金额精度统一优化 - 完成总结 - -## ✅ 已完成的工作 - -### 1. 后端改动 - -**创建统一金额处理包** -- ✅ `backend/pkg/money/format.go` - 角精度处理函数 - -**更新业务模块** -- ✅ `backend/internal/modules/order/repository.go` - 订单金额计算 -- ✅ `backend/internal/modules/dispute/repository.go` - 纠纷金额处理 -- ✅ `backend/internal/modules/listing/service.go` - 商品定价 -- ✅ `backend/internal/modules/listing/repository.go` - 商品金额存储 - -**测试用例更新** -- ✅ `backend/internal/modules/order/repository_test.go` - 更新为角精度期望值 - -### 2. 前端改动 - -**创建统一金额工具** -- ✅ `frontend/src/shared/utils/money.ts` - 金额处理函数 -- ✅ `frontend/src/shared/utils/index.ts` - 导出money模块 - -**更新金额计算** -- ✅ `frontend/src/shared/utils/pricing.ts` - roundMoney改为角精度 -- ✅ `frontend/src/shared/utils/listingDisplay.ts` - 所有金额显示统一 - -**更新组件** -- ✅ `frontend/src/shared/composables/useMoney.ts` - 使用新的formatMoneyWithSymbol -- ✅ `frontend/src/features/listings/views/ListingDetailView.vue` - PC端商品详情 -- ✅ `frontend/src/features/listings/views/MobileListingDetailView.vue` - 移动端商品详情 -- ✅ `frontend/src/features/seller/views/SellerHandoffsView.vue` - 卖家交接管理 - -### 3. 文档 - -- ✅ `docs/MONEY_PRECISION_REFACTOR.md` - 详细说明文档 - -## 核心变更 - -### 精度规范 - -**优化前:整元四舍五入** -```go -func roundMoney(value float64) float64 { - return math.Round(value) // 12.45 -> 12.0 -} -``` - -**优化后:角精度(0.1元)** -```go -func roundMoney(value float64) float64 { - return math.Round(value*10) / 10 // 12.45 -> 12.5 -} -``` - -### 显示格式 - -**前端统一格式化** -```typescript -formatMoney(123.4) // "123.4" -formatMoney(100.0) // "100.0" -formatMoneyWithSymbol(50.5) // "¥50.5" -``` - -## 测试结果 - -```bash -cd backend && go test ./internal/modules/order/... -# PASS: TestCalculateCheckoutSettlementRefundsUnusedRent -# PASS: TestCalculateCheckoutSettlementUsesBuyerAndSellerRatiosSeparately -# PASS: TestCalculateCheckoutSettlementAddsDepositCompensation -# PASS: TestArchiveListingAfterCheckoutMovesListingOffline -``` - -## 影响评估 - -### 用户可见变化 - -| 场景 | 优化前 | 优化后 | -|------|--------|--------| -| 商品价格 | ¥123 | ¥123.0 | -| 押金 | ¥50 | ¥50.0 | -| 租金计算 | ¥100 | ¥100.5 | -| 订单总价 | ¥273 | ¥273.5 | - -### 业务逻辑影响 - -- **金额计算**:从整元精度改为角精度,更精确 -- **数据库存储**:DECIMAL(12,2)不变,兼容现有数据 -- **API响应**:金额字段保持浮点数,前端统一格式化 -- **向下兼容**:已有订单数据自动适配 - -## 剩余工作 - -### 需要手动验证的场景 - -1. **前端其他视图** - 检查还有没有遗漏的Math.round() - ```bash - grep -rn "Math.round" frontend/src/features --include="*.vue" --include="*.ts" - ``` - -2. **后台管理页面** - admin相关的金额显示 - ```bash - grep -rn "Math.round" frontend/src/features/admin --include="*.vue" - ``` - -3. **移动端页面** - 移动端金额显示组件 - -4. **钱包模块** - 余额/流水显示 - -### 建议后续优化 - -1. ✅ 补充单元测试覆盖边界情况 -2. 添加 E2E 测试验证完整支付流程 -3. 监控生产环境金额计算,确保无误差 -4. 考虑配置化精度(方便未来调整) - -## 验证清单 - -- ✅ 后端编译通过 -- ✅ 后端测试通过 -- ⏳ 前端类型检查(需运行 `npm run typecheck`) -- ⏳ 前端构建测试(需运行 `npm run build`) -- ⏳ 手动测试:创建商品 -- ⏳ 手动测试:下单支付 -- ⏳ 手动测试:订单结算 - -## 总结 - -已完成**后端和核心前端**的金额精度统一优化,从整元四舍五入改为角精度(0.1元)。所有金额计算和显示逻辑已统一,测试用例已更新并通过。 - -建议在部署前进行完整的手动测试,特别是支付和结算流程,确保金额计算正确。 diff --git a/docs/OPTIMIZATION_PLAN.md b/docs/OPTIMIZATION_PLAN.md new file mode 100644 index 0000000..7510ba3 --- /dev/null +++ b/docs/OPTIMIZATION_PLAN.md @@ -0,0 +1,802 @@ +# HFB Sys 项目优化计划 + +> 生成时间: 2026-06-05 +> 项目版本: refactor/features-architecture 分支 + +## 项目概况 + +**项目名称**: HFB Sys - 哈夫币租号平台 +**技术栈**: +- 后端: Go 1.26 + Gin + GORM + MySQL 8.4 + Redis 7.4 +- 前端: Vue 3 + TypeScript + Vite + Element Plus + Vant +- 基础设施: Docker Compose + MinIO + +**代码规模**: +- 后端: 120个Go文件, ~18,625行代码, 21个业务模块 +- 前端: 69个Vue组件, ~34,750行代码, 10个功能模块 +- 测试覆盖: 仅5个测试文件 (覆盖率极低 ⚠️) +- 依赖包: 185MB node_modules + +--- + +## 🔴 高优先级问题 (立即处理) + +### 1. 测试覆盖率严重不足 + +**问题描述**: +- 整个项目只有5个测试文件 (`backend/internal/modules/order/repository_test.go` 等) +- 核心业务逻辑(订单、钱包、支付)缺少单元测试 +- 前端组件完全没有测试 + +**影响范围**: +- 代码质量无法保证 +- 重构和功能迭代风险高 +- 无法及时发现回归问题 +- 金额计算、订单状态流转等关键逻辑缺少验证 + +**解决方案**: + +#### 后端测试 +```go +// 示例: backend/internal/modules/wallet/service_test.go +package wallet_test + +import ( + "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestWalletService_Deduct(t *testing.T) { + // 测试余额扣减 + // 测试余额不足情况 + // 测试并发扣减 +} +``` + +#### 前端测试 +```typescript +// 示例: frontend/src/features/orders/__tests__/OrderList.spec.ts +import { describe, it, expect } from 'vitest' +import { mount } from '@vue/test-utils' +import OrderList from '../views/OrderList.vue' + +describe('OrderList', () => { + it('renders order items correctly', () => { + // 测试订单列表渲染 + }) +}) +``` + +**目标**: +- [ ] 核心模块测试覆盖率达到 70% +- [ ] 订单模块: 状态流转、金额计算、超时处理 +- [ ] 钱包模块: 余额操作、并发控制、流水记录 +- [ ] 支付模块: 支付回调、退款流程 +- [ ] 前端核心组件测试覆盖率 50%+ + +**工具选择**: +- 后端: Go `testing` + `testify` + `mockery` +- 前端: `vitest` + `@vue/test-utils` + +--- + +### 2. 数据库索引优化不足 + +**问题描述**: +- 迁移文件 `backend/migrations/000001_init.sql` 中索引定义85个 +- 缺少针对高频复合查询的覆盖索引 +- 时间范围查询缺少优化 + +**影响范围**: +- 订单列表查询可能较慢 +- 钱包流水查询性能不佳 +- 后台管理页面加载慢 + +**需要添加的索引**: + +```sql +-- 1. 订单状态+创建时间查询 (后台订单管理、用户订单列表) +CREATE INDEX idx_rental_orders_status_created_at +ON rental_orders(status, created_at DESC); + +-- 2. 钱包流水按用户+业务类型+时间查询 +CREATE INDEX idx_wallet_ledger_user_biz_created +ON wallet_ledger(user_id, biz_type, created_at DESC); + +-- 3. 订单结算状态查询优化 +CREATE INDEX idx_rental_orders_settlement +ON rental_orders(settlement_status, owner_id, created_at); + +-- 4. 商品筛选查询优化 +CREATE INDEX idx_rental_listings_published +ON rental_listings(status, review_status, published_at DESC) +WHERE in_transaction = 0; + +-- 5. 用户实名认证状态查询 +CREATE INDEX idx_users_realname_status +ON users(realname_status, status); +``` + +**执行计划**: +- [ ] 创建新的迁移文件 `000003_add_indexes.sql` +- [ ] 在开发环境验证查询性能提升 +- [ ] 使用 `EXPLAIN` 分析慢查询 +- [ ] 生产环境灰度添加索引 + +**监控指标**: +- 慢查询日志 (>100ms) +- 索引命中率 +- 查询平均响应时间 + +--- + +### 3. 环境变量管理不规范 + +**问题描述**: +- `.env.example` 包含40个环境变量 +- JWT_SECRET 默认值为 "change-me" (安全隐患) +- 配置分散在多个文件中 +- 缺少配置校验 + +**影响范围**: +- 生产环境可能使用不安全的默认值 +- 配置错误难以发现 +- 缺少环境差异化配置管理 + +**解决方案**: + +#### 1. 使用 Viper 进行配置管理 +```go +// backend/internal/config/config.go +package config + +import ( + "github.com/spf13/viper" +) + +type Config struct { + App AppConfig + Database DatabaseConfig + JWT JWTConfig + // ... +} + +func Load() (*Config, error) { + viper.SetConfigName("config") + viper.SetConfigType("yaml") + viper.AddConfigPath("./configs") + viper.AutomaticEnv() + + // 配置校验 + if err := viper.ReadInConfig(); err != nil { + return nil, err + } + + var cfg Config + if err := viper.Unmarshal(&cfg); err != nil { + return nil, err + } + + // 安全配置强制校验 + if cfg.App.Env == "production" { + if cfg.JWT.Secret == "change-me" || len(cfg.JWT.Secret) < 32 { + return nil, errors.New("production JWT secret must be set and >= 32 chars") + } + } + + return &cfg, nil +} +``` + +#### 2. 配置文件分层 +``` +backend/configs/ +├── config.yaml # 默认配置 +├── config.dev.yaml # 开发环境覆盖 +├── config.prod.yaml # 生产环境覆盖 +└── config.local.yaml # 本地开发 (git ignore) +``` + +#### 3. 使用密钥管理服务 +```yaml +# 生产环境使用 Vault / AWS Secrets Manager +jwt: + secret: ${VAULT_JWT_SECRET} +database: + password: ${VAULT_DB_PASSWORD} +``` + +**执行计划**: +- [ ] 安装 Viper: `go get github.com/spf13/viper` +- [ ] 重构 `internal/config` 包 +- [ ] 迁移环境变量到 YAML 配置 +- [ ] 添加配置校验逻辑 +- [ ] 更新文档和部署脚本 + +--- + +### 4. 前端缺少统一的 HTTP 请求封装 + +**问题描述**: +- 未找到 `frontend/src/utils/request.ts` 文件 +- axios 直接在各个 API 文件中使用 +- Token 刷新、错误处理逻辑可能分散 +- 缺少统一的 Loading 状态管理 + +**影响范围**: +- Token 过期处理不一致 +- 错误提示用户体验差 +- 重复代码多 +- 难以统一添加日志、监控 + +**解决方案**: + +```typescript +// frontend/src/utils/request.ts +import axios, { AxiosError, AxiosRequestConfig } from 'axios' +import { ElMessage } from 'element-plus' +import { useSessionStore } from '@/stores/session' +import { getAccessToken, getRefreshToken, setAuthTokens } from '@/utils/authStorage' + +// 创建 axios 实例 +const request = axios.create({ + baseURL: '/api', + timeout: 30000, +}) + +// 请求拦截器 +request.interceptors.request.use( + (config) => { + // 自动添加 Token + const token = getAccessToken('user') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// 响应拦截器 +let isRefreshing = false +let refreshSubscribers: Array<(token: string) => void> = [] + +request.interceptors.response.use( + (response) => { + return response.data + }, + async (error: AxiosError) => { + const originalRequest = error.config as AxiosRequestConfig & { _retry?: boolean } + + // Token 过期,尝试刷新 + if (error.response?.status === 401 && !originalRequest._retry) { + if (isRefreshing) { + // 等待 Token 刷新完成 + return new Promise((resolve) => { + refreshSubscribers.push((token: string) => { + if (originalRequest.headers) { + originalRequest.headers.Authorization = `Bearer ${token}` + } + resolve(request(originalRequest)) + }) + }) + } + + originalRequest._retry = true + isRefreshing = true + + try { + const refreshToken = getRefreshToken('user') + if (!refreshToken) { + throw new Error('No refresh token') + } + + // 调用刷新接口 + const { data } = await axios.post('/api/auth/refresh', { + refresh_token: refreshToken, + }) + + setAuthTokens('user', { + access_token: data.access_token, + refresh_token: data.refresh_token, + }) + + // 通知所有等待的请求 + refreshSubscribers.forEach((callback) => callback(data.access_token)) + refreshSubscribers = [] + + // 重试原请求 + if (originalRequest.headers) { + originalRequest.headers.Authorization = `Bearer ${data.access_token}` + } + return request(originalRequest) + } catch (refreshError) { + // 刷新失败,跳转登录 + const session = useSessionStore() + session.logout() + window.location.href = '/login' + return Promise.reject(refreshError) + } finally { + isRefreshing = false + } + } + + // 统一错误处理 + const message = error.response?.data?.message || error.message || '请求失败' + ElMessage.error(message) + + return Promise.reject(error) + } +) + +export default request +``` + +**使用方式**: +```typescript +// frontend/src/features/orders/api/orders.ts +import request from '@/utils/request' + +export const fetchOrders = (params: any) => { + return request.get('/orders', { params }) +} +``` + +**执行计划**: +- [ ] 创建 `frontend/src/utils/request.ts` +- [ ] 重构所有 API 调用使用统一封装 +- [ ] 实现 Token 刷新机制 +- [ ] 添加请求/响应日志 +- [ ] 测试 Token 过期场景 + +--- + +## 🟠 中优先级改进 (近期处理) + +### 5. 路由守卫性能问题 + +**问题**: `frontend/src/router/index.ts` 的 `beforeEach` 在每次导航时都可能调用 `session.loadMe()` + +**优化方案**: +```typescript +// frontend/src/router/index.ts +router.beforeEach(async (to) => { + // ... 其他逻辑 + + if (to.meta.requiresAuth) { + const session = useSessionStore() + session.syncFromStorage() + const hasToken = !!session.token + + if (!hasToken) { + const loginPath = getLoginPath('user', to.path) + return { path: loginPath, query: { redirect: to.fullPath } } + } + + // 优化: 添加缓存判断和加载中标志 + if (!session.phone && !session._loadingMe) { + session._loadingMe = true + try { + await session.loadMe() + } catch (error) { + const loginPath = getLoginPath('user', to.path) + return { path: loginPath, query: { redirect: to.fullPath } } + } finally { + session._loadingMe = false + } + } + } + + // ... 其他逻辑 +}) +``` + +--- + +### 6. 前端组件复用性不足 + +**现状**: +- `frontend/src/components/` 仅有2个共享组件 +- `frontend/src/shared/composables/` 仅有4个组合式函数 +- 许多页面可能存在重复的 UI 逻辑 + +**建议提取的通用组件**: +- [ ] `StatusTag.vue` - 状态标签 +- [ ] `DateRangePicker.vue` - 日期范围选择 +- [ ] `EmptyState.vue` - 空状态占位 +- [ ] `LoadingOverlay.vue` - 加载遮罩 +- [ ] `ImageUpload.vue` - 图片上传 +- [ ] `MoneyDisplay.vue` - 金额展示 +- [ ] `OrderStatusFlow.vue` - 订单状态流程 + +**建议提取的 Composables**: +- [ ] `useTable.ts` - 表格分页、排序 +- [ ] `useForm.ts` - 表单验证、提交 +- [ ] `useModal.ts` - 弹窗状态管理 +- [ ] `usePermission.ts` - 权限判断 +- [ ] `useWebSocket.ts` - WebSocket 连接 + +--- + +### 7. 后端路由初始化代码过长 + +**问题**: `backend/internal/router/router.go` 文件415行,所有依赖注入在一个 `New` 函数中 + +**重构方案**: + +#### 方案一: 模块化路由注册 +```go +// backend/internal/router/router.go +func New(cfg config.Config, deps Dependencies, logger *zap.Logger) *gin.Engine { + engine := gin.New() + engine.Use(middleware.RequestID()) + engine.Use(middleware.RequestLogger(logger)) + engine.Use(middleware.Recovery(logger)) + + // 初始化依赖 + services := initServices(cfg, deps, logger) + + // 注册路由 + api := engine.Group("/api") + registerAuthRoutes(api, services.auth) + registerUserRoutes(api, services.user, services.auth.JWTManager) + registerOrderRoutes(api, services.order, services.auth.JWTManager) + // ... + + return engine +} + +// backend/internal/router/auth_routes.go +func registerAuthRoutes(api *gin.RouterGroup, authSvc *auth.Service) { + authHandler := auth.NewHandler(authSvc) + authRoutes := api.Group("/auth") + { + authRoutes.POST("/sms/send", authHandler.SendSMS) + authRoutes.POST("/sms/login", authHandler.Login) + authRoutes.POST("/refresh", authHandler.Refresh) + authRoutes.POST("/logout", authHandler.Logout) + } +} +``` + +#### 方案二: 使用依赖注入容器 (Wire) +```go +// backend/internal/wire/wire.go +//go:build wireinject +// +build wireinject + +package wire + +import ( + "github.com/google/wire" + "hfb_sys/backend/internal/router" +) + +func InitializeApp(cfg config.Config) (*gin.Engine, error) { + wire.Build( + provideDB, + provideRedis, + auth.NewJWTManager, + auth.NewService, + order.NewService, + router.New, + ) + return nil, nil +} +``` + +--- + +### 8. 缺少 API 文档自动化 + +**解决方案**: 集成 Swagger/OpenAPI + +```go +// 1. 安装 swag +// go install github.com/swaggo/swag/cmd/swag@latest + +// 2. 在 handler 添加注释 +// backend/internal/modules/order/handler.go + +// CreateOrder 创建订单 +// @Summary 创建租赁订单 +// @Description 根据商品ID创建新的租赁订单 +// @Tags 订单 +// @Accept json +// @Produce json +// @Param body body CreateOrderRequest true "订单信息" +// @Success 200 {object} CreateOrderResponse +// @Failure 400 {object} ErrorResponse +// @Router /api/orders [post] +// @Security BearerAuth +func (h *Handler) Create(c *gin.Context) { + // ... +} + +// 3. 生成文档 +// swag init -g cmd/api/main.go -o docs + +// 4. 注册路由 +import "github.com/swaggo/gin-swagger" +import "github.com/swaggo/files" + +engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) +``` + +--- + +## 🟢 低优先级优化 (持续改进) + +### 9. 前端构建优化 + +```typescript +// frontend/vite.config.ts 优化 +import { visualizer } from 'rollup-plugin-visualizer' +import viteCompression from 'vite-plugin-compression' + +export default defineConfig({ + plugins: [ + vue(), + // Gzip 压缩 + viteCompression({ + algorithm: 'gzip', + ext: '.gz', + }), + // Brotli 压缩 + viteCompression({ + algorithm: 'brotliCompress', + ext: '.br', + }), + // 构建分析 + visualizer({ + open: true, + filename: 'dist/stats.html', + }), + ], + build: { + // 代码分割优化 + rollupOptions: { + output: { + manualChunks: { + 'vendor-vue': ['vue', 'vue-router', 'pinia'], + 'vendor-element': ['element-plus', '@element-plus/icons-vue'], + 'vendor-vant': ['vant'], + 'vendor-utils': ['axios', 'qrcode'], + }, + }, + }, + // 启用 CSS 代码分割 + cssCodeSplit: true, + // 文件大小限制警告 + chunkSizeWarningLimit: 1000, + }, +}) +``` + +### 10. 日志和监控增强 + +#### Prometheus 指标收集 +```go +// backend/internal/metrics/metrics.go +import "github.com/prometheus/client_golang/prometheus" + +var ( + httpRequestsTotal = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "http_requests_total", + Help: "Total HTTP requests", + }, + []string{"method", "path", "status"}, + ) + + httpRequestDuration = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "http_request_duration_seconds", + Help: "HTTP request duration", + }, + []string{"method", "path"}, + ) +) + +// 注册中间件 +engine.Use(metrics.PrometheusMiddleware()) +engine.GET("/metrics", gin.WrapH(promhttp.Handler())) +``` + +#### 慢查询日志 +```go +// backend/internal/database/database.go +import "gorm.io/plugin/dbresolver" + +db.Use(&SlowQueryLogger{ + SlowThreshold: 100 * time.Millisecond, + Logger: logger, +}) +``` + +### 11. Redis 缓存策略优化 + +```go +// 示例: 系统配置缓存 +func (r *Repository) GetConfig(key string) (*model.SystemConfig, error) { + // 1. 查询缓存 + cacheKey := fmt.Sprintf("config:%s", key) + cached, err := r.redis.Get(ctx, cacheKey).Result() + if err == nil { + var config model.SystemConfig + json.Unmarshal([]byte(cached), &config) + return &config, nil + } + + // 2. 缓存未命中,查询数据库 + var config model.SystemConfig + if err := r.db.Where("key = ?", key).First(&config).Error; err != nil { + return nil, err + } + + // 3. 写入缓存 (5分钟过期) + data, _ := json.Marshal(config) + r.redis.Set(ctx, cacheKey, data, 5*time.Minute) + + return &config, nil +} +``` + +### 12. 代码质量工具集成 + +#### 后端 golangci-lint +```yaml +# backend/.golangci.yml +linters: + enable: + - gofmt + - govet + - errcheck + - staticcheck + - gosimple + - ineffassign + - unused + - misspell + - gocyclo +``` + +#### 前端 ESLint + Prettier +```json +// frontend/.eslintrc.json +{ + "extends": [ + "plugin:vue/vue3-recommended", + "@vue/typescript/recommended", + "prettier" + ], + "rules": { + "vue/multi-word-component-names": "off", + "@typescript-eslint/no-explicit-any": "warn" + } +} +``` + +#### Pre-commit hooks +```json +// package.json +{ + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.{ts,vue}": ["eslint --fix", "prettier --write"], + "*.go": ["gofmt -w", "golangci-lint run"] + } +} +``` + +### 13. Docker 镜像优化 + +```dockerfile +# backend/Dockerfile (多阶段构建) +FROM golang:1.26-alpine AS builder +WORKDIR /app +COPY go.* ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o api ./cmd/api + +FROM alpine:latest +RUN apk --no-cache add ca-certificates tzdata +WORKDIR /app +COPY --from=builder /app/api . +EXPOSE 8080 +CMD ["./api"] +``` + +```dockerfile +# frontend/Dockerfile +FROM node:20-alpine AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM nginx:alpine +COPY --from=builder /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] +``` + +--- + +## 📅 实施计划 + +### 第一周 (基础设施) +- [ ] 周一-周二: 为 order、wallet、payment 模块添加单元测试 +- [ ] 周三: 创建数据库索引迁移文件并测试 +- [ ] 周四: 创建前端统一请求封装 `request.ts` +- [ ] 周五: 重构现有 API 调用使用新封装 + +### 第二周 (工具集成) +- [ ] 周一: 集成 Swagger API 文档 +- [ ] 周二: 配置 golangci-lint 和 ESLint +- [ ] 周三: 添加 pre-commit hooks +- [ ] 周四-周五: 优化路由守卫和路由初始化代码 + +### 第三周 (性能优化) +- [ ] 周一-周二: 实现 Redis 缓存策略 +- [ ] 周三: 添加 Prometheus 监控 +- [ ] 周四: Docker 镜像优化 +- [ ] 周五: 前端构建优化和测试 + +### 第四周 (测试和发布) +- [ ] 周一-周三: 补充测试用例,达到覆盖率目标 +- [ ] 周四: 性能测试和压力测试 +- [ ] 周五: 文档更新,代码审查 + +--- + +## 📊 成功指标 + +### 代码质量 +- [ ] 核心模块测试覆盖率 ≥ 70% +- [ ] golangci-lint 检查通过 +- [ ] 前端 ESLint 检查通过 +- [ ] 0 个 TODO/FIXME 注释 + +### 性能指标 +- [ ] API 平均响应时间 < 100ms (P95) +- [ ] 数据库慢查询 < 10 条/天 +- [ ] 前端首屏加载时间 < 2s +- [ ] 缓存命中率 > 80% + +### 安全性 +- [ ] 生产环境所有默认密码已更改 +- [ ] JWT Secret 长度 ≥ 32 字符 +- [ ] 所有敏感信息使用密钥管理服务 +- [ ] 通过安全扫描 (Snyk/Trivy) + +--- + +## 附录 + +### 相关文档 +- [项目计划](./project-plan.md) +- [数据库设计](./database.md) +- [API 文档](./api.md) +- [业务规则](./business-rules.md) + +### 参考资源 +- [Go Testing Best Practices](https://go.dev/doc/tutorial/add-a-test) +- [Vue Test Utils](https://test-utils.vuejs.org/) +- [MySQL Index Design](https://dev.mysql.com/doc/refman/8.0/en/optimization-indexes.html) +- [Viper Configuration](https://github.com/spf13/viper) + +--- + +**最后更新**: 2026-06-05 +**负责人**: 待分配 +**审核人**: 待分配 diff --git a/docs/P1_COMPLETION_SUMMARY.md b/docs/P1_COMPLETION_SUMMARY.md deleted file mode 100644 index 886d359..0000000 --- a/docs/P1_COMPLETION_SUMMARY.md +++ /dev/null @@ -1,310 +0,0 @@ -# Features 架构迁移 - P1 阶段完成总结 - -## 🎉 里程碑达成 - -**P1 阶段(核心业务模块)已全部完成!** - ---- - -## 📊 完成情况 - -### 迁移统计 - -| 阶段 | 模块 | 文件数 | 代码行数 | 状态 | -|------|------|--------|----------|------| -| P0 | shared(基础设施) | 22 | ~2,000 | ✅ | -| P1.1 | wallet(钱包) | 5 | ~500 | ✅ | -| P1.2 | chats(聊天) | 8 | ~800 | ✅ | -| P1.3 | orders(订单) | 11 | ~1,200 | ✅ | -| **总计** | **4个模块** | **46** | **~4,500** | ✅ | - -### Git 提交 - -- **第一次提交 (b5903a1):** P0 + P1 部分(wallet, chats)- 42 文件 -- **第二次提交 (125d83f):** P1.3(orders 重构)- 13 文件 - -**总变更:** 55 个文件,~13,000 行代码 - ---- - -## 🏗️ 新架构概览 - -``` -frontend/src/ -├── features/ # 业务功能模块(按领域组织) -│ ├── wallet/ # 钱包支付 ✅ -│ │ ├── api/ -│ │ ├── composables/ -│ │ ├── views/ -│ │ ├── types.ts -│ │ └── index.ts -│ ├── chats/ # 聊天消息 ✅ -│ │ ├── api/ -│ │ ├── components/ -│ │ ├── composables/ -│ │ ├── views/ -│ │ └── index.ts -│ └── orders/ # 订单管理 ✅ (已重构) -│ ├── api/ -│ ├── composables/ -│ │ ├── useOrderDetail.ts # 核心订单 -│ │ ├── useOrderSnapshot.ts # 订单快照 -│ │ ├── usePaymentPolling.ts # 支付轮询 -│ │ └── useSettlement.ts # 结算流程 -│ ├── views/ -│ ├── types.ts -│ └── index.ts -└── shared/ # 跨模块共享层 ✅ - ├── api/ # API 客户端 - ├── composables/ # 通用 hooks - ├── components/ # 共享组件 - ├── utils/ # 工具函数 - ├── types/ # 全局类型 - └── styles/ # 全局样式 -``` - ---- - -## ⭐ 核心成果 - -### 1. 建立 Features 架构基础 - -**shared/ 共享层** -- ✅ API 基础设施:统一的 axios 客户端、请求/响应拦截器 -- ✅ 通用工具函数:8个工具模块(authStorage, pricing, time 等) -- ✅ 全局类型定义:status, types, publish 等 -- ✅ 通用 composables:useMoney, useSmsCountdown, usePricingCalculator -- ✅ 全局样式:5个 CSS 文件 - -**features/ 业务层** -- ✅ 清晰的模块边界:每个 feature 独立自治 -- ✅ 标准化结构:api/ + composables/ + views/ + types.ts + index.ts -- ✅ 统一导出规范:通过 index.ts 暴露公共接口 - ---- - -### 2. 订单模块重构 🌟 - -**重构前问题:** -- `useOrderDetail.ts` 405 行,混合订单、支付、结算、争议逻辑 -- 职责不清晰,难以维护和测试 -- 支付轮询和结算逻辑无法复用 - -**重构方案:** - -#### usePaymentPolling.ts(65行) -```typescript -// 专注支付轮询 -export function usePaymentPolling() { - const activePayment = ref(null) - const checkingPayment = ref(false) - - function startPaymentPolling(payment, onSuccess) { ... } - function stopPaymentPolling() { ... } - async function checkPaymentStatus(onSuccess) { ... } - - return { activePayment, checkingPayment, ... } -} -``` - -#### useSettlement.ts(170行) -```typescript -// 专注结算流程 -export function useSettlement(order) { - const checkoutForm = ref({ ... }) - const counterForm = ref({ ... }) - - async function handleSubmitCheckout(onSuccess) { ... } - async function handleAcceptCheckout(onSuccess) { ... } - async function handleCounterCheckout(onSuccess) { ... } - async function handleConfirmCheckout(onSuccess) { ... } - - return { checkoutForm, counterForm, ... } -} -``` - -#### useOrderDetail.ts(215行,重构后) -```typescript -// 核心订单逻辑,组合使用上述 composables -export function useOrderDetail() { - const paymentPolling = usePaymentPolling() - const settlement = useSettlement(order) - - async function loadOrder() { ... } - async function handlePay() { - const payment = await startOrderPayment(order.value.id) - paymentPolling.startPaymentPolling(payment, loadOrder) - } - - return { - ...paymentPolling, // 支付能力 - ...settlement, // 结算能力 - // 订单核心能力 - } -} -``` - -**重构优势:** -- ✅ 单一职责:每个 composable 专注一个领域 -- ✅ 可复用:支付轮询和结算逻辑可独立使用 -- ✅ 易测试:小文件更容易编写单元测试 -- ✅ 易维护:代码从 405 行拆分为 3 个文件(~150 行/文件) - ---- - -### 3. 技术改进 - -#### 导入路径规范化 -```typescript -// ✅ features 内部使用相对路径 -import { apiClient } from '@/shared/api/client' -import type { Order } from '../api/orders' - -// ❌ 避免旧的绝对路径 -// import { apiClient } from './client' -``` - -#### 模块化导出 -```typescript -// features/orders/index.ts -export * from './api/orders' -export * from './composables/useOrderDetail' -export * from './composables/useOrderSnapshot' -export * from './composables/usePaymentPolling' -export * from './composables/useSettlement' -``` - -#### 类型安全 -```typescript -// shared/types/ 统一管理全局类型 -import type { ApiResponse } from '@/shared/types/types' -import type { OrderStatus } from '@/shared/types/status' -``` - ---- - -## 🎯 架构优势 - -### 1. 可维护性 -- **模块独立:** 每个 feature 可以独立开发、测试、部署 -- **职责清晰:** 代码按业务领域组织,而非技术分层 -- **易于定位:** 找订单功能?直接看 `features/orders/` - -### 2. 可扩展性 -- **水平扩展:** 新增功能模块不影响现有模块 -- **垂直扩展:** 单个模块内部可以灵活拆分 composables - -### 3. 可复用性 -- **shared/ 层:** 通用能力全局复用 -- **独立 composables:** 如 usePaymentPolling 可在任何需要支付的地方使用 - -### 4. 开发体验 -- **心智负担低:** 开发订单功能只需关注 `features/orders/` -- **导入清晰:** `import { useOrderDetail } from '@/features/orders'` -- **易于协作:** 不同开发者可以并行开发不同 feature - ---- - -## 📖 学到的经验 - -### 1. 渐进式迁移策略有效 -- 先建立 shared/ 基础设施 -- 从简单模块(wallet, chats)入手 -- 最后处理复杂模块(orders) - -### 2. 重构时机把握 -- 在迁移过程中发现臃肿代码(useOrderDetail 405行) -- 立即重构而非拖延,避免技术债务累积 - -### 3. 保持小步前进 -- 每完成一个模块立即提交 -- 便于回滚和问题定位 - ---- - -## ⏭️ 下一步计划 - -### P2 阶段:扩展模块 - -#### P2.1: 商品浏览模块(listings) -- API: listings.ts, listingOptions.ts, homeConfig.ts -- Views: 5个页面 -- Composables: home/ 目录下的3个文件 -- Components: ListingCard, 多个过滤器组件 -- **预计:** 3小时 - -#### P2.2: 用户认证模块(auth) -- API: auth.ts, realname.ts, notifications.ts -- Views: 登录、注册、个人资料等 -- Composables: useSmsCountdown 等 -- **预计:** 3小时 - -### P3 阶段:剩余模块 -- seller(卖家中心)- 2小时 -- disputes(争议仲裁)- 1小时 -- admin(管理后台)- 4小时 - -### 清理阶段 -- 删除旧的 api/, views/, composables/ 目录 -- 更新路由配置 -- 移除兼容层 -- 全面测试 - ---- - -## 🚀 如何继续 - -### 选项 1:继续 P2 迁移 -```bash -# 等分类器恢复后推送 -git push origin refactor/features-architecture - -# 开始迁移 listings 模块 -``` - -### 选项 2:验证当前成果 -```bash -# 启动开发服务器 -npm run dev - -# 手动测试迁移的功能 -# - 钱包:充值、账单 -# - 聊天:消息列表、实时聊天 -# - 订单:创建、支付、交接、结算 -``` - -### 选项 3:合并到主分支 -- 当前 P0+P1 已经是可用的增量改进 -- 可以先合并,避免分支太久导致冲突 -- 后续继续在新分支上完成 P2/P3 - ---- - -## ✅ 验证清单 - -**已完成:** -- [x] P0 基础设施准备 -- [x] P1.1 钱包模块迁移 -- [x] P1.2 聊天模块迁移 -- [x] P1.3 订单模块迁移与重构 -- [x] 建立清晰的模块边界 -- [x] 统一导入路径规范 -- [x] 创建完整文档 - -**待完成:** -- [ ] 推送到远程分支 -- [ ] 运行类型检查(待清理旧文件后) -- [ ] 启动开发服务器验证 -- [ ] 更新路由配置 -- [ ] P2 阶段迁移 -- [ ] P3 阶段迁移 -- [ ] 删除旧文件 -- [ ] 全面测试 - ---- - -**当前分支:** refactor/features-architecture -**最新提交:** 125d83f -**完成进度:** 40%(4/10 模块) - -需要继续 P2 阶段吗?还是先验证当前成果? diff --git a/docs/P2_COMPLETION_SUMMARY.md b/docs/P2_COMPLETION_SUMMARY.md deleted file mode 100644 index 00b4632..0000000 --- a/docs/P2_COMPLETION_SUMMARY.md +++ /dev/null @@ -1,274 +0,0 @@ -# Features 架构迁移 - P2 阶段完成总结 - -## 🎉 P2 阶段完成! - -**完成时间:** 2026-06-04 -**分支:** refactor/features-architecture -**提交:** 405abfa - ---- - -## 📊 P2 完成情况 - -### P2.1: 商品浏览模块(listings)✅ - -**文件统计:** 23个文件 - -``` -features/listings/ -├── api/ # 3个文件 -│ ├── listings.ts # 商品 CRUD、查询 -│ ├── listingOptions.ts # 发布选项配置 -│ └── homeConfig.ts # 首页配置(横幅、公告) -├── components/ # 9个组件 -│ ├── ListingCard.vue # 商品卡片 -│ ├── HomeFilters.vue # 首页过滤器 -│ ├── RangeFilter.vue # 范围过滤 -│ ├── SkinFilter.vue # 皮肤过滤 -│ ├── StringFilter.vue # 字符串过滤 -│ ├── HomeBanner.vue # 横幅 -│ ├── HomeAnnouncement.vue # 公告 -│ ├── HomeStats.vue # 统计 -│ └── HomeZonesAndSort.vue # 分区和排序 -├── composables/ # 3个 + 2个测试 -│ ├── useHomeFilters.ts # 过滤器状态管理 -│ ├── useFilterOptions.ts # 过滤选项处理 -│ ├── useListingQuery.ts # 列表查询逻辑 -│ └── __tests__/ # 测试文件 -├── views/ # 5个页面 -│ ├── HomeView.vue # 首页 -│ ├── ListingsView.vue # 商品列表 -│ ├── ListingDetailView.vue # 商品详情 -│ ├── MobileHomeView.vue # 移动端首页 -│ └── MobileListingDetailView.vue # 移动端详情 -└── index.ts # 模块导出 -``` - -**功能覆盖:** -- ✅ 首页浏览、搜索、筛选 -- ✅ 商品详情查看 -- ✅ 高级筛选(服务器、等级、哈夫币、皮肤、价格区间等) -- ✅ 排序功能(价格、时间) -- ✅ 分区功能(租赁区、出售区等) -- ✅ 横幅、公告展示 -- ✅ 统计信息展示 -- ✅ 移动端完整支持 - ---- - -### P2.2: 用户认证模块(auth)✅ - -**文件统计:** 12个文件 - -``` -features/auth/ -├── api/ # 3个文件 -│ ├── auth.ts # 用户认证(登录、注册、Token) -│ ├── realname.ts # 实名认证 -│ └── notifications.ts # 通知消息 -├── views/ # 8个页面 -│ ├── LoginView.vue # 登录页 -│ ├── ProfileView.vue # 个人资料 -│ ├── RealnameView.vue # 实名认证 -│ ├── NotificationsView.vue # 通知列表 -│ ├── MobileLoginView.vue # 移动端登录 -│ ├── MobileRegisterView.vue # 移动端注册 -│ ├── MobileProfileView.vue # 移动端个人资料 -│ └── MobileRealnameView.vue # 移动端实名认证 -└── index.ts # 模块导出 -``` - -**功能覆盖:** -- ✅ 短信验证码登录 -- ✅ 用户注册 -- ✅ Token 管理(刷新、过期处理) -- ✅ 实名认证流程 -- ✅ 个人资料编辑 -- ✅ 头像上传 -- ✅ 通知中心 -- ✅ 风险检查 -- ✅ 移动端完整支持 - ---- - -## 📈 累计进度 - -### 已完成模块统计 - -| 阶段 | 模块 | 文件数 | 状态 | -|------|------|--------|------| -| P0 | shared | 22 | ✅ | -| P1 | wallet | 5 | ✅ | -| P1 | chats | 8 | ✅ | -| P1 | orders | 11 | ✅ (已重构) | -| P2 | listings | 23 | ✅ | -| P2 | auth | 12 | ✅ | -| **总计** | **6个模块** | **81** | **✅** | - -### Git 提交历史 - -- **405abfa** - feat: P2阶段完成 - listings和auth模块迁移 -- **f415832** - docs: 添加 P1 阶段完成总结 -- **125d83f** - feat: P1阶段完成 - 订单模块迁移与重构 -- **b5903a1** - feat: Features架构迁移 - P0和P1部分完成 - -**总变更:** 90个文件,~23,000行代码 - ---- - -## 🏗️ 当前架构全貌 - -``` -frontend/src/ -├── features/ # 业务功能模块 ✅ -│ ├── wallet/ # 钱包支付 ✅ -│ ├── chats/ # 聊天消息 ✅ -│ ├── orders/ # 订单管理 ✅ (已重构) -│ ├── listings/ # 商品浏览 ✅ -│ ├── auth/ # 用户认证 ✅ -│ ├── seller/ # 卖家中心 ⏸️ P3 -│ ├── disputes/ # 争议仲裁 ⏸️ P3 -│ └── admin/ # 管理后台 ⏸️ P3 -└── shared/ # 共享资源层 ✅ - ├── api/ - ├── composables/ - ├── components/ - ├── utils/ - ├── types/ - └── styles/ -``` - ---- - -## ⭐ 技术亮点 - -### 1. 模块独立性 -每个 feature 都是自治的,包含: -- API 层:独立的 API 调用 -- Composables 层:业务逻辑 -- Views 层:页面视图 -- Components 层:专属组件 -- 统一导出:通过 index.ts - -### 2. 导入路径规范 -```typescript -// ✅ 模块内部使用相对路径 -import { fetchListings } from '../api/listings' - -// ✅ 跨模块引用使用绝对路径 -import { apiClient } from '@/shared/api/client' -import type { ApiResponse } from '@/shared/types/types' -``` - -### 3. 共享层设计 -``` -shared/ -├── api/ # API 客户端、拦截器 -├── composables/ # 通用 hooks(useMoney, usePricingCalculator) -├── utils/ # 工具函数(8个模块) -├── types/ # 全局类型定义 -└── styles/ # 全局样式 -``` - ---- - -## ⏭️ 下一步:P3 阶段 - -### 剩余模块 - -#### P3.1: 卖家中心(seller) -- API: 复用 listings.ts -- Views: 4个页面 -- Composables: usePublishForm, usePublishDraft -- **预计:** 2小时 - -#### P3.2: 争议仲裁(disputes) -- API: disputes.ts -- Components: 从 OrderDetail 拆分 -- Composables: useDispute -- **预计:** 1小时 - -#### P3.3: 管理后台(admin) -- API: 8个 admin API 文件 -- Views: 15个管理页面 -- Composables: useAdminTable, useAdminPaginatedTable -- **预计:** 4小时 - -### 清理工作 -- 删除旧的 api/, views/, composables/ 目录 -- 更新路由配置 -- 移除兼容层(如果建立了的话) -- 全面测试 -- **预计:** 2小时 - -**P3 总预计:** ~9小时 - ---- - -## 📊 整体进度 - -**已完成:** 60%(6/10 模块) - -**剩余工作:** -- ⏸️ P3: 3个模块(seller, disputes, admin) -- 🔧 清理:删除旧文件、更新路由、测试 - -**预计剩余时间:** ~9小时 - ---- - -## ✅ P2 验证清单 - -- [x] listings 模块迁移完成(23个文件) -- [x] auth 模块迁移完成(12个文件) -- [x] 所有 API 导入路径已更新 -- [x] 模块导出文件已创建 -- [ ] 类型检查通过(待清理旧文件后) -- [ ] 开发服务器启动验证 -- [ ] 功能测试(首页、登录、个人资料) - ---- - -## 🎯 架构优势体现 - -### 开发体验改善 -- **心智负担降低:** 开发商品功能只需关注 `features/listings/` -- **导入清晰:** `import { fetchListings } from '@/features/listings'` -- **并行开发:** 不同开发者可以独立开发不同 feature - -### 代码组织改善 -- **模块边界清晰:** 每个 feature 职责明确 -- **依赖关系明确:** shared/ 是基础,features/ 是业务 -- **易于重构:** 可以独立重构单个 feature - -### 可维护性提升 -- **易于定位:** 找功能直接看对应 feature -- **易于测试:** 每个 feature 可以独立测试 -- **易于删除:** 废弃功能直接删除整个 feature 目录 - ---- - -## 🚀 如何继续 - -### 选项 1:继续 P3 迁移 -继续迁移剩余的3个模块(seller, disputes, admin) - -### 选项 2:先验证 P2 成果 -```bash -npm run dev -# 测试首页、商品列表、登录、注册等功能 -``` - -### 选项 3:推送并休息 -```bash -git push origin refactor/features-architecture -# 让分类器恢复,或者团队审核当前进度 -``` - ---- - -**当前分支:** refactor/features-architecture -**最新提交:** 405abfa -**完成进度:** 60%(6/10 模块) - -需要我继续 P3 阶段吗? diff --git a/docs/PROJECT_ANALYSIS.md b/docs/PROJECT_ANALYSIS.md deleted file mode 100644 index ad1fd75..0000000 --- a/docs/PROJECT_ANALYSIS.md +++ /dev/null @@ -1,472 +0,0 @@ -# HFB 租号平台项目分析报告 - -生成时间:2026-06-04 - -## 项目概况 - -**项目定位**:《三角洲行动》游戏账号租赁平台,面向 C2C 租号场景 -**技术栈**:Go + Gin + GORM + MySQL + Redis / Vue 3 + TypeScript + Vite + Element Plus -**代码规模**: -- 后端:~18,000 行 Go 代码,121 个文件 -- 前端:~32,000 行 TypeScript/Vue 代码,158 个文件 -- 测试覆盖:后端 5 个测试文件(覆盖率极低) -- 最近活跃度:近两周 179 次提交(开发活跃) - -**架构特点**: -- 前后端分离,RESTful API 设计 -- 模块化设计(19 个业务模块) -- Docker Compose 本地开发环境 -- 支持 Mock 和真实服务切换 - ---- - -## 一、优势亮点 ✅ - -### 1.1 架构设计合理 -- **清晰的模块化**:按业务领域拆分(auth、listing、order、wallet、dispute 等),职责清晰 -- **三层架构**:Repository → Service → Handler 分层明确 -- **依赖注入**:通过构造函数注入,便于测试和扩展 -- **中间件设计**:request_id、logger、recovery、auth、permission 等职责分离 - -### 1.2 工程化完善 -- **一键启动脚本**:`./scripts/dev.sh` 自动化所有启动流程 -- **健康检查机制**:Docker 容器和 HTTP 服务都有完善的健康检查 -- **日志管理**:使用 Zap 结构化日志,支持按天切分 -- **配置管理**:支持环境变量和 .env 文件,开发/生产环境隔离 -- **数据库迁移**:自动检测并执行 SQL 迁移脚本 - -### 1.3 业务功能完整 -- 核心交易流程:发布 → 审核 → 下单 → 交接 → 归还 → 结算 -- 风控体系:实名认证、信用分、冻结机制 -- 纠纷处理:申诉仲裁、证据上传、客服介入 -- 通知系统:站内信 + 订单群聊 -- 后台管理:用户、订单、商品、审核、审计日志 - -### 1.4 开发体验良好 -- **类型安全**:前端 TypeScript 严格模式,后端 Go 强类型 -- **组件化**:前端按 features 组织,共享组件复用 -- **自动化构建**:Vite 热更新 + Docker 多阶段构建优化镜像体积 -- **代码整洁**:无 TODO/FIXME 残留,console.log 极少 - ---- - -## 二、待优化问题 ⚠️ - -### 2.1 测试覆盖严重不足 🔴 - -**现状**: -- 后端仅 5 个测试文件,覆盖率不足 5% -- 前端配置了 Vitest 但无测试用例 -- 缺少集成测试、E2E 测试 - -**风险**: -- 核心金融逻辑(钱包、订单、押金)无测试保障 -- 重构时容易引入 Bug -- 交付质量完全依赖手工测试 - -**建议**: -``` -优先级 P0: -1. 钱包服务单元测试(余额计算、流水记录、并发安全) -2. 订单状态机测试(状态转换、超时处理) -3. 支付回调测试(幂等性、签名校验) - -优先级 P1: -4. 实名认证集成测试 -5. 权限中间件测试 -6. 前端核心流程 E2E 测试(发布-下单-交接) -``` - -### 2.2 错误处理不一致 - -**现状**: -- 部分模块返回自定义错误(如 `auth.ErrInvalidPhone`) -- 部分模块直接返回 `fmt.Errorf` -- 缺少统一的错误码体系 -- 前端错误处理分散在各组件 - -**建议**: -```go -// 统一错误定义 -package errors - -type BizError struct { - Code string // "AUTH_INVALID_PHONE" - Message string // "手机号格式错误" - HTTPCode int // 400 -} - -// 错误注册表 -var ( - ErrInvalidPhone = &BizError{"AUTH_INVALID_PHONE", "手机号格式错误", 400} - ErrInsufficientBalance = &BizError{"WALLET_INSUFFICIENT", "余额不足", 400} - // ... -) - -// 中间件统一处理 -func ErrorHandler() gin.HandlerFunc { - return func(c *gin.Context) { - c.Next() - if len(c.Errors) > 0 { - err := c.Errors.Last().Err - if bizErr, ok := err.(*BizError); ok { - c.JSON(bizErr.HTTPCode, gin.H{"code": bizErr.Code, "message": bizErr.Message}) - } - } - } -} -``` - -### 2.3 性能瓶颈隐患 - -**问题点**: - -1. **N+1 查询风险** - ```go - // 潜在问题:循环中查询用户信息 - for _, order := range orders { - user := getUserByID(order.UserID) // N+1 查询 - } - - // 优化方案:使用 GORM Preload - db.Preload("Owner").Preload("Renter").Find(&orders) - ``` - -2. **缺少缓存层** - - 系统配置每次查询数据库 - - 用户实名状态高频读取无缓存 - - 商品列表无 Redis 缓存 - -3. **Redis 连接未复用** - - 每个请求都创建新连接(检查 `redis.Client` 是否全局单例) - -**建议**: -```go -// 系统配置缓存 -func (s *SystemConfigService) GetConfig(key string) (string, error) { - cacheKey := "config:" + key - val, err := s.redis.Get(ctx, cacheKey).Result() - if err == redis.Nil { - val, err = s.repo.GetConfig(key) - if err == nil { - s.redis.Set(ctx, cacheKey, val, 5*time.Minute) - } - } - return val, err -} -``` - -### 2.4 安全加固建议 - -**现状问题**: - -1. **JWT Secret 弱密钥** - ```env - JWT_SECRET=change-me # 开发环境默认值风险 - ``` - -2. **缺少 Rate Limiting** - - 登录接口无防暴力破解 - - 短信验证码虽有冷却但无 IP 级限流 - -3. **文件上传安全** - - 虽限制文件类型,但未检测文件内容(MIME 伪造风险) - - 无文件大小限制(潜在 DoS) - -4. **SQL 注入风险低但需注意** - - GORM 参数化查询保护较好 - - 但存在 `db.Where("status = ?", status)` 手动拼接风险 - -**建议**: -```go -// 1. 强制生产环境强密钥 -if cfg.AppEnv == "production" && cfg.JWTSecret == "change-me" { - log.Fatal("生产环境必须设置强 JWT_SECRET") -} - -// 2. 添加限流中间件 -func RateLimitMiddleware(redis *redis.Client) gin.HandlerFunc { - return func(c *gin.Context) { - key := "rate:" + c.ClientIP() + ":" + c.Request.URL.Path - count, _ := redis.Incr(c, key).Result() - if count == 1 { - redis.Expire(c, key, time.Minute) - } - if count > 100 { // 每分钟 100 次 - c.AbortWithStatusJSON(429, gin.H{"error": "请求过于频繁"}) - return - } - c.Next() - } -} - -// 3. 文件内容检测 -func validateFileContent(file []byte, allowedTypes []string) error { - mimeType := http.DetectContentType(file) - for _, allowed := range allowedTypes { - if mimeType == allowed { - return nil - } - } - return errors.New("文件类型不允许") -} -``` - -### 2.5 数据库设计可优化 - -**问题点**: - -1. **索引缺失** - ```sql - -- 缺少复合索引 - SELECT * FROM rental_orders - WHERE renter_id = ? AND status = ? - ORDER BY created_at DESC; - -- 建议添加:KEY idx_orders_renter_status_time (renter_id, status, created_at) - ``` - -2. **JSON 字段查询效率低** - ```sql - -- asset_summary、season_tags 使用 JSON 存储 - -- 如需频繁按标签查询,建议改为关联表 - CREATE TABLE listing_tags ( - listing_id BIGINT, - tag_type VARCHAR(32), - tag_value VARCHAR(64), - INDEX(listing_id), - INDEX(tag_type, tag_value) - ); - ``` - -3. **大字段分离不足** - - `description TEXT` 与主查询字段混在一起 - - 建议分离到 `listing_details` 表 - -**建议**: -```sql --- 优化热点查询索引 -ALTER TABLE rental_orders -ADD INDEX idx_orders_renter_status_time (renter_id, status, created_at); - -ALTER TABLE rental_orders -ADD INDEX idx_orders_owner_status_time (owner_id, status, created_at); - --- 钱包流水查询优化 -ALTER TABLE wallet_ledger -ADD INDEX idx_ledger_user_time (user_id, created_at DESC); -``` - -### 2.6 前端优化空间 - -**问题点**: - -1. **代码分割可优化** - - 虽有 `manualChunks`,但 Element Plus 和 Vant 同时使用导致体积臃肿 - - 建议按桌面/移动端路由懒加载 - -2. **API 调用缺少取消机制** - ```typescript - // 问题:用户快速切换页面时,旧请求未取消 - const fetchData = async () => { - const data = await api.get('/listings'); - } - - // 建议:使用 AbortController - const controller = new AbortController(); - const data = await api.get('/listings', { signal: controller.signal }); - onUnmounted(() => controller.abort()); - ``` - -3. **状态管理可简化** - - 部分简单状态用 Pinia 过度设计 - - 可用 `provide/inject` 或 `localStorage` 简化 - -4. **TypeScript `any` 残留** - - 虽然很少(1 处),但建议完全消除 - -**建议**: -```typescript -// 1. 路由懒加载 + 预加载 -const routes = [ - { - path: '/admin', - component: () => import('@/layouts/AdminLayout.vue'), - children: [ - { - path: 'users', - component: () => import('@/features/admin/views/UsersView.vue'), - } - ] - } -]; - -// 2. API 取消封装 -export const useCancelableRequest = () => { - const controller = ref(new AbortController()); - - onUnmounted(() => controller.value.abort()); - - const request = async (url: string, options = {}) => { - return axios.get(url, { - ...options, - signal: controller.value.signal - }); - }; - - return { request }; -}; -``` - -### 2.7 监控和运维缺失 🔴 - -**现状**: -- 无性能监控(APM) -- 无错误追踪(Sentry) -- 无业务指标监控(Prometheus + Grafana) -- 日志仅存储本地,无集中采集 - -**建议**: -```yaml -# docker-compose.prod.yml 添加监控栈 -services: - prometheus: - image: prom/prometheus - volumes: - - ./prometheus.yml:/etc/prometheus/prometheus.yml - - grafana: - image: grafana/grafana - ports: - - "3000:3000" - - loki: - image: grafana/loki - - promtail: - image: grafana/promtail - volumes: - - ./backend/logs:/logs - - ./promtail.yml:/etc/promtail/config.yml -``` - -```go -// 后端添加 Prometheus 指标 -import "github.com/prometheus/client_golang/prometheus" - -var ( - httpRequestDuration = prometheus.NewHistogramVec(...) - orderCreated = prometheus.NewCounterVec(...) - walletBalance = prometheus.NewGaugeVec(...) -) -``` - -### 2.8 文档维护问题 - -**现状**: -- API 文档手动维护(`docs/api.md`),易过期 -- 缺少 Swagger/OpenAPI 自动生成 -- 缺少架构图、流程图 -- 开发规范未文档化 - -**建议**: -```go -// 使用 swaggo 自动生成 API 文档 -// @title HFB 租号平台 API -// @version 1.0 -// @host localhost:8080 -// @BasePath /api - -// @Summary 发送登录验证码 -// @Tags 认证 -// @Param phone body string true "手机号" -// @Success 200 {object} response.Success -// @Router /auth/send-code [post] -func (h *Handler) SendCode(c *gin.Context) { ... } - -// 启动时访问 /swagger/index.html -``` - ---- - -## 三、优化优先级建议 - -### P0 - 立即修复(影响生产安全) - -1. **补充核心业务单元测试**(钱包、订单、支付) -2. **生产环境安全加固**(强密钥、限流、文件校验) -3. **添加监控告警**(至少日志采集 + 错误告警) -4. **数据库热点索引优化** - -### P1 - 近期优化(提升质量) - -5. **统一错误处理体系** -6. **系统配置缓存层** -7. **N+1 查询优化** -8. **前端代码分割优化** -9. **API 文档自动化** - -### P2 - 长期改进(提升体验) - -10. **引入 APM 性能监控** -11. **前端错误边界和离线缓存** -12. **数据库读写分离(如果流量增长)** -13. **CI/CD 流水线完善** - ---- - -## 四、技术债务清单 - -| 类别 | 问题 | 影响 | 工作量估算 | -|------|------|------|-----------| -| 测试 | 缺少单元测试 | 高 | 3-5 人天 | -| 安全 | 限流机制缺失 | 高 | 1 人天 | -| 性能 | 缺少缓存层 | 中 | 2 人天 | -| 监控 | 无 APM 和告警 | 高 | 3 人天 | -| 文档 | API 文档手动维护 | 低 | 1 人天 | -| 数据库 | 索引优化 | 中 | 0.5 人天 | - -**总估算**:10-15 人天可完成 P0+P1 优化 - ---- - -## 五、架构演进建议 - -### 5.1 短期(3 个月内) -- 完善测试覆盖到 60%+ -- 接入 Sentry 错误追踪 -- 添加 Redis 缓存层 -- 补充核心业务监控指标 - -### 5.2 中期(6-12 个月) -- 考虑微服务拆分(订单服务独立) -- 引入消息队列(RabbitMQ/Kafka)处理异步任务 -- 实施数据库分库分表(按用户 ID 哈希) -- WebSocket 优化为独立长连接服务 - -### 5.3 长期(1 年以上) -- 多租户改造(支持多游戏品类) -- 智能定价和反欺诈模型 -- 区块链存证(订单不可篡改) -- 海外市场国际化 - ---- - -## 六、总结 - -**整体评价**:⭐⭐⭐⭐☆ (4/5) - -这是一个**架构清晰、工程化良好**的商业项目,核心业务逻辑完整,代码质量整体优秀。主要短板在**测试覆盖和监控体系**,这在快速迭代期可以理解,但在生产上线前必须补齐。 - -**最紧迫的 3 件事**: -1. 补充核心金融逻辑单元测试 -2. 生产环境安全加固(限流 + 强密钥 + 文件校验) -3. 接入基础监控(日志采集 + 错误告警) - -完成这 3 项后,项目就具备了生产级可靠性。后续可按优先级逐步优化性能和体验。 - ---- - -**分析人**:Claude Code -**项目规模**:中型(5 万行代码) -**技术栈成熟度**:高(Go + Vue 主流栈) -**团队建议规模**:3-5 人(2 后端 + 2 前端 + 1 测试/运维) diff --git a/docs/business-rules.md b/docs/business-rules.md deleted file mode 100644 index ded25e0..0000000 --- a/docs/business-rules.md +++ /dev/null @@ -1,191 +0,0 @@ -# 业务规则 - -业务规则以 [项目计划](project-plan.md) 为准。 - -一期关键边界: - -- 哈夫币是游戏账号内资产,不是平台币。 -- 哈夫币数量由号主手动填报,订单创建时生成账号资产快照。 -- 平台不保存游戏账号密码,不代收验证码,不绕过游戏安全机制。 -- 账号交接采用号主手动交接。 -- 资金先做账务模型,不直接接真实支付和提现。 -- 押金、交接超时、归还超时、短信限流等阈值进入系统配置。 - -## 开发态实名认证 - -- 当前实现为 mock 实名服务。 -- 提交合法姓名和 18 位身份证号后直接通过认证。 -- 后端只返回脱敏姓名和脱敏证件号。 -- 用户表 `realname_status` 会同步更新为 `verified`。 -- 后续接入阿里云或腾讯云实名服务时,保持 `POST /api/realname/start` 和 `GET /api/realname/status` 的业务语义不变。 - -## 开发态租号发布 - -- 发布租号前必须登录并完成实名认证。 -- 一期创建发布时同时创建 `game_accounts` 和 `rental_listings`。 -- 哈夫币数量是号主手动填报值,不代表实时值。 -- 号主可上传账号资产截图,地址保存在 `game_accounts.screenshot_urls`,最多保留 12 个。 -- 当前提交审核会进入 `review_status = pending`,由后台商品审核通过后才上架。 -- 后台审核通过后,发布状态变为 `published`,审核状态变为 `approved`,账号状态变为 `published`。 -- 后台审核拒绝后,发布保留为草稿,审核状态变为 `rejected`,拒绝原因写入 `review_reason`。 -- 公开列表只展示 `status = published` 且 `review_status = approved` 的发布。 - -## 开发态订单创建 - -- 创建订单需要登录。 -- 一期创建订单暂不接真实支付和押金冻结,创建成功后直接进入 `pending_handoff`。 -- 创建订单时会在数据库事务内锁定发布和账号,防止同一账号重复出租。 -- 创建订单时生成 `account_snapshot`,记录下单时账号资产状态。 -- 订单创建后发布状态变为 `rented`,不再出现在公开租号列表。 -- 待交接订单可以由租客取消,取消后发布状态恢复为 `published`。 - -## 开发态账号交接 - -- 创建订单后状态为 `pending_handoff`,交接状态为 `pending_owner`。 -- 只有号主可以提交交接说明。 -- 号主提交交接说明后,交接状态变为 `pending_renter_confirm`。 -- 只有租客可以确认收号。 -- 租客确认收号后,订单状态变为 `renting`,交接状态变为 `received`。 -- 确认收号时会重新计算租赁开始时间和结束时间。 -- 交接记录保存在 `handoff_records`,订单双方都可以查看。 - -## 开发态结账与完成 - -- 租赁中订单可以由租客发起结账,填写使用结束说明、消耗金额、哈夫币消耗量、其他扣款和证据链接。 -- 逾期中订单仍允许租客发起结账,但后台和号主可以根据逾期情况发起申诉或客服处理。 -- 租客发起结账后,订单状态变为 `pending_checkout_confirm`,交接状态变为 `pending_owner_checkout`。 -- 只有号主可以确认结账或修改结账。 -- 号主直接确认结账后,订单状态变为 `completed`,交接状态变为 `returned`,结算状态标记为 `settled`。 -- 号主修改结账后,订单状态变为 `pending_checkout_accept`,交接状态变为 `pending_renter_checkout`,必须等待租客确认修正。 -- 待号主确认结账或待租客确认修正时,任一方都可以发起结账争议。 -- 结账争议后订单状态变为 `checkout_disputing`,交接状态变为 `checkout_disputed`,由客服仲裁。 -- 订单完成后,账号和发布状态改为 `offline`,不会自动回到公开首页;如需再次出租,需号主手动重新上架。 -- 当前会生成开发态模拟钱包流水,不代表真实支付或提现。 - -## 开发态超时任务 - -- 后端启动后会运行订单超时扫描任务,默认每 1 分钟执行一次。 -- 任务从 `system_configs` 读取超时阈值,包括号主待交接、租客确认收号、租客结账宽限和号主确认结账。 -- 号主待交接超时:订单保持 `pending_handoff`,交接状态变为 `owner_timeout`,租客仍可取消订单或发起申诉。 -- 租客确认收号超时:订单状态变为 `abnormal`,交接状态变为 `renter_confirm_timeout`,进入客服介入。 -- 租客逾期未结账:订单状态变为 `overdue`,交接状态变为 `return_overdue`,租客仍可发起结账,号主可发起申诉。 -- 号主确认结账超时:订单状态变为 `abnormal`,交接状态变为 `owner_checkout_confirm_timeout`,进入客服复核。 -- 每个超时动作只推进一次状态,避免重复通知。 -- 超时动作会给相关用户写入站内信,并以 `system` 身份写入 `audit_logs`。 - -## 开发态文件上传 - -- 文件上传接口为 `/api/files/upload`,文件访问接口为 `/api/files/object`。 -- 开发环境使用 MinIO,配置项包括 `STORAGE_ENDPOINT`、`STORAGE_BUCKET`、`STORAGE_ACCESS_KEY_ID` 和 `STORAGE_SECRET_ACCESS_KEY`。 -- 当前支持上传 10MB 内的 JPG、PNG、WebP 和 PDF。 -- 上传场景包括账号截图、交接附件、申诉证据、实名回执引用和头像等。 -- 账号资产截图已接入发布页面,商品审核和商品详情后台可通过后台文件代理查看。 -- 申诉证据已在订单详情页接入上传,上传成功后会把文件访问地址追加到证据列表。 -- 文件访问通过后端代理读取私有对象,后续接 OSS/COS 时保持业务接口不变。 - -## 开发态钱包账务 - -- 钱包账务当前为模拟流水,不代表真实支付、充值或提现。 -- 创建订单时为租客生成一笔冻结流水,金额为租金加押金。 -- 取消待交接订单时释放租客冻结金额。 -- 订单完成时释放租客冻结金额,给号主生成租金入账流水,并给租客生成押金退回流水。 -- 每笔流水记录 `balance_after`,用于后续对账。 -- 后台资金流水接口为 `/api/admin/wallet/ledger`,前端页面为 `/admin/wallet-ledger`。 -- 后台可按用户、订单和业务类型查看最近流水,用于客服核对押金、租金、释放和结算记录。 -- 后续接入真实支付后,需要把模拟冻结替换为支付成功后的真实冻结。 - -## 开发态站内信 - -- 订单创建后通知号主和租客。 -- 租客取消订单后通知号主和租客。 -- 号主提交交接说明后通知租客。 -- 租客确认收号后通知号主。 -- 租客发起结账后通知号主。 -- 号主确认结账后通知号主和租客。 -- 号主修改结账后通知租客。 -- 租客拒绝修正结账后通知双方并进入争议。 -- 发起申诉后通知对方和发起人。 -- 仲裁完成后通知号主和租客。 -- 站内信支持列表查询和标记已读。 - -## 开发态申诉仲裁 - -- 订单双方都可以在非终态订单发起申诉。 -- 同一个订单同一时间只允许存在一个 `open` 或 `processing` 申诉。 -- 发起普通申诉后订单状态变为 `disputing`,发起结账争议后订单状态变为 `checkout_disputing`,账号和发布保持锁定。 -- 开发态后台仲裁接口为 `/api/admin/disputes`,当前只要求登录,后续接后台管理员和 RBAC。 -- 仲裁会释放开发态模拟冻结金额,并根据结果生成钱包流水。 -- 全额退款:释放冻结金额后,将租金加押金作为可用余额退给租客,订单置为 `closed`。 -- 部分退款:需要填写退给租客的金额,剩余冻结金额结算给号主,订单置为 `closed`。 -- 释放押金:租金结算给号主,押金退给租客,订单置为 `completed`。 -- 扣押金/赔付号主:可填写从押金中赔付给号主的金额;不填默认处理全额押金,订单置为 `completed`。 -- 关闭订单:只释放冻结金额,不产生可用余额结算,订单置为 `closed`,关联商品和账号下架。 -- 仲裁完成会写入 `audit_logs`,记录裁决结果、金额、订单状态和资金处理。 -- 当前仍是开发态模拟账务,不代表真实退款、扣款或提现;接入真实支付后需要替换为支付渠道退款、分账和对账逻辑。 - -## 开发态系统配置 - -- 系统配置接口为 `/api/admin/system-configs`。 -- 首次查询会自动补齐一组默认配置,包括交接超时、归还确认超时、短信限流、最低押金、实名下单开关、平台抽成和提现门槛。 -- 更新配置会写入 `audit_logs`,记录操作人、配置项、修改前值和修改后值。 -- 当前后台接口已使用独立管理员登录和后台 JWT;后续接入角色和权限后再限制可操作配置项。 - -## 开发态后台登录 - -- 后台登录接口为 `/api/admin/auth/login`,前端页面为 `/admin/login`。 -- 后台页面使用独立管理布局,不再混用用户端侧边栏。 -- 后台登录前必须先请求 `/api/admin/auth/captcha` 获取图形验证码。 -- 图形验证码为后端生成的 SVG,验证码答案保存在 Redis,默认 3 分钟过期,校验后立即删除。 -- 后台 JWT 与普通用户 JWT 区分 `admin` 和 `user`,普通用户 Token 不能访问 `/api/admin/*`。 -- 开发态首次后台登录会自动初始化默认管理员:用户名 `admin`,密码 `admin123456`。 -- 默认管理员只用于本地开发;正式部署前必须改为初始化脚本、强密码和管理员密码修改流程。 - -## 开发态后台仪表盘 - -- 后台仪表盘接口为 `/api/admin/dashboard`,前端页面为 `/admin/dashboard`。 -- 当前统计用户数、实名用户数、商品数、上架数、订单数、租赁中订单、今日订单、今日钱包流水。 -- 待处理事项包括待审核商品、待仲裁申诉、待交接订单和待结账确认订单。 -- 最近订单和最近申诉用于运营快速定位问题,后续接入后台订单管理和商品审核后再跳转到对应详情页。 - -## 开发态用户管理 - -- 用户管理接口为 `/api/admin/users`,前端页面为 `/admin/users`。 -- 后台可查看用户手机号、实名状态、风险状态、信用分、订单数、发布数和申诉数。 -- 冻结用户会将 `users.status` 改为 `frozen`,`risk_status` 改为 `frozen`,被冻结用户不能继续登录。 -- 解冻用户会将 `users.status` 改为 `active`,`risk_status` 改为 `normal`。 -- 冻结和解冻都会写入 `audit_logs`,记录管理员、用户、前后状态和原因。 - -## 开发态订单管理 - -- 订单管理接口为 `/api/admin/orders`,前端页面为 `/admin/orders`。 -- 后台可查看全量订单、租客、号主、订单状态、交接状态、结算状态、租金和押金。 -- 订单详情页 `/admin/orders/:id` 展示订单状态、双方用户、租期、交接记录和账号资产快照。 -- 高风险客服操作集中放在订单详情页处理,必须填写原因并写入审计日志。 - -## 开发态商品管理 - -- 商品管理接口为 `/api/admin/listings`,前端页面为 `/admin/listings`。 -- 后台可查看全量商品、号主、账号 ID、区服、平台、段位、哈夫币、时租、押金、商品状态和审核状态。 -- 当前支持按号主 ID、商品状态、审核状态和查询条数筛选。 -- 商品详情页为 `/admin/listings/:id`,支持查看完整账号、价格、租期、审核信息和账号资产截图。 -- 后台可对非租赁中的商品执行强制下架和标记异常。 -- 强制下架会将商品和账号状态改为 `offline`,标记异常会将商品和账号状态改为 `abnormal`。 -- 强制下架和标记异常必须填写原因,写入 `audit_logs`,并通知号主。 -- 租赁中的商品暂不允许直接下架或标记异常,需要先处理关联订单。 - -## 开发态订单客服操作 - -- 订单详情页 `/admin/orders/:id` 支持客服关闭订单和标记异常。 -- 已完成、已取消、已关闭订单为终态,不允许再次客服关闭或标记异常。 -- 客服关闭订单会将订单状态改为 `closed`,交接状态改为 `admin_closed`,结算状态改为 `closed`。 -- 客服关闭订单会释放开发态模拟冻结金额,并将关联商品和账号下架为 `offline`。 -- 标记异常会将订单状态改为 `abnormal`,交接状态改为 `admin_abnormal`,关联商品和账号改为 `abnormal`。 -- 客服关闭和标记异常必须填写原因,写入 `audit_logs`,并通知租客和号主。 -- 当前不处理真实退款、扣款或赔付,真实支付接入后需要补充资金裁决逻辑。 - -## 开发态审计日志 - -- 审计日志接口为 `/api/admin/audit-logs`,前端页面为 `/admin/audit-logs`。 -- 当前可查看管理员、操作动作、业务类型、业务 ID、IP、User-Agent、操作明细和创建时间。 -- 当前已写入审计日志的动作包括系统配置创建/更新、用户冻结和用户解冻。 -- 审计日志只做追加和只读查询,不提供后台删除或修改入口。 diff --git a/docs/database.md b/docs/database.md deleted file mode 100644 index ddf0463..0000000 --- a/docs/database.md +++ /dev/null @@ -1,25 +0,0 @@ -# 数据库设计 - -数据库设计以 [项目计划](project-plan.md) 第 9 章为准。 - -一期优先落表: - -- `users` -- `user_realname` -- `game_accounts` -- `rental_listings` -- `rental_orders` -- `handoff_records` -- `wallet_accounts` -- `wallet_ledger` -- `disputes` -- `notifications` -- `audit_logs` -- `admin_users` -- `roles` -- `permissions` -- `admin_user_roles` -- `role_permissions` -- `system_configs` - -后续实现迁移时,资金相关表必须保证流水只追加,订单相关表必须保留账号资产快照。 diff --git a/docs/order-payment-implementation-plan.md b/docs/order-payment-implementation-plan.md deleted file mode 100644 index 1e3b51d..0000000 --- a/docs/order-payment-implementation-plan.md +++ /dev/null @@ -1,107 +0,0 @@ -# 订单支付确认改造 —— 实施计划 - -> 状态:核心订单支付链路已按分步兼容策略实施;旧字段暂保留兼容 -> 日期:2026-05-24 - -说明:本文来自改造前计划,用于保留决策背景。当前分支没有直接删除旧价格/租期字段,也没有删除增量迁移文件;为了避免影响已有页面和开发库,采用 `price`、`rented_at` 等新字段优先、旧字段兜底的兼容迁移方式。 - -## 目标 - -将当前"下单即锁定"的流程改造为: - -``` -下单 → 待支付(pending_payment) → 支付确认 → 冻结锁定 → 待交接(pending_handoff) -``` - -同时清理 `price_hourly`、`price_daily`、`price_weekly`、`rent_start_at`、`rent_end_at`、`rent_hours` 等时租残留字段。 - ---- - -## 改造清单(按依赖顺序) - -``` -第1层(无依赖,可并行) -├── A. 合并 3 个 SQL 迁移文件 → 1 个 000001_init.sql -│ 修改 rental_listings:price + in_transaction -│ 修改 rental_orders:rented_at + estimated_duration_hours -│ 修改 notifications:category/link_type/link_id/extra_data -│ 新增 sms_logs 表 -│ 同步改 scripts/dev.sh -│ -├── B. Go 模型改造 -│ model/listing.go → Price + InTransaction -│ model/order.go → RentedAt + EstimatedDurationHours -│ model/notification.go → Category/LinkType/LinkID/ExtraData -│ -第2层(依赖第1层) -├── C. Listing 模块清理 -│ listing/dto.go → ListingDTO + CreateRequest 适配 -│ listing/repository.go → Create/Update/listQuery/toDTO 全部替换 -│ listing/service.go → 校验适配 -│ -├── D. Order DTO 改造 -│ order/dto.go → 删 RentStartAt/RentEndAt/RentHours,加 RentedAt/EstimatedDurationHours -│ -第3层(依赖第2层) -├── E. Order 核心改造 -│ order/service.go → 删 internalOrderHours,加错误,加 Pay() -│ order/repository.go → Create() → pending_payment + in_transaction -│ order/repository.go → 新增 Pay():余额→扣款→冻结→锁定→通知 -│ order/repository.go → Cancel() 适配 pending_payment -│ order/handler.go → 新增 Pay handler -│ 路由注册 → POST /orders/:id/pay -│ -├── F. 钱包充值 -│ wallet/repository.go → Recharge() -│ wallet/service.go → Recharge() -│ wallet/handler.go → Recharge handler -│ 路由注册 → POST /wallet/recharge -│ -第4层(依赖第3层 E) -└── G. 超时扫描 - job.go → 新增 handlePendingPaymentTimeout(15min 超时取消) - system_configs → order.pending_payment_timeout_minutes: 15 -``` - ---- - -## API 变更 - -| API | 类型 | 说明 | -|-----|------|------| -| `POST /api/orders` | 行为变更 | 返回 `pending_payment`,不锁商品,标记 `in_transaction` | -| `POST /api/orders/{id}/pay` | **新增** | 校验余额→扣款→冻结→锁定→通知 | -| `POST /api/orders/{id}/cancel` | 行为变更 | 允许取消 `pending_payment` | -| `POST /api/wallet/recharge` | **新增** | 开发环境充值 | - ---- - -## 涉及文件 - -### 修改(17 个) -``` -backend/migrations/000001_init.sql -scripts/dev.sh -backend/internal/model/listing.go -backend/internal/model/order.go -backend/internal/model/notification.go -backend/internal/modules/listing/dto.go -backend/internal/modules/listing/repository.go -backend/internal/modules/listing/service.go -backend/internal/modules/order/dto.go -backend/internal/modules/order/service.go -backend/internal/modules/order/repository.go -backend/internal/modules/order/handler.go -backend/internal/modules/wallet/repository.go -backend/internal/modules/wallet/service.go -backend/internal/modules/wallet/handler.go -backend/internal/router/router.go(或同等路由文件) -backend/internal/jobs/ordertimeout/job.go -backend/internal/modules/systemconfig/defaults.go(或同等文件) -``` - -### 删除(2 个) -``` -backend/migrations/000002_order_checkouts.sql -backend/migrations/000003_add_indexes.sql -``` diff --git a/docs/order-testing-messaging-analysis.md b/docs/order-testing-messaging-analysis.md deleted file mode 100644 index e442207..0000000 --- a/docs/order-testing-messaging-analysis.md +++ /dev/null @@ -1,511 +0,0 @@ -# HFB Sys 订单购买测试 & 消息系统增强 —— 综合分析报告 - -> 生成日期:2026-05-24 -> 状态:订单支付与开发充值主链路已实施;消息系统增强留待后续 - -说明:本文来自改造前分析,用于保留问题背景和测试思路。文中对“当前链路”的描述对应改造前状态;当前分支已接入 `pending_payment`、支付冻结、开发充值、结账确认等订单系统能力,消息系统增强仍未纳入本轮改造。 - ---- - -## 第一部分:如何进行实际的订单购买测试 - -### 1. 当前完整订单购买链路 - -从前端到后端,当前链路如下: - -``` -租客浏览商品列表 → 点击商品详情 → 点击"立即租赁" - ↓ -MobileListingDetailView.vue 调用 createOrder(listingId) - ↓ -POST /api/orders {listing_id} - ↓ -handler.CreateOrder() → 验证 listing 状态(published & approved) - ↓ -service.CreateOrder(ctx, userID, listingID) - ↓ -repository.Create(tx) → 一条大事务: - ├── SELECT listing + account FOR UPDATE (悲观锁防并发) - ├── 校验: listing.status=published, account.status=published - ├── INSERT rental_orders (status=pending_handoff, rent_hours=24 硬编码) - ├── UPDATE listing.status → rented, account.status → rented - ├── INSERT account_snapshot (JSON 字段, 记录下单时资产快照) - ├── INSERT wallet_ledger (order_lock, 模拟冻结 rent_amount + deposit_amount) - ├── UPDATE wallet_accounts (frozen_balance ↑) - ├── notification.Append() → 通知号主+租客 - └── COMMIT -``` - -**关键发现——无支付环节**:`POST /api/orders` 调用后直接进入 `pending_handoff`,完全没有支付确认步骤。这是因为项目计划明确说"一期先做账务模型,不直接接真实支付和提现"。 - -### 2. 当前存在的 9 个关键缺失 - -| # | 缺失项 | 影响 | 涉及文件 | -|---|--------|------|----------| -| 1 | **无支付确认步骤** | 订单创建即生效,无资金冻结验证 | `order/repository.go` Create() | -| 2 | **租期硬编码 24h** | `internalOrderHours = 24`,用户无法选择 | `order/repository.go:21` | -| 3 | **无余额校验** | 下单时未检查租客 `available_balance >= rent_amount + deposit_amount` | `order/repository.go` Create() | -| 4 | **前端余额硬编码** | `MobileProfileView.vue` 写死 `¥0.00`,未调 API | `MobileProfileView.vue` | -| 5 | **钱包首次查询才创建** | `GET /api/wallet/balance` 首次访问才初始化账户 | `wallet/repository.go` | -| 6 | **无充值入口** | 没有任何充值接口或页面 | 全项目 | -| 7 | **站内信前端空壳** | `MobileMessagesView.vue` 只显示 `van-empty` | `MobileMessagesView.vue` | -| 8 | **无租期即将结束提醒** | 项目计划中规划了但未实现 | 超时扫描任务 | -| 9 | **短信完全未接** | 只有登录验证码的 mock,业务通知短信完全缺失 | `integrations/sms/` | - -### 3. 要完成端到端测试必须补充的最小功能集 - -``` -必须在测试前补充的功能(按依赖顺序): - -第1步:余额充值(测试前置条件) - └── POST /api/wallet/recharge {amount} → 给测试用户加余额 - -第2步:租期选择(核心流程) - └── 前端:下单时增加租期选择组件 - └── 后端:CreateOrderDTO 增加 rent_hours 字段 - -第3步:支付确认步骤(状态机改造) - └── 新增订单状态:pending_payment - └── POST /api/orders → pending_payment(而非直接 pending_handoff) - └── POST /api/orders/{id}/pay → 校验余额 → 扣款 → pending_handoff - -第4步:前端站内信接入 - └── MobileMessagesView.vue 接入 fetchNotifications API - └── 底部导航栏增加未读消息角标 -``` - -### 4. 支付确认步骤的推荐设计 - -``` -建议的状态机改造(最小侵入): - -POST /api/orders - ↓ -[新增] pending_payment(待支付,默认 15 分钟超时自动取消) - ↓ -POST /api/orders/{id}/pay - ├── 校验:订单归属租客、status=pending_payment、未超时 - ├── 校验:wallet_accounts.available_balance >= rent_amount + deposit_amount - ├── UPDATE wallet_accounts: available_balance -= total, frozen_balance += total - ├── INSERT wallet_ledger: order_lock (冻结流水) - ├── UPDATE rental_orders: status → pending_handoff - ├── UPDATE listing + account: status → rented - └── notification.Append() → 通知双方 -``` - -对应的新 API: -- `POST /api/orders/{id}/pay` — 确认支付 -- `GET /api/orders/{id}/payment-status` — 查询支付状态 -- 超时扫描任务新增:`pending_payment` 超过 15 分钟 → 自动取消 - -### 5. 完整测试场景清单 - -#### 5.1 正常流程测试 - -| 场景 | 步骤 | 验证点 | -|------|------|--------| -| 完整租赁闭环 | 浏览→下单→支付→号主交接→收号确认→租赁→结账→号主确认→完成 | 所有状态流转正确,资金流水完整 | -| 租期选择 | 选择不同租期(1h/3h/12h/24h) | rent_end_at 正确计算,租金按比例 | -| 多商品下单 | 不同商品分别下单 | 互不影响,各自锁定 | -| 结账修改流程 | 号主修改结账金额→租客同意修正 | 状态流转:pending_checkout_confirm → pending_checkout_accept → completed | - -#### 5.2 边界与异常测试 - -| 场景 | 验证点 | -|------|--------| -| 余额不足下单 | 返回明确错误,不创建订单 | -| 已租出商品下单 | `SELECT FOR UPDATE` 后检测到 status≠published,拒绝 | -| 审核未通过商品下单 | 拒绝(review_status≠approved) | -| 自己租自己 | 拒绝(owner_id = renter_id) | -| 未实名租客下单 | 根据 system_config 的 `realname_required_for_order` 配置 | -| 非法状态转换 | 已取消订单不能再次取消,已完成订单不能结账等 | -| 结账争议流程 | 任一方发起争议→客服仲裁→完成/关闭 | - -#### 5.3 并发测试 - -| 场景 | 验证点 | -|------|--------| -| 2 人同时下单同一商品 | `SELECT FOR UPDATE` 保证只有一人成功 | -| 同时支付+超时取消 | 互斥,不会出现既支付又取消 | -| 并发结算 | wallet_ledger 不出现负数或重复入账 | -| 并发创建订单 | 库存锁定正确 | - -#### 5.4 超时测试(依赖超时扫描任务) - -| 超时类型 | 默认阈值 | 期望行为 | -|----------|----------|----------| -| 待支付超时 | 15 min | 订单自动取消 | -| 号主待交接超时 | 30 min | handoff_status → owner_timeout,通知双方 | -| 租客确认收号超时 | 30 min | status → abnormal,客服介入 | -| 租客逾期未结账 | 10 min 宽限 | status → overdue | -| 号主确认结账超时 | 120 min | status → abnormal | - -#### 5.5 安全测试 - -| 场景 | 验证点 | -|------|--------| -| 未登录访问 | 所有写接口返回 401 | -| 跨用户操作 | A 不能取消 B 的订单,不能确认 B 的收号 | -| 后台接口保护 | 普通用户 token 不能访问 /api/admin/* | -| 重复提交 | 防重机制(前端 loading + 后端幂等) | -| SQL 注入 | 所有查询通过 GORM 参数化 | -| 越权查看 | 用户不能查看他人订单、钱包、交接记录 | - -### 6. 具体测试实施方案 - -#### 6.1 测试环境搭建 - -```bash -# 1. 启动基础设施 -docker compose -f deploy/docker-compose.dev.yml up -d - -# 2. 初始化数据库 -docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < backend/migrations/000001_init.sql - -# 3. 启动后端 -cd backend && cp .env.example .env && go run ./cmd/api - -# 4. 启动前端 -cd frontend && npm install && npm run dev -``` - -#### 6.2 手动端到端测试步骤(核心路径) - -``` -前置条件:准备两个测试手机号(号主A + 租客B) - -Step 1: 号主A 注册/登录 - POST /api/auth/sms/send {phone: "138xxxx0001"} - POST /api/auth/sms/login {phone: "138xxxx0001", code: "从日志获取"} - -Step 2: 号主A 实名认证(mock) - POST /api/realname/start {name: "张三", id_no: "110101199001011234"} - -Step 3: 号主A 发布商品 - POST /api/listings { - game_name: "三角洲行动", - server_region: "微信区", - haf_coin_amount: 5000000, - price_hourly: 10, - deposit_amount: 100, - min_rent_hours: 1, - max_rent_hours: 24 - } - POST /api/listings/{id}/submit-review - -Step 4: 后台审核通过 - POST /api/admin/auth/login {username: "admin", password: "admin123456", captcha: "..."} - POST /api/admin/listings/{id}/approve - -Step 5: 租客B 注册/登录 - (同 Step 1,使用 138xxxx0002) - -Step 6: 租客B 充值(当前需手动) - 直接改数据库或通过调试接口给租客B加余额 - -Step 7: 租客B 浏览并下单 - GET /api/listings → 查看商品 - POST /api/orders {listing_id, rent_hours: 3} - -Step 8: 租客B 支付(当前直接跳到 pending_handoff,后续需补充) - 验证订单状态 - -Step 9: 号主A 提交交接说明 - POST /api/orders/{id}/handoff {content: "登录方式:..."} - -Step 10: 租客B 确认收号 - POST /api/orders/{id}/confirm-receive - -Step 11: 租客B 发起结账 - POST /api/orders/{id}/checkout { - content: "使用结束", - consumable_amount: 30, - coin_consumed_m: 0.5 - } - -Step 12: 号主A 确认结账 - POST /api/orders/{id}/checkout/confirm - -Step 13: 验证结果 - GET /api/orders/{id} → status=completed - GET /api/wallet/ledger → 流水完整 -``` - -#### 6.3 自动化测试建议 - -| 层级 | 工具 | 覆盖内容 | -|------|------|----------| -| 单元测试 | Go testing + testify | Repository 的事务方法,Service 参数校验 | -| 集成测试 | Go testing + testcontainers | 真实 MySQL/Redis 下的完整流程 | -| API 测试 | Postman/Newman 或 Go httptest | 所有 API 端点的正常+异常路径 | -| E2E 测试 | Playwright 或 Cypress | 前端页面操作完整流程 | -| 并发测试 | Go benchmark + goroutines | 并发下单、并发结算 | - ---- - -## 第二部分:应增加什么消息系统 - -### 1. 现有消息系统现状评估 - -#### 1.1 站内信体系 - -**好消息**:后端站内信的写入非常完整——所有 18 个关键业务节点都在事务内通过 `notification.Append(tx, ...)` 写入,覆盖了订单全生命周期的每个状态变更。 - -| 文件 | notification.Append 调用次数 | 场景 | -|------|------------------------------|------| -| `order/repository.go` | 9 次 | 创建/取消/交接/收号/结账/修改结账/客服关闭/标记异常/完成结算 | -| `dispute/repository.go` | 4 次 | 发起申诉(2)/仲裁完成(2) | -| `ordertimeout/job.go` | 4 次 | 号主超时/收号超时/逾期/确认结账超时 | - -**坏消息**:前端完全没接——`MobileMessagesView.vue` 只有一个 `van-empty` 组件,`Desktop NotificationsView.vue` 虽然接入了 API 但缺乏未读数角标和分类。 - -#### 1.2 表结构分析 - -```sql -notifications ( - id, user_id, type, title, content, - biz_type, biz_id, read_at, created_at -) -``` - -**当前优点**: -- 简洁高效 -- `(user_id, read_at, created_at)` 联合索引支持快速分页查询 - -**当前不足**: -- 缺少 `category` 字段(订单消息/系统通知/公告无法区分) -- 缺少软删除标记 -- 缺少 `extra_data` (JSON) 用于存储跳转链接等扩展信息 - -#### 1.3 对照项目计划的缺口 - -项目计划第 8 章规划的但**尚未实现**的场景: - -| 规划场景 | 当前状态 | 优先级 | -|----------|----------|--------| -| 商品审核通过/拒绝通知号主 | ✅ 已实现 | — | -| 租期即将结束提醒 | ❌ 未实现 | 🔴 高 | -| 账户冻结/解冻通知用户 | ❌ 未实现 | 🟡 中 | -| 短信登录验证码 | ✅ mock | — | -| 租期即将到期短信 | ❌ 未实现 | 🔴 高 | -| 申诉被受理短信 | ❌ 未实现 | 🟡 中 | -| 仲裁结果短信 | ❌ 未实现 | 🟡 中 | -| WebSocket/SSE 实时推送 | ❌ 未实现 | 🟢 低 | - -### 2. 推荐的消息系统增强架构 - -#### 2.1 站内信增强(Phase 1 — 立即做) - -``` -最小可行方案: -┌─────────────────────────────────────────────────┐ -│ notifications 表扩展 │ -├─────────────────────────────────────────────────┤ -│ + category VARCHAR(32) -- order|system|announce │ -│ + link_type VARCHAR(32) -- order_detail|... │ -│ + link_id BIGINT │ -│ + extra_data JSON -- 扩展数据 │ -├─────────────────────────────────────────────────┤ -│ 新增 API: │ -│ GET /api/notifications/unread-count │ -│ POST /api/notifications/batch-read │ -└─────────────────────────────────────────────────┘ - -前端改动: -├── MobileMessagesView.vue:接入 fetchNotifications,消息列表 -├── 底部导航栏:未读消息红点角标 -├── Desktop NotificationsView.vue:增强消息分类和已读标记 -└── Router:增加消息未读数 store -``` - -#### 2.2 短信系统增强(Phase 2 — 短期) - -``` -设计短信 Provider 抽象层: - -internal/integrations/sms/ -├── provider.go ← Provider 接口 -│ type Provider interface { -│ Send(ctx, phone, templateCode string, params map[string]string) error -│ SendBatch(ctx, phones []string, ...) error -│ } -├── mock.go ← MockProvider(开发环境) -├── aliyun.go ← AliyunProvider(生产环境) -├── limiter.go ← 限流器(基于 Redis) -│ - 手机号维度:60s/次,10次/天 -│ - IP 维度:100次/小时 -│ - 场景维度:可配置 -└── logger.go ← 发送日志(sms_logs 表) - -短信触发场景: -├── 登录验证码(已有 mock) -├── 租期即将到期提醒(新增 🔴) -├── 订单申诉被受理(新增 🟡) -├── 仲裁结果通知(新增 🟡) -└── 高风险安全提醒(预留) -``` - -#### 2.3 SSE 实时推送架构(Phase 3 — 中期) - -``` -推荐 SSE(Server-Sent Events)而非 WebSocket: -理由:本场景是单向推送(服务端→客户端),SSE 更轻量, - 基于 HTTP,不需要额外协议升级,断线自动重连。 - -Go 侧架构: -┌──────────────────────────────────────┐ -│ SSEBroker (单例) │ -├──────────────────────────────────────┤ -│ clients map[userID]*SSEClient │ -│ Notify(userID, event) │ -│ Broadcast(event) │ -└──────────────────────────────────────┘ - ↓ 事件分发 -┌──────────────────────────────────────┐ -│ SSE Events: │ -│ - order.status_changed │ -│ - order.handoff_updated │ -│ - order.checkout_updated │ -│ - notification.new │ -│ - dispute.updated │ -└──────────────────────────────────────┘ - -Vue 侧: -// composables/useSSE.ts -const eventSource = new EventSource('/api/sse/stream?token=xxx') -eventSource.addEventListener('notification.new', (e) => { - const data = JSON.parse(e.data) - notificationStore.incrementUnread() -}) - -重连策略: -- EventSource 原生支持自动重连 -- 可设置 retry interval: 3000ms -- 重连时重新验证 token -``` - -#### 2.4 订单全链路状态变更推送矩阵 - -``` -订单状态变更 → 推送内容设计: - -pending_payment → 租客: {type:"order.created", title:"订单已创建", orderId, amount, expireAt} - 号主: {type:"order.new_rental", title:"有新的租用请求"} - -pending_handoff → 租客: {type:"order.paid", title:"支付成功,等待号主交接"} - 号主: {type:"order.pending_handoff", title:"请尽快完成账号交接"} - -pending_renter_confirm → 租客: {type:"handoff.submitted", title:"号主已完成交接,请确认收号"} - -renting → 号主: {type:"handoff.confirmed", title:"租客已确认收号,租赁开始"} - -[租期结束前5分钟] → 租客: {type:"rental.expiring", title:"租期即将结束"} - -pending_checkout_confirm → 号主: {type:"checkout.submitted", title:"租客已发起结账"} - -completed → 双方: {type:"order.completed", title:"订单已完成"} -``` - -### 3. 数据库设计建议 - -#### 3.1 新增表 - -```sql --- 短信发送日志 -CREATE TABLE sms_logs ( - id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, - phone VARCHAR(20) NOT NULL, - template_code VARCHAR(64) NOT NULL, - template_params JSON, - status VARCHAR(16) NOT NULL DEFAULT 'pending', -- pending|sent|failed - provider VARCHAR(32) NOT NULL, - provider_msg_id VARCHAR(128), - error_msg VARCHAR(512), - biz_type VARCHAR(32), - biz_id BIGINT UNSIGNED, - user_id BIGINT UNSIGNED, - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - INDEX idx_sms_logs_phone_created (phone, created_at), - INDEX idx_sms_logs_status (status) -); - --- SSE 推送记录(可选,用于对账) -CREATE TABLE push_records ( - id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, - user_id BIGINT UNSIGNED NOT NULL, - event_type VARCHAR(64) NOT NULL, - payload JSON, - delivered TINYINT DEFAULT 0, - delivered_at DATETIME, - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - INDEX idx_push_records_user (user_id, created_at) -); -``` - -#### 3.2 notifications 表扩展 - -```sql -ALTER TABLE notifications - ADD COLUMN category VARCHAR(32) NOT NULL DEFAULT 'order' - COMMENT 'order|system|announce|security', - ADD COLUMN link_type VARCHAR(32) DEFAULT NULL - COMMENT 'order_detail|listing_detail|dispute_detail|wallet|url', - ADD COLUMN link_id BIGINT UNSIGNED DEFAULT NULL, - ADD COLUMN extra_data JSON DEFAULT NULL; -``` - -### 4. 实施优先级总览 - -``` -Phase 1(立即 — 让消息系统可用) -├── ✅ 让 MobileMessagesView.vue 接入 fetchNotifications -├── ✅ 底部导航栏增加未读消息角标 -├── ✅ 增加 GET /api/notifications/unread-count API -├── ✅ 增加 POST /api/notifications/batch-read API -└── ✅ 消息列表支持点击跳转到对应订单详情 - -Phase 2(短期 — 完善通知体系) -├── notifications 表扩展 category/link_type/extra_data -├── 实现租期即将结束通知(站内信 + 前端定时检查) -├── 实现用户冻结/解冻通知 -├── 短信 Provider 抽象层 + 限流器 -├── sms_logs 表 + 短信日志后台查看 -└── 接入一个真实短信服务商 - -Phase 3(中期 — 实时体验) -├── SSE Broker 实现 -├── 订单状态实时推送接入前端 -├── 租期倒计时实时更新 -├── 客服消息实时通知 -└── push_records 表(可选) -``` - ---- - -## 附录:关键文件索引 - -### 后端核心文件 - -| 文件 | 说明 | -|------|------| -| `backend/internal/modules/order/repository.go` | 订单 Repository,核心业务逻辑(1089行) | -| `backend/internal/modules/order/handler.go` | 订单 HTTP Handler(376行) | -| `backend/internal/modules/order/service.go` | 订单 Service 层(160行) | -| `backend/internal/modules/order/dto.go` | 订单 DTO 定义(126行) | -| `backend/internal/model/order.go` | RentalOrder 模型定义 | -| `backend/internal/modules/wallet/repository.go` | 钱包 Repository + AppendEntries | -| `backend/internal/modules/notification/repository.go` | 通知 Repository + Append | -| `backend/internal/modules/dispute/repository.go` | 争议仲裁 Repository | -| `backend/internal/jobs/ordertimeout/job.go` | 超时扫描定时任务 | - -### 前端核心文件 - -| 文件 | 说明 | -|------|------| -| `frontend/src/views/mobile/MobileListingDetailView.vue` | 商品详情/下单页 | -| `frontend/src/views/mobile/MobileOrdersView.vue` | 订单列表页 | -| `frontend/src/views/mobile/MobileMessagesView.vue` | 消息页(空壳) | -| `frontend/src/views/mobile/MobileProfileView.vue` | 个人中心(余额硬编码) | -| `frontend/src/api/orders.ts` | 订单 API 定义 | -| `frontend/src/api/notifications.ts` | 通知 API 定义 | -| `frontend/src/api/wallet.ts` | 钱包 API 定义 | diff --git a/docs/project-plan.md b/docs/project-plan.md deleted file mode 100644 index e1fa927..0000000 --- a/docs/project-plan.md +++ /dev/null @@ -1,945 +0,0 @@ -# 哈夫币租号平台项目计划 - -## 1. 项目定位与业务边界 - -本项目是面向《三角洲行动》账号租赁场景的前后端分离平台,核心能力包括手机号登录、实名认证、号主发布租号、租客下单、账号交接、租期归还、押金结算、纠纷仲裁和后台审核管理。 - -哈夫币在本系统中只被定义为游戏账号内资产,不是平台自发行虚拟币,不提供平台内铸币、转赠、交易、提现或链上能力。平台只记录账号资产描述、租赁订单、押金、租金、结算流水和纠纷处理结果。 - -一期不做自动上号器、不自动改密、不强制踢下线、不绕过游戏安全机制,也不开发外挂、盗号、破解、规避封禁等能力。账号租赁可能涉及游戏官方协议、账号安全、未成年人保护、支付合规和纠纷处理风险,上线前需要补充用户协议、隐私政策、交易规则和合规评估。 - -## 2. 技术栈与开发部署方式 - -前端技术栈: - -- Vue 3 -- TypeScript -- Vite -- Element Plus -- Pinia -- Vue Router -- Axios - -后端技术栈: - -- Go -- Gin -- GORM -- MySQL 8 -- Redis -- JWT -- Casbin -- Zap 或 Zerolog -- Viper - -开源借鉴策略: - -- 项目路线为借鉴成熟开源后台的通用工程能力,租号业务核心从头自研。 -- 可重点参考 `gin-vue-admin`、`go-admin` 这类 Go/Vue 后台项目的 JWT、Casbin、RBAC、菜单权限、Swagger、GORM 分层、配置管理、日志、文件上传和基础 CRUD 组织方式。 -- 不直接二开租号源码,不把未知项目的交易、资金和风控逻辑作为基础。 -- 不直接接入未知质量的租号系统源码,不复用不可信的订单、资金、押金、交接或仲裁逻辑。 -- 必须自研的核心模块包括租号发布、订单状态机、账号交接、押金冻结、资金流水、纠纷仲裁、风控规则和哈夫币资产快照。 -- 后台 UI 布局、菜单管理、权限管理可以参考开源项目;用户端体验、号主端流程和租号业务页面从头设计。 - -文件存储: - -- 开发环境使用 MinIO。 -- 生产环境使用阿里云 OSS 或腾讯云 COS。 -- 文件主要用于账号资产截图、租赁前后凭证、纠纷证据、后台公告图片、实名认证服务回执或材料引用。 -- 一期不要求平台长期保存身份证原图,实名认证资料优先交由第三方实名服务处理。 - -开发方式: - -- 本机直接运行 Go 后端,便于调试和热重载。 -- 本机直接运行 Vue 前端,便于页面开发。 -- Docker Compose 启动 MySQL、Redis、MinIO。 -- 后端可使用 `air` 做本地热重载。 -- 前端使用 `pnpm dev` 本地开发。 - -生产部署: - -- 后端构建 Docker 镜像部署。 -- 前端构建静态资源后由 Nginx 托管。 -- MySQL 生产优先使用云数据库。 -- Redis 生产优先使用云 Redis。 -- 文件存储生产使用 OSS/COS。 -- Nginx 负责 HTTPS、静态资源、反向代理和基础限流。 - -## 3. 三角洲行动特有规则 - -哈夫币填报: - -- 一期不接游戏 API 同步,哈夫币数量由号主手动填报。 -- 号主发布时必须上传租前资产截图,作为哈夫币数量、段位、资产描述和纠纷仲裁依据。 -- `game_accounts.haf_coin_amount` 表示号主最近一次填报值,不代表实时值。 -- 下单时必须生成订单账号快照,记录哈夫币数量、区服、登录平台、段位、赛季限定资产、账号截图和资产描述。 -- 租赁前后哈夫币差异以订单快照、交接记录、租前租后截图和客服仲裁为准。 - -安全验证: - -- 如果账号登录需要安全锁、二次验证、手机验证码或设备确认,由号主在交接阶段手动配合。 -- 号主超时未配合安全验证时,租客可取消订单或发起申诉。 -- 平台不保存游戏账号密码,不代收验证码,不绕过游戏登录、二次验证、安全锁或风控机制。 - -区服与资产: - -- 区服资产默认隔离,商品必须明确区服。 -- 不同区服的哈夫币、段位和资产不合并展示。 -- 跨区服租赁不作为一期核心能力。 -- 赛季限定资产以标签和资产说明形式展示,可作为号主定价和押金建议参考,但一期不参与自动估值。 - -## 4. 核心业务模块 - -用户与认证: - -- 手机号短信验证码登录。 -- JWT 登录态。 -- 用户角色包括租客、号主、管理员相关角色。 -- 支持实名状态、风控状态、冻结状态。 - -实名认证: - -- 接入阿里云实人认证或腾讯云身份认证。 -- 用户发起认证后,平台记录认证渠道、认证流水号、认证状态和脱敏结果。 -- 未实名用户不能发布租号,后台可配置是否限制未实名租客下单。 - -租号发布: - -- 号主实名后可发布账号。 -- 发布内容包括游戏、区服、平台、段位、哈夫币数量、账号资产描述、截图、租金、押金、租期范围。 -- 商品发布后进入待审核状态,后台审核通过后才能上架。 - -订单租赁: - -- 租客选择商品和租期后创建订单。 -- 系统锁定商品库存,避免同一账号被重复出租。 -- 订单流转覆盖待确认、待交接、租赁中、待号主确认结账、待租客确认修正、结账争议中、已完成、已取消、申诉中。 - -钱包账务: - -- 一期先做账务模型,不直接接真实支付和提现。 -- 系统记录租金、押金、冻结、解冻、扣款、退款、结算等流水。 -- 后续可接微信支付、支付宝支付、人工打款或第三方提现通道。 - -后台管理: - -- 用户管理。 -- 实名状态查看。 -- 商品审核。 -- 订单管理。 -- 纠纷仲裁。 -- 资金流水。 -- 风控名单。 -- 审计日志。 - -## 5. 账号交接与回收流程 - -一期采用号主手动交接模式,平台不保存游戏账号密码,不托管明文账号凭据。 - -交接流程: - -1. 租客创建订单,系统校验商品状态、租期、押金和余额账务状态。 -2. 订单确认后,商品进入锁定状态,订单进入待交接。 -3. 号主在订单内提交交接说明,例如登录方式、注意事项、联系说明或外部交接备注。 -4. 租客确认收到账号后,订单进入租赁中,并记录租赁开始时间和预计结束时间。 -5. 租期即将结束时,系统通过站内信和短信提醒租客完成使用并发起结账。 -6. 租客发起结账,填写使用结束说明、消耗金额、哈夫币消耗量和必要证据。 -7. 号主确认账号状态无误后直接完成结算,或修改结账金额后交由租客确认。 -8. 租客同意修正后订单完成;拒绝修正或任一方对交接、使用、结账、资产变化有异议时,订单进入申诉仲裁。 - -回收边界: - -- 平台不自动修改账号密码。 -- 平台不强制踢下线。 -- 平台不绕过游戏登录、二次验证、安全锁或风控机制。 -- 平台不承诺技术性收回账号,只通过订单规则、押金、证据和仲裁处理争议。 - -超时机制: - -- 号主待交接超时:订单进入待交接后,默认 30 分钟未提交交接说明,租客可取消订单或发起申诉。 -- 租客确认收号超时:号主提交交接说明后,默认 30 分钟未确认收号,订单进入客服介入,不自动开始租期。 -- 租客结账超时:超过租期结束时间仍未发起结账,系统提醒后进入逾期中,号主可发起申诉。 -- 号主确认结账超时:租客发起结账后,默认 2 小时未确认,订单进入客服复核。 -- 所有超时阈值必须进入 `system_configs` 管理,后台可调整。 - -订单状态机: - -| From | To | 触发者 | 条件 | -| ---------- | ---------- | --------- | ----------------------------------- | -| 待确认 | 待交接 | 系统 | 订单确认,商品锁定,账务校验通过 | -| 待确认 | 已取消 | 租客/系统 | 租客主动取消或确认超时 | -| 待交接 | 待收号确认 | 号主 | 号主提交交接说明 | -| 待交接 | 已取消 | 租客 | 号主交接超时且未进入申诉 | -| 待交接 | 申诉中 | 租客/号主 | 交接争议或安全验证无法完成 | -| 待收号确认 | 租赁中 | 租客 | 租客确认收到账号并可正常登录 | -| 待收号确认 | 申诉中 | 租客/系统 | 租客确认超时、无法登录或描述不符 | -| 租赁中 | 逾期中 | 系统 | 超过租期结束时间仍未发起结账 | -| 租赁中 | 待号主确认结账 | 租客 | 租客发起结账和租后凭证 | -| 逾期中 | 待号主确认结账 | 租客 | 租客补交结账申请 | -| 逾期中 | 申诉中 | 号主/系统 | 逾期未归还或疑似资产损失 | -| 待号主确认结账 | 已完成 | 号主 | 号主确认结账 | -| 待号主确认结账 | 待租客确认修正 | 号主 | 号主修改结账金额 | -| 待租客确认修正 | 已完成 | 租客 | 租客同意修正结账 | -| 待号主确认结账 | 结账争议中 | 任一方 | 发起结账争议 | -| 待租客确认修正 | 结账争议中 | 任一方 | 发起结账争议 | -| 结账争议中 | 已完成/已关闭/异常 | 客服 | 后台仲裁 | -| 申诉中 | 已完成 | 客服 | 仲裁为正常完成或部分扣款后完成 | -| 申诉中 | 已取消 | 客服 | 仲裁为订单取消和退款 | -| 申诉中 | 已关闭 | 客服 | 仲裁为异常关闭、冻结用户或冻结商品 | - -终态规则: - -- `已完成`、`已取消`、`已关闭` 为终态,普通业务流程不能逆转。 -- 终态订单如需调整,只能通过后台复核流程生成新的资金流水和审计日志,不能直接改旧流水。 -- `申诉中` 会冻结相关押金和结算金额,直到客服仲裁。 - -## 6. 押金、价格与结算模型 - -定价模型: - -- 租金由号主自主设置。 -- 支持按小时、按天、按周配置价格。 -- 平台可在后续提供建议价,但一期不强制。 -- 商品需配置最短租期和最长租期。 - -押金模型: - -- 押金由号主设置,平台校验最低押金。 -- 最低押金可根据账号估值、哈夫币数量、稀有资产、租期长度、号主历史纠纷率、租客风险等级给出动态建议。 -- 一期先实现规则化最低押金,动态建议可后续迭代。 -- 押金不足以覆盖损失时,订单进入人工仲裁,不自动产生超额扣款。 - -账务模型: - -- 一期先做平台内账务,不接真实支付和提现。 -- 钱包流水采用不可变账本设计。 -- 余额可通过流水汇总或账户余额表事务更新获得。 -- 每笔余额变化必须有业务单据来源,例如订单、押金、仲裁、退款、结算。 -- 平台抽成比例、号主结算周期、提现门槛作为系统配置项预留。 - -结算规则: - -- 正常完成订单后,租金按平台抽成规则分账给号主。 -- 押金在双方结账确认或客服仲裁后释放给租客。 -- 如发生资产损失、无法登录、封号或超时归还,可由客服仲裁后扣除部分或全部押金。 -- 如号主虚假描述、超时未交接或账号无法使用,可裁定全额或部分退款。 -- 仲裁导致的扣款、退款、赔付必须生成资金流水和审计日志。 - -## 7. 纠纷仲裁规则 - -纠纷类型: - -- 无法登录。 -- 账号描述不符。 -- 哈夫币数量争议。 -- 账号资产损失。 -- 账号封禁或异常。 -- 号主超时未交接。 -- 租客超时未归还。 -- 交接凭证争议。 -- 退款、押金、赔付争议。 - -证据要求: - -- 租前账号资产截图。 -- 租后账号资产截图。 -- 哈夫币数量截图。 -- 系统订单时间线。 -- 交接记录。 -- 站内沟通记录。 -- 第三方沟通截图。 -- 游戏内异常或封禁截图。 - -仲裁流程: - -1. 任一方在订单详情发起申诉。 -2. 订单进入申诉中,相关押金和结算金额保持冻结。 -3. 双方在限定时间内补充证据。 -4. 客服查看订单、交接、截图、聊天和资金流水。 -5. 客服选择裁决结果并填写裁决说明。 -6. 系统根据裁决结果调整订单状态和资金流水。 -7. 双方收到站内信,关键结果可短信通知。 - -裁决结果: - -- 全额退款。 -- 部分退款。 -- 释放押金。 -- 扣除部分押金。 -- 扣除全部押金。 -- 赔付号主。 -- 订单关闭。 -- 商品冻结。 -- 用户冻结。 -- 进入二次复核。 - -## 8. 消息通知机制 - -一期采用站内信加关键节点短信。 - -站内信场景: - -- 商品审核通过或拒绝。 -- 租客下单。 -- 订单进入待交接。 -- 号主提交交接说明。 -- 租客确认收号。 -- 租期即将结束。 -- 租客发起结账。 -- 号主确认或修改结账。 -- 租客确认或拒绝修正结账。 -- 订单完成结算。 -- 发起申诉。 -- 仲裁结果。 -- 账户冻结或解冻。 - -短信场景: - -- 登录验证码。 -- 租期即将到期。 -- 订单申诉被受理。 -- 仲裁结果。 -- 高风险账号安全提醒。 - -扩展方向: - -- 后续可增加 WebSocket 或 SSE,实现订单状态和客服消息实时推送。 -- 短信必须做手机号、IP、设备、场景维度限流,防止短信轰炸。 - -## 9. 数据库设计概要 - -核心关系: - -- 一个用户可以同时是租客和号主。 -- 一个用户最多对应一条当前实名信息。 -- 一个号主可以发布多个游戏账号。 -- 一个游戏账号同一时间只能有一个上架商品或一个有效租赁订单。 -- 一个租赁商品关联一个游戏账号。 -- 一个订单关联一个租客、一个号主、一个商品和一个游戏账号快照。 -- 一个订单可以有多条交接记录、通知、审计日志和纠纷证据。 -- 资金流水只追加,不覆盖。 -- 后台管理员和角色为多对多关系,角色和权限为多对多关系。 -- 可调业务阈值统一放入 `system_configs`,例如最低押金、交接超时、归还超时、短信限流和实名下单开关。 - -核心表: - -`users` - -- `id` -- `phone` -- `nickname` -- `avatar_url` -- `realname_status` -- `risk_status` -- `credit_score` -- `status` -- `last_login_at` -- `created_at` -- `updated_at` - -`user_realname` - -- `id` -- `user_id` -- `provider` -- `provider_order_no` -- `status` -- `masked_name` -- `masked_id_no` -- `verified_at` -- `fail_reason` -- `created_at` -- `updated_at` - -`game_accounts` - -- `id` -- `owner_id` -- `game_name` -- `server_region` -- `login_platform` -- `title` -- `description` -- `rank_level` -- `haf_coin_amount` -- `asset_summary` -- `season_tags` -- `screenshot_urls` -- `status` -- `created_at` -- `updated_at` - -说明:`haf_coin_amount` 是号主最近一次填报值,不代表实时值;订单创建时必须写入 `rental_orders.account_snapshot`。 - -`rental_listings` - -- `id` -- `account_id` -- `owner_id` -- `price_hourly` -- `price_daily` -- `price_weekly` -- `deposit_amount` -- `min_rent_hours` -- `max_rent_hours` -- `status` -- `review_status` -- `review_reason` -- `published_at` -- `created_at` -- `updated_at` - -`rental_orders` - -- `id` -- `order_no` -- `listing_id` -- `account_id` -- `owner_id` -- `renter_id` -- `rent_start_at` -- `rent_end_at` -- `rent_hours` -- `rent_amount` -- `deposit_amount` -- `platform_fee` -- `account_snapshot` -- `status` -- `handoff_status` -- `settlement_status` -- `owner_settled_at` -- `settled_at` -- `created_at` -- `updated_at` - -`handoff_records` - -- `id` -- `order_id` -- `from_user_id` -- `to_user_id` -- `type` -- `content` -- `attachment_urls` -- `confirmed_by_renter_at` -- `confirmed_by_owner_at` -- `created_at` - -`wallet_accounts` - -- `id` -- `user_id` -- `available_balance` -- `frozen_balance` -- `status` -- `created_at` -- `updated_at` - -`wallet_ledger` - -- `id` -- `ledger_no` -- `user_id` -- `order_id` -- `direction` -- `amount` -- `balance_after` -- `balance_type` -- `biz_type` -- `biz_no` -- `remark` -- `created_at` - -说明:`balance_after` 记录本次流水发生后对应余额类型的余额,用于审计和对账。 - -`disputes` - -- `id` -- `order_id` -- `initiator_id` -- `target_user_id` -- `type` -- `status` -- `description` -- `evidence_urls` -- `arbitration_result` -- `arbitration_remark` -- `handled_by` -- `handled_at` -- `created_at` -- `updated_at` - -`notifications` - -- `id` -- `user_id` -- `type` -- `title` -- `content` -- `biz_type` -- `biz_id` -- `read_at` -- `created_at` - -`audit_logs` - -- `id` -- `actor_type` -- `actor_id` -- `action` -- `biz_type` -- `biz_id` -- `ip` -- `user_agent` -- `detail` -- `created_at` - -`admin_users` - -- `id` -- `username` -- `password_hash` -- `nickname` -- `status` -- `last_login_at` -- `created_at` -- `updated_at` - -`roles` - -- `id` -- `code` -- `name` -- `description` -- `created_at` -- `updated_at` - -`permissions` - -- `id` -- `code` -- `name` -- `resource` -- `action` -- `created_at` -- `updated_at` - -`admin_user_roles` - -- `id` -- `admin_user_id` -- `role_id` -- `created_at` - -`role_permissions` - -- `id` -- `role_id` -- `permission_id` -- `created_at` - -`system_configs` - -- `id` -- `key` -- `value` -- `description` -- `updated_by` -- `created_at` -- `updated_at` - -索引策略: - -- `users.phone` 唯一索引。 -- `game_accounts.owner_id` 普通索引。 -- `game_accounts.game_name, server_region, login_platform` 组合索引。 -- `rental_listings.status, review_status, price_hourly` 组合索引。 -- `rental_orders.order_no` 唯一索引。 -- `rental_orders.renter_id, status` 组合索引。 -- `rental_orders.owner_id, status` 组合索引。 -- `wallet_ledger.user_id, created_at` 组合索引。 -- `wallet_ledger.ledger_no` 唯一索引。 -- `disputes.order_id` 普通索引。 -- `notifications.user_id, read_at, created_at` 组合索引。 -- `audit_logs.actor_id, created_at` 组合索引。 -- `admin_user_roles.admin_user_id, role_id` 唯一索引。 -- `role_permissions.role_id, permission_id` 唯一索引。 -- `system_configs.key` 唯一索引。 - -## 10. API 接口规划 - -用户认证: - -- `POST /api/auth/sms/send`:发送短信验证码。 -- `POST /api/auth/sms/login`:手机号验证码登录。 -- `POST /api/auth/refresh`:刷新 Token。 -- `POST /api/auth/logout`:退出登录。 - -实名认证: - -- `POST /api/realname/start`:发起实名认证。 -- `GET /api/realname/status`:查询实名状态。 -- `POST /api/realname/callback`:实名认证服务回调。 - -租号发布: - -- `GET /api/listings`:租号列表。 -- `GET /api/listings/{id}`:租号详情。 -- `POST /api/listings`:创建发布。 -- `PUT /api/listings/{id}`:修改发布。 -- `POST /api/listings/{id}/submit-review`:提交审核。 -- `DELETE /api/listings/{id}`:下架发布。 - -订单: - -- `POST /api/orders`:创建订单。 -- `GET /api/orders`:订单列表。 -- `GET /api/orders/{id}`:订单详情。 -- `POST /api/orders/{id}/cancel`:取消订单。 -- `POST /api/orders/{id}/confirm-receive`:租客确认收号。 -- `POST /api/orders/{id}/checkout`:租客发起结账。 -- `POST /api/orders/{id}/checkout/confirm`:号主确认结账。 -- `POST /api/orders/{id}/checkout/counter`:号主修改结账。 -- `POST /api/orders/{id}/checkout/accept`:租客同意修正结账。 -- `POST /api/orders/{id}/dispute`:发起申诉。 - -交接: - -- `POST /api/orders/{id}/handoff`:号主提交交接说明。 -- `GET /api/orders/{id}/handoff-records`:查看交接记录。 - -钱包: - -- `GET /api/wallet/balance`:查询余额。 -- `GET /api/wallet/ledger`:查询流水。 -- `POST /api/wallet/withdraw`:提现申请预留接口。 - -通知: - -- `GET /api/notifications`:站内信列表。 -- `POST /api/notifications/{id}/read`:标记已读。 - -后台: - -- `POST /api/admin/auth/login`:后台登录。 -- `POST /api/admin/auth/logout`:后台退出。 -- `GET /api/admin/me`:当前管理员信息。 -- `GET /api/admin/dashboard`:后台仪表盘。 -- `GET /api/admin/users`:用户列表。 -- `POST /api/admin/users/{id}/freeze`:冻结用户。 -- `POST /api/admin/users/{id}/unfreeze`:解冻用户。 -- `GET /api/admin/listings/pending`:待审核商品。 -- `POST /api/admin/listings/{id}/approve`:审核通过。 -- `POST /api/admin/listings/{id}/reject`:审核拒绝。 -- `GET /api/admin/orders`:订单列表。 -- `GET /api/admin/disputes`:纠纷列表。 -- `POST /api/admin/disputes/{id}/arbitrate`:纠纷仲裁。 -- `GET /api/admin/wallet/ledger`:资金流水。 -- `GET /api/admin/system-configs`:系统配置列表。 -- `PUT /api/admin/system-configs/{key}`:更新系统配置。 -- `GET /api/admin/audit-logs`:审计日志。 - -## 11. 安全与风控 - -认证安全: - -- 短信验证码存 Redis,设置过期时间。 -- 验证码一次性使用。 -- 限制手机号、IP、设备、场景维度发送频率。 -- 登录失败、验证码错误、异常设备需要计入风控。 - -接口安全: - -- 所有写接口校验 JWT。 -- 后台接口使用 Casbin 做 RBAC 权限控制。 -- 关键写操作防重复提交。 -- 金额、状态流转、订单归属必须由后端校验。 -- 所有 SQL 通过 ORM 参数化,禁止拼接用户输入。 - -业务风控: - -- 检测同一用户、同一设备、同一 IP 的异常注册和下单。 -- 检测号主自己租自己或关联账号刷单。 -- 检测重复发布同一账号。 -- 检测频繁取消、频繁申诉、频繁仲裁失败用户。 -- 检测高价值账号低押金异常发布。 -- 检测短时间大量短信请求。 - -账号安全: - -- 平台不保存游戏账号明文密码。 -- 交接说明和证据只对订单相关用户和管理员可见。 -- 敏感字段脱敏展示。 -- 实名信息加密存储。 -- 账号截图和纠纷证据使用私有文件访问,避免公开 URL 长期暴露。 - -审计要求: - -- 登录、实名、发布、审核、下单、交接、归还、申诉、仲裁、冻结、退款、结算都写审计日志。 -- 后台管理员的每次裁决必须记录操作者、时间、IP、说明和变更前后关键状态。 - -## 12. 后台管理 - -后台角色: - -- 超级管理员:拥有全部权限。 -- 审核员:处理商品审核和资料审核。 -- 客服:处理订单、交接问题和纠纷。 -- 财务:查看流水、处理结算和提现预留。 -- 风控:处理冻结、黑名单和异常用户。 - -后台功能: - -- 仪表盘:用户数、商品数、订单数、待审核、待仲裁、流水概览。 -- 用户管理:查看用户、实名状态、风险状态、冻结/解冻。 -- 商品审核:查看账号资产、截图、价格、押金、审核通过/拒绝。 -- 订单管理:查看订单时间线、交接记录、资金状态。 -- 仲裁中心:查看纠纷、证据、双方说明,执行裁决。 -- 资金流水:查看租金、押金、冻结、解冻、扣款、退款、结算。 -- 通知管理:查看站内信发送记录和短信发送记录。 -- 系统配置:管理交接超时、归还超时、短信限流、最低押金、平台抽成和实名下单开关。 -- 审计日志:查看管理员操作和高风险业务操作。 - -## 13. 前端页面与路由规划 - -用户端页面: - -- `/`:首页,展示推荐租号、热门区服和平台公告。 -- `/listings`:租号列表,支持区服、平台、价格、押金、段位、哈夫币数量筛选。 -- `/listings/:id`:租号详情,展示账号资产、租金、押金、租期、号主信用和风险提示。 -- `/orders/create`:下单页,选择租期并确认租金、押金和规则。 -- `/orders`:我的订单。 -- `/orders/:id`:订单详情,展示状态机时间线、交接记录、归还入口和申诉入口。 -- `/wallet`:钱包余额和流水。 -- `/notifications`:站内信。 -- `/realname`:实名认证。 - -号主端页面: - -- `/seller/listings`:我的发布。 -- `/seller/listings/create`:发布租号。 -- `/seller/listings/:id/edit`:编辑发布。 -- `/seller/handoffs`:交接管理。 -- `/seller/disputes`:纠纷处理。 -- `/seller/earnings`:收益流水。 - -后台端页面: - -- `/admin/dashboard`:仪表盘。 -- `/admin/users`:用户管理。 -- `/admin/listings/review`:商品审核。 -- `/admin/orders`:订单管理。 -- `/admin/disputes`:仲裁中心。 -- `/admin/wallet-ledger`:资金流水。 -- `/admin/system-configs`:系统配置。 -- `/admin/audit-logs`:审计日志。 - -移动端前端分阶段规划: - -- Phase 1:租号交易首页 MVP。参考 `https://m.guaishouw.com/` 的移动端信息组织方式,先做简化交易入口,不复制其业务规则和视觉资产。首页覆盖搜索入口、频道入口、交易数据概览、基础排序、租号商品卡片和底部导航,优先保证用户能快速浏览可租账号并进入后续交易链路。 -- Phase 2:筛选排序增强。在 Phase 1 基础上补充区服、平台、价格、押金、段位、哈夫币数量、租期等筛选项,完善综合排序、价格排序、最新上架、热度或成交数据排序,列表筛选结果需与后端查询条件保持一致。 -- Phase 3:详情下单。完善租号详情页、资产截图、租金押金说明、号主信用、风险提示、租期选择和下单确认页,形成从首页卡片到详情再到创建订单的闭环。 -- Phase 4:号主上架。补充移动端号主发布入口,支持账号信息填写、哈夫币手动填报、区服平台选择、资产截图上传、价格押金配置、提交审核和我的发布管理。 -- Phase 5:消息、公告和我的。完善站内信、订单提醒、平台公告、个人中心、实名认证入口、我的订单、钱包流水和号主收益入口,形成租客与号主的日常运营闭环。 - -前端实现原则: - -- 后台布局、菜单和权限控制可参考开源后台项目。 -- 租客端、号主端的交易体验和业务页面从头实现。 -- 移动端先按简化 MVP 迭代,不提前实现复杂筛选、复杂下单和号主完整工作台,避免和 UI 实现节奏冲突。 -- 路由权限需要区分游客、已登录用户、已实名用户、号主和管理员。 - -## 14. 项目目录规划 - -```text -hfb_sys/ -├── backend/ -│ ├── cmd/ -│ │ └── api/ -│ ├── config/ -│ ├── internal/ -│ │ ├── handler/ -│ │ ├── service/ -│ │ ├── repo/ -│ │ ├── model/ -│ │ ├── middleware/ -│ │ ├── modules/ -│ │ │ ├── auth/ -│ │ │ ├── user/ -│ │ │ ├── realname/ -│ │ │ ├── listing/ -│ │ │ ├── order/ -│ │ │ ├── wallet/ -│ │ │ ├── dispute/ -│ │ │ ├── notification/ -│ │ │ └── admin/ -│ │ └── integrations/ -│ │ ├── sms/ -│ │ ├── realname/ -│ │ └── storage/ -│ ├── pkg/ -│ └── migrations/ -├── frontend/ -│ ├── src/ -│ │ ├── api/ -│ │ ├── router/ -│ │ ├── stores/ -│ │ ├── views/ -│ │ ├── components/ -│ │ └── layouts/ -│ └── public/ -├── deploy/ -│ ├── docker-compose.dev.yml -│ ├── docker-compose.prod.yml -│ └── nginx/ -├── docs/ -│ ├── project-plan.md -│ ├── database.md -│ ├── api.md -│ └── business-rules.md -└── README.md -``` - -## 15. 阶段开发计划 - -第 0 阶段:项目初始化 - -- 创建前后端目录。 -- 初始化 Go 项目。 -- 初始化 Vue 项目。 -- 参考 `gin-vue-admin`、`go-admin` 的目录分层、RBAC、日志、配置、Swagger 和文件上传实现方式。 -- 配置 Docker Compose 开发环境。 -- 接入 MySQL、Redis、MinIO。 -- 建立基础配置、日志、错误码和响应结构。 - -第 1 阶段:用户与认证 - -- 实现短信验证码发送接口。 -- 实现短信验证码登录。 -- 实现 JWT 鉴权中间件。 -- 实现用户资料查询。 -- 加入短信限流和验证码一次性校验。 - -第 2 阶段:实名认证 - -- 建立实名表和状态流转。 -- 接入实名服务适配器。 -- 实现实名发起、查询、回调。 -- 限制未实名用户发布租号。 - -第 3 阶段:租号发布与审核 - -- 实现游戏账号和发布商品模型。 -- 实现哈夫币手动填报、区服隔离、赛季标签和账号资产截图。 -- 实现发布、修改、下架、提交审核。 -- 实现后台审核通过和拒绝。 -- 实现租号列表、详情和筛选。 - -第 4 阶段:订单、交接与账务 - -- 实现创建订单和账号锁定。 -- 实现订单状态机和合法状态转换校验。 -- 实现订单账号资产快照。 -- 实现号主提交交接说明。 -- 实现租客确认收号。 -- 实现租客发起结账、号主确认或修改结账、租客确认或拒绝修正结账。 -- 实现交接、确认收号、结账逾期、确认结账超时处理。 -- 实现钱包账户、押金冻结、租金流水、结算流水。 -- 预留支付和提现接口。 - -第 5 阶段:纠纷、通知与后台 - -- 实现纠纷发起、举证、客服仲裁。 -- 实现站内信通知。 -- 接入关键节点短信通知。 -- 完善后台仪表盘、用户管理、订单管理、资金流水、系统配置、审计日志。 - -第 6 阶段:测试、风控与部署 - -- 补齐单元测试和集成测试。 -- 做并发下单测试。 -- 做越权、重复提交、短信轰炸基础安全测试。 -- 完成 Docker 生产部署配置。 -- 准备上线前用户协议、隐私政策、交易规则和风险提示。 - -## 16. 测试计划 - -文档检查: - -- `docs/project-plan.md` 是完整项目方案,不再是生成说明。 -- 文档明确写入借鉴开源、自研业务核心的路线。 -- 文档不把直接二开租号源码作为推荐方案。 -- 技术栈统一为 Go 方案,无 Java 或 Spring Boot 推荐残留。 -- MySQL 明确为主数据库。 -- Redis 明确用于验证码、缓存、锁和限流。 -- Docker 方案区分本地开发和生产部署。 -- 哈夫币边界明确,不描述为平台虚拟币。 -- 三角洲行动特有规则有独立章节。 -- 哈夫币数量明确为号主填报和订单快照,不承诺实时同步。 -- 一期账号交接明确为号主手动交接。 -- 交接超时阈值和处理策略明确。 -- 订单状态机有状态转换表。 -- 一期资金模型明确为先做账务,不直接接真实支付提现。 -- 一期通知明确为站内信加关键短信。 -- 数据库概要包含 `wallet_ledger.balance_after`、`system_configs`、`owner_settled_at`、`account_snapshot`、`admin_user_roles`、`role_permissions`。 -- 前端路由规划覆盖用户端、号主端和后台端。 - -功能测试: - -- 短信验证码正确、错误、过期、重复使用。 -- 手机号、IP、设备限流生效。 -- JWT 过期、伪造、缺失时被拒绝。 -- 未实名用户不能发布租号。 -- 实名认证成功、失败、认证中状态流转正确。 -- 商品草稿、待审核、已上架、已下架、审核拒绝状态流转正确。 -- 审核未通过商品不能下单。 -- 同一账号并发下单只能成功一单。 -- 订单待交接、租赁中、待号主确认结账、待租客确认修正、结账争议中、已完成、申诉中状态流转正确。 -- 非法订单状态转换会被拒绝。 -- 交接、收号、结账逾期、确认结账超时会按配置触发取消、申诉、逾期或客服复核。 -- 押金冻结、释放、扣款、退款流水一致。 -- 每笔 `wallet_ledger` 正确记录 `balance_after`。 -- 租金、平台抽成、号主结算流水一致。 -- 订单结算后正确写入 `owner_settled_at` 或 `settled_at`。 -- 纠纷仲裁不同裁决结果正确落账。 -- 站内信和短信在关键节点触发。 - -安全测试: - -- 普通用户不能访问后台接口。 -- 后台不同角色只能访问授权功能。 -- 用户不能查看他人订单、钱包、交接记录或纠纷证据。 -- SQL 注入、越权访问、重复提交有基础防护。 -- 短信轰炸被限流。 -- 高风险操作全部写入审计日志。 - -性能与稳定性测试: - -- 租号列表分页和筛选在基础数据量下响应稳定。 -- 并发创建订单时库存锁定正确。 -- 钱包流水在并发结算时不出现负数或重复入账。 -- Redis、MySQL 短暂异常时接口返回可识别错误,不产生脏状态。 - -## 17. 风险与合规说明 - -账号租赁存在天然风险,包括账号找回、账号封禁、虚假描述、资产损失、租客恶意破坏、号主恶意交接、未成年人交易、资金纠纷和平台责任边界不清。 - -上线前必须补充: - -- 用户协议。 -- 隐私政策。 -- 租号交易规则。 -- 押金与赔付规则。 -- 纠纷仲裁规则。 -- 未成年人保护说明。 -- 实名认证授权说明。 -- 支付和提现合规方案。 -- 游戏官方规则风险评估。 - -平台规则必须明确: - -- 哈夫币不是平台发行资产。 -- 平台不保证游戏账号不会被官方限制、封禁或找回。 -- 平台不提供绕过游戏安全机制的技术服务。 -- 平台基于订单记录、交接记录、证据和仲裁规则处理争议。 -- 真实支付和提现上线前必须完成资质、风控、对账、发票或税务相关评估。