refactor: 重构后端架构为 go-zero 框架,优化项目结构
主要变更: - 采用 go-zero 框架替代 Gin,提升开发效率 - 重构项目结构,API 文件模块化组织 - 将 model 移至 api/internal/model 目录 - 移除 common 包,改为标准 pkg 目录结构 - 实现统一的仓储模式,支持配置驱动数据库切换 - 简化测试策略,专注 API 集成测试 - 更新 CLAUDE.md 文档,提供详细的开发指导 技术栈更新: - 框架: Gin → go-zero v1.6.0+ - 代码生成: 引入 goctl 工具 - 架构模式: 四层架构 → go-zero 三层架构 (Handler→Logic→Model) - 项目布局: 遵循 Go 社区标准和 go-zero 最佳实践
This commit is contained in:
@ -14,6 +14,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
|
||||
"photography-backend/internal/config"
|
||||
"photography-backend/internal/database"
|
||||
"photography-backend/internal/repository/postgres"
|
||||
"photography-backend/internal/service"
|
||||
"photography-backend/internal/service/auth"
|
||||
@ -38,7 +39,7 @@ func main() {
|
||||
defer zapLogger.Sync()
|
||||
|
||||
// 初始化数据库
|
||||
db, err := postgres.NewDatabase(&cfg.Database)
|
||||
db, err := database.New(cfg)
|
||||
if err != nil {
|
||||
zapLogger.Fatal("Failed to connect to database", zap.Error(err))
|
||||
}
|
||||
@ -49,11 +50,16 @@ func main() {
|
||||
zapLogger.Fatal("Failed to migrate database", zap.Error(err))
|
||||
}
|
||||
|
||||
// 填充种子数据
|
||||
if err := db.Seed(); err != nil {
|
||||
zapLogger.Warn("Failed to seed database", zap.Error(err))
|
||||
}
|
||||
|
||||
// 初始化仓库
|
||||
userRepo := postgres.NewUserRepository(db.DB)
|
||||
photoRepo := postgres.NewPhotoRepository(db.DB)
|
||||
categoryRepo := postgres.NewCategoryRepository(db.DB)
|
||||
tagRepo := postgres.NewTagRepository(db.DB)
|
||||
userRepo := postgres.NewUserRepository(db.GetDB())
|
||||
photoRepo := postgres.NewPhotoRepository(db.GetDB())
|
||||
categoryRepo := postgres.NewCategoryRepository(db.GetDB())
|
||||
tagRepo := postgres.NewTagRepository(db.GetDB())
|
||||
|
||||
// 初始化服务
|
||||
jwtService := auth.NewJWTService(&cfg.JWT)
|
||||
@ -98,12 +104,12 @@ func main() {
|
||||
|
||||
// 设置路由
|
||||
routes.SetupRoutes(r, &routes.Handlers{
|
||||
Auth: authHandler,
|
||||
Photo: photoHandler,
|
||||
Category: categoryHandler,
|
||||
Tag: tagHandler,
|
||||
User: userHandler,
|
||||
}, authMiddleware)
|
||||
AuthHandler: authHandler,
|
||||
PhotoHandler: photoHandler,
|
||||
CategoryHandler: categoryHandler,
|
||||
TagHandler: tagHandler,
|
||||
UserHandler: userHandler,
|
||||
}, authMiddleware, zapLogger)
|
||||
|
||||
// 创建HTTP服务器
|
||||
server := &http.Server{
|
||||
|
||||
@ -13,11 +13,12 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"photography-backend/internal/config"
|
||||
"photography-backend/internal/database"
|
||||
"photography-backend/internal/models"
|
||||
"photography-backend/internal/model/entity"
|
||||
"photography-backend/internal/model/dto"
|
||||
"photography-backend/internal/service/upload"
|
||||
"photography-backend/internal/service/auth"
|
||||
"photography-backend/internal/handlers"
|
||||
"photography-backend/internal/middleware"
|
||||
"photography-backend/internal/api/handlers"
|
||||
"photography-backend/internal/api/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -217,18 +218,18 @@ func main() {
|
||||
|
||||
// 认证相关处理函数
|
||||
func login(c *gin.Context) {
|
||||
var req models.LoginRequest
|
||||
var req dto.LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 查找用户
|
||||
var user models.User
|
||||
var user entity.User
|
||||
db := database.GetDB()
|
||||
|
||||
// 可以使用用户名或邮箱登录
|
||||
if err := db.Where("username = ? OR email = ?", req.Username, req.Username).First(&user).Error; err != nil {
|
||||
if err := db.Where("username = ? OR email = ?", req.Email, req.Email).First(&user).Error; err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
|
||||
return
|
||||
}
|
||||
@ -250,14 +251,14 @@ func login(c *gin.Context) {
|
||||
}
|
||||
|
||||
func register(c *gin.Context) {
|
||||
var req models.CreateUserRequest
|
||||
var req dto.CreateUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户名是否已存在
|
||||
var existingUser models.User
|
||||
var existingUser entity.User
|
||||
db := database.GetDB()
|
||||
if err := db.Where("username = ? OR email = ?", req.Username, req.Email).First(&existingUser).Error; err == nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "用户名或邮箱已存在"})
|
||||
@ -265,12 +266,12 @@ func register(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
user := models.User{
|
||||
user := entity.User{
|
||||
Username: req.Username,
|
||||
Email: req.Email,
|
||||
Password: req.Password, // 实际项目中应该加密
|
||||
Name: req.Name,
|
||||
Role: "user",
|
||||
Role: entity.UserRoleUser,
|
||||
IsActive: true,
|
||||
}
|
||||
|
||||
@ -298,7 +299,7 @@ func refreshToken(c *gin.Context) {
|
||||
|
||||
// 用户 CRUD 操作
|
||||
func getUsers(c *gin.Context) {
|
||||
var users []models.User
|
||||
var users []entity.User
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Find(&users).Error; err != nil {
|
||||
@ -310,7 +311,7 @@ func getUsers(c *gin.Context) {
|
||||
}
|
||||
|
||||
func createUser(c *gin.Context) {
|
||||
var user models.User
|
||||
var user entity.User
|
||||
if err := c.ShouldBindJSON(&user); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
@ -327,7 +328,7 @@ func createUser(c *gin.Context) {
|
||||
|
||||
func getUser(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var user models.User
|
||||
var user entity.User
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&user, id).Error; err != nil {
|
||||
@ -340,7 +341,7 @@ func getUser(c *gin.Context) {
|
||||
|
||||
func updateUser(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var user models.User
|
||||
var user entity.User
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&user, id).Error; err != nil {
|
||||
@ -365,7 +366,7 @@ func deleteUser(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Delete(&models.User{}, id).Error; err != nil {
|
||||
if err := db.Delete(&entity.User{}, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
@ -375,7 +376,7 @@ func deleteUser(c *gin.Context) {
|
||||
|
||||
// 分类 CRUD 操作
|
||||
func getCategories(c *gin.Context) {
|
||||
var categories []models.Category
|
||||
var categories []entity.Category
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Find(&categories).Error; err != nil {
|
||||
@ -387,7 +388,7 @@ func getCategories(c *gin.Context) {
|
||||
}
|
||||
|
||||
func createCategory(c *gin.Context) {
|
||||
var category models.Category
|
||||
var category entity.Category
|
||||
if err := c.ShouldBindJSON(&category); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
@ -404,7 +405,7 @@ func createCategory(c *gin.Context) {
|
||||
|
||||
func getCategory(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var category models.Category
|
||||
var category entity.Category
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&category, id).Error; err != nil {
|
||||
@ -417,7 +418,7 @@ func getCategory(c *gin.Context) {
|
||||
|
||||
func updateCategory(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var category models.Category
|
||||
var category entity.Category
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&category, id).Error; err != nil {
|
||||
@ -442,7 +443,7 @@ func deleteCategory(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Delete(&models.Category{}, id).Error; err != nil {
|
||||
if err := db.Delete(&entity.Category{}, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
@ -452,7 +453,7 @@ func deleteCategory(c *gin.Context) {
|
||||
|
||||
// 标签 CRUD 操作
|
||||
func getTags(c *gin.Context) {
|
||||
var tags []models.Tag
|
||||
var tags []entity.Tag
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Find(&tags).Error; err != nil {
|
||||
@ -464,7 +465,7 @@ func getTags(c *gin.Context) {
|
||||
}
|
||||
|
||||
func createTag(c *gin.Context) {
|
||||
var tag models.Tag
|
||||
var tag entity.Tag
|
||||
if err := c.ShouldBindJSON(&tag); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
@ -481,7 +482,7 @@ func createTag(c *gin.Context) {
|
||||
|
||||
func getTag(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var tag models.Tag
|
||||
var tag entity.Tag
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&tag, id).Error; err != nil {
|
||||
@ -494,7 +495,7 @@ func getTag(c *gin.Context) {
|
||||
|
||||
func updateTag(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var tag models.Tag
|
||||
var tag entity.Tag
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&tag, id).Error; err != nil {
|
||||
@ -519,7 +520,7 @@ func deleteTag(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Delete(&models.Tag{}, id).Error; err != nil {
|
||||
if err := db.Delete(&entity.Tag{}, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
@ -529,7 +530,7 @@ func deleteTag(c *gin.Context) {
|
||||
|
||||
// 相册 CRUD 操作
|
||||
func getAlbums(c *gin.Context) {
|
||||
var albums []models.Album
|
||||
var albums []entity.Album
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Find(&albums).Error; err != nil {
|
||||
@ -541,7 +542,7 @@ func getAlbums(c *gin.Context) {
|
||||
}
|
||||
|
||||
func createAlbum(c *gin.Context) {
|
||||
var album models.Album
|
||||
var album entity.Album
|
||||
if err := c.ShouldBindJSON(&album); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
@ -558,7 +559,7 @@ func createAlbum(c *gin.Context) {
|
||||
|
||||
func getAlbum(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var album models.Album
|
||||
var album entity.Album
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&album, id).Error; err != nil {
|
||||
@ -571,7 +572,7 @@ func getAlbum(c *gin.Context) {
|
||||
|
||||
func updateAlbum(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var album models.Album
|
||||
var album entity.Album
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&album, id).Error; err != nil {
|
||||
@ -596,7 +597,7 @@ func deleteAlbum(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Delete(&models.Album{}, id).Error; err != nil {
|
||||
if err := db.Delete(&entity.Album{}, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
@ -606,7 +607,7 @@ func deleteAlbum(c *gin.Context) {
|
||||
|
||||
// 照片 CRUD 操作
|
||||
func getPhotos(c *gin.Context) {
|
||||
var photos []models.Photo
|
||||
var photos []entity.Photo
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Find(&photos).Error; err != nil {
|
||||
@ -618,7 +619,7 @@ func getPhotos(c *gin.Context) {
|
||||
}
|
||||
|
||||
func createPhoto(c *gin.Context) {
|
||||
var photo models.Photo
|
||||
var photo entity.Photo
|
||||
if err := c.ShouldBindJSON(&photo); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
@ -635,7 +636,7 @@ func createPhoto(c *gin.Context) {
|
||||
|
||||
func getPhoto(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var photo models.Photo
|
||||
var photo entity.Photo
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&photo, id).Error; err != nil {
|
||||
@ -648,7 +649,7 @@ func getPhoto(c *gin.Context) {
|
||||
|
||||
func updatePhoto(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var photo models.Photo
|
||||
var photo entity.Photo
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.First(&photo, id).Error; err != nil {
|
||||
@ -673,7 +674,7 @@ func deletePhoto(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
db := database.GetDB()
|
||||
|
||||
if err := db.Delete(&models.Photo{}, id).Error; err != nil {
|
||||
if err := db.Delete(&entity.Photo{}, id).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user