Files
urldb/handlers/tag_handler.go
2025-08-09 17:26:52 +08:00

287 lines
7.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"net/http"
"strconv"
"github.com/ctwj/urldb/db/converter"
"github.com/ctwj/urldb/db/dto"
"github.com/ctwj/urldb/db/entity"
"github.com/ctwj/urldb/utils"
"github.com/gin-gonic/gin"
)
// GetTags 获取标签列表
func GetTags(c *gin.Context) {
// 获取分页参数
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.SearchOrderByResourceCount(search, page, pageSize)
} else {
// 分页查询(按资源数量排序)
tags, total, err = repoManager.TagRepository.FindWithPaginationOrderByResourceCount(page, pageSize)
}
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
}
// 获取每个标签的资源数量
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 创建标签
func CreateTag(c *gin.Context) {
var req dto.CreateTagRequest
if err := c.ShouldBindJSON(&req); err != nil {
ErrorResponse(c, err.Error(), http.StatusBadRequest)
return
}
// 首先检查是否存在已删除的同名标签
deletedTag, err := repoManager.TagRepository.FindByNameIncludingDeleted(req.Name)
if err == nil && deletedTag.DeletedAt.Valid {
// 如果存在已删除的同名标签,则恢复它
err = repoManager.TagRepository.RestoreDeletedTag(deletedTag.ID)
if err != nil {
ErrorResponse(c, "恢复已删除标签失败: "+err.Error(), http.StatusInternalServerError)
return
}
// 重新获取恢复后的标签
restoredTag, err := repoManager.TagRepository.FindByID(deletedTag.ID)
if err != nil {
ErrorResponse(c, "获取恢复的标签失败: "+err.Error(), http.StatusInternalServerError)
return
}
// 更新标签信息
restoredTag.Description = req.Description
restoredTag.CategoryID = req.CategoryID
err = repoManager.TagRepository.UpdateWithNulls(restoredTag)
if err != nil {
ErrorResponse(c, "更新恢复的标签失败: "+err.Error(), http.StatusInternalServerError)
return
}
SuccessResponse(c, gin.H{
"message": "标签恢复成功",
"tag": converter.ToTagResponse(restoredTag, 0),
})
return
}
// 如果不存在已删除的同名标签,则创建新标签
tag := &entity.Tag{
Name: req.Name,
Description: req.Description,
CategoryID: req.CategoryID,
}
err = repoManager.TagRepository.Create(tag)
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
}
SuccessResponse(c, gin.H{
"message": "标签创建成功",
"tag": converter.ToTagResponse(tag, 0),
})
}
// GetTagByID 根据ID获取标签详情
func GetTagByID(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
ErrorResponse(c, "无效的ID", http.StatusBadRequest)
return
}
tag, err := repoManager.TagRepository.FindByID(uint(id))
if err != nil {
ErrorResponse(c, "标签不存在", http.StatusNotFound)
return
}
// 获取资源数量
resourceCount, _ := repoManager.TagRepository.GetResourceCount(tag.ID)
response := converter.ToTagResponse(tag, resourceCount)
SuccessResponse(c, response)
}
// UpdateTag 更新标签
func UpdateTag(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
ErrorResponse(c, "无效的ID", http.StatusBadRequest)
return
}
var req dto.UpdateTagRequest
if err := c.ShouldBindJSON(&req); err != nil {
ErrorResponse(c, err.Error(), http.StatusBadRequest)
return
}
tag, err := repoManager.TagRepository.FindByID(uint(id))
if err != nil {
ErrorResponse(c, "标签不存在", http.StatusNotFound)
return
}
// 添加调试信息
utils.Debug("更新标签 - ID: %d, 请求CategoryID: %v, 当前CategoryID: %v", id, req.CategoryID, tag.CategoryID)
if req.Name != "" {
tag.Name = req.Name
}
if req.Description != "" {
tag.Description = req.Description
}
// 处理CategoryID包括设置为null的情况
tag.CategoryID = req.CategoryID
// 添加调试信息
utils.Debug("更新后CategoryID: %v", tag.CategoryID)
// 使用专门的更新方法确保能更新null值
err = repoManager.TagRepository.UpdateWithNulls(tag)
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
}
SuccessResponse(c, gin.H{"message": "标签更新成功"})
}
// DeleteTag 删除标签
func DeleteTag(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
ErrorResponse(c, "无效的ID", http.StatusBadRequest)
return
}
err = repoManager.TagRepository.Delete(uint(id))
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
}
SuccessResponse(c, gin.H{"message": "标签删除成功"})
}
// GetTagByID 根据ID获取标签详情使用全局repoManager
func GetTagByIDGlobal(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
ErrorResponse(c, "无效的ID", http.StatusBadRequest)
return
}
tag, err := repoManager.TagRepository.FindByID(uint(id))
if err != nil {
ErrorResponse(c, "标签不存在", http.StatusNotFound)
return
}
// 获取资源数量
resourceCount, _ := repoManager.TagRepository.GetResourceCount(tag.ID)
response := converter.ToTagResponse(tag, resourceCount)
SuccessResponse(c, response)
}
// GetTags 获取标签列表使用全局repoManager
func GetTagsGlobal(c *gin.Context) {
tags, err := repoManager.TagRepository.FindAll()
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
}
// 获取每个标签的资源数量
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)
}
// GetTagsByCategory 根据分类ID获取标签列表
func GetTagsByCategory(c *gin.Context) {
categoryIDStr := c.Param("categoryId")
categoryID, err := strconv.ParseUint(categoryIDStr, 10, 32)
if err != nil {
ErrorResponse(c, "无效的分类ID", http.StatusBadRequest)
return
}
// 获取分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
tags, total, err := repoManager.TagRepository.FindByCategoryIDPaginated(uint(categoryID), page, pageSize)
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
}
// 获取每个标签的资源数量
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,
})
}