package routers // Add the package declaration at the top import ( "fmt" "go_blog/controllers" "go_blog/models" "go_blog/pkg/jwt" "go_blog/serializers" "go_blog/themes" // <-- 确保导入 themes 包 "log" "net/http" "strconv" "time" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // 新增:自定义后台认证中间件(处理页面重定向) func CheckAdminAuth() gin.HandlerFunc { return func(c *gin.Context) { currentPath := c.Request.URL.Path user, _ := c.Get("user") // 从jwt中间件获取用户信息 // 已登录状态访问登录/注册页:重定向到后台首页 if (currentPath == "/admin/login" || currentPath == "/admin/register") && user != nil { c.Redirect(http.StatusFound, "/admin/index") c.Abort() return } // 未登录状态访问非登录/注册页:重定向到登录页 if (currentPath != "/admin/login" && currentPath != "/admin/register") && user == nil { c.Redirect(http.StatusFound, "/admin/login") c.Abort() return } c.Next() } } func RegisterRoutes(r *gin.Engine) { // 注册WebSocket路由 r.GET("/events", esSSE) r.GET("/page", func(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 } var items []models.Content var pager serializers.Pager pager.InitPager(c) // 这会从查询参数中读取 page 和 pageSize offset := (pager.Page - 1) * pager.PageSize dbInterface, dbOk := c.Get("DB") if !dbOk { log.Println("未找到键 'DB' 的上下文值") c.JSON(http.StatusInternalServerError, gin.H{"error": "内部服务器错误"}) return } db, typeOk := dbInterface.(*gorm.DB) if !typeOk { log.Println("无法将 DB 转换为 *gorm.DB 类型") c.JSON(http.StatusInternalServerError, gin.H{"error": "内部服务器错误"}) return } db.Select("*").Offset(offset).Limit(pager.PageSize).Find(&items, "type = ?", "post") var totalCount int64 db.Model(&models.Content{}).Where("type = ?", "post").Count(&totalCount) pager.Total = int(totalCount) // 确保 Pager 结构体中的 Total 类型匹配 tpl := themeManager.GetTemplate("index") // 假设分页列表也使用 index 模板 if tpl == nil { c.String(http.StatusInternalServerError, "Template 'index' not found in current theme: "+themeManager.CurrentTheme()) return } c.Status(http.StatusOK) c.Header("Content-Type", "text/html; charset=utf-8") err := tpl.Execute(c.Writer, gin.H{ "Items": items, "Pager": pager, // 确保你的 index.tmpl 支持 Pager 结构 "Title": "文章列表 - 第 " + strconv.Itoa(pager.Page) + " 页", }) if err != nil { c.String(http.StatusInternalServerError, "Error rendering template: "+err.Error()) } }) r.GET("/createcontent", func(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 } // 假设你的主题中有一个名为 "content" 的模板 (content.html 或 content.tmpl) // 注意:当前的 default 主题并没有 content.tmpl,你需要添加它。 // 如果这个页面是后台页面,它可能不需要主题化,或者使用一个固定的后台模板。 tpl := themeManager.GetTemplate("content") if tpl == nil { c.String(http.StatusInternalServerError, "Template 'content' not found in current theme: "+themeManager.CurrentTheme()+". Make sure 'content.html' or 'content.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()) } }) r.GET("/ws", controllers.WebSocketHandler) r.POST("/content", controllers.CreateContentHandler) // Frontend routes (dynamic themes) r.GET("/", controllers.Home) r.GET("/post/:id", controllers.ShowPost) admin := r.Group("/admin") admin.Use(CheckAdminAuth()) // 使用自定义重定向中间件 { // 无需认证的公开路由(登录/注册) admin.GET("/login", controllers.ShowLoginPage) admin.GET("/register", controllers.ShowRegisterPage) admin.POST("/login", controllers.UsersLoginHandler) admin.POST("/register", controllers.UsersRegisterHandler) // 需要认证的路由组(使用jwt中间件验证令牌) authAdmin := admin.Group("", jwt.AuthRequired()) { authAdmin.GET("/index", controllers.ShowAdminIndexPage) // 后台首页 authAdmin.GET("/themes", controllers.ListThemes) // 主题列表 authAdmin.GET("/themes/switch", controllers.ShowThemeSwitchPage) // 新增:主题切换页面 authAdmin.POST("/themes/switch", controllers.SwitchTheme) // 原有:处理主题切换提交 authAdmin.POST("/setinfo", controllers.UsersSetInfoHandler) authAdmin.POST("/setpwd", controllers.UsersSetPwdHandler) } } // Static files for themes r.StaticFS("/themes", http.Dir("web/themes")) } func esSSE(c *gin.Context) { w := c.Writer w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") w.Header().Set("Access-Control-Allow-Origin", "*") _, ok := w.(http.Flusher) if !ok { log.Panic("server not support") //浏览器不兼容 } for { // Simulate sending events every second fmt.Fprintf(w, "data: %s\n\n", time.Now().Format(time.Stamp)) w.(http.Flusher).Flush() time.Sleep(1 * time.Second) } _, err := fmt.Fprintf(w, "event: connecttime\ndata: %s\n\n", "connecttime") if err != nil { print("error", err) return } }