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:
xujiang
2025-07-10 15:05:52 +08:00
parent a2f2f66f88
commit 39a42695d3
52 changed files with 6047 additions and 2349 deletions

View File

@ -0,0 +1,39 @@
package interfaces
import (
"context"
"photography-backend/internal/model/entity"
)
// CategoryRepository 分类仓储接口
type CategoryRepository interface {
// 基本CRUD操作
Create(ctx context.Context, category *entity.Category) error
GetByID(ctx context.Context, id uint) (*entity.Category, error)
GetBySlug(ctx context.Context, slug string) (*entity.Category, error)
Update(ctx context.Context, category *entity.Category) error
Delete(ctx context.Context, id uint) error
// 查询操作
List(ctx context.Context, parentID *uint) ([]*entity.Category, error)
GetTree(ctx context.Context) ([]*entity.CategoryTree, error)
GetChildren(ctx context.Context, parentID uint) ([]*entity.Category, error)
GetParent(ctx context.Context, categoryID uint) (*entity.Category, error)
// 排序操作
Reorder(ctx context.Context, parentID *uint, categoryIDs []uint) error
GetNextSortOrder(ctx context.Context, parentID *uint) (int, error)
// 验证操作
ValidateSlugUnique(ctx context.Context, slug string, excludeID uint) error
ValidateParentCategory(ctx context.Context, categoryID, parentID uint) error
// 统计操作
Count(ctx context.Context) (int64, error)
CountActive(ctx context.Context) (int64, error)
CountTopLevel(ctx context.Context) (int64, error)
GetStats(ctx context.Context) (*entity.CategoryStats, error)
// 工具方法
GenerateUniqueSlug(ctx context.Context, baseName string) (string, error)
}

View File

@ -0,0 +1,33 @@
package interfaces
import (
"context"
"photography-backend/internal/model/entity"
)
// PhotoRepository 照片仓储接口
type PhotoRepository interface {
// 基本CRUD操作
Create(ctx context.Context, photo *entity.Photo) error
GetByID(ctx context.Context, id uint) (*entity.Photo, error)
Update(ctx context.Context, photo *entity.Photo) error
Delete(ctx context.Context, id uint) error
// 查询操作
List(ctx context.Context, params *entity.PhotoListParams) ([]*entity.Photo, int64, error)
ListByUserID(ctx context.Context, userID uint, params *entity.PhotoListParams) ([]*entity.Photo, int64, error)
ListByCategory(ctx context.Context, categoryID uint, params *entity.PhotoListParams) ([]*entity.Photo, int64, error)
Search(ctx context.Context, query string, params *entity.PhotoListParams) ([]*entity.Photo, int64, error)
// 批量操作
BatchUpdate(ctx context.Context, ids []uint, updates map[string]interface{}) error
BatchDelete(ctx context.Context, ids []uint) error
BatchUpdateCategories(ctx context.Context, photoIDs []uint, categoryIDs []uint) error
BatchUpdateTags(ctx context.Context, photoIDs []uint, tagIDs []uint) error
// 统计操作
Count(ctx context.Context) (int64, error)
CountByStatus(ctx context.Context, status string) (int64, error)
CountByUser(ctx context.Context, userID uint) (int64, error)
GetStats(ctx context.Context) (*entity.PhotoStats, error)
}

View File

@ -0,0 +1,42 @@
package interfaces
import (
"context"
"photography-backend/internal/model/entity"
)
// TagRepository 标签仓储接口
type TagRepository interface {
// 基本CRUD操作
Create(ctx context.Context, tag *entity.Tag) error
GetByID(ctx context.Context, id uint) (*entity.Tag, error)
GetBySlug(ctx context.Context, slug string) (*entity.Tag, error)
GetByName(ctx context.Context, name string) (*entity.Tag, error)
Update(ctx context.Context, tag *entity.Tag) error
Delete(ctx context.Context, id uint) error
// 查询操作
List(ctx context.Context, params *entity.TagListParams) ([]*entity.Tag, int64, error)
Search(ctx context.Context, query string) ([]*entity.Tag, error)
GetPopular(ctx context.Context, limit int) ([]*entity.Tag, error)
GetByPhotos(ctx context.Context, photoIDs []uint) ([]*entity.Tag, error)
// 批量操作
CreateMultiple(ctx context.Context, tags []*entity.Tag) error
GetOrCreateByNames(ctx context.Context, names []string) ([]*entity.Tag, error)
BatchDelete(ctx context.Context, ids []uint) error
// 关联操作
AttachToPhoto(ctx context.Context, tagID, photoID uint) error
DetachFromPhoto(ctx context.Context, tagID, photoID uint) error
GetPhotoTags(ctx context.Context, photoID uint) ([]*entity.Tag, error)
// 统计操作
Count(ctx context.Context) (int64, error)
CountByPhotos(ctx context.Context) (map[uint]int64, error)
GetStats(ctx context.Context) (*entity.TagStats, error)
// 工具方法
GenerateUniqueSlug(ctx context.Context, baseName string) (string, error)
ValidateSlugUnique(ctx context.Context, slug string, excludeID uint) error
}

View File

@ -0,0 +1,40 @@
package interfaces
import (
"context"
"photography-backend/internal/model/entity"
)
// UserRepository 用户仓储接口
type UserRepository interface {
// 基本CRUD操作
Create(ctx context.Context, user *entity.User) error
GetByID(ctx context.Context, id uint) (*entity.User, error)
GetByEmail(ctx context.Context, email string) (*entity.User, error)
GetByUsername(ctx context.Context, username string) (*entity.User, error)
Update(ctx context.Context, user *entity.User) error
Delete(ctx context.Context, id uint) error
// 查询操作
List(ctx context.Context, params *entity.UserListParams) ([]*entity.User, int64, error)
Search(ctx context.Context, query string, params *entity.UserListParams) ([]*entity.User, int64, error)
// 认证相关
UpdatePassword(ctx context.Context, userID uint, hashedPassword string) error
UpdateLastLogin(ctx context.Context, userID uint) error
IncrementLoginCount(ctx context.Context, userID uint) error
// 状态管理
SetActive(ctx context.Context, userID uint, isActive bool) error
VerifyEmail(ctx context.Context, userID uint) error
// 统计操作
Count(ctx context.Context) (int64, error)
CountByRole(ctx context.Context, role entity.UserRole) (int64, error)
CountActive(ctx context.Context) (int64, error)
GetStats(ctx context.Context) (*entity.UserStats, error)
// 验证操作
ExistsByEmail(ctx context.Context, email string) (bool, error)
ExistsByUsername(ctx context.Context, username string) (bool, error)
}