package handlers import ( "net/http" "regexp" "strconv" "strings" "goalfymax-admin/internal/config" "goalfymax-admin/internal/models" "goalfymax-admin/internal/services" "github.com/gin-gonic/gin" ) type InviteCodeHandler struct { service services.InviteCodeService userLevelService services.UserLevelConfigService } func NewInviteCodeHandler(service services.InviteCodeService, userLevelService services.UserLevelConfigService) *InviteCodeHandler { return &InviteCodeHandler{ service: service, userLevelService: userLevelService, } } // GetInviteCodeList 获取邀请码列表 func (h *InviteCodeHandler) GetInviteCodeList(c *gin.Context) { var req models.InviteCodeListRequest if err := c.ShouldBindQuery(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "参数错误", "data": nil, }) return } // 设置默认分页参数 if req.Page <= 0 { req.Page = 1 } if req.Size <= 0 { req.Size = 20 } response, err := h.service.List(&req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": 500, "message": err.Error(), "data": nil, }) return } // enrich invite_url base := config.GetConfig().SSO.SSOServerURL base = strings.TrimRight(base, "/") enriched := make([]gin.H, 0, len(response.List)) for _, item := range response.List { // 获取用户等级信息 var userLevelName string if item.UserLevelID != nil { if level, err := h.userLevelService.GetByID(*item.UserLevelID); err == nil { userLevelName = level.LevelName } } enriched = append(enriched, gin.H{ "id": item.ID, "code": item.Code, "is_used": item.IsUsed, "client_id": item.ClientID, "client_label": config.GetClientValue(item.ClientID), "email": item.Email, "user_level_id": item.UserLevelID, "user_level_name": userLevelName, "expires_at": item.ExpiresAt, "created_at": item.CreatedAt, "invite_url": base + "/invite/" + item.Code, }) } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "获取成功", "data": gin.H{ "list": enriched, "total": response.Total, }, }) } // GetInviteCodeDetail 获取邀请码详情 func (h *InviteCodeHandler) GetInviteCodeDetail(c *gin.Context) { idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "ID格式错误", "data": nil, }) return } inviteCode, err := h.service.GetByID(uint(id)) if err != nil { c.JSON(http.StatusNotFound, gin.H{ "code": 404, "message": "邀请码不存在", "data": nil, }) return } base := config.GetConfig().SSO.SSOServerURL base = strings.TrimRight(base, "/") // 获取用户等级信息 var userLevelName string if inviteCode.UserLevelID != nil { if level, err := h.userLevelService.GetByID(*inviteCode.UserLevelID); err == nil { userLevelName = level.LevelName } } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "获取成功", "data": gin.H{ "id": inviteCode.ID, "code": inviteCode.Code, "is_used": inviteCode.IsUsed, "client_id": inviteCode.ClientID, "client_label": config.GetClientValue(inviteCode.ClientID), "email": inviteCode.Email, "user_level_id": inviteCode.UserLevelID, "user_level_name": userLevelName, "expires_at": inviteCode.ExpiresAt, "created_at": inviteCode.CreatedAt, "invite_url": base + "/invite/" + inviteCode.Code, }, }) } // validateEmail 验证邮箱格式 func validateEmail(email string) bool { emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`) return emailRegex.MatchString(email) } // CreateInviteCode 创建邀请码(支持设置过期时间和邮箱列表) func (h *InviteCodeHandler) CreateInviteCode(c *gin.Context) { var req models.InviteCodeCreateRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "参数错误:" + err.Error(), "data": nil, }) return } // 验证邮箱格式 if len(req.Emails) > 0 { for _, email := range req.Emails { if email != "" && !validateEmail(email) { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "邮箱格式不正确: " + email, "data": nil, }) return } } } // 验证用户等级ID是否存在且启用 if req.UserLevelID != nil { userLevel, err := h.userLevelService.GetByID(*req.UserLevelID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "用户等级不存在", "data": nil, }) return } if userLevel.Status != 1 { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "用户等级已禁用", "data": nil, }) return } } inviteCodes, err := h.service.Create(&req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": 500, "message": err.Error(), "data": nil, }) return } base := config.GetConfig().SSO.SSOServerURL base = strings.TrimRight(base, "/") // 如果只创建了一个邀请码,返回单个对象(向后兼容) if len(inviteCodes) == 1 { inviteCode := inviteCodes[0] var userLevelName string if inviteCode.UserLevelID != nil { if level, err := h.userLevelService.GetByID(*inviteCode.UserLevelID); err == nil { userLevelName = level.LevelName } } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "创建成功", "data": gin.H{ "id": inviteCode.ID, "code": inviteCode.Code, "is_used": inviteCode.IsUsed, "client_id": inviteCode.ClientID, "client_label": config.GetClientValue(inviteCode.ClientID), "email": inviteCode.Email, "user_level_id": inviteCode.UserLevelID, "user_level_name": userLevelName, "expires_at": inviteCode.ExpiresAt, "created_at": inviteCode.CreatedAt, "invite_url": base + "/invite/" + inviteCode.Code, }, }) return } // 如果创建了多个邀请码,返回数组 enriched := make([]gin.H, 0, len(inviteCodes)) for _, inviteCode := range inviteCodes { var userLevelName string if inviteCode.UserLevelID != nil { if level, err := h.userLevelService.GetByID(*inviteCode.UserLevelID); err == nil { userLevelName = level.LevelName } } enriched = append(enriched, gin.H{ "id": inviteCode.ID, "code": inviteCode.Code, "is_used": inviteCode.IsUsed, "client_id": inviteCode.ClientID, "client_label": config.GetClientValue(inviteCode.ClientID), "email": inviteCode.Email, "user_level_id": inviteCode.UserLevelID, "user_level_name": userLevelName, "expires_at": inviteCode.ExpiresAt, "created_at": inviteCode.CreatedAt, "invite_url": base + "/invite/" + inviteCode.Code, }) } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "创建成功", "data": enriched, }) } // UpdateInviteCode 更新邀请码(支持更新过期时间) func (h *InviteCodeHandler) UpdateInviteCode(c *gin.Context) { idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "ID格式错误", "data": nil, }) return } var req models.InviteCodeUpdateRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "参数错误", "data": nil, }) return } inviteCode, err := h.service.Update(uint(id), &req) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": err.Error(), "data": nil, }) return } base := config.GetConfig().SSO.SSOServerURL base = strings.TrimRight(base, "/") // 获取用户等级信息 var userLevelName string if inviteCode.UserLevelID != nil { if level, err := h.userLevelService.GetByID(*inviteCode.UserLevelID); err == nil { userLevelName = level.LevelName } } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "更新成功", "data": gin.H{ "id": inviteCode.ID, "code": inviteCode.Code, "is_used": inviteCode.IsUsed, "client_id": inviteCode.ClientID, "client_label": config.GetClientValue(inviteCode.ClientID), "email": inviteCode.Email, "user_level_id": inviteCode.UserLevelID, "user_level_name": userLevelName, "expires_at": inviteCode.ExpiresAt, "created_at": inviteCode.CreatedAt, "invite_url": base + "/invite/" + inviteCode.Code, }, }) } // DeleteInviteCode 删除邀请码 func (h *InviteCodeHandler) DeleteInviteCode(c *gin.Context) { idStr := c.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "ID格式错误", "data": nil, }) return } err = h.service.Delete(uint(id)) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": 500, "message": err.Error(), "data": nil, }) return } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "删除成功", "data": nil, }) } // GetInviteCodeStatistics 获取统计信息 func (h *InviteCodeHandler) GetInviteCodeStatistics(c *gin.Context) { stats, err := h.service.GetStatistics() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": 500, "message": err.Error(), "data": nil, }) return } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "获取成功", "data": stats, }) } // MarkInviteCodeAsUsed 标记邀请码为已使用 func (h *InviteCodeHandler) MarkInviteCodeAsUsed(c *gin.Context) { var req struct { Code string `json:"code" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "参数错误", "data": nil, }) return } err := h.service.MarkAsUsed(req.Code) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": err.Error(), "data": nil, }) return } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "标记成功", "data": nil, }) } // ValidateInviteCode 验证邀请码是否有效 func (h *InviteCodeHandler) ValidateInviteCode(c *gin.Context) { var req struct { Code string `json:"code" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": "参数错误", "data": nil, }) return } err := h.service.ValidateInviteCode(req.Code) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 400, "message": err.Error(), "data": nil, }) return } c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "邀请码有效", "data": nil, }) } // GetClientOptions 获取客户端选项列表 func (h *InviteCodeHandler) GetClientOptions(c *gin.Context) { options := config.GetClientOptions() c.JSON(http.StatusOK, gin.H{ "code": 200, "message": "获取成功", "data": options, }) }