diff --git a/app/main/api/desc/front/agent.api b/app/main/api/desc/front/agent.api index d41b730..5d401b4 100644 --- a/app/main/api/desc/front/agent.api +++ b/app/main/api/desc/front/agent.api @@ -121,6 +121,14 @@ type ( GetInviteLinkResp { InviteLink string `json:"invite_link"` // 邀请链接 } + // 生成邀请海报(背景图+二维码,返回 base64) + GetInvitePosterReq { + InviteLink string `form:"invite_link"` // 邀请链接(短链) + Format string `form:"format,optional"` // 返回格式:base64(默认) + } + GetInvitePosterResp { + PosterBase64 string `json:"poster_base64"` // 海报图片 base64(不含 data:image/png;base64, 前缀) + } // 获取代理等级特权信息 GetLevelPrivilegeResp { Levels []LevelPrivilegeItem `json:"levels"` @@ -244,6 +252,10 @@ service main { @handler GetInviteLink get /invite_link (GetInviteLinkReq) returns (GetInviteLinkResp) + // 生成邀请海报(背景图+邀请链接二维码) + @handler GetInvitePoster + get /invite/poster (GetInvitePosterReq) returns (GetInvitePosterResp) + // 获取代理等级特权信息 @handler GetLevelPrivilege get /level/privilege returns (GetLevelPrivilegeResp) diff --git a/app/main/api/etc/main.dev.yaml b/app/main/api/etc/main.dev.yaml index ad82b07..67812c6 100644 --- a/app/main/api/etc/main.dev.yaml +++ b/app/main/api/etc/main.dev.yaml @@ -58,8 +58,8 @@ WechatH5: AppID: "wxb786749edb73eb04" AppSecret: "b2aad5ec8788eb1e74a3c385dd5aa282" WechatMini: - AppID: "xxx" # 小程序的AppID - AppSecret: "xxxx" # 小程序的AppSecret + AppID: "wxc17ebfe0d5b832b0" # 小程序的AppID + AppSecret: "92100f1fbad05309635cea0671d37995" # 小程序的AppSecret Query: ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒 AdminConfig: diff --git a/app/main/api/etc/main.yaml b/app/main/api/etc/main.yaml index 8a6971c..17845fd 100644 --- a/app/main/api/etc/main.yaml +++ b/app/main/api/etc/main.yaml @@ -55,8 +55,8 @@ WechatH5: AppID: "wxb786749edb73eb04" AppSecret: "b2aad5ec8788eb1e74a3c385dd5aa282" WechatMini: - AppID: "xxx" # 小程序的AppID - AppSecret: "xxxx" # 小程序的AppSecret + AppID: "wxc17ebfe0d5b832b0" # 小程序的AppID + AppSecret: "92100f1fbad05309635cea0671d37995" # 小程序的AppSecret Query: ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒 AdminConfig: diff --git a/app/main/api/internal/handler/agent/getinviteposterhandler.go b/app/main/api/internal/handler/agent/getinviteposterhandler.go new file mode 100644 index 0000000..008c9f2 --- /dev/null +++ b/app/main/api/internal/handler/agent/getinviteposterhandler.go @@ -0,0 +1,30 @@ +package agent + +import ( + "net/http" + + "bdqr-server/app/main/api/internal/logic/agent" + "bdqr-server/app/main/api/internal/svc" + "bdqr-server/app/main/api/internal/types" + "bdqr-server/common/result" + "bdqr-server/pkg/lzkit/validator" + + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetInvitePosterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetInvitePosterReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := agent.NewGetInvitePosterLogic(r.Context(), svcCtx) + resp, err := l.GetInvitePoster(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/main/api/internal/handler/routes.go b/app/main/api/internal/handler/routes.go index c0e9e75..18b09a9 100644 --- a/app/main/api/internal/handler/routes.go +++ b/app/main/api/internal/handler/routes.go @@ -661,6 +661,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/invite_link", Handler: agent.GetInviteLinkHandler(serverCtx), }, + { + Method: http.MethodGet, + Path: "/invite/poster", + Handler: agent.GetInvitePosterHandler(serverCtx), + }, { Method: http.MethodGet, Path: "/level/privilege", diff --git a/app/main/api/internal/logic/agent/getinviteposterlogic.go b/app/main/api/internal/logic/agent/getinviteposterlogic.go new file mode 100644 index 0000000..44ed140 --- /dev/null +++ b/app/main/api/internal/logic/agent/getinviteposterlogic.go @@ -0,0 +1,66 @@ +package agent + +import ( + "context" + "encoding/base64" + "strings" + + "bdqr-server/app/main/model" + "bdqr-server/common/ctxdata" + "bdqr-server/common/xerr" + + "github.com/pkg/errors" + + "bdqr-server/app/main/api/internal/svc" + "bdqr-server/app/main/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetInvitePosterLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetInvitePosterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetInvitePosterLogic { + return &GetInvitePosterLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetInvitePosterLogic) GetInvitePoster(req *types.GetInvitePosterReq) (resp *types.GetInvitePosterResp, err error) { + // 1. 需登录且为代理 + userID, err := ctxdata.GetUidFromCtx(l.ctx) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败, %v", err) + } + + _, err = l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID) + if err != nil { + if errors.Is(err, model.ErrNotFound) { + return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "") + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err) + } + + // 2. 邀请链接不能为空 + inviteLink := strings.TrimSpace(req.InviteLink) + if inviteLink == "" { + return nil, errors.Wrapf(xerr.NewErrMsg("邀请链接不能为空"), "") + } + + // 3. 调用 ImageService 生成邀请海报(背景图 + 二维码) + imgData, _, err := l.svcCtx.ImageService.ProcessImageWithQRCode("invitation", inviteLink) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成海报失败: %v", err) + } + + // 4. 返回 base64 + posterBase64 := base64.StdEncoding.EncodeToString(imgData) + return &types.GetInvitePosterResp{ + PosterBase64: posterBase64, + }, nil +} diff --git a/app/main/api/internal/service/imageService.go b/app/main/api/internal/service/imageService.go index 6c5ad79..922a773 100644 --- a/app/main/api/internal/service/imageService.go +++ b/app/main/api/internal/service/imageService.go @@ -26,13 +26,13 @@ func NewImageService() *ImageService { // ProcessImageWithQRCode 处理图片,在中间添加二维码 func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]byte, string, error) { - // 1. 根据qrcodeType确定使用哪张背景图 + // 1. 根据qrcodeType确定使用哪张背景图(与 uniapp_ycc/src/static/invitation 下海报一致,需复制到本目录 static/images) var backgroundImageName string switch qrcodeType { case "promote": backgroundImageName = "tg_qrcode_1.png" case "invitation": - backgroundImageName = "yq_qrcode_1.png" + backgroundImageName = "invitation_01.png" // 与 uniapp static/invitation/invitation_01.png 同一张图,部署时拷贝到 static/images default: backgroundImageName = "tg_qrcode_1.png" // 默认使用第一张图片 } @@ -79,10 +79,10 @@ func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]b case "invitation": // invitation类型:精确设置二维码尺寸 - qrSize = 360 // 固定尺寸320px + qrSize = 138 // 固定尺寸320px // 中间偏上位置 qrX = (imgWidth - qrSize) / 2 // 水平居中 - qrY = 555 // 垂直位置200px + qrY = 140 // 垂直位置200px default: // 默认(promote样式) @@ -162,7 +162,7 @@ func (s *ImageService) CheckImageExists(qrcodeType string) bool { case "promote": backgroundImageName = "tg_qrcode_1.png" case "invitation": - backgroundImageName = "yq_qrcode_1.png" + backgroundImageName = "invitation_01.png" default: backgroundImageName = "tg_qrcode_1.png" } diff --git a/app/main/api/internal/types/agent.go b/app/main/api/internal/types/agent.go index e288ae9..8b09565 100644 --- a/app/main/api/internal/types/agent.go +++ b/app/main/api/internal/types/agent.go @@ -116,6 +116,17 @@ type GetInviteLinkResp struct { InviteLink string `json:"invite_link"` // 邀请链接 } +// GetInvitePosterReq 生成邀请海报请求(邀请链接 + 可选 format=base64) +type GetInvitePosterReq struct { + InviteLink string `form:"invite_link"` // 邀请链接(短链) + Format string `form:"format,optional"` // 返回格式:base64(默认) +} + +// GetInvitePosterResp 生成邀请海报响应 +type GetInvitePosterResp struct { + PosterBase64 string `json:"poster_base64"` // 海报图片 base64(不含 data:image/png;base64, 前缀) +} + type GetLevelPrivilegeResp struct { Levels []LevelPrivilegeItem `json:"levels"` UpgradeToGoldFee float64 `json:"upgrade_to_gold_fee"` diff --git a/app/main/api/static/images/invitation_01.png b/app/main/api/static/images/invitation_01.png new file mode 100644 index 0000000..06e65ff Binary files /dev/null and b/app/main/api/static/images/invitation_01.png differ