diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b01e3b0 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/goblog.db b/goblog.db index 5fbff75..c13266a 100644 Binary files a/goblog.db and b/goblog.db differ diff --git a/goblog.exe b/goblog.exe index 8837c0c..105fa6d 100644 Binary files a/goblog.exe and b/goblog.exe differ diff --git a/goblog.exe~ b/goblog.exe~ new file mode 100644 index 0000000..4ef13c8 Binary files /dev/null and b/goblog.exe~ differ diff --git a/handlers/post.go b/handlers/post.go index 0460ce4..3598532 100644 --- a/handlers/post.go +++ b/handlers/post.go @@ -225,6 +225,11 @@ func UpdatePost(c *gin.Context) { updates["published_at"] = &now } } + // 如果文章是已发布状态但没有发布时间,设置发布时间 + if post.Status == "published" && post.PublishedAt == nil { + now := time.Now() + updates["published_at"] = &now + } updates["is_top"] = req.IsTop // 处理标签 diff --git a/handlers/view.go b/handlers/view.go index 2dfce92..a6ac582 100644 --- a/handlers/view.go +++ b/handlers/view.go @@ -15,7 +15,6 @@ import ( "gorm.io/gorm" ) -// 模板函数 func templateFuncs() template.FuncMap { return template.FuncMap{ "add": func(a, b int) int { @@ -30,12 +29,6 @@ func templateFuncs() template.FuncMap { } } -// 初始化模板 - 返回 gin 可用的 HTMLRender -func InitTemplates(theme string) (*template.Template, error) { - tmpl, err := template.New("").Funcs(templateFuncs()).ParseGlob("templates/" + theme + "/*.html") - return tmpl, err -} - // 首页 type IndexData struct { Title string @@ -61,8 +54,7 @@ func IndexView(c *gin.Context) { tagID, _ := strconv.Atoi(c.Query("tag")) db := database.DB.Model(&models.Post{}).Preload("Category").Preload("Tags").Preload("Author"). - Where("status = ?", "published"). - Where("published_at IS NOT NULL") + Where("status = ?", "published") if categoryID > 0 { db = db.Where("category_id = ?", categoryID) @@ -98,7 +90,7 @@ func IndexView(c *gin.Context) { Year: time.Now().Year(), } - c.HTML(http.StatusOK, "base.html", data) + c.HTML(http.StatusOK, "index", data) } // 文章详情页 @@ -112,6 +104,8 @@ type PostDetailData struct { Comments []models.Comment CommentCount int64 Year int + PrevPost *models.Post // 上一篇 + NextPost *models.Post // 下一篇 } func PostView(c *gin.Context) { @@ -129,7 +123,7 @@ func PostView(c *gin.Context) { First(&post).Error if err != nil { - c.HTML(http.StatusNotFound, "base.html", gin.H{ + c.HTML(http.StatusNotFound, "index", gin.H{ "Title": "404 - 页面不存在", "SiteName": cfg.App.Name, "Year": time.Now().Year(), @@ -148,6 +142,16 @@ func PostView(c *gin.Context) { 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, @@ -160,7 +164,15 @@ func PostView(c *gin.Context) { Year: time.Now().Year(), } - c.HTML(http.StatusOK, "base.html", data) + // 只有当查询成功时才赋值 + if prevErr == nil { + data.PrevPost = &prevPost + } + if nextErr == nil { + data.NextPost = &nextPost + } + + c.HTML(http.StatusOK, "post", data) } // 独立页面 @@ -180,9 +192,8 @@ func PageView(c *gin.Context) { var page models.Page err := database.DB.Where("slug = ? AND status = ?", slug, "published").First(&page).Error - if err != nil { - c.HTML(http.StatusNotFound, "base.html", gin.H{ + c.HTML(http.StatusNotFound, "index", gin.H{ "Title": "404 - 页面不存在", "SiteName": cfg.App.Name, "Year": time.Now().Year(), @@ -204,7 +215,7 @@ func PageView(c *gin.Context) { Year: time.Now().Year(), } - c.HTML(http.StatusOK, "base.html", data) + c.HTML(http.StatusOK, "page", data) } // 提交评论(表单提交) @@ -228,14 +239,13 @@ func SubmitComment(c *gin.Context) { Email: email, Website: website, Content: content, - IP: c.ClientIP(), Status: "pending", } if err := database.DB.Create(&comment).Error; err != nil { - c.String(http.StatusInternalServerError, "发表评论失败") + c.String(http.StatusInternalServerError, "提交失败") return } - c.Redirect(http.StatusFound, "/post/"+post.Slug+"#comment-"+strconv.Itoa(int(comment.ID))) + c.Redirect(http.StatusFound, "/post/"+post.Slug) } diff --git a/main.go b/main.go index b5dd2a6..d1492c2 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "goblog/database" "goblog/handlers" "goblog/middleware" + "goblog/utils" "github.com/gin-gonic/gin" ) @@ -32,12 +33,9 @@ func main() { // 创建路由 r := gin.Default() - // 初始化模板 - tmpl, err := handlers.InitTemplates(cfg.App.Theme) - if err != nil { - log.Fatal("模板初始化失败:", err) - } - r.SetHTMLTemplate(tmpl) + // 使用自定义的 TemplateRenderer + htmlRenderer := utils.LoadTemplates(cfg.App.Theme) + r.HTMLRender = htmlRenderer // 静态文件 r.Static("/static", "./static") diff --git a/static/admin/app.js b/static/admin/app.js index d6eeb11..2760d2f 100644 --- a/static/admin/app.js +++ b/static/admin/app.js @@ -175,6 +175,7 @@ async function loadPosts() {