diff --git a/apps/main.py b/apps/main.py index 1189366819eb382b74ebb9f392c8e2d3ba67bde6..d33212c6a3ebf007c4f65fb2a6dcf8a67d281b18 100644 --- a/apps/main.py +++ b/apps/main.py @@ -17,6 +17,7 @@ from apps.cron.delete_user import DeleteUserCron from apps.dependency.session import VerifySessionMiddleware from apps.routers import ( api_key, + appcenter, auth, blacklist, chat, @@ -45,6 +46,7 @@ app.add_middleware(VerifySessionMiddleware) app.include_router(conversation.router) app.include_router(auth.router) app.include_router(api_key.router) +app.include_router(appcenter.router) app.include_router(comment.router) app.include_router(record.router) app.include_router(health.router) diff --git a/apps/manager/appcenter.py b/apps/manager/appcenter.py index df693ff59225d60ea6d624533229cf23e961fe67..f94866bb338b77416e7957826fac725603ec3736 100644 --- a/apps/manager/appcenter.py +++ b/apps/manager/appcenter.py @@ -6,8 +6,11 @@ import uuid from enum import Enum from typing import Any, Optional +from fastapi.encoders import jsonable_encoder + from apps.constants import LOGGER from apps.entities.appcenter import AppCenterCardItem, AppData +from apps.entities.collection import User from apps.entities.enum_var import SearchType from apps.entities.flow import Permission from apps.entities.pool import AppPool @@ -164,7 +167,7 @@ class AppCenterManager: ) try: app_collection = MongoDB.get_collection("app") - await app_collection.insert_one(app.model_dump(by_alias=True)) + await app_collection.insert_one(jsonable_encoder(app)) return app_id except Exception as e: LOGGER.error(f"[AppCenterManager] Create app failed: {e}") @@ -255,21 +258,23 @@ class AppCenterManager: try: user_collection = MongoDB.get_collection("user") app_collection = MongoDB.get_collection("app") - user_data = await user_collection.find_one({"_id": user_sub}, {"_id": 0, "app_usage": 1}) - if user_data and "app_usage" in user_data and user_data["app_usage"]: - usage_list = sorted( - user_data["app_usage"].items(), - key=lambda x: x[1]["last_used"], - reverse=True, - )[:count] - app_ids = [t[0] for t in usage_list] - apps = await app_collection.find( - {"_id": {"$in": app_ids}}, {"name": 1}).to_list(len(app_ids)) - app_map = {str(a["_id"]): a.get("name", "") for a in apps} - return RecentAppList(applications=[ - RecentAppListItem(appId=app_id, name=app_map.get(app_id, "")) - for app_id in app_ids - ]) + # 校验用户信息 + user_data = User.model_validate(await user_collection.find_one({"_id": user_sub})) + # 获取最近使用的应用ID列表,按最后使用时间倒序排序 + # 允许 app_usage 为空 + usage_list = sorted( + user_data.app_usage.items(), + key=lambda x: x[1].last_used, + reverse=True, + )[:count] + app_ids = [t[0] for t in usage_list] + apps = await app_collection.find( + {"_id": {"$in": app_ids}}, {"name": 1}).to_list(len(app_ids)) + app_map = {str(a["_id"]): a.get("name", "") for a in apps} + return RecentAppList(applications=[ + RecentAppListItem(appId=app_id, name=app_map.get(app_id, "")) + for app_id in app_ids + ]) except Exception as e: LOGGER.info(f"[AppCenterManager] Get recently used apps failed: {e}") return None diff --git a/apps/manager/conversation.py b/apps/manager/conversation.py index 5d5a2825e8a88e8514c50b4b49b4c2c547a29564..f595d0c5b1103eea9e52319ba0304d7e7beac25d 100644 --- a/apps/manager/conversation.py +++ b/apps/manager/conversation.py @@ -3,6 +3,7 @@ Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. """ import uuid +from datetime import datetime, timezone from typing import Any, Optional from apps.constants import LOGGER @@ -39,7 +40,7 @@ class ConversationManager: @staticmethod async def add_conversation_by_user_sub(user_sub: str, app_id: str, *, is_debug: bool) -> Optional[Conversation]: - """通过用户ID查询历史记录""" + """通过用户ID新建对话""" conversation_id = str(uuid.uuid4()) conv = Conversation( _id=conversation_id, @@ -52,7 +53,18 @@ class ConversationManager: conv_collection = MongoDB.get_collection("conversation") await conv_collection.insert_one(conv.model_dump(by_alias=True), session=session) user_collection = MongoDB.get_collection("user") - await user_collection.update_one({"_id": user_sub}, {"$push": {"conversations": conversation_id}}, session=session) + update_data: dict[str, dict[str, Any]] = { + "$push": {"conversations": conversation_id}, + } + # 非调试模式下更新应用使用情况 + if not is_debug: + update_data["$set"] = {f"app_usage.{app_id}.last_used": round(datetime.now(timezone.utc).timestamp(), 3)} + update_data["$inc"] = {f"app_usage.{app_id}.count": 1} + await user_collection.update_one( + {"_id": user_sub}, + update_data, + session=session, + ) await session.commit_transaction() return conv except Exception as e: diff --git a/apps/routers/appcenter.py b/apps/routers/appcenter.py index 9d25b7407764b944a5ed22b1e545bba29bfc8ad3..8ba2f16c30552788ab320ab91afbe4e0a841020b 100644 --- a/apps/routers/appcenter.py +++ b/apps/routers/appcenter.py @@ -37,12 +37,13 @@ router = APIRouter( @router.get("", response_model=Union[GetAppListRsp, ResponseData]) async def get_applications( # noqa: ANN201, PLR0913 user_sub: Annotated[str, Depends(get_user)], - my_app: Annotated[Optional[bool], Query(None, alias="createdByMe", description="筛选我创建的")], - my_fav: Annotated[Optional[bool], Query(None, alias="favorited", description="筛选我收藏的")], - search_type: Annotated[SearchType, Query(SearchType.ALL, alias="searchType", description="搜索类型")], - keyword: Annotated[Optional[str], Query(None, alias="keyword", description="搜索关键字")], - page: Annotated[int, Query(1, alias="page", ge=1, description="页码")], - page_size: Annotated[int, Query(20, alias="pageSize", ge=1, le=100, description="每页条数")], + *, + my_app: Annotated[bool, Query(..., alias="createdByMe", description="筛选我创建的")] = False, + my_fav: Annotated[bool, Query(..., alias="favorited", description="筛选我收藏的")] = False, + search_type: Annotated[SearchType, Query(..., alias="searchType", description="搜索类型")] = SearchType.ALL, + keyword: Annotated[Optional[str], Query(..., alias="keyword", description="搜索关键字")] = None, + page: Annotated[int, Query(..., alias="page", ge=1, description="页码")] = 1, + page_size: Annotated[int, Query(..., alias="pageSize", ge=1, le=100, description="每页条数")] = 20, ): """获取应用列表""" if my_app and my_fav: # 只能同时使用一个过滤条件 @@ -117,13 +118,13 @@ async def create_or_update_application( # noqa: ANN201 @router.get("/recent", response_model=Union[GetRecentAppListRsp, ResponseData]) async def get_recently_used_applications( # noqa: ANN201 - count: Annotated[int, Query(5, ge=1, le=10)], user_sub: Annotated[str, Depends(get_user)], + count: Annotated[int, Query(..., ge=1, le=10)] = 5, ): """获取最近使用的应用""" recent_apps = await AppCenterManager.get_recently_used_apps( count, user_sub) - if not recent_apps: + if recent_apps is None: return JSONResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=ResponseData( code=status.HTTP_500_INTERNAL_SERVER_ERROR, message="查询失败",