diff --git a/app/main/api/desc/front/agent.api b/app/main/api/desc/front/agent.api index 733e1d7..b154069 100644 --- a/app/main/api/desc/front/agent.api +++ b/app/main/api/desc/front/agent.api @@ -123,8 +123,9 @@ type ( } // 生成邀请海报(背景图+二维码,返回 base64) GetInvitePosterReq { - InviteLink string `form:"invite_link"` // 邀请链接(短链) - Format string `form:"format,optional"` // 返回格式:base64(默认) + InviteLink string `form:"invite_link"` // 邀请链接(短链) + Format string `form:"format,optional"` // 返回格式:base64(默认) + TemplateIndex int `form:"template_index,optional"` // 模板序号 1-4,默认 1 } GetInvitePosterResp { PosterBase64 string `json:"poster_base64"` // 海报图片 base64(不含 data:image/png;base64, 前缀) diff --git a/app/main/api/internal/logic/agent/getinviteposterlogic.go b/app/main/api/internal/logic/agent/getinviteposterlogic.go index 44ed140..c16da65 100644 --- a/app/main/api/internal/logic/agent/getinviteposterlogic.go +++ b/app/main/api/internal/logic/agent/getinviteposterlogic.go @@ -3,6 +3,7 @@ package agent import ( "context" "encoding/base64" + "fmt" "strings" "bdqr-server/app/main/model" @@ -52,13 +53,20 @@ func (l *GetInvitePosterLogic) GetInvitePoster(req *types.GetInvitePosterReq) (r return nil, errors.Wrapf(xerr.NewErrMsg("邀请链接不能为空"), "") } - // 3. 调用 ImageService 生成邀请海报(背景图 + 二维码) - imgData, _, err := l.svcCtx.ImageService.ProcessImageWithQRCode("invitation", inviteLink) + // 3. 确定模板类型(1-4 对应 invitation_01 ~ invitation_04) + 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 { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成海报失败: %v", err) } - // 4. 返回 base64 + // 5. 返回 base64 posterBase64 := base64.StdEncoding.EncodeToString(imgData) return &types.GetInvitePosterResp{ PosterBase64: posterBase64, diff --git a/app/main/api/internal/logic/user/bindmobilelogic.go b/app/main/api/internal/logic/user/bindmobilelogic.go index ef9b474..59c27d9 100644 --- a/app/main/api/internal/logic/user/bindmobilelogic.go +++ b/app/main/api/internal/logic/user/bindmobilelogic.go @@ -221,13 +221,16 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind return err } - // 3) 源用户软删除 - // 软删源用户(通常为临时用户),防止遗留无效账号;软删可保留历史痕迹,满足审计需求 + // 3) 源用户软删除(若存在) + // 源用户可能不存在(孤儿 auth:user 已删或从未写入),此时跳过软删即可 currentUser, err := l.svcCtx.UserModel.FindOne(ctx, currentUserID) if err != nil { - return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找当前用户失败: %v", err) - } - if err := l.svcCtx.UserModel.Delete(ctx, session, currentUser.Id); err != nil { + if errors.Is(err, model.ErrNotFound) { + l.Infof("[BindMobile] 源用户在 user 表中不存在,跳过软删 | sourceUserId: %s", currentUserID) + } 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) } } diff --git a/app/main/api/internal/service/imageService.go b/app/main/api/internal/service/imageService.go index 922a773..c36d4c0 100644 --- a/app/main/api/internal/service/imageService.go +++ b/app/main/api/internal/service/imageService.go @@ -26,13 +26,19 @@ func NewImageService() *ImageService { // ProcessImageWithQRCode 处理图片,在中间添加二维码 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 switch qrcodeType { case "promote": backgroundImageName = "tg_qrcode_1.png" - case "invitation": - backgroundImageName = "invitation_01.png" // 与 uniapp static/invitation/invitation_01.png 同一张图,部署时拷贝到 static/images + case "invitation", "invitation_01": + 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: backgroundImageName = "tg_qrcode_1.png" // 默认使用第一张图片 } @@ -77,12 +83,11 @@ func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]b qrX = 192 // 距左边180px qrY = imgHeight - qrSize - 190 // 距底边100px - case "invitation": - // invitation类型:精确设置二维码尺寸 - qrSize = 138 // 固定尺寸320px - // 中间偏上位置 - qrX = (imgWidth - qrSize) / 2 // 水平居中 - qrY = 140 // 垂直位置200px + case "invitation", "invitation_01", "invitation_02", "invitation_03", "invitation_04": + // invitation 类型(多模板):二维码尺寸与位置一致 + qrSize = 138 + qrX = (imgWidth - qrSize) / 2 + qrY = 140 default: // 默认(promote样式) @@ -152,7 +157,7 @@ func (s *ImageService) loadImage(path string) (image.Image, error) { // GetSupportedImageTypes 获取支持的图片类型列表 func (s *ImageService) GetSupportedImageTypes() []string { - return []string{"promote", "invitation"} + return []string{"promote", "invitation", "invitation_01", "invitation_02", "invitation_03", "invitation_04"} } // CheckImageExists 检查指定类型的背景图是否存在 @@ -161,8 +166,14 @@ func (s *ImageService) CheckImageExists(qrcodeType string) bool { switch qrcodeType { case "promote": backgroundImageName = "tg_qrcode_1.png" - case "invitation": + case "invitation", "invitation_01": 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: backgroundImageName = "tg_qrcode_1.png" } diff --git a/app/main/api/internal/types/types.go b/app/main/api/internal/types/types.go index e35447a..bcb1b4a 100644 --- a/app/main/api/internal/types/types.go +++ b/app/main/api/internal/types/types.go @@ -1398,8 +1398,9 @@ type GetInviteLinkResp struct { } type GetInvitePosterReq struct { - InviteLink string `form:"invite_link"` // 邀请链接(短链) - Format string `form:"format,optional"` // 返回格式:base64(默认) + InviteLink string `form:"invite_link"` // 邀请链接(短链) + Format string `form:"format,optional"` // 返回格式:base64(默认) + TemplateIndex int `form:"template_index,optional"` // 模板序号 1-4,默认 1 } type GetInvitePosterResp struct { diff --git a/app/main/api/static/images/invitation_02.png b/app/main/api/static/images/invitation_02.png new file mode 100644 index 0000000..61891b3 Binary files /dev/null and b/app/main/api/static/images/invitation_02.png differ diff --git a/app/main/api/static/images/invitation_03.png b/app/main/api/static/images/invitation_03.png new file mode 100644 index 0000000..9e1ca2b Binary files /dev/null and b/app/main/api/static/images/invitation_03.png differ diff --git a/app/main/api/static/images/invitation_04.png b/app/main/api/static/images/invitation_04.png new file mode 100644 index 0000000..4cc71f0 Binary files /dev/null and b/app/main/api/static/images/invitation_04.png differ