package dto import ( "time" "photography-backend/internal/model/entity" ) // CreateCategoryRequest 创建分类请求 type CreateCategoryRequest struct { Name string `json:"name" binding:"required,min=1,max=100" validate:"required,min=1,max=100"` Description string `json:"description" binding:"omitempty,max=1000" validate:"omitempty,max=1000"` Slug string `json:"slug" binding:"omitempty,min=1,max=100" validate:"omitempty,min=1,max=100"` ParentID *uint `json:"parent_id" binding:"omitempty,min=1" validate:"omitempty,min=1"` Color string `json:"color" binding:"omitempty,len=7" validate:"omitempty,len=7"` CoverImage string `json:"cover_image" binding:"omitempty,url" validate:"omitempty,url"` SortOrder int `json:"sort_order" binding:"omitempty,min=0" validate:"omitempty,min=0"` } // UpdateCategoryRequest 更新分类请求 type UpdateCategoryRequest struct { Name *string `json:"name" binding:"omitempty,min=1,max=100" validate:"omitempty,min=1,max=100"` Description *string `json:"description" binding:"omitempty,max=1000" validate:"omitempty,max=1000"` Slug *string `json:"slug" binding:"omitempty,min=1,max=100" validate:"omitempty,min=1,max=100"` ParentID *uint `json:"parent_id" binding:"omitempty,min=0" validate:"omitempty,min=0"` Color *string `json:"color" binding:"omitempty,len=7" validate:"omitempty,len=7"` CoverImage *string `json:"cover_image" binding:"omitempty,url" validate:"omitempty,url"` SortOrder *int `json:"sort_order" binding:"omitempty,min=0" validate:"omitempty,min=0"` IsActive *bool `json:"is_active" binding:"omitempty"` } // CategoryResponse 分类响应 type CategoryResponse struct { ID uint `json:"id"` Name string `json:"name"` Description string `json:"description"` Slug string `json:"slug"` ParentID *uint `json:"parent_id"` Color string `json:"color"` CoverImage string `json:"cover_image"` Sort int `json:"sort"` IsActive bool `json:"is_active"` PhotoCount int64 `json:"photo_count"` AlbumCount int64 `json:"album_count"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // CategoryTreeResponse 分类树响应 type CategoryTreeResponse struct { ID uint `json:"id"` Name string `json:"name"` Description string `json:"description"` Slug string `json:"slug"` ParentID *uint `json:"parent_id"` Color string `json:"color"` CoverImage string `json:"cover_image"` Sort int `json:"sort"` IsActive bool `json:"is_active"` PhotoCount int64 `json:"photo_count"` AlbumCount int64 `json:"album_count"` Children []CategoryTreeResponse `json:"children"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // ListCategoriesOptions 分类列表查询选项 type ListCategoriesOptions struct { Page int `json:"page" form:"page" binding:"omitempty,min=1" validate:"omitempty,min=1"` Limit int `json:"limit" form:"limit" binding:"omitempty,min=1,max=100" validate:"omitempty,min=1,max=100"` Sort string `json:"sort" form:"sort" binding:"omitempty,oneof=id name sort created_at updated_at" validate:"omitempty,oneof=id name sort created_at updated_at"` Order string `json:"order" form:"order" binding:"omitempty,oneof=asc desc" validate:"omitempty,oneof=asc desc"` ParentID *uint `json:"parent_id" form:"parent_id" binding:"omitempty,min=0" validate:"omitempty,min=0"` IsActive *bool `json:"is_active" form:"is_active" binding:"omitempty"` Search string `json:"search" form:"search" binding:"omitempty,max=100" validate:"omitempty,max=100"` WithCount bool `json:"with_count" form:"with_count" binding:"omitempty"` } // CategoryListResponse 分类列表响应 type CategoryListResponse struct { Categories []CategoryResponse `json:"categories"` Total int64 `json:"total"` Page int `json:"page"` Limit int `json:"limit"` } // ReorderCategoriesRequest 重新排序分类请求 type ReorderCategoriesRequest struct { ParentID *uint `json:"parent_id" binding:"omitempty,min=0" validate:"omitempty,min=0"` CategoryIDs []uint `json:"category_ids" binding:"required,min=1" validate:"required,min=1"` } // CategoryStatsResponse 分类统计响应 type CategoryStatsResponse struct { Total int64 `json:"total"` Active int64 `json:"active"` TopLevel int64 `json:"top_level"` PhotoCounts map[string]int64 `json:"photo_counts"` Popular []CategoryResponse `json:"popular"` } // ConvertToCategoryResponse 将分类实体转换为响应DTO func ConvertToCategoryResponse(category *entity.Category) *CategoryResponse { if category == nil { return nil } return &CategoryResponse{ ID: category.ID, Name: category.Name, Description: category.Description, ParentID: category.ParentID, Color: category.Color, CoverImage: category.CoverImage, Sort: category.Sort, IsActive: category.IsActive, PhotoCount: category.PhotoCount, CreatedAt: category.CreatedAt, UpdatedAt: category.UpdatedAt, } } // ConvertToCategoryTreeResponse 将分类树转换为响应DTO func ConvertToCategoryTreeResponse(tree []entity.CategoryTree) []CategoryTreeResponse { result := make([]CategoryTreeResponse, len(tree)) for i, category := range tree { result[i] = CategoryTreeResponse{ ID: category.ID, Name: category.Name, Description: category.Description, ParentID: category.ParentID, Color: category.Color, CoverImage: category.CoverImage, Sort: category.Sort, IsActive: category.IsActive, PhotoCount: category.PhotoCount, Children: ConvertToCategoryTreeResponse(category.Children), CreatedAt: category.CreatedAt, UpdatedAt: category.UpdatedAt, } } return result }