diff --git a/apps/routers/appcenter.py b/apps/routers/appcenter.py index 304aab52092bf825829ed1a7273787a8d3746d28..3aa7ebd439b78d7d25f407ac48a66758c59d09c4 100644 --- a/apps/routers/appcenter.py +++ b/apps/routers/appcenter.py @@ -54,7 +54,7 @@ async def get_applications( # noqa: PLR0913 page: Annotated[int, Query(ge=1)] = 1, ) -> JSONResponse: """获取应用列表""" - user_sub: str = request.state.user_sub + user_id: str = request.state.user_id if createdByMe and favorited: # 只能同时使用一个过滤条件 return JSONResponse( status_code=status.HTTP_400_BAD_REQUEST, @@ -70,7 +70,7 @@ async def get_applications( # noqa: PLR0913 AppFilterType.USER if createdByMe else (AppFilterType.FAVORITE if favorited else AppFilterType.ALL) ) app_cards, total_apps = await AppCenterManager.fetch_apps( - user_sub, + user_id, keyword, appType, page, @@ -103,12 +103,12 @@ async def get_applications( # noqa: PLR0913 @router.post("", response_model=BaseAppOperationRsp | ResponseData) async def create_or_update_application(raw_request: Request, request: CreateAppRequest) -> JSONResponse: """创建或更新应用""" - user_sub: str = raw_request.state.user_sub + user_id: str = raw_request.state.user_id app_id = request.app_id if app_id: # 更新应用 try: - await AppCenterManager.update_app(user_sub, app_id, request) + await AppCenterManager.update_app(user_id, app_id, request) except ValueError: logger.exception("[AppCenter] 更新应用请求无效") return JSONResponse( @@ -141,7 +141,7 @@ async def create_or_update_application(raw_request: Request, request: CreateAppR ) else: # 创建应用 try: - app_id = await AppCenterManager.create_app(user_sub, request) + app_id = await AppCenterManager.create_app(user_id, request) except Exception: logger.exception("[AppCenter] 创建应用失败") return JSONResponse( @@ -168,9 +168,9 @@ async def get_recently_used_applications( count: Annotated[int, Query(ge=1, le=10)] = 5, ) -> JSONResponse: """获取最近使用的应用""" - user_sub: str = request.state.user_sub + user_id: str = request.state.user_id try: - recent_apps = await AppCenterManager.get_recently_used_apps(count, user_sub) + recent_apps = await AppCenterManager.get_recently_used_apps(count, user_id) except Exception: logger.exception("[AppCenter] 获取最近使用的应用失败") return JSONResponse( @@ -306,9 +306,9 @@ async def delete_application( app_id: Annotated[uuid.UUID, Path(..., alias="appId", description="应用ID")], ) -> JSONResponse: """删除应用""" - user_sub: str = request.state.user_sub + user_id: str = request.state.user_id try: - await AppCenterManager.delete_app(app_id, user_sub) + await AppCenterManager.delete_app(app_id, user_id) except ValueError: logger.exception("[AppCenter] 删除应用请求无效") return JSONResponse( @@ -355,9 +355,9 @@ async def publish_application( app_id: Annotated[uuid.UUID, Path(..., alias="appId", description="应用ID")], ) -> JSONResponse: """发布应用""" - user_sub: str = request.state.user_sub + user_id: str = request.state.user_id try: - published = await AppCenterManager.update_app_publish_status(app_id, user_sub) + published = await AppCenterManager.update_app_publish_status(app_id, user_id) if not published: logger.error("[AppCenter] 发布应用失败") return JSONResponse( @@ -405,9 +405,9 @@ async def modify_favorite_application( request: Annotated[ChangeFavouriteAppRequest, Body(...)], ) -> JSONResponse: """更改应用收藏状态""" - user_sub: str = raw_request.state.user_sub + user_id: str = raw_request.state.user_id try: - await AppCenterManager.modify_favorite_app(app_id, user_sub, favorited=request.favorited) + await AppCenterManager.modify_favorite_app(app_id, user_id, favorited=request.favorited) except ValueError: logger.exception("[AppCenter] 修改收藏状态请求无效") return JSONResponse( diff --git a/apps/services/appcenter.py b/apps/services/appcenter.py index 3423e0a05993a45b2e7f5b5f13db20c719f7188d..cd2c07657cc7daec00331c7265d4371605025e11 100644 --- a/apps/services/appcenter.py +++ b/apps/services/appcenter.py @@ -33,6 +33,7 @@ from apps.schemas.flow import AppMetadata, MetadataType, Permission from .flow import FlowManager from .mcp_service import MCPServiceManager +from .user import UserManager logger = logging.getLogger(__name__) @@ -41,23 +42,22 @@ class AppCenterManager: """应用中心管理器""" @staticmethod - async def validate_user_app_access(user_sub: str, app_id: uuid.UUID) -> bool: + async def validate_user_app_access(user_id: str, app_id: uuid.UUID) -> bool: """ 验证用户对应用的访问权限 - :param user_sub: 用户唯一标识符 + :param user_id: 用户唯一标识符 :param app_id: 应用id :return: 如果用户具有所需权限则返回True,否则返回False """ async with postgres.session() as session: - sql = select(App.author, App.permission).where(App.id == app_id) + sql = select(App.authorId, App.permission).where(App.id == app_id) app_info = (await session.execute(sql)).one_or_none() if not app_info: msg = f"[AppCenterManager] 应用不存在: {app_id}" raise ValueError(msg) - # 作者一定可以访问 - if app_info.author == user_sub: + if app_info.authorId == user_id: return True if app_info.permission == PermissionType.PUBLIC: @@ -67,7 +67,7 @@ class AppCenterManager: if app_info.permission == PermissionType.PROTECTED: sql = select(AppACL.appId).where( AppACL.appId == app_id, - AppACL.userSub == user_sub, + AppACL.userId == user_id, ) acl_info = (await session.execute(sql)).one_or_none() if acl_info: @@ -76,11 +76,11 @@ class AppCenterManager: @staticmethod - async def validate_app_belong_to_user(user_sub: str, app_id: uuid.UUID) -> bool: + async def validate_app_belong_to_user(user_id: str, app_id: uuid.UUID) -> bool: """ 验证用户对应用的属权 - :param user_sub: 用户唯一标识符 + :param user_id: 用户唯一标识符 :param app_id: 应用id :return: 如果应用属于用户则返回True,否则返回False """ @@ -89,7 +89,7 @@ class AppCenterManager: select(App).where( and_( App.id == app_id, - App.author == user_sub, + App.authorId == user_id, ), ), )).one_or_none() @@ -101,7 +101,7 @@ class AppCenterManager: @staticmethod async def fetch_apps( - user_sub: str, + user_id: str, keyword: str | None, app_type: AppType | None, page: int, @@ -110,7 +110,7 @@ class AppCenterManager: """ 获取应用列表 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param keyword: 搜索关键字 :param app_type: 应用类型 :param page: 页码 @@ -119,14 +119,14 @@ class AppCenterManager: """ async with postgres.session() as session: protected_apps = select(AppACL.appId).where( - AppACL.userSub == user_sub, + AppACL.userId == user_id, ) app_data = select(App).where( or_( App.permission == PermissionType.PUBLIC, and_( App.permission == PermissionType.PRIVATE, - App.author == user_sub, + App.authorId == user_id, ), and_( App.permission == PermissionType.PROTECTED, @@ -135,20 +135,18 @@ class AppCenterManager: ), ).cte() - # 获取用户所有收藏的应用 favapps_sql = select(UserFavorite.itemId).where( and_( - UserFavorite.userSub == user_sub, + UserFavorite.userId == user_id, UserFavorite.favouriteType == UserFavoriteType.APP, ), ) favapps = list((await session.scalars(favapps_sql)).all()) - # 根据搜索类型加入搜索条件 if filter_type == AppFilterType.ALL: filtered_apps = select(app_data).where(app_data.c.isPublished == True).cte() # noqa: E712 elif filter_type == AppFilterType.USER: - filtered_apps = select(app_data).where(app_data.c.author == user_sub).cte() + filtered_apps = select(app_data).where(app_data.c.authorId == user_id).cte() elif filter_type == AppFilterType.FAVORITE: filtered_apps = select(app_data).where( and_( @@ -157,25 +155,24 @@ class AppCenterManager: ), ).cte() - # 根据应用类型加入搜索条件 if app_type is not None: type_apps = select(filtered_apps).where(filtered_apps.c.appType == AppType(app_type)).cte() else: type_apps = filtered_apps - # 加入关键字搜索条件 if keyword: - keyword_apps = select(type_apps).where( - or_( - type_apps.c.name.ilike(f"%{keyword}%"), - type_apps.c.description.ilike(f"%{keyword}%"), - type_apps.c.author.ilike(f"%{keyword}%"), - ), - ).cte() + # 通过 userName 关键词搜索作者 + author_ids = await UserManager.get_user_ids_by_username_keyword(keyword) + conditions = [ + type_apps.c.name.ilike(f"%{keyword}%"), + type_apps.c.description.ilike(f"%{keyword}%"), + ] + if author_ids: + conditions.append(type_apps.c.authorId.in_(author_ids)) + keyword_apps = select(type_apps).where(or_(*conditions)).cte() else: keyword_apps = type_apps - # 进行搜索 total_apps = (await session.scalars( select(func.count()).select_from(keyword_apps), )).one() @@ -184,20 +181,22 @@ class AppCenterManager: .offset((page - 1) * SERVICE_PAGE_SIZE).limit(SERVICE_PAGE_SIZE), )).all()) - # 构建返回的应用卡片列表 - app_cards = [ - AppCenterCardItem( + # 批量获取所有作者的用户名 + author_ids = {row.authorId for row in result} + author_names = await UserManager.get_usernames_by_ids(author_ids) + + app_cards = [] + for row in result: + app_cards += [AppCenterCardItem( appId=row.id, appType=row.appType, icon=row.icon, name=row.name, description=row.description, - author=row.author, + author=author_names[row.authorId], favorited=(row.id in favapps), published=row.isPublished, - ) - for row in result - ] + )] return app_cards, total_apps @@ -210,7 +209,6 @@ class AppCenterManager: :param app_id: 应用唯一标识 :return: 应用元数据 """ - # 先在数据库中检查应用是否存在 async with postgres.session() as session: app_exists = (await session.scalars( select(App.id).where(App.id == app_id), @@ -219,21 +217,19 @@ class AppCenterManager: msg = f"[AppCenterManager] 应用不存在: {app_id}" raise ValueError(msg) - # 应用存在,使用Loader获取Metadata try: return await pool.app_loader.read_metadata(app_id) except ValueError as e: - # 如果Loader抛出ValueError,说明metadata文件不存在 msg = f"[AppCenterManager] 应用元数据文件不存在: {app_id}" raise ValueError(msg) from e @staticmethod - async def create_app(user_sub: str, data: AppData) -> uuid.UUID: + async def create_app(user_id: str, data: AppData) -> uuid.UUID: """ 创建应用 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param data: 应用数据 :return: 应用唯一标识 """ @@ -241,25 +237,23 @@ class AppCenterManager: await AppCenterManager._process_app_and_save( app_type=data.app_type, app_id=app_id, - user_sub=user_sub, + user_id=user_id, data=data, ) return app_id @staticmethod - async def update_app(user_sub: str, app_id: uuid.UUID, data: AppData) -> None: + async def update_app(user_id: str, app_id: uuid.UUID, data: AppData) -> None: """ 更新应用 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param app_id: 应用唯一标识 :param data: 应用数据 """ - # 获取应用数据并验证权限 - app_data = await AppCenterManager._get_app_data(app_id, user_sub) + app_data = await AppCenterManager._get_app_data(app_id, user_id) - # 不允许更改应用类型 if app_data.appType != data.app_type: err = f"【AppCenterManager】不允许更改应用类型: {app_data.appType} -> {data.app_type}" raise ValueError(err) @@ -267,25 +261,23 @@ class AppCenterManager: await AppCenterManager._process_app_and_save( app_type=data.app_type, app_id=app_id, - user_sub=user_sub, + user_id=user_id, data=data, published=None, ) @staticmethod - async def update_app_publish_status(app_id: uuid.UUID, user_sub: str) -> bool: + async def update_app_publish_status(app_id: uuid.UUID, user_id: str) -> bool: """ 发布应用 :param app_id: 应用唯一标识 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :return: 发布状态 """ - # 获取应用数据并验证权限 - app_data = await AppCenterManager._get_app_data(app_id, user_sub) + app_data = await AppCenterManager._get_app_data(app_id, user_id) - # 计算发布状态 flows = await FlowManager.get_flows_by_app_id(app_id) published = True for flow in flows: @@ -293,7 +285,6 @@ class AppCenterManager: published = False break - # 更新数据库 async with postgres.session() as session: app_obj = (await session.scalars( select(App).where(App.id == app_id), @@ -308,7 +299,7 @@ class AppCenterManager: await AppCenterManager._process_app_and_save( app_type=app_data.appType, app_id=app_id, - user_sub=user_sub, + user_id=user_id, data=None, published=published, ) @@ -316,12 +307,12 @@ class AppCenterManager: @staticmethod - async def modify_favorite_app(app_id: uuid.UUID, user_sub: str, *, favorited: bool) -> None: + async def modify_favorite_app(app_id: uuid.UUID, user_id: str, *, favorited: bool) -> None: """ 修改收藏状态 :param app_id: 应用唯一标识 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param favorited: 是否收藏 """ async with postgres.session() as session: @@ -335,36 +326,33 @@ class AppCenterManager: app_favorite = (await session.scalars( select(UserFavorite).where( and_( - UserFavorite.userSub == user_sub, + UserFavorite.userId == user_id, UserFavorite.itemId == app_id, UserFavorite.favouriteType == UserFavoriteType.APP, ), ), )).one_or_none() if not app_favorite and favorited: - # 添加收藏 app_favorite = UserFavorite( - userSub=user_sub, + userId=user_id, favouriteType=UserFavoriteType.APP, itemId=app_id, ) session.add(app_favorite) elif app_favorite and not favorited: - # 删除收藏 await session.delete(app_favorite) else: - # 重复操作 msg = f"[AppCenterManager] 重复操作: {app_id}" raise ValueError(msg) @staticmethod - async def delete_app(app_id: uuid.UUID, user_sub: str) -> None: + async def delete_app(app_id: uuid.UUID, user_id: str) -> None: """ 删除应用 :param app_id: 应用唯一标识 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 """ async with postgres.session() as session: app_obj = (await session.scalars( @@ -373,32 +361,30 @@ class AppCenterManager: if not app_obj: msg = f"[AppCenterManager] 应用不存在: {app_id}" raise ValueError(msg) - if app_obj.author != user_sub: - msg = f"[AppCenterManager] 权限不足: {user_sub} -> {app_obj.author}" + if app_obj.authorId != user_id: + msg = f"[AppCenterManager] 权限不足: {user_id} -> {app_obj.authorId}" raise InstancePermissionError(msg) await session.delete(app_obj) await session.commit() @staticmethod - async def get_recently_used_apps(count: int, user_sub: str) -> RecentAppList: + async def get_recently_used_apps(count: int, user_id: str) -> RecentAppList: """ 获取用户最近使用的应用列表 :param count: 应用数量 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :return: 最近使用的应用列表 """ - # 获取用户使用情况 async with postgres.session() as session: recent_apps = list((await session.scalars( select(UserAppUsage.appId).where( - UserAppUsage.userSub == user_sub, + UserAppUsage.userId == user_id, ).order_by( UserAppUsage.lastUsed.desc(), ).limit(count), )).all()) - # 批量查询AppName result = [] for app_id in recent_apps: name = (await session.scalars(select(App.name).where(App.id == app_id))).one_or_none() @@ -409,11 +395,11 @@ class AppCenterManager: @staticmethod - async def update_recent_app(user_sub: str, app_id: uuid.UUID) -> None: + async def update_recent_app(user_id: str, app_id: uuid.UUID) -> None: """ 更新用户的最近使用应用列表 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param app_id: 应用唯一标识 :return: 更新是否成功 """ @@ -422,10 +408,10 @@ class AppCenterManager: async with postgres.session() as session: app_usages = list((await session.scalars( - select(UserAppUsage).where(UserAppUsage.userSub == user_sub), + select(UserAppUsage).where(UserAppUsage.userId == user_id), )).all()) if not app_usages: - msg = f"[AppCenterManager] 用户不存在: {user_sub}" + msg = f"[AppCenterManager] 用户不存在: {user_id}" raise ValueError(msg) for app_data in app_usages: @@ -435,19 +421,19 @@ class AppCenterManager: await session.merge(app_data) break else: - app_data = UserAppUsage(userSub=user_sub, appId=app_id, lastUsed=datetime.now(UTC), usageCount=1) + app_data = UserAppUsage(userId=user_id, appId=app_id, lastUsed=datetime.now(UTC), usageCount=1) await session.merge(app_data) await session.commit() return @staticmethod - async def _get_app_data(app_id: uuid.UUID, user_sub: str, *, check_author: bool = True) -> App: + async def _get_app_data(app_id: uuid.UUID, user_id: str, *, check_author: bool = True) -> App: """ 从数据库获取应用数据并验证权限 :param app_id: 应用唯一标识 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param check_author: 是否检查作者 :return: 应用数据 """ @@ -458,8 +444,8 @@ class AppCenterManager: if not app_data: msg = f"【AppCenterManager】应用不存在: {app_id}" raise ValueError(msg) - if check_author and app_data.author != user_sub: - msg = f"【AppCenterManager】权限不足: {user_sub} -> {app_data.author}" + if check_author and app_data.authorId != user_id: + msg = f"【AppCenterManager】权限不足: {user_id} -> {app_data.authorId}" raise InstancePermissionError(msg) return app_data @@ -475,7 +461,6 @@ class AppCenterManager: """创建工作流应用的元数据""" metadata = AppMetadata(**common_params) - # 设置工作流应用特有属性 if data: metadata.links = data.links metadata.first_questions = data.first_questions @@ -483,25 +468,19 @@ class AppCenterManager: metadata.links = app_data.links metadata.first_questions = app_data.first_questions - # 处理 'flows' 字段 if app_data: - # 更新场景 (update_app, update_app_publish_status): - # 总是使用 app_data 中已存在的 flows。 metadata.flows = app_data.flows else: - # 创建场景 (create_app, app_data is None): - # flows 默认为空列表。 metadata.flows = [] - # 处理 'published' 字段 if app_data: - if published is None: # 对应 update_app + if published is None: metadata.published = getattr(app_data, "published", False) - else: # 对应 update_app_publish_status + else: metadata.published = published - elif published is not None: # 对应 _process_app_and_save 被直接调用且提供了 published,但无 app_data + elif published is not None: metadata.published = published - else: # 对应 create_app (app_data is None, published 参数为 None) + else: metadata.published = False return metadata @@ -510,7 +489,7 @@ class AppCenterManager: @staticmethod async def _create_agent_metadata( common_params: dict, - user_sub: str, + user_id: str, data: AppData | None = None, *, published: bool | None = None, @@ -518,20 +497,16 @@ class AppCenterManager: """创建 Agent 应用的元数据""" metadata = AgentAppMetadata(**common_params) - # mcp_service 逻辑 if data is not None and hasattr(data, "mcp_service") and data.mcp_service: - # 验证传入的 mcp_service 状态,确保只使用已经激活的 activated_mcp_ids = [] for svc in data.mcp_service: - is_activated = await MCPServiceManager.is_active(user_sub, svc) + is_activated = await MCPServiceManager.is_active(user_id, svc) if is_activated: activated_mcp_ids.append(svc) metadata.mcp_service = activated_mcp_ids else: - # data 中找不到 mcp_service,则默认为空列表。 metadata.mcp_service = [] - # Agent 应用的发布状态逻辑 if published is not None: metadata.published = published else: @@ -543,7 +518,7 @@ class AppCenterManager: async def _create_metadata( # noqa: PLR0913 app_type: AppType, app_id: uuid.UUID, - user_sub: str, + user_id: str, data: AppData | None = None, app_data: AppMetadata | AgentAppMetadata | None = None, *, @@ -554,23 +529,22 @@ class AppCenterManager: :param app_type: 应用类型 :param app_id: 应用唯一标识 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param data: 应用数据,用于新建或更新时提供 :param app_data: 现有应用数据,用于更新时提供 :param published: 发布状态,用于更新时提供 :return: 应用元数据 :raises ValueError: 无效应用类型或缺少必要数据 """ - # 验证必要数据 source = data if data else app_data if not source: msg = "必须提供 data 或 app_data 参数" raise ValueError(msg) - # 构建通用参数 + common_params = { "type": MetadataType.APP, "id": app_id, - "author": user_sub, + "author": user_id, "icon": source.icon, "name": source.name, "description": source.description, @@ -581,10 +555,9 @@ class AppCenterManager: ) if data else (app_data.permission if app_data else None), } - # 根据应用类型创建不同的元数据 if app_type == AppType.AGENT and isinstance(app_data, AgentAppMetadata): return await AppCenterManager._create_agent_metadata( - common_params, user_sub, data, published=published, + common_params, user_id, data, published=published, ) if app_type == AppType.FLOW and isinstance(app_data, AppMetadata): return await AppCenterManager._create_flow_metadata(common_params, data, app_data, published=published) @@ -597,7 +570,7 @@ class AppCenterManager: async def _process_app_and_save( app_type: AppType, app_id: uuid.UUID, - user_sub: str, + user_id: str, data: AppData | None = None, *, published: bool | None = None, @@ -607,23 +580,20 @@ class AppCenterManager: :param app_type: 应用类型 :param app_id: 应用唯一标识 - :param user_sub: 用户唯一标识 + :param user_id: 用户唯一标识 :param data: 应用数据,用于新建或更新时提供 :param published: 发布状态,用于更新时提供 :return: 应用元数据 """ - # 获取现有的应用元数据 app_data = await pool.app_loader.read_metadata(app_id) - # 创建应用元数据 metadata = await AppCenterManager._create_metadata( app_type=app_type, app_id=app_id, - user_sub=user_sub, + user_id=user_id, data=data, app_data=app_data, published=published, ) - # 保存应用 await pool.app_loader.save(metadata, app_id) return metadata diff --git a/design/call/api.md b/design/call/api.md index aa8deaf288d0d6097c4962e7e53d1e9cdc65c7ad..073375707affa24e8a836f0f1e26a8502d05ea34 100644 --- a/design/call/api.md +++ b/design/call/api.md @@ -200,7 +200,7 @@ sequenceDiagram API->>+API: _init(call_vars) alt 存在ServiceId - API->>+Service: get_service_metadata(user_sub, service_id) + API->>+Service: get_service_metadata(user_id, service_id) Service-->>-API: service_metadata API->>API: 保存_auth认证信息 end diff --git a/design/call/core.md b/design/call/core.md index 1910f072457d26214b9be12ec39264f153581ed8..d165382b60fbe473859596c6d04dbac25921aa07 100644 --- a/design/call/core.md +++ b/design/call/core.md @@ -323,7 +323,7 @@ classDiagram +task_id: UUID +executor_id: str +session_id: str | None - +user_sub: str + +user_id: str +app_id: UUID | None +conversation_id: UUID | None } @@ -577,7 +577,7 @@ CallVars是CoreCall中最重要的数据结构,包含了执行Call所需的所 | `task_id` | UUID | ✅ | 当前任务的唯一标识符 | | `executor_id` | str | ✅ | Flow执行器的ID | | `session_id` | str \| None | ❌ | 用户会话ID(可选) | -| `user_sub` | str | ✅ | 用户唯一标识符 | +| `user_id` | str | ✅ | 用户唯一标识符 | | `app_id` | UUID \| None | ❌ | 应用ID(可选) | | `conversation_id` | UUID \| None | ❌ | 对话ID(可选) | diff --git a/design/call/facts.md b/design/call/facts.md index 32efd0653d9176c7de517698e2d6f64d03667842..346474e230fc7305fa2843f858b6d1e95e56918b 100644 --- a/design/call/facts.md +++ b/design/call/facts.md @@ -56,7 +56,7 @@ graph TB ```mermaid classDiagram class FactsInput { - +str user_sub + +str user_id +list~dict~ message } @@ -220,7 +220,7 @@ graph TB ```python input_data = { - "user_sub": "user123", + "user_id": "user123", "message": [ {"role": "user", "content": "北京天气如何?"}, {"role": "assistant", "content": "北京今天晴天,温度25度。"} diff --git a/design/call/suggest.md b/design/call/suggest.md index 7f745e12d2c9d225171e52a88c4dd8f268591077..3e96a75ef8aef29ff8e8a0684f6425e16d30aca6 100644 --- a/design/call/suggest.md +++ b/design/call/suggest.md @@ -49,7 +49,7 @@ classDiagram class SuggestionInput { +str question - +str user_sub + +str user_id +list~str~ history_questions } @@ -86,7 +86,7 @@ erDiagram UserTag { bigint id PK - string userSub FK + string userId FK bigint tag FK int count } @@ -100,13 +100,13 @@ erDiagram User { bigint id PK - string userSub UK + string userId UK } Record { uuid id PK uuid conversation_id - string user_sub + string user_id string content dict key } @@ -128,7 +128,7 @@ erDiagram ```json { "question": "杭州有哪些著名景点?", - "user_sub": "user_12345", + "user_id": "user_12345", "history_questions": [ "简单介绍一下杭州", "杭州有哪些著名景点?" @@ -139,7 +139,7 @@ erDiagram **字段说明:** - `question` (string): 当前用户提出的问题 -- `user_sub` (string): 用户唯一标识 +- `user_id` (string): 用户唯一标识 - `history_questions` (list[string]): 该对话中的历史问题列表 #### SingleFlowSuggestionConfig @@ -404,7 +404,7 @@ sequenceDiagram Executor->>Suggestion: _init(call_vars) activate Suggestion - Suggestion->>UserTagMgr: get_user_domain_by_user_sub_and_topk(user_sub, 5) + Suggestion->>UserTagMgr: get_user_domain_by_user_and_topk(user_id, 5) activate UserTagMgr UserTagMgr-->>Suggestion: 返回用户偏好标签列表 deactivate UserTagMgr @@ -584,7 +584,7 @@ sequenceDiagram **查询逻辑:** -1. 根据 user_sub 和 conversation_id 查询 MongoDB +1. 根据 user_id 和 conversation_id 查询 MongoDB 2. 限制返回最近 15 条记录 3. 解密每条记录的 content 字段 4. 从 RecordContent 中提取 question 字段 @@ -597,7 +597,7 @@ MongoDB Record → 解密 → RecordContent → question ### 9.2 用户画像查询 -**查询方法:** `UserTagManager.get_user_domain_by_user_sub_and_topk()` +**查询方法:** `UserTagManager.get_user_domain_by_user_and_topk()` **SQL 查询逻辑:** @@ -605,7 +605,7 @@ MongoDB Record → 解密 → RecordContent → question SELECT ut.*, t.name, t.definition FROM framework_user_tag ut JOIN framework_tag t ON ut.tag = t.id -WHERE ut.userSub = ? +WHERE ut.userId = ? ORDER BY ut.count DESC LIMIT 5 ``` diff --git a/design/executor/agent.md b/design/executor/agent.md index f2681535db1df67ab909d0e7e1a5306af582377a..623993062023b10d5e99c625031eb8f2b8221182 100644 --- a/design/executor/agent.md +++ b/design/executor/agent.md @@ -83,8 +83,8 @@ classDiagram } class MCPPool { - +get(mcp_id, user_sub) MCPClient - +stop(mcp_id, user_sub) None + +get(mcp_id, user_id) MCPClient + +stop(mcp_id, user_id) None } BaseExecutor <|-- MCPAgentExecutor @@ -710,7 +710,7 @@ erDiagram Task { UUID id PK "任务ID" - int userId FK "用户ID" + string userId FK "用户ID" UUID conversationId FK "对话ID" UUID checkpointId FK "检查点ID" datetime updatedAt "更新时间" @@ -1043,7 +1043,7 @@ graph TD ### 10.1 MCP 连接池 - 使用 `MCPPool` 管理 MCP 客户端 -- 按 `(mcp_id, user_sub)` 复用连接 +- 按 `(mcp_id, user_id)` 复用连接 - 任务结束后统一关闭连接 ### 10.2 上下文管理 diff --git a/design/services/activity.md b/design/services/activity.md index 143ebc691570f8c83f6fd25635a6a608fe26399b..431881995946a757b6c7449e8ec1fed144a6875a 100644 --- a/design/services/activity.md +++ b/design/services/activity.md @@ -18,7 +18,7 @@ Activity 模块是 openEuler Intelligence 框架中的用户活动控制系统 - **表名**: `framework_session_activity` - **主键**: `id` (BigInteger, 自增) - **字段**: - - `userSub`: 用户标识 (String(50), 外键关联framework_user.userSub) + - `userId`: 用户标识 (String(50), 外键关联framework_user.userId) - `timestamp`: 活动时间戳 (DateTime, 时区感知) ### 相关实体 @@ -38,9 +38,9 @@ Activity 模块是 openEuler Intelligence 框架中的用户活动控制系统 #### 静态方法 -- `is_active(user_sub)`: 先按用户滑动窗口统计,再按全局并发统计,达到任一阈值即返回 `True` -- `set_active(user_sub)`: 在未超过全局并发上限时登记一个活动任务,内部使用 SQLAlchemy `merge` 以 userSub 为键写入最新时间戳 -- `remove_active(user_sub)`: 移除用户活动状态 +- `is_active(user_id)`: 先按用户滑动窗口统计,再按全局并发统计,达到任一阈值即返回 `True` +- `set_active(user_id)`: 在未超过全局并发上限时登记一个活动任务,内部使用 SQLAlchemy `merge` 以 userId 为键写入最新时间戳 +- `remove_active(user_id)`: 移除用户活动状态 > **注意** > 当前实现仅在 `is_active` 阶段执行滑动窗口校验;`set_active` 只进行一次全局并发计数后写入数据库。 @@ -56,10 +56,10 @@ sequenceDiagram Note over Client, DB: 用户请求处理流程 Client->>Router: 发起请求 - Router->>Activity: is_active(user_sub) + Router->>Activity: is_active(user_id) Note over Activity, DB: 滑动窗口限流检查 - Activity->>DB: SELECT COUNT(*) FROM framework_session_activity
WHERE userSub=? AND timestamp >= ? + Activity->>DB: SELECT COUNT(*) FROM framework_session_activity
WHERE userId=? AND timestamp >= ? DB-->>Activity: 返回用户窗口内请求数 Activity->>Activity: 检查是否超过SLIDE_WINDOW_QUESTION_COUNT @@ -77,7 +77,7 @@ sequenceDiagram Router-->>Client: 返回429错误 else 系统可处理 Activity-->>Router: 返回False (允许) - Router->>Activity: set_active(user_sub) + Router->>Activity: set_active(user_id) Note over Activity, DB: 设置活动状态 Activity->>DB: SELECT COUNT(*) FROM framework_session_activity @@ -88,15 +88,15 @@ sequenceDiagram Activity-->>Router: 抛出ActivityError Router-->>Client: 返回503错误 else 系统仍可处理 - Activity->>DB: MERGE INTO framework_session_activity
(userSub, timestamp) + Activity->>DB: MERGE INTO framework_session_activity
(userId, timestamp) DB-->>Activity: 插入或更新成功 Activity-->>Router: 设置成功 Router-->>Client: 处理请求 Note over Client, DB: 请求完成后清理 Client->>Router: 请求完成 - Router->>Activity: remove_active(user_sub) - Activity->>DB: DELETE FROM framework_session_activity
WHERE userSub=? + Router->>Activity: remove_active(user_id) + Activity->>DB: DELETE FROM framework_session_activity
WHERE userId=? DB-->>Activity: 删除成功 Activity-->>Router: 清理完成 end @@ -112,7 +112,7 @@ erDiagram User { BigInteger id PK - string userSub UK "用户标识" + string userId UK "用户标识" datetime lastLogin "最后登录时间" boolean isActive "是否活跃" boolean isWhitelisted "是否白名单" @@ -125,13 +125,13 @@ erDiagram SessionActivity { BigInteger id PK - string userSub FK "用户标识" + string userId FK "用户标识" datetime timestamp "活动时间戳" } Session { string id PK "会话ID" - string userSub FK "用户标识" + string userId FK "用户标识" string ip "IP地址" string pluginId "插件ID" string token "Token信息" @@ -275,7 +275,7 @@ flowchart LR ## 性能优化 -1. **数据库索引**: userSub字段建立索引,提高查询效率 +1. **数据库索引**: userId字段建立索引,提高查询效率 2. **异步操作**: 所有数据库操作使用异步方式 3. **连接池管理**: 使用数据库连接池管理连接 4. **批量清理**: 可考虑定期清理过期的活动记录 @@ -307,14 +307,14 @@ SLIDE_WINDOW_QUESTION_COUNT = 5 # 窗口内最大请求数 ```python # 检查是否被限流 -if await Activity.is_active(user_sub): +if await Activity.is_active(user_id): raise HTTPException(status_code=429, detail="请求过于频繁") # 设置活动状态 try: - await Activity.set_active(user_sub) + await Activity.set_active(user_id) # 处理业务逻辑 finally: # 清理活动状态 - await Activity.remove_active(user_sub) + await Activity.remove_active(user_id) ``` diff --git a/design/services/appcenter.md b/design/services/appcenter.md index 8fb04ec3fd7486cb753b11a2f3627c5e4a2a8755..c6f0ac9b50354342f12bd87f62c56058cf8f2252 100644 --- a/design/services/appcenter.md +++ b/design/services/appcenter.md @@ -783,7 +783,7 @@ erDiagram AppACL { uuid appId PK "FK" - int userId "FK" + string userId "FK" string action } @@ -794,7 +794,7 @@ erDiagram } User { - int userId PK + string userId PK datetime lastLogin boolean isActive string personalToken @@ -802,14 +802,14 @@ erDiagram UserFavorite { int id PK - int userId "FK" + string userId "FK" enum favouriteType uuid itemId } UserAppUsage { int id PK - int userId "FK" + string userId "FK" uuid appId "FK" int usageCount datetime lastUsed diff --git a/design/services/blacklist.md b/design/services/blacklist.md index 1199925cb133b2250ef6c876509fa1df716b40a5..ffdd3a3b6b8ddbbd7f9733957eccb3f0cf189277 100644 --- a/design/services/blacklist.md +++ b/design/services/blacklist.md @@ -38,14 +38,14 @@ erDiagram Record { uuid id PK "问答对ID" - int userId FK "用户标识" + string userId FK "用户标识" text content "加密内容" text key "加密密钥" } User { int id PK "用户ID" - int userId UK "用户标识" + string userId UK "用户标识" int credit "信用分" boolean isWhitelisted "白名单标识" } diff --git a/design/services/comment.md b/design/services/comment.md index 5c553f401c9333604487119e2c1e49a14bd13ac4..05d86c00e53764c9bc516cfc3b9f2a6288835932 100644 --- a/design/services/comment.md +++ b/design/services/comment.md @@ -299,7 +299,7 @@ classDiagram class Comment { +int id +UUID recordId - +int userId + +string userId +CommentType commentType +list~str~ feedbackType +str feedbackLink @@ -357,7 +357,7 @@ erDiagram FRAMEWORK_RECORD ||--o| FRAMEWORK_COMMENT : has FRAMEWORK_USER { - int userId PK + string userId PK string userName datetime createdAt } @@ -365,7 +365,7 @@ erDiagram FRAMEWORK_RECORD { uuid id PK uuid conversationId - int userId FK + string userId FK string content datetime createdAt } @@ -373,7 +373,7 @@ erDiagram FRAMEWORK_COMMENT { bigint id PK uuid recordId FK - int userId FK + string userId FK enum commentType array feedbackType string feedbackLink diff --git a/design/services/conversation.md b/design/services/conversation.md index 965319f9563692857e44f5abc14a9f3edd0989bf..e64409cdf100fbde6da9bd8751d46bfbc5eddbda 100644 --- a/design/services/conversation.md +++ b/design/services/conversation.md @@ -49,7 +49,7 @@ erDiagram Conversation { uuid id PK - int userId FK + string userId FK uuid appId FK string title boolean isTemporary @@ -57,7 +57,7 @@ erDiagram } UserAppUsage { - int userId FK + string userId FK uuid appId FK int usageCount datetime lastUsed diff --git a/design/services/document.md b/design/services/document.md index de54088eaf97f5bf319af6451404fc56811041d0..d882539a53d9e13da6020533b775db9fbb12e7e5 100644 --- a/design/services/document.md +++ b/design/services/document.md @@ -731,7 +731,7 @@ erDiagram Document { uuid id PK - int userId + string userId string name string extension float size @@ -750,7 +750,7 @@ erDiagram Conversation { uuid id PK - int userId + string userId string title datetime createdAt } @@ -758,7 +758,7 @@ erDiagram Record { uuid id PK uuid conversationId FK - int userId + string userId string content datetime createdAt } diff --git a/design/services/mcp_service.md b/design/services/mcp_service.md index 491269171cd7ca517aa1c354657ddf929d58c69f..cb4f73a0635ebb99adb2108bc7135f8187a4a678 100644 --- a/design/services/mcp_service.md +++ b/design/services/mcp_service.md @@ -1047,7 +1047,7 @@ erDiagram MCPActivated { string mcpId PK "FK" - int userId PK "FK" + string userId PK "FK" json env datetime activatedAt } @@ -1068,7 +1068,7 @@ erDiagram } User { - int userId PK + string userId PK string email boolean isAdmin } diff --git a/design/services/personal_token.md b/design/services/personal_token.md index a5ba63c6ff655af1369fdb69d07794c5759debae..05028d6bb216a236bb5e3b2c6f469ab0bc9715b7 100644 --- a/design/services/personal_token.md +++ b/design/services/personal_token.md @@ -41,14 +41,14 @@ sequenceDiagram Client->>Router: 调用受保护接口(携带 Authorization ) Router->>Dep: verify_session - Dep-->>Router: 注入 request.state.session_id / user_sub(可选) + Dep-->>Router: 注入 request.state.session_id / user_id(可选) Router->>Dep: verify_personal_token Dep->>PTM: get_user_by_personal_token(token) - PTM->>DB: SELECT userSub WHERE personalToken == token - DB-->>PTM: userSub 或 None - PTM-->>Dep: userSub 或 None + PTM->>DB: SELECT userId WHERE personalToken == token + DB-->>PTM: userId 或 None + PTM-->>Dep: userId 或 None alt token 有效 - Dep-->>Router: 注入 request.state.user_sub + Dep-->>Router: 注入 request.state.user_id Router-->>Client: 200 成功响应 else token 无效 Dep-->>Router: 抛出 401 Personal Token 无效 @@ -58,7 +58,7 @@ sequenceDiagram ## 数据模型摘要 -- 用户表 `User` 至少包含:`userSub`(用户唯一标识)、`personalToken`(个人令牌)。 +- 用户表 `User` 至少包含:`userId`(用户唯一标识)、`personalToken`(个人令牌)。 - 个人令牌生成逻辑:`sha256(uuid4().hex)[:16]`(16 位十六进制字符串)。 ## 接口规范 @@ -129,7 +129,7 @@ curl -X GET \ "message": "用户数据详细信息获取成功", "result": { "userInfoList": [ - { "userName": "alice", "userSub": "alice" } + { "userName": "alice", "userId": "alice" } ], "total": 42 } @@ -159,7 +159,7 @@ curl -X GET \ - 令牌-用户映射与更新 - “令牌查用户”:按“令牌等于用户表中的个人令牌字段”的条件检索,返回匹配到的用户标识;异常会被记录并视为查找失败。 - - “更新令牌”:按用户标识定位记录并写入新生成的令牌;当前实现缺少 `commit` 且使用 `User.id` 过滤(与传入的 `user_sub` 类型不符),导致数据库值保持不变。 + - “更新令牌”:按用户标识定位记录并写入新生成的令牌;当前实现缺少 `commit` 且使用 `User.id` 过滤(与传入的 `user_id` 类型不符),导致数据库值保持不变。 ## 已知限制与建议 diff --git a/design/services/service.md b/design/services/service.md index 8de26447a9260a611858c5643d9473753f88d1d2..2a413c3caae747a6bc5d141b3c5ed7d322940785 100644 --- a/design/services/service.md +++ b/design/services/service.md @@ -540,7 +540,7 @@ sequenceDiagram Client->>Router: POST /api/admin/service (无service_id) Router->>Router: 验证管理员权限 - Router->>Manager: create_service(user_sub, data) + Router->>Manager: create_service(user_id, data) Manager->>Manager: 生成UUID服务ID Manager->>Validator: load_dict(data) Note over Validator: 验证OpenAPI规范
提取服务元数据 @@ -587,7 +587,7 @@ sequenceDiagram Client->>Router: POST /api/admin/service (含service_id) Router->>Router: 验证管理员权限 - Router->>Manager: update_service(user_sub, service_id, data) + Router->>Manager: update_service(user_id, service_id, data) Manager->>DB: 查询Service记录 alt 服务不存在 @@ -718,7 +718,7 @@ sequenceDiagram Client->>Router: PUT /api/service/{serviceId} Router->>Router: 验证用户身份 - Router->>Manager: modify_favorite_service(user_sub, service_id, favorited) + Router->>Manager: modify_favorite_service(user_id, service_id, favorited) Manager->>DB: 查询Service是否存在 alt 服务不存在 @@ -738,7 +738,7 @@ sequenceDiagram alt favorited=true且未收藏 DB-->>Manager: 返回空 Manager->>DB: 插入UserFavorite记录 - Note over DB: itemId=service_id
userSub=user_sub
favouriteType=SERVICE + Note over DB: itemId=service_id
userId=user_id
favouriteType=SERVICE Manager->>DB: 提交事务 Manager-->>Router: 返回成功 Router-->>Client: 200 OK @@ -789,7 +789,7 @@ sequenceDiagram - **特殊处理**: - 当搜索类型为AUTHOR时,验证关键字是否包含在用户标识中 - 如果不包含,直接返回空列表 - - 自动将关键字替换为完整的user_sub进行精确匹配 + - 自动将关键字替换为完整的user_id进行精确匹配 - **执行步骤**: 1. 构建包含author条件的查询语句 2. 根据搜索类型添加额外的过滤条件 @@ -942,7 +942,7 @@ sequenceDiagram - **添加收藏**: 查询UserFavorite不存在且favorited=true时插入新记录 - **取消收藏**: 查询UserFavorite存在且favorited=false时删除记录 - **无变化**: 其他情况不执行数据库操作,直接返回成功 -- **复合键**: UserFavorite表使用(itemId, userSub, favouriteType)作为唯一键 +- **复合键**: UserFavorite表使用(itemId, userId, favouriteType)作为唯一键 - **类型标识**: favouriteType固定为UserFavoriteType.SERVICE - **幂等性**: 多次调用相同参数不会产生错误,状态最终一致 - **使用场景**: 服务列表中的收藏按钮点击事件 @@ -953,7 +953,7 @@ sequenceDiagram - **功能描述**: 从UserFavorite表提取用户收藏的服务UUID - **查询条件**: - - userSub等于指定用户标识 + - userId等于指定用户标识 - favouriteType等于SERVICE类型 - **执行步骤**: 1. 构建查询语句筛选UserFavorite记录 @@ -1010,7 +1010,7 @@ sequenceDiagram - **功能描述**: 在通用查询基础上添加作者过滤 - **执行步骤**: - 1. 创建基础SELECT并添加author=user_sub条件 + 1. 创建基础SELECT并添加author=user_id条件 2. 如果有keyword,使用AND组合作者条件和搜索条件 3. 根据searchType选择搜索字段 4. 应用排序和分页 @@ -1067,19 +1067,19 @@ erDiagram ServiceACL { uuid serviceId PK "FK" - string userSub PK "FK" + string userId PK "FK" datetime createdAt } UserFavorite { uuid itemId PK "FK" - string userSub PK "FK" + string userId PK "FK" enum favouriteType PK datetime createdAt } User { - string userSub PK + string userId PK string email boolean isAdmin } @@ -1143,7 +1143,7 @@ erDiagram #### 收藏唯一性 -- UserFavorite表使用(itemId, userSub, favouriteType)复合主键 +- UserFavorite表使用(itemId, userId, favouriteType)复合主键 - 同一用户不能重复收藏同一服务 - 数据库约束自动保证唯一性 @@ -1437,7 +1437,7 @@ ReducedOpenAPISpec包含提取的核心信息: ServiceACL表维护私有服务的授权用户: -- 复合主键:(serviceId, userSub) +- 复合主键:(serviceId, userId) - 作者自动拥有访问权限 - ACL列表用户可访问PRIVATE服务的元数据 - 服务删除时级联删除ACL记录 diff --git a/design/services/session.md b/design/services/session.md index 30bdd9d8dc3b334dc6acab91ffc158c08561a1b9..717fa0a84d1d8a7f322b9ee7f84ac4b82eb81916 100644 --- a/design/services/session.md +++ b/design/services/session.md @@ -43,10 +43,10 @@ Session 模块是 openEuler Intelligence 框架中的会话管理系统,负责 #### 静态方法 -- `create_session(user_sub, ip)`: 创建浏览器会话 +- `create_session(user_id, ip)`: 创建浏览器会话 - `delete_session(session_id)`: 删除浏览器会话 - `get_user(session_id)`: 从会话中获取用户 -- `get_session_by_user_sub(user_sub)`: 根据用户标识获取会话 +- `get_session_by_user(user_id)`: 根据用户标识获取会话 ## 时序图 @@ -58,7 +58,7 @@ sequenceDiagram participant DB as 数据库 Note over Client, DB: 创建会话流程 - Client->>SessionMgr: create_session(user_sub, ip) + Client->>SessionMgr: create_session(user_id, ip) SessionMgr->>SessionMgr: 验证参数 alt 参数无效 SessionMgr-->>Client: 抛出ValueError @@ -74,12 +74,12 @@ sequenceDiagram Note over Client, DB: 获取用户流程 Client->>SessionMgr: get_user(session_id) SessionMgr->>DB: 查询Session.userId - DB-->>SessionMgr: 返回user_sub或None + DB-->>SessionMgr: 返回user_id或None alt 用户不存在 SessionMgr-->>Client: 返回None else 用户存在 - SessionMgr->>BlacklistMgr: check_blacklisted_users(user_sub) + SessionMgr->>BlacklistMgr: check_blacklisted_users(user_id) BlacklistMgr->>DB: 查询用户黑名单状态 DB-->>BlacklistMgr: 返回黑名单状态 BlacklistMgr-->>SessionMgr: 返回是否在黑名单中 @@ -91,7 +91,7 @@ sequenceDiagram DB-->>SessionMgr: 删除成功 SessionMgr-->>Client: 返回None else 用户不在黑名单中 - SessionMgr-->>Client: 返回user_sub + SessionMgr-->>Client: 返回user_id end end @@ -112,7 +112,7 @@ sequenceDiagram end Note over Client, DB: 根据用户查询会话流程 - Client->>SessionMgr: get_session_by_user_sub(user_sub) + Client->>SessionMgr: get_session_by_user(user_id) SessionMgr->>DB: 查询Session.id DB-->>SessionMgr: 返回session_id或None SessionMgr-->>Client: 返回session_id或None @@ -126,7 +126,7 @@ erDiagram User ||--o{ SessionActivity : "用户产生活动" User { - int userId PK "用户标识" + string userId PK "用户标识" boolean isWhitelisted "是否白名单" integer credit "信用分" string personalToken "个人令牌" @@ -134,7 +134,7 @@ erDiagram Session { string id PK "会话ID" - int userId FK "用户标识" + string userId FK "用户标识" string ip "IP地址" string pluginId "插件ID" string token "Token信息" @@ -144,7 +144,7 @@ erDiagram SessionActivity { BigInteger id PK - int userId FK "用户标识" + string userId FK "用户标识" datetime timestamp "活动时间戳" } ``` @@ -171,7 +171,7 @@ flowchart TD F2 -->|是| G2[记录错误日志] G2 --> H2[删除会话] H2 --> I2[返回None] - F2 -->|否| J2[返回user_sub] + F2 -->|否| J2[返回user_id] end subgraph "删除会话流程" @@ -243,11 +243,11 @@ SESSION_TTL = 43200 # 会话有效期(分钟),默认30天 ```python # 创建会话 -session_id = await SessionManager.create_session(user_sub="user123", ip="192.168.1.1") +session_id = await SessionManager.create_session(user_id="user123", ip="192.168.1.1") # 获取用户信息 -user_sub = await SessionManager.get_user(session_id) -if user_sub: +user_id = await SessionManager.get_user(session_id) +if user_id: # 用户有效,处理业务逻辑 else: # 用户无效或在黑名单中 @@ -256,7 +256,7 @@ else: await SessionManager.delete_session(session_id) # 根据用户查询会话 -session_id = await SessionManager.get_session_by_user_sub(user_sub) +session_id = await SessionManager.get_session_by_user(user_id) ``` ## 扩展性 diff --git a/design/services/tag.md b/design/services/tag.md index ff54e2a485023d2f9a009d695d0cf09ef9322dc0..1a558b36a1c7f93fdb739049839fa7588be69604 100644 --- a/design/services/tag.md +++ b/design/services/tag.md @@ -20,7 +20,7 @@ erDiagram framework_user { BigInteger id PK "主键" - int userId UK "用户标识" + string userId UK "用户标识" datetime lastLogin "最后登录时间" boolean isActive "是否活跃" boolean isWhitelisted "是否白名单" @@ -40,7 +40,7 @@ erDiagram framework_user_tag { BigInteger id PK "主键" - int userId FK "用户标识(外键)" + string userId FK "用户标识(外键)" BigInteger tag FK "标签ID(外键)" integer count "标签使用频次(默认0)" } diff --git a/design/services/user.md b/design/services/user.md index 526409fe55656a95747f406ab568890ce061f7ae..a659e738000327318bd687e4f3bbc75d084fd9e8 100644 --- a/design/services/user.md +++ b/design/services/user.md @@ -47,14 +47,14 @@ erDiagram UserFavorite { bigint id PK "收藏ID" - int userId FK "用户标识" + string userId FK "用户标识" enum favouriteType "收藏类型" uuid itemId "项目ID" } UserAppUsage { bigint id PK "使用记录ID" - int userId FK "用户标识" + string userId FK "用户标识" uuid appId FK "应用ID" int usageCount "使用次数" datetime lastUsed "最后使用时间" @@ -62,7 +62,7 @@ erDiagram UserTag { bigint id PK "标签ID" - int userId FK "用户标识" + string userId FK "用户标识" bigint tag FK "标签ID" int count "标签归类次数" }