613 lines
28 KiB
Markdown
613 lines
28 KiB
Markdown
# 渠道管理与用户注册绑定调用链文档
|
||
|
||
## 概述
|
||
|
||
本文档描述 Bindbox Game 项目中渠道管理模块与用户注册绑定的调用链关系。
|
||
|
||
**渠道绑定的三种方式:**
|
||
1. **用户登录时绑定** - 微信/抖音登录时传入 `channel_code`
|
||
2. **定时任务自动绑定** - 直播间奖品发放时,根据活动关联渠道自动绑定主播邀请人
|
||
3. **抖音登录绑定** - 抖音小程序登录时传入 `channel_code`
|
||
|
||
---
|
||
|
||
## 一、数据模型
|
||
|
||
### 1.1 渠道表 (channels)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | int64 | 主键ID |
|
||
| name | string | 渠道名称 |
|
||
| code | string | 渠道唯一标识(用于登录时绑定) |
|
||
| type | string | 渠道类型 |
|
||
| remarks | string | 备注 |
|
||
| created_at | time | 创建时间 |
|
||
| updated_at | time | 更新时间 |
|
||
| deleted_at | time | 删除时间(软删) |
|
||
|
||
**文件位置**: `internal/repository/mysql/model/channels.gen.go:16-25`
|
||
|
||
### 1.2 用户表 (users) - 渠道相关字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | int64 | 主键ID |
|
||
| channel_id | int64 | 渠道ID(关联 channels.id) |
|
||
| invite_code | string | 用户唯一邀请码 |
|
||
| inviter_id | int64 | 邀请人用户ID |
|
||
| openid | string | 微信openid |
|
||
| unionid | string | 微信unionid |
|
||
|
||
**文件位置**: `internal/repository/mysql/model/users.gen.go:16-33`
|
||
|
||
---
|
||
|
||
## 二、调用链架构图
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 前端/客户端 │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ API 路由层 │
|
||
│ internal/router/router.go │
|
||
│ │
|
||
│ 渠道管理路由: │
|
||
│ - POST /api/admin/channels → CreateChannel() │
|
||
│ - PUT /api/admin/channels/:id → ModifyChannel() │
|
||
│ - DELETE /api/admin/channels/:id → DeleteChannel() │
|
||
│ - GET /api/admin/channels → ListChannels() │
|
||
│ - GET /api/admin/channels/:id/stats → ChannelStats() │
|
||
│ │
|
||
│ 用户登录路由: │
|
||
│ - POST /api/app/users/weixin/login → WeixinLogin() │
|
||
│ (携带 channel_code 参数) │
|
||
│ - POST /api/app/users/douyin/login → DouyinLogin() │
|
||
│ (携带 channel_code 参数) │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
┌─────────────────────┼─────────────────────┐
|
||
▼ ▼ ▼
|
||
┌─────────────────────────┐ ┌───────────────────┐ ┌───────────────────────┐
|
||
│ 渠道管理 API 层 │ │ 用户登录 API 层 │ │ 定时任务调度器 │
|
||
│ internal/api/admin/ │ │ internal/api/user/│ │ internal/service/ │
|
||
│ channels.go │ │ login_app.go │ │ douyin/scheduler.go │
|
||
│ │ │ login_douyin_app │ │ │
|
||
│ - CreateChannel() │ │ - WeixinLogin() │ │ - GrantLivestreamPrizes()
|
||
│ - ModifyChannel() │ │ - DouyinLogin() │ │ - bindAnchorInviter │
|
||
│ - DeleteChannel() │ │ 接收channel_code│ │ IfNeeded() │
|
||
│ - ListChannels() │ │ │ │ │
|
||
│ - ChannelStats() │ │ │ │ 每5分钟自动执行 │
|
||
└─────────────────────────┘ └───────────────────┘ └───────────────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────────────────────┐ ┌───────────────────┐ ┌───────────────────────┐
|
||
│ 渠道 Service 层 │ │ 用户 Service 层 │ │ 用户 Service 层 │
|
||
│ internal/service/ │ │ internal/service/ │ │ internal/service/user │
|
||
│ channel/channel.go │ │ user/ │ │ │
|
||
│ │ │ login_weixin.go │ │ - BindInviter() │
|
||
│ - Create() │ │ login_douyin.go │ │ (定时任务调用) │
|
||
│ - Modify() │ │ │ │ │
|
||
│ - Delete() │ │ - LoginWeixin() │ │ │
|
||
│ - List() │ │ - LoginDouyin() │ │ │
|
||
│ - GetStats() │ │ 查渠道并绑定用户 │ │ │
|
||
│ - GetByID() │ │ │ │ │
|
||
└─────────────────────────┘ └───────────────────┘ └───────────────────────┘
|
||
│ │ │
|
||
└─────────────────────┼─────────────────────┘
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 数据访问层 (DAO) │
|
||
│ internal/repository/mysql/dao/ │
|
||
│ │
|
||
│ - channels.gen.go 渠道表操作 │
|
||
│ - users.gen.go 用户表操作 │
|
||
│ - user_invites.gen.go 邀请关系表操作 │
|
||
│ - livestream_activities.gen.go 直播间活动表(含渠道字段) │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ MySQL 数据库 │
|
||
│ - channels 表 │
|
||
│ - users 表 (channel_id 字段) │
|
||
│ - user_invites 表 │
|
||
│ - livestream_activities 表 (channel_id, channel_code 字段) │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 三、详细调用链
|
||
|
||
### 3.1 渠道管理(管理端)
|
||
|
||
#### 创建渠道
|
||
|
||
```
|
||
HTTP POST /api/admin/channels
|
||
│
|
||
├── 参数: { name, code, type, remarks }
|
||
│
|
||
▼
|
||
internal/api/admin/channels.go:26 CreateChannel()
|
||
│
|
||
├── 验证参数
|
||
│
|
||
▼
|
||
internal/service/channel/channel.go:79 Create()
|
||
│
|
||
├── 创建 Channels 模型
|
||
│
|
||
▼
|
||
dao.Channels.Create(m)
|
||
│
|
||
▼
|
||
MySQL INSERT INTO channels
|
||
```
|
||
|
||
#### 查询渠道列表(含用户数统计)
|
||
|
||
```
|
||
HTTP GET /api/admin/channels
|
||
│
|
||
▼
|
||
internal/api/admin/channels.go:135 ListChannels()
|
||
│
|
||
▼
|
||
internal/service/channel/channel.go:111 List()
|
||
│
|
||
├── 1. 查询渠道列表
|
||
│ SELECT * FROM channels WHERE name LIKE ? ORDER BY id DESC
|
||
│
|
||
├── 2. 统计每个渠道的用户数
|
||
│ SELECT channel_id, count(*) as count
|
||
│ FROM users
|
||
│ WHERE channel_id IN (?)
|
||
│ GROUP BY channel_id
|
||
│
|
||
▼
|
||
返回渠道列表(含 user_count 字段)
|
||
```
|
||
|
||
#### 渠道数据分析
|
||
|
||
```
|
||
HTTP GET /api/admin/channels/:channel_id/stats
|
||
│
|
||
▼
|
||
internal/api/admin/channels.go:53 ChannelStats()
|
||
│
|
||
▼
|
||
internal/service/channel/channel.go:169 GetStats()
|
||
│
|
||
├── 1. 统计渠道用户总数
|
||
│ SELECT count(*) FROM users WHERE channel_id = ?
|
||
│
|
||
├── 2. 统计渠道订单数和GMV
|
||
│ SELECT count(*) as count, sum(actual_amount) as gmv
|
||
│ FROM orders o
|
||
│ JOIN users u ON u.id = o.user_id
|
||
│ WHERE u.channel_id = ? AND o.status = 2
|
||
│
|
||
├── 3. 月度用户增长统计
|
||
│ SELECT DATE_FORMAT(created_at, '%Y-%m') as date, count(*) as count
|
||
│ FROM users
|
||
│ WHERE channel_id = ? AND created_at >= ?
|
||
│ GROUP BY date
|
||
│
|
||
├── 4. 月度订单统计
|
||
│ SELECT DATE_FORMAT(created_at, '%Y-%m') as date, count(*), sum(actual_amount)
|
||
│ FROM orders o
|
||
│ JOIN users u ON u.id = o.user_id
|
||
│ WHERE u.channel_id = ? AND o.status = 2 AND o.created_at >= ?
|
||
│ GROUP BY date
|
||
│
|
||
▼
|
||
返回渠道统计数据
|
||
```
|
||
|
||
---
|
||
|
||
### 3.2 用户注册绑定渠道
|
||
|
||
#### 微信登录(绑定渠道)
|
||
|
||
```
|
||
HTTP POST /api/app/users/weixin/login
|
||
│
|
||
├── 参数: { code, invite_code, douyin_id, channel_code }
|
||
│
|
||
▼
|
||
internal/api/user/login_app.go:47 WeixinLogin()
|
||
│
|
||
├── 1. 微信 code2session 获取 openid/unionid
|
||
│
|
||
▼
|
||
internal/service/user/login_weixin.go:42 LoginWeixin()
|
||
│
|
||
├── 2. 查询渠道(如果传入 channel_code)
|
||
│ ch, _ := s.readDB.Channels.Where(Channels.Code.Eq(in.ChannelCode)).First()
|
||
│ channelID = ch.ID
|
||
│ 【文件位置: login_weixin.go:86-92】
|
||
│
|
||
├── 3. 查找或创建用户
|
||
│ ├── 查找: WHERE openid = ? OR unionid = ?
|
||
│ │
|
||
│ └── 创建新用户:
|
||
│ u = &model.Users{
|
||
│ Nickname: nickname,
|
||
│ Openid: in.OpenID,
|
||
│ ChannelID: channelID, // 绑定渠道
|
||
│ ...
|
||
│ }
|
||
│ 【文件位置: login_weixin.go:113-124】
|
||
│
|
||
├── 4. 更新已有用户(如果传入 channel_code)
|
||
│ if channelID > 0 {
|
||
│ UPDATE users SET channel_id = ? WHERE id = ?
|
||
│ }
|
||
│ 【文件位置: login_weixin.go:141-143】
|
||
│
|
||
├── 5. 处理邀请关系(如果传入 invite_code 且是新用户)
|
||
│ 【详见 3.3 节】
|
||
│
|
||
▼
|
||
返回用户信息和 Token
|
||
```
|
||
|
||
**关键代码片段**(`login_weixin.go:86-92`):
|
||
|
||
```go
|
||
// 查找渠道ID
|
||
var channelID int64
|
||
if in.ChannelCode != "" {
|
||
ch, _ := s.readDB.Channels.WithContext(ctx).Where(s.readDB.Channels.Code.Eq(in.ChannelCode)).First()
|
||
if ch != nil {
|
||
channelID = ch.ID
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3.3 抖音登录(绑定渠道)
|
||
|
||
```
|
||
HTTP POST /api/app/users/douyin/login
|
||
│
|
||
├── 参数: { code, anonymous_code, invite_code, channel_code }
|
||
│
|
||
▼
|
||
internal/api/user/login_douyin_app.go:44 DouyinLogin()
|
||
│
|
||
├── 参数校验
|
||
│
|
||
▼
|
||
internal/service/user/login_douyin.go:39 LoginDouyin()
|
||
│
|
||
├── 1. 抖音 code2session 获取 openid
|
||
│
|
||
├── 2. 查询渠道(如果传入 channel_code)
|
||
│ ch, _ := s.readDB.Channels.Where(Channels.Code.Eq(in.ChannelCode)).First()
|
||
│ channelID = ch.ID
|
||
│ 【文件位置: login_douyin.go:91-97】
|
||
│
|
||
├── 3. 查找或创建用户
|
||
│ ├── 查找: WHERE douyin_id = ? OR unionid = ?
|
||
│ │
|
||
│ └── 创建新用户:
|
||
│ u = &model.Users{
|
||
│ Nickname: nickname,
|
||
│ DouyinID: openID,
|
||
│ ChannelID: channelID, // 绑定渠道
|
||
│ ...
|
||
│ }
|
||
│ 【文件位置: login_douyin.go:119-127】
|
||
│
|
||
├── 4. 更新已有用户(如果传入 channel_code 且未绑定)
|
||
│ if channelID > 0 && u.ChannelID == 0 {
|
||
│ UPDATE users SET channel_id = ?
|
||
│ }
|
||
│ 【文件位置: login_douyin.go:143-144】
|
||
│
|
||
└── 5. 处理邀请关系(如果传入 invite_code 且是新用户)
|
||
```
|
||
|
||
---
|
||
|
||
### 3.4 邀请关系绑定
|
||
|
||
用户绑定邀请人有两种方式:
|
||
|
||
#### 方式一:登录时自动绑定(推荐)
|
||
|
||
```
|
||
用户登录时传入 invite_code 参数
|
||
│
|
||
▼
|
||
LoginWeixin() / LoginDouyin() 内部处理
|
||
│
|
||
├── 检查是否新用户
|
||
│
|
||
├── 查找邀请人(通过 invite_code)
|
||
│
|
||
├── 创建 user_invites 记录
|
||
│
|
||
├── 更新 users.inviter_id
|
||
│
|
||
▼
|
||
触发任务中心奖励: task.OnInviteSuccess()
|
||
```
|
||
|
||
#### 方式二:用户主动绑定
|
||
|
||
```
|
||
HTTP POST /api/app/users/inviter/bind
|
||
│
|
||
├── 参数: { invite_code }
|
||
│
|
||
▼
|
||
internal/api/user/bind_inviter_app.go:34 BindInviter()
|
||
│
|
||
▼
|
||
internal/service/user/bind_inviter.go:33 BindInviter()
|
||
│
|
||
├── 1. 加锁获取当前用户
|
||
│
|
||
├── 2. 检查是否已绑定(inviter_id != 0 则拒绝)
|
||
│
|
||
├── 3. 查找邀请人
|
||
│
|
||
├── 4. 创建 user_invites 记录
|
||
│
|
||
├── 5. 更新 users.inviter_id
|
||
│
|
||
▼
|
||
触发任务中心奖励: task.OnInviteSuccess()
|
||
```
|
||
|
||
---
|
||
|
||
### 3.5 定时任务自动绑定渠道(直播间奖品发放)
|
||
|
||
**重要场景:直播间用户通过渠道绑定主播邀请人**
|
||
|
||
```
|
||
定时任务 (每5分钟)
|
||
│
|
||
▼
|
||
internal/service/douyin/scheduler.go:24 StartDouyinOrderSync()
|
||
│
|
||
├── ticker5min.C 触发
|
||
│
|
||
▼
|
||
internal/service/douyin/scheduler.go:155 GrantLivestreamPrizes()
|
||
│
|
||
├── 1. 查找未发放的直播抽奖记录
|
||
│ SELECT * FROM livestream_draw_logs WHERE is_granted = 0
|
||
│
|
||
├── 2. 解析活动关联的渠道/主播邀请码
|
||
│ resolveActivityAnchorCodes()
|
||
│ 【文件位置: scheduler.go:418-489】
|
||
│
|
||
│ ├── 查询直播间活动的渠道信息
|
||
│ │ SELECT id, channel_id, channel_code
|
||
│ │ FROM livestream_activities
|
||
│ │ WHERE id IN (?)
|
||
│ │ 【文件位置: scheduler.go:451-458】
|
||
│ │
|
||
│ └── 补充缺失的渠道 code
|
||
│ fetchChannelCodes()
|
||
│ SELECT id, code FROM channels WHERE id IN (?)
|
||
│ 【文件位置: scheduler.go:491-513】
|
||
│
|
||
├── 3. 自动绑定主播邀请人(如果用户未绑定)
|
||
│ bindAnchorInviterIfNeeded(ctx, userID, anchorCode)
|
||
│ 【文件位置: scheduler.go:515-546】
|
||
│
|
||
│ ├── 查询用户是否已有邀请人
|
||
│ │ SELECT inviter_id FROM users WHERE id = ?
|
||
│ │
|
||
│ └── 如果 inviter_id == 0,调用绑定服务
|
||
│ s.userSvc.BindInviter(ctx, userID, BindInviterInput{InviteCode: anchorCode})
|
||
│ 【文件位置: scheduler.go:534】
|
||
│
|
||
└── 4. 发放奖品并更新状态
|
||
```
|
||
|
||
**关键代码:自动绑定主播邀请人**
|
||
|
||
```go
|
||
// scheduler.go:515-546
|
||
func (s *service) bindAnchorInviterIfNeeded(ctx context.Context, userID int64, anchorCode string) {
|
||
// 1. 检查用户是否已有邀请人
|
||
userRecord, err := s.readDB.Users.WithContext(ctx).
|
||
Select(s.readDB.Users.InviterID).
|
||
Where(s.readDB.Users.ID.Eq(userID)).
|
||
First()
|
||
if userRecord.InviterID != 0 {
|
||
return // 已绑定,跳过
|
||
}
|
||
|
||
// 2. 自动绑定主播邀请人
|
||
s.userSvc.BindInviter(ctx, userID, user.BindInviterInput{InviteCode: anchorCode})
|
||
}
|
||
```
|
||
|
||
**数据流:**
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────────────────────┐
|
||
│ 直播间活动配置 │
|
||
│ livestream_activities │
|
||
│ ├── channel_id (关联渠道ID) │
|
||
│ └── channel_code (主播邀请码) │
|
||
└───────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌───────────────────────────────────────────────────────────────────────┐
|
||
│ 直播抽奖记录 │
|
||
│ livestream_draw_logs │
|
||
│ ├── activity_id (关联活动) │
|
||
│ ├── local_user_id (本地用户ID) │
|
||
│ └── is_granted (发放状态) │
|
||
└───────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌───────────────────────────────────────────────────────────────────────┐
|
||
│ 定时任务处理 │
|
||
│ GrantLivestreamPrizes() │
|
||
│ │
|
||
│ 1. 查 activity → 获取 channel_code │
|
||
│ 2. 查 channels → 补充缺失的 code │
|
||
│ 3. 查 users.inviter_id → 检查是否已绑定 │
|
||
│ 4. 未绑定 → 调用 BindInviter() 绑定主播 │
|
||
└───────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌───────────────────────────────────────────────────────────────────────┐
|
||
│ 用户邀请关系 │
|
||
│ users.inviter_id = 主播用户ID │
|
||
│ user_invites 表新增记录 │
|
||
└───────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 四、核心文件索引
|
||
|
||
| 文件路径 | 说明 | 关键函数 |
|
||
|----------|------|----------|
|
||
| `internal/api/admin/channels.go` | 渠道管理 API | CreateChannel, ListChannels, ChannelStats |
|
||
| `internal/service/channel/channel.go` | 渠道业务逻辑 | Create, List, GetStats |
|
||
| `internal/api/user/login_app.go` | 用户登录 API (微信) | WeixinLogin |
|
||
| `internal/service/user/login_weixin.go` | 微信登录逻辑 | LoginWeixin(渠道绑定核心) |
|
||
| `internal/api/user/login_douyin_app.go` | 用户登录 API (抖音) | DouyinLogin |
|
||
| `internal/service/user/login_douyin.go` | 抖音登录逻辑 | LoginDouyin(渠道绑定核心) |
|
||
| `internal/api/user/bind_inviter_app.go` | 绑定邀请人 API | BindInviter |
|
||
| `internal/service/user/bind_inviter.go` | 绑定邀请人逻辑 | BindInviter |
|
||
| **`internal/service/douyin/scheduler.go`** | **抖音定时任务** | **GrantLivestreamPrizes, bindAnchorInviterIfNeeded** |
|
||
| `internal/repository/mysql/model/channels.gen.go` | 渠道模型 | Channels struct |
|
||
| `internal/repository/mysql/model/users.gen.go` | 用户模型 | Users struct(含 channel_id) |
|
||
| `internal/repository/mysql/model/user_invites.gen.go` | 邀请关系模型 | UserInvites struct |
|
||
| `internal/repository/mysql/model/livestream_activities.gen.go` | 直播间活动模型 | LivestreamActivities(含 channel_id, channel_code) |
|
||
| `internal/router/router.go` | 路由配置 | 渠道路由: 215-219 行 |
|
||
|
||
---
|
||
|
||
## 五、数据流图
|
||
|
||
### 5.1 用户注册绑定渠道流程
|
||
|
||
```
|
||
┌──────────┐ ┌──────────────┐ ┌────────────────┐
|
||
│ 前端 │────▶│ 微信登录 API │────▶│ 用户 Service │
|
||
│ │ │ │ │ │
|
||
│ channel_ │ │ code │ │ 1. code2session│
|
||
│ code │ │ invite_code │ │ 2. 查渠道 │
|
||
└──────────┘ └──────────────┘ │ 3. 创建/更新用户│
|
||
│ 4. 绑定邀请人 │
|
||
└───────┬────────┘
|
||
│
|
||
┌─────────────────────────┼─────────────────────────┐
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||
│ channels 表 │ │ users 表 │ │user_invites表│
|
||
│ │ │ │ │ │
|
||
│ code → ID │ │ channel_id │ │ inviter_id │
|
||
│ │ │ inviter_id │ │ invitee_id │
|
||
└──────────────┘ └──────────────┘ └──────────────┘
|
||
```
|
||
|
||
### 5.2 渠道统计查询流程
|
||
|
||
```
|
||
┌──────────┐ ┌──────────────┐ ┌────────────────┐
|
||
│ 管理后台 │────▶│ 渠道统计 API │────▶│ 渠道 Service │
|
||
│ │ │ │ │ │
|
||
│ 选择渠道 │ │ channel_id │ │ 1. 统计用户数 │
|
||
│ 时间范围 │ │ days │ │ 2. 统计订单数 │
|
||
└──────────┘ │ start_date │ │ 3. 统计GMV │
|
||
│ end_date │ │ 4. 月度趋势 │
|
||
└──────────────┘ └───────┬────────┘
|
||
│
|
||
┌─────────────────────────┴────────────────┐
|
||
│ │
|
||
▼ ▼
|
||
┌──────────────┐ ┌──────────────┐
|
||
│ users 表 │ │ orders 表 │
|
||
│ │ │ │
|
||
│ WHERE │ │ JOIN users │
|
||
│ channel_id=? │ │ WHERE │
|
||
│ │ │ channel_id=? │
|
||
└──────────────┘ └──────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 六、业务规则
|
||
|
||
### 6.1 渠道绑定规则
|
||
|
||
| 场景 | 触发条件 | 说明 |
|
||
|------|----------|------|
|
||
| 微信登录绑定 | 传入 `channel_code` | 查询 channels 表,绑定 channel_id 到用户 |
|
||
| 抖音登录绑定 | 传入 `channel_code` | 查询 channels 表,仅当用户未绑定时才更新 |
|
||
| 定时任务绑定 | 直播间活动配置了 `channel_code` | 自动绑定主播邀请人(邀请关系,非渠道) |
|
||
|
||
### 6.2 渠道与邀请人的区别
|
||
|
||
| 概念 | 字段 | 说明 |
|
||
|------|------|------|
|
||
| **渠道 (Channel)** | `users.channel_id` | 用户来源渠道,用于统计分析 |
|
||
| **邀请人 (Inviter)** | `users.inviter_id` | 邀请该用户注册的人,用于奖励计算 |
|
||
|
||
**定时任务场景:**
|
||
- 直播间活动的 `channel_code` 用作**主播邀请码**
|
||
- 定时任务调用 `BindInviter()` 绑定的是**邀请关系**,而非渠道
|
||
- 主播邀请码 = 某个用户的 `invite_code`(通常是主播账号)
|
||
|
||
### 6.3 邀请绑定规则
|
||
|
||
1. **仅限一次**: 用户绑定邀请人后不可更改
|
||
2. **不能自邀**: 用户不能邀请自己
|
||
3. **奖励触发**: 绑定成功后触发任务中心奖励逻辑
|
||
4. **定时任务补绑**: 直播间用户未绑定邀请人时,自动绑定主播
|
||
|
||
### 6.4 权限控制
|
||
|
||
渠道管理接口需要以下权限:
|
||
|
||
| 操作 | 权限标识 |
|
||
|------|----------|
|
||
| 创建渠道 | `channel:create` |
|
||
| 修改渠道 | `channel:modify` |
|
||
| 删除渠道 | `channel:delete` |
|
||
| 查看渠道 | `channel:view` |
|
||
|
||
---
|
||
|
||
## 七、相关迁移文件
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `migrations/20260223_add_channel_fields_to_livestream_activities.sql` | 直播间活动添加渠道字段 |
|
||
|
||
---
|
||
|
||
## 八、注意事项
|
||
|
||
1. **渠道 Code 唯一性**: 渠道的 `code` 字段必须唯一,用于用户登录时匹配
|
||
2. **统计性能**: 渠道统计涉及多表 JOIN,大数据量时需注意性能优化
|
||
3. **事务处理**: 用户创建和渠道绑定在同一事务中,保证数据一致性
|
||
4. **软删除**: 渠道删除为软删除,不影响已绑定用户
|
||
|
||
---
|
||
|
||
*文档生成时间: 2026-02-27*
|
||
*项目: bindbox_game* |