v1.0
This commit is contained in:
211
邀请链接和二维码生成逻辑说明.md
Normal file
211
邀请链接和二维码生成逻辑说明.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# 邀请链接和二维码生成逻辑说明
|
||||
|
||||
## 一、邀请链接生成逻辑
|
||||
|
||||
### 1. API 端点
|
||||
- **路径**: `GET /agent/invite_link`
|
||||
- **处理器**: `GetInviteLinkHandler`
|
||||
- **逻辑**: `GetInviteLinkLogic`
|
||||
|
||||
### 2. 生成流程
|
||||
|
||||
#### 步骤 1: 验证代理身份
|
||||
```go
|
||||
// 获取当前用户ID
|
||||
userID := ctxdata.GetUidFromCtx(ctx)
|
||||
|
||||
// 查询代理信息
|
||||
agent := AgentModel.FindOneByUserId(userID)
|
||||
```
|
||||
|
||||
#### 步骤 2: 生成邀请码
|
||||
- 生成一个8位随机邀请码(使用 `tool.Krand(8, tool.KC_RAND_KIND_ALL)`)
|
||||
- 检查邀请码是否已存在(最多重试10次)
|
||||
- 创建邀请码记录:
|
||||
- `agent_id`: 当前代理ID
|
||||
- `target_level`: 1(普通代理)
|
||||
- `status`: 0(未使用)
|
||||
- `expire_time`: NULL(不过期)
|
||||
- `remark`: "邀请链接生成"
|
||||
|
||||
#### 步骤 3: 构建邀请链接
|
||||
```go
|
||||
frontendDomain := "https://example.com" // TODO: 需要配置
|
||||
inviteLink := fmt.Sprintf("%s/register?invite_code=%s", frontendDomain, inviteCode)
|
||||
```
|
||||
|
||||
#### 步骤 4: 生成二维码URL
|
||||
```go
|
||||
qrCodeUrl := fmt.Sprintf("%s/api/v1/image/qrcode?type=invitation&content=%s", frontendDomain, inviteLink)
|
||||
```
|
||||
|
||||
### 3. 当前问题
|
||||
- ❌ `frontendDomain` 硬编码为 `"https://example.com"`,需要配置化
|
||||
- ❌ 二维码API (`/api/v1/image/qrcode`) 可能还未实现
|
||||
|
||||
## 二、二维码生成逻辑
|
||||
|
||||
### 1. 两种生成方式
|
||||
|
||||
#### 方式 A: 前端生成(当前使用)
|
||||
- **位置**: `ycc-proxy-webview/src/components/QRcode.vue`
|
||||
- **库**: `qrcode` (npm)
|
||||
- **逻辑**:
|
||||
```javascript
|
||||
// 如果提供了后端返回的 qrCodeUrl,优先使用
|
||||
if (mode === "invitation" && qrCodeUrl) {
|
||||
// 加载后端生成的二维码图片
|
||||
qrImg.src = qrCodeUrl;
|
||||
} else {
|
||||
// 前端生成二维码
|
||||
QRCode.toDataURL(url, { width: 150, margin: 0 });
|
||||
}
|
||||
```
|
||||
|
||||
#### 方式 B: 后端生成(已实现服务但可能缺少API端点)
|
||||
- **服务**: `ImageService.ProcessImageWithQRCode()`
|
||||
- **功能**:
|
||||
- 支持两种类型:`promote`(推广)和 `invitation`(邀请)
|
||||
- 加载背景图片(`static/images/yq_qrcode_1.png` 或 `tg_qrcode_1.png`)
|
||||
- 生成二维码并合成到背景图上
|
||||
- 返回 PNG 格式图片
|
||||
|
||||
### 2. 二维码海报生成流程
|
||||
|
||||
#### 推广海报(promote模式)
|
||||
- **背景图**: `static/images/tg_qrcode_1.png` - `tg_qrcode_8.jpg`(8张轮播图)
|
||||
- **二维码位置**: 左下角
|
||||
- 尺寸: 280px
|
||||
- 位置: X=192px, Y=距离底部190px
|
||||
- **用途**: 推广产品查询服务
|
||||
|
||||
#### 邀请海报(invitation模式)
|
||||
- **背景图**: `static/images/yq_qrcode_1.png`
|
||||
- **二维码位置**: 中间偏上
|
||||
- 尺寸: 360px
|
||||
- 位置: 水平居中,垂直位置Y=555px
|
||||
- **用途**: 邀请好友成为下级代理
|
||||
|
||||
### 3. 前端海报合成逻辑
|
||||
|
||||
```javascript
|
||||
// 1. 加载海报背景图
|
||||
posterImg.src = posterImages[index];
|
||||
|
||||
// 2. 生成或加载二维码
|
||||
if (mode === "invitation" && qrCodeUrl) {
|
||||
// 使用后端返回的二维码
|
||||
qrImg.src = qrCodeUrl;
|
||||
} else {
|
||||
// 前端生成二维码
|
||||
QRCode.toDataURL(url);
|
||||
}
|
||||
|
||||
// 3. 在Canvas上绘制
|
||||
ctx.drawImage(posterImg, 0, 0); // 背景
|
||||
ctx.drawImage(qrCodeImg, x, y, size, size); // 二维码
|
||||
```
|
||||
|
||||
## 三、数据流程
|
||||
|
||||
### 邀请链接流程
|
||||
|
||||
```
|
||||
用户点击"生成邀请链接"
|
||||
↓
|
||||
前端调用 GET /agent/invite_link
|
||||
↓
|
||||
后端逻辑 (GetInviteLinkLogic):
|
||||
1. 验证代理身份
|
||||
2. 生成新的邀请码(8位随机,不过期)
|
||||
3. 保存到 agent_invite_code 表
|
||||
4. 构建邀请链接: https://domain/register?invite_code=XXXXX
|
||||
5. 构建二维码URL: https://domain/api/v1/image/qrcode?type=invitation&content=...
|
||||
↓
|
||||
返回 { invite_link, qr_code_url }
|
||||
↓
|
||||
前端显示链接和二维码
|
||||
```
|
||||
|
||||
### 二维码使用流程
|
||||
|
||||
#### 邀请模式 (invitation)
|
||||
```
|
||||
后端返回 qrCodeUrl
|
||||
↓
|
||||
前端 QRcode 组件加载二维码图片
|
||||
↓
|
||||
如果加载成功: 直接使用后端生成的二维码海报
|
||||
如果加载失败: 降级到前端生成二维码
|
||||
↓
|
||||
合成到邀请海报背景图 (yq_qrcode_1.png)
|
||||
↓
|
||||
用户可以保存或分享海报
|
||||
```
|
||||
|
||||
#### 推广模式 (promote)
|
||||
```
|
||||
前端生成二维码 (使用 qrcode 库)
|
||||
↓
|
||||
合成到推广海报背景图 (tg_qrcode_1.png - 8.png)
|
||||
↓
|
||||
用户可以在多张海报中切换
|
||||
↓
|
||||
用户可以保存或分享海报
|
||||
```
|
||||
|
||||
## 四、相关数据库表
|
||||
|
||||
### agent_invite_code
|
||||
- 存储邀请码信息
|
||||
- 每个邀请链接对应一个邀请码记录
|
||||
- 备注:`"邀请链接生成"` 表示这是通过链接生成的
|
||||
|
||||
### agent_invite_code_usage
|
||||
- 存储邀请码使用历史
|
||||
- 记录每个代理是通过哪个邀请码成为的
|
||||
- 支持统计和查询
|
||||
|
||||
## 五、待完善的问题
|
||||
|
||||
### 1. 前端域名配置
|
||||
- ❌ 当前硬编码为 `"https://example.com"`
|
||||
- ✅ 应该从配置文件读取
|
||||
|
||||
### 2. 二维码API实现
|
||||
- ❓ `/api/v1/image/qrcode` 端点是否存在?
|
||||
- ✅ `ImageService.ProcessImageWithQRCode()` 已实现
|
||||
- ❓ 是否需要创建对应的 Handler 和路由?
|
||||
|
||||
### 3. 邀请码复用
|
||||
- 当前每次调用都生成新的邀请码
|
||||
- 是否应该复用已有的邀请码?
|
||||
|
||||
## 六、链接格式对比
|
||||
|
||||
### 邀请链接(成为代理)
|
||||
```
|
||||
格式: https://domain/register?invite_code=XXXXX
|
||||
参数: invite_code (8位邀请码)
|
||||
用途: 用户通过此链接注册成为代理
|
||||
```
|
||||
|
||||
### 推广链接(推广产品)
|
||||
```
|
||||
格式: https://domain/agent/promotionInquire/{linkIdentifier}
|
||||
参数: linkIdentifier (加密的JSON字符串,包含agent_id, product_id, set_price)
|
||||
用途: 用户通过此链接查询产品
|
||||
```
|
||||
|
||||
## 七、文件位置
|
||||
|
||||
### 后端
|
||||
- **邀请链接逻辑**: `app/main/api/internal/logic/agent/getinvitelinklogic.go`
|
||||
- **二维码服务**: `app/main/api/internal/service/imageService.go`
|
||||
- **推广链接逻辑**: `app/main/api/internal/logic/agent/generatinglinklogic.go`
|
||||
|
||||
### 前端
|
||||
- **二维码组件**: `ycc-proxy-webview/src/components/QRcode.vue`
|
||||
- **邀请页面**: `ycc-proxy-webview/src/views/Invitation.vue`
|
||||
- **推广查询页**: `ycc-proxy-webview/src/views/PromotionInquire.vue`
|
||||
|
||||
Reference in New Issue
Block a user