package handlers import ( "html/template" "math" "net/http" "strconv" "time" "goblog/config" "goblog/database" "goblog/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) func templateFuncs() template.FuncMap { return template.FuncMap{ "add": func(a, b int) int { return a + b }, "sub": func(a, b int) int { return a - b }, "html": func(s string) template.HTML { return template.HTML(s) }, } } // 首页 type IndexData struct { Title string SiteName string SiteDesc string Description string Posts []models.Post Pages []models.Page CurrentPage int TotalPages int Year int } func IndexView(c *gin.Context) { cfg := config.Load() page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) if page < 1 { page = 1 } pageSize := 10 categoryID, _ := strconv.Atoi(c.Query("category")) tagID, _ := strconv.Atoi(c.Query("tag")) db := database.DB.Model(&models.Post{}).Preload("Category").Preload("Tags").Preload("Author"). Where("status = ?", "published") if categoryID > 0 { db = db.Where("category_id = ?", categoryID) } if tagID > 0 { db = db.Joins("JOIN post_tags ON post_tags.post_id = posts.id"). Where("post_tags.tag_id = ?", tagID) } var total int64 db.Count(&total) var posts []models.Post offset := (page - 1) * pageSize db.Order("is_top DESC, published_at DESC, created_at DESC"). Offset(offset).Limit(pageSize).Find(&posts) // 获取页面 var pages []models.Page database.DB.Where("status = ?", "published").Order("`order` ASC").Find(&pages) totalPages := int(math.Ceil(float64(total) / float64(pageSize))) data := IndexData{ Title: "首页", SiteName: cfg.App.Name, SiteDesc: cfg.App.Description, Description: cfg.App.Description, Posts: posts, Pages: pages, CurrentPage: page, TotalPages: totalPages, Year: time.Now().Year(), } c.HTML(http.StatusOK, "index", data) } // 文章详情页 type PostDetailData struct { Title string SiteName string SiteDesc string Description string Post models.Post Pages []models.Page Comments []models.Comment CommentCount int64 Year int PrevPost *models.Post // 上一篇 NextPost *models.Post // 下一篇 } func PostView(c *gin.Context) { cfg := config.Load() slug := c.Param("slug") var post models.Post err := database.DB.Preload("Category").Preload("Tags").Preload("Author"). Preload("Comments", func(db *gorm.DB) *gorm.DB { return db.Where("status = ? AND parent_id IS NULL", "approved").Preload("Children", func(db *gorm.DB) *gorm.DB { return db.Where("status = ?", "approved") }) }). Where("slug = ? AND status = ?", slug, "published"). First(&post).Error if err != nil { c.HTML(http.StatusNotFound, "index", gin.H{ "Title": "404 - 页面不存在", "SiteName": cfg.App.Name, "Year": time.Now().Year(), }) return } // 增加浏览量 database.DB.Model(&post).UpdateColumn("views", gorm.Expr("views + 1")) // 获取页面 var pages []models.Page database.DB.Where("status = ?", "published").Order("`order` ASC").Find(&pages) // 统计评论数 var commentCount int64 database.DB.Model(&models.Comment{}).Where("post_id = ? AND status = ?", post.ID, "approved").Count(&commentCount) // 获取上一篇(发布时间更早的文章) var prevPost models.Post prevErr := database.DB.Where("status = ? AND published_at < ?", "published", post.PublishedAt). Order("published_at DESC").First(&prevPost).Error // 获取下一篇(发布时间更晚的文章) var nextPost models.Post nextErr := database.DB.Where("status = ? AND published_at > ?", "published", post.PublishedAt). Order("published_at ASC").First(&nextPost).Error data := PostDetailData{ Title: post.Title, SiteName: cfg.App.Name, SiteDesc: cfg.App.Description, Description: post.Summary, Post: post, Pages: pages, Comments: post.Comments, CommentCount: commentCount, Year: time.Now().Year(), } // 只有当查询成功时才赋值 if prevErr == nil { data.PrevPost = &prevPost } if nextErr == nil { data.NextPost = &nextPost } c.HTML(http.StatusOK, "post", data) } // 独立页面 type PageDetailData struct { Title string SiteName string SiteDesc string Description string Page models.Page Pages []models.Page Year int } func PageView(c *gin.Context) { cfg := config.Load() slug := c.Param("slug") var page models.Page err := database.DB.Where("slug = ? AND status = ?", slug, "published").First(&page).Error if err != nil { c.HTML(http.StatusNotFound, "index", gin.H{ "Title": "404 - 页面不存在", "SiteName": cfg.App.Name, "Year": time.Now().Year(), }) return } // 获取所有页面 var pages []models.Page database.DB.Where("status = ?", "published").Order("`order` ASC").Find(&pages) data := PageDetailData{ Title: page.Title, SiteName: cfg.App.Name, SiteDesc: cfg.App.Description, Description: "", Page: page, Pages: pages, Year: time.Now().Year(), } c.HTML(http.StatusOK, "page", data) } // 提交评论(表单提交) func SubmitComment(c *gin.Context) { postID, _ := strconv.Atoi(c.PostForm("post_id")) author := c.PostForm("author") email := c.PostForm("email") website := c.PostForm("website") content := c.PostForm("content") // 检查文章是否存在 var post models.Post if err := database.DB.First(&post, postID).Error; err != nil { c.String(http.StatusBadRequest, "文章不存在") return } comment := models.Comment{ PostID: uint(postID), Author: author, Email: email, Website: website, Content: content, Status: "pending", } if err := database.DB.Create(&comment).Error; err != nil { c.String(http.StatusInternalServerError, "提交失败") return } c.Redirect(http.StatusFound, "/post/"+post.Slug) }