diff --git a/conf/conf.ini b/config/conf.ini similarity index 100% rename from conf/conf.ini rename to config/conf.ini diff --git a/conf/config.go b/config/config.go similarity index 100% rename from conf/config.go rename to config/config.go diff --git a/conf/config.yml b/config/config.yml similarity index 100% rename from conf/config.yml rename to config/config.yml diff --git a/main.go b/main.go index 2c99192..1d953ad 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "go_blog/conf" + conf "go_blog/config" "go_blog/controllers" "go_blog/models" "go_blog/serializers" diff --git a/models/article.go b/models/article.go new file mode 100644 index 0000000..3c12d95 --- /dev/null +++ b/models/article.go @@ -0,0 +1,18 @@ +package models + +import "gorm.io/gorm" + +type Article struct { + gorm.Model + Title string + Content string `gorm:"type:text"` + AuthorID uint + Tags []Tag `gorm:"many2many:article_tags;"` +} + +// Tag represents the tag model +type Tag struct { + gorm.Model + Name string `gorm:"uniqueIndex"` // Ensures tag names are unique + Articles []Article `gorm:"many2many:article_tags;"` // Reverse relationship +} diff --git a/models/init.go b/models/init.go index 99849bb..d09f208 100644 --- a/models/init.go +++ b/models/init.go @@ -8,7 +8,7 @@ package models import ( "fmt" - "go_blog/conf" + conf "go_blog/config" "go_blog/pkg/util" "time" diff --git a/models/users.go b/models/user.go similarity index 100% rename from models/users.go rename to models/user.go diff --git a/pkg/jwt/auth.go b/pkg/jwt/auth.go index 1253913..aa2d16f 100644 --- a/pkg/jwt/auth.go +++ b/pkg/jwt/auth.go @@ -7,7 +7,7 @@ package jwt import ( - "go_blog/conf" + conf "go_blog/config" "go_blog/models" "time" diff --git a/routers/router.go b/routers/router.go new file mode 100644 index 0000000..f7373c2 --- /dev/null +++ b/routers/router.go @@ -0,0 +1,23 @@ +package routers // Add the package declaration at the top + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +func RegisterRoutes(r *gin.Engine) { + // Frontend routes (dynamic themes) + r.GET("/", handlers.Home) + r.GET("/post/:id", handlers.ShowPost) + + // Admin panel + admin := r.Group("/admin", middleware.AuthRequired()) + { + admin.GET("/themes", handlers.ListThemes) + admin.POST("/themes/switch", handlers.SwitchTheme) + } + + // Static files for themes + r.StaticFS("/themes", http.Dir("web/themes")) +} diff --git a/themes/manager.go b/themes/manager.go new file mode 100644 index 0000000..29c111a --- /dev/null +++ b/themes/manager.go @@ -0,0 +1,54 @@ +package theme // Declare the package at the top +import ( + "fmt" + "html/template" + "net/http" + "os" + "path/filepath" + "strings" +) + +// ThemeManager manages themes for the blog system +type ThemeManager struct { + CurrentTheme string // Name of the currently active theme + Templates map[string]*template.Template // Cached compiled HTML templates +} + +// LoadTheme loads a specified theme by its name +func (tm *ThemeManager) LoadTheme(themeName string) error { + // 1. 读取theme.yaml验证主题有效性 + // 2. 预编译所有HTML模板,缓存到Templates + // 3. 注册静态资源路由:/themes/[name]/static/*filepath + tm.CurrentTheme = themeName + + // Step 1: Validate the theme by reading theme.yaml + themeConfigPath := fmt.Sprintf("h:/code/go_blog/themes/%s/theme.yaml", themeName) + if _, err := os.Stat(themeConfigPath); os.IsNotExist(err) { + return fmt.Errorf("theme %s does not exist or is invalid", themeName) + } + + // Step 2: Precompile all HTML templates and cache them + tm.Templates = make(map[string]*template.Template) + templateDir := fmt.Sprintf("h:/code/go_blog/themes/%s/templates", themeName) + err := filepath.Walk(templateDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && strings.HasSuffix(info.Name(), ".html") { + tmpl, err := template.ParseFiles(path) + if err != nil { + return err + } + tm.Templates[info.Name()] = tmpl + } + return nil + }) + if err != nil { + return fmt.Errorf("failed to load templates: %v", err) + } + + // Step 3: Register static resource routes + http.Handle(fmt.Sprintf("/themes/%s/static/", themeName), http.StripPrefix(fmt.Sprintf("/themes/%s/static/", themeName), http.FileServer(http.Dir(fmt.Sprintf("h:/code/go_blog/themes/%s/static", themeName))))) + + return nil +} diff --git a/themes/parser.go b/themes/parser.go new file mode 100644 index 0000000..1f6fd2c --- /dev/null +++ b/themes/parser.go @@ -0,0 +1,35 @@ +package parser // Declare the package at the top + +import ( + "fmt" + "net/http" + "your_project_path/config" // Adjust import path as needed + "your_project_path/themes" // Adjust import path as needed + + "github.com/gin-gonic/gin" +) + +// RenderTemplate renders a template based on the current theme +func RenderTemplate(c *gin.Context, tmpl string, data gin.H) { + // Get the current theme + theme := config.GetCurrentTheme() + + // Construct the template path: "themes/default/home.html" + tplPath := fmt.Sprintf("themes/%s/%s", theme, tmpl) + + // Render the template using html/template + c.HTML(http.StatusOK, tplPath, data) +} + +// SwitchTheme handles POST requests to switch the current theme +func SwitchTheme(c *gin.Context) { + newTheme := c.PostForm("theme") + manager := themes.GetManager() + + if err := manager.LoadTheme(newTheme); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + } else { + config.SetCurrentTheme(newTheme) // Update the configuration + c.JSON(http.StatusOK, gin.H{"status": "success"}) + } +} diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..088d75e --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,14 @@ +// 示例:插件接口 +type Plugin interface { + OnArticleCreate(article *models.Article) // 文章创建钩子 + RegisterRoutes(r *gin.Engine) // 添加新路由 +} + +// 主题ZIP上传示例 +func handleThemeUpload(c *gin.Context) { + file, _ := c.FormFile("theme") + if !strings.HasSuffix(file.Filename, ".zip") { + c.AbortWithStatus(400) + } + // 解压到临时目录并校验文件结构 +} \ No newline at end of file diff --git a/web/themes/skeleton.go b/web/themes/skeleton.go new file mode 100644 index 0000000..1bb840c --- /dev/null +++ b/web/themes/skeleton.go @@ -0,0 +1,5 @@ + +

{{ .Site.Title }}

+{{ range .Posts }} +
{{ .Content }}
+{{ end }} \ No newline at end of file