feat: 新增admin用户与会员管理接口

This commit is contained in:
root
2026-03-09 22:44:05 +08:00
parent 27617cd373
commit 386877da9a
6 changed files with 691 additions and 7 deletions
@@ -0,0 +1,120 @@
package handler
import (
"errors"
"net/http"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
adminservice "wx_service/internal/admin/service"
"wx_service/internal/model"
)
func (h *Handler) MembershipOverview(c *gin.Context) {
data, err := h.svc.MembershipOverview(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "load membership overview failed"))
return
}
c.JSON(http.StatusOK, model.Success(data))
}
func (h *Handler) ListMembershipRedeemCodes(c *gin.Context) {
page, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("page", "1")))
pageSize, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("page_size", "20")))
data, err := h.svc.ListMembershipRedeemCodes(c.Request.Context(), adminservice.ListMembershipRedeemCodesQuery{
Page: page,
PageSize: pageSize,
Keyword: c.Query("keyword"),
Status: c.Query("status"),
})
if err != nil {
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "load redeem codes failed"))
return
}
c.JSON(http.StatusOK, model.Success(data))
}
type createMembershipRedeemCodesRequest struct {
PackageType string `json:"package_type"`
DurationDays int `json:"duration_days"`
Quantity int `json:"quantity"`
MaxUses int `json:"max_uses"`
ExpiresAt string `json:"expires_at"`
}
func (h *Handler) CreateMembershipRedeemCodes(c *gin.Context) {
var req createMembershipRedeemCodesRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "invalid request payload"))
return
}
var expiresAt *time.Time
if strings.TrimSpace(req.ExpiresAt) != "" {
parsed, err := time.ParseInLocation("2006-01-02 15:04:05", req.ExpiresAt, time.Local)
if err != nil {
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "expires_at format should be YYYY-MM-DD HH:mm:ss"))
return
}
expiresAt = &parsed
}
codes, err := h.svc.CreateMembershipRedeemCodes(c.Request.Context(), adminservice.CreateMembershipRedeemCodesInput{
PackageType: req.PackageType,
DurationDays: req.DurationDays,
Quantity: req.Quantity,
MaxUses: req.MaxUses,
ExpiresAt: expiresAt,
})
if err != nil {
if errors.Is(err, adminservice.ErrInvalidInput) {
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "invalid input"))
return
}
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "create redeem codes failed"))
return
}
c.JSON(http.StatusOK, model.Success(gin.H{
"count": len(codes),
"codes": codes,
}))
}
type updateMembershipRedeemCodeStatusRequest struct {
Status string `json:"status"`
}
func (h *Handler) UpdateMembershipRedeemCodeStatus(c *gin.Context) {
id, err := parseUintID(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "invalid redeem code id"))
return
}
var req updateMembershipRedeemCodeStatusRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "invalid request payload"))
return
}
err = h.svc.UpdateMembershipRedeemCodeStatus(c.Request.Context(), id, req.Status)
if err != nil {
switch {
case errors.Is(err, adminservice.ErrMembershipRedeemCodeNotFound):
c.JSON(http.StatusNotFound, model.Error(http.StatusNotFound, "redeem code not found"))
case errors.Is(err, adminservice.ErrInvalidInput):
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "status must be active/disabled"))
default:
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "update redeem code status failed"))
}
return
}
c.JSON(http.StatusOK, model.Success(gin.H{"message": "更新成功"}))
}