feat: 书库导入导出/图片变体/书籍搜索/小组件运行时等
新增: - 书库导入导出(library_import/library_export)及测试 - 图片变体生成(image_variants)与响应式图片(responsiveImage) - 书籍搜索(bookSearch)+ BookSearch/LibrarySearchGrid 组件 - 小组件运行时(widgetRuntime)与静态检查(widgetLint) - 上传缓存中间件(upload_cache)与字体 CSS 提取脚本 其它: - 后端 handlers/services 全量调整 - 前端页面、组件、库函数与配置更新
This commit is contained in:
@@ -101,7 +101,9 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
|
||||
postFileSvc.WithOperations(ops)
|
||||
pointsSvc := service.NewPointsService(model.DB)
|
||||
leaderboardSvc := service.NewLeaderboardService(model.DB)
|
||||
librarySvc := service.NewLibraryService(model.DB, cfg.DataDir).WithSetting(settingSvc)
|
||||
librarySvc := service.NewLibraryService(model.DB, cfg.DataDir).
|
||||
WithSetting(settingSvc).
|
||||
WithUploadsDir(filepath.Join(cfg.DataDir, "uploads"))
|
||||
adminUserSvc := service.NewAdminUserService(model.DB)
|
||||
legacyImportSvc := service.NewLegacyImportService(model.DB, filepath.Join(cfg.DataDir, "uploads"))
|
||||
moderationSvc := service.NewModerationService(model.DB, notifSvc)
|
||||
@@ -183,6 +185,9 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
|
||||
// 挂在 OptionalAuth 之后可顺带拿到登录用户
|
||||
r.Use(middleware.VisitCapture(visitSvc))
|
||||
|
||||
// 上传文件长缓存(必须先于 r.Static 注册;文件名随机不覆盖,可 immutable)
|
||||
r.Use(middleware.UploadStaticCache())
|
||||
|
||||
// 上传文件静态服务(data/uploads → /uploads)
|
||||
r.Static("/uploads", filepath.Join(cfg.DataDir, "uploads"))
|
||||
|
||||
@@ -209,7 +214,6 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
|
||||
pubAPI.POST("/posts/:id/unlock-password", middleware.CSRFMiddleware(), middleware.RateLimitMiddleware(limiter, service.RateHidePassword), h.UnlockPostPassword)
|
||||
pubAPI.GET("/posts/:id/attachments/:aid/download", h.DownloadPostAttachment)
|
||||
pubAPI.GET("/posts/:id/comments", h.PostComments)
|
||||
pubAPI.GET("/posts/:id/comments/:cid", h.CommentLocation)
|
||||
pubAPI.GET("/users/:id", h.UserProfile)
|
||||
pubAPI.GET("/users/:id/comments", h.UserComments)
|
||||
pubAPI.GET("/users/:id/favorites", h.UserFavorites)
|
||||
@@ -226,6 +230,8 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
|
||||
pubAPI.GET("/library/:slug", h.LibraryDetail)
|
||||
pubAPI.GET("/library/files/:fid/download", h.LibraryFileDownload)
|
||||
pubAPI.GET("/site-state", h.SiteState)
|
||||
// 自适应图片变体(?u=<源图URL>&w=<白名单宽度>,公开只读、immutable 缓存)
|
||||
pubAPI.GET("/img", h.ImageVariant)
|
||||
pubAPI.GET("/media/:object", h.PublicObject)
|
||||
pubAPI.POST("/auth/code", middleware.CSRFMiddleware(), h.SendEmailCode)
|
||||
pubAPI.POST("/auth/reset-password", middleware.CSRFMiddleware(), h.ResetPassword)
|
||||
@@ -376,23 +382,34 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
|
||||
// 群聊监管:移出后挂到 RequireAuth 组,允许「仅群管/消息 flag」用户访问
|
||||
// (见下方 msgAPI)
|
||||
|
||||
// 站点公告文章管理(管理员及以上)
|
||||
announceAPI := staffAPI.Group("", authMW.RequirePerm(service.PermAnnouncements))
|
||||
// 渠道内容管理(公告/单页/书库/广告):RequireActor 允许任意登录账号进入,
|
||||
// 由 RequirePerm 按渠道权限码放行——角色默认管理员及以上,
|
||||
// 超管/站长亦可将单个渠道授予板块管理员或普通用户(账号级授权)
|
||||
permAPI := r.Group("/api/admin", authMW.RequireActor(), middleware.CSRFMiddleware())
|
||||
|
||||
// 站点公告文章管理(PermAnnouncements)
|
||||
announceAPI := permAPI.Group("", authMW.RequirePerm(service.PermAnnouncements))
|
||||
announceAPI.GET("/announcements", h.AdminListAnnouncements)
|
||||
announceAPI.POST("/announcements", h.AdminCreateAnnouncement)
|
||||
announceAPI.PUT("/announcements/:id", h.AdminUpdateAnnouncement)
|
||||
announceAPI.POST("/announcements/:id/pin", h.AdminToggleAnnouncementPin)
|
||||
announceAPI.DELETE("/announcements/:id", h.AdminDeleteAnnouncement)
|
||||
announceAPI.GET("/pages", h.AdminListSitePages)
|
||||
announceAPI.POST("/pages", h.AdminCreateSitePage)
|
||||
announceAPI.PUT("/pages/:id", h.AdminUpdateSitePage)
|
||||
announceAPI.DELETE("/pages/:id", h.AdminDeleteSitePage)
|
||||
announceAPI.DELETE("/pages/:id/purge", h.AdminPurgeSitePage)
|
||||
|
||||
// 书库管理(管理员及以上,同公告/单页权限)
|
||||
libraryAPI := staffAPI.Group("/library", authMW.RequirePerm(service.PermAnnouncements))
|
||||
// 站点单页管理(PermPages)
|
||||
pagesAPI := permAPI.Group("", authMW.RequirePerm(service.PermPages))
|
||||
pagesAPI.GET("/pages", h.AdminListSitePages)
|
||||
pagesAPI.POST("/pages", h.AdminCreateSitePage)
|
||||
pagesAPI.PUT("/pages/:id", h.AdminUpdateSitePage)
|
||||
pagesAPI.DELETE("/pages/:id", h.AdminDeleteSitePage)
|
||||
pagesAPI.DELETE("/pages/:id/purge", h.AdminPurgeSitePage)
|
||||
|
||||
// 书库管理(PermLibrary)
|
||||
libraryAPI := permAPI.Group("/library", authMW.RequirePerm(service.PermLibrary))
|
||||
{
|
||||
libraryAPI.GET("/docs", h.AdminListLibraryDocs)
|
||||
libraryAPI.GET("/export", h.AdminExportAllLibrary)
|
||||
libraryAPI.POST("/import", middleware.RateLimitMiddleware(limiter, service.RateUpload), h.AdminImportLibrary)
|
||||
libraryAPI.GET("/docs/:id/export", h.AdminExportLibraryDoc)
|
||||
libraryAPI.POST("/docs", h.AdminCreateLibraryDoc)
|
||||
libraryAPI.PUT("/docs/:id", h.AdminUpdateLibraryDoc)
|
||||
libraryAPI.DELETE("/docs/:id", h.AdminDeleteLibraryDoc)
|
||||
@@ -409,8 +426,8 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
|
||||
libraryAPI.POST("/cover/from-media", middleware.RateLimitMiddleware(limiter, service.RateUpload), h.UploadLibraryCoverFromMedia)
|
||||
}
|
||||
|
||||
// 广告位管理(管理员及以上)
|
||||
adsAPI := staffAPI.Group("", authMW.RequirePerm(service.PermAnnouncements))
|
||||
// 广告位管理(PermAds)
|
||||
adsAPI := permAPI.Group("", authMW.RequirePerm(service.PermAds))
|
||||
adsAPI.GET("/ads/config", h.AdminGetAdsConfig)
|
||||
adsAPI.PUT("/ads/config", h.AdminSaveAdsConfig)
|
||||
adsAPI.GET("/ads", h.AdminListAds)
|
||||
@@ -477,6 +494,8 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
|
||||
usersAPI.GET("/users", h.AdminListUsers)
|
||||
usersAPI.PUT("/users/:id/role", h.AdminUpdateUserRole)
|
||||
usersAPI.PUT("/users/:id/messages", h.AdminSetUserMessages)
|
||||
usersAPI.GET("/users/:id/perms", h.AdminGetUserPerms)
|
||||
usersAPI.PUT("/users/:id/perms", h.AdminSetUserPerms)
|
||||
usersAPI.PUT("/users/:id/ban", h.AdminSetUserBan)
|
||||
usersAPI.GET("/users/:id/login-logs", h.AdminUserLoginLogs)
|
||||
// 积分管理:手动调整(加分计累计/扣分仅扣余额)与积分流水分页
|
||||
|
||||
Reference in New Issue
Block a user