88c37e50b2
Introduce a new enterprise-site publishing channel that lets tenants push articles to self-hosted PbootCMS sites alongside the existing media supply flow. Backend (server/internal/tenant): - enterprise_site_service: CRUD, ping, category sync, and article publish - enterprise_site_pbootcms: PbootCMS API client integration - enterprise_site_crypto: encrypt/decrypt stored site credentials - enterprise_site_handler + routes under /enterprise-sites - migrations for the enterprise site publisher tables - config: add SERVER_PUBLIC_BASE_URL (Server.PublicBaseURL) for callbacks - article/media services adjusted to support the publish flow Frontend (apps/admin-web): - PublishArticleModal & ArticlePublishStatus: enterprise-site publish UI - MediaView: manage enterprise sites and categories - api + shared-types: enterprise site endpoints and types - http-client: add PATCH method support Integrations: - pbootcms GeoPublisher controller plugin + install guide - docs/enterprise-site-publisher-v1.md design doc
331 lines
18 KiB
Go
331 lines
18 KiB
Go
package transport
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/geo-platform/tenant-api/internal/bootstrap"
|
|
"github.com/geo-platform/tenant-api/internal/shared/auth"
|
|
"github.com/geo-platform/tenant-api/internal/shared/middleware"
|
|
"github.com/geo-platform/tenant-api/internal/shared/swagger"
|
|
"github.com/geo-platform/tenant-api/internal/tenant/repository"
|
|
)
|
|
|
|
func RegisterRoutes(app *bootstrap.App) {
|
|
registerInternalMetricsRoutes(app)
|
|
|
|
authAPI := app.Engine.Group("/api/auth")
|
|
authHandler := NewAuthHandler(app)
|
|
authAPI.GET("/password-key", authHandler.PasswordPublicKey)
|
|
authAPI.POST("/login", authHandler.Login)
|
|
authAPI.POST("/refresh", authHandler.Refresh)
|
|
|
|
publicAssets := NewAssetHandler(app)
|
|
app.Engine.GET("/api/public/assets/:token", publicAssets.Serve)
|
|
|
|
mediaHandler := NewMediaHandler(app)
|
|
|
|
protected := app.Engine.Group("/api")
|
|
protected.Use(auth.Middleware(app.JWT, app.Sessions))
|
|
protected.Use(middleware.TenantScope())
|
|
protected.Use(middleware.WorkspaceScope(app.DB))
|
|
protected.Use(middleware.BrandScope(app.DB))
|
|
|
|
protected.GET("/auth/me", authHandler.Me)
|
|
protected.POST("/auth/password", authHandler.ChangePassword)
|
|
protected.POST("/auth/logout", authHandler.Logout)
|
|
|
|
desktopClientHandler := NewDesktopClientHandler(app)
|
|
desktopReleaseHandler := NewDesktopReleaseHandler(app)
|
|
desktopBugReportHandler := NewDesktopBugReportHandler(app)
|
|
desktopAccountHandler := NewDesktopAccountHandler(app)
|
|
desktopTaskHandler := NewDesktopTaskHandler(app)
|
|
desktopDispatchHandler := NewDesktopDispatchHandler(app)
|
|
desktopMonitoringHandler := NewDesktopMonitoringHandler(app)
|
|
desktopContentHandler := NewDesktopContentHandler(app)
|
|
publishJobHandler := NewPublishJobHandler(app)
|
|
protected.POST("/desktop/clients/register", desktopClientHandler.Register)
|
|
app.Engine.GET("/api/desktop/releases/latest", desktopReleaseHandler.LatestPublic)
|
|
app.Engine.GET("/api/desktop/releases/download-url", desktopReleaseHandler.DownloadURLPublic)
|
|
app.Engine.GET("/api/desktop/releases/updater/:platform/:arch/:channel/:version/:feed", desktopReleaseHandler.UpdaterFeedPublic)
|
|
app.Engine.GET("/api/desktop/releases/updater/:platform/:arch/:channel/:version", desktopReleaseHandler.UpdaterFeedPublic)
|
|
publicBugReportRateLimit := middleware.RateLimitByClientIP(10, time.Minute, 42961, "desktop_bug_report_rate_limited", "客户端 Bug 上报过于频繁,请稍后再试")
|
|
app.Engine.POST("/api/desktop/bug-reports", publicBugReportRateLimit, desktopBugReportHandler.UploadPublic)
|
|
|
|
desktopAuth := app.Engine.Group("/api/desktop")
|
|
desktopAuth.Use(DesktopClientMiddleware(repository.NewDesktopClientRepository(app.DB)))
|
|
desktopAuth.POST("/clients/rotate", desktopClientHandler.Rotate)
|
|
desktopAuth.POST("/clients/heartbeat", desktopClientHandler.Heartbeat)
|
|
desktopAuth.POST("/clients/offline", desktopClientHandler.Offline)
|
|
desktopAuth.POST("/clients/revoke", desktopClientHandler.Revoke)
|
|
desktopAuth.POST("/clients/bug-reports", desktopBugReportHandler.Upload)
|
|
desktopAuth.GET("/clients/releases/latest", desktopReleaseHandler.Latest)
|
|
desktopAuth.GET("/clients/releases/download-url", desktopReleaseHandler.DownloadURL)
|
|
desktopAuth.GET("/dispatch", desktopDispatchHandler.Dispatch)
|
|
desktopAuth.GET("/accounts", desktopAccountHandler.List)
|
|
desktopAuth.GET("/content/articles/:id", desktopContentHandler.Article)
|
|
desktopAuth.GET("/content/assets/:token", publicAssets.ServeDesktop)
|
|
desktopAuth.GET("/publish-tasks", desktopTaskHandler.ListPublish)
|
|
desktopAuth.POST("/accounts/health-reports", desktopAccountHandler.ReportHealth)
|
|
desktopAuth.POST("/accounts", desktopAccountHandler.Upsert)
|
|
desktopAuth.PATCH("/accounts/:id", desktopAccountHandler.Patch)
|
|
desktopAuth.DELETE("/accounts/:id", desktopAccountHandler.Delete)
|
|
desktopAuth.POST("/tasks/lease", desktopTaskHandler.Lease)
|
|
desktopAuth.POST("/tasks/:id/lease", desktopTaskHandler.Lease)
|
|
desktopAuth.POST("/tasks/:id/extend", desktopTaskHandler.Extend)
|
|
desktopAuth.POST("/tasks/:id/publish-submit-marker", desktopTaskHandler.MarkPublishSubmitStarted)
|
|
desktopAuth.POST("/tasks/:id/cancel", desktopTaskHandler.Cancel)
|
|
desktopAuth.POST("/tasks/:id/result", desktopTaskHandler.Result)
|
|
desktopAuth.POST("/publish-tasks/:id/retry", desktopTaskHandler.RetryPublish)
|
|
desktopAuth.POST("/monitoring/tasks/lease", desktopMonitoringHandler.Lease)
|
|
desktopAuth.POST("/monitoring/tasks/resume", desktopMonitoringHandler.Resume)
|
|
desktopAuth.POST("/monitoring/tasks/:id/result", desktopMonitoringHandler.Result)
|
|
desktopAuth.POST("/monitoring/tasks/:id/skip", desktopMonitoringHandler.Skip)
|
|
desktopAuth.POST("/monitoring/tasks/:id/cancel", desktopMonitoringHandler.Cancel)
|
|
|
|
tenantProtected := protected.Group("/tenant")
|
|
tenantProtected.Use(RequireActiveTenantSubscription(
|
|
repository.NewTenantPlanRepository(app.DB),
|
|
repository.NewAuthRepository(app.DB),
|
|
))
|
|
tenantProtected.GET("/accounts", desktopAccountHandler.TenantList)
|
|
tenantProtected.POST("/accounts/:id/request-delete", desktopAccountHandler.RequestDelete)
|
|
tenantProtected.POST("/tasks/:id/reconcile", desktopTaskHandler.Reconcile)
|
|
tenantProtected.POST("/tasks/:id/cancel", desktopTaskHandler.TenantCancel)
|
|
tenantProtected.GET("/publish-tasks", desktopTaskHandler.TenantListPublish)
|
|
tenantProtected.POST("/publish-tasks/:id/retry", middleware.RequireCurrentBrand(), desktopTaskHandler.TenantRetryPublish)
|
|
tenantProtected.POST("/publish-jobs", middleware.RequireCurrentBrand(), publishJobHandler.Create)
|
|
|
|
complianceHandler := NewComplianceHandler(app)
|
|
compliance := tenantProtected.Group("/compliance")
|
|
compliance.GET("/runtime-status", complianceHandler.RuntimeStatus)
|
|
compliance.POST("/check", complianceHandler.CheckPlain)
|
|
compliance.POST("/check-records/:id/ack", complianceHandler.CreateAck)
|
|
|
|
media := tenantProtected.Group("/media")
|
|
media.GET("/platforms", mediaHandler.ListPlatforms)
|
|
|
|
enterpriseSiteHandler := NewEnterpriseSiteHandler(app)
|
|
enterpriseSites := tenantProtected.Group("/enterprise-sites")
|
|
enterpriseSites.GET("", enterpriseSiteHandler.List)
|
|
enterpriseSites.POST("", enterpriseSiteHandler.Create)
|
|
enterpriseSites.PATCH("/:id", enterpriseSiteHandler.Update)
|
|
enterpriseSites.DELETE("/:id", enterpriseSiteHandler.Delete)
|
|
enterpriseSites.POST("/:id/ping", enterpriseSiteHandler.Ping)
|
|
enterpriseSites.GET("/:id/categories", enterpriseSiteHandler.Categories)
|
|
enterpriseSites.POST("/:id/categories/sync", enterpriseSiteHandler.SyncCategories)
|
|
enterpriseSites.POST("/:id/publish", middleware.RequireCurrentBrand(), enterpriseSiteHandler.PublishArticle)
|
|
|
|
desktopClient := tenantProtected.Group("/desktop-client")
|
|
desktopClient.GET("/releases/downloadable", desktopReleaseHandler.ListDownloadable)
|
|
|
|
mediaSupplyHandler := NewMediaSupplyHandler(app)
|
|
mediaSupply := tenantProtected.Group("/media-supply")
|
|
mediaSupply.GET("/resources", mediaSupplyHandler.ListResources)
|
|
mediaSupply.GET("/resources/by-ids", mediaSupplyHandler.ListResourcesByIDs)
|
|
mediaSupply.GET("/resources/search-options", mediaSupplyHandler.SearchOptions)
|
|
mediaSupply.POST("/sync-jobs", mediaSupplyHandler.QueueSync)
|
|
mediaSupply.PUT("/resources/:id/price", mediaSupplyHandler.SetResourcePrice)
|
|
mediaSupply.POST("/orders", middleware.RequireCurrentBrand(), mediaSupplyHandler.CreateOrder)
|
|
mediaSupply.GET("/orders", mediaSupplyHandler.ListOrders)
|
|
mediaSupply.GET("/orders/:id", mediaSupplyHandler.GetOrder)
|
|
mediaSupply.GET("/wallet", mediaSupplyHandler.WalletStatus)
|
|
mediaSupply.GET("/wallet/ledgers", mediaSupplyHandler.ListWalletLedgers)
|
|
mediaSupply.POST("/wallet/adjustments", mediaSupplyHandler.AdjustWallet)
|
|
mediaSupply.GET("/supplier-session", mediaSupplyHandler.SessionStatus)
|
|
mediaSupply.PUT("/supplier-session", mediaSupplyHandler.ImportSession)
|
|
mediaSupply.POST("/supplier-session/login", mediaSupplyHandler.LoginConfiguredAccount)
|
|
|
|
workspace := tenantProtected.Group("/workspace")
|
|
wsHandler := NewWorkspaceHandler(app)
|
|
workspace.GET("/overview", middleware.RequireCurrentBrand(), wsHandler.Overview)
|
|
workspace.GET("/recent-articles", middleware.RequireCurrentBrand(), wsHandler.RecentArticles)
|
|
workspace.GET("/quota-summary", wsHandler.QuotaSummary)
|
|
workspace.GET("/ai-point-usage", wsHandler.AIPointUsageLogs)
|
|
workspace.GET("/template-cards", wsHandler.TemplateCards)
|
|
workspace.GET("/kol-cards", wsHandler.KolCards)
|
|
|
|
templates := tenantProtected.Group("/templates")
|
|
tplHandler := NewTemplateHandler(app)
|
|
templates.GET("", tplHandler.List)
|
|
templates.GET("/:id", tplHandler.Detail)
|
|
templates.POST("/:id/drafts", middleware.RequireCurrentBrand(), tplHandler.SaveDraft)
|
|
templates.POST("/:id/analyze-tasks", tplHandler.CreateAnalyzeTask)
|
|
templates.GET("/:id/analyze_task_result", tplHandler.GetAnalyzeTaskResult)
|
|
templates.POST("/:id/title-tasks", tplHandler.CreateTitleTask)
|
|
templates.GET("/:id/gen_title_task_result", tplHandler.GetTitleTaskResult)
|
|
templates.POST("/:id/outline-tasks", tplHandler.CreateOutlineTask)
|
|
templates.GET("/:id/gen_outline_task_result", tplHandler.GetOutlineTaskResult)
|
|
templates.POST("/:id/generate", middleware.RequireCurrentBrand(), tplHandler.Generate)
|
|
|
|
kolManage := tenantProtected.Group("/kol/manage")
|
|
kolManageHandler := NewKolManageHandler(app, publicAssets)
|
|
kolManage.GET("/profile", kolManageHandler.GetProfile)
|
|
kolManage.PUT("/profile", kolManageHandler.UpdateProfile)
|
|
kolManage.POST("/profile/avatar", kolManageHandler.UploadAvatar)
|
|
kolManage.GET("/packages", kolManageHandler.ListPackages)
|
|
kolManage.POST("/packages", kolManageHandler.CreatePackage)
|
|
kolManage.PUT("/packages/:id", kolManageHandler.UpdatePackage)
|
|
kolManage.DELETE("/packages/:id", kolManageHandler.DeletePackage)
|
|
kolManage.PUT("/packages/:id/publish", kolManageHandler.PublishPackage)
|
|
kolManage.PUT("/packages/:id/archive", kolManageHandler.ArchivePackage)
|
|
kolManage.POST("/packages/:id/self-subscription", kolManageHandler.SelfSubscribePackage)
|
|
kolManage.DELETE("/packages/:id/self-subscription", kolManageHandler.CancelSelfSubscription)
|
|
kolManage.GET("/packages/:id/prompts", kolManageHandler.ListPrompts)
|
|
kolManage.POST("/packages/:id/prompts", kolManageHandler.CreatePrompt)
|
|
kolManage.GET("/prompts/:id", kolManageHandler.GetPromptLatest)
|
|
kolManage.PUT("/prompts/:id", kolManageHandler.UpdatePromptMetadata)
|
|
kolManage.DELETE("/prompts/:id", kolManageHandler.DeletePrompt)
|
|
kolManage.POST("/prompts/:id/save", kolManageHandler.SavePrompt)
|
|
kolManage.POST("/prompts/:id/publish", kolManageHandler.PublishPrompt)
|
|
kolManage.PUT("/prompts/:id/activate", kolManageHandler.ActivatePrompt)
|
|
kolManage.PUT("/prompts/:id/archive", kolManageHandler.ArchivePrompt)
|
|
kolManage.POST("/assist", kolManageHandler.AssistSubmit)
|
|
kolManage.POST("/assist/stream", kolManageHandler.AssistStream)
|
|
kolManage.GET("/assist/:id", kolManageHandler.AssistGet)
|
|
|
|
kolDash := tenantProtected.Group("/kol/dashboard")
|
|
kolDashboardHandler := NewKolDashboardHandler(app)
|
|
kolDash.GET("/overview", kolDashboardHandler.Overview)
|
|
kolDash.GET("/packages", kolDashboardHandler.Packages)
|
|
kolDash.GET("/trend", kolDashboardHandler.Trend)
|
|
|
|
kolMarketplace := tenantProtected.Group("/kol/marketplace")
|
|
kolMarketplaceHandler := NewKolMarketplaceHandler(app)
|
|
kolMarketplace.GET("/packages", kolMarketplaceHandler.ListPackages)
|
|
kolMarketplace.GET("/packages/:id", kolMarketplaceHandler.GetPackage)
|
|
kolMarketplace.POST("/packages/:id/subscribe", kolMarketplaceHandler.Subscribe)
|
|
|
|
kolSubscriptions := tenantProtected.Group("/kol")
|
|
kolSubscriptions.GET("/subscriptions", kolMarketplaceHandler.ListSubscriptions)
|
|
kolSubscriptions.GET("/subscription-prompts", kolMarketplaceHandler.ListSubscriptionPrompts)
|
|
kolSubscriptions.GET("/subscription-prompts/:id/schema", kolMarketplaceHandler.SubscriptionPromptSchema)
|
|
kolSubscriptions.POST("/subscription-prompts/:id/generate", middleware.RequireCurrentBrand(), kolMarketplaceHandler.Generate)
|
|
|
|
articles := tenantProtected.Group("/articles")
|
|
artHandler := NewArticleHandler(app)
|
|
articles.Use(middleware.RequireCurrentBrand())
|
|
articles.GET("", artHandler.List)
|
|
articles.POST("", artHandler.Create)
|
|
articles.POST("/generate-from-rule", artHandler.GenerateFromRule)
|
|
articles.POST("/imitations/generate", artHandler.GenerateImitation)
|
|
articleRecords := articles.Group("/:id")
|
|
articleRecords.Use(middleware.ArticleBrandScope(app.DB))
|
|
articleRecords.POST("/regenerate", artHandler.Regenerate)
|
|
articleRecords.POST("/images", artHandler.UploadImage)
|
|
articleRecords.POST("/selection-optimize/stream", artHandler.OptimizeSelectionStream)
|
|
articleRecords.GET("", artHandler.Detail)
|
|
articleRecords.PUT("", artHandler.Update)
|
|
articleRecords.GET("/stream", artHandler.Stream)
|
|
articleRecords.GET("/versions", artHandler.Versions)
|
|
articleRecords.POST("/compliance/check", complianceHandler.CheckArticle)
|
|
articleRecords.GET("/compliance/latest", complianceHandler.LatestCheck)
|
|
articleRecords.POST("/compliance/manual-reviews", complianceHandler.SubmitManualReview)
|
|
articleRecords.GET("/compliance/manual-reviews/latest", complianceHandler.LatestManualReview)
|
|
articleRecords.POST("/compliance/manual-reviews/:review_id/cancel", complianceHandler.CancelManualReview)
|
|
articleRecords.GET("/publish-records", mediaHandler.ListPublishRecords)
|
|
articleRecords.DELETE("", artHandler.Delete)
|
|
|
|
brands := tenantProtected.Group("/brands")
|
|
brandHandler := NewBrandHandler(app)
|
|
questionExpansionHandler := NewQuestionExpansionHandler(app)
|
|
brands.GET("", brandHandler.List)
|
|
brands.GET("/library-summary", brandHandler.Summary)
|
|
brands.POST("", brandHandler.Create)
|
|
brands.GET("/:id", brandHandler.Detail)
|
|
brands.PUT("/:id", brandHandler.Update)
|
|
brands.DELETE("/:id", brandHandler.Delete)
|
|
brands.GET("/:id/keywords", brandHandler.ListKeywords)
|
|
brands.POST("/:id/keywords", brandHandler.CreateKeyword)
|
|
brands.PUT("/:id/keywords/:kid", brandHandler.UpdateKeyword)
|
|
brands.DELETE("/:id/keywords/:kid", brandHandler.DeleteKeyword)
|
|
brands.GET("/:id/questions", brandHandler.ListQuestions)
|
|
brands.POST("/:id/questions", brandHandler.CreateQuestion)
|
|
brands.POST("/:id/questions/combination-preview", questionExpansionHandler.CombinationPreview)
|
|
brands.POST("/:id/questions/combination-fill", questionExpansionHandler.CombinationFill)
|
|
brands.POST("/:id/questions/ai-distill", questionExpansionHandler.AIDistill)
|
|
brands.POST("/:id/questions/classify-metadata", questionExpansionHandler.ClassifyMetadata)
|
|
brands.POST("/:id/questions/materialize", questionExpansionHandler.Materialize)
|
|
brands.PUT("/:id/questions/:qid", brandHandler.UpdateQuestion)
|
|
brands.DELETE("/:id/questions/:qid", brandHandler.DeleteQuestion)
|
|
brands.GET("/:id/competitors", brandHandler.ListCompetitors)
|
|
brands.POST("/:id/competitors", brandHandler.CreateCompetitor)
|
|
brands.PUT("/:id/competitors/:cid", brandHandler.UpdateCompetitor)
|
|
brands.DELETE("/:id/competitors/:cid", brandHandler.DeleteCompetitor)
|
|
|
|
monitoring := tenantProtected.Group("/monitoring")
|
|
monitoringHandler := NewMonitoringHandler(app)
|
|
monitoring.GET("/dashboard/composite", monitoringHandler.DashboardComposite)
|
|
monitoring.GET("/citation-summary", monitoringHandler.CitationSummary)
|
|
monitoring.GET("/brands/:brand_id/questions/:question_id/detail", monitoringHandler.QuestionDetail)
|
|
monitoring.POST("/brands/:brand_id/collect-now", monitoringHandler.CollectNow)
|
|
|
|
knowledge := tenantProtected.Group("/knowledge")
|
|
knowledgeHandler := NewKnowledgeHandler(app)
|
|
knowledge.GET("/groups", knowledgeHandler.ListGroups)
|
|
knowledge.POST("/groups", knowledgeHandler.CreateGroup)
|
|
knowledge.PUT("/groups/:gid", knowledgeHandler.UpdateGroup)
|
|
knowledge.DELETE("/groups/:gid", knowledgeHandler.DeleteGroup)
|
|
knowledge.GET("/items", knowledgeHandler.ListItems)
|
|
knowledge.GET("/items/:id", knowledgeHandler.GetItemDetail)
|
|
knowledge.POST("/items/text", knowledgeHandler.CreateTextItem)
|
|
knowledge.POST("/items/url", knowledgeHandler.CreateURLItem)
|
|
knowledge.POST("/items/file", knowledgeHandler.CreateFileItem)
|
|
knowledge.POST("/items/retry/:id", knowledgeHandler.RetryItem)
|
|
knowledge.DELETE("/items/:id", knowledgeHandler.DeleteItem)
|
|
|
|
// Prompt Rules
|
|
promptRules := tenantProtected.Group("/prompt-rules")
|
|
promptRules.Use(middleware.RequireCurrentBrand())
|
|
prHandler := NewPromptRuleHandler(app)
|
|
promptRules.GET("", prHandler.List)
|
|
promptRules.GET("/simple", prHandler.ListSimple)
|
|
promptRules.POST("", prHandler.Create)
|
|
promptRules.GET("/:id", prHandler.Detail)
|
|
promptRules.PUT("/:id", prHandler.Update)
|
|
promptRules.DELETE("/:id", prHandler.Delete)
|
|
promptRules.PUT("/:id/status", prHandler.ToggleStatus)
|
|
// Prompt Rule Groups
|
|
promptRules.GET("/groups", prHandler.ListGroups)
|
|
promptRules.POST("/groups", prHandler.CreateGroup)
|
|
promptRules.PUT("/groups/:gid", prHandler.UpdateGroup)
|
|
promptRules.DELETE("/groups/:gid", prHandler.DeleteGroup)
|
|
|
|
// Schedule Tasks
|
|
schedules := tenantProtected.Group("/schedules")
|
|
schHandler := NewScheduleTaskHandler(app)
|
|
schedules.Use(middleware.RequireCurrentBrand())
|
|
schedules.GET("", schHandler.List)
|
|
schedules.POST("", schHandler.Create)
|
|
schedules.GET("/:id", schHandler.Detail)
|
|
schedules.PUT("/:id", schHandler.Update)
|
|
schedules.DELETE("/:id", schHandler.Delete)
|
|
schedules.PUT("/:id/status", schHandler.ToggleStatus)
|
|
|
|
instantTasks := tenantProtected.Group("/instant-tasks")
|
|
instHandler := NewInstantTaskHandler(app)
|
|
instantTasks.GET("", middleware.RequireCurrentBrand(), instHandler.List)
|
|
|
|
images := tenantProtected.Group("/images")
|
|
imgHandler := NewImageHandler(app)
|
|
images.GET("", imgHandler.ListImages)
|
|
images.POST("", imgHandler.UploadImage)
|
|
images.PUT("/:id", imgHandler.UpdateImage)
|
|
images.GET("/:id/references", imgHandler.GetImageReferences)
|
|
images.DELETE("/:id", imgHandler.DeleteImage)
|
|
images.GET("/storage-usage", imgHandler.StorageUsage)
|
|
|
|
imageFolders := tenantProtected.Group("/images/folders")
|
|
imageFolders.GET("", imgHandler.ListFolders)
|
|
imageFolders.POST("", imgHandler.CreateFolder)
|
|
imageFolders.PUT("/:id", imgHandler.UpdateFolder)
|
|
imageFolders.GET("/:id/delete-preview", imgHandler.FolderDeletePreview)
|
|
imageFolders.DELETE("/:id", imgHandler.DeleteFolder)
|
|
|
|
if swagger.EnabledForMode(app.Config().Server.Mode) {
|
|
swagger.Register(app.Engine, swagger.Config{
|
|
Title: "省心推 Admin API",
|
|
Version: "dev",
|
|
})
|
|
}
|
|
}
|