From 5584df3d55eacbda5032f4b7edaaa796f631951a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=81=B5=E5=BA=94?= Date: Thu, 2 Jul 2026 10:39:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20PR#164=E5=AE=A1=E6=9F=A5=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20-=20P1=20count=5Fby=5Fuser=20status=E5=8F=82?= =?UTF-8?q?=E6=95=B0=20+=20P2=20=E5=86=85=E5=AD=98=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P1修复: - voice_library_repository.count_by_user() 增加可选 status 参数 - 修复 list_voices_unified 中 TypeError: count_by_user got unexpected keyword argument 'status' P2修复: - 移除 limit=1000 全量拉取,改为直接传递 skip/limit 到仓储层 - 删除冗余的 clone_repository_count() 辅助函数 - 优化统一列表分页逻辑,代码更清晰 Co-Authored-By: Claude Fable 5 --- apps/api/app/api/routes/voices.py | 52 +++++++------------ .../voice_library_repository.py | 8 +-- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/apps/api/app/api/routes/voices.py b/apps/api/app/api/routes/voices.py index 9e39beebd..d7cf61252 100644 --- a/apps/api/app/api/routes/voices.py +++ b/apps/api/app/api/routes/voices.py @@ -137,56 +137,42 @@ def list_voices_unified( preset_count = 0 clone_count = 0 + has_preset = type is None or type == "preset" + has_clone = type is None or type == "clone" + # 获取预置音色 - if type is None or type == "preset": + if has_preset: preset_items = [_preset_to_unified_response(p) for p in PRESET_VOICES] preset_count = len(preset_items) - if type == "preset": - # 仅预置:应用分页 - items = preset_items[skip : skip + limit] - else: - items.extend(preset_items) # 获取克隆音色 - if type is None or type == "clone": + if has_clone: use_case = ListVoiceLibraryUseCase(voice_repository) - clone_items_raw = use_case.execute(user_id, status=status_filter, skip=0, limit=1000) + clone_items_raw = use_case.execute(user_id, status=status_filter, skip=skip, limit=limit) clone_items = [_to_unified_response(i) for i in clone_items_raw] - clone_count = len(clone_items) - if type == "clone": - # 仅克隆:应用分页 - items = clone_items[skip : skip + limit] - else: - items.extend(clone_items) + clone_count = voice_repository.count_by_user(user_id, status=status_filter) if status_filter else voice_repository.count_by_user(user_id) - # 全量模式:应用分页 - if type is None: - total = preset_count + clone_count - items = items[skip : skip + limit] - elif type == "preset": + # 组装结果 + if type == "preset": + items = preset_items[skip : skip + limit] total = preset_count + elif type == "clone": + items = clone_items + total = clone_count else: - total = clone_repository_count(voice_repository, user_id, status_filter) + # 全量模式:预置在前,克隆补位 + all_items = preset_items + clone_items + total = preset_count + clone_count + items = all_items[skip : skip + limit] return UnifiedVoiceListResponse( items=items, total=total, - preset_count=preset_count if type != "clone" else 0, - clone_count=clone_count if type != "preset" else 0, + preset_count=preset_count if has_preset else 0, + clone_count=clone_count if has_clone else 0, ) -def clone_repository_count( - voice_repository: SQLAlchemyVoiceLibraryRepository, - user_id: str, - status_filter: Optional[str], -) -> int: - """获取克隆音色数量。""" - if status_filter: - return voice_repository.count_by_user(user_id, status=status_filter) - return voice_repository.count_by_user(user_id) - - # ==================== 预置音色专用端点 ==================== diff --git a/packages/adapters/sqlalchemy_impl/voice_library_repository.py b/packages/adapters/sqlalchemy_impl/voice_library_repository.py index c0875c0f3..673d438c8 100644 --- a/packages/adapters/sqlalchemy_impl/voice_library_repository.py +++ b/packages/adapters/sqlalchemy_impl/voice_library_repository.py @@ -110,15 +110,17 @@ class SQLAlchemyVoiceLibraryRepository: self.session.commit() return True - def count_by_user(self, user_id: str) -> int: - return ( + def count_by_user(self, user_id: str, *, status: Optional[str] = None) -> int: + query = ( self.session.query(VoiceLibraryModel) .filter( VoiceLibraryModel.user_id == user_id, VoiceLibraryModel.status != "deleted", ) - .count() ) + if status: + query = query.filter(VoiceLibraryModel.status == status) + return query.count() @staticmethod def _model_to_entity(model: VoiceLibraryModel) -> VoiceLibraryItem: