+
{{ blogConfig.website_name }}
@@ -59,7 +86,10 @@ const coverStyle = computed(() => {
-
+
diff --git a/gin-blog-front/src/views/home/components/TalkingCarousel.vue b/gin-blog-front/src/views/home/components/TalkingCarousel.vue
index b65ca8d51bc356ff809c160714ab2025b3eb76e2..16a966937e4ed13e1a8f9749f35dee596effc5e7 100644
--- a/gin-blog-front/src/views/home/components/TalkingCarousel.vue
+++ b/gin-blog-front/src/views/home/components/TalkingCarousel.vue
@@ -1,13 +1,14 @@
@@ -29,8 +30,17 @@ onMounted(() => {
/* 左 -> 右 闪的特效 */
@keyframes passing {
- 0% { transform: translateX(-50%); opacity: 0; }
- 50% { transform: translateX(0); opacity: 1; }
- 100% { transform: translateX(50%); opacity: 0; }
+ 0% {
+ transform: translateX(-50%);
+ opacity: 0;
+ }
+ 50% {
+ transform: translateX(0);
+ opacity: 1;
+ }
+ 100% {
+ transform: translateX(50%);
+ opacity: 0;
+ }
}
diff --git a/gin-blog-server/api/front/oneSence.go b/gin-blog-server/api/front/oneSence.go
new file mode 100644
index 0000000000000000000000000000000000000000..8db32367afe34019f5765a7d060afc21f4b1336b
--- /dev/null
+++ b/gin-blog-server/api/front/oneSence.go
@@ -0,0 +1,14 @@
+package front
+
+import (
+ "gin-blog/utils/r"
+
+ "github.com/gin-gonic/gin"
+)
+
+type OneSence struct{}
+
+// 得到一句话
+func (*OneSence) GetOneSence(c *gin.Context) {
+ r.Success(c, oneSenceService.GetOneSence())
+}
diff --git a/gin-blog-server/api/front/z_enter.go b/gin-blog-server/api/front/z_enter.go
index 3c94ba16927740b7bd29c0a7a81be65216718d2e..57d037e7abd434854f158d99506ecc105f273398 100644
--- a/gin-blog-server/api/front/z_enter.go
+++ b/gin-blog-server/api/front/z_enter.go
@@ -1,18 +1,19 @@
-package front
-
-import "gin-blog/service"
-
-var (
- tagService service.Tag
- categoryService service.Category
- messageService service.Message
- articleService service.Article
- userService service.User
- commentService service.Comment
- linkService service.FriendLink
- roleService service.Role
- resourceService service.Resource
- menuService service.Menu
- blogInfoService service.BlogInfo
- operationLogService service.OperationLog
-)
+package front
+
+import "gin-blog/service"
+
+var (
+ tagService service.Tag
+ categoryService service.Category
+ messageService service.Message
+ articleService service.Article
+ userService service.User
+ commentService service.Comment
+ linkService service.FriendLink
+ roleService service.Role
+ resourceService service.Resource
+ menuService service.Menu
+ blogInfoService service.BlogInfo
+ operationLogService service.OperationLog
+ oneSenceService service.OneSence
+)
diff --git a/gin-blog-server/api/v1/oneSence.go b/gin-blog-server/api/v1/oneSence.go
new file mode 100644
index 0000000000000000000000000000000000000000..1cbbcfd97cfa567de39916daa2282df2691ae9d9
--- /dev/null
+++ b/gin-blog-server/api/v1/oneSence.go
@@ -0,0 +1,30 @@
+package v1
+
+import (
+ "gin-blog/model/req"
+ "gin-blog/utils"
+ "gin-blog/utils/r"
+ "github.com/gin-gonic/gin"
+)
+
+type OneSence struct{}
+
+// get 所有话
+func (*OneSence) GetAllSence(c *gin.Context) {
+ r.Success(c, oneSence.GetAllSence())
+}
+
+// post 增加一句话
+func (*OneSence) AddPostSence(c *gin.Context) {
+ r.Success(c, oneSence.AddOneSence(utils.BindJson[[]req.OneSence](c)))
+}
+
+// patch 修改一句话
+func (*OneSence) ModPatchSence(c *gin.Context) {
+ r.Success(c, oneSence.ModOneSence(utils.BindJson[req.OneSence](c)))
+}
+
+// delete 一句话
+func (*OneSence) DelOneSence(c *gin.Context) {
+ r.Success(c, oneSence.DelOneSence(utils.BindJson[[]req.OneSence](c)))
+}
diff --git a/gin-blog-server/api/v1/z_enter.go b/gin-blog-server/api/v1/z_enter.go
index a68dd7ccebe1f16ef248ee6a58efd851cbe86ed7..8ef869d90c90aec71981cabb0b87bc01fe8a931d 100644
--- a/gin-blog-server/api/v1/z_enter.go
+++ b/gin-blog-server/api/v1/z_enter.go
@@ -1,20 +1,21 @@
-package v1
-
-import "gin-blog/service"
-
-var (
- tagService service.Tag
- categoryService service.Category
- messageService service.Message
- articleService service.Article
- userService service.User
- commentService service.Comment
- linkService service.FriendLink
- roleService service.Role
- resourceService service.Resource
- menuService service.Menu
- blogInfoService service.BlogInfo
- operationLogService service.OperationLog
- pageService service.Page
- fileService service.File // 文件相关: 上传、导入、导出...
-)
+package v1
+
+import "gin-blog/service"
+
+var (
+ tagService service.Tag
+ categoryService service.Category
+ messageService service.Message
+ articleService service.Article
+ userService service.User
+ commentService service.Comment
+ linkService service.FriendLink
+ roleService service.Role
+ resourceService service.Resource
+ menuService service.Menu
+ blogInfoService service.BlogInfo
+ operationLogService service.OperationLog
+ pageService service.Page
+ fileService service.File // 文件相关: 上传、导入、导出...
+ oneSence service.OneSence
+)
diff --git a/gin-blog-server/dao/one_sence.go b/gin-blog-server/dao/one_sence.go
new file mode 100644
index 0000000000000000000000000000000000000000..4364a1bddf64a871b429e066e4ef0f8cf582c9da
--- /dev/null
+++ b/gin-blog-server/dao/one_sence.go
@@ -0,0 +1,22 @@
+package dao
+
+import (
+ "gin-blog/model"
+)
+
+type Onesence struct{}
+
+func (*Onesence) GetOneSence() []model.Onesence {
+ var list = make([]model.Onesence, 0)
+ var randomOnesence model.Onesence
+ db := DB.Model(&Onesence{})
+ db.Raw("SELECT * FROM onesence ORDER BY RAND() LIMIT 1").Scan(&randomOnesence)
+ list = append(list, randomOnesence)
+ return list
+}
+
+func (*Onesence) GetAllSence() []model.Onesence {
+ var list = make([]model.Onesence, 0)
+ DB.Model(&Onesence{}).Find(&list)
+ return list
+}
diff --git a/gin-blog-server/gvb.sql b/gin-blog-server/gvb.sql
index 4fcf0b540bff50e91fbb668c4965ca684203a4bc..92de42c211391ee5bd437ade0084fcabb251789e 100644
--- a/gin-blog-server/gvb.sql
+++ b/gin-blog-server/gvb.sql
@@ -155,6 +155,10 @@ INSERT INTO `casbin_rule` VALUES (2471, 'p', 'admin', '/role', 'DELETE', '', '',
INSERT INTO `casbin_rule` VALUES (2470, 'p', 'admin', '/role', 'POST', '', '', '');
INSERT INTO `casbin_rule` VALUES (2469, 'p', 'admin', '/role/list', 'GET', '', '', '');
INSERT INTO `casbin_rule` VALUES (2472, 'p', 'admin', '/role/option', 'GET', '', '', '');
+INSERT INTO `casbin_rule` VALUES (2501, 'p', 'admin', '/setting/onesence', 'DELETE', '', '', '');
+INSERT INTO `casbin_rule` VALUES (2502, 'p', 'admin', '/setting/onesence', 'POST', '', '', '');
+INSERT INTO `casbin_rule` VALUES (2503, 'p', 'admin', '/setting/onesence', 'PATCH', '', '', '');
+INSERT INTO `casbin_rule` VALUES (2504, 'p', 'admin', '/setting/onesence', 'GET', '', '', '');
INSERT INTO `casbin_rule` VALUES (2478, 'p', 'admin', '/setting/about', 'GET', '', '', '');
INSERT INTO `casbin_rule` VALUES (2482, 'p', 'admin', '/setting/about', 'PUT', '', '', '');
INSERT INTO `casbin_rule` VALUES (2477, 'p', 'admin', '/setting/blog-config', 'GET', '', '', '');
@@ -935,3 +939,18 @@ INSERT INTO `user_role` VALUES (2, 2);
INSERT INTO `user_role` VALUES (3, 3);
SET FOREIGN_KEY_CHECKS = 1;
+
+-- ----------------------------
+-- Table structure for OneSence
+-- ----------------------------
+DROP TABLE IF EXISTS `OneSence`;
+CREATE TABLE `OneSence` (
+ `sence_id` bigint AUTO_INCREMENT, -- 设置为自增
+ `sence` VARCHAR(255),
+ PRIMARY KEY (`sence_id`) -- 设置主键
+) ENGINE = InnoDB
+ CHARACTER SET = utf8mb4
+ COLLATE = utf8mb4_0900_ai_ci
+ ROW_FORMAT = DYNAMIC;
+
+INSERT INTO `OneSence` (`sence`) VALUES ('沒有天賦,那就反復'); -- 插入数据时不再手动指定 sence_id
diff --git a/gin-blog-server/model/OneSence.go b/gin-blog-server/model/OneSence.go
new file mode 100644
index 0000000000000000000000000000000000000000..af5e1ea51df74786cbaaad798cd90c761f2b54e7
--- /dev/null
+++ b/gin-blog-server/model/OneSence.go
@@ -0,0 +1,6 @@
+package model
+
+type Onesence struct {
+ Id int `gorm:"primaryKey;autoIncrement;column:sence_id;type:bigint;comment:句子id" json:"sence_id"`
+ Sence string `gorm:"type:varchar(255);comment:句子" json:"sence"`
+}
diff --git a/gin-blog-server/model/req/one_sence.go b/gin-blog-server/model/req/one_sence.go
new file mode 100644
index 0000000000000000000000000000000000000000..02cd48e0f62b2970e4d769e86f9bde4d7fc1ce1d
--- /dev/null
+++ b/gin-blog-server/model/req/one_sence.go
@@ -0,0 +1,7 @@
+package req
+
+// 得到一个句子
+type OneSence struct {
+ ID int `json:"id"`
+ Sence string `json:"sence"`
+}
diff --git a/gin-blog-server/model/resp/one_sence.go b/gin-blog-server/model/resp/one_sence.go
new file mode 100644
index 0000000000000000000000000000000000000000..5bbd4e5b7235da31cd6d01fa8a2c030ed652362d
--- /dev/null
+++ b/gin-blog-server/model/resp/one_sence.go
@@ -0,0 +1,7 @@
+package resp
+
+type OneSence struct {
+ ID int `json:"id"`
+ Sence string `json:"name"`
+ GetTime string `json:"time"`
+}
diff --git a/gin-blog-server/routes/back_router.go b/gin-blog-server/routes/back_router.go
index 92771f6d1a68ed69b1890413e09698203d5a1ed1..34ac2b6cf02f92e524fa56d2c70710b1d04b31f1 100644
--- a/gin-blog-server/routes/back_router.go
+++ b/gin-blog-server/routes/back_router.go
@@ -1,184 +1,188 @@
-package routes
-
-import (
- "gin-blog/config"
- "gin-blog/docs"
- "gin-blog/routes/middleware"
- "net/http"
-
- "github.com/gin-contrib/sessions"
- "github.com/gin-contrib/sessions/cookie"
- "github.com/gin-gonic/gin"
- swaggerFiles "github.com/swaggo/files"
- ginSwagger "github.com/swaggo/gin-swagger"
-)
-
-// 后台管理页面的接口路由
-func BackRouter() http.Handler {
- gin.SetMode(config.Cfg.Server.AppMode)
-
- r := gin.New()
- r.SetTrustedProxies([]string{"*"})
-
- // 使用本地文件上传, 需要静态文件服务, 使用七牛云不需要
- if config.Cfg.Upload.OssType == "local" {
- r.Static("/public", "./public")
- r.StaticFS("/dir", http.Dir("./public")) // 将 public 目录内的文件列举展示
- }
-
- r.Use(middleware.Logger()) // 自定义的 zap 日志中间件
- r.Use(middleware.ErrorRecovery(false)) // 自定义错误处理中间件
- r.Use(middleware.Cors()) // 跨域中间件
-
- // 初始化 session store, session 中用来传递用户的详细信息
- // ! Session 如果使用 Redis 存, 可以存进去, 但是获取不到值?
- // store, _ := redis.NewStoreWithDB(10,
- // "tcp",
- // config.Cfg.Redis.Addr,
- // config.Cfg.Redis.Password,
- // strconv.Itoa(config.Cfg.Redis.DB),
- // []byte(config.Cfg.Session.Salt))
-
- // 基于 cookie 存储 session
- store := cookie.NewStore([]byte(config.Cfg.Session.Salt))
-
- // session 存储时间跟 JWT 过期时间一致
- store.Options(sessions.Options{MaxAge: int(config.Cfg.JWT.Expire) * 3600})
- r.Use(sessions.Sessions(config.Cfg.Session.Name, store)) // Session 中间件
-
- // Swagger 文档
- docs.SwaggerInfo.BasePath = "/api"
- r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
-
- // 无需鉴权的接口
- base := r.Group("/api")
- {
- // TODO: 用户注册 和 后台登录 应该记录到 日志
- base.POST("/login", userAuthAPI.Login) // 后台登录
- base.POST("/report", blogInfoAPI.Report) // 上报信息
- }
-
- // 需要鉴权的接口
- auth := base.Group("") // "/admin"
- // !注意使用中间件的顺序
- auth.Use(middleware.JWTAuth()) // JWT 鉴权中间件
- auth.Use(middleware.RBAC()) // casbin 权限中间件
- auth.Use(middleware.ListenOnline()) // 监听在线用户
- auth.Use(middleware.OperationLog()) // 记录操作日志
- {
- auth.GET("/home", blogInfoAPI.GetHomeInfo) // 后台首页信息
- auth.GET("/logout", userAuthAPI.Logout) // 退出登录
- auth.POST("/upload", uploadAPI.UploadFile) // 文件上传
-
- // 博客设置
- setting := auth.Group("/setting")
- {
- setting.GET("/blog-config", blogInfoAPI.GetBlogConfig) // 获取博客设置
- setting.PUT("/blog-config", blogInfoAPI.UpdateBlogConfig) // 编辑博客设置
- setting.GET("/about", blogInfoAPI.GetAbout) // 获取关于我
- setting.PUT("/about", blogInfoAPI.UpdateAbout) // 编辑关于我
- }
- // 用户模块
- user := auth.Group("/user")
- {
- user.GET("/list", userAPI.GetList) // 用户列表
- user.PUT("", userAPI.Update) // 更新用户信息
- user.PUT("/disable", userAPI.UpdateDisable) // 修改用户禁用状态
- user.PUT("/password", userAPI.UpdatePassword) // 修改普通用户密码
- user.PUT("/current/password", userAPI.UpdateCurrentPassword) // 修改管理员密码
- user.GET("/info", userAPI.GetInfo) // 获取当前用户信息
- user.PUT("/current", userAPI.UpdateCurrent) // 修改当前用户信息
- user.GET("/online", userAPI.GetOnlineList) // 获取在线用户
- user.DELETE("/offline", userAPI.ForceOffline) // 强制用户下线
- }
- // 分类模块
- category := auth.Group("/category")
- {
- category.GET("/list", categoryAPI.GetList) // 分类列表
- category.POST("", categoryAPI.SaveOrUpdate) // 新增/编辑分类
- category.DELETE("", categoryAPI.Delete) // 删除分类
- category.GET("/option", categoryAPI.GetOption) // 分类选项列表
- }
- // 标签模块
- tag := auth.Group("/tag")
- {
- tag.GET("/list", tagAPI.GetList) // 标签列表
- tag.POST("", tagAPI.SaveOrUpdate) // 新增/编辑标签
- tag.DELETE("", tagAPI.Delete) // 删除标签
- tag.GET("/option", tagAPI.GetOption) // 标签选项列表
- }
- // 文章模块
- articles := auth.Group("/article")
- {
- articles.GET("/list", articleAPI.GetList) // 文章列表
- articles.POST("", articleAPI.SaveOrUpdate) // 新增/编辑文章
- articles.PUT("/top", articleAPI.UpdateTop) // 更新文章置顶
- articles.GET("/:id", articleAPI.GetInfo) // 文章详情
- articles.PUT("/soft-delete", articleAPI.SoftDelete) // 软删除文章
- articles.DELETE("", articleAPI.Delete) // 物理删除文章
- articles.POST("/export", articleAPI.Export) // 导出文章
- articles.POST("/import", articleAPI.Import) // 导入文章
- }
- // 评论模块
- comment := auth.Group("/comment")
- {
- comment.GET("/list", commentAPI.GetList) // 评论列表
- comment.DELETE("", commentAPI.Delete) // 删除评论
- comment.PUT("/review", commentAPI.UpdateReview) // 修改评论审核
- }
- // 留言模块
- message := auth.Group("/message")
- {
- message.GET("/list", messageAPI.GetList) // 留言列表
- message.DELETE("", messageAPI.Delete) // 删除留言
- message.PUT("/review", messageAPI.UpdateReview) // 审核留言
- }
- // 友情链接
- link := auth.Group("/link")
- {
- link.GET("/list", linkAPI.GetList) // 友链列表
- link.POST("", linkAPI.SaveOrUpdate) // 新增/编辑友链
- link.DELETE("", linkAPI.Delete) // 删除友链
- }
- // 资源模块
- resource := auth.Group("/resource")
- {
- resource.GET("/list", resourceAPI.GetTreeList) // 资源列表(树形)
- resource.POST("", resourceAPI.SaveOrUpdate) // 新增/编辑资源
- resource.DELETE("/:id", resourceAPI.Delete) // 删除资源
- resource.PUT("/anonymous", resourceAPI.UpdateAnonymous) // 修改资源匿名访问
- resource.GET("/option", resourceAPI.GetOption) // 资源选项列表(树形)
- }
- // 菜单模块
- menu := auth.Group("/menu")
- {
- menu.GET("/list", menuAPI.GetTreeList) // 菜单列表
- menu.POST("", menuAPI.SaveOrUpdate) // 新增/编辑菜单
- menu.DELETE("/:id", menuAPI.Delete) // 删除菜单
- menu.GET("/user/list", menuAPI.GetUserMenu) // 获取当前用户的菜单
- menu.GET("/option", menuAPI.GetOption) // 菜单选项列表(树形)
- }
- // 角色模块
- role := auth.Group("/role")
- {
- role.GET("/list", roleAPI.GetTreeList) // 角色列表(树形)
- role.POST("", roleAPI.SaveOrUpdate) // 新增/编辑菜单
- role.DELETE("", roleAPI.Delete) // 删除角色
- role.GET("/option", roleAPI.GetOption) // 角色选项列表(树形)
- }
- // 操作日志模块
- operationLog := auth.Group("/operation/log")
- {
- operationLog.GET("/list", operationLogAPI.GetList) // 操作日志列表
- operationLog.DELETE("", operationLogAPI.Delete) // 删除操作日志
- }
- // 页面模块
- page := auth.Group("/page")
- {
- page.GET("/list", pageAPI.GetList) // 页面列表
- page.POST("", pageAPI.SaveOrUpdate) // 新增/编辑页面
- page.DELETE("", pageAPI.Delete) // 删除页面
- }
- }
- return r
-}
+package routes
+
+import (
+ "gin-blog/config"
+ "gin-blog/docs"
+ "gin-blog/routes/middleware"
+ "net/http"
+
+ "github.com/gin-contrib/sessions"
+ "github.com/gin-contrib/sessions/cookie"
+ "github.com/gin-gonic/gin"
+ swaggerFiles "github.com/swaggo/files"
+ ginSwagger "github.com/swaggo/gin-swagger"
+)
+
+// 后台管理页面的接口路由
+func BackRouter() http.Handler {
+ gin.SetMode(config.Cfg.Server.AppMode)
+
+ r := gin.New()
+ r.SetTrustedProxies([]string{"*"})
+
+ // 使用本地文件上传, 需要静态文件服务, 使用七牛云不需要
+ if config.Cfg.Upload.OssType == "local" {
+ r.Static("/public", "./public")
+ r.StaticFS("/dir", http.Dir("./public")) // 将 public 目录内的文件列举展示
+ }
+
+ r.Use(middleware.Logger()) // 自定义的 zap 日志中间件
+ r.Use(middleware.ErrorRecovery(false)) // 自定义错误处理中间件
+ r.Use(middleware.Cors()) // 跨域中间件
+
+ // 初始化 session store, session 中用来传递用户的详细信息
+ // ! Session 如果使用 Redis 存, 可以存进去, 但是获取不到值?
+ // store, _ := redis.NewStoreWithDB(10,
+ // "tcp",
+ // config.Cfg.Redis.Addr,
+ // config.Cfg.Redis.Password,
+ // strconv.Itoa(config.Cfg.Redis.DB),
+ // []byte(config.Cfg.Session.Salt))
+
+ // 基于 cookie 存储 session
+ store := cookie.NewStore([]byte(config.Cfg.Session.Salt))
+
+ // session 存储时间跟 JWT 过期时间一致
+ store.Options(sessions.Options{MaxAge: int(config.Cfg.JWT.Expire) * 3600})
+ r.Use(sessions.Sessions(config.Cfg.Session.Name, store)) // Session 中间件
+
+ // Swagger 文档
+ docs.SwaggerInfo.BasePath = "/api"
+ r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
+
+ // 无需鉴权的接口
+ base := r.Group("/api")
+ {
+ // TODO: 用户注册 和 后台登录 应该记录到 日志
+ base.POST("/login", userAuthAPI.Login) // 后台登录
+ base.POST("/report", blogInfoAPI.Report) // 上报信息
+ }
+
+ // 需要鉴权的接口
+ auth := base.Group("") // "/admin"
+ // !注意使用中间件的顺序
+ auth.Use(middleware.JWTAuth()) // JWT 鉴权中间件
+ auth.Use(middleware.RBAC()) // casbin 权限中间件
+ auth.Use(middleware.ListenOnline()) // 监听在线用户
+ auth.Use(middleware.OperationLog()) // 记录操作日志
+ {
+ auth.GET("/home", blogInfoAPI.GetHomeInfo) // 后台首页信息
+ auth.GET("/logout", userAuthAPI.Logout) // 退出登录
+ auth.POST("/upload", uploadAPI.UploadFile) // 文件上传
+
+ // 博客设置
+ setting := auth.Group("/setting")
+ {
+ setting.GET("/blog-config", blogInfoAPI.GetBlogConfig) // 获取博客设置
+ setting.PUT("/blog-config", blogInfoAPI.UpdateBlogConfig) // 编辑博客设置
+ setting.GET("/about", blogInfoAPI.GetAbout) // 获取关于我
+ setting.PUT("/about", blogInfoAPI.UpdateAbout) // 编辑关于我
+ setting.GET("/onesence", controlOneSenceAPI.GetAllSence) // 编辑一句话接口
+ setting.POST("/onesence", controlOneSenceAPI.AddPostSence)
+ setting.PATCH("/onesence", controlOneSenceAPI.ModPatchSence)
+ setting.DELETE("onesence", controlOneSenceAPI.DelOneSence)
+ }
+ // 用户模块
+ user := auth.Group("/user")
+ {
+ user.GET("/list", userAPI.GetList) // 用户列表
+ user.PUT("", userAPI.Update) // 更新用户信息
+ user.PUT("/disable", userAPI.UpdateDisable) // 修改用户禁用状态
+ user.PUT("/password", userAPI.UpdatePassword) // 修改普通用户密码
+ user.PUT("/current/password", userAPI.UpdateCurrentPassword) // 修改管理员密码
+ user.GET("/info", userAPI.GetInfo) // 获取当前用户信息
+ user.PUT("/current", userAPI.UpdateCurrent) // 修改当前用户信息
+ user.GET("/online", userAPI.GetOnlineList) // 获取在线用户
+ user.DELETE("/offline", userAPI.ForceOffline) // 强制用户下线
+ }
+ // 分类模块
+ category := auth.Group("/category")
+ {
+ category.GET("/list", categoryAPI.GetList) // 分类列表
+ category.POST("", categoryAPI.SaveOrUpdate) // 新增/编辑分类
+ category.DELETE("", categoryAPI.Delete) // 删除分类
+ category.GET("/option", categoryAPI.GetOption) // 分类选项列表
+ }
+ // 标签模块
+ tag := auth.Group("/tag")
+ {
+ tag.GET("/list", tagAPI.GetList) // 标签列表
+ tag.POST("", tagAPI.SaveOrUpdate) // 新增/编辑标签
+ tag.DELETE("", tagAPI.Delete) // 删除标签
+ tag.GET("/option", tagAPI.GetOption) // 标签选项列表
+ }
+ // 文章模块
+ articles := auth.Group("/article")
+ {
+ articles.GET("/list", articleAPI.GetList) // 文章列表
+ articles.POST("", articleAPI.SaveOrUpdate) // 新增/编辑文章
+ articles.PUT("/top", articleAPI.UpdateTop) // 更新文章置顶
+ articles.GET("/:id", articleAPI.GetInfo) // 文章详情
+ articles.PUT("/soft-delete", articleAPI.SoftDelete) // 软删除文章
+ articles.DELETE("", articleAPI.Delete) // 物理删除文章
+ articles.POST("/export", articleAPI.Export) // 导出文章
+ articles.POST("/import", articleAPI.Import) // 导入文章
+ }
+ // 评论模块
+ comment := auth.Group("/comment")
+ {
+ comment.GET("/list", commentAPI.GetList) // 评论列表
+ comment.DELETE("", commentAPI.Delete) // 删除评论
+ comment.PUT("/review", commentAPI.UpdateReview) // 修改评论审核
+ }
+ // 留言模块
+ message := auth.Group("/message")
+ {
+ message.GET("/list", messageAPI.GetList) // 留言列表
+ message.DELETE("", messageAPI.Delete) // 删除留言
+ message.PUT("/review", messageAPI.UpdateReview) // 审核留言
+ }
+ // 友情链接
+ link := auth.Group("/link")
+ {
+ link.GET("/list", linkAPI.GetList) // 友链列表
+ link.POST("", linkAPI.SaveOrUpdate) // 新增/编辑友链
+ link.DELETE("", linkAPI.Delete) // 删除友链
+ }
+ // 资源模块
+ resource := auth.Group("/resource")
+ {
+ resource.GET("/list", resourceAPI.GetTreeList) // 资源列表(树形)
+ resource.POST("", resourceAPI.SaveOrUpdate) // 新增/编辑资源
+ resource.DELETE("/:id", resourceAPI.Delete) // 删除资源
+ resource.PUT("/anonymous", resourceAPI.UpdateAnonymous) // 修改资源匿名访问
+ resource.GET("/option", resourceAPI.GetOption) // 资源选项列表(树形)
+ }
+ // 菜单模块
+ menu := auth.Group("/menu")
+ {
+ menu.GET("/list", menuAPI.GetTreeList) // 菜单列表
+ menu.POST("", menuAPI.SaveOrUpdate) // 新增/编辑菜单
+ menu.DELETE("/:id", menuAPI.Delete) // 删除菜单
+ menu.GET("/user/list", menuAPI.GetUserMenu) // 获取当前用户的菜单
+ menu.GET("/option", menuAPI.GetOption) // 菜单选项列表(树形)
+ }
+ // 角色模块
+ role := auth.Group("/role")
+ {
+ role.GET("/list", roleAPI.GetTreeList) // 角色列表(树形)
+ role.POST("", roleAPI.SaveOrUpdate) // 新增/编辑菜单
+ role.DELETE("", roleAPI.Delete) // 删除角色
+ role.GET("/option", roleAPI.GetOption) // 角色选项列表(树形)
+ }
+ // 操作日志模块
+ operationLog := auth.Group("/operation/log")
+ {
+ operationLog.GET("/list", operationLogAPI.GetList) // 操作日志列表
+ operationLog.DELETE("", operationLogAPI.Delete) // 删除操作日志
+ }
+ // 页面模块
+ page := auth.Group("/page")
+ {
+ page.GET("/list", pageAPI.GetList) // 页面列表
+ page.POST("", pageAPI.SaveOrUpdate) // 新增/编辑页面
+ page.DELETE("", pageAPI.Delete) // 删除页面
+ }
+ }
+ return r
+}
diff --git a/gin-blog-server/routes/front_router.go b/gin-blog-server/routes/front_router.go
index 5e45de176b9064f0c8b104a487370f384bb9196b..c06de99dea9aecd7d320c43374a5f1b91ed966d8 100644
--- a/gin-blog-server/routes/front_router.go
+++ b/gin-blog-server/routes/front_router.go
@@ -1,103 +1,104 @@
-package routes
-
-import (
- "gin-blog/config"
- "gin-blog/routes/middleware"
- "net/http"
-
- "github.com/gin-contrib/sessions"
- "github.com/gin-contrib/sessions/cookie"
- "github.com/gin-gonic/gin"
-)
-
-// 前台页面接口路由
-func FrontRouter() http.Handler {
- gin.SetMode(config.Cfg.Server.AppMode)
-
- r := gin.New()
- r.SetTrustedProxies([]string{"*"})
-
- // 使用本地文件上传, 需要静态文件服务, 使用七牛云不需要
- // if config.Cfg.Upload.OssType == "local" {
- // r.Static("/public", "./public")
- // r.StaticFS("/dir", http.Dir("./public")) // 将 public 目录内的文件列举展示
- // }
-
- // 开发模式同时把日志写到控制台
- // if config.Cfg.Server.AppMode == "debug" {
- // r.Use(gin.Logger()) // gin 默认日志挺好看的
- // }
- r.Use(middleware.Logger()) // 自定义的 zap 日志中间件
- r.Use(middleware.ErrorRecovery(false)) // 自定义错误处理中间件
- r.Use(middleware.Cors()) // 跨域中间件
-
- // ! Session 如果使用 Redis 存, 可以存进去, 但是获取不到值?
- // store, _ := redis.NewStoreWithDB(10,
- // "tcp",
- // config.Cfg.Redis.Addr,
- // config.Cfg.Redis.Password,
- // strconv.Itoa(config.Cfg.Redis.DB),
- // []byte(config.Cfg.Session.Salt))
-
- // 基于 cookies 存储 session
- store := cookie.NewStore([]byte(config.Cfg.Session.Salt))
-
- store.Options(sessions.Options{MaxAge: config.Cfg.Session.MaxAge})
- r.Use(sessions.Sessions(config.Cfg.Session.Name, store)) // Session 中间件 (使用 Redis 存储引擎)
-
- // 无需监权的接口
- base := r.Group("/api/front")
- {
- base.POST("/login", userAuthAPI.Login) // 登录
- base.GET("/logout", userAuthAPI.Logout) // 退出登录
- base.POST("/register", userAuthAPI.Register) // 注册
- base.GET("/code", userAuthAPI.SendCode) // 验证码
- base.GET("/home", fBlogInfoAPI.GetFrontHomeInfo) // 前台首页
- base.GET("/about", blogInfoAPI.GetAbout) // 获取关于我
-
- article := base.Group("/article")
- {
- article.GET("/list", fArticleAPI.GetFrontList) // 前台文章列表
- article.GET("/:id", fArticleAPI.GetFrontInfo) // 前台文章详情
- article.GET("/archive", fArticleAPI.GetArchiveList) // 前台文章归档
- article.GET("/search", fArticleAPI.Search) // 前台文章搜索
- }
- category := base.Group("/category")
- {
- category.GET("/list", fCategoryAPI.GetFrontList) // 前台分类列表
- }
- tag := base.Group("/tag")
- {
- tag.GET("/list", fTagAPI.GetFrontList) // 前台标签列表
- }
- link := base.Group("/link")
- {
- link.GET("/list", fLinkAPI.GetFrontList) // 前台友链列表
- }
- message := base.Group("/message")
- {
- message.GET("/list", fMessageAPI.GetFrontList) // 前台留言列表
- }
- comment := base.Group("/comment")
- {
- comment.GET("/list", fCommentAPI.GetFrontList) // 前台评论列表
- comment.GET("/replies/:comment_id", fCommentAPI.GetReplyListByCommentId) // 根据评论 id 查询回复
- }
- }
-
- // 需要登录才能进行的操作
- base.Use(middleware.JWTAuth())
- // base.Use(middleware.RBAC()) // TODO: 前端不做权限
- // base.Use(middleware.ListenOnline())
- {
- base.POST("/upload", uploadAPI.UploadFile) // 文件上传
- base.GET("/user/info", userAPI.GetInfo) // 根据 Token 获取用户信息
- base.PUT("/user/info", userAPI.UpdateCurrent) // 根据 Token 更新当前用户信息
- base.POST("/message", fMessageAPI.Save) // 前台新增留言
- base.POST("/comment", fCommentAPI.Save) // 前台新增评论
- base.GET("/comment/like/:comment_id", fCommentAPI.SaveLike) // 前台点赞评论
- base.GET("/article/like/:article_id", fArticleAPI.SaveLike) // 前台点赞文章
- }
-
- return r
-}
+package routes
+
+import (
+ "gin-blog/config"
+ "gin-blog/routes/middleware"
+ "net/http"
+
+ "github.com/gin-contrib/sessions"
+ "github.com/gin-contrib/sessions/cookie"
+ "github.com/gin-gonic/gin"
+)
+
+// 前台页面接口路由
+func FrontRouter() http.Handler {
+ gin.SetMode(config.Cfg.Server.AppMode)
+
+ r := gin.New()
+ r.SetTrustedProxies([]string{"*"})
+
+ // 使用本地文件上传, 需要静态文件服务, 使用七牛云不需要
+ // if config.Cfg.Upload.OssType == "local" {
+ // r.Static("/public", "./public")
+ // r.StaticFS("/dir", http.Dir("./public")) // 将 public 目录内的文件列举展示
+ // }
+
+ // 开发模式同时把日志写到控制台
+ // if config.Cfg.Server.AppMode == "debug" {
+ // r.Use(gin.Logger()) // gin 默认日志挺好看的
+ // }
+ r.Use(middleware.Logger()) // 自定义的 zap 日志中间件
+ r.Use(middleware.ErrorRecovery(false)) // 自定义错误处理中间件
+ r.Use(middleware.Cors()) // 跨域中间件
+
+ // ! Session 如果使用 Redis 存, 可以存进去, 但是获取不到值?
+ // store, _ := redis.NewStoreWithDB(10,
+ // "tcp",
+ // config.Cfg.Redis.Addr,
+ // config.Cfg.Redis.Password,
+ // strconv.Itoa(config.Cfg.Redis.DB),
+ // []byte(config.Cfg.Session.Salt))
+
+ // 基于 cookies 存储 session
+ store := cookie.NewStore([]byte(config.Cfg.Session.Salt))
+
+ store.Options(sessions.Options{MaxAge: config.Cfg.Session.MaxAge})
+ r.Use(sessions.Sessions(config.Cfg.Session.Name, store)) // Session 中间件 (使用 Redis 存储引擎)
+
+ // 无需监权的接口
+ base := r.Group("/api/front")
+ {
+ base.POST("/login", userAuthAPI.Login) // 登录
+ base.GET("/logout", userAuthAPI.Logout) // 退出登录
+ base.POST("/register", userAuthAPI.Register) // 注册
+ base.GET("/code", userAuthAPI.SendCode) // 验证码
+ base.GET("/home", fBlogInfoAPI.GetFrontHomeInfo) // 前台首页
+ base.GET("/about", blogInfoAPI.GetAbout) // 获取关于我
+ base.GET("/oneSence", oneSenceAPI.GetOneSence) //获得一句话
+
+ article := base.Group("/article")
+ {
+ article.GET("/list", fArticleAPI.GetFrontList) // 前台文章列表
+ article.GET("/:id", fArticleAPI.GetFrontInfo) // 前台文章详情
+ article.GET("/archive", fArticleAPI.GetArchiveList) // 前台文章归档
+ article.GET("/search", fArticleAPI.Search) // 前台文章搜索
+ }
+ category := base.Group("/category")
+ {
+ category.GET("/list", fCategoryAPI.GetFrontList) // 前台分类列表
+ }
+ tag := base.Group("/tag")
+ {
+ tag.GET("/list", fTagAPI.GetFrontList) // 前台标签列表
+ }
+ link := base.Group("/link")
+ {
+ link.GET("/list", fLinkAPI.GetFrontList) // 前台友链列表
+ }
+ message := base.Group("/message")
+ {
+ message.GET("/list", fMessageAPI.GetFrontList) // 前台留言列表
+ }
+ comment := base.Group("/comment")
+ {
+ comment.GET("/list", fCommentAPI.GetFrontList) // 前台评论列表
+ comment.GET("/replies/:comment_id", fCommentAPI.GetReplyListByCommentId) // 根据评论 id 查询回复
+ }
+ }
+
+ // 需要登录才能进行的操作
+ base.Use(middleware.JWTAuth())
+ // base.Use(middleware.RBAC()) // TODO: 前端不做权限
+ // base.Use(middleware.ListenOnline())
+ {
+ base.POST("/upload", uploadAPI.UploadFile) // 文件上传
+ base.GET("/user/info", userAPI.GetInfo) // 根据 Token 获取用户信息
+ base.PUT("/user/info", userAPI.UpdateCurrent) // 根据 Token 更新当前用户信息
+ base.POST("/message", fMessageAPI.Save) // 前台新增留言
+ base.POST("/comment", fCommentAPI.Save) // 前台新增评论
+ base.GET("/comment/like/:comment_id", fCommentAPI.SaveLike) // 前台点赞评论
+ base.GET("/article/like/:article_id", fArticleAPI.SaveLike) // 前台点赞文章
+ }
+
+ return r
+}
diff --git a/gin-blog-server/routes/z_enter.go b/gin-blog-server/routes/z_enter.go
index 4fea016040daec887afdd9a0df5b2b80398aa8e8..1ed79e916db12061b0dc05ba05ec97010098e26b 100644
--- a/gin-blog-server/routes/z_enter.go
+++ b/gin-blog-server/routes/z_enter.go
@@ -1,38 +1,39 @@
-package routes
-
-import (
- "gin-blog/api/front"
- v1 "gin-blog/api/v1"
-)
-
-// 后台接口
-var (
- categoryAPI v1.Category // 分类
- tagAPI v1.Tag // 标签
- articleAPI v1.Article // 文章
- userAPI v1.User // 用户
- userAuthAPI v1.UserAuth // 用户账号
- commentAPI v1.Comment // 评论
- uploadAPI v1.Upload // 文件上传
- messageAPI v1.Message // 留言
- linkAPI v1.Link // 友情链接
- roleAPI v1.Role // 角色
- resourceAPI v1.Resource // 资源
- menuAPI v1.Menu // 菜单
- blogInfoAPI v1.BlogInfo // 博客设置
- operationLogAPI v1.OperationLog // 操作日志
- pageAPI v1.Page // 页面
-
- // store redis.Store // 使用 redis 作为 session 的存储引擎
-)
-
-// 前台接口
-var (
- fBlogInfoAPI front.BlogInfo // 博客信息
- fArticleAPI front.Article // 文章
- fCategoryAPI front.Category // 分类
- fTagAPI front.Tag // 标签
- fMessageAPI front.Message // 留言
- fCommentAPI front.Comment // 评论
- fLinkAPI front.Link // 友链
-)
+package routes
+
+import (
+ "gin-blog/api/front"
+ v1 "gin-blog/api/v1"
+)
+
+// 后台接口
+var (
+ categoryAPI v1.Category // 分类
+ tagAPI v1.Tag // 标签
+ articleAPI v1.Article // 文章
+ userAPI v1.User // 用户
+ userAuthAPI v1.UserAuth // 用户账号
+ commentAPI v1.Comment // 评论
+ uploadAPI v1.Upload // 文件上传
+ messageAPI v1.Message // 留言
+ linkAPI v1.Link // 友情链接
+ roleAPI v1.Role // 角色
+ resourceAPI v1.Resource // 资源
+ menuAPI v1.Menu // 菜单
+ blogInfoAPI v1.BlogInfo // 博客设置
+ operationLogAPI v1.OperationLog // 操作日志
+ pageAPI v1.Page // 页面
+ controlOneSenceAPI v1.OneSence //对一句话进行操作
+ // store redis.Store // 使用 redis 作为 session 的存储引擎
+)
+
+// 前台接口
+var (
+ fBlogInfoAPI front.BlogInfo // 博客信息
+ fArticleAPI front.Article // 文章
+ fCategoryAPI front.Category // 分类
+ fTagAPI front.Tag // 标签
+ fMessageAPI front.Message // 留言
+ fCommentAPI front.Comment // 评论
+ fLinkAPI front.Link // 友链
+ oneSenceAPI front.OneSence //获得一句话
+)
diff --git a/gin-blog-server/service/one_sence.go b/gin-blog-server/service/one_sence.go
new file mode 100644
index 0000000000000000000000000000000000000000..6327bba9f972489709f9cca8ecb8deed4a07585b
--- /dev/null
+++ b/gin-blog-server/service/one_sence.go
@@ -0,0 +1,75 @@
+package service
+
+import (
+ "gin-blog/dao"
+ "gin-blog/model"
+ "gin-blog/model/req"
+ "gin-blog/model/resp"
+ "gin-blog/utils/r"
+ "time"
+)
+
+type OneSence struct{}
+
+func (*OneSence) translateModelResp(res []model.Onesence) []resp.OneSence {
+ ans := make([]resp.OneSence, len(res))
+ timeStr := time.Now().UTC().String()
+ for i, v := range res {
+ ans[i] = resp.OneSence{
+ ID: v.Id,
+ Sence: v.Sence,
+ GetTime: timeStr,
+ }
+ }
+ return ans
+}
+
+func (*OneSence) translateReqModel(res []req.OneSence) []model.Onesence {
+ ans := make([]model.Onesence, len(res))
+ for i, v := range res {
+ ans[i] = model.Onesence{
+ Id: v.ID,
+ Sence: v.Sence,
+ }
+ }
+ return ans
+}
+
+func (r *OneSence) GetOneSence() resp.PageResult[[]resp.OneSence] {
+ list := oneSence.GetOneSence()
+ return resp.PageResult[[]resp.OneSence]{
+ List: r.translateModelResp(list),
+ }
+}
+func (r *OneSence) GetAllSence() resp.PageResult[[]resp.OneSence] {
+ list := oneSence.GetAllSence()
+ return resp.PageResult[[]resp.OneSence]{
+ List: r.translateModelResp(list),
+ }
+}
+
+// 批量增加
+func (o *OneSence) AddOneSence(sence []req.OneSence) (code int) {
+ ansOneSence := o.translateReqModel(sence)
+ dao.Create(&ansOneSence)
+ return r.OK
+}
+
+// 批量删除
+func (o *OneSence) DelOneSence(sence []req.OneSence) (code int) {
+ ansOneSence := o.translateReqModel(sence)
+ idx := []int{}
+ for i := 0; i < len(ansOneSence); i++ {
+ idx = append(idx, ansOneSence[i].Id)
+ }
+ dao.Delete(&model.Onesence{}, "sence_id in ?", idx)
+ return r.OK
+}
+
+// 修改一条
+func (*OneSence) ModOneSence(sence req.OneSence) (code int) {
+ newSence := dao.GetOne(&model.Onesence{}, "sence_id=?", sence.ID)
+ newSence.Sence = sence.Sence
+ dao.Update(&newSence)
+ return r.OK
+}
diff --git a/gin-blog-server/service/page.go b/gin-blog-server/service/page.go
index 7bda73758e46f617bd174b2f06f2ff4d56016c2b..b529e8a0424e072be1723e243ae89f7546800a09 100644
--- a/gin-blog-server/service/page.go
+++ b/gin-blog-server/service/page.go
@@ -6,6 +6,8 @@ import (
"gin-blog/model/req"
"gin-blog/utils"
"gin-blog/utils/r"
+ "gin-blog/utils/upload"
+ "log/slog"
)
type Page struct{}
@@ -33,6 +35,11 @@ func (*Page) SaveOrUpdate(req req.AddOrEditPage) (code int) {
page := utils.CopyProperties[model.Page](req) // vo -> po
if page.ID != 0 {
+ orderPage := dao.GetOne[model.Page](model.Page{}, "id", page.ID)
+ err := upload.NewOSS().DeleteFile(orderPage.Cover)
+ if err != nil {
+ slog.Warn("file del is fail! err:" + err.Error())
+ }
dao.Update(&page)
} else {
dao.Create(&page)
diff --git a/gin-blog-server/service/z_enter.go b/gin-blog-server/service/z_enter.go
index 1b4d8e3d599be4cd6ea2fe32f5f162d2d23b54bf..cc305418c91ca1b3250d10fcac73fd0e0dbdf6ab 100644
--- a/gin-blog-server/service/z_enter.go
+++ b/gin-blog-server/service/z_enter.go
@@ -1,46 +1,47 @@
-package service
-
-import (
- "gin-blog/dao"
-)
-
-// redis key
-
-const (
- KEY_CODE = "code:" // 验证码
- KEY_USER = "user:" // 记录用户
- KEY_DELETE = "delete:" //? 记录强制下线用户?
- KEY_ABOUT = "about" // 关于我信息
- KEY_BLOG_CONFIG = "blog_config" // 博客配置信息
- KEY_VISITOR_AREA = "visitor_area" // 地域统计
- KEY_VIEW_COUNT = "view_count" // 访问数量
-
- KEY_UNIQUE_VISITOR_SET = "unique_visitor" // 唯一用户记录 set
-
- KEY_ARTICLE_USER_LIKE_SET = "article_user_like:" // 文章点赞 Set
- KEY_ARTICLE_LIKE_COUNT = "article_like_count" // 文章点赞数
- KEY_ARTICLE_VIEW_COUNT = "article_view_count" // 文章查看数
-
- KEY_COMMENT_USER_LIKE_SET = "comment_user_like:" // 评论点赞 Set
- KEY_COMMENT_LIKE_COUNT = "comment_like_count" // 评论点赞数
-
- KEY_PAGE = "page" // 页面封面
-)
-
-var (
- tagDao dao.Tag
- categoryDao dao.Category
- messageDao dao.Message
- articleDao dao.Article
- userDao dao.User
- commentDao dao.Comment
- friendLinkDao dao.FriendLink
- roleDao dao.Role
- resourceDao dao.Resource
- menuDao dao.Menu
- operationLogDao dao.OperationLog
-)
-
-var (
- blogInfoService BlogInfo
-)
+package service
+
+import (
+ "gin-blog/dao"
+)
+
+// redis key
+
+const (
+ KEY_CODE = "code:" // 验证码
+ KEY_USER = "user:" // 记录用户
+ KEY_DELETE = "delete:" //? 记录强制下线用户?
+ KEY_ABOUT = "about" // 关于我信息
+ KEY_BLOG_CONFIG = "blog_config" // 博客配置信息
+ KEY_VISITOR_AREA = "visitor_area" // 地域统计
+ KEY_VIEW_COUNT = "view_count" // 访问数量
+
+ KEY_UNIQUE_VISITOR_SET = "unique_visitor" // 唯一用户记录 set
+
+ KEY_ARTICLE_USER_LIKE_SET = "article_user_like:" // 文章点赞 Set
+ KEY_ARTICLE_LIKE_COUNT = "article_like_count" // 文章点赞数
+ KEY_ARTICLE_VIEW_COUNT = "article_view_count" // 文章查看数
+
+ KEY_COMMENT_USER_LIKE_SET = "comment_user_like:" // 评论点赞 Set
+ KEY_COMMENT_LIKE_COUNT = "comment_like_count" // 评论点赞数
+
+ KEY_PAGE = "page" // 页面封面
+)
+
+var (
+ tagDao dao.Tag
+ categoryDao dao.Category
+ messageDao dao.Message
+ articleDao dao.Article
+ userDao dao.User
+ commentDao dao.Comment
+ friendLinkDao dao.FriendLink
+ roleDao dao.Role
+ resourceDao dao.Resource
+ menuDao dao.Menu
+ operationLogDao dao.OperationLog
+ oneSence dao.Onesence
+)
+
+var (
+ blogInfoService BlogInfo
+)
diff --git a/gin-blog-server/utils/upload/local.go b/gin-blog-server/utils/upload/local.go
index 40557866ad4d72327aeae59a697b38dcabe6ffc9..c3c1aacd454ab5ee0c2b0fb3dfa296318bcf48f2 100644
--- a/gin-blog-server/utils/upload/local.go
+++ b/gin-blog-server/utils/upload/local.go
@@ -61,6 +61,14 @@ func (*Local) UploadFile(file *multipart.FileHeader) (filePath, fileName string,
// 从本地删除文件
func (*Local) DeleteFile(key string) error {
+ if strings.Contains(key, "/") {
+ if strings.Contains(key, config.Cfg.Upload.StorePath) {
+ if err := os.Remove(key); err != nil {
+ return errors.New("本地文件删除失败, err:" + err.Error())
+ }
+ }
+ return nil
+ }
p := config.Cfg.Upload.StorePath + "/" + key
if strings.Contains(p, config.Cfg.Upload.StorePath) {
if err := os.Remove(p); err != nil {
diff --git a/gin-blog-server/utils/upload/oss.go b/gin-blog-server/utils/upload/oss.go
index 74947b910388d91c51d54b36665725439fc27e7d..4964f0c89abc854128c8050d662595ef8c6a0d5f 100644
--- a/gin-blog-server/utils/upload/oss.go
+++ b/gin-blog-server/utils/upload/oss.go
@@ -1,24 +1,30 @@
-package upload
-
-import (
- "gin-blog/config"
- "mime/multipart"
-)
-
-// OSS 对象存储接口
-type OSS interface {
- UploadFile(file *multipart.FileHeader) (string, string, error)
- DeleteFile(key string) error
-}
-
-// 根据配置文件中的配置判断文件上传实例
-func NewOSS() OSS {
- switch config.Cfg.Upload.OssType {
- case "local":
- return &Local{}
- case "qiniu":
- return &Qiniu{}
- default:
- return &Local{}
- }
-}
+package upload
+
+import (
+ "gin-blog/config"
+ "mime/multipart"
+)
+
+// OSS 对象存储接口
+type OSS interface {
+ UploadFile(file *multipart.FileHeader) (string, string, error)
+ DeleteFile(key string) error
+}
+
+var once OSS = nil
+
+// 根据配置文件中的配置判断文件上传实例
+func NewOSS() OSS {
+ if once != nil {
+ return once
+ }
+ switch config.Cfg.Upload.OssType {
+ case "local":
+ once = &Local{}
+ case "qiniu":
+ once = &Qiniu{}
+ default:
+ once = &Local{}
+ }
+ return once
+}
diff --git a/gin-blog-server/utils/viper.go b/gin-blog-server/utils/viper.go
index 91d67a28dc556cfde43d47327c67d5c2955fdb45..3627a03eefdeb323a57720b79013484657937747 100644
--- a/gin-blog-server/utils/viper.go
+++ b/gin-blog-server/utils/viper.go
@@ -1,50 +1,50 @@
-package utils
-
-import (
- "flag"
- "gin-blog/config"
- "log"
- "strings"
-
- "github.com/spf13/viper"
-)
-
-// 优先级: 命令行 > 默认值
-func InitViper() {
- // 根据命令行读取配置文件路径
- var configPath string
- flag.StringVar(&configPath, "c", "", "chosse config file.")
- flag.Parse()
- if configPath != "" { // 命令行读取到参数
- log.Printf("命令行读取参数, 配置文件路径为: %s\n", configPath)
- } else { // 命令行未读取到参数
- log.Println("命令行参数为空, 默认加载: config/config.toml")
- configPath = "config/config.toml"
- }
-
- // 目前读取固定固定路径的配置文件
- v := viper.New()
- v.SetConfigFile(configPath)
- v.AutomaticEnv() // 允许使用环境变量
- v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // SERVER_APPMODE => SERVER.APPMODE
-
- // 读取配置文件
- if err := v.ReadInConfig(); err != nil {
- log.Panic("配置文件读取失败: ", err)
- }
-
- // 加载配置文件内容到结构体对象
- if err := v.Unmarshal(&config.Cfg); err != nil {
- log.Panic("配置文件内容加载失败: ", err)
- }
-
- // TODO: 配置文件热重载, 使用场景是什么?
- // v.WatchConfig()
- // v.OnConfigChange(func(e fsnotify.Event) {
- // log.Println("检测到配置文件内容修改")
- // if err := v.Unmarshal(&config.Cfg); err != nil {
- // log.Panic("配置文件内容加载失败: ", err)
- // }
- // })
- log.Println("配置文件内容加载成功")
-}
+package utils
+
+import (
+ "flag"
+ "gin-blog/config"
+ "log"
+ "strings"
+
+ "github.com/spf13/viper"
+)
+
+// 优先级: 命令行 > 默认值
+func InitViper() {
+ // 根据命令行读取配置文件路径
+ var configPath string
+ flag.StringVar(&configPath, "c", "", "chosse config file.")
+ flag.Parse()
+ if configPath != "" { // 命令行读取到参数
+ log.Printf("命令行读取参数, 配置文件路径为: %s\n", configPath)
+ } else { // 命令行未读取到参数
+ log.Println("命令行参数为空, 默认加载: config/config.toml")
+ configPath = "config/config.toml"
+ }
+
+ // 目前读取固定固定路径的配置文件
+ v := viper.New()
+ v.SetConfigFile(configPath)
+ //v.AutomaticEnv() // 允许使用环境变量
+ v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) // SERVER_APPMODE => SERVER.APPMODE
+
+ // 读取配置文件
+ if err := v.ReadInConfig(); err != nil {
+ log.Panic("配置文件读取失败: ", err)
+ }
+
+ // 加载配置文件内容到结构体对象
+ if err := v.Unmarshal(&config.Cfg); err != nil {
+ log.Panic("配置文件内容加载失败: ", err)
+ }
+
+ // TODO: 配置文件热重载, 使用场景是什么?
+ // v.WatchConfig()
+ // v.OnConfigChange(func(e fsnotify.Event) {
+ // log.Println("检测到配置文件内容修改")
+ // if err := v.Unmarshal(&config.Cfg); err != nil {
+ // log.Panic("配置文件内容加载失败: ", err)
+ // }
+ // })
+ log.Println("配置文件内容加载成功")
+}