This commit is contained in:
Mrx
2026-03-02 16:34:47 +08:00
parent 7e2dda986f
commit be6d3e5f2c
8 changed files with 47 additions and 23 deletions

View File

@@ -123,8 +123,9 @@ type (
} }
// 生成邀请海报(背景图+二维码,返回 base64 // 生成邀请海报(背景图+二维码,返回 base64
GetInvitePosterReq { GetInvitePosterReq {
InviteLink string `form:"invite_link"` // 邀请链接(短链) InviteLink string `form:"invite_link"` // 邀请链接(短链)
Format string `form:"format,optional"` // 返回格式base64默认 Format string `form:"format,optional"` // 返回格式base64默认
TemplateIndex int `form:"template_index,optional"` // 模板序号 1-4默认 1
} }
GetInvitePosterResp { GetInvitePosterResp {
PosterBase64 string `json:"poster_base64"` // 海报图片 base64不含 data:image/png;base64, 前缀) PosterBase64 string `json:"poster_base64"` // 海报图片 base64不含 data:image/png;base64, 前缀)

View File

@@ -3,6 +3,7 @@ package agent
import ( import (
"context" "context"
"encoding/base64" "encoding/base64"
"fmt"
"strings" "strings"
"bdqr-server/app/main/model" "bdqr-server/app/main/model"
@@ -52,13 +53,20 @@ func (l *GetInvitePosterLogic) GetInvitePoster(req *types.GetInvitePosterReq) (r
return nil, errors.Wrapf(xerr.NewErrMsg("邀请链接不能为空"), "") return nil, errors.Wrapf(xerr.NewErrMsg("邀请链接不能为空"), "")
} }
// 3. 调用 ImageService 生成邀请海报(背景图 + 二维码 // 3. 确定模板类型1-4 对应 invitation_01 ~ invitation_04
imgData, _, err := l.svcCtx.ImageService.ProcessImageWithQRCode("invitation", inviteLink) templateIndex := req.TemplateIndex
if templateIndex < 1 || templateIndex > 4 {
templateIndex = 1
}
qrcodeType := fmt.Sprintf("invitation_%02d", templateIndex)
// 4. 调用 ImageService 生成邀请海报(背景图 + 二维码)
imgData, _, err := l.svcCtx.ImageService.ProcessImageWithQRCode(qrcodeType, inviteLink)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成海报失败: %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成海报失败: %v", err)
} }
// 4. 返回 base64 // 5. 返回 base64
posterBase64 := base64.StdEncoding.EncodeToString(imgData) posterBase64 := base64.StdEncoding.EncodeToString(imgData)
return &types.GetInvitePosterResp{ return &types.GetInvitePosterResp{
PosterBase64: posterBase64, PosterBase64: posterBase64,

View File

@@ -221,13 +221,16 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
return err return err
} }
// 3) 源用户软删除 // 3) 源用户软删除(若存在)
// 软删源用户(通常为临时用户),防止遗留无效账号;软删可保留历史痕迹,满足审计需求 // 源用户可能不存在(孤儿 authuser 已删或从未写入),此时跳过软删即可
currentUser, err := l.svcCtx.UserModel.FindOne(ctx, currentUserID) currentUser, err := l.svcCtx.UserModel.FindOne(ctx, currentUserID)
if err != nil { if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找当前用户失败: %v", err) if errors.Is(err, model.ErrNotFound) {
} l.Infof("[BindMobile] 源用户在 user 表中不存在,跳过软删 | sourceUserId: %s", currentUserID)
if err := l.svcCtx.UserModel.Delete(ctx, session, currentUser.Id); err != nil { } else {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找当前用户失败: %v", err)
}
} else if err := l.svcCtx.UserModel.Delete(ctx, session, currentUser.Id); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "删除当前用户失败: %v", err) return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "删除当前用户失败: %v", err)
} }
} }

View File

@@ -26,13 +26,19 @@ func NewImageService() *ImageService {
// ProcessImageWithQRCode 处理图片,在中间添加二维码 // ProcessImageWithQRCode 处理图片,在中间添加二维码
func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]byte, string, error) { func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]byte, string, error) {
// 1. 根据qrcodeType确定使用哪张背景图与 uniapp_ycc/src/static/invitation 下海报一致,需复制到本目录 static/images // 1. 根据qrcodeType确定使用哪张背景图与 uniapp static/invitation 下海报一致,需复制到本目录 static/images
var backgroundImageName string var backgroundImageName string
switch qrcodeType { switch qrcodeType {
case "promote": case "promote":
backgroundImageName = "tg_qrcode_1.png" backgroundImageName = "tg_qrcode_1.png"
case "invitation": case "invitation", "invitation_01":
backgroundImageName = "invitation_01.png" // 与 uniapp static/invitation/invitation_01.png 同一张图,部署时拷贝到 static/images backgroundImageName = "invitation_01.png"
case "invitation_02":
backgroundImageName = "invitation_02.png"
case "invitation_03":
backgroundImageName = "invitation_03.png"
case "invitation_04":
backgroundImageName = "invitation_04.png"
default: default:
backgroundImageName = "tg_qrcode_1.png" // 默认使用第一张图片 backgroundImageName = "tg_qrcode_1.png" // 默认使用第一张图片
} }
@@ -77,12 +83,11 @@ func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]b
qrX = 192 // 距左边180px qrX = 192 // 距左边180px
qrY = imgHeight - qrSize - 190 // 距底边100px qrY = imgHeight - qrSize - 190 // 距底边100px
case "invitation": case "invitation", "invitation_01", "invitation_02", "invitation_03", "invitation_04":
// invitation类型:精确设置二维码尺寸 // invitation 类型(多模板):二维码尺寸与位置一致
qrSize = 138 // 固定尺寸320px qrSize = 138
// 中间偏上位置 qrX = (imgWidth - qrSize) / 2
qrX = (imgWidth - qrSize) / 2 // 水平居中 qrY = 140
qrY = 140 // 垂直位置200px
default: default:
// 默认promote样式 // 默认promote样式
@@ -152,7 +157,7 @@ func (s *ImageService) loadImage(path string) (image.Image, error) {
// GetSupportedImageTypes 获取支持的图片类型列表 // GetSupportedImageTypes 获取支持的图片类型列表
func (s *ImageService) GetSupportedImageTypes() []string { func (s *ImageService) GetSupportedImageTypes() []string {
return []string{"promote", "invitation"} return []string{"promote", "invitation", "invitation_01", "invitation_02", "invitation_03", "invitation_04"}
} }
// CheckImageExists 检查指定类型的背景图是否存在 // CheckImageExists 检查指定类型的背景图是否存在
@@ -161,8 +166,14 @@ func (s *ImageService) CheckImageExists(qrcodeType string) bool {
switch qrcodeType { switch qrcodeType {
case "promote": case "promote":
backgroundImageName = "tg_qrcode_1.png" backgroundImageName = "tg_qrcode_1.png"
case "invitation": case "invitation", "invitation_01":
backgroundImageName = "invitation_01.png" backgroundImageName = "invitation_01.png"
case "invitation_02":
backgroundImageName = "invitation_02.png"
case "invitation_03":
backgroundImageName = "invitation_03.png"
case "invitation_04":
backgroundImageName = "invitation_04.png"
default: default:
backgroundImageName = "tg_qrcode_1.png" backgroundImageName = "tg_qrcode_1.png"
} }

View File

@@ -1398,8 +1398,9 @@ type GetInviteLinkResp struct {
} }
type GetInvitePosterReq struct { type GetInvitePosterReq struct {
InviteLink string `form:"invite_link"` // 邀请链接(短链) InviteLink string `form:"invite_link"` // 邀请链接(短链)
Format string `form:"format,optional"` // 返回格式base64默认 Format string `form:"format,optional"` // 返回格式base64默认
TemplateIndex int `form:"template_index,optional"` // 模板序号 1-4默认 1
} }
type GetInvitePosterResp struct { type GetInvitePosterResp struct {

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB