From 7032235923e9a8c7ceecd6ddfadd82480738ef88 Mon Sep 17 00:00:00 2001 From: ctwj <908504609@qq.com> Date: Sat, 9 Aug 2025 17:26:52 +0800 Subject: [PATCH] =?UTF-8?q?update:=20ui=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/repo/tag_repository.go | 70 +++ handlers/tag_handler.go | 8 +- web/components.d.ts | 1 + web/components/Admin/ManualBatchTransfer.vue | 410 ++++++++++++++ web/components/Admin/TransferredList.vue | 285 ++++++++++ web/components/Admin/UntransferredList.vue | 541 +++++++++++++++++++ web/pages/admin/data-transfer.vue | 46 +- 7 files changed, 1344 insertions(+), 17 deletions(-) create mode 100644 web/components/Admin/ManualBatchTransfer.vue create mode 100644 web/components/Admin/TransferredList.vue create mode 100644 web/components/Admin/UntransferredList.vue diff --git a/db/repo/tag_repository.go b/db/repo/tag_repository.go index a2e876d..279616e 100644 --- a/db/repo/tag_repository.go +++ b/db/repo/tag_repository.go @@ -17,7 +17,9 @@ type TagRepository interface { GetResourceCount(tagID uint) (int64, error) FindByResourceID(resourceID uint) ([]entity.Tag, error) FindWithPagination(page, pageSize int) ([]entity.Tag, int64, error) + FindWithPaginationOrderByResourceCount(page, pageSize int) ([]entity.Tag, int64, error) Search(query string, page, pageSize int) ([]entity.Tag, int64, error) + SearchOrderByResourceCount(query string, page, pageSize int) ([]entity.Tag, int64, error) UpdateWithNulls(tag *entity.Tag) error GetByID(id uint) (*entity.Tag, error) RestoreDeletedTag(id uint) error @@ -172,3 +174,71 @@ func (r *TagRepositoryImpl) GetByID(id uint) (*entity.Tag, error) { func (r *TagRepositoryImpl) RestoreDeletedTag(id uint) error { return r.db.Unscoped().Model(&entity.Tag{}).Where("id = ?", id).Update("deleted_at", nil).Error } + +// FindWithPaginationOrderByResourceCount 按资源数量排序的分页查询 +func (r *TagRepositoryImpl) FindWithPaginationOrderByResourceCount(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.Preload("Category"). + Select("tags.*, COALESCE(resource_counts.count, 0) as resource_count"). + Joins(`LEFT JOIN ( + SELECT rt.tag_id, COUNT(rt.resource_id) as count + FROM resource_tags rt + INNER JOIN resources r ON rt.resource_id = r.id AND r.deleted_at IS NULL + GROUP BY rt.tag_id + ) as resource_counts ON tags.id = resource_counts.tag_id`). + Order("COALESCE(resource_counts.count, 0) DESC, tags.created_at DESC"). + Offset(offset).Limit(pageSize). + Find(&tags).Error + + if err != nil { + return nil, 0, err + } + + return tags, total, nil +} + +// SearchOrderByResourceCount 按资源数量排序的搜索 +func (r *TagRepositoryImpl) SearchOrderByResourceCount(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.Preload("Category"). + Select("tags.*, COALESCE(resource_counts.count, 0) as resource_count"). + Joins(`LEFT JOIN ( + SELECT rt.tag_id, COUNT(rt.resource_id) as count + FROM resource_tags rt + INNER JOIN resources r ON rt.resource_id = r.id AND r.deleted_at IS NULL + GROUP BY rt.tag_id + ) as resource_counts ON tags.id = resource_counts.tag_id`). + Where("tags.name ILIKE ? OR tags.description ILIKE ?", searchQuery, searchQuery). + Order("COALESCE(resource_counts.count, 0) DESC, tags.created_at DESC"). + Offset(offset).Limit(pageSize). + Find(&tags).Error + + if err != nil { + return nil, 0, err + } + + return tags, total, nil +} diff --git a/handlers/tag_handler.go b/handlers/tag_handler.go index 1d10fde..b4bf4c1 100644 --- a/handlers/tag_handler.go +++ b/handlers/tag_handler.go @@ -24,11 +24,11 @@ func GetTags(c *gin.Context) { var err error if search != "" { - // 搜索标签 - tags, total, err = repoManager.TagRepository.Search(search, page, pageSize) + // 搜索标签(按资源数量排序) + tags, total, err = repoManager.TagRepository.SearchOrderByResourceCount(search, page, pageSize) } else { - // 分页查询 - tags, total, err = repoManager.TagRepository.FindWithPagination(page, pageSize) + // 分页查询(按资源数量排序) + tags, total, err = repoManager.TagRepository.FindWithPaginationOrderByResourceCount(page, pageSize) } if err != nil { diff --git a/web/components.d.ts b/web/components.d.ts index 7616934..ae5b293 100644 --- a/web/components.d.ts +++ b/web/components.d.ts @@ -11,6 +11,7 @@ declare module 'vue' { NA: typeof import('naive-ui')['NA'] NAlert: typeof import('naive-ui')['NAlert'] NAvatar: typeof import('naive-ui')['NAvatar'] + NBadge: typeof import('naive-ui')['NBadge'] NButton: typeof import('naive-ui')['NButton'] NButtonGroup: typeof import('naive-ui')['NButtonGroup'] NCard: typeof import('naive-ui')['NCard'] diff --git a/web/components/Admin/ManualBatchTransfer.vue b/web/components/Admin/ManualBatchTransfer.vue new file mode 100644 index 0000000..c2052dc --- /dev/null +++ b/web/components/Admin/ManualBatchTransfer.vue @@ -0,0 +1,410 @@ + + + \ No newline at end of file diff --git a/web/components/Admin/TransferredList.vue b/web/components/Admin/TransferredList.vue new file mode 100644 index 0000000..1aa9b59 --- /dev/null +++ b/web/components/Admin/TransferredList.vue @@ -0,0 +1,285 @@ + + + \ No newline at end of file diff --git a/web/components/Admin/UntransferredList.vue b/web/components/Admin/UntransferredList.vue new file mode 100644 index 0000000..0458b15 --- /dev/null +++ b/web/components/Admin/UntransferredList.vue @@ -0,0 +1,541 @@ + + + + + \ No newline at end of file diff --git a/web/pages/admin/data-transfer.vue b/web/pages/admin/data-transfer.vue index 60355e1..8f38b52 100644 --- a/web/pages/admin/data-transfer.vue +++ b/web/pages/admin/data-transfer.vue @@ -1,26 +1,46 @@ \ No newline at end of file