This commit is contained in:
2026-10-25 21:03:49 +08:00
parent 039528e759
commit 1245d118ff
3 changed files with 258 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
// Package userhdl 是后台管理小程序端用户的 HTTP 接入层。
package userhdl
import (
"strconv"
"github.com/gin-gonic/gin"
"portal-mini-go/internal/pkg/errors"
"portal-mini-go/internal/pkg/response"
usersvc "portal-mini-go/internal/service/admin/user"
)
// Handler 用户管理请求处理。
type Handler struct {
svc *usersvc.Service
}
func NewHandler(svc *usersvc.Service) *Handler { return &Handler{svc: svc} }
// List 分页列表用户。支持 query:mini_id(0 表示全部)、keyword、page、size。
func (h *Handler) List(c *gin.Context) {
miniID, _ := strconv.ParseUint(c.DefaultQuery("mini_id", "0"), 10, 64)
keyword := c.Query("keyword")
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
size, _ := strconv.Atoi(c.DefaultQuery("size", "20"))
list, total, err := h.svc.List(c.Request.Context(), usersvc.ListReq{
MiniID: miniID,
Keyword: keyword,
Page: page,
Size: size,
})
if err != nil {
c.Error(err)
return
}
response.OK(c, gin.H{"list": list, "total": total, "page": page, "size": size})
}
// Get 查询单个用户详情。
func (h *Handler) Get(c *gin.Context) {
id, ok := parseID(c)
if !ok {
return
}
u, err := h.svc.GetByID(c.Request.Context(), id)
if err != nil {
c.Error(err)
return
}
response.OK(c, u)
}
// UpdateReq 编辑用户资料请求;留空字段不更新。
type UpdateReq struct {
Nickname *string `json:"nickname"`
Avatar *string `json:"avatar"`
Status *int8 `json:"status"`
}
// Update 编辑用户资料(昵称 / 头像 / 状态)。
func (h *Handler) Update(c *gin.Context) {
id, ok := parseID(c)
if !ok {
return
}
var req UpdateReq
if err := c.ShouldBindJSON(&req); err != nil {
c.Error(errors.ErrBadRequest)
return
}
u, err := h.svc.Update(c.Request.Context(), id, usersvc.UpdateReq{
Nickname: req.Nickname,
Avatar: req.Avatar,
Status: req.Status,
})
if err != nil {
c.Error(err)
return
}
response.OK(c, u)
}
// StatusReq 禁用 / 启用请求。
type StatusReq struct {
Status int8 `json:"status" binding:"required"`
}
// SetStatus 禁用 / 启用用户。
func (h *Handler) SetStatus(c *gin.Context) {
id, ok := parseID(c)
if !ok {
return
}
var req StatusReq
if err := c.ShouldBindJSON(&req); err != nil {
c.Error(errors.ErrBadRequest)
return
}
u, err := h.svc.SetStatus(c.Request.Context(), id, req.Status)
if err != nil {
c.Error(err)
return
}
response.OK(c, u)
}
// parseID 从路径参数解析并校验 uint64 主键。
func parseID(c *gin.Context) (uint64, bool) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.Error(errors.ErrBadRequest)
return 0, false
}
return id, true
}
// Register 注册后台用户管理路由。g 已带 /api/admin 前缀与 JWT 鉴权中间件。
func Register(g *gin.RouterGroup, h *Handler) {
rg := g.Group("/users")
{
rg.GET("", h.List)
rg.GET("/:id", h.Get)
rg.PUT("/:id", h.Update)
rg.POST("/:id/status", h.SetStatus)
}
}
@@ -0,0 +1,78 @@
// Package usersvc 是后台管理小程序端用户的业务逻辑。
package usersvc
import (
"context"
"portal-mini-go/internal/model"
"portal-mini-go/internal/pkg/errors"
"portal-mini-go/internal/repository/user"
)
// Service 用户管理业务服务,依赖用户仓储。
type Service struct {
repo *user.Repository
}
func New(repo *user.Repository) *Service { return &Service{repo: repo} }
// ListReq 列表查询条件。
type ListReq struct {
MiniID uint64
Keyword string
Page int
Size int
}
// List 分页查询用户,缺省第 1 页、每页 20 条。
func (s *Service) List(ctx context.Context, req ListReq) ([]model.User, int64, error) {
page, size := req.Page, req.Size
if page <= 0 {
page = 1
}
if size <= 0 {
size = 20
}
return s.repo.AdminList(ctx, user.AdminListFilter{
MiniID: req.MiniID,
Keyword: req.Keyword,
Page: page,
Size: size,
})
}
// GetByID 按 ID 查询用户详情。
func (s *Service) GetByID(ctx context.Context, id uint64) (*model.User, error) {
return s.repo.AdminGet(ctx, id)
}
// UpdateReq 编辑用户资料请求;指针区分“未提供”与“置空”。
type UpdateReq struct {
Nickname *string
Avatar *string
Status *int8
}
// Update 编辑用户资料与状态,返回更新后的用户。
func (s *Service) Update(ctx context.Context, id uint64, req UpdateReq) (*model.User, error) {
if req.Status != nil {
if *req.Status != model.UserStatusEnabled && *req.Status != model.UserStatusDisabled {
return nil, errors.New(40000, "非法的用户状态")
}
}
if err := s.repo.AdminUpdate(ctx, id, req.Nickname, req.Avatar, req.Status); err != nil {
return nil, err
}
return s.repo.AdminGet(ctx, id)
}
// SetStatus 禁用 / 启用用户,返回更新后的用户。
func (s *Service) SetStatus(ctx context.Context, id uint64, status int8) (*model.User, error) {
if status != model.UserStatusEnabled && status != model.UserStatusDisabled {
return nil, errors.New(40000, "非法的用户状态")
}
if err := s.repo.AdminUpdate(ctx, id, nil, nil, &status); err != nil {
return nil, err
}
return s.repo.AdminGet(ctx, id)
}