初始化项目:基础设施 + 用户认证 + 后台管理系统 + AGPL 3.0 许可

This commit is contained in:
2026-05-26 13:46:33 +08:00
parent 1315df6501
commit 483fdd919f
56 changed files with 5804 additions and 40 deletions

View File

@ -0,0 +1,131 @@
package admin
import (
"net/http"
"strconv"
"metazone.cc/metalab/internal/common"
"metazone.cc/metalab/internal/model"
"metazone.cc/metalab/internal/service"
"github.com/gin-gonic/gin"
)
// AdminController 管理后台控制器
type AdminController struct {
adminService *service.AdminService
}
// NewAdminController 构造函数
func NewAdminController(adminService *service.AdminService) *AdminController {
return &AdminController{adminService: adminService}
}
// Dashboard 管理首页(欢迎页)
func (ac *AdminController) Dashboard(c *gin.Context) {
c.HTML(http.StatusOK, "admin/dashboard/index.html", common.BuildAdminPageData(c, gin.H{
"Title": "管理首页",
}))
}
// 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",
}))
}
// 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, "操作失败")
}
}