diff --git a/db/converter/converter.go b/db/converter/converter.go index b0a9050..a7d8471 100644 --- a/db/converter/converter.go +++ b/db/converter/converter.go @@ -32,9 +32,10 @@ func ToResourceResponse(resource *entity.Resource) dto.ResourceResponse { response.Tags = make([]dto.TagResponse, len(resource.Tags)) for i, tag := range resource.Tags { response.Tags[i] = dto.TagResponse{ - ID: tag.ID, - Name: tag.Name, - Description: tag.Description, + ID: tag.ID, + Name: tag.Name, + Description: tag.Description, + ResourceCount: 0, // 在资源上下文中,标签的资源数量不相关 } } @@ -71,19 +72,21 @@ func ToCategoryResponseList(categories []entity.Category, resourceCounts map[uin } // ToTagResponse 将Tag实体转换为TagResponse -func ToTagResponse(tag *entity.Tag) dto.TagResponse { +func ToTagResponse(tag *entity.Tag, resourceCount int64) dto.TagResponse { return dto.TagResponse{ - ID: tag.ID, - Name: tag.Name, - Description: tag.Description, + ID: tag.ID, + Name: tag.Name, + Description: tag.Description, + ResourceCount: resourceCount, } } // ToTagResponseList 将Tag实体列表转换为TagResponse列表 -func ToTagResponseList(tags []entity.Tag) []dto.TagResponse { +func ToTagResponseList(tags []entity.Tag, resourceCounts map[uint]int64) []dto.TagResponse { responses := make([]dto.TagResponse, len(tags)) for i, tag := range tags { - responses[i] = ToTagResponse(&tag) + count := resourceCounts[tag.ID] + responses[i] = ToTagResponse(&tag, count) } return responses } diff --git a/db/dto/response.go b/db/dto/response.go index 0e483bc..136512c 100644 --- a/db/dto/response.go +++ b/db/dto/response.go @@ -39,9 +39,10 @@ type CategoryResponse struct { // TagResponse 标签响应 type TagResponse struct { - ID uint `json:"id"` - Name string `json:"name"` - Description string `json:"description"` + ID uint `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + ResourceCount int64 `json:"resource_count"` } // PanResponse 平台响应 diff --git a/db/repo/category_repository.go b/db/repo/category_repository.go index 22d50e0..075e2d9 100644 --- a/db/repo/category_repository.go +++ b/db/repo/category_repository.go @@ -12,6 +12,8 @@ type CategoryRepository interface { FindByName(name string) (*entity.Category, error) FindWithResources() ([]entity.Category, error) GetResourceCount(categoryID uint) (int64, error) + FindWithPagination(page, pageSize int) ([]entity.Category, int64, error) + Search(query string, page, pageSize int) ([]entity.Category, int64, error) } // CategoryRepositoryImpl Category的Repository实现 @@ -49,3 +51,49 @@ func (r *CategoryRepositoryImpl) GetResourceCount(categoryID uint) (int64, error err := r.db.Model(&entity.Resource{}).Where("category_id = ?", categoryID).Count(&count).Error return count, err } + +// FindWithPagination 分页查询分类 +func (r *CategoryRepositoryImpl) FindWithPagination(page, pageSize int) ([]entity.Category, int64, error) { + var categories []entity.Category + var total int64 + + // 获取总数 + err := r.db.Model(&entity.Category{}).Count(&total).Error + if err != nil { + return nil, 0, err + } + + // 分页查询 + offset := (page - 1) * pageSize + err = r.db.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&categories).Error + if err != nil { + return nil, 0, err + } + + return categories, total, nil +} + +// Search 搜索分类 +func (r *CategoryRepositoryImpl) Search(query string, page, pageSize int) ([]entity.Category, int64, error) { + var categories []entity.Category + var total int64 + + // 构建搜索条件 + searchQuery := "%" + query + "%" + + // 获取总数 + err := r.db.Model(&entity.Category{}).Where("name ILIKE ? OR description ILIKE ?", searchQuery, searchQuery).Count(&total).Error + if err != nil { + return nil, 0, err + } + + // 分页搜索 + offset := (page - 1) * pageSize + err = r.db.Where("name ILIKE ? OR description ILIKE ?", searchQuery, searchQuery). + Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&categories).Error + if err != nil { + return nil, 0, err + } + + return categories, total, nil +} diff --git a/db/repo/tag_repository.go b/db/repo/tag_repository.go index 818fed8..d9c3745 100644 --- a/db/repo/tag_repository.go +++ b/db/repo/tag_repository.go @@ -13,6 +13,8 @@ type TagRepository interface { FindWithResources() ([]entity.Tag, error) GetResourceCount(tagID uint) (int64, error) FindByResourceID(resourceID uint) ([]entity.Tag, error) + FindWithPagination(page, pageSize int) ([]entity.Tag, int64, error) + Search(query string, page, pageSize int) ([]entity.Tag, int64, error) } // TagRepositoryImpl Tag的Repository实现 @@ -58,3 +60,49 @@ func (r *TagRepositoryImpl) FindByResourceID(resourceID uint) ([]entity.Tag, err Where("resource_tags.resource_id = ?", resourceID).Find(&tags).Error return tags, err } + +// FindWithPagination 分页查询标签 +func (r *TagRepositoryImpl) FindWithPagination(page, pageSize int) ([]entity.Tag, int64, error) { + var tags []entity.Tag + var total int64 + + // 获取总数 + err := r.db.Model(&entity.Tag{}).Count(&total).Error + if err != nil { + return nil, 0, err + } + + // 分页查询 + offset := (page - 1) * pageSize + err = r.db.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&tags).Error + if err != nil { + return nil, 0, err + } + + return tags, total, nil +} + +// Search 搜索标签 +func (r *TagRepositoryImpl) Search(query string, page, pageSize int) ([]entity.Tag, int64, error) { + var tags []entity.Tag + var total int64 + + // 构建搜索条件 + searchQuery := "%" + query + "%" + + // 获取总数 + err := r.db.Model(&entity.Tag{}).Where("name ILIKE ? OR description ILIKE ?", searchQuery, searchQuery).Count(&total).Error + if err != nil { + return nil, 0, err + } + + // 分页搜索 + offset := (page - 1) * pageSize + err = r.db.Where("name ILIKE ? OR description ILIKE ?", searchQuery, searchQuery). + Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&tags).Error + if err != nil { + return nil, 0, err + } + + return tags, total, nil +} diff --git a/handlers/category_handler.go b/handlers/category_handler.go index 52a9947..f22c53b 100644 --- a/handlers/category_handler.go +++ b/handlers/category_handler.go @@ -13,7 +13,23 @@ import ( // GetCategories 获取分类列表 func GetCategories(c *gin.Context) { - categories, err := repoManager.CategoryRepository.FindAll() + // 获取分页参数 + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) + search := c.Query("search") + + var categories []entity.Category + var total int64 + var err error + + if search != "" { + // 搜索分类 + categories, total, err = repoManager.CategoryRepository.Search(search, page, pageSize) + } else { + // 分页查询 + categories, total, err = repoManager.CategoryRepository.FindWithPagination(page, pageSize) + } + if err != nil { ErrorResponse(c, err.Error(), http.StatusInternalServerError) return @@ -30,7 +46,14 @@ func GetCategories(c *gin.Context) { } responses := converter.ToCategoryResponseList(categories, resourceCounts) - SuccessResponse(c, responses) + + // 返回分页格式的响应 + SuccessResponse(c, gin.H{ + "items": responses, + "total": total, + "page": page, + "page_size": pageSize, + }) } // CreateCategory 创建分类 diff --git a/handlers/tag_handler.go b/handlers/tag_handler.go index 21ca52c..f9b6c6e 100644 --- a/handlers/tag_handler.go +++ b/handlers/tag_handler.go @@ -13,14 +13,47 @@ import ( // GetTags 获取标签列表 func GetTags(c *gin.Context) { - tags, err := repoManager.TagRepository.FindAll() + // 获取分页参数 + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) + search := c.Query("search") + + var tags []entity.Tag + var total int64 + var err error + + if search != "" { + // 搜索标签 + tags, total, err = repoManager.TagRepository.Search(search, page, pageSize) + } else { + // 分页查询 + tags, total, err = repoManager.TagRepository.FindWithPagination(page, pageSize) + } + if err != nil { ErrorResponse(c, err.Error(), http.StatusInternalServerError) return } - responses := converter.ToTagResponseList(tags) - SuccessResponse(c, responses) + // 获取每个标签的资源数量 + resourceCounts := make(map[uint]int64) + for _, tag := range tags { + count, err := repoManager.TagRepository.GetResourceCount(tag.ID) + if err != nil { + continue + } + resourceCounts[tag.ID] = count + } + + responses := converter.ToTagResponseList(tags, resourceCounts) + + // 返回分页格式的响应 + SuccessResponse(c, gin.H{ + "items": responses, + "total": total, + "page": page, + "page_size": pageSize, + }) } // CreateTag 创建标签 @@ -44,7 +77,7 @@ func CreateTag(c *gin.Context) { SuccessResponse(c, gin.H{ "message": "标签创建成功", - "tag": converter.ToTagResponse(tag), + "tag": converter.ToTagResponse(tag, 0), }) } @@ -63,7 +96,9 @@ func GetTagByID(c *gin.Context) { return } - response := converter.ToTagResponse(tag) + // 获取资源数量 + resourceCount, _ := repoManager.TagRepository.GetResourceCount(tag.ID) + response := converter.ToTagResponse(tag, resourceCount) SuccessResponse(c, response) } @@ -137,7 +172,9 @@ func GetTagByIDGlobal(c *gin.Context) { return } - response := converter.ToTagResponse(tag) + // 获取资源数量 + resourceCount, _ := repoManager.TagRepository.GetResourceCount(tag.ID) + response := converter.ToTagResponse(tag, resourceCount) SuccessResponse(c, response) } @@ -149,6 +186,16 @@ func GetTagsGlobal(c *gin.Context) { return } - responses := converter.ToTagResponseList(tags) + // 获取每个标签的资源数量 + resourceCounts := make(map[uint]int64) + for _, tag := range tags { + count, err := repoManager.TagRepository.GetResourceCount(tag.ID) + if err != nil { + continue + } + resourceCounts[tag.ID] = count + } + + responses := converter.ToTagResponseList(tags, resourceCounts) SuccessResponse(c, responses) } diff --git a/web/pages/admin.vue b/web/pages/admin.vue index fa0416a..4955862 100644 --- a/web/pages/admin.vue +++ b/web/pages/admin.vue @@ -125,7 +125,7 @@ - -