5.8 KiB
5.8 KiB
邀请链接和二维码生成逻辑说明
一、邀请链接生成逻辑
1. API 端点
- 路径:
GET /agent/invite_link - 处理器:
GetInviteLinkHandler - 逻辑:
GetInviteLinkLogic
2. 生成流程
步骤 1: 验证代理身份
// 获取当前用户ID
userID := ctxdata.GetUidFromCtx(ctx)
// 查询代理信息
agent := AgentModel.FindOneByUserId(userID)
步骤 2: 生成邀请码
- 生成一个8位随机邀请码(使用
tool.Krand(8, tool.KC_RAND_KIND_ALL)) - 检查邀请码是否已存在(最多重试10次)
- 创建邀请码记录:
agent_id: 当前代理IDtarget_level: 1(普通代理)status: 0(未使用)expire_time: NULL(不过期)remark: "邀请链接生成"
步骤 3: 构建邀请链接
frontendDomain := "https://example.com" // TODO: 需要配置
inviteLink := fmt.Sprintf("%s/register?invite_code=%s", frontendDomain, inviteCode)
步骤 4: 生成二维码URL
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) - 逻辑:
// 如果提供了后端返回的 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. 前端海报合成逻辑
// 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