新功能: 还原 v1/public/user/invite_sales 接口 + promo schema 修复迁移
Build docker and publish / build (20.15.1) (push) Failing after 13m47s
Build docker and publish / build (20.15.1) (pull_request) Failing after 15m7s

- 还原 /v1/public/user/invite_sales 接口及 /invite/sales 别名(与 invite_records 并存)
  逻辑/handler/types 与 197fed7d 删除前版本完全一致,按 fefbd4f5 新 routes 结构注册
- 新增迁移 02155_promo_schema_fix: 幂等修复 subscribe_promo / order 列类型与索引偏差
- 同步 etc/ppanel.yaml 数据库连接配置
- 补齐相关需求与设计文档
This commit is contained in:
2026-05-28 20:46:37 -07:00
parent fefbd4f56a
commit 3e265bd837
12 changed files with 2418 additions and 2 deletions
+153
View File
@@ -0,0 +1,153 @@
# 用户端提现列表 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)的返回结构同步,避免前端类型联动断裂。