删除无用文档
This commit is contained in:
@@ -27,10 +27,12 @@
|
||||
```bash
|
||||
docker compose -f deploy/docker-compose.dev.yml up -d
|
||||
|
||||
docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < backend/migrations/000001_init.sql
|
||||
|
||||
cd backend
|
||||
cp .env.example .env
|
||||
go run github.com/pressly/goose/v3/cmd/goose@v3.27.1 \
|
||||
-dir migrations \
|
||||
mysql 'hfb:secret@tcp(127.0.0.1:3306)/hfb_sys?charset=utf8mb4&parseTime=True&loc=Local&multiStatements=true' \
|
||||
up
|
||||
go run ./cmd/api
|
||||
|
||||
cd ../frontend
|
||||
|
||||
+11
-4
@@ -67,13 +67,20 @@ backend/logs/app-YYYY-MM-DD.log
|
||||
docker compose -f deploy/docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
## 4. 手动初始化数据库
|
||||
## 4. 手动执行数据库迁移
|
||||
|
||||
将命令中的 `change-hfb-password` 替换为 `backend/.env` 里的 `MYSQL_PASSWORD`。
|
||||
通常直接使用一键部署脚本即可。确实需要手动迁移时,使用后端镜像内置的 goose:
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/docker-compose.prod.yml exec -T mysql \
|
||||
mysql -uhfb -pchange-hfb-password hfb_sys < backend/migrations/000001_init.sql
|
||||
MYSQL_DSN="$(awk -F= '$1=="MYSQL_DSN"{sub(/^[^=]*=/,""); print; exit}' backend/.env)"
|
||||
case "$MYSQL_DSN" in
|
||||
*multiStatements=*) GOOSE_DSN="$MYSQL_DSN" ;;
|
||||
*\?*) GOOSE_DSN="${MYSQL_DSN}&multiStatements=true" ;;
|
||||
*) GOOSE_DSN="${MYSQL_DSN}?multiStatements=true" ;;
|
||||
esac
|
||||
|
||||
docker compose -f deploy/docker-compose.prod.yml run --rm --no-deps backend \
|
||||
/app/goose -dir /app/migrations mysql "$GOOSE_DSN" up
|
||||
```
|
||||
|
||||
## 5. 验证
|
||||
|
||||
@@ -1,922 +0,0 @@
|
||||
# HFB Sys 项目优化计划
|
||||
|
||||
> 生成时间: 2026-06-05
|
||||
> 最后更新: 2026-06-05
|
||||
> 项目版本: refactor/features-architecture 分支
|
||||
|
||||
## 优化进度总览
|
||||
|
||||
- 🟢 已完成: 4 项
|
||||
- 🟡 进行中: 0 项
|
||||
- ⚪ 待处理: 9 项
|
||||
|
||||
**已完成**:
|
||||
- ✅ 前端统一请求封装优化 (2026-06-05)
|
||||
- ✅ 路由守卫性能优化 (2026-06-05)
|
||||
- ✅ 数据库索引优化 (2026-06-05)
|
||||
- ✅ Swagger API 文档集成 (2026-06-05)
|
||||
|
||||
## 项目概况
|
||||
|
||||
**项目名称**: 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. ✅ 数据库索引优化(已完成 2026-06-05)
|
||||
|
||||
**原问题描述**:
|
||||
- 迁移文件 `backend/migrations/000001_init.sql` 中缺少针对高频复合查询的覆盖索引
|
||||
- 时间范围查询缺少优化
|
||||
- 订单列表查询、钱包流水查询性能不佳
|
||||
|
||||
**已完成的优化**:
|
||||
|
||||
#### 新增 5 个复合索引
|
||||
|
||||
1. **订单状态+创建时间索引** (`idx_rental_orders_status_created_at`)
|
||||
- 优化订单列表查询性能
|
||||
- 预计性能提升 90%
|
||||
|
||||
2. **钱包流水按用户+业务类型+时间索引** (`idx_wallet_ledger_user_biz_created`)
|
||||
- 优化按业务类型筛选流水
|
||||
- 预计性能提升 90%
|
||||
|
||||
3. **订单结算状态索引** (`idx_rental_orders_settlement`)
|
||||
- 优化结算任务查询
|
||||
- 支持财务报表生成
|
||||
|
||||
4. **商品发布时间索引** (`idx_rental_listings_published`)
|
||||
- 优化首页商品列表
|
||||
- 预计性能提升 90%
|
||||
|
||||
5. **用户实名认证状态索引** (`idx_users_realname_status`)
|
||||
- 优化用户统计查询
|
||||
- 支持后台用户管理
|
||||
|
||||
**相关文件**:
|
||||
- `backend/migrations/000003_add_indexes.sql` - 索引迁移文件
|
||||
- `backend/migrations/test_index_performance.sql` - 性能测试脚本
|
||||
- `docs/DATABASE_INDEX_OPTIMIZATION.md` - 详细分析文档
|
||||
|
||||
**性能提升预估**:
|
||||
- 订单列表查询: 500ms → 50ms (减少 90%)
|
||||
- 钱包流水查询: 300ms → 30ms (减少 90%)
|
||||
- 商品列表查询: 200ms → 20ms (减少 90%)
|
||||
- 磁盘空间增加: ~3.1MB (可忽略)
|
||||
|
||||
**执行建议**:
|
||||
- ✅ 在开发环境测试通过
|
||||
- ⚠️ 生产环境需在低峰期执行
|
||||
- ⚠️ 逐个表创建索引,监控系统负载
|
||||
- ⚠️ 执行前备份数据库
|
||||
|
||||
---
|
||||
|
||||
### 原计划内容(已废弃)
|
||||
- [ ] 创建新的迁移文件 `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 请求封装优化(已完成 2026-06-05)
|
||||
|
||||
**原问题描述**:
|
||||
- apiClient 缺少日志记录和性能监控
|
||||
- 缺少类型安全的辅助函数
|
||||
- 错误处理可以进一步增强
|
||||
|
||||
**已完成的优化**:
|
||||
|
||||
#### 1. 增强的日志记录和监控
|
||||
- ✅ 开发环境自动记录请求/响应日志
|
||||
- ✅ 记录请求耗时
|
||||
- ✅ 慢请求自动警告(>1s)
|
||||
- ✅ 错误日志详细记录
|
||||
|
||||
#### 2. 性能监控系统
|
||||
- ✅ 创建 `apiMonitor` 工具
|
||||
- ✅ 记录所有请求的性能指标
|
||||
- ✅ 支持查看平均响应时间、成功率
|
||||
- ✅ 支持查看最慢的请求
|
||||
- ✅ 支持按 URL 分组统计
|
||||
- ✅ 开发环境下通过 `__apiMonitor.printReport()` 查看报告
|
||||
|
||||
#### 3. 类型安全的辅助函数
|
||||
- ✅ 创建 `api` 对象,提供简洁的 API 调用方式
|
||||
- ✅ `api.get<T>(url)` - GET 请求
|
||||
- ✅ `api.post<T>(url, data)` - POST 请求
|
||||
- ✅ `api.put<T>(url, data)` - PUT 请求
|
||||
- ✅ `api.delete<T>(url)` - DELETE 请求
|
||||
- ✅ `api.patch<T>(url, data)` - PATCH 请求
|
||||
- ✅ `api.silent()` - 静默请求
|
||||
- ✅ `api.retry()` - 带重试的请求
|
||||
- ✅ `api.concurrent()` - 并发请求
|
||||
- ✅ `api.sequential()` - 串行请求
|
||||
|
||||
#### 4. 增强的错误处理
|
||||
- ✅ 新增 `skipErrorHandler` 配置项
|
||||
- ✅ 支持跳过自动错误提示
|
||||
- ✅ 保持原有 `silent` 参数功能
|
||||
|
||||
#### 5. 改进的超时配置
|
||||
- ✅ 默认超时从 10s 增加到 30s,避免大文件上传超时
|
||||
- ✅ 支持单个请求自定义超时时间
|
||||
|
||||
#### 6. 完整的使用文档
|
||||
- ✅ 创建 `docs/API_OPTIMIZATION_GUIDE.md`
|
||||
- ✅ 包含使用示例、最佳实践、故障排查
|
||||
|
||||
**相关文件**:
|
||||
- `frontend/src/shared/api/client.ts` - 增强的 apiClient
|
||||
- `frontend/src/shared/api/helpers.ts` - 类型安全辅助函数
|
||||
- `frontend/src/shared/api/monitor.ts` - 性能监控工具
|
||||
- `frontend/src/shared/api/index.ts` - 统一导出
|
||||
- `docs/API_OPTIMIZATION_GUIDE.md` - 使用指南
|
||||
|
||||
**向后兼容**:
|
||||
- ✅ 完全兼容现有代码,无需修改
|
||||
- ✅ 新功能为可选增强,不影响现有功能
|
||||
|
||||
---
|
||||
|
||||
### 原计划内容(已废弃)
|
||||
|
||||
**问题描述**:
|
||||
- 未找到 `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. ✅ 路由守卫性能优化(已完成 2026-06-05)
|
||||
|
||||
**原问题**: `frontend/src/router/index.ts` 的 `beforeEach` 在每次导航时都可能重复调用 `session.loadMe()`
|
||||
|
||||
**已完成的优化**:
|
||||
|
||||
#### 1. 添加加载状态标志
|
||||
- ✅ 在 `sessionStore` 中添加 `_loadingMe` 标志
|
||||
- ✅ 防止并发调用 `loadMe()`
|
||||
- ✅ 如果正在加载,等待完成而不是重复请求
|
||||
|
||||
#### 2. 优化加载逻辑
|
||||
- ✅ 只有当 `phone` 为空时才调用 `loadMe()`
|
||||
- ✅ 避免每次路由跳转都发起请求
|
||||
- ✅ 减少不必要的 API 调用
|
||||
|
||||
#### 3. 改进实名认证检查
|
||||
- ✅ 优化实名状态检查逻辑
|
||||
- ✅ 只在必要时重新加载用户信息
|
||||
- ✅ 减少重复检查
|
||||
|
||||
**性能提升**:
|
||||
- 🚀 路由跳转时的 API 请求减少约 70%
|
||||
- 🚀 页面切换更快速
|
||||
- 🚀 减轻后端服务器压力
|
||||
|
||||
**相关文件**:
|
||||
- `frontend/src/stores/session.ts` - 添加加载标志和防重复逻辑
|
||||
- `frontend/src/router/index.ts` - 优化路由守卫逻辑
|
||||
|
||||
**向后兼容**:
|
||||
- ✅ 完全兼容现有功能
|
||||
- ✅ 用户体验无影响,只是性能提升
|
||||
|
||||
---
|
||||
|
||||
### 原计划内容(已废弃)
|
||||
|
||||
### 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. ✅ Swagger API 文档集成(已完成 2026-06-05)
|
||||
|
||||
**原问题**: 缺少 API 文档自动化,团队协作和前后端对接效率低
|
||||
|
||||
**已完成的工作**:
|
||||
|
||||
#### 1. 安装 Swagger 依赖
|
||||
- ✅ `github.com/swaggo/swag` - Swagger 文档生成工具
|
||||
- ✅ `github.com/swaggo/gin-swagger` - Gin 框架集成
|
||||
- ✅ `github.com/swaggo/files` - 静态文件服务
|
||||
|
||||
#### 2. 添加 API 通用信息
|
||||
在 `cmd/api/main.go` 中添加:
|
||||
- API 标题、版本、描述
|
||||
- 联系方式和许可证
|
||||
- 认证方式(Bearer Token)
|
||||
|
||||
#### 3. 为 Handler 添加 Swagger 注释
|
||||
示例:`internal/modules/auth/handler.go`
|
||||
- ✅ SendSMS - 发送短信验证码
|
||||
- ✅ Login - 短信验证码登录
|
||||
- ✅ Refresh - 刷新访问令牌
|
||||
- ✅ Logout - 登出
|
||||
|
||||
#### 4. 集成 Swagger UI 路由
|
||||
在 `internal/router/router.go` 中添加:
|
||||
- 路由: `GET /swagger/*any`
|
||||
- 仅在非生产环境启用
|
||||
- 支持交互式 API 测试
|
||||
|
||||
#### 5. 生成文档文件
|
||||
- ✅ `docs/docs.go` - Go 代码
|
||||
- ✅ `docs/swagger.json` - JSON 格式
|
||||
- ✅ `docs/swagger.yaml` - YAML 格式
|
||||
|
||||
**使用方式**:
|
||||
|
||||
1. **查看文档**:
|
||||
启动服务后访问 `http://localhost:8080/swagger/index.html`
|
||||
|
||||
2. **添加新接口文档**:
|
||||
在 handler 函数上方添加注释:
|
||||
```go
|
||||
// @Summary 接口摘要
|
||||
// @Description 详细描述
|
||||
// @Tags 标签
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param name type dataType required "说明"
|
||||
// @Success 200 {object} response.Body
|
||||
// @Router /path [method]
|
||||
```
|
||||
|
||||
3. **重新生成文档**:
|
||||
```bash
|
||||
swag init -g cmd/api/main.go -o docs --parseDependency --parseInternal
|
||||
```
|
||||
|
||||
**效果**:
|
||||
- 📚 自动生成交互式 API 文档
|
||||
- 🧪 支持在线测试 API
|
||||
- 👥 提升团队协作效率
|
||||
- 📝 文档与代码同步
|
||||
|
||||
**后续工作**:
|
||||
- [ ] 为其他模块(订单、钱包、商品等)添加 Swagger 注释
|
||||
- [ ] 添加请求/响应示例
|
||||
- [ ] 完善错误码说明
|
||||
|
||||
---
|
||||
|
||||
### 原计划内容(已废弃)
|
||||
|
||||
## 🟢 低优先级优化 (持续改进)
|
||||
|
||||
### 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
|
||||
**负责人**: 待分配
|
||||
**审核人**: 待分配
|
||||
@@ -1,101 +0,0 @@
|
||||
# 公告系统功能说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
在钱包旁边新增了公告中心功能,用户可以查看平台通知、使用教程、规则说明和常见问题解答。
|
||||
|
||||
## 主要特性
|
||||
|
||||
### 前台功能(用户端)
|
||||
- **公告列表页** (`/announcements`)
|
||||
- 支持按分类筛选(全部、通知公告、使用教程、规则说明、常见问题)
|
||||
- 显示置顶和重要标记
|
||||
- 分页浏览
|
||||
- 点击查看详情
|
||||
|
||||
- **公告详情页** (`/announcements/:id`)
|
||||
- 查看完整公告内容
|
||||
- 支持富文本显示
|
||||
- 自动统计浏览次数
|
||||
|
||||
### 后台功能(管理端)
|
||||
- 公告管理 CRUD(创建、编辑、删除)
|
||||
- 发布/归档公告
|
||||
- 设置优先级、置顶、重要标记
|
||||
- 按状态和分类筛选
|
||||
|
||||
## 数据库表结构
|
||||
|
||||
```sql
|
||||
CREATE TABLE announcements (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
category VARCHAR(32) NOT NULL DEFAULT 'notice',
|
||||
priority INT NOT NULL DEFAULT 0,
|
||||
is_pinned TINYINT(1) NOT NULL DEFAULT 0,
|
||||
is_important TINYINT(1) NOT NULL DEFAULT 0,
|
||||
view_count INT NOT NULL DEFAULT 0,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'draft',
|
||||
published_at DATETIME NULL,
|
||||
created_by BIGINT UNSIGNED NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
## API 端点
|
||||
|
||||
### 用户端
|
||||
- `GET /api/announcements` - 获取公告列表
|
||||
- `GET /api/announcements/:id` - 获取公告详情
|
||||
|
||||
### 管理端
|
||||
- `GET /api/admin/announcements` - 管理员获取公告列表
|
||||
- `GET /api/admin/announcements/:id` - 管理员获取公告详情
|
||||
- `POST /api/admin/announcements` - 创建公告
|
||||
- `PUT /api/admin/announcements/:id` - 更新公告
|
||||
- `POST /api/admin/announcements/:id/publish` - 发布公告
|
||||
- `POST /api/admin/announcements/:id/archive` - 归档公告
|
||||
- `DELETE /api/admin/announcements/:id` - 删除公告
|
||||
|
||||
## 权限要求
|
||||
|
||||
管理端需要以下权限:
|
||||
- `announcement:view` - 查看公告
|
||||
- `announcement:manage` - 管理公告(创建、编辑、发布、归档、删除)
|
||||
|
||||
## 前端路由
|
||||
|
||||
- `/announcements` - 公告列表
|
||||
- `/announcements/:id` - 公告详情
|
||||
|
||||
## 导航入口
|
||||
|
||||
在顶部导航栏"钱包"旁边添加了"公告"入口,用户可以方便地访问公告中心。
|
||||
|
||||
## 数据迁移
|
||||
|
||||
1. 运行 `000005_add_announcements.sql` 创建表结构
|
||||
2. 运行 `000006_insert_sample_announcements.sql` 插入示例数据
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 后端
|
||||
- 使用 Go + Gin 框架
|
||||
- GORM 作为 ORM
|
||||
- 遵循模块化设计(handler -> service -> repository)
|
||||
|
||||
### 前端
|
||||
- Vue 3 + TypeScript
|
||||
- Element Plus UI 组件库
|
||||
- 响应式设计,支持移动端
|
||||
|
||||
## 未来扩展
|
||||
|
||||
可以考虑添加:
|
||||
- 公告搜索功能
|
||||
- 用户收藏公告
|
||||
- 评论功能
|
||||
- 富文本编辑器(管理端)
|
||||
- 公告推送通知
|
||||
@@ -1,142 +0,0 @@
|
||||
## 🔒 彻底杜绝字符编码问题的方案
|
||||
|
||||
本文档说明如何在整个技术栈中确保使用 UTF-8 编码,避免出现乱码问题。
|
||||
|
||||
### 1. MySQL 服务器配置(已完成 ✅)
|
||||
|
||||
**配置文件:** `deploy/mysql/my.cnf`
|
||||
|
||||
```ini
|
||||
[client]
|
||||
default-character-set = utf8mb4
|
||||
|
||||
[mysql]
|
||||
default-character-set = utf8mb4
|
||||
|
||||
[mysqld]
|
||||
character-set-server = utf8mb4
|
||||
collation-server = utf8mb4_unicode_ci
|
||||
init-connect = 'SET NAMES utf8mb4'
|
||||
skip-character-set-client-handshake
|
||||
```
|
||||
|
||||
**Docker Compose 配置:** `deploy/docker-compose.prod.yml`
|
||||
|
||||
```yaml
|
||||
mysql:
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
volumes:
|
||||
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf:ro
|
||||
```
|
||||
|
||||
### 2. 数据库连接字符集(已完成 ✅)
|
||||
|
||||
**配置:** `backend/internal/config/config.go`
|
||||
|
||||
```go
|
||||
MySQLDSN: "hfb:secret@tcp(127.0.0.1:3306)/hfb_sys?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
```
|
||||
|
||||
**关键参数:**
|
||||
- `charset=utf8mb4` - 强制使用 UTF-8 编码
|
||||
- `parseTime=True` - 正确解析时间类型
|
||||
- `loc=Local` - 使用本地时区
|
||||
|
||||
### 3. 数据库表结构(已完成 ✅)
|
||||
|
||||
**迁移文件:** `backend/migrations/*.sql`
|
||||
|
||||
```sql
|
||||
CREATE TABLE table_name (
|
||||
...
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
**转换现有表:**
|
||||
```sql
|
||||
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### 4. 后端 API 响应头(建议添加)
|
||||
|
||||
**在 HTTP 响应中设置:**
|
||||
```go
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
```
|
||||
|
||||
### 5. 前端 HTML 元信息(已完成 ✅)
|
||||
|
||||
**index.html:**
|
||||
```html
|
||||
<meta charset="UTF-8">
|
||||
```
|
||||
|
||||
### 6. 文件编辑器配置
|
||||
|
||||
**确保所有代码文件使用 UTF-8:**
|
||||
- `.editorconfig` - 统一团队编码
|
||||
- IDE 设置 - 文件编码为 UTF-8
|
||||
- Git 设置 - 避免行尾符问题
|
||||
|
||||
### 7. 验证检查清单
|
||||
|
||||
部署后执行以下命令验证:
|
||||
|
||||
```bash
|
||||
# 1. 检查 MySQL 字符集配置
|
||||
docker exec -i deploy-mysql-1 mysql -u hfb -p<password> -e "SHOW VARIABLES LIKE 'character%';"
|
||||
|
||||
# 2. 检查表字符集
|
||||
docker exec -i deploy-mysql-1 mysql -u hfb -p<password> hfb_sys -e "SHOW CREATE TABLE announcements\G"
|
||||
|
||||
# 3. 验证数据正确性
|
||||
docker exec -i deploy-mysql-1 mysql -u hfb -p<password> hfb_sys -e "SELECT id, title FROM announcements LIMIT 3;"
|
||||
```
|
||||
|
||||
### 8. 常见问题排查
|
||||
|
||||
**问题:数据库中已有乱码数据**
|
||||
```bash
|
||||
# 执行修复脚本
|
||||
docker exec -i deploy-mysql-1 mysql -u hfb -p<password> hfb_sys < backend/migrations/000008_fix_announcement_charset.sql
|
||||
```
|
||||
|
||||
**问题:新插入的数据仍然乱码**
|
||||
- 检查数据库连接 DSN 是否包含 `charset=utf8mb4`
|
||||
- 检查 MySQL 配置文件是否生效
|
||||
- 重启 MySQL 容器使配置生效
|
||||
|
||||
**问题:只有某些字段乱码**
|
||||
```sql
|
||||
-- 转换特定列
|
||||
ALTER TABLE table_name MODIFY column_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### 9. 部署流程
|
||||
|
||||
每次部署时确保:
|
||||
|
||||
1. ✅ MySQL 配置文件已挂载
|
||||
2. ✅ 环境变量 MYSQL_DSN 包含 charset 参数
|
||||
3. ✅ 新建表使用正确的字符集
|
||||
4. ✅ 迁移脚本指定字符集
|
||||
|
||||
### 10. 开发规范
|
||||
|
||||
**新建表时必须指定:**
|
||||
```sql
|
||||
CREATE TABLE new_table (
|
||||
...
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='表注释';
|
||||
```
|
||||
|
||||
**修改表时保持一致:**
|
||||
```sql
|
||||
ALTER TABLE existing_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
通过以上配置,确保了从数据库服务器 → 连接驱动 → 表结构 → 应用层 → 前端展示的完整链路都使用 UTF-8 编码,彻底杜绝乱码问题。
|
||||
@@ -1,193 +0,0 @@
|
||||
# 部署故障排查指南
|
||||
|
||||
## SSH 连接断开问题
|
||||
|
||||
### 问题现象
|
||||
执行 `scripts/deploy-prod.sh` 后:
|
||||
- SSH 连接立即断开
|
||||
- 无法重新连接服务器
|
||||
- 服务器可能完全无响应
|
||||
|
||||
### 根本原因
|
||||
**Docker 构建过程耗尽服务器内存,导致系统 OOM (Out of Memory) 崩溃**
|
||||
|
||||
#### 技术细节
|
||||
1. **同时构建多个镜像**:原脚本使用 `docker compose up -d --build` 会并行构建 backend 和 frontend
|
||||
2. **前端构建超高内存消耗**:Node.js/npm 构建过程可能消耗 1-2GB 内存
|
||||
3. **无资源限制**:所有容器没有 memory limit,可无限制消耗系统资源
|
||||
4. **连锁反应**:
|
||||
- Docker 构建吃满内存
|
||||
- Linux OOM Killer 开始杀进程
|
||||
- SSH daemon 被杀死 → 连接断开
|
||||
- 系统核心服务被杀 → 无法重连
|
||||
- 最严重时整个系统死机
|
||||
|
||||
### 立即恢复方法
|
||||
|
||||
#### 方法 1:物理/远程控制台重启
|
||||
```bash
|
||||
# 通过云服务商控制台重启服务器
|
||||
# 重启后立即禁用 Docker 自动启动
|
||||
sudo systemctl disable docker
|
||||
sudo systemctl stop docker
|
||||
|
||||
# 清理所有容器
|
||||
cd /path/to/hfb_sys
|
||||
docker compose -f deploy/docker-compose.prod.yml down
|
||||
```
|
||||
|
||||
#### 方法 2:强制重启前快速执行
|
||||
如果还能短暂连接,立即执行:
|
||||
```bash
|
||||
sudo systemctl stop docker
|
||||
sudo killall -9 dockerd containerd
|
||||
```
|
||||
|
||||
### 根本解决方案(已修复)
|
||||
|
||||
#### 1. 添加资源限制(docker-compose.prod.yml)
|
||||
所有服务现在都有明确的内存和 CPU 限制:
|
||||
- MySQL: 512M memory, 1 CPU
|
||||
- Redis: 256M memory, 0.5 CPU
|
||||
- MinIO: 512M memory, 0.5 CPU
|
||||
- Backend: 512M memory, 1 CPU
|
||||
- Frontend: 256M memory, 0.5 CPU
|
||||
|
||||
总计:~2GB 内存(适合 4GB 服务器)
|
||||
|
||||
#### 2. 串行构建(deploy-prod.sh)
|
||||
修改后的脚本:
|
||||
```bash
|
||||
# 先构建 backend
|
||||
compose build backend
|
||||
|
||||
# 再构建 frontend
|
||||
compose build frontend
|
||||
|
||||
# 最后启动(不再构建)
|
||||
compose up -d --no-build
|
||||
```
|
||||
|
||||
这样可以避免内存峰值,但会增加 1-2 分钟部署时间。
|
||||
|
||||
### 安全部署流程
|
||||
|
||||
#### 首次部署
|
||||
```bash
|
||||
# 1. 在本地或有充足资源的机器上预构建镜像
|
||||
docker compose -f deploy/docker-compose.prod.yml build
|
||||
|
||||
# 2. 保存镜像
|
||||
docker save -o backend.tar <image_name>:latest
|
||||
docker save -o frontend.tar <image_name>:latest
|
||||
|
||||
# 3. 上传到服务器
|
||||
scp *.tar server:/tmp/
|
||||
|
||||
# 4. 在服务器上加载
|
||||
ssh server
|
||||
docker load -i /tmp/backend.tar
|
||||
docker load -i /tmp/frontend.tar
|
||||
|
||||
# 5. 使用 --no-build 启动
|
||||
./scripts/deploy-prod.sh --no-build
|
||||
```
|
||||
|
||||
#### 日常更新(推荐)
|
||||
```bash
|
||||
# 直接使用修复后的脚本
|
||||
./scripts/deploy-prod.sh
|
||||
|
||||
# 或者只更新不重新构建
|
||||
./scripts/deploy-prod.sh --no-build
|
||||
```
|
||||
|
||||
### 监控服务器资源
|
||||
|
||||
#### 部署前检查
|
||||
```bash
|
||||
# 查看可用内存
|
||||
free -h
|
||||
|
||||
# 查看 CPU 负载
|
||||
uptime
|
||||
|
||||
# 建议:至少保留 1GB 可用内存
|
||||
```
|
||||
|
||||
#### 部署中监控
|
||||
```bash
|
||||
# 另一个终端实时监控
|
||||
watch -n 1 'free -h && docker stats --no-stream'
|
||||
```
|
||||
|
||||
### 服务器配置建议
|
||||
|
||||
#### 最低配置
|
||||
- 内存:4GB
|
||||
- CPU:2 核
|
||||
- 磁盘:20GB
|
||||
|
||||
#### 推荐配置
|
||||
- 内存:8GB
|
||||
- CPU:4 核
|
||||
- 磁盘:50GB
|
||||
- 启用 Swap:4GB
|
||||
|
||||
#### 启用 Swap(紧急缓冲)
|
||||
```bash
|
||||
# 创建 4GB swap
|
||||
sudo fallocate -l 4G /swapfile
|
||||
sudo chmod 600 /swapfile
|
||||
sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
|
||||
# 永久启用
|
||||
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
|
||||
```
|
||||
|
||||
### 其他可能原因
|
||||
|
||||
#### 1. 网络超时
|
||||
```bash
|
||||
# 增加 SSH 保活
|
||||
# 编辑 ~/.ssh/config
|
||||
Host your-server
|
||||
ServerAliveInterval 60
|
||||
ServerAliveCountMax 3
|
||||
```
|
||||
|
||||
#### 2. Docker daemon 崩溃
|
||||
```bash
|
||||
# 查看 Docker 日志
|
||||
sudo journalctl -u docker -n 100 --no-pager
|
||||
|
||||
# 重启 Docker
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
#### 3. 磁盘满
|
||||
```bash
|
||||
# 检查磁盘空间
|
||||
df -h
|
||||
|
||||
# 清理 Docker 垃圾
|
||||
docker system prune -a --volumes -f
|
||||
```
|
||||
|
||||
## 预防措施清单
|
||||
|
||||
- [x] 所有服务添加 memory/CPU 限制
|
||||
- [x] 串行构建避免内存峰值
|
||||
- [ ] 启用服务器 Swap
|
||||
- [ ] 部署前检查可用内存
|
||||
- [ ] 设置 SSH 保活
|
||||
- [ ] 定期清理 Docker 磁盘
|
||||
- [ ] 监控部署过程资源使用
|
||||
|
||||
## 紧急联系
|
||||
|
||||
如果服务器完全无响应:
|
||||
1. 联系云服务商客服强制重启
|
||||
2. 通过 VNC/控制台登录
|
||||
3. 考虑升级服务器配置
|
||||
@@ -1,606 +0,0 @@
|
||||
# 压力测试指南
|
||||
|
||||
本文档提供完整的压力测试方案,用于评估系统在大数据量和高并发场景下的性能表现。
|
||||
|
||||
## 一、测试环境准备
|
||||
|
||||
### 1.1 硬件配置建议
|
||||
|
||||
**最低配置:**
|
||||
- CPU: 4核
|
||||
- 内存: 8GB
|
||||
- 磁盘: SSD 50GB
|
||||
|
||||
**推荐配置:**
|
||||
- CPU: 8核+
|
||||
- 内存: 16GB+
|
||||
- 磁盘: SSD 100GB+
|
||||
- MySQL: 独立部署,开启慢查询日志
|
||||
|
||||
### 1.2 数据库优化配置
|
||||
|
||||
在 `deploy/docker-compose.dev.yml` 中调整 MySQL 配置:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mysql:
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=secret
|
||||
command:
|
||||
- --max_connections=500
|
||||
- --innodb_buffer_pool_size=2G
|
||||
- --innodb_log_file_size=512M
|
||||
- --slow_query_log=1
|
||||
- --slow_query_log_file=/var/log/mysql/slow.log
|
||||
- --long_query_time=0.5
|
||||
```
|
||||
|
||||
### 1.3 后端配置优化
|
||||
|
||||
在 `backend/.env` 中调整:
|
||||
|
||||
```bash
|
||||
# 数据库连接池
|
||||
DB_MAX_OPEN_CONNS=100
|
||||
DB_MAX_IDLE_CONNS=20
|
||||
DB_CONN_MAX_LIFETIME=3600
|
||||
|
||||
# Redis配置
|
||||
REDIS_POOL_SIZE=50
|
||||
|
||||
# 日志级别(压测时降低日志输出)
|
||||
LOG_LEVEL=warn
|
||||
|
||||
# Gin模式
|
||||
APP_ENV=production
|
||||
```
|
||||
|
||||
## 二、生成测试数据
|
||||
|
||||
### 2.1 执行数据生成脚本
|
||||
|
||||
```bash
|
||||
# 连接到数据库容器
|
||||
docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < scripts/load_test_data.sql
|
||||
```
|
||||
|
||||
### 2.2 数据规模说明
|
||||
|
||||
该脚本会生成:
|
||||
- **10,000** 个用户(90%已实名)
|
||||
- **50,000** 个租号商品
|
||||
- **30,000** 个订单(包含各种状态)
|
||||
- **100,000** 条钱包流水
|
||||
- **50,000** 条聊天消息
|
||||
|
||||
### 2.3 验证数据生成
|
||||
|
||||
```sql
|
||||
-- 查看数据统计
|
||||
SELECT '用户数' as item, COUNT(*) as count FROM users
|
||||
UNION ALL
|
||||
SELECT '商品数', COUNT(*) FROM rental_listings
|
||||
UNION ALL
|
||||
SELECT '订单数', COUNT(*) FROM rental_orders
|
||||
UNION ALL
|
||||
SELECT '钱包流水', COUNT(*) FROM wallet_ledger;
|
||||
```
|
||||
|
||||
### 2.4 自定义数据量
|
||||
|
||||
修改脚本底部的调用参数:
|
||||
|
||||
```sql
|
||||
-- 根据需要调整数量
|
||||
CALL generate_users(50000); -- 生成5万用户
|
||||
CALL generate_listings(200000); -- 生成20万商品
|
||||
CALL generate_orders(100000); -- 生成10万订单
|
||||
CALL generate_wallet_ledger(500000); -- 生成50万流水
|
||||
```
|
||||
|
||||
## 三、索引优化验证
|
||||
|
||||
### 3.1 检查现有索引
|
||||
|
||||
```sql
|
||||
-- 查看订单表索引
|
||||
SHOW INDEX FROM rental_orders;
|
||||
|
||||
-- 查看钱包流水索引
|
||||
SHOW INDEX FROM wallet_ledger;
|
||||
|
||||
-- 查看商品表索引
|
||||
SHOW INDEX FROM rental_listings;
|
||||
```
|
||||
|
||||
### 3.2 分析慢查询
|
||||
|
||||
```sql
|
||||
-- 分析商品列表查询
|
||||
EXPLAIN SELECT * FROM rental_listings
|
||||
WHERE status = 'active'
|
||||
AND review_status = 'approved'
|
||||
ORDER BY published_at DESC
|
||||
LIMIT 20;
|
||||
|
||||
-- 分析用户订单查询
|
||||
EXPLAIN SELECT * FROM rental_orders
|
||||
WHERE renter_id = 1234
|
||||
AND status = 'active'
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- 分析钱包流水查询
|
||||
EXPLAIN SELECT * FROM wallet_ledger
|
||||
WHERE user_id = 1234
|
||||
AND biz_type = 'rent_payment'
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 50;
|
||||
```
|
||||
|
||||
### 3.3 添加缺失索引(如果需要)
|
||||
|
||||
```sql
|
||||
-- 示例:为常用查询组合添加联合索引
|
||||
ALTER TABLE rental_orders
|
||||
ADD INDEX idx_status_handoff_created (status, handoff_status, created_at);
|
||||
|
||||
-- 为管理后台查询优化
|
||||
ALTER TABLE wallet_ledger
|
||||
ADD INDEX idx_created_biz_type (created_at, biz_type);
|
||||
```
|
||||
|
||||
## 四、压力测试执行
|
||||
|
||||
### 4.1 使用 Go 压测工具
|
||||
|
||||
```bash
|
||||
cd scripts
|
||||
|
||||
# 编译压测工具
|
||||
go build -o stress_test stress_test.go
|
||||
|
||||
# 场景1: 商品列表查询(高频读)
|
||||
./stress_test -url http://localhost:8080 -c 50 -d 60 -s list_listings
|
||||
|
||||
# 场景2: 订单创建(写操作)
|
||||
./stress_test -url http://localhost:8080 -c 20 -d 60 -s create_order
|
||||
|
||||
# 场景3: 钱包流水查询
|
||||
./stress_test -url http://localhost:8080 -c 30 -d 60 -s wallet
|
||||
|
||||
# 场景4: 混合场景(模拟真实流量)
|
||||
./stress_test -url http://localhost:8080 -c 100 -d 300 -s mixed
|
||||
```
|
||||
|
||||
### 4.2 使用 Apache Bench (ab)
|
||||
|
||||
```bash
|
||||
# 简单的商品列表查询压测
|
||||
ab -n 10000 -c 100 http://localhost:8080/api/listings?page=1&page_size=20
|
||||
|
||||
# 健康检查接口压测
|
||||
ab -n 50000 -c 200 http://localhost:8080/health
|
||||
```
|
||||
|
||||
### 4.3 使用 wrk
|
||||
|
||||
```bash
|
||||
# 安装 wrk
|
||||
brew install wrk # macOS
|
||||
# sudo apt install wrk # Ubuntu
|
||||
|
||||
# 基础压测
|
||||
wrk -t4 -c100 -d60s http://localhost:8080/api/listings
|
||||
|
||||
# 使用脚本进行复杂场景测试
|
||||
wrk -t4 -c100 -d60s -s scripts/wrk_scenario.lua http://localhost:8080
|
||||
```
|
||||
|
||||
创建 `scripts/wrk_scenario.lua`:
|
||||
|
||||
```lua
|
||||
-- 模拟不同的查询参数
|
||||
counter = 0
|
||||
|
||||
request = function()
|
||||
counter = counter + 1
|
||||
page = (counter % 10) + 1
|
||||
path = "/api/listings?page=" .. page .. "&page_size=20"
|
||||
return wrk.format("GET", path)
|
||||
end
|
||||
```
|
||||
|
||||
## 五、性能监控
|
||||
|
||||
### 5.1 数据库性能监控
|
||||
|
||||
```sql
|
||||
-- 实时查看正在执行的查询
|
||||
SHOW FULL PROCESSLIST;
|
||||
|
||||
-- 查看慢查询日志
|
||||
docker exec hfb-mysql tail -f /var/log/mysql/slow.log
|
||||
|
||||
-- 查看表锁情况
|
||||
SHOW OPEN TABLES WHERE In_use > 0;
|
||||
|
||||
-- 查看InnoDB状态
|
||||
SHOW ENGINE INNODB STATUS;
|
||||
|
||||
-- 查看连接数
|
||||
SHOW STATUS LIKE 'Threads_connected';
|
||||
SHOW STATUS LIKE 'Max_used_connections';
|
||||
```
|
||||
|
||||
### 5.2 应用性能监控
|
||||
|
||||
在压测期间,监控后端日志:
|
||||
|
||||
```bash
|
||||
# 实时查看后端日志
|
||||
tail -f backend/logs/app-*.log | grep -E "ERROR|WARN|latency"
|
||||
|
||||
# 监控容器资源使用
|
||||
docker stats hfb-backend hfb-mysql hfb-redis
|
||||
```
|
||||
|
||||
### 5.3 系统资源监控
|
||||
|
||||
```bash
|
||||
# CPU和内存使用
|
||||
top -p $(pgrep -f "go run")
|
||||
|
||||
# 网络连接数
|
||||
netstat -an | grep :8080 | wc -l
|
||||
|
||||
# 查看打开的文件描述符
|
||||
lsof -p $(pgrep -f "go run") | wc -l
|
||||
```
|
||||
|
||||
## 六、性能指标基准
|
||||
|
||||
### 6.1 响应时间目标
|
||||
|
||||
| 接口类型 | P50 | P95 | P99 |
|
||||
|---------|-----|-----|-----|
|
||||
| 商品列表查询 | < 50ms | < 100ms | < 200ms |
|
||||
| 订单详情查询 | < 30ms | < 80ms | < 150ms |
|
||||
| 钱包流水查询 | < 40ms | < 100ms | < 200ms |
|
||||
| 创建订单 | < 100ms | < 300ms | < 500ms |
|
||||
| 支付处理 | < 200ms | < 500ms | < 1000ms |
|
||||
|
||||
### 6.2 吞吐量目标
|
||||
|
||||
- **读操作**:单机 QPS > 1000
|
||||
- **写操作**:单机 QPS > 200
|
||||
- **混合场景**:单机 QPS > 500
|
||||
|
||||
### 6.3 数据库查询目标
|
||||
|
||||
- **简单查询**:< 10ms
|
||||
- **联表查询**:< 50ms
|
||||
- **复杂聚合**:< 100ms
|
||||
|
||||
## 七、常见性能瓶颈与优化
|
||||
|
||||
### 7.1 数据库层面
|
||||
|
||||
#### 问题1:商品列表查询慢
|
||||
|
||||
**症状:** `SELECT * FROM rental_listings WHERE status = 'active'` 耗时超过 100ms
|
||||
|
||||
**优化方案:**
|
||||
|
||||
```sql
|
||||
-- 1. 添加覆盖索引
|
||||
ALTER TABLE rental_listings
|
||||
ADD INDEX idx_status_review_published_cover (
|
||||
status, review_status, published_at, id, price, deposit_amount
|
||||
);
|
||||
|
||||
-- 2. 避免 SELECT *,只查询需要的字段
|
||||
SELECT id, owner_id, price, deposit_amount, published_at
|
||||
FROM rental_listings
|
||||
WHERE status = 'active' AND review_status = 'approved'
|
||||
ORDER BY published_at DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
|
||||
#### 问题2:用户订单分页查询慢
|
||||
|
||||
**症状:** 大偏移量分页(page > 100)性能下降
|
||||
|
||||
**优化方案:**
|
||||
|
||||
```sql
|
||||
-- 使用游标分页代替 OFFSET
|
||||
SELECT * FROM rental_orders
|
||||
WHERE renter_id = ?
|
||||
AND id < ? -- 上一页最后一条的ID
|
||||
ORDER BY id DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
|
||||
在代码中实现:
|
||||
|
||||
```go
|
||||
// 使用游标分页
|
||||
func (r *Repository) ListOrdersCursor(userID, lastID uint64, limit int) ([]Order, error) {
|
||||
query := `SELECT * FROM rental_orders
|
||||
WHERE renter_id = ? AND id < ?
|
||||
ORDER BY id DESC LIMIT ?`
|
||||
|
||||
if lastID == 0 {
|
||||
lastID = ^uint64(0) // Max uint64
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 问题3:钱包流水查询慢(10万+数据)
|
||||
|
||||
**优化方案:**
|
||||
|
||||
```sql
|
||||
-- 1. 确保有复合索引
|
||||
ALTER TABLE wallet_ledger
|
||||
ADD INDEX idx_user_created_desc (user_id, created_at DESC);
|
||||
|
||||
-- 2. 分区表(适用于超大数据量)
|
||||
ALTER TABLE wallet_ledger
|
||||
PARTITION BY RANGE (YEAR(created_at)) (
|
||||
PARTITION p2024 VALUES LESS THAN (2025),
|
||||
PARTITION p2025 VALUES LESS THAN (2026),
|
||||
PARTITION p2026 VALUES LESS THAN (2027),
|
||||
PARTITION p_future VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
|
||||
-- 3. 归档历史数据
|
||||
CREATE TABLE wallet_ledger_archive LIKE wallet_ledger;
|
||||
INSERT INTO wallet_ledger_archive
|
||||
SELECT * FROM wallet_ledger
|
||||
WHERE created_at < DATE_SUB(NOW(), INTERVAL 6 MONTH);
|
||||
```
|
||||
|
||||
### 7.2 应用层面
|
||||
|
||||
#### 问题1:N+1 查询问题
|
||||
|
||||
**症状:** 商品列表查询后,循环查询关联的账号信息
|
||||
|
||||
**优化方案:**
|
||||
|
||||
```go
|
||||
// 错误做法:N+1查询
|
||||
for _, listing := range listings {
|
||||
account, _ := repo.GetAccount(listing.AccountID)
|
||||
listing.Account = account
|
||||
}
|
||||
|
||||
// 正确做法:预加载
|
||||
func (r *Repository) ListWithAccounts(filter ListingFilter) ([]Listing, error) {
|
||||
query := `
|
||||
SELECT
|
||||
rl.*,
|
||||
ga.title as account_title,
|
||||
ga.rank_level,
|
||||
ga.server_region
|
||||
FROM rental_listings rl
|
||||
LEFT JOIN game_accounts ga ON rl.account_id = ga.id
|
||||
WHERE rl.status = ?
|
||||
ORDER BY rl.published_at DESC
|
||||
LIMIT ?
|
||||
`
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 问题2:缓存缺失
|
||||
|
||||
**优化方案:**
|
||||
|
||||
```go
|
||||
// 为热点数据添加Redis缓存
|
||||
func (s *Service) GetListing(id uint64) (*Listing, error) {
|
||||
cacheKey := fmt.Sprintf("listing:%d", id)
|
||||
|
||||
// 1. 尝试从缓存读取
|
||||
if cached, err := s.redis.Get(ctx, cacheKey).Bytes(); err == nil {
|
||||
var listing Listing
|
||||
json.Unmarshal(cached, &listing)
|
||||
return &listing, nil
|
||||
}
|
||||
|
||||
// 2. 缓存未命中,从数据库读取
|
||||
listing, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 写入缓存
|
||||
data, _ := json.Marshal(listing)
|
||||
s.redis.Set(ctx, cacheKey, data, 10*time.Minute)
|
||||
|
||||
return listing, nil
|
||||
}
|
||||
```
|
||||
|
||||
#### 问题3:数据库连接池耗尽
|
||||
|
||||
**优化方案:**
|
||||
|
||||
```go
|
||||
// 在 database/mysql.go 中优化连接池配置
|
||||
db.SetMaxOpenConns(100) // 最大连接数
|
||||
db.SetMaxIdleConns(20) // 空闲连接数
|
||||
db.SetConnMaxLifetime(time.Hour) // 连接最大生命周期
|
||||
db.SetConnMaxIdleTime(10 * time.Minute) // 空闲连接超时
|
||||
```
|
||||
|
||||
### 7.3 Redis 优化
|
||||
|
||||
```bash
|
||||
# 监控 Redis 性能
|
||||
redis-cli --latency
|
||||
redis-cli --stat
|
||||
|
||||
# 查看慢查询
|
||||
redis-cli SLOWLOG GET 10
|
||||
|
||||
# 查看内存使用
|
||||
redis-cli INFO memory
|
||||
```
|
||||
|
||||
**配置优化:**
|
||||
|
||||
```redis
|
||||
# 最大内存限制
|
||||
maxmemory 2gb
|
||||
|
||||
# 内存淘汰策略
|
||||
maxmemory-policy allkeys-lru
|
||||
|
||||
# 持久化配置(开发环境可以关闭以提升性能)
|
||||
save ""
|
||||
appendonly no
|
||||
```
|
||||
|
||||
## 八、特定场景测试
|
||||
|
||||
### 8.1 订单高峰测试
|
||||
|
||||
模拟秒杀或活动高峰期:
|
||||
|
||||
```bash
|
||||
# 同时创建1000个订单
|
||||
./stress_test -url http://localhost:8080 -c 100 -d 10 -s create_order
|
||||
```
|
||||
|
||||
**预期检查:**
|
||||
- 数据库连接池是否耗尽
|
||||
- 是否出现死锁
|
||||
- 钱包余额扣减是否正确(需要事务隔离)
|
||||
|
||||
### 8.2 聊天消息压测
|
||||
|
||||
```bash
|
||||
# 模拟100个用户同时发送消息
|
||||
./stress_test -url http://localhost:8080 -c 100 -d 60 -s chat
|
||||
```
|
||||
|
||||
**预期检查:**
|
||||
- WebSocket 连接数限制
|
||||
- 消息写入速度
|
||||
- 未读消息计数准确性
|
||||
|
||||
### 8.3 大数据量查询
|
||||
|
||||
```sql
|
||||
-- 测试后台钱包流水导出(大数据量)
|
||||
SELECT * FROM wallet_ledger
|
||||
WHERE created_at >= '2024-01-01'
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- 超时检查
|
||||
SET SESSION max_execution_time = 30000; -- 30秒超时
|
||||
```
|
||||
|
||||
## 九、压测后清理
|
||||
|
||||
### 9.1 清理测试数据
|
||||
|
||||
```sql
|
||||
-- 谨慎执行!会删除所有测试数据
|
||||
DELETE FROM wallet_ledger WHERE id > 100;
|
||||
DELETE FROM rental_orders WHERE id > 100;
|
||||
DELETE FROM rental_listings WHERE id > 100;
|
||||
DELETE FROM game_accounts WHERE id > 100;
|
||||
DELETE FROM users WHERE id > 1000;
|
||||
|
||||
-- 重置自增ID
|
||||
ALTER TABLE users AUTO_INCREMENT = 1001;
|
||||
ALTER TABLE rental_orders AUTO_INCREMENT = 101;
|
||||
```
|
||||
|
||||
### 9.2 恢复配置
|
||||
|
||||
```bash
|
||||
# 恢复开发环境配置
|
||||
cd backend
|
||||
cp .env.example .env
|
||||
|
||||
# 重启服务
|
||||
./scripts/dev.sh
|
||||
```
|
||||
|
||||
## 十、持续监控建议
|
||||
|
||||
### 10.1 生产环境监控
|
||||
|
||||
推荐集成:
|
||||
- **APM**: New Relic / Datadog
|
||||
- **日志**: ELK Stack / Grafana Loki
|
||||
- **监控**: Prometheus + Grafana
|
||||
- **告警**: PagerDuty / 企业微信
|
||||
|
||||
### 10.2 关键指标
|
||||
|
||||
**应用层:**
|
||||
- API 响应时间(P50/P95/P99)
|
||||
- QPS / TPS
|
||||
- 错误率
|
||||
- 慢查询数量
|
||||
|
||||
**数据库层:**
|
||||
- 连接数
|
||||
- 慢查询数
|
||||
- 锁等待时间
|
||||
- InnoDB 缓存命中率
|
||||
|
||||
**系统层:**
|
||||
- CPU 使用率
|
||||
- 内存使用率
|
||||
- 磁盘 IO
|
||||
- 网络带宽
|
||||
|
||||
## 十一、性能优化 Checklist
|
||||
|
||||
- [ ] 数据库索引覆盖所有常用查询
|
||||
- [ ] 消除 N+1 查询问题
|
||||
- [ ] 热点数据使用 Redis 缓存
|
||||
- [ ] 数据库连接池配置合理
|
||||
- [ ] 分页查询使用游标而非 OFFSET
|
||||
- [ ] 大数据量表考虑分区
|
||||
- [ ] 历史数据定期归档
|
||||
- [ ] 慢查询日志监控告警
|
||||
- [ ] 数据库读写分离(如适用)
|
||||
- [ ] CDN 加速静态资源
|
||||
|
||||
## 附录
|
||||
|
||||
### A. 压测命令速查
|
||||
|
||||
```bash
|
||||
# 启动测试环境
|
||||
docker-compose -f deploy/docker-compose.dev.yml up -d
|
||||
cd backend && go run ./cmd/api
|
||||
|
||||
# 生成测试数据
|
||||
docker exec -i hfb-mysql mysql -uhfb -psecret hfb_sys < scripts/load_test_data.sql
|
||||
|
||||
# 执行压测
|
||||
cd scripts
|
||||
go build -o stress_test stress_test.go
|
||||
./stress_test -url http://localhost:8080 -c 100 -d 60 -s mixed
|
||||
|
||||
# 监控性能
|
||||
docker stats
|
||||
docker exec hfb-mysql mysqladmin -uhfb -psecret processlist
|
||||
```
|
||||
|
||||
### B. 参考资料
|
||||
|
||||
- [MySQL 性能优化最佳实践](https://dev.mysql.com/doc/refman/8.0/en/optimization.html)
|
||||
- [Go 性能优化](https://github.com/dgryski/go-perfbook)
|
||||
- [Gin 框架性能调优](https://gin-gonic.com/docs/benchmarks/)
|
||||
@@ -1,121 +0,0 @@
|
||||
# 订单详情页 UI 优化
|
||||
|
||||
## 优化内容
|
||||
|
||||
### 问题
|
||||
- 原页面 UI 过长,需要滚动到最底部才能看到"提交交接说明"、"提交结账"、"发起申诉"等操作按钮
|
||||
- 用户体验差,操作流程不流畅
|
||||
|
||||
### 解决方案
|
||||
|
||||
#### 1. 布局调整
|
||||
- 采用**左右分栏布局**:主内容区(左)+ 操作侧边栏(右)
|
||||
- 侧边栏**固定悬浮**(sticky),始终可见
|
||||
- 页面最大宽度从 1200px 扩展到 1400px,为侧边栏留出空间
|
||||
|
||||
#### 2. 操作侧边栏设计
|
||||
- **宽度**: 320px
|
||||
- **位置**: 右侧固定悬浮(sticky top: 24px)
|
||||
- **样式**: 白色卡片,带阴影和边框,重要操作突出显示
|
||||
|
||||
#### 3. 按钮优化
|
||||
|
||||
##### 快捷操作(直接执行)
|
||||
- **提交交接**: 号主在侧边栏直接填写并提交
|
||||
- **确认收号**: 租客一键确认
|
||||
- **确认结账**: 号主一键确认
|
||||
- **同意修正**: 租客一键同意
|
||||
|
||||
##### 复杂操作(跳转填写)
|
||||
- **发起结账**: 点击后平滑滚动到结账表单填写区
|
||||
- **修改结账**: 点击后平滑滚动到修改表单
|
||||
- **拒绝修正**: 点击后平滑滚动到拒绝原因填写区
|
||||
- **发起申诉**: 点击后平滑滚动到申诉表单
|
||||
|
||||
#### 4. 响应式设计
|
||||
- **桌面端**: 左右分栏,侧边栏悬浮
|
||||
- **移动端**: 单列布局,侧边栏移到顶部(order: -1)
|
||||
|
||||
## 核心代码变更
|
||||
|
||||
### 布局结构
|
||||
```vue
|
||||
<div class="content-layout">
|
||||
<div class="main-content">
|
||||
<!-- 主要内容:进度、信息、交接记录、详细表单 -->
|
||||
</div>
|
||||
|
||||
<div class="action-sidebar">
|
||||
<!-- 操作卡片:根据订单状态和用户角色显示 -->
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 样式关键点
|
||||
```css
|
||||
.content-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 320px;
|
||||
gap: 24px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.action-sidebar {
|
||||
position: sticky;
|
||||
top: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.sidebar-card {
|
||||
padding: 20px;
|
||||
background: #ffffff;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
```
|
||||
|
||||
### 平滑滚动函数
|
||||
```typescript
|
||||
function scrollToCheckout() {
|
||||
const checkoutSection = document.querySelector('.checkout-form-section')
|
||||
if (checkoutSection) {
|
||||
checkoutSection.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 优化效果
|
||||
|
||||
### 用户体验提升
|
||||
1. **无需滚动查找**: 所有核心操作始终可见
|
||||
2. **快速决策**: 重要信息和操作集中在右侧
|
||||
3. **减少误操作**: 复杂操作跳转到详细表单,简单操作直接执行
|
||||
4. **视觉引导**: 申诉等特殊操作用不同颜色背景突出
|
||||
|
||||
### 操作流程优化
|
||||
- **交接**: 侧边栏直接提交 → 提升效率
|
||||
- **结账**: 侧边栏点击跳转 → 避免误操作
|
||||
- **申诉**: 侧边栏始终可见 → 降低投诉门槛
|
||||
|
||||
### 性能优化
|
||||
- 使用 CSS `position: sticky` 代替 JavaScript 监听滚动
|
||||
- 平滑滚动使用原生 `scrollIntoView` API
|
||||
- 响应式布局使用 CSS Grid,无需 JavaScript
|
||||
|
||||
## 兼容性
|
||||
|
||||
- **现代浏览器**: 完全支持
|
||||
- **移动端**: 自动切换为单列布局
|
||||
- **低分辨率**: 自动调整为堆叠布局
|
||||
|
||||
## 文件变更
|
||||
|
||||
- `frontend/src/features/orders/views/OrderDetailView.vue`
|
||||
- 添加 `.content-layout` 和 `.action-sidebar` 布局
|
||||
- 添加侧边栏操作卡片
|
||||
- 添加平滑滚动函数
|
||||
- 为表单区域添加 class 标识
|
||||
- 响应式样式优化
|
||||
@@ -1,74 +0,0 @@
|
||||
# 订单详情页 UI 优化总结
|
||||
|
||||
## 问题
|
||||
- 原页面 UI 过长,操作按钮在页面底部
|
||||
- 用户需要滚动到最底部才能执行"提交交接"、"提交结账"、"发起申诉"等关键操作
|
||||
- 部分操作在侧边栏和主内容区重复显示
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 布局重构
|
||||
- **左右分栏布局**:主内容区(左)+ 操作侧边栏(右,320px)
|
||||
- **侧边栏悬浮**:`position: sticky; top: 24px;` 始终可见
|
||||
- **页面最大宽度**:从 1200px 扩展到 1400px
|
||||
|
||||
### 2. 操作整合(避免重复)
|
||||
|
||||
#### 简单操作 - 直接在侧边栏完成
|
||||
- ✅ **提交交接说明**:侧边栏内直接填写 textarea 并提交(移除主内容区重复表单)
|
||||
- ✅ **确认收号**:侧边栏一键确认(移除主内容区重复按钮)
|
||||
- ✅ **确认结账**:侧边栏一键确认 + 跳转到修改表单按钮
|
||||
- ✅ **同意修正结账**:侧边栏一键同意 + 跳转到拒绝表单按钮
|
||||
|
||||
#### 复杂操作 - 侧边栏提供快捷入口,主内容区保留详细表单
|
||||
- 📝 **发起结账**:侧边栏可快速提交(使用当前表单值),也可跳转到详细表单修改消耗品、哈夫币等
|
||||
- 📝 **修改结账**:侧边栏提供跳转按钮,主内容区保留完整修改表单
|
||||
- 📝 **拒绝修正**:侧边栏提供跳转按钮,主内容区填写拒绝原因
|
||||
- 📝 **发起申诉**:侧边栏提供跳转按钮,主内容区填写完整申诉信息
|
||||
|
||||
### 3. 视觉优化
|
||||
- **卡片样式**:白色背景 + 边框 + 阴影
|
||||
- **高亮卡片**:发起结账使用蓝色背景(`.highlight-card`)
|
||||
- **争议卡片**:发起申诉使用红色背景(`.dispute-card`)
|
||||
- **小分隔线**:侧边栏内使用 `.section-divider-mini` 分隔主次操作
|
||||
|
||||
### 4. 响应式设计
|
||||
- **桌面端**:`grid-template-columns: 1fr 320px`
|
||||
- **移动端**:单列布局,侧边栏移到顶部(`order: -1`)
|
||||
|
||||
## 主要代码变更
|
||||
|
||||
### 新增函数
|
||||
```typescript
|
||||
function scrollToCheckout()
|
||||
function scrollToCounterCheckout()
|
||||
function scrollToRejectCheckout()
|
||||
function scrollToDispute()
|
||||
```
|
||||
|
||||
### 新增样式类
|
||||
```css
|
||||
.content-layout { display: grid; grid-template-columns: 1fr 320px; }
|
||||
.action-sidebar { position: sticky; top: 24px; }
|
||||
.sidebar-card { ... }
|
||||
.sidebar-card.highlight-card { background: #eff6ff; }
|
||||
.sidebar-card.dispute-card { background: #fef2f2; }
|
||||
.section-divider-mini { ... }
|
||||
```
|
||||
|
||||
### 移除重复内容
|
||||
- ❌ 主内容区的"提交交接说明"表单
|
||||
- ❌ 主内容区的"确认收号"表单
|
||||
- ❌ "确认结账"部分的重复按钮和分隔线
|
||||
|
||||
## 用户体验提升
|
||||
|
||||
1. **无需滚动**:所有关键操作始终在右侧可见
|
||||
2. **快捷操作**:简单操作直接在侧边栏完成(如提交交接、确认收号)
|
||||
3. **灵活选择**:复杂操作既可快速提交,也可跳转到详细表单修改
|
||||
4. **视觉引导**:重要操作用颜色区分(蓝色高亮、红色警告)
|
||||
5. **减少误操作**:复杂表单保留在主内容区,避免误提交
|
||||
|
||||
## 文件变更
|
||||
- `frontend/src/features/orders/views/OrderDetailView.vue`
|
||||
- `docs/ui-optimization-order-detail.md`(优化文档)
|
||||
@@ -1,319 +0,0 @@
|
||||
# 压力测试使用指南
|
||||
|
||||
**更新时间**:2026-06-06
|
||||
**状态**:✅ 已完成改进,工具可用
|
||||
|
||||
---
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 生成测试数据
|
||||
|
||||
```bash
|
||||
cd /Users/yml/codes/hfb_sys
|
||||
./scripts/stress_test.sh data -u 1000 -l 5000 -o 3000
|
||||
```
|
||||
|
||||
### 2. 执行压力测试
|
||||
|
||||
```bash
|
||||
# 真实业务场景(推荐)
|
||||
./scripts/stress_test.sh test -c 100 -d 300 -s realistic --warmup 200
|
||||
|
||||
# 管理后台场景
|
||||
./scripts/stress_test.sh test -c 50 -d 180 -s admin
|
||||
|
||||
# 商品查询专项测试
|
||||
./scripts/stress_test.sh test -c 200 -d 120 -s listing_only
|
||||
|
||||
# 梯度压测(逐步加压)
|
||||
./scripts/stress_test.sh test --gradual -c 200 -d 60 -s realistic --warmup 200
|
||||
```
|
||||
|
||||
### 3. 监控和报告
|
||||
|
||||
```bash
|
||||
# 实时监控
|
||||
./scripts/stress_test.sh monitor
|
||||
|
||||
# 生成报告
|
||||
./scripts/stress_test.sh report
|
||||
|
||||
# 清理数据
|
||||
./scripts/stress_test.sh clean
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 测试场景说明
|
||||
|
||||
### realistic 场景(真实业务流量)
|
||||
|
||||
模拟真实用户行为,流量分布:
|
||||
|
||||
- 35% - 商品列表查询(高频操作)
|
||||
- 25% - 商品详情查询
|
||||
- 15% - 我的订单列表
|
||||
- 10% - 钱包余额查询
|
||||
- 7% - 聊天列表
|
||||
- 5% - 订单详情
|
||||
- 2% - 创建订单
|
||||
- 1% - 支付订单
|
||||
|
||||
**适用场景**:评估系统整体性能,模拟生产环境
|
||||
|
||||
### admin 场景(管理后台)
|
||||
|
||||
模拟管理员操作,流量分布:
|
||||
|
||||
- 25% - 用户管理
|
||||
- 20% - 订单管理
|
||||
- 15% - 商品审核
|
||||
- 15% - 钱包流水
|
||||
- 10% - 申诉管理
|
||||
- 10% - 审计日志
|
||||
- 5% - 仪表盘
|
||||
|
||||
**适用场景**:评估后台管理系统性能
|
||||
|
||||
### listing_only 场景(商品查询)
|
||||
|
||||
专注于商品查询性能:
|
||||
|
||||
- 50% - 商品列表查询
|
||||
- 50% - 商品详情查询
|
||||
|
||||
**适用场景**:评估商品模块单点性能
|
||||
|
||||
---
|
||||
|
||||
## 参数说明
|
||||
|
||||
### 数据生成参数
|
||||
|
||||
```bash
|
||||
-u, --users NUM # 生成用户数量(默认: 1000)
|
||||
-l, --listings NUM # 生成商品数量(默认: 5000)
|
||||
-o, --orders NUM # 生成订单数量(默认: 3000)
|
||||
--ledger NUM # 生成钱包流水数量(默认: 10000)
|
||||
--chat-messages NUM # 生成聊天消息数量(默认: 5000)
|
||||
--use-optimized # 使用优化的数据生成脚本(实验性)
|
||||
```
|
||||
|
||||
### 压力测试参数
|
||||
|
||||
```bash
|
||||
-c, --concurrency NUM # 并发数(默认: 50)
|
||||
-d, --duration SEC # 测试时长/秒(默认: 60)
|
||||
-s, --scenario NAME # 测试场景: realistic, admin, listing_only
|
||||
--gradual # 启用梯度压测
|
||||
--warmup NUM # 预热用户数(默认: 100)
|
||||
--url URL # 后端地址(默认: http://localhost:8080)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 压测工具特性
|
||||
|
||||
### ✅ 已实现功能
|
||||
|
||||
1. **真实认证支持**
|
||||
- 自动生成用户 token 池(避免 401 错误)
|
||||
- 支持管理员 token 自动获取
|
||||
- 模拟真实用户行为
|
||||
|
||||
2. **智能商品 ID 预加载**
|
||||
- 启动时从 API 获取可用商品 ID 列表
|
||||
- 避免 404 错误,提高成功率
|
||||
|
||||
3. **详细统计指标**
|
||||
- P50/P95/P99 延迟分布
|
||||
- 错误分类统计(Top 10)
|
||||
- 实时进度显示
|
||||
- QPS 统计
|
||||
|
||||
4. **梯度压测**
|
||||
- 阶段1: 10并发, 30秒(预热)
|
||||
- 阶段2: 25%负载, 60秒
|
||||
- 阶段3: 50%负载, 60秒
|
||||
- 阶段4: 100%负载, 60秒
|
||||
- 阶段5: 200%负载, 30秒(峰值)
|
||||
|
||||
5. **自动重试机制**
|
||||
- Token 生成失败自动重试
|
||||
- 支持固定验证码(123456)快速登录
|
||||
|
||||
---
|
||||
|
||||
## 性能基线
|
||||
|
||||
基于初步测试(10并发,现有数据):
|
||||
|
||||
| 指标 | 数值 | 状态 |
|
||||
|------|------|------|
|
||||
| QPS | 2,600+ | ✅ 优秀 |
|
||||
| P50 延迟 | 3ms | ✅ 优秀 |
|
||||
| P95 延迟 | 7ms | ✅ 优秀 |
|
||||
| P99 延迟 | 10ms | ✅ 优秀 |
|
||||
| 最大延迟 | 101ms | ✅ 可接受 |
|
||||
|
||||
**结论**:系统基础性能非常好,可以承受高并发压力。
|
||||
|
||||
---
|
||||
|
||||
## 完整流程示例
|
||||
|
||||
### 场景1:首次压测
|
||||
|
||||
```bash
|
||||
# 1. 启动开发环境
|
||||
./scripts/dev.sh
|
||||
|
||||
# 2. 生成测试数据(小规模)
|
||||
./scripts/stress_test.sh data -u 1000 -l 5000 -o 3000
|
||||
|
||||
# 3. 执行压测(100并发,5分钟)
|
||||
./scripts/stress_test.sh test -c 100 -d 300 -s realistic --warmup 200
|
||||
|
||||
# 4. 查看报告
|
||||
./scripts/stress_test.sh report
|
||||
```
|
||||
|
||||
### 场景2:梯度压测
|
||||
|
||||
```bash
|
||||
# 逐步加压,找到系统极限
|
||||
./scripts/stress_test.sh test --gradual -c 200 -d 60 -s realistic --warmup 200
|
||||
```
|
||||
|
||||
### 场景3:专项测试
|
||||
|
||||
```bash
|
||||
# 测试商品查询性能
|
||||
./scripts/stress_test.sh test -c 200 -d 120 -s listing_only --warmup 100
|
||||
|
||||
# 测试管理后台性能
|
||||
./scripts/stress_test.sh test -c 50 -d 180 -s admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 监控命令
|
||||
|
||||
### 实时监控
|
||||
|
||||
```bash
|
||||
# 容器资源使用
|
||||
docker stats hfb-backend hfb-mysql hfb-redis
|
||||
|
||||
# MySQL 连接数
|
||||
docker exec hfb-mysql mysql -uhfb -psecret -e "SHOW STATUS LIKE 'Threads_connected';"
|
||||
|
||||
# MySQL 慢查询
|
||||
docker exec hfb-mysql mysql -uhfb -psecret -e "SHOW STATUS LIKE 'Slow_queries';"
|
||||
|
||||
# Redis 统计
|
||||
docker exec hfb-redis redis-cli INFO stats | grep -E "total_commands_processed|instantaneous_ops_per_sec"
|
||||
```
|
||||
|
||||
### 查看正在执行的查询
|
||||
|
||||
```bash
|
||||
docker exec hfb-mysql mysql -uhfb -psecret -e "SHOW FULL PROCESSLIST;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 如果出现性能瓶颈
|
||||
|
||||
1. **数据库层面**
|
||||
```sql
|
||||
-- 检查慢查询
|
||||
SHOW STATUS LIKE 'Slow_queries';
|
||||
|
||||
-- 查看缺失的索引
|
||||
EXPLAIN SELECT * FROM rental_listings
|
||||
WHERE status = 'active'
|
||||
ORDER BY published_at DESC;
|
||||
```
|
||||
|
||||
2. **应用层面**
|
||||
- 检查是否有 N+1 查询
|
||||
- 添加 Redis 缓存(商品列表、用户信息)
|
||||
- 优化数据库连接池配置
|
||||
|
||||
3. **系统层面**
|
||||
- 增加 MySQL `innodb_buffer_pool_size`
|
||||
- 增加 `max_connections`
|
||||
- 启用查询缓存
|
||||
|
||||
---
|
||||
|
||||
## 文件说明
|
||||
|
||||
```
|
||||
scripts/
|
||||
├── stress_test.sh # 统一入口脚本
|
||||
├── load_stress.go # Go 压测工具(改进版)
|
||||
├── load_test_data.sql # 数据生成脚本
|
||||
└── load_test_data_optimized.sql # 优化版数据生成(实验性)
|
||||
|
||||
docs/
|
||||
├── 压力测试使用指南.md # 本文档(快速上手)
|
||||
└── stress-test-guide.md # 详细技术指南(性能优化)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: Token 生成失败怎么办?
|
||||
|
||||
**A:** 工具已自动处理:
|
||||
1. 先尝试固定验证码 `123456`(mock 模式)
|
||||
2. 失败后自动发送验证码并重试
|
||||
3. 等待 200ms 后重新登录
|
||||
|
||||
### Q: 商品详情 404 率高怎么办?
|
||||
|
||||
**A:** 工具已自动修复:
|
||||
- 启动时从 `/api/listings` 预加载可用商品 ID
|
||||
- 自动使用真实存在的商品 ID 进行测试
|
||||
|
||||
### Q: 如何提高成功率?
|
||||
|
||||
**A:**
|
||||
1. 增加 `--warmup` 参数生成更多 token
|
||||
2. 降低并发数 `-c`
|
||||
3. 检查数据是否正常生成
|
||||
|
||||
### Q: 梯度压测的作用是什么?
|
||||
|
||||
**A:**
|
||||
- 逐步增加负载,观察系统性能变化
|
||||
- 找到系统性能拐点和极限
|
||||
- 避免冷启动导致的误判
|
||||
|
||||
---
|
||||
|
||||
## 下一步
|
||||
|
||||
1. **执行完整压测**:100-200并发,持续5-10分钟
|
||||
2. **性能调优**:根据慢查询日志优化索引
|
||||
3. **容量规划**:根据压测结果评估单机承载能力
|
||||
4. **监控集成**:接入 Prometheus + Grafana
|
||||
|
||||
---
|
||||
|
||||
## 参考文档
|
||||
|
||||
- 详细技术指南:`docs/stress-test-guide.md`
|
||||
- 项目架构分析:`docs/项目架构分析报告.md`
|
||||
- API 文档:`docs/api.md`
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-06-06
|
||||
**维护人**:Claude Opus 4.8
|
||||
@@ -1,636 +0,0 @@
|
||||
# 提现功能 API 文档
|
||||
|
||||
## 目录
|
||||
- [收款账号管理 API](#收款账号管理-api)
|
||||
- [提现申请 API (用户端)](#提现申请-api-用户端)
|
||||
- [提现管理 API (管理员端)](#提现管理-api-管理员端)
|
||||
|
||||
---
|
||||
|
||||
## 收款账号管理 API
|
||||
|
||||
### 1. 查询收款账号列表
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/payment-accounts?page=1&page_size=20
|
||||
Authorization: Bearer {user_token}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 123,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "138****5678",
|
||||
"bank_name": "",
|
||||
"bank_branch": "",
|
||||
"certificate_urls": ["https://..."],
|
||||
"is_default": true,
|
||||
"status": "active",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:00:00Z"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 查询收款账号详情
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/payment-accounts/:id
|
||||
Authorization: Bearer {user_token}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"user_id": 123,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "138****5678",
|
||||
"bank_name": "",
|
||||
"bank_branch": "",
|
||||
"certificate_urls": ["https://..."],
|
||||
"is_default": true,
|
||||
"status": "active",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 添加收款账号
|
||||
|
||||
**请求**
|
||||
```
|
||||
POST /api/payment-accounts
|
||||
Authorization: Bearer {user_token}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"account_type": "alipay", // alipay | wechat | bank
|
||||
"account_name": "张三", // 必须与实名认证姓名一致
|
||||
"account_no": "13812345678", // 支付宝账号/微信号/银行卡号
|
||||
"bank_name": "中国工商银行", // 银行卡必填
|
||||
"bank_branch": "北京分行", // 银行卡可选
|
||||
"certificate_urls": [ // 凭证截图(可选)
|
||||
"https://..."
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"user_id": 123,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "138****5678",
|
||||
"is_default": false,
|
||||
"status": "active",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误响应**
|
||||
```json
|
||||
{
|
||||
"code": 40001,
|
||||
"message": "账户名必须与实名认证姓名一致"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 40002,
|
||||
"message": "请先完成实名认证"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 40003,
|
||||
"message": "收款账号数量已达上限(最多5个)"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 更新收款账号
|
||||
|
||||
**请求**
|
||||
```
|
||||
PUT /api/payment-accounts/:id
|
||||
Authorization: Bearer {user_token}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"bank_branch": "北京朝阳支行",
|
||||
"certificate_urls": ["https://..."]
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"account_type": "bank",
|
||||
"account_name": "张三",
|
||||
"account_no": "6222****1234",
|
||||
"bank_name": "中国工商银行",
|
||||
"bank_branch": "北京朝阳支行",
|
||||
"is_default": false,
|
||||
"status": "active",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:05:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 删除收款账号
|
||||
|
||||
**请求**
|
||||
```
|
||||
DELETE /api/payment-accounts/:id
|
||||
Authorization: Bearer {user_token}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"deleted": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 设置默认收款账号
|
||||
|
||||
**请求**
|
||||
```
|
||||
POST /api/payment-accounts/:id/set-default
|
||||
Authorization: Bearer {user_token}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"updated": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 提现申请 API (用户端)
|
||||
|
||||
### 1. 创建提现申请
|
||||
|
||||
**请求**
|
||||
```
|
||||
POST /api/withdrawals
|
||||
Authorization: Bearer {user_token}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"payment_account_id": 1,
|
||||
"amount": 100.00
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"user_id": 123,
|
||||
"amount": 100.00,
|
||||
"fee": 0.00,
|
||||
"actual_amount": 100.00,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "138****5678",
|
||||
"bank_name": "",
|
||||
"status": "pending",
|
||||
"review_remark": "",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:00:00Z",
|
||||
"reviewed_at": null,
|
||||
"paid_at": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误响应**
|
||||
```json
|
||||
{
|
||||
"code": 40001,
|
||||
"message": "提现金额低于最小限额"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 40002,
|
||||
"message": "提现金额超过最大限额"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 40003,
|
||||
"message": "余额不足"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 查询提现列表
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/withdrawals?page=1&page_size=20
|
||||
Authorization: Bearer {user_token}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"user_id": 123,
|
||||
"amount": 100.00,
|
||||
"fee": 0.00,
|
||||
"actual_amount": 100.00,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "138****5678",
|
||||
"bank_name": "",
|
||||
"status": "completed",
|
||||
"review_remark": "审核通过",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:30:00Z",
|
||||
"reviewed_at": "2026-06-06T10:10:00Z",
|
||||
"paid_at": "2026-06-06T10:30:00Z"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 查询提现详情
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/withdrawals/:id
|
||||
Authorization: Bearer {user_token}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"user_id": 123,
|
||||
"amount": 100.00,
|
||||
"fee": 0.00,
|
||||
"actual_amount": 100.00,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "138****5678",
|
||||
"bank_name": "",
|
||||
"status": "processing",
|
||||
"review_remark": "审核通过",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:10:00Z",
|
||||
"reviewed_at": "2026-06-06T10:10:00Z",
|
||||
"paid_at": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 取消提现申请
|
||||
|
||||
**请求**
|
||||
```
|
||||
POST /api/withdrawals/:id/cancel
|
||||
Authorization: Bearer {user_token}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"cancelled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误响应**
|
||||
```json
|
||||
{
|
||||
"code": 40001,
|
||||
"message": "提现申请状态已锁定,无法操作"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 提现管理 API (管理员端)
|
||||
|
||||
### 1. 查询提现列表
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/admin/withdrawals?status=pending&page=1&page_size=20
|
||||
Authorization: Bearer {admin_token}
|
||||
X-Required-Permission: withdrawal:list
|
||||
```
|
||||
|
||||
**查询参数**
|
||||
- `status`: 状态筛选 (pending | processing | completed | rejected | cancelled)
|
||||
- `user_id`: 用户ID筛选
|
||||
- `page`: 页码
|
||||
- `page_size`: 每页数量
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"user_id": 123,
|
||||
"user_nickname": "用户昵称",
|
||||
"user_phone": "138****5678",
|
||||
"amount": 100.00,
|
||||
"fee": 0.00,
|
||||
"actual_amount": 100.00,
|
||||
"payment_account_id": 1,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "13812345678", // 管理员可见完整账号
|
||||
"bank_name": "",
|
||||
"bank_branch": "",
|
||||
"status": "pending",
|
||||
"reviewed_by": null,
|
||||
"reviewed_by_name": "",
|
||||
"reviewed_at": null,
|
||||
"review_remark": "",
|
||||
"paid_by": null,
|
||||
"paid_by_name": "",
|
||||
"paid_at": null,
|
||||
"payment_proof_url": "",
|
||||
"payment_remark": "",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:00:00Z"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 查询提现详情
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/admin/withdrawals/:id
|
||||
Authorization: Bearer {admin_token}
|
||||
X-Required-Permission: withdrawal:detail
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"user_id": 123,
|
||||
"user_nickname": "用户昵称",
|
||||
"user_phone": "13812345678",
|
||||
"amount": 100.00,
|
||||
"fee": 0.00,
|
||||
"actual_amount": 100.00,
|
||||
"payment_account_id": 1,
|
||||
"account_type": "alipay",
|
||||
"account_name": "张三",
|
||||
"account_no": "13812345678",
|
||||
"bank_name": "",
|
||||
"bank_branch": "",
|
||||
"status": "pending",
|
||||
"reviewed_by": null,
|
||||
"reviewed_by_name": "",
|
||||
"reviewed_at": null,
|
||||
"review_remark": "",
|
||||
"paid_by": null,
|
||||
"paid_by_name": "",
|
||||
"paid_at": null,
|
||||
"payment_proof_url": "",
|
||||
"payment_remark": "",
|
||||
"created_at": "2026-06-06T10:00:00Z",
|
||||
"updated_at": "2026-06-06T10:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 审核提现申请
|
||||
|
||||
**请求**
|
||||
```
|
||||
POST /api/admin/withdrawals/:id/review
|
||||
Authorization: Bearer {admin_token}
|
||||
X-Required-Permission: withdrawal:review
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"approved": true,
|
||||
"remark": "审核通过"
|
||||
}
|
||||
```
|
||||
|
||||
**审核通过响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"status": "processing",
|
||||
"reviewed_by": 10,
|
||||
"reviewed_by_name": "财务管理员",
|
||||
"reviewed_at": "2026-06-06T10:10:00Z",
|
||||
"review_remark": "审核通过",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**审核拒绝请求**
|
||||
```json
|
||||
{
|
||||
"approved": false,
|
||||
"remark": "账号信息不符"
|
||||
}
|
||||
```
|
||||
|
||||
**审核拒绝响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"status": "rejected",
|
||||
"reviewed_by": 10,
|
||||
"reviewed_by_name": "财务管理员",
|
||||
"reviewed_at": "2026-06-06T10:10:00Z",
|
||||
"review_remark": "账号信息不符",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 确认打款
|
||||
|
||||
**请求**
|
||||
```
|
||||
POST /api/admin/withdrawals/:id/confirm-payment
|
||||
Authorization: Bearer {admin_token}
|
||||
X-Required-Permission: withdrawal:pay
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"payment_proof_url": "https://storage.example.com/proofs/proof_123.jpg",
|
||||
"remark": "已通过支付宝转账"
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"withdraw_no": "WD17362512001a2b3c4d",
|
||||
"status": "completed",
|
||||
"paid_by": 10,
|
||||
"paid_by_name": "财务管理员",
|
||||
"paid_at": "2026-06-06T10:30:00Z",
|
||||
"payment_proof_url": "https://storage.example.com/proofs/proof_123.jpg",
|
||||
"payment_remark": "已通过支付宝转账",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 状态说明
|
||||
|
||||
### 提现状态 (status)
|
||||
|
||||
| 状态 | 说明 | 允许操作 |
|
||||
|------|------|---------|
|
||||
| `pending` | 待审核 | 用户可取消、管理员可审核 |
|
||||
| `processing` | 处理中 | 管理员可确认打款 |
|
||||
| `completed` | 已完成 | 无 |
|
||||
| `rejected` | 已拒绝 | 无 |
|
||||
| `cancelled` | 已取消 | 无 |
|
||||
|
||||
### 账号类型 (account_type)
|
||||
|
||||
| 类型 | 说明 |
|
||||
|------|------|
|
||||
| `alipay` | 支付宝 |
|
||||
| `wechat` | 微信 |
|
||||
| `bank` | 银行卡 |
|
||||
|
||||
---
|
||||
|
||||
## 错误码说明
|
||||
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| 40001 | 请求参数错误 |
|
||||
| 40002 | 实名认证未通过 |
|
||||
| 40003 | 账号数量限制 |
|
||||
| 40004 | 提现金额错误 |
|
||||
| 40005 | 余额不足 |
|
||||
| 40006 | 状态锁定 |
|
||||
| 40401 | 未找到资源 |
|
||||
| 40301 | 未授权 |
|
||||
| 50001 | 服务器错误 |
|
||||
|
||||
---
|
||||
|
||||
## 接口权限说明
|
||||
|
||||
### 用户端接口
|
||||
所有用户端接口需要携带用户 Token (`Authorization: Bearer {user_token}`)
|
||||
|
||||
### 管理员端接口
|
||||
所有管理员端接口需要:
|
||||
1. 携带管理员 Token (`Authorization: Bearer {admin_token}`)
|
||||
2. 拥有对应的权限
|
||||
|
||||
#### 提现管理权限列表
|
||||
- `withdrawal:list` - 查看提现申请列表
|
||||
- `withdrawal:detail` - 查看提现详情
|
||||
- `withdrawal:review` - 审核提现申请
|
||||
- `withdrawal:pay` - 确认打款
|
||||
|
||||
**财务角色 (finance)** 默认拥有以上所有权限。
|
||||
@@ -1,365 +0,0 @@
|
||||
# 提现功能前端开发完成总结
|
||||
|
||||
## 🎉 已完成的工作
|
||||
|
||||
### 1. API 接口层(✅ 完成)
|
||||
|
||||
#### 文件:`frontend/src/features/wallet/api/withdrawal.ts`
|
||||
- ✅ 收款账号管理 API(6个接口)
|
||||
- fetchPaymentAccounts - 获取收款账号列表
|
||||
- fetchPaymentAccount - 获取单个收款账号
|
||||
- createPaymentAccount - 创建收款账号
|
||||
- updatePaymentAccount - 更新收款账号
|
||||
- deletePaymentAccount - 删除收款账号
|
||||
- setDefaultPaymentAccount - 设置默认账号
|
||||
|
||||
- ✅ 提现申请 API(4个接口)
|
||||
- createWithdrawal - 创建提现申请
|
||||
- fetchWithdrawals - 获取提现列表
|
||||
- fetchWithdrawal - 获取单个提现详情
|
||||
- cancelWithdrawal - 取消提现
|
||||
|
||||
#### 文件:`frontend/src/features/admin/api/adminWithdrawal.ts`
|
||||
- ✅ 管理员端提现管理 API(4个接口)
|
||||
- fetchAdminWithdrawals - 获取提现列表(支持筛选)
|
||||
- fetchAdminWithdrawal - 获取提现详情
|
||||
- reviewWithdrawal - 审核提现
|
||||
- confirmPayment - 确认打款
|
||||
|
||||
### 2. 用户端页面(✅ 完成)
|
||||
|
||||
#### 收款账号管理页面
|
||||
**文件**:`frontend/src/features/wallet/views/PaymentAccountsView.vue`
|
||||
|
||||
**功能**:
|
||||
- ✅ 卡片式展示收款账号列表
|
||||
- ✅ 支持三种账号类型(支付宝、微信、银行卡)
|
||||
- ✅ 显示默认账号标识
|
||||
- ✅ 账号脱敏显示
|
||||
- ✅ 设置默认账号
|
||||
- ✅ 编辑账号(仅部分字段)
|
||||
- ✅ 删除账号
|
||||
- ✅ 添加新账号
|
||||
- ✅ 数量限制提示(最多5个)
|
||||
|
||||
#### 提现申请页面
|
||||
**文件**:`frontend/src/features/wallet/views/WithdrawalView.vue`
|
||||
|
||||
**功能**:
|
||||
- ✅ 显示钱包余额(可用余额、冻结余额)
|
||||
- ✅ 提现表单
|
||||
- 选择收款账号(下拉选择)
|
||||
- 输入提现金额
|
||||
- 实时计算到账金额
|
||||
- 金额验证(最低10元,最高5000元)
|
||||
- 余额不足提示
|
||||
- ✅ 提现说明展示
|
||||
- ✅ 提现记录列表
|
||||
- 显示提现状态
|
||||
- 取消待审核的提现
|
||||
- 分页显示
|
||||
- ✅ 无收款账号时引导添加
|
||||
|
||||
#### 收款账号编辑对话框
|
||||
**文件**:`frontend/src/features/wallet/components/PaymentAccountDialog.vue`
|
||||
|
||||
**功能**:
|
||||
- ✅ 新建/编辑收款账号
|
||||
- ✅ 账号类型选择(支付宝/微信/银行卡)
|
||||
- ✅ 银行卡特有字段(银行名称、开户支行)
|
||||
- ✅ 实名验证提示
|
||||
- ✅ 上传凭证(占位,待集成文件上传)
|
||||
- ✅ 表单验证
|
||||
|
||||
### 3. 管理员端页面(✅ 完成)
|
||||
|
||||
#### 提现审核页面
|
||||
**文件**:`frontend/src/features/admin/views/AdminWithdrawalsView.vue`
|
||||
|
||||
**功能**:
|
||||
- ✅ 提现列表展示
|
||||
- 显示用户信息(昵称、手机号)
|
||||
- 显示金额信息
|
||||
- 显示收款账号信息(完整账号)
|
||||
- 显示状态标签
|
||||
- ✅ 筛选功能
|
||||
- 按状态筛选
|
||||
- 按用户ID筛选
|
||||
- ✅ 操作按钮
|
||||
- 查看详情
|
||||
- 通过审核(pending状态)
|
||||
- 拒绝审核(pending状态)
|
||||
- 确认打款(processing状态)
|
||||
- ✅ 分页功能
|
||||
- ✅ 刷新按钮
|
||||
|
||||
#### 提现详情对话框
|
||||
**文件**:`frontend/src/features/admin/components/WithdrawalDetailDialog.vue`
|
||||
|
||||
**功能**:
|
||||
- ✅ 完整的提现信息展示
|
||||
- 基本信息(单号、状态、时间)
|
||||
- 用户信息(ID、昵称、手机)
|
||||
- 金额信息(提现金额、手续费、实际到账)
|
||||
- 收款账号信息(完整账号,管理员可见)
|
||||
- 审核信息(审核人、时间、备注)
|
||||
- 打款信息(打款人、时间、备注、凭证)
|
||||
- ✅ 操作按钮
|
||||
- 通过审核
|
||||
- 拒绝审核
|
||||
- 确认打款
|
||||
- ✅ 操作提示
|
||||
- ✅ 状态标识
|
||||
|
||||
### 4. 路由配置(✅ 完成)
|
||||
|
||||
#### 用户端路由
|
||||
**文件**:`frontend/src/router/accountRoutes.ts`
|
||||
|
||||
```typescript
|
||||
/wallet/payment-accounts → PaymentAccountsView(收款账号管理)
|
||||
/wallet/withdrawal → WithdrawalView(提现申请)
|
||||
```
|
||||
|
||||
#### 管理员端路由
|
||||
**文件**:`frontend/src/router/adminRoutes.ts`
|
||||
|
||||
```typescript
|
||||
/admin/withdrawals → AdminWithdrawalsView(提现审核)
|
||||
```
|
||||
|
||||
### 5. 模块导出(✅ 完成)
|
||||
|
||||
**文件**:`frontend/src/features/wallet/index.ts`
|
||||
|
||||
已更新导出配置,包含提现相关的 API 和类型。
|
||||
|
||||
---
|
||||
|
||||
## 📋 功能特性
|
||||
|
||||
### 用户端特性
|
||||
1. **收款账号管理**
|
||||
- 支持 3 种账号类型
|
||||
- 账号加密存储(后端)
|
||||
- 账号脱敏显示
|
||||
- 实名验证
|
||||
- 默认账号管理
|
||||
- 最多 5 个账号
|
||||
|
||||
2. **提现申请**
|
||||
- 实时余额显示
|
||||
- 金额限制提示
|
||||
- 手续费计算
|
||||
- 收款账号选择
|
||||
- 提现状态跟踪
|
||||
- 取消待审核提现
|
||||
|
||||
3. **用户体验**
|
||||
- 响应式设计
|
||||
- 友好的错误提示
|
||||
- 加载状态展示
|
||||
- 确认对话框
|
||||
- 引导式交互
|
||||
|
||||
### 管理员端特性
|
||||
1. **提现审核**
|
||||
- 多条件筛选
|
||||
- 完整信息展示
|
||||
- 快速审核操作
|
||||
- 批注功能
|
||||
|
||||
2. **打款确认**
|
||||
- 详细的收款信息
|
||||
- 打款备注
|
||||
- 凭证上传(待实现)
|
||||
- 操作记录
|
||||
|
||||
3. **数据展示**
|
||||
- 完整账号可见
|
||||
- 用户信息展示
|
||||
- 操作历史追踪
|
||||
- 状态流转清晰
|
||||
|
||||
---
|
||||
|
||||
## 🎨 UI/UX 设计
|
||||
|
||||
### 设计特点
|
||||
1. **卡片式布局** - 收款账号以卡片形式展示,清晰直观
|
||||
2. **状态标签** - 使用不同颜色区分提现状态
|
||||
3. **响应式设计** - 适配不同屏幕尺寸
|
||||
4. **友好提示** - 充分的操作提示和帮助信息
|
||||
5. **统一风格** - 与项目整体设计保持一致
|
||||
|
||||
### 颜色规范
|
||||
- 支付宝:蓝色 (#1677ff)
|
||||
- 微信:绿色 (#07c160)
|
||||
- 银行卡:橙色 (#ff6a00)
|
||||
- 待审核:警告黄 (warning)
|
||||
- 处理中:主题蓝 (primary)
|
||||
- 已完成:成功绿 (success)
|
||||
- 已拒绝:危险红 (danger)
|
||||
- 已取消:灰色 (info)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 业务流程
|
||||
|
||||
### 用户提现流程
|
||||
```
|
||||
1. 用户登录
|
||||
↓
|
||||
2. 进入钱包页面
|
||||
↓
|
||||
3. 点击"提现"
|
||||
↓
|
||||
4. 添加收款账号(如果没有)
|
||||
↓
|
||||
5. 选择收款账号
|
||||
↓
|
||||
6. 输入提现金额
|
||||
↓
|
||||
7. 确认提交
|
||||
↓
|
||||
8. 查看提现记录
|
||||
```
|
||||
|
||||
### 管理员审核流程
|
||||
```
|
||||
1. 管理员登录
|
||||
↓
|
||||
2. 进入提现管理页面
|
||||
↓
|
||||
3. 筛选待审核提现
|
||||
↓
|
||||
4. 查看详情
|
||||
↓
|
||||
5. 审核(通过/拒绝)
|
||||
↓
|
||||
6. 如果通过:手动转账
|
||||
↓
|
||||
7. 上传凭证(可选)
|
||||
↓
|
||||
8. 确认打款完成
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 待完善功能
|
||||
|
||||
### 1. 文件上传集成
|
||||
- [ ] PaymentAccountDialog 中的凭证上传
|
||||
- [ ] WithdrawalDetailDialog 中的打款凭证上传
|
||||
- 需要集成项目的文件上传组件
|
||||
|
||||
### 2. 移动端适配
|
||||
- [ ] 创建移动端版本的页面
|
||||
- [ ] 响应式布局优化
|
||||
|
||||
### 3. 实时通知
|
||||
- [ ] 提现状态变更通知
|
||||
- [ ] WebSocket 实时推送
|
||||
|
||||
### 4. 更多功能
|
||||
- [ ] 提现记录导出
|
||||
- [ ] 批量审核
|
||||
- [ ] 统计报表
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试建议
|
||||
|
||||
### 用户端测试
|
||||
1. **收款账号管理**
|
||||
- [ ] 添加支付宝账号
|
||||
- [ ] 添加微信账号
|
||||
- [ ] 添加银行卡账号
|
||||
- [ ] 测试账号数量限制(5个)
|
||||
- [ ] 设置默认账号
|
||||
- [ ] 编辑账号信息
|
||||
- [ ] 删除账号
|
||||
|
||||
2. **提现申请**
|
||||
- [ ] 测试金额验证(最低10元)
|
||||
- [ ] 测试金额验证(最高5000元)
|
||||
- [ ] 测试余额不足提示
|
||||
- [ ] 测试提现成功
|
||||
- [ ] 测试取消提现
|
||||
- [ ] 测试无收款账号提示
|
||||
|
||||
### 管理员端测试
|
||||
1. **提现审核**
|
||||
- [ ] 测试列表加载
|
||||
- [ ] 测试状态筛选
|
||||
- [ ] 测试用户ID筛选
|
||||
- [ ] 测试审核通过
|
||||
- [ ] 测试审核拒绝
|
||||
- [ ] 测试确认打款
|
||||
|
||||
2. **权限测试**
|
||||
- [ ] 测试非财务角色无法访问
|
||||
- [ ] 测试财务角色正常访问
|
||||
|
||||
---
|
||||
|
||||
## 📝 使用说明
|
||||
|
||||
### 开发环境运行
|
||||
```bash
|
||||
# 确保后端已启动
|
||||
cd /Users/yml/codes/hfb_sys
|
||||
./scripts/dev.sh
|
||||
|
||||
# 访问前端
|
||||
# 用户端:http://localhost:5173/wallet/payment-accounts
|
||||
# 管理端:http://localhost:5173/admin/withdrawals
|
||||
```
|
||||
|
||||
### 前端页面访问
|
||||
**用户端**:
|
||||
- 收款账号管理:`/wallet/payment-accounts`
|
||||
- 提现申请:`/wallet/withdrawal`
|
||||
|
||||
**管理员端**:
|
||||
- 提现审核:`/admin/withdrawals`
|
||||
|
||||
---
|
||||
|
||||
## 🎯 总结
|
||||
|
||||
✅ **前端开发已完成**
|
||||
|
||||
已完成的功能:
|
||||
1. ✅ 完整的 API 接口层
|
||||
2. ✅ 用户端收款账号管理页面
|
||||
3. ✅ 用户端提现申请页面
|
||||
4. ✅ 管理员端提现审核页面
|
||||
5. ✅ 所有必要的组件和对话框
|
||||
6. ✅ 路由配置
|
||||
7. ✅ TypeScript 类型定义
|
||||
|
||||
**系统现在具备完整的手动提现功能**,包括:
|
||||
- 用户添加收款账号
|
||||
- 用户发起提现申请
|
||||
- 财务审核提现
|
||||
- 财务确认打款
|
||||
- 完整的状态流转
|
||||
|
||||
**下一步**:
|
||||
1. 集成文件上传功能
|
||||
2. 完整的端到端测试
|
||||
3. 移动端页面开发(可选)
|
||||
4. 生产环境部署
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [后端实施总结](../../docs/提现功能实施总结.md)
|
||||
- [API 文档](../../docs/提现功能API文档.md)
|
||||
|
||||
---
|
||||
|
||||
**开发完成时间**:2026-06-06
|
||||
**开发状态**:✅ 已完成并可用
|
||||
@@ -1,414 +0,0 @@
|
||||
# 🎉 提现功能完整实施总结
|
||||
|
||||
## 项目概述
|
||||
|
||||
**功能名称**:手动提现功能
|
||||
**实施日期**:2026-06-06
|
||||
**实施状态**:✅ 已完成
|
||||
**版本**:v1.0
|
||||
|
||||
---
|
||||
|
||||
## ✅ 实施完成情况
|
||||
|
||||
### 后端开发(100% 完成)
|
||||
|
||||
#### 1. 数据库设计 ✅
|
||||
- [x] 创建 `user_payment_accounts` 表(用户收款账号)
|
||||
- [x] 创建 `withdrawal_requests` 表(提现申请)
|
||||
- [x] 添加提现相关权限(4个)
|
||||
- [x] 创建财务管理员角色
|
||||
- [x] 数据模型定义
|
||||
|
||||
#### 2. 业务模块 ✅
|
||||
- [x] **收款账号管理模块** (`paymentaccount`)
|
||||
- Service 层、Repository 层、Handler 层
|
||||
- AES 加密存储
|
||||
- 账号脱敏
|
||||
- 实名验证
|
||||
- 默认账号管理
|
||||
|
||||
- [x] **提现申请模块** (`withdrawal`)
|
||||
- Service 层、Repository 层、Handler 层
|
||||
- 创建提现申请
|
||||
- 审核流程
|
||||
- 打款确认
|
||||
- 钱包流水集成
|
||||
|
||||
#### 3. API 接口 ✅
|
||||
- [x] 用户端 API(10个接口)
|
||||
- 收款账号管理(6个)
|
||||
- 提现申请(4个)
|
||||
|
||||
- [x] 管理员端 API(4个接口)
|
||||
- 提现列表和详情
|
||||
- 审核提现
|
||||
- 确认打款
|
||||
|
||||
#### 4. 路由配置 ✅
|
||||
- [x] 注册所有 API 路由
|
||||
- [x] 配置权限验证
|
||||
- [x] 编译测试通过
|
||||
|
||||
---
|
||||
|
||||
### 前端开发(100% 完成)
|
||||
|
||||
#### 1. API 接口层 ✅
|
||||
- [x] `wallet/api/withdrawal.ts` - 用户端 API
|
||||
- [x] `admin/api/adminWithdrawal.ts` - 管理员端 API
|
||||
- [x] TypeScript 类型定义
|
||||
|
||||
#### 2. 用户端页面 ✅
|
||||
- [x] **收款账号管理页面** (`PaymentAccountsView.vue`)
|
||||
- 卡片式展示
|
||||
- 增删改查
|
||||
- 默认账号管理
|
||||
|
||||
- [x] **提现申请页面** (`WithdrawalView.vue`)
|
||||
- 余额显示
|
||||
- 提现表单
|
||||
- 提现记录
|
||||
- 取消提现
|
||||
|
||||
- [x] **收款账号对话框** (`PaymentAccountDialog.vue`)
|
||||
- 新建/编辑
|
||||
- 表单验证
|
||||
- 实名提示
|
||||
|
||||
#### 3. 管理员端页面 ✅
|
||||
- [x] **提现审核页面** (`AdminWithdrawalsView.vue`)
|
||||
- 列表展示
|
||||
- 筛选功能
|
||||
- 审核操作
|
||||
|
||||
- [x] **提现详情对话框** (`WithdrawalDetailDialog.vue`)
|
||||
- 完整信息展示
|
||||
- 审核操作
|
||||
- 打款确认
|
||||
|
||||
#### 4. 路由配置 ✅
|
||||
- [x] 注册用户端路由(2个)
|
||||
- [x] 注册管理员端路由(1个)
|
||||
- [x] 编译测试通过
|
||||
|
||||
---
|
||||
|
||||
## 📊 功能统计
|
||||
|
||||
### 代码统计
|
||||
| 类别 | 文件数 | 说明 |
|
||||
|------|--------|------|
|
||||
| 后端模型 | 2 | withdrawal.go, payment_account.go |
|
||||
| 后端模块 | 8 | service, repository, handler, dto (×2) |
|
||||
| 前端 API | 2 | withdrawal.ts, adminWithdrawal.ts |
|
||||
| 前端页面 | 4 | 用户端3个,管理端1个 |
|
||||
| 前端组件 | 1 | WithdrawalDetailDialog.vue |
|
||||
| 数据库迁移 | 1 | 000002_add_withdrawal_tables.sql |
|
||||
| 文档 | 4 | 实施总结、API文档、前端总结、测试清单 |
|
||||
| **总计** | **22** | - |
|
||||
|
||||
### API 接口统计
|
||||
| 类型 | 数量 | 说明 |
|
||||
|------|------|------|
|
||||
| 用户端 - 收款账号 | 6 | 增删改查、设置默认 |
|
||||
| 用户端 - 提现 | 4 | 创建、查询、取消 |
|
||||
| 管理端 - 提现 | 4 | 列表、详情、审核、打款 |
|
||||
| **总计** | **14** | - |
|
||||
|
||||
### 数据库对象
|
||||
| 类型 | 数量 | 说明 |
|
||||
|------|------|------|
|
||||
| 数据表 | 2 | user_payment_accounts, withdrawal_requests |
|
||||
| 权限 | 5 | withdrawal:*, wallet:admin_ledger |
|
||||
| 角色 | 1 | finance(财务管理员) |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心功能
|
||||
|
||||
### 用户端功能
|
||||
1. ✅ **收款账号管理**
|
||||
- 支持支付宝、微信、银行卡
|
||||
- AES 加密存储
|
||||
- 账号脱敏显示
|
||||
- 实名验证
|
||||
- 默认账号
|
||||
- 最多5个
|
||||
|
||||
2. ✅ **提现申请**
|
||||
- 选择收款账号
|
||||
- 金额限制(10-5000元)
|
||||
- 手续费计算(当前0%)
|
||||
- 余额验证
|
||||
- 状态跟踪
|
||||
- 取消功能
|
||||
|
||||
### 管理员端功能
|
||||
1. ✅ **提现审核**
|
||||
- 列表查询
|
||||
- 状态筛选
|
||||
- 用户筛选
|
||||
- 通过/拒绝审核
|
||||
- 备注记录
|
||||
|
||||
2. ✅ **打款确认**
|
||||
- 完整账号查看
|
||||
- 打款备注
|
||||
- 凭证上传(待实现)
|
||||
- 状态更新
|
||||
|
||||
### 钱包集成
|
||||
1. ✅ **余额管理**
|
||||
- 提现冻结
|
||||
- 审核拒绝解冻
|
||||
- 用户取消解冻
|
||||
- 打款完成扣除
|
||||
|
||||
2. ✅ **流水记录**
|
||||
- withdraw_freeze
|
||||
- withdraw_reject
|
||||
- withdraw_cancel
|
||||
- withdraw_complete
|
||||
|
||||
---
|
||||
|
||||
## 🔐 安全措施
|
||||
|
||||
1. ✅ **账号加密** - AES-256 加密存储
|
||||
2. ✅ **实名验证** - 账户名必须与实名一致
|
||||
3. ✅ **账号脱敏** - 用户端仅显示脱敏信息
|
||||
4. ✅ **权限控制** - 财务角色专用权限
|
||||
5. ✅ **金额限制** - 单笔限额10-5000元
|
||||
6. ✅ **状态锁定** - 审核后无法随意修改
|
||||
7. ✅ **快照机制** - 提现申请保存账号快照
|
||||
|
||||
---
|
||||
|
||||
## 📁 文件清单
|
||||
|
||||
### 后端文件
|
||||
```
|
||||
backend/
|
||||
├── migrations/
|
||||
│ └── 000002_add_withdrawal_tables.sql
|
||||
├── internal/
|
||||
│ ├── model/
|
||||
│ │ ├── payment_account.go
|
||||
│ │ └── withdrawal.go
|
||||
│ ├── modules/
|
||||
│ │ ├── paymentaccount/
|
||||
│ │ │ ├── service.go
|
||||
│ │ │ ├── repository.go
|
||||
│ │ │ ├── handler.go
|
||||
│ │ │ └── dto.go
|
||||
│ │ └── withdrawal/
|
||||
│ │ ├── service.go
|
||||
│ │ ├── repository.go
|
||||
│ │ ├── handler.go
|
||||
│ │ └── dto.go
|
||||
│ └── router/
|
||||
│ └── router.go (已更新)
|
||||
```
|
||||
|
||||
### 前端文件
|
||||
```
|
||||
frontend/src/
|
||||
├── features/
|
||||
│ ├── wallet/
|
||||
│ │ ├── api/
|
||||
│ │ │ └── withdrawal.ts
|
||||
│ │ ├── views/
|
||||
│ │ │ ├── PaymentAccountsView.vue
|
||||
│ │ │ └── WithdrawalView.vue
|
||||
│ │ ├── components/
|
||||
│ │ │ └── PaymentAccountDialog.vue
|
||||
│ │ └── index.ts (已更新)
|
||||
│ └── admin/
|
||||
│ ├── api/
|
||||
│ │ └── adminWithdrawal.ts
|
||||
│ ├── views/
|
||||
│ │ └── AdminWithdrawalsView.vue
|
||||
│ └── components/
|
||||
│ └── WithdrawalDetailDialog.vue
|
||||
└── router/
|
||||
├── accountRoutes.ts (已更新)
|
||||
└── adminRoutes.ts (已更新)
|
||||
```
|
||||
|
||||
### 文档文件
|
||||
```
|
||||
docs/
|
||||
├── 提现功能实施总结.md
|
||||
├── 提现功能API文档.md
|
||||
├── 提现功能前端开发总结.md
|
||||
└── 提现功能测试清单.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 业务流程
|
||||
|
||||
### 完整提现流程
|
||||
```
|
||||
用户端:
|
||||
1. 添加收款账号(需实名认证)
|
||||
2. 选择收款账号
|
||||
3. 输入提现金额
|
||||
4. 提交申请
|
||||
5. 系统冻结余额
|
||||
6. 等待审核
|
||||
|
||||
管理员端:
|
||||
7. 查看待审核列表
|
||||
8. 审核通过
|
||||
9. 手动转账到用户账号
|
||||
10. 上传打款凭证(可选)
|
||||
11. 确认打款完成
|
||||
|
||||
系统:
|
||||
12. 扣除冻结余额
|
||||
13. 记录流水
|
||||
14. 状态变更为"已完成"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 生产环境部署前必做
|
||||
|
||||
1. **修改加密密钥** ⚠️
|
||||
```go
|
||||
// backend/internal/modules/paymentaccount/repository.go
|
||||
const encryptionKey = "your-32-byte-secret-key-here!!"
|
||||
```
|
||||
建议从环境变量读取
|
||||
|
||||
2. **执行数据库迁移**
|
||||
```bash
|
||||
mysql -u root -p database < backend/migrations/000002_add_withdrawal_tables.sql
|
||||
```
|
||||
|
||||
3. **配置财务管理员**
|
||||
```sql
|
||||
-- 查询 finance 角色ID
|
||||
SELECT id FROM roles WHERE code = 'finance';
|
||||
|
||||
-- 分配角色
|
||||
INSERT INTO admin_user_roles (admin_user_id, role_id)
|
||||
VALUES (管理员ID, 财务角色ID);
|
||||
```
|
||||
|
||||
4. **配置限额**(可选)
|
||||
```go
|
||||
// backend/internal/modules/withdrawal/service.go
|
||||
const (
|
||||
MinWithdrawalAmount = 10.0
|
||||
MaxWithdrawalAmount = 5000.0
|
||||
WithdrawalFeeRate = 0.0
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试状态
|
||||
|
||||
- [x] 后端编译通过
|
||||
- [x] 前端编译通过
|
||||
- [x] 系统正常启动
|
||||
- [ ] 功能测试(待执行)
|
||||
- [ ] 集成测试(待执行)
|
||||
- [ ] 压力测试(待执行)
|
||||
|
||||
**测试清单**:详见 `docs/提现功能测试清单.md`
|
||||
|
||||
---
|
||||
|
||||
## 🚀 后续优化建议
|
||||
|
||||
### 短期优化
|
||||
1. **文件上传集成** - 凭证上传功能
|
||||
2. **移动端适配** - H5 页面开发
|
||||
3. **实时通知** - WebSocket 状态推送
|
||||
4. **数据导出** - 提现记录导出
|
||||
|
||||
### 中期优化
|
||||
1. **自动化提现** - 小额自动审核
|
||||
2. **批量打款** - 导出批量打款文件
|
||||
3. **提现报表** - 财务统计报表
|
||||
4. **风控规则** - 异常检测
|
||||
|
||||
### 长期优化
|
||||
1. **支付网关对接** - 自动打款
|
||||
2. **银行接口对接** - 企业网银直连
|
||||
3. **实时到账** - T+0 提现
|
||||
4. **多级审批** - 大额提现审批流程
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关资源
|
||||
|
||||
### 文档
|
||||
- [后端实施总结](./提现功能实施总结.md)
|
||||
- [API 接口文档](./提现功能API文档.md)
|
||||
- [前端开发总结](./提现功能前端开发总结.md)
|
||||
- [测试清单](./提现功能测试清单.md)
|
||||
|
||||
### 访问地址
|
||||
**用户端**:
|
||||
- 收款账号管理:http://localhost:5173/wallet/payment-accounts
|
||||
- 提现申请:http://localhost:5173/wallet/withdrawal
|
||||
|
||||
**管理员端**:
|
||||
- 提现审核:http://localhost:5173/admin/withdrawals
|
||||
|
||||
### API 文档
|
||||
- Swagger 文档:http://localhost:8080/swagger/index.html
|
||||
|
||||
---
|
||||
|
||||
## 🎉 项目总结
|
||||
|
||||
### 完成情况
|
||||
✅ **后端开发**:100% 完成
|
||||
✅ **前端开发**:100% 完成
|
||||
✅ **文档编写**:100% 完成
|
||||
⏳ **功能测试**:待执行
|
||||
⏳ **生产部署**:待执行
|
||||
|
||||
### 技术亮点
|
||||
1. **完整的业务流程** - 从申请到打款的完整闭环
|
||||
2. **安全可靠** - 多层次安全措施
|
||||
3. **用户友好** - 清晰的界面和流程引导
|
||||
4. **可扩展性** - 预留自动化升级空间
|
||||
5. **代码质量** - 规范的分层架构
|
||||
|
||||
### 交付物
|
||||
- ✅ 22个代码文件
|
||||
- ✅ 14个 API 接口
|
||||
- ✅ 6个前端页面/组件
|
||||
- ✅ 2张数据表
|
||||
- ✅ 4份完整文档
|
||||
|
||||
---
|
||||
|
||||
## 👏 致谢
|
||||
|
||||
感谢您的信任和支持!
|
||||
|
||||
本项目已完整实现了手动提现功能,包括:
|
||||
- 完整的后端业务逻辑
|
||||
- 友好的前端用户界面
|
||||
- 详尽的文档和测试清单
|
||||
- 规范的代码结构
|
||||
|
||||
系统已具备上线条件,完成测试后即可投入使用。
|
||||
|
||||
如有任何问题或需要进一步的支持,请随时联系。
|
||||
|
||||
---
|
||||
|
||||
**项目状态**:✅ 开发完成,待测试
|
||||
**完成日期**:2026-06-06
|
||||
**版本**:v1.0
|
||||
@@ -1,356 +0,0 @@
|
||||
# 手动提现功能实施完成总结
|
||||
|
||||
## 🎉 已完成的工作
|
||||
|
||||
### 1. 数据库迁移(✅ 完成)
|
||||
|
||||
**文件**: `backend/migrations/000002_add_withdrawal_tables.sql`
|
||||
|
||||
创建了两张新表:
|
||||
|
||||
#### user_payment_accounts (用户收款账号表)
|
||||
- 支持三种账号类型:支付宝 (alipay)、微信 (wechat)、银行卡 (bank)
|
||||
- 账号信息加密存储
|
||||
- 支持上传认证凭证(收款码截图)
|
||||
- 支持设置默认账号
|
||||
- 每个用户最多5个收款账号
|
||||
|
||||
#### withdrawal_requests (提现申请表)
|
||||
- 记录用户提现申请的完整信息
|
||||
- 账号信息快照(防止用户修改收款账号影响已有提现)
|
||||
- 支持手续费计算
|
||||
- 完整的审核流程:pending → processing → completed
|
||||
- 记录审核人、打款人、打款凭证等信息
|
||||
|
||||
#### 权限和角色
|
||||
- 新增 4 个提现相关权限
|
||||
- 新增 `finance` 财务管理员角色
|
||||
- 关联权限到角色
|
||||
|
||||
### 2. 数据模型(✅ 完成)
|
||||
|
||||
**文件**:
|
||||
- `backend/internal/model/payment_account.go` - 收款账号模型
|
||||
- `backend/internal/model/withdrawal.go` - 提现申请模型
|
||||
|
||||
### 3. 收款账号管理模块(✅ 完成)
|
||||
|
||||
**目录**: `backend/internal/modules/paymentaccount/`
|
||||
|
||||
#### 核心功能:
|
||||
- **增删改查**:用户管理自己的收款账号
|
||||
- **实名验证**:账户名必须与实名认证姓名一致
|
||||
- **加密存储**:使用 AES 加密存储账号信息
|
||||
- **脱敏显示**:前端显示时自动脱敏(如:138****5678)
|
||||
- **默认账号**:支持设置默认收款账号
|
||||
- **数量限制**:每个用户最多 5 个收款账号
|
||||
|
||||
**文件**:
|
||||
- `service.go` - 业务逻辑层
|
||||
- `repository.go` - 数据访问层(含加密/解密/脱敏逻辑)
|
||||
- `handler.go` - HTTP 接口处理
|
||||
- `dto.go` - 数据传输对象
|
||||
|
||||
### 4. 提现申请模块(✅ 完成)
|
||||
|
||||
**目录**: `backend/internal/modules/withdrawal/`
|
||||
|
||||
#### 用户端功能:
|
||||
- **创建提现申请**:选择收款账号、输入金额
|
||||
- **查询提现列表**:查看自己的提现记录
|
||||
- **查询提现详情**:查看单个提现申请
|
||||
- **取消提现**:待审核状态可取消
|
||||
|
||||
#### 管理员端功能:
|
||||
- **查询提现列表**:支持按状态、用户筛选
|
||||
- **查询提现详情**:查看完整信息(包括完整账号)
|
||||
- **审核提现**:通过/拒绝提现申请
|
||||
- **确认打款**:上传打款凭证,完成提现
|
||||
|
||||
#### 核心流程:
|
||||
1. **用户申请** → 冻结可用余额 → 创建提现记录(status=pending)
|
||||
2. **财务审核** → 通过(status=processing)/ 拒绝(status=rejected,解冻余额)
|
||||
3. **手动打款** → 上传凭证 → 确认完成(status=completed,扣除冻结余额)
|
||||
|
||||
#### 限额控制:
|
||||
- 最低提现金额:10 元
|
||||
- 最高单笔提现:5000 元
|
||||
- 手续费率:0%(可配置)
|
||||
|
||||
**文件**:
|
||||
- `service.go` - 业务逻辑层
|
||||
- `repository.go` - 数据访问层(含钱包流水集成)
|
||||
- `handler.go` - HTTP 接口处理
|
||||
- `dto.go` - 数据传输对象
|
||||
|
||||
### 5. 路由配置(✅ 完成)
|
||||
|
||||
**文件**: `backend/internal/router/router.go`
|
||||
|
||||
#### 用户端 API:
|
||||
```
|
||||
POST /api/payment-accounts # 添加收款账号
|
||||
GET /api/payment-accounts # 查询收款账号列表
|
||||
GET /api/payment-accounts/:id # 查询收款账号详情
|
||||
PUT /api/payment-accounts/:id # 更新收款账号
|
||||
DELETE /api/payment-accounts/:id # 删除收款账号
|
||||
POST /api/payment-accounts/:id/set-default # 设为默认
|
||||
|
||||
POST /api/withdrawals # 创建提现申请
|
||||
GET /api/withdrawals # 查询提现列表
|
||||
GET /api/withdrawals/:id # 查询提现详情
|
||||
POST /api/withdrawals/:id/cancel # 取消提现
|
||||
```
|
||||
|
||||
#### 管理员端 API:
|
||||
```
|
||||
GET /api/admin/withdrawals # 查询提现列表(需权限:withdrawal:list)
|
||||
GET /api/admin/withdrawals/:id # 查询提现详情(需权限:withdrawal:detail)
|
||||
POST /api/admin/withdrawals/:id/review # 审核提现(需权限:withdrawal:review)
|
||||
POST /api/admin/withdrawals/:id/confirm-payment # 确认打款(需权限:withdrawal:pay)
|
||||
```
|
||||
|
||||
### 6. 钱包模块更新(✅ 完成)
|
||||
|
||||
更新了 `wallet/service.go`,提现功能已迁移到独立的 withdrawal 模块。
|
||||
|
||||
---
|
||||
|
||||
## 📋 数据库表结构
|
||||
|
||||
### user_payment_accounts
|
||||
```sql
|
||||
id BIGINT 主键
|
||||
user_id BIGINT 用户ID
|
||||
account_type VARCHAR(32) 账号类型:alipay/wechat/bank
|
||||
account_name VARCHAR(128) 账户名
|
||||
account_no VARCHAR(255) 账号(加密存储)
|
||||
bank_name VARCHAR(128) 银行名称
|
||||
bank_branch VARCHAR(255) 开户行支行
|
||||
certificate_urls JSON 认证凭证
|
||||
is_default TINYINT 是否默认账号
|
||||
status VARCHAR(32) 状态:active/disabled
|
||||
created_at DATETIME
|
||||
updated_at DATETIME
|
||||
```
|
||||
|
||||
### withdrawal_requests
|
||||
```sql
|
||||
id BIGINT 主键
|
||||
withdraw_no VARCHAR(64) 提现单号(唯一)
|
||||
user_id BIGINT 用户ID
|
||||
amount DECIMAL(12,2) 提现金额
|
||||
fee DECIMAL(12,2) 手续费
|
||||
actual_amount DECIMAL(12,2) 实际到账金额
|
||||
payment_account_id BIGINT 收款账号ID
|
||||
account_type VARCHAR(32) 账号类型(快照)
|
||||
account_name VARCHAR(128) 账户名(快照)
|
||||
account_no VARCHAR(128) 账号(快照,脱敏)
|
||||
bank_name VARCHAR(128) 银行名称(快照)
|
||||
bank_branch VARCHAR(255) 开户行支行(快照)
|
||||
status VARCHAR(32) 状态:pending/processing/completed/rejected/cancelled
|
||||
reviewed_by BIGINT 审核人ID
|
||||
reviewed_at DATETIME 审核时间
|
||||
review_remark VARCHAR(255) 审核备注
|
||||
paid_by BIGINT 打款人ID
|
||||
paid_at DATETIME 打款时间
|
||||
payment_proof_url VARCHAR(512) 打款凭证URL
|
||||
payment_remark VARCHAR(255) 打款备注
|
||||
created_at DATETIME
|
||||
updated_at DATETIME
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 安全措施
|
||||
|
||||
1. **账号加密存储**:使用 AES-256 加密收款账号
|
||||
2. **实名验证**:账户名必须与实名认证姓名一致
|
||||
3. **账号脱敏**:用户端仅显示脱敏账号(如 138****5678)
|
||||
4. **权限控制**:管理员操作需要对应权限
|
||||
5. **金额限制**:单笔提现限额、最低提现金额
|
||||
6. **状态锁定**:审核中/已完成的提现无法修改
|
||||
7. **快照机制**:提现申请创建时保存账号信息快照
|
||||
|
||||
---
|
||||
|
||||
## 🔄 业务流程
|
||||
|
||||
### 用户提现流程
|
||||
```
|
||||
1. 用户添加收款账号(需实名认证)
|
||||
↓
|
||||
2. 用户发起提现申请
|
||||
↓
|
||||
3. 系统冻结用户可用余额
|
||||
↓
|
||||
4. 创建提现申请(status=pending)
|
||||
↓
|
||||
5. 等待财务审核
|
||||
```
|
||||
|
||||
### 财务审核流程
|
||||
```
|
||||
1. 财务管理员查看待审核列表
|
||||
↓
|
||||
2. 审核提现申请
|
||||
├─ 通过:status → processing
|
||||
└─ 拒绝:status → rejected,解冻余额
|
||||
↓
|
||||
3. 手动转账(支付宝/微信/银行)
|
||||
↓
|
||||
4. 上传打款凭证
|
||||
↓
|
||||
5. 确认完成(status → completed)
|
||||
↓
|
||||
6. 系统扣除冻结余额
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 钱包流水业务类型
|
||||
|
||||
提现相关的 `biz_type`:
|
||||
- `withdraw_freeze` - 提现冻结
|
||||
- `withdraw_reject` - 提现拒绝(解冻)
|
||||
- `withdraw_cancel` - 用户取消提现(解冻)
|
||||
- `withdraw_complete` - 提现完成(扣除冻结余额)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 部署步骤
|
||||
|
||||
### 1. 执行数据库迁移
|
||||
```bash
|
||||
mysql -u root -p your_database < backend/migrations/000002_add_withdrawal_tables.sql
|
||||
```
|
||||
|
||||
### 2. 重新编译后端
|
||||
```bash
|
||||
cd backend
|
||||
go build -o server cmd/api/main.go
|
||||
```
|
||||
|
||||
### 3. 重启服务
|
||||
```bash
|
||||
./server
|
||||
```
|
||||
|
||||
### 4. 配置财务管理员
|
||||
```sql
|
||||
-- 查询 finance 角色ID
|
||||
SELECT id FROM roles WHERE code = 'finance';
|
||||
|
||||
-- 给管理员分配财务角色
|
||||
INSERT INTO admin_user_roles (admin_user_id, role_id)
|
||||
VALUES (你的管理员ID, 财务角色ID);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ 配置说明
|
||||
|
||||
### 加密密钥配置
|
||||
文件:`backend/internal/modules/paymentaccount/repository.go`
|
||||
|
||||
**重要**:生产环境必须修改加密密钥!
|
||||
```go
|
||||
const encryptionKey = "your-32-byte-secret-key-here!!" // 32字节
|
||||
```
|
||||
|
||||
建议从环境变量或配置文件读取:
|
||||
```go
|
||||
var encryptionKey = os.Getenv("PAYMENT_ACCOUNT_ENCRYPTION_KEY")
|
||||
```
|
||||
|
||||
### 提现限额配置
|
||||
文件:`backend/internal/modules/withdrawal/service.go`
|
||||
```go
|
||||
const (
|
||||
MinWithdrawalAmount = 10.0 // 最低提现金额
|
||||
MaxWithdrawalAmount = 5000.0 // 单笔最高提现金额
|
||||
WithdrawalFeeRate = 0.0 // 手续费率
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 测试建议
|
||||
|
||||
### 1. 收款账号管理测试
|
||||
- [ ] 添加支付宝账号
|
||||
- [ ] 添加微信账号
|
||||
- [ ] 添加银行卡账号
|
||||
- [ ] 测试实名验证(账户名不匹配)
|
||||
- [ ] 测试账号数量限制(最多5个)
|
||||
- [ ] 测试设置默认账号
|
||||
- [ ] 测试删除账号
|
||||
- [ ] 验证账号加密和脱敏显示
|
||||
|
||||
### 2. 提现申请测试
|
||||
- [ ] 测试最低金额限制(<10元)
|
||||
- [ ] 测试最高金额限制(>5000元)
|
||||
- [ ] 测试余额不足
|
||||
- [ ] 测试正常提现申请
|
||||
- [ ] 测试用户取消提现(pending状态)
|
||||
- [ ] 测试无法取消已审核的提现
|
||||
|
||||
### 3. 财务审核测试
|
||||
- [ ] 测试查询待审核列表
|
||||
- [ ] 测试审核通过
|
||||
- [ ] 测试审核拒绝(验证余额解冻)
|
||||
- [ ] 测试确认打款(上传凭证)
|
||||
- [ ] 测试管理员可见完整账号
|
||||
|
||||
### 4. 权限测试
|
||||
- [ ] 测试非财务管理员无法访问审核接口
|
||||
- [ ] 测试财务管理员可以访问所有提现接口
|
||||
- [ ] 测试用户只能查看自己的提现记录
|
||||
|
||||
---
|
||||
|
||||
## 📝 后续优化建议
|
||||
|
||||
### 短期优化
|
||||
1. **前端页面开发**:用户端收款账号管理、提现申请页面
|
||||
2. **管理员前端**:提现审核列表、审核详情页面
|
||||
3. **通知功能**:提现状态变更时发送通知
|
||||
4. **文件上传**:集成打款凭证上传功能
|
||||
|
||||
### 中期优化
|
||||
1. **自动化提现**:小额提现自动审核
|
||||
2. **批量打款**:导出批量打款文件
|
||||
3. **提现报表**:财务报表统计
|
||||
4. **风控规则**:异常提现检测
|
||||
|
||||
### 长期优化
|
||||
1. **支付网关对接**:集成自动打款接口
|
||||
2. **银行接口对接**:企业网银直连
|
||||
3. **实时到账**:T+0 实时提现
|
||||
4. **多级审批**:大额提现多级审批流程
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
1. **加密密钥**:生产环境必须使用强随机密钥,并妥善保管
|
||||
2. **权限配置**:确保财务管理员权限配置正确
|
||||
3. **余额校验**:提现前严格校验余额,防止超额提现
|
||||
4. **状态机**:严格按照状态流转规则操作
|
||||
5. **审计日志**:所有财务操作应记录审计日志
|
||||
6. **测试环境**:充分测试后再上线生产环境
|
||||
|
||||
---
|
||||
|
||||
## 🎯 项目总结
|
||||
|
||||
本次实施完成了**手动提现功能的完整开发**,包括:
|
||||
- ✅ 数据库设计和迁移
|
||||
- ✅ 后端业务逻辑实现
|
||||
- ✅ API 接口开发
|
||||
- ✅ 权限和角色配置
|
||||
- ✅ 安全措施实施
|
||||
|
||||
系统已具备完整的手动提现能力,财务管理员可以通过管理后台进行提现审核和打款确认操作。
|
||||
|
||||
**下一步**:前端界面开发 → 完整测试 → 生产环境部署
|
||||
@@ -1,396 +0,0 @@
|
||||
# 提现功能测试清单
|
||||
|
||||
## 🧪 测试环境准备
|
||||
|
||||
### 前置条件
|
||||
- [x] 后端服务已启动(http://localhost:8080)
|
||||
- [x] 前端服务已启动(http://localhost:5173)
|
||||
- [x] 数据库迁移已执行
|
||||
- [x] 财务角色和权限已配置
|
||||
|
||||
---
|
||||
|
||||
## 📝 用户端测试
|
||||
|
||||
### 1. 收款账号管理测试
|
||||
|
||||
#### 1.1 添加支付宝账号
|
||||
- [ ] 访问 `/wallet/payment-accounts`
|
||||
- [ ] 点击"添加收款账号"
|
||||
- [ ] 选择"支付宝"
|
||||
- [ ] 输入账户名(需与实名认证姓名一致)
|
||||
- [ ] 输入支付宝账号
|
||||
- [ ] 点击"添加"
|
||||
- [ ] **预期结果**:成功添加,显示在列表中,账号已脱敏
|
||||
|
||||
#### 1.2 添加微信账号
|
||||
- [ ] 选择"微信"
|
||||
- [ ] 输入账户名
|
||||
- [ ] 输入微信号
|
||||
- [ ] 点击"添加"
|
||||
- [ ] **预期结果**:成功添加
|
||||
|
||||
#### 1.3 添加银行卡账号
|
||||
- [ ] 选择"银行卡"
|
||||
- [ ] 输入账户名
|
||||
- [ ] 输入银行卡号
|
||||
- [ ] 输入银行名称(如:中国工商银行)
|
||||
- [ ] 输入开户支行(可选)
|
||||
- [ ] 点击"添加"
|
||||
- [ ] **预期结果**:成功添加,银行信息显示
|
||||
|
||||
#### 1.4 实名验证测试
|
||||
- [ ] 使用未实名认证的账号添加收款账号
|
||||
- [ ] **预期结果**:提示"请先完成实名认证"
|
||||
- [ ] 使用已实名账号,但账户名与实名不一致
|
||||
- [ ] **预期结果**:提示"账户名必须与实名认证姓名一致"
|
||||
|
||||
#### 1.5 账号数量限制测试
|
||||
- [ ] 添加第5个收款账号
|
||||
- [ ] **预期结果**:成功添加
|
||||
- [ ] 尝试添加第6个收款账号
|
||||
- [ ] **预期结果**:按钮变为"已达账号数量上限",无法添加
|
||||
|
||||
#### 1.6 设置默认账号
|
||||
- [ ] 点击某个账号的"星星"图标
|
||||
- [ ] **预期结果**:该账号标记为默认,其他账号取消默认
|
||||
|
||||
#### 1.7 编辑账号
|
||||
- [ ] 点击某个账号的"编辑"按钮
|
||||
- [ ] 修改支行信息(银行卡)
|
||||
- [ ] 点击"更新"
|
||||
- [ ] **预期结果**:信息更新成功
|
||||
|
||||
#### 1.8 删除账号
|
||||
- [ ] 点击某个账号的"删除"按钮
|
||||
- [ ] 确认删除
|
||||
- [ ] **预期结果**:账号删除成功
|
||||
|
||||
---
|
||||
|
||||
### 2. 提现申请测试
|
||||
|
||||
#### 2.1 正常提现流程
|
||||
- [ ] 访问 `/wallet/withdrawal`
|
||||
- [ ] 查看钱包余额显示正确
|
||||
- [ ] 选择收款账号
|
||||
- [ ] 输入金额 100
|
||||
- [ ] 查看到账金额显示为 100(手续费0%)
|
||||
- [ ] 点击"提交申请"
|
||||
- [ ] 确认提现
|
||||
- [ ] **预期结果**:提现申请提交成功,在提现记录中显示"待审核"
|
||||
|
||||
#### 2.2 最低金额限制测试
|
||||
- [ ] 输入金额 5
|
||||
- [ ] **预期结果**:按钮禁用,或提示"提现金额低于最小限额"
|
||||
|
||||
#### 2.3 最高金额限制测试
|
||||
- [ ] 输入金额 6000
|
||||
- [ ] **预期结果**:提示"提现金额超过最大限额"
|
||||
|
||||
#### 2.4 余额不足测试
|
||||
- [ ] 输入金额大于可用余额
|
||||
- [ ] **预期结果**:显示红色警告"余额不足,可用余额:¥xxx"
|
||||
|
||||
#### 2.5 无收款账号测试
|
||||
- [ ] 删除所有收款账号
|
||||
- [ ] 访问提现页面
|
||||
- [ ] **预期结果**:显示"还没有收款账号",引导添加
|
||||
|
||||
#### 2.6 取消提现测试
|
||||
- [ ] 在提现记录中找到"待审核"状态的提现
|
||||
- [ ] 点击"取消"按钮
|
||||
- [ ] 确认取消
|
||||
- [ ] **预期结果**:状态变为"已取消",余额解冻
|
||||
|
||||
#### 2.7 无法取消已审核提现
|
||||
- [ ] 尝试取消"处理中"或"已完成"状态的提现
|
||||
- [ ] **预期结果**:没有"取消"按钮
|
||||
|
||||
---
|
||||
|
||||
## 🔐 管理员端测试
|
||||
|
||||
### 3. 提现审核测试
|
||||
|
||||
#### 3.1 登录财务账号
|
||||
- [ ] 使用财务管理员账号登录
|
||||
- [ ] 访问 `/admin/withdrawals`
|
||||
- [ ] **预期结果**:可以正常访问
|
||||
|
||||
#### 3.2 权限测试
|
||||
- [ ] 使用非财务角色管理员登录
|
||||
- [ ] 访问提现管理页面
|
||||
- [ ] **预期结果**:无权限或看不到相关菜单
|
||||
|
||||
#### 3.3 查看提现列表
|
||||
- [ ] 查看提现列表
|
||||
- [ ] **预期结果**:显示所有提现申请,包含用户信息、金额、收款方式、状态
|
||||
|
||||
#### 3.4 状态筛选
|
||||
- [ ] 选择"待审核"状态
|
||||
- [ ] 点击"查询"
|
||||
- [ ] **预期结果**:只显示待审核的提现
|
||||
|
||||
#### 3.5 用户筛选
|
||||
- [ ] 输入用户ID
|
||||
- [ ] 点击"查询"
|
||||
- [ ] **预期结果**:只显示该用户的提现记录
|
||||
|
||||
#### 3.6 查看提现详情
|
||||
- [ ] 点击某条记录的"详情"按钮
|
||||
- [ ] **预期结果**:
|
||||
- 显示完整的提现信息
|
||||
- 显示用户信息(昵称、手机号)
|
||||
- 显示完整的收款账号(未脱敏)
|
||||
- 显示金额信息
|
||||
- 如有银行卡,显示开户支行
|
||||
|
||||
#### 3.7 审核通过
|
||||
- [ ] 在待审核的提现详情中点击"通过审核"
|
||||
- [ ] 输入审核备注(可选)
|
||||
- [ ] 确认
|
||||
- [ ] **预期结果**:
|
||||
- 状态变为"处理中"
|
||||
- 显示审核人和审核时间
|
||||
- 显示操作提示"请手动转账到用户收款账号"
|
||||
|
||||
#### 3.8 审核拒绝
|
||||
- [ ] 在待审核的提现详情中点击"拒绝"
|
||||
- [ ] 输入拒绝原因
|
||||
- [ ] 确认
|
||||
- [ ] **预期结果**:
|
||||
- 状态变为"已拒绝"
|
||||
- 显示审核人和审核时间
|
||||
- 用户余额解冻
|
||||
|
||||
#### 3.9 确认打款
|
||||
- [ ] 手动转账到用户收款账号
|
||||
- [ ] 在"处理中"的提现详情中点击"确认打款"
|
||||
- [ ] 输入打款备注(如:已通过支付宝转账)
|
||||
- [ ] 确认
|
||||
- [ ] **预期结果**:
|
||||
- 状态变为"已完成"
|
||||
- 显示打款人和打款时间
|
||||
- 用户冻结余额扣除
|
||||
|
||||
#### 3.10 完整账号可见性测试
|
||||
- [ ] 查看提现详情
|
||||
- [ ] **预期结果**:管理员可以看到完整的收款账号(未脱敏)
|
||||
|
||||
---
|
||||
|
||||
## 💰 钱包余额测试
|
||||
|
||||
### 4. 余额流转测试
|
||||
|
||||
#### 4.1 提现冻结测试
|
||||
- [ ] 记录提现前的可用余额和冻结余额
|
||||
- [ ] 提交提现申请
|
||||
- [ ] 查看钱包余额
|
||||
- [ ] **预期结果**:
|
||||
- 可用余额减少(提现金额)
|
||||
- 冻结余额增加(提现金额)
|
||||
|
||||
#### 4.2 审核拒绝解冻测试
|
||||
- [ ] 管理员拒绝提现
|
||||
- [ ] 查看钱包余额
|
||||
- [ ] **预期结果**:
|
||||
- 冻结余额减少(提现金额)
|
||||
- 可用余额增加(提现金额)
|
||||
|
||||
#### 4.3 用户取消解冻测试
|
||||
- [ ] 用户取消待审核提现
|
||||
- [ ] 查看钱包余额
|
||||
- [ ] **预期结果**:余额解冻(同上)
|
||||
|
||||
#### 4.4 打款完成扣除测试
|
||||
- [ ] 管理员确认打款
|
||||
- [ ] 查看钱包余额
|
||||
- [ ] **预期结果**:
|
||||
- 冻结余额减少(提现金额)
|
||||
- 总余额减少(提现金额)
|
||||
|
||||
#### 4.5 钱包流水测试
|
||||
- [ ] 访问钱包流水页面
|
||||
- [ ] **预期结果**:可以看到以下流水记录
|
||||
- `withdraw_freeze` - 提现冻结
|
||||
- `withdraw_reject` - 提现拒绝(如有)
|
||||
- `withdraw_cancel` - 用户取消提现(如有)
|
||||
- `withdraw_complete` - 提现完成
|
||||
|
||||
---
|
||||
|
||||
## 🔄 业务流程完整性测试
|
||||
|
||||
### 5. 端到端测试
|
||||
|
||||
#### 场景1:正常提现流程
|
||||
```
|
||||
1. 用户添加收款账号 ✓
|
||||
↓
|
||||
2. 用户发起提现 ✓
|
||||
↓
|
||||
3. 余额冻结 ✓
|
||||
↓
|
||||
4. 管理员审核通过 ✓
|
||||
↓
|
||||
5. 管理员手动转账 ✓
|
||||
↓
|
||||
6. 管理员确认打款 ✓
|
||||
↓
|
||||
7. 冻结余额扣除 ✓
|
||||
```
|
||||
|
||||
#### 场景2:提现被拒绝
|
||||
```
|
||||
1. 用户发起提现 ✓
|
||||
↓
|
||||
2. 余额冻结 ✓
|
||||
↓
|
||||
3. 管理员审核拒绝 ✓
|
||||
↓
|
||||
4. 余额解冻 ✓
|
||||
```
|
||||
|
||||
#### 场景3:用户取消提现
|
||||
```
|
||||
1. 用户发起提现 ✓
|
||||
↓
|
||||
2. 余额冻结 ✓
|
||||
↓
|
||||
3. 用户取消提现 ✓
|
||||
↓
|
||||
4. 余额解冻 ✓
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 UI/UX 测试
|
||||
|
||||
### 6. 界面和交互测试
|
||||
|
||||
#### 6.1 响应式测试
|
||||
- [ ] 桌面端显示正常
|
||||
- [ ] 平板端显示正常
|
||||
- [ ] 手机端显示正常(如已适配)
|
||||
|
||||
#### 6.2 加载状态
|
||||
- [ ] 列表加载时显示 loading
|
||||
- [ ] 提交操作时按钮显示 loading
|
||||
- [ ] 数据为空时显示空状态
|
||||
|
||||
#### 6.3 错误提示
|
||||
- [ ] 网络错误时显示友好提示
|
||||
- [ ] 表单验证错误显示清晰
|
||||
- [ ] 操作失败时显示具体原因
|
||||
|
||||
#### 6.4 确认对话框
|
||||
- [ ] 删除账号需要确认
|
||||
- [ ] 提交提现需要确认
|
||||
- [ ] 取消提现需要确认
|
||||
- [ ] 审核操作需要确认
|
||||
|
||||
#### 6.5 状态标签
|
||||
- [ ] 待审核:黄色警告标签
|
||||
- [ ] 处理中:蓝色主题标签
|
||||
- [ ] 已完成:绿色成功标签
|
||||
- [ ] 已拒绝:红色危险标签
|
||||
- [ ] 已取消:灰色信息标签
|
||||
|
||||
---
|
||||
|
||||
## 🔒 安全性测试
|
||||
|
||||
### 7. 安全测试
|
||||
|
||||
#### 7.1 账号脱敏
|
||||
- [ ] 用户端收款账号列表显示脱敏账号
|
||||
- [ ] 提现记录显示脱敏账号
|
||||
- [ ] 管理员端显示完整账号
|
||||
|
||||
#### 7.2 权限验证
|
||||
- [ ] 未登录用户无法访问提现页面
|
||||
- [ ] 用户只能查看自己的收款账号
|
||||
- [ ] 用户只能查看自己的提现记录
|
||||
- [ ] 非财务管理员无法访问提现审核
|
||||
|
||||
#### 7.3 实名验证
|
||||
- [ ] 未实名用户无法添加收款账号
|
||||
- [ ] 账户名不匹配无法添加
|
||||
|
||||
#### 7.4 金额验证
|
||||
- [ ] 最低金额限制生效
|
||||
- [ ] 最高金额限制生效
|
||||
- [ ] 余额不足无法提现
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据一致性测试
|
||||
|
||||
### 8. 数据库验证
|
||||
|
||||
#### 8.1 收款账号
|
||||
- [ ] 账号加密存储(后端数据库检查)
|
||||
- [ ] 默认账号只有一个
|
||||
- [ ] 删除是软删除(status=disabled)
|
||||
|
||||
#### 8.2 提现记录
|
||||
- [ ] 提现单号唯一
|
||||
- [ ] 账号信息快照正确
|
||||
- [ ] 状态流转正确
|
||||
- [ ] 审核信息记录完整
|
||||
- [ ] 打款信息记录完整
|
||||
|
||||
#### 8.3 钱包流水
|
||||
- [ ] 每次操作都有对应流水
|
||||
- [ ] 流水金额正确
|
||||
- [ ] 余额计算正确
|
||||
- [ ] 业务类型标记正确
|
||||
|
||||
---
|
||||
|
||||
## ✅ 测试结果
|
||||
|
||||
### 通过标准
|
||||
- [ ] 所有核心功能测试通过
|
||||
- [ ] 无阻塞性 Bug
|
||||
- [ ] UI/UX 友好
|
||||
- [ ] 安全性验证通过
|
||||
- [ ] 数据一致性正确
|
||||
|
||||
### 发现的问题
|
||||
|
||||
| 编号 | 问题描述 | 严重程度 | 状态 |
|
||||
|------|----------|----------|------|
|
||||
| 1 | | | |
|
||||
| 2 | | | |
|
||||
| 3 | | | |
|
||||
|
||||
---
|
||||
|
||||
## 📝 测试报告
|
||||
|
||||
**测试日期**:
|
||||
**测试人员**:
|
||||
**测试环境**:
|
||||
**测试结果**:
|
||||
|
||||
**备注**:
|
||||
|
||||
---
|
||||
|
||||
## 🚀 上线前检查清单
|
||||
|
||||
- [ ] 所有测试通过
|
||||
- [ ] 生产环境加密密钥已更新
|
||||
- [ ] 数据库迁移已在生产环境执行
|
||||
- [ ] 财务管理员账号已创建
|
||||
- [ ] 财务角色权限已配置
|
||||
- [ ] 备份数据库
|
||||
- [ ] 准备回滚方案
|
||||
- [ ] 监控和告警配置
|
||||
|
||||
---
|
||||
|
||||
**测试完成后,系统即可上线使用!**
|
||||
@@ -1,215 +0,0 @@
|
||||
# 文件上传功能集成说明
|
||||
|
||||
## ✅ 已完成的修复
|
||||
|
||||
### 1. 钱包页面提现按钮(已修复)
|
||||
**文件**:`frontend/src/features/wallet/views/WalletView.vue`
|
||||
|
||||
**修复内容**:
|
||||
- ✅ 移除了 `disabled` 属性
|
||||
- ✅ 添加了路由跳转功能
|
||||
- ✅ 移除了"待开发"标签
|
||||
- ✅ 改为 `type="primary"` 样式
|
||||
|
||||
**现在的功能**:
|
||||
- 点击"申请提现"按钮会跳转到 `/wallet/withdrawal` 页面
|
||||
|
||||
---
|
||||
|
||||
### 2. 收款账号凭证上传(已集成)
|
||||
**文件**:`frontend/src/features/wallet/components/PaymentAccountDialog.vue`
|
||||
|
||||
**集成内容**:
|
||||
- ✅ 导入文件上传 API (`uploadFile`)
|
||||
- ✅ 添加上传处理函数 (`handleUpload`)
|
||||
- ✅ 添加删除图片函数 (`removeImage`)
|
||||
- ✅ 更新模板,支持图片预览和删除
|
||||
- ✅ 添加完整样式
|
||||
|
||||
**功能特性**:
|
||||
1. **图片预览** - 已上传的图片显示缩略图
|
||||
2. **删除功能** - 鼠标悬停显示删除按钮
|
||||
3. **数量限制** - 最多上传 3 张图片
|
||||
4. **文件验证**
|
||||
- 只能上传图片文件
|
||||
- 最大 5MB
|
||||
5. **上传状态** - 显示上传进度和 loading 图标
|
||||
6. **图片优化** - 自动压缩和优化图片(使用 WebP 格式)
|
||||
|
||||
**使用场景**:
|
||||
- 支付宝/微信收款码截图
|
||||
- 银行卡照片
|
||||
- 其他支付凭证
|
||||
|
||||
---
|
||||
|
||||
## 🎯 使用说明
|
||||
|
||||
### 用户端操作流程
|
||||
|
||||
1. **进入收款账号管理**
|
||||
- 访问:http://localhost:5173/wallet/payment-accounts
|
||||
- 或从钱包页面点击"管理收款账号"
|
||||
|
||||
2. **添加收款账号**
|
||||
- 点击"添加收款账号"按钮
|
||||
- 选择账号类型(支付宝/微信/银行卡)
|
||||
- 填写必填信息
|
||||
- 上传凭证图片(可选):
|
||||
- 点击"上传凭证"按钮
|
||||
- 选择图片文件
|
||||
- 等待上传完成
|
||||
- 可以上传最多 3 张图片
|
||||
- 点击图片上的删除按钮可以移除
|
||||
|
||||
3. **申请提现**
|
||||
- 在钱包页面点击"申请提现"
|
||||
- 选择收款账号
|
||||
- 输入金额
|
||||
- 提交申请
|
||||
|
||||
---
|
||||
|
||||
## 📸 支持的图片格式
|
||||
|
||||
- **输入格式**:JPEG, PNG, WebP
|
||||
- **输出格式**:WebP(自动转换)
|
||||
- **最大尺寸**:5MB
|
||||
- **图片处理**:
|
||||
- 自动压缩
|
||||
- 保持宽高比
|
||||
- 优化文件大小
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术实现
|
||||
|
||||
### 文件上传流程
|
||||
```
|
||||
1. 用户选择图片
|
||||
↓
|
||||
2. 验证文件类型和大小
|
||||
↓
|
||||
3. 调用 optimizeImageForUpload() 优化图片
|
||||
↓
|
||||
4. 上传到服务器 (/api/files/upload)
|
||||
↓
|
||||
5. 返回 URL 和元数据
|
||||
↓
|
||||
6. 保存 URL 到 certificate_urls 数组
|
||||
```
|
||||
|
||||
### API 接口
|
||||
```typescript
|
||||
uploadFile(file: File, scene: string): Promise<UploadedFile>
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `file`: File 对象
|
||||
- `scene`: 上传场景标识(使用 `'payment-cert'`)
|
||||
|
||||
**返回**:
|
||||
```typescript
|
||||
{
|
||||
object_key: string
|
||||
url: string
|
||||
thumbnail_url?: string
|
||||
medium_url?: string
|
||||
filename: string
|
||||
content_type: string
|
||||
size: number
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 UI 设计
|
||||
|
||||
### 上传区域
|
||||
```
|
||||
┌─────────┬─────────┬─────────┐
|
||||
│ 图片1 │ 图片2 │ + 上传 │
|
||||
│ [删除] │ [删除] │ 凭证 │
|
||||
└─────────┴─────────┴─────────┘
|
||||
```
|
||||
|
||||
### 交互效果
|
||||
- ✅ 鼠标悬停显示删除按钮
|
||||
- ✅ 上传时显示 loading 图标
|
||||
- ✅ 上传按钮有 hover 效果
|
||||
- ✅ 图片预览(100x100px)
|
||||
- ✅ 响应式布局
|
||||
|
||||
---
|
||||
|
||||
## 🔒 安全说明
|
||||
|
||||
1. **文件验证**
|
||||
- 前端验证文件类型
|
||||
- 前端验证文件大小
|
||||
- 后端也会进行二次验证
|
||||
|
||||
2. **图片处理**
|
||||
- 自动压缩减小文件大小
|
||||
- 统一转换为 WebP 格式
|
||||
- 限制图片尺寸
|
||||
|
||||
3. **存储**
|
||||
- URL 存储在数据库
|
||||
- 图片存储在 MinIO/OSS
|
||||
- 支持私有访问控制
|
||||
|
||||
---
|
||||
|
||||
## 📋 测试建议
|
||||
|
||||
### 功能测试
|
||||
- [ ] 上传 JPEG 图片
|
||||
- [ ] 上传 PNG 图片
|
||||
- [ ] 上传 WebP 图片
|
||||
- [ ] 上传超过 5MB 的图片(应该失败)
|
||||
- [ ] 上传非图片文件(应该失败)
|
||||
- [ ] 上传 3 张图片(达到上限)
|
||||
- [ ] 删除已上传的图片
|
||||
- [ ] 重新上传删除的图片
|
||||
|
||||
### UI 测试
|
||||
- [ ] 图片预览显示正常
|
||||
- [ ] 删除按钮悬停显示
|
||||
- [ ] 上传中显示 loading
|
||||
- [ ] 上传成功提示
|
||||
- [ ] 上传失败提示
|
||||
- [ ] 布局响应式
|
||||
|
||||
---
|
||||
|
||||
## 🐛 已知限制
|
||||
|
||||
1. **当前版本**:
|
||||
- 只支持图片上传
|
||||
- 最多 3 张图片
|
||||
- 单个文件最大 5MB
|
||||
|
||||
2. **未来优化**:
|
||||
- 支持 PDF 文件
|
||||
- 批量上传
|
||||
- 拖拽上传
|
||||
- 图片裁剪
|
||||
|
||||
---
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
✅ **文件上传功能已完全集成**
|
||||
|
||||
两个主要修复:
|
||||
1. ✅ 钱包页面"申请提现"按钮可点击
|
||||
2. ✅ 收款账号凭证上传功能完整实现
|
||||
|
||||
用户现在可以:
|
||||
- 正常使用提现功能
|
||||
- 上传收款账号凭证图片
|
||||
- 查看和管理已上传的图片
|
||||
- 删除不需要的图片
|
||||
|
||||
系统功能完整,可以正常使用!
|
||||
@@ -1,218 +0,0 @@
|
||||
# ✅ 提现功能最终检查清单
|
||||
|
||||
## 🎉 开发完成状态
|
||||
|
||||
**开发进度**:100% 完成
|
||||
**测试状态**:待测试
|
||||
**上线状态**:待部署
|
||||
|
||||
---
|
||||
|
||||
## 📦 已完成的功能
|
||||
|
||||
### 后端功能 ✅
|
||||
- [x] 数据库表设计和迁移
|
||||
- [x] 收款账号管理模块
|
||||
- [x] 提现申请模块
|
||||
- [x] 钱包流水集成
|
||||
- [x] 权限和角色配置
|
||||
- [x] API 接口开发
|
||||
- [x] 路由配置
|
||||
|
||||
### 前端功能 ✅
|
||||
- [x] 收款账号管理页面
|
||||
- [x] 提现申请页面
|
||||
- [x] 管理员审核页面
|
||||
- [x] 文件上传功能
|
||||
- [x] 路由配置
|
||||
- [x] 编译测试通过
|
||||
|
||||
### 文档 ✅
|
||||
- [x] 后端实施总结
|
||||
- [x] API 接口文档
|
||||
- [x] 前端开发总结
|
||||
- [x] 测试清单
|
||||
- [x] 完整实施总结
|
||||
- [x] 文件上传集成说明
|
||||
|
||||
---
|
||||
|
||||
## 🔧 修复记录
|
||||
|
||||
### Bug #1: 钱包页面"申请提现"按钮无法点击
|
||||
**状态**:✅ 已修复
|
||||
|
||||
**问题**:
|
||||
- 按钮被设置为 `disabled` 状态
|
||||
- 显示"待开发"标签
|
||||
- 点击没有响应
|
||||
|
||||
**修复**:
|
||||
- 移除 `disabled` 属性
|
||||
- 添加路由跳转功能
|
||||
- 移除"待开发"标签
|
||||
- 改为 `type="primary"` 主题色
|
||||
|
||||
**文件**:`frontend/src/features/wallet/views/WalletView.vue`
|
||||
|
||||
---
|
||||
|
||||
### Bug #2: 收款账号"上传凭证"按钮无法点击
|
||||
**状态**:✅ 已修复
|
||||
|
||||
**问题**:
|
||||
- 上传按钮是占位按钮
|
||||
- 没有实际功能
|
||||
|
||||
**修复**:
|
||||
- 集成项目文件上传 API
|
||||
- 实现图片上传功能
|
||||
- 添加图片预览
|
||||
- 添加删除功能
|
||||
- 添加文件验证
|
||||
- 限制上传数量(3张)
|
||||
|
||||
**文件**:`frontend/src/features/wallet/components/PaymentAccountDialog.vue`
|
||||
|
||||
---
|
||||
|
||||
## 🚀 部署前检查
|
||||
|
||||
### 1. 环境配置 ⚠️
|
||||
|
||||
#### 后端配置
|
||||
```bash
|
||||
# 1. 修改加密密钥(必须)
|
||||
# 文件:backend/internal/modules/paymentaccount/repository.go
|
||||
# 将 encryptionKey 改为随机生成的32字节密钥
|
||||
const encryptionKey = "your-32-byte-secret-key-here!!"
|
||||
```
|
||||
|
||||
#### 数据库迁移
|
||||
```bash
|
||||
# 2. 执行数据库迁移(必须)
|
||||
cd backend/migrations
|
||||
mysql -u root -p database < 000002_add_withdrawal_tables.sql
|
||||
```
|
||||
|
||||
#### 财务管理员配置
|
||||
```sql
|
||||
-- 3. 创建财务管理员账号(必须)
|
||||
-- 查询 finance 角色ID
|
||||
SELECT id FROM roles WHERE code = 'finance';
|
||||
|
||||
-- 分配角色给管理员
|
||||
INSERT INTO admin_user_roles (admin_user_id, role_id)
|
||||
VALUES (管理员ID, 财务角色ID);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 功能测试 ⏳
|
||||
|
||||
#### 用户端测试
|
||||
- [ ] 访问 http://localhost:5173/wallet
|
||||
- [ ] 点击"申请提现"按钮能正常跳转
|
||||
- [ ] 进入收款账号管理页面
|
||||
- [ ] 添加支付宝账号
|
||||
- [ ] 上传凭证图片
|
||||
- [ ] 添加微信账号
|
||||
- [ ] 添加银行卡账号
|
||||
- [ ] 设置默认账号
|
||||
- [ ] 删除账号
|
||||
- [ ] 发起提现申请
|
||||
- [ ] 查看提现记录
|
||||
- [ ] 取消提现
|
||||
|
||||
#### 管理员端测试
|
||||
- [ ] 使用财务账号登录
|
||||
- [ ] 访问 http://localhost:5173/admin/withdrawals
|
||||
- [ ] 查看提现列表
|
||||
- [ ] 筛选待审核提现
|
||||
- [ ] 查看提现详情
|
||||
- [ ] 审核通过
|
||||
- [ ] 审核拒绝
|
||||
- [ ] 确认打款
|
||||
|
||||
#### 钱包余额测试
|
||||
- [ ] 提现后余额冻结
|
||||
- [ ] 审核拒绝后余额解冻
|
||||
- [ ] 用户取消后余额解冻
|
||||
- [ ] 打款完成后余额扣除
|
||||
- [ ] 查看钱包流水
|
||||
|
||||
---
|
||||
|
||||
### 3. 安全检查 🔒
|
||||
|
||||
- [ ] 加密密钥已更新(生产环境)
|
||||
- [ ] 账号信息加密存储
|
||||
- [ ] 用户端账号脱敏显示
|
||||
- [ ] 管理员端完整账号可见
|
||||
- [ ] 实名验证生效
|
||||
- [ ] 权限控制正常
|
||||
- [ ] 金额限制生效
|
||||
- [ ] 文件上传验证
|
||||
|
||||
---
|
||||
|
||||
## 📝 已修复的问题总结
|
||||
|
||||
### ✅ 问题1:申请提现按钮无法点击
|
||||
- **修复文件**:`WalletView.vue`
|
||||
- **修复内容**:启用按钮,添加路由跳转
|
||||
- **测试方法**:刷新页面,点击"申请提现"按钮,应跳转到提现页面
|
||||
|
||||
### ✅ 问题2:上传凭证按钮无法点击
|
||||
- **修复文件**:`PaymentAccountDialog.vue`
|
||||
- **修复内容**:集成文件上传功能
|
||||
- **测试方法**:
|
||||
1. 打开添加收款账号对话框
|
||||
2. 点击"上传凭证"按钮
|
||||
3. 选择图片文件
|
||||
4. 查看上传结果
|
||||
|
||||
---
|
||||
|
||||
## 🎯 关键指标
|
||||
|
||||
### 功能完整性
|
||||
- ✅ 用户端:100% 完成
|
||||
- ✅ 管理端:100% 完成
|
||||
- ✅ API 接口:100% 完成
|
||||
- ✅ 文档:100% 完成
|
||||
|
||||
### Bug 修复
|
||||
- ✅ Bug #1:申请提现按钮 - 已修复
|
||||
- ✅ Bug #2:上传凭证按钮 - 已修复
|
||||
|
||||
---
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
### 文档位置
|
||||
所有文档都在 `docs/` 目录下:
|
||||
- `提现功能实施总结.md` - 后端完整说明
|
||||
- `提现功能API文档.md` - API 接口文档
|
||||
- `提现功能前端开发总结.md` - 前端开发说明
|
||||
- `提现功能测试清单.md` - 详细测试清单
|
||||
- `提现功能完整实施总结.md` - 项目总结
|
||||
- `文件上传功能集成说明.md` - 文件上传详细说明
|
||||
|
||||
### 访问地址
|
||||
- 用户端收款账号:http://localhost:5173/wallet/payment-accounts
|
||||
- 用户端提现申请:http://localhost:5173/wallet/withdrawal
|
||||
- 管理端提现审核:http://localhost:5173/admin/withdrawals
|
||||
|
||||
---
|
||||
|
||||
## 🎊 完成状态
|
||||
|
||||
**项目状态**:✅ 开发完成
|
||||
**Bug 修复**:✅ 全部修复
|
||||
**测试状态**:⏳ 待测试
|
||||
**部署状态**:⏳ 待部署
|
||||
|
||||
---
|
||||
|
||||
**准备就绪,可以开始测试了!** 🚀
|
||||
@@ -1,672 +0,0 @@
|
||||
# HFB_SYS 项目架构分析报告
|
||||
|
||||
**分析时间**:2026-06-06
|
||||
**工具**:Claude Code + Fast-Context MCP
|
||||
**分析范围**:代码架构、业务流程、性能评估、优化建议
|
||||
|
||||
---
|
||||
|
||||
## 一、项目概述
|
||||
|
||||
### 1.1 项目定位
|
||||
**HFB_SYS** 是一个游戏账号租赁交易平台(Rent-a-Game-Account Platform),支持用户发布、租赁游戏账号,并提供完整的订单、支付、客服、申诉等功能。
|
||||
|
||||
### 1.2 技术栈
|
||||
|
||||
#### 后端
|
||||
- **语言**:Go 1.21+
|
||||
- **框架**:Gin (HTTP路由)
|
||||
- **数据库**:MySQL 8.4
|
||||
- **缓存**:Redis 7.4
|
||||
- **对象存储**:MinIO
|
||||
- **文档**:Swagger (swaggo)
|
||||
- **日志**:zap
|
||||
- **部署**:Docker + Docker Compose
|
||||
|
||||
#### 前端
|
||||
- **框架**:Vue 3 + TypeScript
|
||||
- **构建工具**:Vite
|
||||
- **UI库**:Element Plus
|
||||
- **路由**:Vue Router
|
||||
- **状态管理**:Pinia
|
||||
|
||||
---
|
||||
|
||||
## 二、代码架构分析
|
||||
|
||||
### 2.1 后端模块划分
|
||||
|
||||
项目采用**按业务领域模块化**的设计,每个模块独立封装:
|
||||
|
||||
```
|
||||
backend/internal/modules/
|
||||
├── auth/ # 认证模块(短信登录、JWT)
|
||||
├── user/ # 用户模块
|
||||
├── realname/ # 实名认证模块
|
||||
├── listing/ # 商品管理模块(游戏账号出租)
|
||||
├── order/ # 订单管理模块
|
||||
├── payment/ # 支付模块(乐刷)
|
||||
├── wallet/ # 钱包模块
|
||||
├── chat/ # 聊天模块
|
||||
├── chathub/ # WebSocket聊天中心
|
||||
├── dispute/ # 申诉模块
|
||||
├── notification/ # 通知模块
|
||||
├── file/ # 文件上传模块(MinIO)
|
||||
├── adminauth/ # 管理员认证
|
||||
├── adminuser/ # 用户管理(后台)
|
||||
├── adminmgr/ # 管理员管理
|
||||
├── adminrole/ # 角色权限管理
|
||||
├── adminaudit/ # 审计日志
|
||||
├── admindashboard/ # 仪表盘
|
||||
├── systemconfig/ # 系统配置
|
||||
└── announcement/ # 公告管理
|
||||
```
|
||||
|
||||
**架构特点**:
|
||||
- ✅ 每个模块独立的 `handler.go`, `service.go`, `repository.go`, `dto.go`
|
||||
- ✅ 清晰的三层架构(Handler → Service → Repository)
|
||||
- ✅ 依赖注入在 `router/router.go` 中统一管理
|
||||
- ✅ 模块间通过接口解耦(如 order 模块注入 chat 模块的 repo)
|
||||
|
||||
### 2.2 三层架构设计
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Handler Layer │ HTTP请求处理、参数验证、响应格式化
|
||||
│ (handler.go) │
|
||||
└──────────────┬──────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Service Layer │ 业务逻辑、事务控制、跨模块协调
|
||||
│ (service.go) │
|
||||
└──────────────┬──────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Repository Layer │ 数据访问、SQL查询、缓存操作
|
||||
│ (repository.go) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**示例:订单创建流程**
|
||||
```go
|
||||
// Handler 层
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req CreateOrderRequest
|
||||
c.ShouldBindJSON(&req)
|
||||
order, err := h.service.CreateOrder(ctx, userID, req)
|
||||
c.JSON(200, Response{Data: order})
|
||||
}
|
||||
|
||||
// Service 层
|
||||
func (s *Service) CreateOrder(ctx, userID, req) (*Order, error) {
|
||||
// 1. 查询商品
|
||||
listing := s.repo.FindListing(req.ListingID)
|
||||
|
||||
// 2. 验证库存
|
||||
if listing.InTransaction { return ErrUnavailable }
|
||||
|
||||
// 3. 创建订单(事务)
|
||||
order := s.repo.CreateOrder(...)
|
||||
|
||||
// 4. 锁定库存
|
||||
s.repo.LockListing(listing.ID)
|
||||
|
||||
// 5. 创建聊天会话
|
||||
s.chatRepo.CreateConversation(order.ID)
|
||||
|
||||
return order, nil
|
||||
}
|
||||
|
||||
// Repository 层
|
||||
func (r *Repository) CreateOrder(order *Order) error {
|
||||
return r.db.Create(order).Error
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 路由设计
|
||||
|
||||
**API分组**:
|
||||
```go
|
||||
/api/
|
||||
├── /auth/ # 用户认证(公开)
|
||||
├── /listings # 商品列表(公开+认证)
|
||||
├── /orders # 订单管理(需认证)
|
||||
├── /wallet # 钱包管理(需认证)
|
||||
├── /chats # 聊天(需认证)
|
||||
├── /disputes # 申诉(需认证)
|
||||
└── /admin/ # 管理后台(需管理员认证+权限)
|
||||
├── /users
|
||||
├── /orders
|
||||
├── /listings
|
||||
├── /wallet/ledger
|
||||
├── /disputes
|
||||
├── /audit-logs
|
||||
├── /roles
|
||||
├── /admin-users
|
||||
└── /announcements
|
||||
```
|
||||
|
||||
**中间件链**:
|
||||
- `RequestID()` → 生成请求ID
|
||||
- `RequestLogger()` → 请求日志
|
||||
- `Recovery()` → Panic恢复
|
||||
- `Auth()` → JWT认证(用户)
|
||||
- `AdminAuth()` → JWT认证(管理员)
|
||||
- `RequirePermission(code)` → RBAC权限校验
|
||||
- `RequireRealname()` → 实名认证校验
|
||||
|
||||
---
|
||||
|
||||
## 三、核心业务流程
|
||||
|
||||
### 3.1 租号交易流程
|
||||
|
||||
```
|
||||
号主发布商品
|
||||
↓
|
||||
平台审核通过
|
||||
↓
|
||||
商品上架展示
|
||||
↓
|
||||
租客浏览选择
|
||||
↓
|
||||
创建订单(待支付)
|
||||
↓
|
||||
租客支付(冻结押金+租金)
|
||||
↓
|
||||
号主交接账号(上传截图)
|
||||
↓
|
||||
租客确认收货
|
||||
↓
|
||||
租期结束 → 租客归还账号
|
||||
↓
|
||||
号主确认归还 → 验收账号
|
||||
↓
|
||||
系统结算(释放押金,转账租金给号主)
|
||||
↓
|
||||
双方互评(可选)
|
||||
```
|
||||
|
||||
**异常处理**:
|
||||
- 交接超时 → 自动取消订单
|
||||
- 归还异常 → 发起申诉 → 客服介入 → 平台仲裁
|
||||
- 恶意行为 → 冻结账户 → 扣除信用分
|
||||
|
||||
### 3.2 支付流程
|
||||
|
||||
```
|
||||
用户下单
|
||||
↓
|
||||
调用 payment.Start() → 生成支付单
|
||||
↓
|
||||
调用第三方支付API(乐刷)
|
||||
↓
|
||||
返回支付URL/二维码
|
||||
↓
|
||||
用户扫码支付
|
||||
↓
|
||||
支付回调 → payment.Notify()
|
||||
↓
|
||||
验签 → 更新支付单状态
|
||||
↓
|
||||
更新订单状态 → 冻结钱包余额
|
||||
↓
|
||||
通知用户(WebSocket + 站内信)
|
||||
```
|
||||
|
||||
**支持的支付方式**:
|
||||
- 乐刷支付(生产)
|
||||
- Mock支付(测试)
|
||||
- 钱包余额支付
|
||||
|
||||
### 3.3 客服聊天流程
|
||||
|
||||
```
|
||||
用户/号主发起客服咨询
|
||||
↓
|
||||
创建客服会话
|
||||
↓
|
||||
系统自动发送欢迎语
|
||||
↓
|
||||
客服在线 → 实时接收消息(WebSocket)
|
||||
↓
|
||||
客服回复
|
||||
↓
|
||||
支持快捷回复、会话转接、备注
|
||||
```
|
||||
|
||||
**聊天类型**:
|
||||
- `order_group`:订单群聊(号主+租客)
|
||||
- `support`:客服单聊
|
||||
- `system`:系统通知
|
||||
|
||||
---
|
||||
|
||||
## 四、数据库设计分析
|
||||
|
||||
### 4.1 核心表结构
|
||||
|
||||
**用户相关**:
|
||||
- `users` - 用户基础信息
|
||||
- `user_realname` - 实名认证记录
|
||||
- `wallet_accounts` - 钱包账户
|
||||
- `wallet_ledger` - 钱包流水
|
||||
|
||||
**商品订单**:
|
||||
- `game_accounts` - 游戏账号
|
||||
- `rental_listings` - 租号商品
|
||||
- `rental_orders` - 租赁订单
|
||||
|
||||
**交互模块**:
|
||||
- `chat_conversations` - 聊天会话
|
||||
- `chat_messages` - 聊天消息
|
||||
- `disputes` - 申诉记录
|
||||
- `notifications` - 通知记录
|
||||
|
||||
**管理后台**:
|
||||
- `admin_users` - 管理员
|
||||
- `admin_roles` - 角色
|
||||
- `admin_permissions` - 权限
|
||||
- `admin_role_permissions` - 角色权限关联
|
||||
- `admin_user_roles` - 管理员角色关联
|
||||
- `admin_audit_logs` - 审计日志
|
||||
- `system_configs` - 系统配置
|
||||
- `announcements` - 公告
|
||||
|
||||
### 4.2 关键索引
|
||||
|
||||
**高频查询索引**(通过代码分析推断):
|
||||
```sql
|
||||
-- 商品查询
|
||||
CREATE INDEX idx_listings_status_review ON rental_listings(status, review_status, published_at);
|
||||
|
||||
-- 订单查询
|
||||
CREATE INDEX idx_orders_renter ON rental_orders(renter_id, created_at);
|
||||
CREATE INDEX idx_orders_owner ON rental_orders(owner_id, created_at);
|
||||
CREATE INDEX idx_orders_status ON rental_orders(status, created_at);
|
||||
|
||||
-- 钱包流水
|
||||
CREATE INDEX idx_ledger_user ON wallet_ledger(user_id, created_at);
|
||||
|
||||
-- 聊天消息
|
||||
CREATE INDEX idx_messages_conv ON chat_messages(conversation_id, created_at);
|
||||
|
||||
-- 审计日志
|
||||
CREATE INDEX idx_audit_admin ON admin_audit_logs(admin_id, created_at);
|
||||
CREATE INDEX idx_audit_time ON admin_audit_logs(created_at);
|
||||
```
|
||||
|
||||
### 4.3 性能瓶颈分析
|
||||
|
||||
**潜在慢查询点**(基于代码review):
|
||||
1. ✅ **分页优化已完成**:所有管理后台列表已统一分页样式
|
||||
2. ⚠️ **订单列表查询**:多条件筛选(status, renter_id, owner_id)可能需要复合索引
|
||||
3. ⚠️ **钱包流水**:大量流水记录可能导致深度分页慢查询
|
||||
4. ⚠️ **商品搜索**:全文搜索功能缺失(目前只能按status/review过滤)
|
||||
|
||||
---
|
||||
|
||||
## 五、压力测试结果评估
|
||||
|
||||
### 5.1 测试环境
|
||||
- **平台**:MacOS (Darwin 25.5.0)
|
||||
- **数据库**:MySQL 8.4 (Docker)
|
||||
- **数据规模**:
|
||||
- 用户:10,001
|
||||
- 商品:50,500
|
||||
- 订单:30,200
|
||||
- 钱包流水:100,500
|
||||
|
||||
### 5.2 性能基线(30并发60秒)
|
||||
|
||||
```
|
||||
场景:realistic(真实业务比例)
|
||||
- 35% 商品列表查询
|
||||
- 25% 商品详情查询
|
||||
- 15% 我的订单
|
||||
- 10% 钱包余额
|
||||
- 7% 聊天列表
|
||||
- 5% 订单详情
|
||||
- 2% 创建订单
|
||||
- 1% 支付订单
|
||||
|
||||
结果:
|
||||
✅ 总请求数:246,371
|
||||
✅ 成功率:100%
|
||||
✅ QPS:4,106.18
|
||||
|
||||
延迟分布:
|
||||
✅ P50:5ms ⭐ 优秀
|
||||
✅ P95:16ms ⭐ 优秀
|
||||
✅ P99:29ms ⭐ 良好
|
||||
✅ 最大:492ms
|
||||
```
|
||||
|
||||
### 5.3 性能评级
|
||||
|
||||
| 指标 | 标准 | 实际 | 评级 |
|
||||
|------|------|------|------|
|
||||
| QPS | >2000 | 4106 | ⭐⭐⭐ |
|
||||
| P50延迟 | <10ms | 5ms | ⭐⭐⭐ |
|
||||
| P95延迟 | <50ms | 16ms | ⭐⭐⭐ |
|
||||
| P99延迟 | <100ms | 29ms | ⭐⭐⭐ |
|
||||
| 成功率 | >95% | 100% | ⭐⭐⭐ |
|
||||
|
||||
**结论**:系统性能优秀,能够支撑中等规模业务(日活1万+)。
|
||||
|
||||
---
|
||||
|
||||
## 六、代码质量评估
|
||||
|
||||
### 6.1 优点
|
||||
|
||||
✅ **清晰的模块化设计**
|
||||
- 每个业务模块独立,职责明确
|
||||
- 依赖注入统一管理
|
||||
- 三层架构规范
|
||||
|
||||
✅ **完善的中间件体系**
|
||||
- 请求日志、认证、权限、错误恢复
|
||||
- 可复用、易扩展
|
||||
|
||||
✅ **RBAC权限系统**
|
||||
- 角色-权限分离
|
||||
- 灵活的权限配置
|
||||
- 细粒度权限控制
|
||||
|
||||
✅ **实时通信支持**
|
||||
- WebSocket客服系统
|
||||
- 订单状态推送
|
||||
- 在线状态管理
|
||||
|
||||
✅ **审计日志**
|
||||
- 记录所有管理后台操作
|
||||
- 便于追溯和审计
|
||||
|
||||
### 6.2 可改进点
|
||||
|
||||
⚠️ **缺少单元测试**
|
||||
- 建议:为核心业务逻辑(订单、支付、钱包)添加单元测试
|
||||
- 目标覆盖率:>60%
|
||||
|
||||
⚠️ **缺少集成测试**
|
||||
- 建议:为关键业务流程添加E2E测试
|
||||
- 场景:创建订单→支付→交接→归还→结算
|
||||
|
||||
⚠️ **缺少API文档维护**
|
||||
- 虽然有Swagger,但需要保持与代码同步
|
||||
- 建议:在CI中添加swagger检查
|
||||
|
||||
⚠️ **错误处理可以更细化**
|
||||
- 当前:统一错误码(如 "bad_request")
|
||||
- 建议:细分业务错误码(如 "listing_unavailable", "insufficient_balance")
|
||||
|
||||
⚠️ **缺少限流保护**
|
||||
- 建议:添加API限流中间件(如 rate limiter)
|
||||
- 保护高频API(登录、创建订单、支付)
|
||||
|
||||
---
|
||||
|
||||
## 七、安全性分析
|
||||
|
||||
### 7.1 已实现的安全措施
|
||||
|
||||
✅ **认证与授权**
|
||||
- JWT Token认证
|
||||
- RBAC权限控制
|
||||
- 实名认证要求(敏感操作)
|
||||
|
||||
✅ **数据安全**
|
||||
- 密码加密存储(假设)
|
||||
- 敏感信息脱敏(手机号、身份证)
|
||||
- 支付回调验签
|
||||
|
||||
✅ **输入验证**
|
||||
- 参数校验(Gin binding)
|
||||
- SQL注入防护(GORM参数化查询)
|
||||
|
||||
✅ **操作审计**
|
||||
- 管理员操作日志
|
||||
- IP地址记录
|
||||
|
||||
### 7.2 潜在安全风险
|
||||
|
||||
⚠️ **缺少HTTPS强制**
|
||||
- 建议:生产环境强制HTTPS
|
||||
- 在反向代理(Nginx)层面处理
|
||||
|
||||
⚠️ **短信验证码限流不足**
|
||||
- 当前:60秒冷却期
|
||||
- 建议:添加IP级别限流、图形验证码
|
||||
|
||||
⚠️ **WebSocket认证**
|
||||
- 需确认:WebSocket连接是否有认证机制
|
||||
- 建议:在握手阶段验证JWT token
|
||||
|
||||
⚠️ **文件上传安全**
|
||||
- 需确认:是否有文件类型/大小验证
|
||||
- 建议:文件类型白名单、病毒扫描
|
||||
|
||||
---
|
||||
|
||||
## 八、性能优化建议
|
||||
|
||||
### 8.1 数据库优化
|
||||
|
||||
**索引优化**:
|
||||
```sql
|
||||
-- 添加复合索引
|
||||
CREATE INDEX idx_orders_renter_status ON rental_orders(renter_id, status, created_at);
|
||||
CREATE INDEX idx_orders_owner_status ON rental_orders(owner_id, status, created_at);
|
||||
|
||||
-- 优化钱包流水查询
|
||||
CREATE INDEX idx_ledger_user_type ON wallet_ledger(user_id, biz_type, created_at);
|
||||
|
||||
-- 优化商品搜索
|
||||
CREATE INDEX idx_listings_game_status ON rental_listings(game_name, status, review_status);
|
||||
```
|
||||
|
||||
**查询优化**:
|
||||
- 使用游标分页替代offset(深度分页场景)
|
||||
- 添加查询结果缓存(商品列表、系统配置)
|
||||
|
||||
### 8.2 缓存策略
|
||||
|
||||
**推荐缓存内容**:
|
||||
```go
|
||||
// 热点商品(5分钟)
|
||||
"listing:hot:{id}" → Listing JSON
|
||||
|
||||
// 商品列表(1分钟)
|
||||
"listings:page:{page}:{params}" → []Listing JSON
|
||||
|
||||
// 用户信息(5分钟)
|
||||
"user:{id}" → User JSON
|
||||
|
||||
// 系统配置(长期)
|
||||
"config:{key}" → Config JSON
|
||||
|
||||
// 在线管理员列表(30秒)
|
||||
"admin:online" → []AdminID
|
||||
```
|
||||
|
||||
### 8.3 架构优化
|
||||
|
||||
**读写分离**:
|
||||
- 主从复制(MySQL Replication)
|
||||
- 读请求走从库
|
||||
- 写请求走主库
|
||||
|
||||
**消息队列**:
|
||||
- 异步任务:通知发送、日志写入、统计计算
|
||||
- 技术选型:RabbitMQ / Kafka / Redis Stream
|
||||
|
||||
**CDN加速**:
|
||||
- 静态资源(前端、图片)走CDN
|
||||
- 减轻服务器带宽压力
|
||||
|
||||
---
|
||||
|
||||
## 九、可扩展性分析
|
||||
|
||||
### 9.1 水平扩展能力
|
||||
|
||||
**无状态设计**:
|
||||
- ✅ HTTP服务无状态(JWT存储在客户端)
|
||||
- ✅ Session存储在Redis(支持多实例)
|
||||
- ⚠️ WebSocket有状态(需要sticky session或Redis pub/sub)
|
||||
|
||||
**负载均衡方案**:
|
||||
```
|
||||
┌────────────┐
|
||||
Internet ─────┤ Nginx LB │
|
||||
└──────┬─────┘
|
||||
│
|
||||
┌────────────┼────────────┐
|
||||
│ │ │
|
||||
┌───▼──┐ ┌──▼───┐ ┌───▼──┐
|
||||
│ API1 │ │ API2 │ │ API3 │
|
||||
└───┬──┘ └──┬───┘ └───┬──┘
|
||||
│ │ │
|
||||
└───────────┼────────────┘
|
||||
│
|
||||
┌───────▼────────┐
|
||||
│ MySQL/Redis │
|
||||
└────────────────┘
|
||||
```
|
||||
|
||||
### 9.2 数据库扩展
|
||||
|
||||
**垂直扩展**:
|
||||
- 升级MySQL配置(CPU、内存、SSD)
|
||||
- 优化MySQL参数(innodb_buffer_pool_size、max_connections)
|
||||
|
||||
**水平扩展**:
|
||||
- 分库分表(按用户ID哈希)
|
||||
- 读写分离(主从复制)
|
||||
- 分片方案(ShardingSphere)
|
||||
|
||||
---
|
||||
|
||||
## 十、部署与运维
|
||||
|
||||
### 10.1 容器化部署
|
||||
|
||||
**当前方案**:
|
||||
- Docker Compose(开发/测试环境)
|
||||
- 包含:MySQL, Redis, MinIO, Backend
|
||||
|
||||
**生产建议**:
|
||||
- Kubernetes编排
|
||||
- 自动伸缩(HPA)
|
||||
- 健康检查
|
||||
- 滚动更新
|
||||
|
||||
### 10.2 监控告警
|
||||
|
||||
**推荐方案**:
|
||||
```
|
||||
Prometheus + Grafana + AlertManager
|
||||
|
||||
监控指标:
|
||||
- QPS、延迟(P50/P95/P99)
|
||||
- 错误率
|
||||
- 数据库连接数
|
||||
- Redis内存使用率
|
||||
- API响应时间
|
||||
- 业务指标(订单量、交易额)
|
||||
|
||||
告警规则:
|
||||
- API错误率 > 5%
|
||||
- P99延迟 > 1秒
|
||||
- 数据库连接池耗尽
|
||||
- Redis内存 > 80%
|
||||
```
|
||||
|
||||
### 10.3 日志管理
|
||||
|
||||
**推荐方案**:
|
||||
```
|
||||
ELK Stack (Elasticsearch + Logstash + Kibana)
|
||||
|
||||
日志类型:
|
||||
- 访问日志(Nginx)
|
||||
- 应用日志(zap)
|
||||
- 错误日志
|
||||
- 审计日志
|
||||
|
||||
日志级别:
|
||||
开发:DEBUG
|
||||
生产:INFO(可动态调整)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十一、总结与建议
|
||||
|
||||
### 11.1 项目亮点
|
||||
|
||||
✅ **清晰的模块化架构**:易维护、易扩展
|
||||
✅ **完善的RBAC权限系统**:灵活、安全
|
||||
✅ **优秀的性能表现**:QPS 4000+, P95延迟16ms
|
||||
✅ **实时客服系统**:WebSocket支持
|
||||
✅ **审计日志完善**:可追溯、可审计
|
||||
|
||||
### 11.2 短期优化建议(1-2周)
|
||||
|
||||
1. ✅ **管理后台分页统一** - 已完成
|
||||
2. **添加API限流**:防止恶意请求
|
||||
3. **优化短信验证码限流**:增加图形验证码
|
||||
4. **完善错误码体系**:细分业务错误
|
||||
5. **添加关键接口的单元测试**
|
||||
|
||||
### 11.3 中期优化建议(1-2月)
|
||||
|
||||
1. **实现缓存层**:Redis缓存热点数据
|
||||
2. **数据库索引优化**:添加复合索引
|
||||
3. **实现读写分离**:MySQL主从复制
|
||||
4. **添加监控告警**:Prometheus + Grafana
|
||||
5. **完善API文档**:保持Swagger同步
|
||||
|
||||
### 11.4 长期演进建议(3-6月)
|
||||
|
||||
1. **微服务拆分**:订单、支付、聊天独立服务
|
||||
2. **引入消息队列**:异步任务处理
|
||||
3. **数据库分库分表**:应对数据增长
|
||||
4. **容器编排**:Kubernetes部署
|
||||
5. **全链路监控**:分布式追踪(Jaeger)
|
||||
|
||||
---
|
||||
|
||||
## 附录
|
||||
|
||||
### A. 技术债务清单
|
||||
|
||||
| 优先级 | 问题 | 影响 | 建议 |
|
||||
|-------|------|------|------|
|
||||
| P0 | 缺少单元测试 | 回归风险高 | 添加核心业务测试 |
|
||||
| P1 | 缺少API限流 | 容易被刷 | 添加限流中间件 |
|
||||
| P1 | 短信限流不足 | 验证码被刷 | 增加图形验证码 |
|
||||
| P2 | 缺少缓存层 | 数据库压力大 | 添加Redis缓存 |
|
||||
| P2 | 深度分页慢 | 用户体验差 | 游标分页 |
|
||||
| P3 | 缺少监控 | 故障发现慢 | Prometheus |
|
||||
|
||||
### B. 性能测试数据
|
||||
|
||||
**商品查询场景**(30并发60秒):
|
||||
- QPS:4,106
|
||||
- P50延迟:5ms
|
||||
- P95延迟:16ms
|
||||
- 成功率:100%
|
||||
|
||||
**管理后台场景**(待测试):
|
||||
- 预期QPS:2,000+
|
||||
- 预期P95延迟:<50ms
|
||||
|
||||
---
|
||||
|
||||
**报告编写人**:Claude Opus 4.8
|
||||
**审核状态**:已完成
|
||||
**下次更新**:根据性能测试结果动态调整
|
||||
@@ -1,94 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# 这个脚本用于删除已合并到 000001_init.sql 的旧迁移文件
|
||||
# 使用场景:迁移文件合并后,清理旧的分散文件
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
MIGRATIONS_DIR="${ROOT_DIR}/backend/migrations"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() {
|
||||
printf "${BLUE}[clean]${NC} %s\n" "$*"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
printf "${GREEN}[clean]${NC} %s\n" "$*"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
printf "${YELLOW}[clean]${NC} %s\n" "$*"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
printf "${RED}[clean]${NC} %s\n" "$*" >&2
|
||||
}
|
||||
|
||||
# 要删除的旧迁移文件列表
|
||||
OLD_MIGRATIONS=(
|
||||
"000002_payment_refund_schema.sql"
|
||||
"000003_add_indexes.sql"
|
||||
"000004_add_support_status.sql"
|
||||
"000005_add_announcements.sql"
|
||||
"000006_insert_sample_announcements.sql"
|
||||
"000007_add_announcement_permissions.sql"
|
||||
"000008_fix_announcement_charset.sql"
|
||||
)
|
||||
|
||||
main() {
|
||||
cd "${MIGRATIONS_DIR}"
|
||||
|
||||
log "检查旧迁移文件..."
|
||||
|
||||
local found=0
|
||||
local file
|
||||
for file in "${OLD_MIGRATIONS[@]}"; do
|
||||
if [[ -f "${file}" ]]; then
|
||||
found=$((found + 1))
|
||||
log_warn "发现旧文件:${file}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "${found}" == "0" ]]; then
|
||||
log_success "没有发现旧的迁移文件,无需清理"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log ""
|
||||
log "即将删除 ${found} 个旧迁移文件"
|
||||
log "这些文件的内容已经合并到 000001_init.sql 中"
|
||||
log ""
|
||||
|
||||
# 确认删除
|
||||
read -p "确认删除?(yes/no): " -r
|
||||
echo
|
||||
if [[ ! "${REPLY}" =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||
log "取消删除"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 执行删除
|
||||
local deleted=0
|
||||
for file in "${OLD_MIGRATIONS[@]}"; do
|
||||
if [[ -f "${file}" ]]; then
|
||||
rm -f "${file}"
|
||||
log_success "已删除:${file}"
|
||||
deleted=$((deleted + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
log ""
|
||||
log_success "清理完成,已删除 ${deleted} 个文件"
|
||||
log ""
|
||||
log "注意事项:"
|
||||
log "1. 如果是开发环境,建议执行:./scripts/dev.sh --clean-init"
|
||||
log "2. 如果是生产环境,建议执行:./scripts/deploy-prod.sh --clean-init"
|
||||
log "3. 这些命令会清理旧数据库并使用新的 000001_init.sql 初始化"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
+3
-16
@@ -62,7 +62,6 @@ show_help() {
|
||||
|
||||
选项:
|
||||
--reset-db 重置数据库(删除并重建)
|
||||
--seed-only 仅重新同步基础数据
|
||||
--no-migrate 不执行数据库迁移
|
||||
--no-frontend 不启动前端
|
||||
--no-backend 不启动后端
|
||||
@@ -90,14 +89,12 @@ show_help() {
|
||||
示例:
|
||||
./scripts/dev.sh # 正常启动
|
||||
./scripts/dev.sh --reset-db # 重置数据库后启动(推荐迁移后使用)
|
||||
./scripts/dev.sh --seed-only # 重新同步基础数据
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# 参数解析
|
||||
RESET_DB="${DEV_RESET_DB:-0}"
|
||||
SEED_ONLY=0
|
||||
NO_MIGRATE=0
|
||||
NO_FRONTEND=0
|
||||
NO_BACKEND=0
|
||||
@@ -108,10 +105,6 @@ while [[ $# -gt 0 ]]; do
|
||||
RESET_DB=1
|
||||
shift
|
||||
;;
|
||||
--seed-only)
|
||||
SEED_ONLY=1
|
||||
shift
|
||||
;;
|
||||
--no-migrate)
|
||||
NO_MIGRATE=1
|
||||
shift
|
||||
@@ -546,13 +539,13 @@ watch_processes() {
|
||||
|
||||
main() {
|
||||
need_cmd docker
|
||||
if [[ "${SEED_ONLY}" != "1" && "${NO_BACKEND}" == "0" ]]; then
|
||||
if [[ "${NO_BACKEND}" == "0" ]]; then
|
||||
need_cmd go
|
||||
fi
|
||||
if [[ "${SEED_ONLY}" != "1" && "${NO_FRONTEND}" == "0" ]]; then
|
||||
if [[ "${NO_FRONTEND}" == "0" ]]; then
|
||||
need_cmd npm
|
||||
fi
|
||||
if [[ "${SEED_ONLY}" != "1" && ( "${NO_BACKEND}" == "0" || "${NO_FRONTEND}" == "0" ) ]]; then
|
||||
if [[ "${NO_BACKEND}" == "0" || "${NO_FRONTEND}" == "0" ]]; then
|
||||
need_cmd curl
|
||||
fi
|
||||
|
||||
@@ -575,12 +568,6 @@ main() {
|
||||
reset_database
|
||||
run_migrations
|
||||
|
||||
# 仅同步基础数据模式
|
||||
if [[ "${SEED_ONLY}" == "1" ]]; then
|
||||
log_success "基础数据同步完成,退出"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${NO_BACKEND}" == "0" ]]; then
|
||||
ensure_port_free "${BACKEND_PORT}" "后端"
|
||||
start_backend
|
||||
|
||||
@@ -300,7 +300,7 @@ function run_stress_test() {
|
||||
log_info "编译压测工具..."
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
go build -o stress_test stress_test.go
|
||||
go build -o stress_test load_stress.go
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "压测工具编译失败"
|
||||
|
||||
Reference in New Issue
Block a user