From 5a674022fb3e9761001fdf6248f8c2009607d4ba Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Wed, 16 Jul 2025 19:05:25 +0800 Subject: [PATCH] perf: User delete api --- backend/apps/system/api/user.py | 61 ++++++++++++++++---- backend/apps/system/crud/user.py | 15 ++++- backend/apps/system/schemas/system_schema.py | 1 + frontend/src/views/system/user/User.vue | 7 ++- 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/backend/apps/system/api/user.py b/backend/apps/system/api/user.py index 34f27518..3b6ae4d1 100644 --- a/backend/apps/system/api/user.py +++ b/backend/apps/system/api/user.py @@ -1,7 +1,7 @@ from typing import Optional from fastapi import APIRouter, Query -from sqlmodel import func, or_, select -from apps.system.crud.user import get_db_user, user_ws_options +from sqlmodel import func, or_, select, delete as sqlmodel_delete +from apps.system.crud.user import get_db_user, single_delete, user_ws_options from apps.system.models.system_model import UserWsModel, WorkspaceModel from apps.system.models.user import UserModel from apps.system.schemas.auth import CacheName, CacheNamespace @@ -20,6 +20,7 @@ async def user_info(current_user: CurrentUser): @router.get("/pager/{pageNum}/{pageSize}", response_model=PaginatedResponse[UserGrid]) async def pager( session: SessionDep, + trans: Trans, pageNum: int, pageSize: int, keyword: Optional[str] = Query(None, description="搜索关键字(可选)"), @@ -67,10 +68,21 @@ async def pager( ) ) - return await paginator.get_paginated_response( + user_page = await paginator.get_paginated_response( stmt=stmt, pagination=pagination, **filters) + + for item in user_page.items: + space_name: str = item['space_name'] + if space_name and 'i18n_default_workspace' in space_name: + parts = list(map( + lambda x: trans(x) if x == "i18n_default_workspace" else x, + space_name.split(',') + )) + output_str = ','.join(parts) + item['space_name'] = output_str + return user_page @router.get("/ws") async def ws_options(session: SessionDep, current_user: CurrentUser, trans: Trans) -> list[UserWs]: @@ -88,9 +100,13 @@ async def ws_change(session: SessionDep, current_user: CurrentUser, oid: int): session.commit() @router.get("/{id}", response_model=UserEditor) -async def query(session: SessionDep, id: int) -> UserEditor: +async def query(session: SessionDep, trans: Trans, id: int) -> UserEditor: db_user: UserModel = get_db_user(session = session, user_id = id) - return db_user + u_ws_options = await user_ws_options(session, id, trans) + result = UserEditor.model_validate(db_user.model_dump()) + if u_ws_options: + result.oid_list = [item.id for item in u_ws_options] + return result @router.post("") async def create(session: SessionDep, creator: UserCreator): @@ -99,28 +115,53 @@ async def create(session: SessionDep, creator: UserCreator): #user_model.create_time = get_timestamp() user_model.language = "zh-CN" session.add(user_model) + if creator.oid_list: + # need to validate oid_list + db_model_list = [ + UserWsModel.model_validate({ + "oid": oid, + "uid": user_model.id, + "weight": 0 + }) + for oid in creator.oid_list + ] + session.add_all(db_model_list) session.commit() @router.put("") @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="editor.id") async def update(session: SessionDep, editor: UserEditor): user_model: UserModel = get_db_user(session = session, user_id = editor.id) + + del_stmt = sqlmodel_delete(UserWsModel).where(UserWsModel.uid == editor.id) + session.exec(del_stmt) + data = editor.model_dump(exclude_unset=True) user_model.sqlmodel_update(data) session.add(user_model) + + if editor.oid_list: + # need to validate oid_list + db_model_list = [ + UserWsModel.model_validate({ + "oid": oid, + "uid": user_model.id, + "weight": 0 + }) + for oid in editor.oid_list + ] + session.add_all(db_model_list) + session.commit() @router.delete("/{id}") -@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id") async def delete(session: SessionDep, id: int): - user_model: UserModel = get_db_user(session = session, user_id = id) - session.delete(user_model) - session.commit() + await single_delete(session, id) @router.delete("") async def batch_del(session: SessionDep, id_list: list[int]): for id in id_list: - delete(session, id) + await single_delete(session, id) @router.put("/language") @clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id") diff --git a/backend/apps/system/crud/user.py b/backend/apps/system/crud/user.py index 2b237ee9..1431b971 100644 --- a/backend/apps/system/crud/user.py +++ b/backend/apps/system/crud/user.py @@ -1,11 +1,12 @@ from typing import Optional -from sqlmodel import Session, select +from sqlmodel import Session, select, delete as sqlmodel_delete from apps.system.models.system_model import UserWsModel, WorkspaceModel from apps.system.schemas.auth import CacheName, CacheNamespace from apps.system.schemas.system_schema import BaseUserDTO, UserInfoDTO, UserWs -from common.core.sqlbot_cache import cache +from common.core.deps import SessionDep +from common.core.sqlbot_cache import cache, clear_cache from common.utils.locale import I18n from ..models.user import UserModel from common.core.security import verify_md5pwd @@ -55,4 +56,12 @@ async def user_ws_options(session: Session, uid: int, trans: Optional[I18n] = No return [ UserWs(id = id, name = trans(name) if name.startswith('i18n') else name) for id, name in result.all() - ] \ No newline at end of file + ] + +@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id") +async def single_delete(session: SessionDep, id: int): + user_model: UserModel = get_db_user(session = session, user_id = id) + del_stmt = sqlmodel_delete(UserWsModel).where(UserWsModel.uid == id) + session.exec(del_stmt) + session.delete(user_model) + session.commit() \ No newline at end of file diff --git a/backend/apps/system/schemas/system_schema.py b/backend/apps/system/schemas/system_schema.py index 8b1f3b99..189b6896 100644 --- a/backend/apps/system/schemas/system_schema.py +++ b/backend/apps/system/schemas/system_schema.py @@ -30,6 +30,7 @@ class UserCreator(BaseUser): name: str email: str status: int = 1 + oid_list: Optional[list[int]] = None class UserEditor(UserCreator, BaseCreatorDTO): pass diff --git a/frontend/src/views/system/user/User.vue b/frontend/src/views/system/user/User.vue index 0b025a74..6e1881b6 100644 --- a/frontend/src/views/system/user/User.vue +++ b/frontend/src/views/system/user/User.vue @@ -205,8 +205,8 @@ @@ -348,10 +348,11 @@ const state = reactive({ id: '', name: '', account: '', - oid: '', + oid: 1, email: '', status: '', phoneNumber: '', + oid_list: [], }, pageInfo: { currentPage: 1,