Files
tyapi-server/internal/domains/admin/handlers/admin_handler.go
2025-07-11 21:05:58 +08:00

314 lines
9.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handlers
import (
"strconv"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"tyapi-server/internal/domains/admin/dto"
"tyapi-server/internal/domains/admin/services"
"tyapi-server/internal/shared/interfaces"
)
// AdminHandler 管理员HTTP处理器
type AdminHandler struct {
adminService *services.AdminService
responseBuilder interfaces.ResponseBuilder
logger *zap.Logger
}
// NewAdminHandler 创建管理员HTTP处理器
func NewAdminHandler(
adminService *services.AdminService,
responseBuilder interfaces.ResponseBuilder,
logger *zap.Logger,
) *AdminHandler {
return &AdminHandler{
adminService: adminService,
responseBuilder: responseBuilder,
logger: logger,
}
}
// Login 管理员登录
// @Summary 管理员登录
// @Description 管理员登录接口
// @Tags 管理员认证
// @Accept json
// @Produce json
// @Param request body dto.AdminLoginRequest true "登录请求"
// @Success 200 {object} dto.AdminLoginResponse
// @Failure 400 {object} interfaces.ErrorResponse
// @Failure 401 {object} interfaces.ErrorResponse
// @Router /admin/login [post]
func (h *AdminHandler) Login(c *gin.Context) {
var req dto.AdminLoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
h.logger.Warn("管理员登录参数验证失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
// 获取客户端信息
clientIP := c.ClientIP()
userAgent := c.GetHeader("User-Agent")
// 调用服务
response, err := h.adminService.Login(c.Request.Context(), &req, clientIP, userAgent)
if err != nil {
h.logger.Error("管理员登录失败", zap.Error(err))
h.responseBuilder.Unauthorized(c, err.Error())
return
}
h.responseBuilder.Success(c, response, "登录成功")
}
// CreateAdmin 创建管理员
// @Summary 创建管理员
// @Description 创建新管理员账户
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Param request body dto.AdminCreateRequest true "创建管理员请求"
// @Success 201 {object} interfaces.SuccessResponse
// @Failure 400 {object} interfaces.ErrorResponse
// @Failure 403 {object} interfaces.ErrorResponse
// @Router /admin [post]
func (h *AdminHandler) CreateAdmin(c *gin.Context) {
var req dto.AdminCreateRequest
if err := c.ShouldBindJSON(&req); err != nil {
h.logger.Warn("创建管理员参数验证失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
// 获取当前操作的管理员ID从JWT中解析
operatorID := h.getCurrentAdminID(c)
// 调用服务
err := h.adminService.CreateAdmin(c.Request.Context(), &req, operatorID)
if err != nil {
h.logger.Error("创建管理员失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Created(c, nil, "管理员创建成功")
}
// UpdateAdmin 更新管理员
// @Summary 更新管理员
// @Description 更新管理员信息
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Param id path string true "管理员ID"
// @Param request body dto.AdminUpdateRequest true "更新管理员请求"
// @Success 200 {object} interfaces.SuccessResponse
// @Failure 400 {object} interfaces.ErrorResponse
// @Failure 404 {object} interfaces.ErrorResponse
// @Router /admin/{id} [put]
func (h *AdminHandler) UpdateAdmin(c *gin.Context) {
adminID := c.Param("id")
if adminID == "" {
h.responseBuilder.BadRequest(c, "管理员ID不能为空")
return
}
var req dto.AdminUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
h.logger.Warn("更新管理员参数验证失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
// 获取当前操作的管理员ID
operatorID := h.getCurrentAdminID(c)
// 调用服务
err := h.adminService.UpdateAdmin(c.Request.Context(), adminID, &req, operatorID)
if err != nil {
h.logger.Error("更新管理员失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "管理员更新成功")
}
// ChangePassword 修改密码
// @Summary 修改密码
// @Description 管理员修改自己的密码
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Param request body dto.AdminPasswordChangeRequest true "修改密码请求"
// @Success 200 {object} interfaces.SuccessResponse
// @Failure 400 {object} interfaces.ErrorResponse
// @Router /admin/change-password [post]
func (h *AdminHandler) ChangePassword(c *gin.Context) {
var req dto.AdminPasswordChangeRequest
if err := c.ShouldBindJSON(&req); err != nil {
h.logger.Warn("修改密码参数验证失败", zap.Error(err))
h.responseBuilder.BadRequest(c, "请求参数错误")
return
}
// 获取当前管理员ID
adminID := h.getCurrentAdminID(c)
// 调用服务
err := h.adminService.ChangePassword(c.Request.Context(), adminID, &req)
if err != nil {
h.logger.Error("修改密码失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "密码修改成功")
}
// ListAdmins 获取管理员列表
// @Summary 获取管理员列表
// @Description 分页获取管理员列表
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param username query string false "用户名搜索"
// @Param email query string false "邮箱搜索"
// @Param role query string false "角色筛选"
// @Param is_active query bool false "状态筛选"
// @Success 200 {object} dto.AdminListResponse
// @Failure 400 {object} interfaces.ErrorResponse
// @Router /admin [get]
func (h *AdminHandler) ListAdmins(c *gin.Context) {
var req dto.AdminListRequest
// 解析查询参数
if page, err := strconv.Atoi(c.DefaultQuery("page", "1")); err == nil {
req.Page = page
} else {
req.Page = 1
}
if pageSize, err := strconv.Atoi(c.DefaultQuery("page_size", "10")); err == nil {
req.PageSize = pageSize
} else {
req.PageSize = 10
}
req.Username = c.Query("username")
req.Email = c.Query("email")
req.Role = c.Query("role")
if isActiveStr := c.Query("is_active"); isActiveStr != "" {
if isActive, err := strconv.ParseBool(isActiveStr); err == nil {
req.IsActive = &isActive
}
}
// 调用服务
response, err := h.adminService.ListAdmins(c.Request.Context(), &req)
if err != nil {
h.logger.Error("获取管理员列表失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取管理员列表失败")
return
}
h.responseBuilder.Success(c, response, "获取管理员列表成功")
}
// GetAdminByID 根据ID获取管理员
// @Summary 获取管理员详情
// @Description 根据ID获取管理员详细信息
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Param id path string true "管理员ID"
// @Success 200 {object} dto.AdminInfo
// @Failure 400 {object} interfaces.ErrorResponse
// @Failure 404 {object} interfaces.ErrorResponse
// @Router /admin/{id} [get]
func (h *AdminHandler) GetAdminByID(c *gin.Context) {
adminID := c.Param("id")
if adminID == "" {
h.responseBuilder.BadRequest(c, "管理员ID不能为空")
return
}
// 调用服务
admin, err := h.adminService.GetAdminByID(c.Request.Context(), adminID)
if err != nil {
h.logger.Error("获取管理员详情失败", zap.Error(err))
h.responseBuilder.NotFound(c, err.Error())
return
}
h.responseBuilder.Success(c, admin, "获取管理员详情成功")
}
// DeleteAdmin 删除管理员
// @Summary 删除管理员
// @Description 软删除管理员账户
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Param id path string true "管理员ID"
// @Success 200 {object} interfaces.SuccessResponse
// @Failure 400 {object} interfaces.ErrorResponse
// @Failure 404 {object} interfaces.ErrorResponse
// @Router /admin/{id} [delete]
func (h *AdminHandler) DeleteAdmin(c *gin.Context) {
adminID := c.Param("id")
if adminID == "" {
h.responseBuilder.BadRequest(c, "管理员ID不能为空")
return
}
// 获取当前操作的管理员ID
operatorID := h.getCurrentAdminID(c)
// 调用服务
err := h.adminService.DeleteAdmin(c.Request.Context(), adminID, operatorID)
if err != nil {
h.logger.Error("删除管理员失败", zap.Error(err))
h.responseBuilder.BadRequest(c, err.Error())
return
}
h.responseBuilder.Success(c, nil, "管理员删除成功")
}
// GetAdminStats 获取管理员统计信息
// @Summary 获取管理员统计
// @Description 获取管理员相关的统计信息
// @Tags 管理员管理
// @Accept json
// @Produce json
// @Success 200 {object} dto.AdminStatsResponse
// @Failure 400 {object} interfaces.ErrorResponse
// @Router /admin/stats [get]
func (h *AdminHandler) GetAdminStats(c *gin.Context) {
// 调用服务
stats, err := h.adminService.GetAdminStats(c.Request.Context())
if err != nil {
h.logger.Error("获取管理员统计失败", zap.Error(err))
h.responseBuilder.InternalError(c, "获取统计信息失败")
return
}
h.responseBuilder.Success(c, stats, "获取统计信息成功")
}
// getCurrentAdminID 获取当前管理员ID
func (h *AdminHandler) getCurrentAdminID(c *gin.Context) string {
// 这里应该从JWT令牌中解析出管理员ID
// 为了简化这里返回一个模拟的ID
// 实际实现中应该从中间件中获取
return "current_admin_id"
}