package dto import ( "time" "photography-backend/internal/model/entity" ) // CreateAlbumRequest 创建相册请求 type CreateAlbumRequest struct { Title string `json:"title" binding:"required,min=1,max=200" validate:"required,min=1,max=200"` Description string `json:"description" binding:"omitempty,max=1000" validate:"omitempty,max=1000"` Slug string `json:"slug" binding:"omitempty,min=1,max=255" validate:"omitempty,min=1,max=255"` CategoryID *uint `json:"category_id" binding:"omitempty,min=1" validate:"omitempty,min=1"` IsPublic bool `json:"is_public" binding:"omitempty"` IsFeatured bool `json:"is_featured" binding:"omitempty"` Password string `json:"password" binding:"omitempty,min=6" validate:"omitempty,min=6"` } // UpdateAlbumRequest 更新相册请求 type UpdateAlbumRequest struct { Title *string `json:"title" binding:"omitempty,min=1,max=200" validate:"omitempty,min=1,max=200"` Description *string `json:"description" binding:"omitempty,max=1000" validate:"omitempty,max=1000"` Slug *string `json:"slug" binding:"omitempty,min=1,max=255" validate:"omitempty,min=1,max=255"` CoverPhotoID *uint `json:"cover_photo_id" binding:"omitempty,min=0" validate:"omitempty,min=0"` CategoryID *uint `json:"category_id" binding:"omitempty,min=0" validate:"omitempty,min=0"` IsPublic *bool `json:"is_public" binding:"omitempty"` IsFeatured *bool `json:"is_featured" binding:"omitempty"` Password *string `json:"password" binding:"omitempty,min=0" validate:"omitempty,min=0"` // 空字符串表示移除密码 SortOrder *int `json:"sort_order" binding:"omitempty,min=0" validate:"omitempty,min=0"` } // AlbumResponse 相册响应 type AlbumResponse struct { ID uint `json:"id"` Title string `json:"title"` Description string `json:"description"` Slug string `json:"slug"` CoverPhotoID *uint `json:"cover_photo_id"` UserID uint `json:"user_id"` CategoryID *uint `json:"category_id"` IsPublic bool `json:"is_public"` IsFeatured bool `json:"is_featured"` HasPassword bool `json:"has_password"` ViewCount int `json:"view_count"` LikeCount int `json:"like_count"` PhotoCount int `json:"photo_count"` SortOrder int `json:"sort_order"` User *UserResponse `json:"user,omitempty"` Category *CategoryResponse `json:"category,omitempty"` CoverPhoto *PhotoListItem `json:"cover_photo,omitempty"` RecentPhotos []PhotoListItem `json:"recent_photos,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // AlbumListItem 相册列表项(简化版) type AlbumListItem struct { ID uint `json:"id"` Title string `json:"title"` Slug string `json:"slug"` IsPublic bool `json:"is_public"` IsFeatured bool `json:"is_featured"` HasPassword bool `json:"has_password"` ViewCount int `json:"view_count"` LikeCount int `json:"like_count"` PhotoCount int `json:"photo_count"` CoverPhoto *PhotoListItem `json:"cover_photo,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // ListAlbumsOptions 相册列表查询选项 type ListAlbumsOptions 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 title created_at updated_at view_count like_count photo_count" validate:"omitempty,oneof=id title created_at updated_at view_count like_count photo_count"` Order string `json:"order" form:"order" binding:"omitempty,oneof=asc desc" validate:"omitempty,oneof=asc desc"` UserID *uint `json:"user_id" form:"user_id" binding:"omitempty,min=1" validate:"omitempty,min=1"` CategoryID *uint `json:"category_id" form:"category_id" binding:"omitempty,min=1" validate:"omitempty,min=1"` IsPublic *bool `json:"is_public" form:"is_public" binding:"omitempty"` IsFeatured *bool `json:"is_featured" form:"is_featured" binding:"omitempty"` Search string `json:"search" form:"search" binding:"omitempty,max=100" validate:"omitempty,max=100"` } // AlbumListResponse 相册列表响应 type AlbumListResponse struct { Albums []AlbumListItem `json:"albums"` Total int64 `json:"total"` Page int `json:"page"` Limit int `json:"limit"` } // AddPhotosToAlbumRequest 向相册添加照片请求 type AddPhotosToAlbumRequest struct { PhotoIDs []uint `json:"photo_ids" binding:"required,min=1" validate:"required,min=1"` } // RemovePhotosFromAlbumRequest 从相册移除照片请求 type RemovePhotosFromAlbumRequest struct { PhotoIDs []uint `json:"photo_ids" binding:"required,min=1" validate:"required,min=1"` } // AlbumPasswordRequest 相册密码验证请求 type AlbumPasswordRequest struct { Password string `json:"password" binding:"required" validate:"required"` } // AlbumStatsResponse 相册统计响应 type AlbumStatsResponse struct { Total int64 `json:"total"` Published int64 `json:"published"` Private int64 `json:"private"` Featured int64 `json:"featured"` WithPassword int64 `json:"with_password"` TotalViews int64 `json:"total_views"` TotalLikes int64 `json:"total_likes"` TotalPhotos int64 `json:"total_photos"` CategoryCounts map[string]int64 `json:"category_counts"` Recent []AlbumListItem `json:"recent"` Popular []AlbumListItem `json:"popular"` } // ConvertToAlbumResponse 将相册实体转换为响应DTO func ConvertToAlbumResponse(album *entity.Album) *AlbumResponse { if album == nil { return nil } response := &AlbumResponse{ ID: album.ID, Title: album.Title, Description: album.Description, Slug: album.Slug, CoverPhotoID: album.CoverPhotoID, UserID: album.UserID, CategoryID: album.CategoryID, IsPublic: album.IsPublic, IsFeatured: album.IsFeatured, HasPassword: album.HasPassword(), ViewCount: album.ViewCount, LikeCount: album.LikeCount, PhotoCount: album.PhotoCount, SortOrder: album.SortOrder, CreatedAt: album.CreatedAt, UpdatedAt: album.UpdatedAt, } // 转换关联对象 if album.User.ID != 0 { response.User = ConvertToUserResponse(&album.User) } if album.Category != nil { response.Category = ConvertToCategoryResponse(album.Category) } if album.CoverPhoto != nil { coverPhoto := ConvertToPhotoListItem(album.CoverPhoto) response.CoverPhoto = &coverPhoto } // 转换最近照片 if len(album.Photos) > 0 { recentPhotos := make([]PhotoListItem, 0, len(album.Photos)) for _, photo := range album.Photos { recentPhotos = append(recentPhotos, ConvertToPhotoListItem(&photo)) } response.RecentPhotos = recentPhotos } return response } // ConvertToAlbumListItem 将相册实体转换为列表项DTO func ConvertToAlbumListItem(album *entity.Album) AlbumListItem { item := AlbumListItem{ ID: album.ID, Title: album.Title, Slug: album.Slug, IsPublic: album.IsPublic, IsFeatured: album.IsFeatured, HasPassword: album.HasPassword(), ViewCount: album.ViewCount, LikeCount: album.LikeCount, PhotoCount: album.PhotoCount, CreatedAt: album.CreatedAt, UpdatedAt: album.UpdatedAt, } // 转换封面照片 if album.CoverPhoto != nil { coverPhoto := ConvertToPhotoListItem(album.CoverPhoto) item.CoverPhoto = &coverPhoto } return item }