This commit is contained in:
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
@Time : 2020/6/28 21:48
|
||||
@Author : xuyiqing
|
||||
@File : config.py
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
@@ -57,7 +51,7 @@ type Config struct {
|
||||
Security SecurityConfig
|
||||
}
|
||||
|
||||
var globalConfig *Config // 新增全局配置变量
|
||||
var globalConfig *Config
|
||||
|
||||
func LoadConfig(configPath string) (*Config, error) {
|
||||
// 1. 基础配置
|
||||
@@ -84,10 +78,9 @@ func LoadConfig(configPath string) (*Config, error) {
|
||||
return nil, fmt.Errorf("读取配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
//监控并重新读取配置文件
|
||||
// 监控配置文件变更
|
||||
viper.WatchConfig()
|
||||
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||
// 配置文件发生变更之后会调用的回调函数
|
||||
fmt.Println("Config file changed:", e.Name)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
@Time : 2020/6/28 21:40
|
||||
@Author : xuyiqing
|
||||
@File : users.py
|
||||
*/
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
|
||||
@@ -2,13 +2,15 @@ package controllers
|
||||
|
||||
import (
|
||||
"go_blog/models"
|
||||
"go_blog/utils"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 登录
|
||||
// CreateContentHandler 创建内容
|
||||
func CreateContentHandler(ctx *gin.Context) {
|
||||
|
||||
var content models.Content
|
||||
if err := ctx.ShouldBindJSON(&content); err != nil {
|
||||
ctx.JSON(400, gin.H{"error": err.Error()})
|
||||
@@ -22,3 +24,61 @@ func CreateContentHandler(ctx *gin.Context) {
|
||||
|
||||
ctx.JSON(201, content)
|
||||
}
|
||||
|
||||
// PageList 分页文章列表
|
||||
func PageList(c *gin.Context) {
|
||||
themeManager, ok := getThemeManager(c)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "Theme manager not found")
|
||||
return
|
||||
}
|
||||
|
||||
db, ok := getDB(c)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "DB not found")
|
||||
return
|
||||
}
|
||||
|
||||
var items []models.Content
|
||||
var pager utils.Pager
|
||||
pager.InitPager(c)
|
||||
offset := (pager.Page - 1) * pager.PageSize
|
||||
|
||||
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)
|
||||
|
||||
tpl := themeManager.GetTemplate("index")
|
||||
if tpl == nil {
|
||||
c.String(http.StatusInternalServerError, "Template 'index' not found")
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||
tpl.Execute(c.Writer, gin.H{
|
||||
"Items": items,
|
||||
"Pager": pager,
|
||||
"Title": "文章列表 - 第 " + strconv.Itoa(pager.Page) + " 页",
|
||||
})
|
||||
}
|
||||
|
||||
// CreateContentPage 创建内容页面
|
||||
func CreateContentPage(c *gin.Context) {
|
||||
themeManager, ok := getThemeManager(c)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "Theme manager not found")
|
||||
return
|
||||
}
|
||||
|
||||
tpl := themeManager.GetTemplate("content")
|
||||
if tpl == nil {
|
||||
c.String(http.StatusInternalServerError, "Template 'content' not found")
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||
tpl.Execute(c.Writer, gin.H{
|
||||
"Title": "创建新内容",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,50 +6,55 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm" // <-- 确保导入 gorm
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func Home(c *gin.Context) {
|
||||
// getThemeManager 从上下文中获取主题管理器
|
||||
func getThemeManager(c *gin.Context) (*utils.ThemeManager, bool) {
|
||||
tm, exists := c.Get("ThemeManager")
|
||||
if !exists {
|
||||
c.String(http.StatusInternalServerError, "Theme manager not found in context")
|
||||
return
|
||||
return nil, false
|
||||
}
|
||||
themeManager, ok := tm.(*utils.ThemeManager)
|
||||
return themeManager, ok
|
||||
}
|
||||
|
||||
// getDB 从上下文中获取数据库实例
|
||||
func getDB(c *gin.Context) (*gorm.DB, bool) {
|
||||
dbInterface, exists := c.Get("DB")
|
||||
if !exists {
|
||||
return nil, false
|
||||
}
|
||||
db, ok := dbInterface.(*gorm.DB)
|
||||
return db, ok
|
||||
}
|
||||
|
||||
// Home 首页
|
||||
func Home(c *gin.Context) {
|
||||
themeManager, ok := getThemeManager(c)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "Invalid theme manager type in context")
|
||||
c.String(http.StatusInternalServerError, "Theme manager not found")
|
||||
return
|
||||
}
|
||||
|
||||
db, ok := getDB(c)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "DB not found")
|
||||
return
|
||||
}
|
||||
|
||||
var items []models.Content
|
||||
// 从 Gin 上下文中获取 DB 实例
|
||||
dbInterface, exists := c.Get("DB")
|
||||
if !exists {
|
||||
c.String(http.StatusInternalServerError, "DB not found in context")
|
||||
return
|
||||
}
|
||||
db, ok := dbInterface.(*gorm.DB)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "Invalid DB type in context")
|
||||
return
|
||||
}
|
||||
|
||||
db.Select("*").Limit(5).Find(&items, "type = ?", "post")
|
||||
|
||||
tpl := themeManager.GetTemplate("index") // "index" 是模板的基本名 (例如 index.tmpl -> index)
|
||||
tpl := themeManager.GetTemplate("index")
|
||||
if tpl == nil {
|
||||
c.String(http.StatusInternalServerError, "Template 'index' not found in current theme: "+themeManager.CurrentTheme())
|
||||
c.String(http.StatusInternalServerError, "Template 'index' not found")
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||
err := tpl.Execute(c.Writer, gin.H{
|
||||
tpl.Execute(c.Writer, gin.H{
|
||||
"Items": items,
|
||||
"Title": "首页", // 你可以根据需要传递更多数据
|
||||
"Title": "首页",
|
||||
})
|
||||
if err != nil {
|
||||
// 实际项目中应记录错误
|
||||
c.String(http.StatusInternalServerError, "Error rendering template: "+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,18 @@ package controllers
|
||||
|
||||
import (
|
||||
"go_blog/models"
|
||||
"go_blog/utils"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm" // <-- 确保导入 gorm
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ShowPost 显示文章详情
|
||||
func ShowPost(c *gin.Context) {
|
||||
tm, exists := c.Get("ThemeManager")
|
||||
if !exists {
|
||||
c.String(http.StatusInternalServerError, "Theme manager not found")
|
||||
return
|
||||
}
|
||||
themeManager, ok := tm.(*utils.ThemeManager)
|
||||
themeManager, ok := getThemeManager(c)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "Invalid theme manager type")
|
||||
c.String(http.StatusInternalServerError, "Theme manager not found")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -29,19 +24,13 @@ func ShowPost(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var content = models.Content{Cid: int32(id)}
|
||||
// 从 Gin 上下文中获取 DB 实例
|
||||
dbInterface, exists := c.Get("DB")
|
||||
if !exists {
|
||||
c.String(http.StatusInternalServerError, "DB not found in context")
|
||||
return
|
||||
}
|
||||
db, ok := dbInterface.(*gorm.DB)
|
||||
db, ok := getDB(c)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "Invalid DB type in context")
|
||||
c.String(http.StatusInternalServerError, "DB not found")
|
||||
return
|
||||
}
|
||||
|
||||
var content = models.Content{Cid: int32(id)}
|
||||
result := db.First(&content)
|
||||
if result.Error != nil {
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
@@ -52,19 +41,12 @@ func ShowPost(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 假设你的主题中有一个名为 "post" 的模板 (post.html 或 post.tmpl)
|
||||
// 注意:当前的 default 主题 (web/themes/default/templates/) 并没有 post.tmpl,你需要添加它。
|
||||
tpl := themeManager.GetTemplate("post")
|
||||
if tpl == nil {
|
||||
c.String(http.StatusInternalServerError, "Template 'post' not found in current theme: "+themeManager.CurrentTheme()+". Make sure 'post.html' or 'post.tmpl' exists in the theme's templates directory.")
|
||||
c.String(http.StatusInternalServerError, "Template 'post' not found")
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusOK)
|
||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||
// 将整个 content 对象传递给模板。模板内部通过 {{ .Title }} {{ .Text }} 等访问。
|
||||
err = tpl.Execute(c.Writer, content)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, "Error rendering template: "+err.Error())
|
||||
}
|
||||
tpl.Execute(c.Writer, content)
|
||||
}
|
||||
|
||||
8
main.go
8
main.go
@@ -49,15 +49,15 @@ func main() {
|
||||
}
|
||||
|
||||
// 5. 创建Gin实例
|
||||
// 根据环境设置Gin模式
|
||||
if conf.Env == config.EnvProduction {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
router := gin.Default()
|
||||
router := gin.New()
|
||||
router.Use(gin.Recovery())
|
||||
themeManager.RegisterStaticRoutes(router)
|
||||
|
||||
// 初始化Session存储(使用Cookie)
|
||||
store := cookie.NewStore([]byte("your-session-secret")) // 建议从配置文件读取密钥
|
||||
store := cookie.NewStore([]byte("your-session-secret"))
|
||||
store.Options(sessions.Options{
|
||||
Path: "/",
|
||||
MaxAge: 86400 * 7, // 7天
|
||||
@@ -66,8 +66,6 @@ func main() {
|
||||
// 6. 注册中间件
|
||||
router.Use(
|
||||
loggerMiddleware(),
|
||||
gin.Logger(),
|
||||
gin.Recovery(),
|
||||
databaseMiddleware(models.DB),
|
||||
configMiddleware(conf),
|
||||
themeMiddleware(themeManager),
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
@Time : 2020/6/28 22:01
|
||||
@Author : xuyiqing
|
||||
@File : users.py
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
@@ -43,24 +37,13 @@ func (a *Account) SetPassword(password string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 验证登录帐户密码合法性
|
||||
func (a *Account) CheckPassword() bool {
|
||||
password := a.Password
|
||||
|
||||
aa, err1 := bcrypt.GenerateFromPassword([]byte(a.Password), 12)
|
||||
print(aa, err1)
|
||||
DB.Where("username = ?", a.Username).First(&a)
|
||||
err := bcrypt.CompareHashAndPassword([]byte(a.Password), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 验证登录帐户密码合法性
|
||||
// IsPasswordEqual 验证密码是否匹配
|
||||
func (a *Account) IsPasswordEqual(password string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(a.Password), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 验证用户民重复
|
||||
// CheckDuplicateUsername 验证用户名是否重复
|
||||
func (a *Account) CheckDuplicateUsername() bool {
|
||||
var count int64
|
||||
if DB.Model(&Account{}).Where("username=?", a.Username).Count(&count); count > 0 {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package models
|
||||
|
||||
const TableNameContent = "contents"
|
||||
|
||||
// Content 内容模型(文章/页面)
|
||||
type Content struct {
|
||||
Cid int32 `gorm:"column:cid;primaryKey;autoIncrement:true" json:"cid"`
|
||||
Title string `gorm:"column:title" json:"title"`
|
||||
@@ -22,7 +21,7 @@ type Content struct {
|
||||
Parent int32 `gorm:"column:parent" json:"parent"`
|
||||
}
|
||||
|
||||
// TableName Content's table name
|
||||
// TableName 指定表名
|
||||
func (*Content) TableName() string {
|
||||
return TableNameContent
|
||||
return "contents"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
@Time : 2020/6/28 21:46
|
||||
@Author : xuyiqing
|
||||
@File : init.py
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
@@ -50,12 +44,8 @@ func InitDatabase(conf *config.Config) {
|
||||
}
|
||||
|
||||
DB = db
|
||||
// 3. 自动迁移数据模型
|
||||
db.AutoMigrate(&Account{})
|
||||
db.AutoMigrate(&Content{})
|
||||
// if err := db.AutoMigrate(&models.Article{}, &models.User{}); err != nil {
|
||||
// panic("数据库迁移失败: " + err.Error())
|
||||
// }
|
||||
// 自动迁移数据模型
|
||||
db.AutoMigrate(&Account{}, &Content{}, &Option{})
|
||||
}
|
||||
|
||||
type BaseModel struct {
|
||||
|
||||
@@ -2,8 +2,7 @@ package models
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
// Option 对应 typecho_options 数据表
|
||||
// 用于存储系统配置项
|
||||
// Option 系统配置项模型
|
||||
type Option struct {
|
||||
Name string `gorm:"column:name;type:varchar(32);primaryKey"` // 配置名称(主键)
|
||||
Value string `gorm:"column:value;type:text"` // 配置值
|
||||
@@ -12,7 +11,7 @@ type Option struct {
|
||||
|
||||
// TableName 指定表名
|
||||
func (Option) TableName() string {
|
||||
return "typecho_options"
|
||||
return "options"
|
||||
}
|
||||
|
||||
// GetOptionValue 根据name和user获取配置值
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package models
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Gender string
|
||||
Age int
|
||||
Password string
|
||||
PasswordHash []byte
|
||||
}
|
||||
|
||||
// GetUserByID 根据 ID 查询用户
|
||||
func GetUserByID(id uint) (*User, error) {
|
||||
var user User
|
||||
if err := DB.First(&user, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
@Time : 2020/7/15 23:27
|
||||
@Author : xuyiqing
|
||||
@File : util.py
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
package routers // Add the package declaration at the top
|
||||
package routers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go_blog/controllers"
|
||||
"go_blog/controllers/admin"
|
||||
"go_blog/models"
|
||||
"go_blog/utils"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 新增:自定义后台认证中间件(处理页面重定向)
|
||||
// 自定义后台认证中间件(通过Session判断登录状态)
|
||||
// CheckAdminAuth 后台认证中间件(处理页面重定向)
|
||||
func CheckAdminAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
currentPath := c.Request.URL.Path
|
||||
@@ -43,7 +37,7 @@ func CheckAdminAuth() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:基于Session的认证中间件
|
||||
// SessionAuthRequired 基于Session的认证中间件
|
||||
func SessionAuthRequired() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
@@ -63,97 +57,16 @@ func SessionAuthRequired() gin.HandlerFunc {
|
||||
}
|
||||
|
||||
func RegisterRoutes(r *gin.Engine) {
|
||||
|
||||
// 注册WebSocket路由
|
||||
// WebSocket 和 SSE 路由
|
||||
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.(*utils.ThemeManager)
|
||||
if !ok {
|
||||
c.String(http.StatusInternalServerError, "Invalid theme manager type")
|
||||
return
|
||||
}
|
||||
|
||||
var items []models.Content
|
||||
var pager utils.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.(*utils.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("/page", controllers.PageList)
|
||||
r.GET("/createcontent", controllers.CreateContentPage)
|
||||
|
||||
// 前端路由(动态主题)
|
||||
r.GET("/", controllers.Home)
|
||||
r.GET("/post/:id", controllers.ShowPost)
|
||||
|
||||
@@ -196,22 +109,15 @@ func esSSE(c *gin.Context) {
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
|
||||
_, ok := w.(http.Flusher)
|
||||
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
log.Panic("server not support") //浏览器不兼容
|
||||
c.String(http.StatusInternalServerError, "server not support SSE")
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
// Simulate sending events every second
|
||||
fmt.Fprintf(w, "data: %s\n\n", time.Now().Format(time.Stamp))
|
||||
w.(http.Flusher).Flush()
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,21 +200,6 @@ func readFile(path string) ([]byte, error) {
|
||||
return os.ReadFile(path)
|
||||
}
|
||||
|
||||
// ListThemes 获取所有可用主题(目录名)
|
||||
func (m *ThemeManager) ListThemes() ([]string, error) {
|
||||
entries, err := os.ReadDir(m.themesDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取主题目录失败: %w", err)
|
||||
}
|
||||
var themes []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
themes = append(themes, entry.Name())
|
||||
}
|
||||
}
|
||||
return themes, nil
|
||||
}
|
||||
|
||||
// GetAvailableThemes 获取所有可用主题(读取 themesDir 目录下的子目录)
|
||||
func (m *ThemeManager) GetAvailableThemes() ([]string, error) {
|
||||
entries, err := os.ReadDir(m.themesDir)
|
||||
|
||||
Reference in New Issue
Block a user