From 3820232241695aeab36c21b6bc9938b1ba8deb45 Mon Sep 17 00:00:00 2001 From: IanShaw027 <131567472+IanShaw027@users.noreply.github.com> Date: Fri, 9 Jan 2026 18:58:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(admin):=20=E4=BF=AE=E5=A4=8D=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E6=89=B9=E9=87=8F=E6=93=8D=E4=BD=9C=E5=92=8C=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E5=8A=9F=E8=83=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 恢复账号管理批量操作栏缺失的功能按钮 - 添加"本页全选"按钮支持批量选择当前页所有账号 - 添加"清除已选"按钮快速清空已选账号列表 - 在重构拆分组件时遗漏,现已恢复 2. 修复分组管理搜索功能仅搜索当前页的问题 - 前端:移除本地过滤逻辑,改用后端搜索 - 后端:添加 search 参数支持,搜索名称和描述字段 - 支持不区分大小写的模糊匹配 - 统一所有管理页面的搜索体验 --- .../internal/handler/admin/group_handler.go | 3 ++- backend/internal/repository/group_repo.go | 10 ++++++-- backend/internal/service/admin_service.go | 6 ++--- .../service/admin_service_delete_test.go | 2 +- .../service/admin_service_group_test.go | 2 +- .../service/gemini_multiplatform_test.go | 2 +- backend/internal/service/group_service.go | 2 +- frontend/src/api/admin/groups.ts | 3 ++- .../admin/account/AccountBulkActionsBar.vue | 23 ++++++++++++++--- frontend/src/views/admin/GroupsView.vue | 25 ++++++++++--------- 10 files changed, 52 insertions(+), 26 deletions(-) diff --git a/backend/internal/handler/admin/group_handler.go b/backend/internal/handler/admin/group_handler.go index acb9462c..1d9f7e24 100644 --- a/backend/internal/handler/admin/group_handler.go +++ b/backend/internal/handler/admin/group_handler.go @@ -67,6 +67,7 @@ func (h *GroupHandler) List(c *gin.Context) { page, pageSize := response.ParsePagination(c) platform := c.Query("platform") status := c.Query("status") + search := c.Query("search") isExclusiveStr := c.Query("is_exclusive") var isExclusive *bool @@ -75,7 +76,7 @@ func (h *GroupHandler) List(c *gin.Context) { isExclusive = &val } - groups, total, err := h.adminService.ListGroups(c.Request.Context(), page, pageSize, platform, status, isExclusive) + groups, total, err := h.adminService.ListGroups(c.Request.Context(), page, pageSize, platform, status, search, isExclusive) if err != nil { response.ErrorFrom(c, err) return diff --git a/backend/internal/repository/group_repo.go b/backend/internal/repository/group_repo.go index 1fb4ae90..a54f3116 100644 --- a/backend/internal/repository/group_repo.go +++ b/backend/internal/repository/group_repo.go @@ -112,10 +112,10 @@ func (r *groupRepository) Delete(ctx context.Context, id int64) error { } func (r *groupRepository) List(ctx context.Context, params pagination.PaginationParams) ([]service.Group, *pagination.PaginationResult, error) { - return r.ListWithFilters(ctx, params, "", "", nil) + return r.ListWithFilters(ctx, params, "", "", "", nil) } -func (r *groupRepository) ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status string, isExclusive *bool) ([]service.Group, *pagination.PaginationResult, error) { +func (r *groupRepository) ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status, search string, isExclusive *bool) ([]service.Group, *pagination.PaginationResult, error) { q := r.client.Group.Query() if platform != "" { @@ -124,6 +124,12 @@ func (r *groupRepository) ListWithFilters(ctx context.Context, params pagination if status != "" { q = q.Where(group.StatusEQ(status)) } + if search != "" { + q = q.Where(group.Or( + group.NameContainsFold(search), + group.DescriptionContainsFold(search), + )) + } if isExclusive != nil { q = q.Where(group.IsExclusiveEQ(*isExclusive)) } diff --git a/backend/internal/service/admin_service.go b/backend/internal/service/admin_service.go index e29bbdb4..cd427368 100644 --- a/backend/internal/service/admin_service.go +++ b/backend/internal/service/admin_service.go @@ -24,7 +24,7 @@ type AdminService interface { GetUserUsageStats(ctx context.Context, userID int64, period string) (any, error) // Group management - ListGroups(ctx context.Context, page, pageSize int, platform, status string, isExclusive *bool) ([]Group, int64, error) + ListGroups(ctx context.Context, page, pageSize int, platform, status, search string, isExclusive *bool) ([]Group, int64, error) GetAllGroups(ctx context.Context) ([]Group, error) GetAllGroupsByPlatform(ctx context.Context, platform string) ([]Group, error) GetGroup(ctx context.Context, id int64) (*Group, error) @@ -478,9 +478,9 @@ func (s *adminServiceImpl) GetUserUsageStats(ctx context.Context, userID int64, } // Group management implementations -func (s *adminServiceImpl) ListGroups(ctx context.Context, page, pageSize int, platform, status string, isExclusive *bool) ([]Group, int64, error) { +func (s *adminServiceImpl) ListGroups(ctx context.Context, page, pageSize int, platform, status, search string, isExclusive *bool) ([]Group, int64, error) { params := pagination.PaginationParams{Page: page, PageSize: pageSize} - groups, result, err := s.groupRepo.ListWithFilters(ctx, params, platform, status, isExclusive) + groups, result, err := s.groupRepo.ListWithFilters(ctx, params, platform, status, search, isExclusive) if err != nil { return nil, 0, err } diff --git a/backend/internal/service/admin_service_delete_test.go b/backend/internal/service/admin_service_delete_test.go index c1d2e4c9..351f64e8 100644 --- a/backend/internal/service/admin_service_delete_test.go +++ b/backend/internal/service/admin_service_delete_test.go @@ -124,7 +124,7 @@ func (s *groupRepoStub) List(ctx context.Context, params pagination.PaginationPa panic("unexpected List call") } -func (s *groupRepoStub) ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status string, isExclusive *bool) ([]Group, *pagination.PaginationResult, error) { +func (s *groupRepoStub) ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status, search string, isExclusive *bool) ([]Group, *pagination.PaginationResult, error) { panic("unexpected ListWithFilters call") } diff --git a/backend/internal/service/admin_service_group_test.go b/backend/internal/service/admin_service_group_test.go index 3171de11..45bab327 100644 --- a/backend/internal/service/admin_service_group_test.go +++ b/backend/internal/service/admin_service_group_test.go @@ -47,7 +47,7 @@ func (s *groupRepoStubForAdmin) List(_ context.Context, _ pagination.PaginationP panic("unexpected List call") } -func (s *groupRepoStubForAdmin) ListWithFilters(_ context.Context, _ pagination.PaginationParams, _, _ string, _ *bool) ([]Group, *pagination.PaginationResult, error) { +func (s *groupRepoStubForAdmin) ListWithFilters(_ context.Context, _ pagination.PaginationParams, _, _, _ string, _ *bool) ([]Group, *pagination.PaginationResult, error) { panic("unexpected ListWithFilters call") } diff --git a/backend/internal/service/gemini_multiplatform_test.go b/backend/internal/service/gemini_multiplatform_test.go index 6007bce8..1a8b005f 100644 --- a/backend/internal/service/gemini_multiplatform_test.go +++ b/backend/internal/service/gemini_multiplatform_test.go @@ -166,7 +166,7 @@ func (m *mockGroupRepoForGemini) DeleteCascade(ctx context.Context, id int64) ([ func (m *mockGroupRepoForGemini) List(ctx context.Context, params pagination.PaginationParams) ([]Group, *pagination.PaginationResult, error) { return nil, nil, nil } -func (m *mockGroupRepoForGemini) ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status string, isExclusive *bool) ([]Group, *pagination.PaginationResult, error) { +func (m *mockGroupRepoForGemini) ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status, search string, isExclusive *bool) ([]Group, *pagination.PaginationResult, error) { return nil, nil, nil } func (m *mockGroupRepoForGemini) ListActive(ctx context.Context) ([]Group, error) { return nil, nil } diff --git a/backend/internal/service/group_service.go b/backend/internal/service/group_service.go index 403636e8..a444556f 100644 --- a/backend/internal/service/group_service.go +++ b/backend/internal/service/group_service.go @@ -21,7 +21,7 @@ type GroupRepository interface { DeleteCascade(ctx context.Context, id int64) ([]int64, error) List(ctx context.Context, params pagination.PaginationParams) ([]Group, *pagination.PaginationResult, error) - ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status string, isExclusive *bool) ([]Group, *pagination.PaginationResult, error) + ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, status, search string, isExclusive *bool) ([]Group, *pagination.PaginationResult, error) ListActive(ctx context.Context) ([]Group, error) ListActiveByPlatform(ctx context.Context, platform string) ([]Group, error) diff --git a/frontend/src/api/admin/groups.ts b/frontend/src/api/admin/groups.ts index 23db9104..44eebc99 100644 --- a/frontend/src/api/admin/groups.ts +++ b/frontend/src/api/admin/groups.ts @@ -16,7 +16,7 @@ import type { * List all groups with pagination * @param page - Page number (default: 1) * @param pageSize - Items per page (default: 20) - * @param filters - Optional filters (platform, status, is_exclusive) + * @param filters - Optional filters (platform, status, is_exclusive, search) * @returns Paginated list of groups */ export async function list( @@ -26,6 +26,7 @@ export async function list( platform?: GroupPlatform status?: 'active' | 'inactive' is_exclusive?: boolean + search?: string }, options?: { signal?: AbortSignal diff --git a/frontend/src/components/admin/account/AccountBulkActionsBar.vue b/frontend/src/components/admin/account/AccountBulkActionsBar.vue index 17bd634d..eaabc611 100644 --- a/frontend/src/components/admin/account/AccountBulkActionsBar.vue +++ b/frontend/src/components/admin/account/AccountBulkActionsBar.vue @@ -1,6 +1,23 @@