主要变更: - 采用 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 最佳实践
131 lines
4.9 KiB
Go
131 lines
4.9 KiB
Go
package entity
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Category 分类实体
|
|
type Category struct {
|
|
ID uint `json:"id" gorm:"primarykey"`
|
|
Name string `json:"name" gorm:"not null;size:100"`
|
|
Slug string `json:"slug" gorm:"uniqueIndex;not null;size:100"`
|
|
Description string `json:"description" gorm:"type:text"`
|
|
ParentID *uint `json:"parent_id" gorm:"index"`
|
|
Color string `json:"color" gorm:"default:#3b82f6;size:7"`
|
|
CoverImage string `json:"cover_image" gorm:"size:500"`
|
|
Sort int `json:"sort" gorm:"default:0;index"`
|
|
SortOrder int `json:"sort_order" gorm:"default:0;index"`
|
|
IsActive bool `json:"is_active" gorm:"default:true;index"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"`
|
|
|
|
// 关联
|
|
Parent *Category `json:"parent,omitempty" gorm:"foreignKey:ParentID"`
|
|
Children []Category `json:"children,omitempty" gorm:"foreignKey:ParentID"`
|
|
Photos []Photo `json:"photos,omitempty" gorm:"foreignKey:CategoryID"`
|
|
Albums []Album `json:"albums,omitempty" gorm:"foreignKey:CategoryID"`
|
|
PhotoCount int64 `json:"photo_count" gorm:"-"` // 照片数量,不存储在数据库中
|
|
}
|
|
|
|
// CategoryTree 分类树结构(用于前端显示)
|
|
type CategoryTree struct {
|
|
ID uint `json:"id"`
|
|
Name string `json:"name"`
|
|
Slug string `json:"slug"`
|
|
Description string `json:"description"`
|
|
ParentID *uint `json:"parent_id"`
|
|
Color string `json:"color"`
|
|
CoverImage string `json:"cover_image"`
|
|
Sort int `json:"sort"`
|
|
SortOrder int `json:"sort_order"`
|
|
IsActive bool `json:"is_active"`
|
|
PhotoCount int64 `json:"photo_count"`
|
|
Children []CategoryTree `json:"children"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// CategoryStats 分类统计信息
|
|
type CategoryStats struct {
|
|
Total int64 `json:"total"` // 总分类数
|
|
Active int64 `json:"active"` // 活跃分类数
|
|
TopLevel int64 `json:"top_level"` // 顶级分类数
|
|
TotalCategories int64 `json:"total_categories"` // 总分类数(别名)
|
|
MaxLevel int64 `json:"max_level"` // 最大层级
|
|
FeaturedCount int64 `json:"featured_count"` // 特色分类数
|
|
PhotoCounts map[string]int64 `json:"photo_counts"` // 各分类照片数量
|
|
}
|
|
|
|
// CategoryListParams 分类列表查询参数
|
|
type CategoryListParams struct {
|
|
Page int `json:"page" form:"page"`
|
|
Limit int `json:"limit" form:"limit"`
|
|
Search string `json:"search" form:"search"`
|
|
ParentID *uint `json:"parent_id" form:"parent_id"`
|
|
IsActive *bool `json:"is_active" form:"is_active"`
|
|
IncludeStats bool `json:"include_stats" form:"include_stats"`
|
|
SortBy string `json:"sort_by" form:"sort_by"`
|
|
Order string `json:"order" form:"order"`
|
|
}
|
|
|
|
// CreateCategoryRequest 创建分类请求
|
|
type CreateCategoryRequest struct {
|
|
Name string `json:"name" binding:"required,max=100"`
|
|
Slug string `json:"slug" binding:"required,max=100"`
|
|
Description string `json:"description" binding:"max=500"`
|
|
ParentID *uint `json:"parent_id"`
|
|
Color string `json:"color" binding:"max=7"`
|
|
CoverImage string `json:"cover_image" binding:"max=500"`
|
|
Sort int `json:"sort"`
|
|
}
|
|
|
|
// UpdateCategoryRequest 更新分类请求
|
|
type UpdateCategoryRequest struct {
|
|
Name *string `json:"name" binding:"omitempty,max=100"`
|
|
Slug *string `json:"slug" binding:"omitempty,max=100"`
|
|
Description *string `json:"description" binding:"max=500"`
|
|
ParentID *uint `json:"parent_id"`
|
|
Color *string `json:"color" binding:"omitempty,max=7"`
|
|
CoverImage *string `json:"cover_image" binding:"omitempty,max=500"`
|
|
SortOrder *int `json:"sort_order"`
|
|
IsActive *bool `json:"is_active"`
|
|
}
|
|
|
|
// ReorderCategoriesRequest 重新排序分类请求
|
|
type ReorderCategoriesRequest struct {
|
|
ParentID *uint `json:"parent_id"`
|
|
CategoryIDs []uint `json:"category_ids" binding:"required,min=1"`
|
|
}
|
|
|
|
// GenerateSlugRequest 生成slug请求
|
|
type GenerateSlugRequest struct {
|
|
Name string `json:"name" binding:"required,max=100"`
|
|
}
|
|
|
|
// GenerateSlugResponse 生成slug响应
|
|
type GenerateSlugResponse struct {
|
|
Slug string `json:"slug"`
|
|
}
|
|
|
|
// SuccessResponse 成功响应
|
|
type SuccessResponse struct {
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// TableName 指定表名
|
|
func (Category) TableName() string {
|
|
return "categories"
|
|
}
|
|
|
|
// IsTopLevel 检查是否为顶级分类
|
|
func (c *Category) IsTopLevel() bool {
|
|
return c.ParentID == nil
|
|
}
|
|
|
|
// HasChildren 检查是否有子分类
|
|
func (c *Category) HasChildren() bool {
|
|
return len(c.Children) > 0
|
|
} |