增加admin相关页面
This commit is contained in:
49
controllers/admin.go
Normal file
49
controllers/admin.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ShowAdminIndexPage 渲染后台首页
|
||||
func ShowAdminIndexPage(c *gin.Context) {
|
||||
// 直接加载 web/admin 目录下的 index.tmpl 模板(需确保文件存在)
|
||||
tpl, err := template.ParseFiles("web/admin/index.tmpl")
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, "加载模板失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
// ShowThemeSwitchPage 渲染主题切换页面
|
||||
func ShowThemeSwitchPage(c *gin.Context) {
|
||||
// 假设主题列表存储在固定路径或需要手动维护(示例数据,需根据实际情况修改)
|
||||
themes := []string{"default", "dark", "light"} // 示例主题列表
|
||||
currentTheme := "default" // 示例当前主题(需根据实际存储方式获取)
|
||||
|
||||
// 直接加载 web/admin 目录下的 themes.tmpl 模板(需确保文件存在)
|
||||
tpl, err := template.ParseFiles("web/admin/themes.tmpl")
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, "加载模板失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||
err = tpl.Execute(c.Writer, gin.H{
|
||||
"CurrentTheme": currentTheme,
|
||||
"Themes": themes,
|
||||
})
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, "渲染模板失败: "+err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,84 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go_blog/config"
|
||||
"go_blog/themes"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListThemes 获取可用主题列表
|
||||
// ListThemes 显示主题管理页面(返回主题列表和当前主题)
|
||||
func ListThemes(c *gin.Context) {
|
||||
// 从主题管理器获取当前主题
|
||||
// 从上下文中获取主题管理器
|
||||
tm, exists := c.Get("ThemeManager")
|
||||
if !exists {
|
||||
c.JSON(500, gin.H{"error": "主题管理器未找到"})
|
||||
c.String(http.StatusInternalServerError, "主题管理器未找到")
|
||||
return
|
||||
}
|
||||
themeManager, ok := tm.(*themes.ThemeManager)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "主题管理器类型错误")
|
||||
return
|
||||
}
|
||||
themeManager := tm.(*themes.ThemeManager)
|
||||
|
||||
// 读取 web/themes 目录下的所有主题文件夹
|
||||
themesDir := "web/themes"
|
||||
entries, err := os.ReadDir(themesDir)
|
||||
// 获取可用主题列表(读取 web/themes 目录下的所有子目录)
|
||||
entries, err := themeManager.GetAvailableThemes() // 假设 ThemeManager 新增获取主题列表方法
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": "读取主题目录失败: " + err.Error()})
|
||||
c.String(http.StatusInternalServerError, "读取主题目录失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var themeList []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
themeList = append(themeList, entry.Name())
|
||||
}
|
||||
// 渲染管理页面模板
|
||||
tpl := themeManager.GetTemplate("admin/themes") // 对应 templates/admin/themes.tmpl
|
||||
if tpl == nil {
|
||||
c.String(http.StatusInternalServerError, "模板 'admin/themes' 未找到")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
"current": themeManager.CurrentTheme(),
|
||||
"themes": themeList,
|
||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||
err = tpl.Execute(c.Writer, gin.H{
|
||||
"CurrentTheme": themeManager.CurrentTheme(),
|
||||
"Themes": entries,
|
||||
})
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, "渲染模板失败: "+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// SwitchTheme 处理主题切换请求
|
||||
func SwitchTheme(c *gin.Context) {
|
||||
// 从上下文中获取主题管理器
|
||||
tm, exists := c.Get("ThemeManager")
|
||||
if !exists {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "主题管理器未找到"})
|
||||
return
|
||||
}
|
||||
themeManager, ok := tm.(*themes.ThemeManager)
|
||||
if !ok {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "主题管理器类型错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取前端提交的主题名称
|
||||
newTheme := c.PostForm("theme")
|
||||
if newTheme == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "主题名称不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
// 加载新主题
|
||||
if err := themeManager.LoadTheme(newTheme); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "加载主题失败: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 持久化主题配置(假设 config 包支持保存到配置文件)
|
||||
if err := config.SetCurrentTheme(newTheme); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存主题配置失败: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"status": "主题切换成功", "current_theme": newTheme})
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ import (
|
||||
"go_blog/pkg/jwt"
|
||||
"go_blog/pkg/util"
|
||||
"go_blog/serializers"
|
||||
"go_blog/themes"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -24,25 +28,43 @@ func UsersLoginHandler(ctx *gin.Context) {
|
||||
response.BadRequest("请求参数错误: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 修正:通过数据库查询获取用户记录(原逻辑直接使用 loginUser.GetUser() 未查询数据库)
|
||||
user := &models.Account{Username: loginUser.Username}
|
||||
if err := models.DB.Where("username = ?", user.Username).First(user).Error; err != nil {
|
||||
response.BadRequest("用户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 修正:使用 IsPasswordEqual 验证密码
|
||||
if !user.IsPasswordEqual(loginUser.Password) {
|
||||
response.BadRequest("密码错误")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
token, err := jwt.GenerateToken(user)
|
||||
if err != nil {
|
||||
response.ServerError("生成令牌失败: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 添加 Authorization 响应头(格式与 auth.go 的 AuthRequired 方法一致)
|
||||
ctx.Header("Authorization", "Bearer " + token)
|
||||
|
||||
// 表单提交场景:设置Cookie并跳转(需配合前端使用Cookie存储JWT)
|
||||
if ctx.ContentType() == "application/x-www-form-urlencoded" {
|
||||
http.SetCookie(ctx.Writer, &http.Cookie{
|
||||
Name: "token",
|
||||
Value: token,
|
||||
Path: "/",
|
||||
Expires: time.Now().Add(24 * time.Hour),
|
||||
HttpOnly: true, // 防止XSS
|
||||
})
|
||||
ctx.Redirect(http.StatusFound, "/admin/index")
|
||||
return
|
||||
}
|
||||
|
||||
// API请求场景:返回JSON
|
||||
data, _ := util.PrecisionLost(user)
|
||||
data["token"] = token
|
||||
response.Response(data, nil)
|
||||
@@ -94,7 +116,7 @@ func UsersSetInfoHandler(ctx *gin.Context) {
|
||||
response.ServerError("用户类型错误")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
models.DB.Model(currentUser).Updates(jsonData)
|
||||
response.Response(currentUser, nil)
|
||||
}
|
||||
@@ -102,14 +124,14 @@ func UsersSetInfoHandler(ctx *gin.Context) {
|
||||
// 修改密码
|
||||
func UsersSetPwdHandler(ctx *gin.Context) {
|
||||
response := Response{Ctx: ctx}
|
||||
|
||||
|
||||
// 从上下文中获取用户(替换原 jwt.AssertUser 调用)
|
||||
user, exists := ctx.Get("user")
|
||||
ctxuser, exists := ctx.Get("user")
|
||||
if !exists {
|
||||
response.Unauthenticated("未验证登录")
|
||||
return
|
||||
}
|
||||
currentUser, ok := user.(*models.Account)
|
||||
currentUser, ok := ctxuser.(*models.Account)
|
||||
if !ok {
|
||||
response.ServerError("用户类型错误")
|
||||
return
|
||||
@@ -148,14 +170,64 @@ func UsersListHandler(ctx *gin.Context) {
|
||||
var pager serializers.Pager
|
||||
pager.InitPager(ctx)
|
||||
var users []models.Account
|
||||
|
||||
|
||||
// 先查询总记录数
|
||||
var totalCount int64
|
||||
models.DB.Model(&models.Account{}).Count(&totalCount)
|
||||
pager.Total = int(totalCount) // 正确设置总数
|
||||
|
||||
|
||||
// 分页查询
|
||||
models.DB.Offset(pager.OffSet()).Limit(pager.PageSize).Find(&users)
|
||||
// 由于 pager.OffSet 是 int 类型,直接使用该变量,无需调用函数
|
||||
models.DB.Offset(pager.OffSet).Limit(pager.PageSize).Find(&users)
|
||||
pager.GetPager()
|
||||
response.Response(users, pager)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
themeManager, ok := tm.(*themes.ThemeManager)
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user