This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/internal/router/api.go
Victor_Jay d9eff2df08 refactor: 重构 Space 页面为统一多 Tab 布局 + 移除独立关注/粉丝子页面
- 后端:SpaceController 支持 5 个 Tab(文章/关注/粉丝/收藏/设置),统一处理本人与访客视图
- 后端:注入 FavoriteService 支持收藏夹 Tab,新增用户统计数据查询
- 后端:新增 PUT /api/space/privacy 隐私设置 API 端点
- 后端:移除 FollowPageController 及 /space/:uid/followers|following 路由
- 前端:完全重写 space/index.html,顶部信息栏 + Tab 导航 + 左侧栏 + 主内容区
- 前端:重写 space.css 适配新布局(Profile Header/Tab Bar/文章/收藏/设置)
- 清理:删除独立的 follow HTML 模板和 CSS 文件
- 模型:User 表新增 follower_list_public 隐私字段
2026-06-01 21:48:01 +08:00

195 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package router
import (
"metazone.cc/metalab/internal/config"
"metazone.cc/metalab/internal/middleware"
"github.com/gin-gonic/gin"
)
// setupAPIRoutes 注册 API 路由
func setupAPIRoutes(r *gin.Engine, cfg *config.Config, d *dependencies) {
// --- 设置页 API需登录 ---
settingsAPI := r.Group("/api/settings")
settingsAPI.Use(d.authMdw.Required())
settingsAPI.Use(d.authMdw.BannedWriteGuard())
settingsAPI.Use(middleware.CSRF(cfg))
{
settingsAPI.PUT("/profile", d.settingsCtrl.UpdateProfile)
settingsAPI.POST("/avatar", d.settingsCtrl.UploadAvatar)
settingsAPI.PUT("/password", d.settingsCtrl.ChangePassword)
settingsAPI.POST("/delete-account", d.settingsCtrl.DeleteAccount)
settingsAPI.GET("/audit-status", d.settingsCtrl.AuditStatus)
// 登录管理
settingsAPI.GET("/sessions", d.settingsCtrl.ListSessions)
settingsAPI.DELETE("/sessions/:sid", d.settingsCtrl.DestroySession)
settingsAPI.POST("/sessions/destroy-others", d.settingsCtrl.DestroyOtherSessions)
settingsAPI.PUT("/sessions/:sid/remark", d.settingsCtrl.UpdateSessionRemark)
// 通知偏好
settingsAPI.GET("/notify-prefs", d.settingsCtrl.GetNotifyPrefs)
settingsAPI.PUT("/notify-prefs", d.settingsCtrl.UpdateNotifyPref)
}
// --- 消息中心 API需登录 ---
messagesAPI := r.Group("/api/messages")
messagesAPI.Use(d.authMdw.Required())
messagesAPI.Use(d.authMdw.BannedWriteGuard())
messagesAPI.Use(middleware.CSRF(cfg))
{
messagesAPI.GET("/unread", d.messageCtrl.UnreadCount)
messagesAPI.POST("/:id/read", d.messageCtrl.MarkRead)
messagesAPI.POST("/read-all", d.messageCtrl.MarkAllRead)
}
// --- 积分/等级 API需登录 ---
levelAPI := r.Group("/api/level")
levelAPI.Use(d.authMdw.Required())
levelAPI.Use(d.authMdw.BannedWriteGuard())
levelAPI.Use(middleware.CSRF(cfg))
{
levelAPI.POST("/checkin", d.levelCtrl.CheckIn)
levelAPI.GET("/info", d.levelCtrl.GetLevel)
}
// --- 认证 API ---
api := r.Group("/api")
api.Use(middleware.CSRF(cfg))
{
api.POST("/auth/check-email", d.authCtrl.CheckEmail)
api.POST("/auth/register", d.authCtrl.Register)
api.POST("/auth/login", d.authCtrl.Login)
api.POST("/auth/confirm-restore", d.authCtrl.ConfirmRestore)
api.POST("/auth/logout", d.authCtrl.Logout)
api.POST("/auth/refresh", d.authCtrl.RefreshToken)
// 帖子公开 API无需登录
api.GET("/posts", d.postCtrl.ListAPI)
api.GET("/posts/:id", d.postCtrl.ShowAPI)
}
// --- 帖子 API需登录 ---
postsAPI := r.Group("/api/posts")
postsAPI.Use(d.authMdw.Required())
postsAPI.Use(d.authMdw.BannedWriteGuard())
postsAPI.Use(middleware.CSRF(cfg))
{
postsAPI.POST("/:id/submit", d.postCtrl.Submit)
postsAPI.POST("/upload-image", d.postCtrl.UploadImage)
}
// --- 创作中心 API需登录 ---
studioAPI := r.Group("/api/studio")
studioAPI.Use(d.authMdw.Required())
studioAPI.Use(d.authMdw.BannedWriteGuard())
studioAPI.Use(middleware.CSRF(cfg))
{
studioAPI.GET("/overview", d.studioCtrl.OverviewAPI)
studioAPI.GET("/posts", d.studioCtrl.ListPostsAPI)
studioAPI.POST("/posts", d.studioCtrl.Create)
studioAPI.PUT("/posts/:id", d.studioCtrl.Update)
studioAPI.DELETE("/posts/:id", d.studioCtrl.Delete)
studioAPI.POST("/posts/:id/submit", d.studioCtrl.Submit)
}
// --- 域能 API需登录 ---
energyAPI := r.Group("/api/energy")
energyAPI.Use(d.authMdw.Required())
energyAPI.Use(d.authMdw.BannedWriteGuard())
energyAPI.Use(middleware.CSRF(cfg))
{
energyAPI.POST("/energize", d.energyCtrl.Energize)
energyAPI.GET("/info", d.energyCtrl.GetEnergyInfo)
energyAPI.GET("/logs", d.energyCtrl.GetEnergyLogs)
}
// --- 评论 API部分需登录 ---
// 公开读取
commentsPublic := r.Group("/api/posts/:id/comments")
{
commentsPublic.GET("", d.commentCtrl.ListRootComments)
commentsPublic.GET("/:root_id/replies", d.commentCtrl.ListReplies)
}
// 需要登录的操作
commentsAPI := r.Group("/api")
commentsAPI.Use(d.authMdw.Required())
commentsAPI.Use(d.authMdw.BannedWriteGuard())
commentsAPI.Use(middleware.CSRF(cfg))
{
commentsAPI.POST("/posts/:id/comments", d.commentCtrl.CreateRoot)
commentsAPI.POST("/comments/:id/reply", d.commentCtrl.CreateReply)
commentsAPI.DELETE("/comments/:id", d.commentCtrl.Delete)
commentsAPI.GET("/users/search", d.commentCtrl.SearchUsers)
commentsAPI.POST("/comments/upload-image", d.commentCtrl.UploadImage)
}
// --- 赞/踩 API ---
// 公开:查询反应状态(未登录返回 none + 点赞数)
r.GET("/api/posts/:id/reaction", d.reactionCtrl.GetReaction)
// 需登录:切换赞/踩
reactionAPI := r.Group("/api/posts/:id")
reactionAPI.Use(d.authMdw.Required())
reactionAPI.Use(d.authMdw.BannedWriteGuard())
reactionAPI.Use(middleware.CSRF(cfg))
{
reactionAPI.POST("/like", d.reactionCtrl.ToggleLike)
reactionAPI.POST("/dislike", d.reactionCtrl.ToggleDislike)
}
// --- 关注 API ---
// 公开(未登录返回 false
r.GET("/api/users/:uid/follow-status", d.followCtrl.GetStatus)
r.GET("/api/users/:uid/followers", d.followCtrl.Followers)
r.GET("/api/users/:uid/following", d.followCtrl.Following)
// 需登录:切换关注
followAPI := r.Group("/api/users/:uid")
followAPI.Use(d.authMdw.Required())
followAPI.Use(d.authMdw.BannedWriteGuard())
followAPI.Use(middleware.CSRF(cfg))
{
followAPI.POST("/follow", d.followCtrl.Toggle)
}
// --- 收藏夹 API ---
// 公开:文章收藏状态(未登录返回 false
r.GET("/api/posts/:id/folder-status", d.favoriteCtrl.GetPostStatus)
// 公开:查看公开收藏夹内容
r.GET("/api/folders/:id/posts", d.favoriteCtrl.ListFolderItems)
// 需登录:收藏操作
folderAPI := r.Group("/api/folders")
folderAPI.Use(d.authMdw.Required())
folderAPI.Use(d.authMdw.BannedWriteGuard())
folderAPI.Use(middleware.CSRF(cfg))
{
folderAPI.GET("", d.favoriteCtrl.ListFolders)
folderAPI.POST("", d.favoriteCtrl.CreateFolder)
folderAPI.PUT("/:id", d.favoriteCtrl.UpdateFolder)
folderAPI.DELETE("/:id", d.favoriteCtrl.DeleteFolder)
folderAPI.POST("/:id/posts", d.favoriteCtrl.AddToFolder)
folderAPI.DELETE("/:id/posts/:postId", d.favoriteCtrl.RemoveFromFolder)
}
// 需登录切换收藏Toggle
favToggleAPI := r.Group("/api/posts/:id")
favToggleAPI.Use(d.authMdw.Required())
favToggleAPI.Use(d.authMdw.BannedWriteGuard())
favToggleAPI.Use(middleware.CSRF(cfg))
{
favToggleAPI.POST("/favorite", d.favoriteCtrl.ToggleFavorite)
}
// --- 空间/隐私设置 API需登录 ---
spaceAPI := r.Group("/api/space")
spaceAPI.Use(d.authMdw.Required())
spaceAPI.Use(d.authMdw.BannedWriteGuard())
spaceAPI.Use(middleware.CSRF(cfg))
{
spaceAPI.PUT("/privacy", d.spaceCtrl.UpdatePrivacy)
}
// --- Studio 趋势 API需登录 ---
trendsAPI := r.Group("/api/studio")
trendsAPI.Use(d.authMdw.Required())
{
trendsAPI.GET("/trends", d.studioCtrl.TrendsAPI)
}
}