3e265bd837
- 还原 /v1/public/user/invite_sales 接口及 /invite/sales 别名(与 invite_records 并存) 逻辑/handler/types 与197fed7d删除前版本完全一致,按fefbd4f5新 routes 结构注册 - 新增迁移 02155_promo_schema_fix: 幂等修复 subscribe_promo / order 列类型与索引偏差 - 同步 etc/ppanel.yaml 数据库连接配置 - 补齐相关需求与设计文档
154 lines
5.8 KiB
Markdown
154 lines
5.8 KiB
Markdown
# 用户端提现列表 API — 订阅字段现状调研
|
||
|
||
> 调研日期:2026-05-27
|
||
> 调研范围:用户端「提现记录列表」接口当前返回字段,重点关注是否包含订阅相关信息
|
||
|
||
## 一、接口信息
|
||
|
||
| 项目 | 值 |
|
||
|------|-----|
|
||
| 方法 | `GET` |
|
||
| 路径 | `/v1/public/user/withdrawal_log` |
|
||
| 认证 | JWT Token(`AuthMiddleware` + `DeviceMiddleware`) |
|
||
| 分组 | `apis/public/user.api` |
|
||
|
||
## 二、文件定位
|
||
|
||
| 层 | 路径 |
|
||
|----|------|
|
||
| API DSL | `apis/public/user.api:118` (`WithdrawalLog`) / `apis/public/user.api:368` (路由) |
|
||
| Handler | `internal/handler/public/user/queryWithdrawalLogHandler.go` |
|
||
| Logic | `internal/logic/public/user/queryWithdrawalLogLogic.go:30` |
|
||
| 类型生成 | `internal/types/types.go`(`WithdrawalLog`、`QueryWithdrawalLogListRequest`、`QueryWithdrawalLogListResponse`) |
|
||
| 数据模型 | `internal/model/user/user.go:167` (`Withdrawal`,表名 `withdrawals`) |
|
||
|
||
## 三、请求参数
|
||
|
||
```go
|
||
QueryWithdrawalLogListRequest {
|
||
Page int `form:"page"`
|
||
Size int `form:"size"`
|
||
}
|
||
```
|
||
|
||
- 默认值:`page=1`、`size=10`(在 logic 内兜底)
|
||
|
||
## 四、响应结构
|
||
|
||
### 4.1 顶层响应
|
||
|
||
```go
|
||
QueryWithdrawalLogListResponse {
|
||
List []WithdrawalLog `json:"list"`
|
||
Total int64 `json:"total"`
|
||
}
|
||
```
|
||
|
||
### 4.2 列表项 `WithdrawalLog`
|
||
|
||
```go
|
||
WithdrawalLog {
|
||
Id int64 `json:"id"`
|
||
UserId int64 `json:"user_id"`
|
||
Amount int64 `json:"amount"` // 单位:分
|
||
Content string `json:"content"` // 收款附加信息
|
||
Status uint8 `json:"status"` // 0:Pending 1:Approved 2:Rejected 3:Cancelled
|
||
Reason string `json:"reason,omitempty"` // 拒绝原因
|
||
Method uint8 `json:"method"` // 0:其他 1:支付宝 2:微信 3:USDT
|
||
Account string `json:"account"` // 收款账号
|
||
QrCodeUrl string `json:"qr_code_url"` // 收款码图片 URL
|
||
CreatedAt int64 `json:"created_at"`
|
||
UpdatedAt int64 `json:"updated_at"`
|
||
}
|
||
```
|
||
|
||
## 五、底层数据模型 `Withdrawal`
|
||
|
||
```go
|
||
type Withdrawal struct {
|
||
Id int64
|
||
UserId int64 // index:idx_user_id
|
||
Amount int64
|
||
Content string // type:text
|
||
Status uint8 // 0:Pending 1:Approved 2:Rejected 3:Cancelled
|
||
Reason string // varchar(500)
|
||
Method uint8 // 0:其他 1:支付宝 2:微信 3:USDT
|
||
Account string // varchar(255)
|
||
QrCodeUrl string // varchar(500)
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
}
|
||
```
|
||
|
||
> 表名:`withdrawals`,与用户关联仅靠 `user_id` 外键,**无任何订阅 ID / 订阅快照字段**。
|
||
|
||
## 六、订阅字段现状(核心结论)
|
||
|
||
### 6.1 当前结论
|
||
|
||
| 维度 | 是否包含订阅信息 |
|
||
|------|------------------|
|
||
| API 响应(`WithdrawalLog`) | ❌ 无 |
|
||
| 数据库表(`withdrawals`) | ❌ 无 |
|
||
| Logic 查询逻辑 | ❌ 无 JOIN、无附加查询 `user_subscribe` |
|
||
|
||
提现记录与订阅之间**完全没有关联**。原因:佣金来源于多次订单累计,提现是从「佣金余额(`user.commission`)」整体扣减,不绑定到任何具体订阅。
|
||
|
||
### 6.2 Logic 当前实现要点
|
||
|
||
```go
|
||
// internal/logic/public/user/queryWithdrawalLogLogic.go:46-72
|
||
query := l.svcCtx.DB.WithContext(l.ctx).
|
||
Model(&user.Withdrawal{}).
|
||
Where("user_id = ?", u.Id)
|
||
|
||
// 仅按 user_id 过滤 + 分页 + 倒序,无任何 Preload / Join
|
||
```
|
||
|
||
## 七、已发现的隐患(与本次需求关联)
|
||
|
||
### 7.1 时间戳违反项目约定 ⚠️
|
||
|
||
`queryWithdrawalLogLogic.go:70-71`:
|
||
|
||
```go
|
||
CreatedAt: row.CreatedAt.UnixMilli(),
|
||
UpdatedAt: row.UpdatedAt.UnixMilli(),
|
||
```
|
||
|
||
- 项目约定:**后端统一返回秒级 Unix 时间戳**(前端 `formatDate` 已按 `数字 × 1000` 处理)
|
||
- 当前实现返回毫秒级,前端会解析为约公元 +55000 年的日期,**展示必然异常**
|
||
- 修复方式:改为 `.Unix()`
|
||
|
||
> 该问题独立于「订阅字段」需求,但属于同一接口,建议同批修复。
|
||
|
||
## 八、可选扩展方向(待业务确认)
|
||
|
||
若产品希望在提现列表中展示订阅相关信息,可选方案如下:
|
||
|
||
| 方案 | 字段示意 | 实现成本 | 适用场景 |
|
||
|------|----------|----------|----------|
|
||
| A. 当前生效订阅摘要 | `current_subscribe: { id, name, expire_at }` | 中(每行额外查 `user_subscribe`) | 想让用户看到「我提的是哪个订阅产生的佣金对应的余额」 |
|
||
| B. 用户全部订阅列表 | `subscribes: [{ id, name, expire_at }]` | 高(N+1 风险) | 极少场景,需评估必要性 |
|
||
| C. 仅订阅 ID 数组 | `subscribe_ids: [int64]` | 低 | 仅前端跳详情用 |
|
||
| D. 不加,保持现状 | — | 0 | 若业务上提现与订阅本就无关 |
|
||
|
||
> **推荐先与产品确认动机**:提现是佣金余额提现,与订阅本身没有直接业务关系,加字段前需明确「让用户看到订阅信息要解决什么问题」。
|
||
|
||
## 九、相关接口(一并列出,便于对照)
|
||
|
||
| 接口 | 方法 | 路径 | 说明 |
|
||
|------|------|------|------|
|
||
| 提交提现 | POST | `/v1/public/user/commission_withdraw` | 入参 `CommissionWithdrawRequest`,返回 `WithdrawalLog` |
|
||
| 取消提现 | POST | `/v1/public/user/withdrawal_cancel` | 入参 `CancelWithdrawalRequest`,返回 `WithdrawalLog` |
|
||
| 提现记录列表 | GET | `/v1/public/user/withdrawal_log` | 本文主角 |
|
||
|
||
> 三个接口共用 `WithdrawalLog` 类型,**任何字段变更需统一同步**,否则前端类型会错位。
|
||
|
||
## 十、后续动作建议
|
||
|
||
1. **产品确认**:是否真的需要在提现列表里返回订阅字段?目的是什么?
|
||
2. **若需新增**:在 `apis/public/user.api` 修改 `WithdrawalLog`,运行 goctl 重新生成,再补 Logic 查询。
|
||
3. **顺手修复**:将 `UnixMilli()` 改为 `Unix()`(独立小 PR 即可)。
|
||
4. **如新增订阅字段**:注意三个接口(list / cancel / withdraw)的返回结构同步,避免前端类型联动断裂。
|