fix
Some checks failed
部署后端服务 / 🧪 测试后端 (push) Failing after 5m8s
部署后端服务 / 🚀 构建并部署 (push) Has been skipped
部署后端服务 / 🔄 回滚部署 (push) Has been skipped

This commit is contained in:
xujiang
2025-07-10 18:09:11 +08:00
parent 35004f224e
commit 010fe2a8c7
96 changed files with 23709 additions and 19 deletions

View File

@ -0,0 +1,196 @@
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
}