Files
go_blog/controllers/admin/users.go

246 lines
6.7 KiB
Go
Raw Normal View History

2025-07-12 15:56:36 +08:00
package admin
2024-01-10 16:05:15 +08:00
import (
"go_blog/models"
"go_blog/pkg/util"
2025-07-12 15:56:36 +08:00
"go_blog/utils"
2025-06-09 17:59:19 +08:00
"html/template"
"net/http"
2024-01-10 16:05:15 +08:00
2025-06-13 08:59:01 +08:00
"github.com/gin-contrib/sessions"
2024-01-10 16:05:15 +08:00
"github.com/gin-gonic/gin"
)
// 登录
func UsersLoginHandler(ctx *gin.Context) {
2025-07-12 15:56:36 +08:00
var loginUser models.Account
2024-01-10 16:05:15 +08:00
if err := ctx.ShouldBind(&loginUser); err != nil {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "请求参数错误: " + err.Error(),
})
2025-05-27 19:01:05 +08:00
return
2024-01-10 16:05:15 +08:00
}
2025-06-09 17:59:19 +08:00
2025-05-27 19:24:07 +08:00
user := &models.Account{Username: loginUser.Username}
if err := models.DB.Where("username = ?", user.Username).First(user).Error; err != nil {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "用户不存在",
})
2025-05-27 19:24:07 +08:00
return
}
if !user.IsPasswordEqual(loginUser.Password) {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "密码错误",
})
2024-01-10 16:05:15 +08:00
return
}
2025-06-09 17:59:19 +08:00
2025-07-12 15:56:36 +08:00
// 改为设置Session不使用JWT
2025-06-13 08:59:01 +08:00
session := sessions.Default(ctx)
session.Set("user_id", user.ID) // 存储用户ID到Session
session.Save()
2025-06-09 17:59:19 +08:00
2025-06-13 08:59:01 +08:00
// 表单提交场景直接跳转无需设置JWT Cookie
2025-06-09 17:59:19 +08:00
if ctx.ContentType() == "application/x-www-form-urlencoded" {
ctx.Redirect(http.StatusFound, "/admin/index")
return
}
2025-06-13 08:59:01 +08:00
// API请求场景返回登录成功无需返回token
2024-01-10 16:05:15 +08:00
data, _ := util.PrecisionLost(user)
2025-06-23 17:04:31 +08:00
ctx.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "msg": "登录成功", "data": data})
2024-01-10 16:05:15 +08:00
}
// 注册
func UsersRegisterHandler(ctx *gin.Context) {
2025-07-12 15:56:36 +08:00
var registerUser models.Account
2024-01-10 16:05:15 +08:00
if err := ctx.ShouldBind(&registerUser); err != nil {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "请求参数错误: " + err.Error(),
}) // 替换 panic 为错误响应
2025-05-27 19:01:05 +08:00
return
2024-01-10 16:05:15 +08:00
}
2025-07-12 15:56:36 +08:00
status := registerUser.CheckDuplicateUsername()
2024-01-10 16:05:15 +08:00
if status == false {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "用户名已存在",
})
2024-01-10 16:05:15 +08:00
return
}
2025-07-12 15:56:36 +08:00
if err := registerUser.SetPassword(registerUser.Password); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "密码设置错误: " + err.Error(),
})
return
2024-01-10 16:05:15 +08:00
}
2025-07-12 15:56:36 +08:00
registerUser.IsActive = true
models.DB.Create(&registerUser)
2025-06-23 17:04:31 +08:00
ctx.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "msg": "注册成功"})
2024-01-10 16:05:15 +08:00
}
// 修改密码
func UsersSetPwdHandler(ctx *gin.Context) {
2025-06-09 17:59:19 +08:00
2025-05-27 19:24:07 +08:00
// 从上下文中获取用户(替换原 jwt.AssertUser 调用)
2025-06-09 17:59:19 +08:00
ctxuser, exists := ctx.Get("user")
2025-05-27 19:24:07 +08:00
if !exists {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized,
"msg": "未验证登录",
})
2025-05-27 19:24:07 +08:00
return
}
2025-06-09 17:59:19 +08:00
currentUser, ok := ctxuser.(*models.Account)
2025-05-27 19:24:07 +08:00
if !ok {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"code": http.StatusInternalServerError,
"msg": "用户类型错误",
})
2025-05-27 19:24:07 +08:00
return
}
2024-01-10 16:05:15 +08:00
if currentUser == nil {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized,
"msg": "未验证登录",
})
2024-01-10 16:05:15 +08:00
return
}
2025-07-12 15:56:36 +08:00
var user models.Account
2024-01-10 16:05:15 +08:00
if err := ctx.ShouldBindJSON(&user); err != nil {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "参数解析失败",
})
2024-01-10 16:05:15 +08:00
return
}
if user.Username != currentUser.Username {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "当前登录用户用户名与输入用户名不符",
})
2024-01-10 16:05:15 +08:00
return
}
2025-07-12 15:56:36 +08:00
if ctx.GetString("OldPwd") == ctx.GetString("NewPwd") {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "两次输入的密码相同",
})
2024-01-10 16:05:15 +08:00
return
}
2025-07-12 15:56:36 +08:00
if isPwd := currentUser.IsPasswordEqual(user.Password); !isPwd {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": "原密码错误",
})
2024-01-10 16:05:15 +08:00
return
}
2025-07-12 15:56:36 +08:00
if err := currentUser.SetPassword(ctx.GetString("NewPwd")); err != nil {
2025-06-23 17:04:31 +08:00
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": err.Error(),
})
2024-01-10 16:05:15 +08:00
return
}
models.DB.Save(&currentUser)
2025-06-23 17:04:31 +08:00
ctx.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "密码修改成功",
})
2024-01-10 16:05:15 +08:00
}
func UsersListHandler(ctx *gin.Context) {
2025-07-12 15:56:36 +08:00
var pager utils.Pager
2024-01-10 16:05:15 +08:00
pager.InitPager(ctx)
var users []models.Account
2025-06-09 17:59:19 +08:00
2025-05-27 19:01:05 +08:00
// 先查询总记录数
var totalCount int64
models.DB.Model(&models.Account{}).Count(&totalCount)
pager.Total = int(totalCount) // 正确设置总数
2025-06-09 17:59:19 +08:00
2025-05-27 19:01:05 +08:00
// 分页查询
2025-06-09 17:59:19 +08:00
// 由于 pager.OffSet 是 int 类型,直接使用该变量,无需调用函数
models.DB.Offset(pager.OffSet).Limit(pager.PageSize).Find(&users)
2024-01-10 16:05:15 +08:00
pager.GetPager()
2025-06-23 17:04:31 +08:00
ctx.JSON(http.StatusOK, gin.H{
"Code": http.StatusOK,
"Msg": "返回成功",
"Data": users,
"Pager": pager,
})
2024-01-10 16:05:15 +08:00
}
2025-06-09 17:59:19 +08:00
// ShowLoginPage 渲染登录页面
func ShowLoginPage(c *gin.Context) {
// 直接加载 web/admin 目录下的 login.tmpl 模板(需确保文件存在)
tpl, err := template.ParseFiles("web/admin/login.tmpl")
if err != nil {
c.String(http.StatusInternalServerError, "加载模板失败: "+err.Error())
return
}
c.Status(http.StatusOK)
c.Header("Content-Type", "text/html; charset=utf-8")
err = tpl.Execute(c.Writer, gin.H{
"Title": "用户登录",
})
if err != nil {
c.String(http.StatusInternalServerError, "渲染模板错误: "+err.Error())
}
}
// ShowRegisterPage 渲染注册页面
func ShowRegisterPage(c *gin.Context) {
tm, exists := c.Get("ThemeManager")
if !exists {
c.String(http.StatusInternalServerError, "Theme manager not found")
return
}
2025-07-12 15:56:36 +08:00
themeManager, ok := tm.(*utils.ThemeManager)
2025-06-09 17:59:19 +08:00
if !ok {
c.String(http.StatusInternalServerError, "Invalid theme manager type")
return
}
// 假设主题中存在 register.tmpl 模板(或使用后台固定模板)
tpl := themeManager.GetTemplate("register")
if tpl == nil {
c.String(http.StatusInternalServerError, "Template 'register' not found in current theme. Make sure 'register.html' or 'register.tmpl' exists.")
return
}
c.Status(http.StatusOK)
c.Header("Content-Type", "text/html; charset=utf-8")
err := tpl.Execute(c.Writer, gin.H{
"Title": "用户注册",
})
if err != nil {
c.String(http.StatusInternalServerError, "Error rendering template: "+err.Error())
}
}
2025-06-13 08:59:01 +08:00
// 退出登录
func UsersLogoutHandler(ctx *gin.Context) {
2025-06-23 17:04:31 +08:00
session := sessions.Default(ctx) // 获取当前请求的Session
// 清除Session中的用户ID
session.Delete("user_id")
// 保存Session修改必须调用
if err := session.Save(); err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"code": http.StatusInternalServerError,
"msg": "退出失败: " + err.Error(),
})
return
}
// 重定向到登录页
ctx.Redirect(http.StatusFound, "/admin/login")
2025-06-13 08:59:01 +08:00
}