154 lines
4.1 KiB
Go
154 lines
4.1 KiB
Go
package admin
|
||
|
||
import (
|
||
"net/http"
|
||
"strconv"
|
||
|
||
"metazone.cc/mce/internal/common"
|
||
"metazone.cc/mce/internal/model"
|
||
"metazone.cc/mce/internal/service"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// Note: service import kept for ListUsersParams / ListUsersResult DTOs
|
||
|
||
// AdminController 管理后台控制器
|
||
type AdminController struct {
|
||
adminService adminUseCase
|
||
}
|
||
|
||
// NewAdminController 构造函数
|
||
func NewAdminController(adminService adminUseCase) *AdminController {
|
||
return &AdminController{adminService: adminService}
|
||
}
|
||
|
||
// Dashboard 管理首页(欢迎页)
|
||
func (ac *AdminController) Dashboard(c *gin.Context) {
|
||
totalUsers, err := ac.adminService.CountUsers()
|
||
if err != nil {
|
||
totalUsers = 0
|
||
}
|
||
postStats, err := ac.adminService.GetPostStats()
|
||
if err != nil {
|
||
postStats = &service.PostStats{}
|
||
}
|
||
storeMetrics := ac.adminService.GetStoreMetrics()
|
||
c.HTML(http.StatusOK, "admin/dashboard/index.html", common.BuildAdminPageData(c, gin.H{
|
||
"Title": "管理首页",
|
||
"TotalUsers": totalUsers,
|
||
"PostTotal": postStats.Total,
|
||
"PostApproved": postStats.Approved,
|
||
"PostPending": postStats.Pending,
|
||
"StoreType": storeMetrics.Type,
|
||
"StoreHealthy": storeMetrics.Healthy,
|
||
"StoreDegraded": storeMetrics.Degraded,
|
||
"DegradedNote": storeMetrics.DegradedNote,
|
||
"ActiveSessions": storeMetrics.ActiveCount,
|
||
}))
|
||
}
|
||
|
||
// UsersPage 用户管理页面
|
||
func (ac *AdminController) UsersPage(c *gin.Context) {
|
||
c.HTML(http.StatusOK, "admin/users/index.html", common.BuildAdminPageData(c, gin.H{
|
||
"Title": "用户管理",
|
||
"ExtraCSS": "/admin/static/css/users.css",
|
||
"ExtraJS": "/admin/static/js/users.js",
|
||
"RoleNames": model.RoleDisplayNames,
|
||
"StatusNames": model.StatusDisplayNames,
|
||
}))
|
||
}
|
||
|
||
// ListUsers 用户列表 API(分页 + 搜索 + 筛选)
|
||
func (ac *AdminController) ListUsers(c *gin.Context) {
|
||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||
|
||
params := service.ListUsersParams{
|
||
Keyword: c.Query("keyword"),
|
||
Role: c.Query("role"),
|
||
Status: c.Query("status"),
|
||
Page: page,
|
||
PageSize: pageSize,
|
||
}
|
||
|
||
result, err := ac.adminService.ListUsers(params)
|
||
if err != nil {
|
||
common.Error(c, http.StatusInternalServerError, "查询失败")
|
||
return
|
||
}
|
||
|
||
common.Ok(c, result)
|
||
}
|
||
|
||
// UpdateUserStatus 封禁/解封用户
|
||
func (ac *AdminController) UpdateUserStatus(c *gin.Context) {
|
||
targetUID, err := parseUIDParam(c)
|
||
if err != nil {
|
||
common.Error(c, http.StatusBadRequest, "无效的用户 ID")
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
Status string `json:"status" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
common.Error(c, http.StatusBadRequest, "参数错误")
|
||
return
|
||
}
|
||
|
||
operatorUID := c.GetUint("uid")
|
||
if err := ac.adminService.UpdateUserStatus(operatorUID, targetUID, req.Status); err != nil {
|
||
handleServiceError(c, err)
|
||
return
|
||
}
|
||
|
||
action := "封禁"
|
||
if req.Status == model.StatusActive {
|
||
action = "解封"
|
||
} else if req.Status == model.StatusLocked {
|
||
action = "已锁定"
|
||
}
|
||
common.OkMessage(c, action+"成功")
|
||
}
|
||
|
||
// ResetToken 强制用户下线
|
||
func (ac *AdminController) ResetToken(c *gin.Context) {
|
||
targetUID, err := parseUIDParam(c)
|
||
if err != nil {
|
||
common.Error(c, http.StatusBadRequest, "无效的用户 ID")
|
||
return
|
||
}
|
||
|
||
operatorUID := c.GetUint("uid")
|
||
if err := ac.adminService.ResetUserToken(operatorUID, targetUID); err != nil {
|
||
handleServiceError(c, err)
|
||
return
|
||
}
|
||
|
||
common.OkMessage(c, "已强制下线")
|
||
}
|
||
|
||
// parseUIDParam 从 URL 路径参数解析 uid
|
||
func parseUIDParam(c *gin.Context) (uint, error) {
|
||
uid, err := strconv.ParseUint(c.Param("uid"), 10, 64)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
return uint(uid), nil
|
||
}
|
||
|
||
// handleServiceError 统一处理 service 层返回的错误
|
||
func handleServiceError(c *gin.Context, err error) {
|
||
switch err {
|
||
case common.ErrPermissionDenied:
|
||
common.Error(c, http.StatusForbidden, "权限不足")
|
||
case common.ErrUserNotFound:
|
||
common.Error(c, http.StatusNotFound, "用户不存在")
|
||
case common.ErrEmailExists:
|
||
common.Error(c, http.StatusConflict, "该邮箱已被其他用户注册,无法解锁")
|
||
default:
|
||
common.Error(c, http.StatusInternalServerError, "操作失败")
|
||
}
|
||
}
|