Files
goalfylearning-admin/internal/api/handlers/invite_code_handler.go

459 lines
11 KiB
Go

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,
})
}