## 手动充值功能说明文档

---

### 一、功能概述

手动充值功能允许玩家通过银行转账或USDT方式进行充值，管理员在后台审核并确认充值后，系统自动为玩家上分。

**核心流程**：

```
管理员配置收款方式（银行/USDT）
        ↓
玩家选择充值方式，输入金额，上传转账截图
        ↓
生成充值订单（状态：PENDING 审核中）
        ↓
管理员审核充值记录
   ├─ 批准 → 自动给玩家钱包上分（可调整金额）
   └─ 拒绝 → 记录拒绝原因
```

---

### 二、数据库表结构

#### `payment_methods` — 收款方式配置表

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | BigInt | 主键 |
| `method_type` | VARCHAR(20) | 类型：`BANK`（银行）/ `USDT` |
| `bank_name` | VARCHAR(128) | 银行名称（BANK 类型使用） |
| `account_holder` | VARCHAR(128) | 银行账户名（BANK 类型使用） |
| `account_number` | VARCHAR(128) | 银行账号（BANK 类型使用） |
| `usdt_address` | VARCHAR(256) | USDT 地址（USDT 类型使用） |
| `qr_code_url` | VARCHAR(500) | USDT 二维码图片 URL（USDT 类型使用） |
| `display_name` | VARCHAR(128) | 展示名称 |
| `sort_order` | INT | 排序序号，越小越靠前 |
| `is_active` | BOOLEAN | 是否启用（管理员可见性） |
| `show_on_player` | BOOLEAN | 是否对玩家展示 |
| `created_by` | BigInt | 创建者 ID |
| `created_at` / `updated_at` | DateTime | 创建/更新时间 |

#### `deposit_orders` — 充值订单表

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | BigInt | 主键 |
| `order_no` | VARCHAR(64) | 订单号（唯一），格式：`DEP{timestamp}{random}` |
| `player_id` | BigInt | 玩家 ID |
| `payment_method_id` | BigInt | 关联的收款方式 ID |
| `method_type` | VARCHAR(20) | 冗余的类型（BANK/USDT），便于筛选 |
| `amount` | DECIMAL(18,4) | 玩家申报的充值金额 |
| `screenshot_url` | VARCHAR(500) | 转账截图 URL |
| `status` | VARCHAR(20) | 状态：`PENDING` / `APPROVED` / `REJECTED` |
| `approved_amount` | DECIMAL(18,4) | 实际批准的金额（批准时写入，可能与申报金额不同） |
| `reviewer_id` | BigInt | 审核人 ID |
| `reviewed_at` | DateTime | 审核时间 |
| `reject_reason` | VARCHAR(500) | 拒绝原因 |
| `remark` | VARCHAR(500) | 备注 |
| `created_at` / `updated_at` | DateTime | 创建/更新时间 |

---

### 三、管理后台操作

#### 3.1 配置收款方式

**入口**：管理后台左侧菜单 → 「收款方式」

支持两种类型：

**银行转账**：
- 填写银行名称（如：工商银行）
- 填写账户持有人姓名
- 填写银行账号
- 设置展示名称（可选）
- 设置排序、是否启用、是否展示给玩家

**USDT 充值**：
- 填写 USDT 收款地址
- 上传 USDT 二维码图片（通过后台媒体库上传，类别为 `payments`）
- 设置展示名称（可选）
- 设置排序、是否启用、是否展示给玩家

**操作说明**：
- `Active` 开关：控制该收款方式是否启用（管理员可见）
- `Show Player` 开关：控制是否在前台展示给玩家
- 一个收款方式可以同时启用但不展示给玩家（用于暂停充值）
- 支持创建多个同类型的收款方式

#### 3.2 审核充值订单

**入口**：管理后台左侧菜单 → 「充值审核」

**列表功能**：
- 显示所有充值订单，包含：订单号、玩家、收款方式类型、金额、截图、状态、批准金额、审核人、时间
- 支持按状态筛选（全部/待审核/已批准/已拒绝）
- 支持按类型筛选（全部/银行/USDT）
- 支持按玩家用户名搜索
- 点击截图缩略图可放大查看

**批准操作**：
1. 点击订单行的「Approve」按钮
2. 在弹窗中查看截图
3. 系统默认填入玩家申报的金额，管理员可根据截图实际情况调整金额
4. 可选填写备注
5. 点击「Confirm Approve」确认

**批准后自动执行**：
- 订单状态变为 `APPROVED`
- 系统自动调用钱包充值服务，将批准金额添加到玩家可用余额
- 生成一条钱包交易记录，类型为 `PLAYER_DEPOSIT`
- 记录审核人和审核时间

**拒绝操作**：
1. 点击订单行的「Reject」按钮
2. 在弹窗中必须填写拒绝原因
3. 点击「Confirm Reject」确认

**拒绝后**：
- 订单状态变为 `REJECTED`
- 记录拒绝原因和审核人
- 玩家不会收到任何资金

---

### 四、玩家端操作

#### 4.1 充值入口

- 玩家登录后，进入「账单」页面
- 顶部有一个「+ 充值」按钮，点击进入充值页面
- 或直接访问 `/wallet/recharge`

#### 4.2 充值流程

1. **选择充值方式**：顶部有「银行转账」和「USDT」两个标签切换
2. **选择收款账户**：系统展示管理员配置的可用收款方式列表，点击选中
3. **查看收款信息**：
   - 银行转账：显示银行名称、账户持有人、银行账号（支持点击复制）
   - USDT：显示 USDT 地址（支持点击复制）和二维码图片
4. **输入充值金额**：输入实际转账的金额
5. **上传转账截图**：
   - 点击上传区域选择图片
   - 前端自动压缩图片（目标大小 ≤1MB，最大分辨率 1920px）
   - 原文件限制 10MB，压缩后限制 5MB
   - 支持预览和删除已选截图
6. **提交充值**：点击提交按钮，系统创建充值订单
7. **成功提示**：显示订单号，提示等待管理员审核

#### 4.3 查看充值记录

- 充值页面右上角有「记录」链接，或访问 `/wallet/recharge/history`
- 显示所有充值订单列表，每条订单显示：
  - 收款方式类型标签
  - 充值金额
  - 状态（审核中/已通过/已拒绝）
  - 收款方式名称、提交时间
  - 如果批准金额与申报金额不同，显示「实际到账」金额
  - 如果被拒绝，显示拒绝原因
- 支持下拉刷新

---

### 五、API 接口列表

#### 管理后台接口

| 方法 | 路径 | 权限 | 说明 |
|------|------|------|------|
| `POST` | `/admin/payment-methods` | `deposit.manage` | 创建收款方式 |
| `GET` | `/admin/payment-methods` | `deposit.manage` | 查看所有收款方式 |
| `PUT` | `/admin/payment-methods/:id` | `deposit.manage` | 更新收款方式 |
| `DELETE` | `/admin/payment-methods/:id` | `deposit.manage` | 停用收款方式（软删除） |
| `GET` | `/admin/deposit-orders` | `deposit.review` | 分页查看充值订单 |
| `POST` | `/admin/deposit-orders/:id/approve` | `deposit.review` | 批准充值订单 |
| `POST` | `/admin/deposit-orders/:id/reject` | `deposit.review` | 拒绝充值订单 |

**充值订单列表查询参数**：
- `page` — 页码（默认 1）
- `pageSize` — 每页数量（默认 20，最大 100）
- `status` — 状态筛选：`PENDING` / `APPROVED` / `REJECTED`
- `keyword` — 玩家用户名关键词
- `methodType` — 类型筛选：`BANK` / `USDT`
- `dateFrom` / `dateTo` — 日期范围（ISO 格式）

**批准充值订单请求体**：
```json
{
  "approvedAmount": 100.00,  // 可选，不传则使用玩家申报金额
  "remark": "备注信息"        // 可选
}
```

**拒绝充值订单请求体**：
```json
{
  "reason": "截图金额与申报金额不符"  // 必填
}
```

#### 玩家端接口

| 方法 | 路径 | 认证 | 说明 |
|------|------|------|------|
| `GET` | `/player/payment-methods` | 需要 | 查看可用的收款方式列表 |
| `POST` | `/player/deposit-orders` | 需要 | 提交充值订单（multipart/form-data） |
| `GET` | `/player/deposit-orders` | 需要 | 查看自己的充值记录 |

**提交充值订单**（multipart/form-data）：
- `paymentMethodId` — 收款方式 ID
- `amount` — 充值金额
- `screenshot` — 转账截图图片文件（最大 5MB，仅接受图片类型）

**查看收款方式请求参数**：
- `methodType` — 可选，筛选类型：`BANK` / `USDT`

---

### 六、文件存储

充值相关截图存储在 `uploads/deposits/` 目录下，文件命名格式：`{timestamp}-{random8}.{ext}`

USDT 二维码图片通过管理员上传接口上传，存储在 `uploads/payments/` 目录下。

**上传大小限制**：
- 管理员上传（USDT 二维码）：5MB
- 玩家上传（充值截图）：5MB（前端压缩后），原文件 10MB

---

### 七、错误码

| 错误码 | 说明 |
|--------|------|
| `INVALID_METHOD_TYPE` | 无效的收款方式类型 |
| `PAYMENT_METHOD_NOT_FOUND` | 收款方式不存在或已停用 |
| `ORDER_NOT_FOUND` | 充值订单不存在 |
| `ORDER_NOT_PENDING` | 订单不是待审核状态 |
| `REASON_REQUIRED` | 拒绝原因为必填项 |
| `SCREENSHOT_REQUIRED` | 转账截图为必填项 |
| `FILE_MUST_BE_IMAGE` | 必须上传图片文件 |
| `INVALID_AMOUNT` | 金额无效 |
| `PAYMENT_METHOD_REQUIRED` | 未选择收款方式 |

---

### 八、权限配置

新增两个后台权限码，需要在数据库中通过种子数据或手动添加到 `permissions` 表：

| 权限码 | 说明 |
|--------|------|
| `deposit.manage` | 管理收款方式 |
| `deposit.review` | 审核充值订单 |

并将这些权限分配给需要操作充值功能的管理员角色（通过 `role_permissions` 表关联）。

---

### 九、注意事项

1. **金额调整**：批准充值时，管理员可以调整实际充值金额。当玩家输入的金额与截图显示的不一致时，以截图为准进行调整。
2. **并发审核**：批准操作在数据库事务中执行，会检查订单状态是否为 `PENDING`，防止多人同时审核同一笔订单。
3. **停用收款方式**：删除操作为软删除（设置 `isActive=false` 和 `showOnPlayer=false`），不会删除历史记录。
4. **截图审核**：管理员应仔细核对截图中的转账金额、时间、收款账户是否与配置的收款方式一致。
5. **前端图片压缩**：使用 `browser-image-compression` 库在浏览器端压缩图片，减少上传时间和服务器存储压力。
