# 邀请链接和二维码生成逻辑说明 ## 一、邀请链接生成逻辑 ### 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`