From d57fabcbb4f946575ef3e5663e98e0e661f03f4d Mon Sep 17 00:00:00 2001 From: Wu Clan Date: Tue, 19 Aug 2025 12:18:38 +0800 Subject: [PATCH] Add bulk update interface for config plugin (#774) * Add bulk update interface for config plugin * Remove email sending update --- backend/plugin/config/api/v1/sys/config.py | 17 ++++++++++ backend/plugin/config/crud/crud_config.py | 16 +++++++-- backend/plugin/config/plugin.toml | 4 +-- backend/plugin/config/schema/config.py | 6 ++++ .../plugin/config/service/config_service.py | 33 +++++++++++++++++++ 5 files changed, 72 insertions(+), 4 deletions(-) diff --git a/backend/plugin/config/api/v1/sys/config.py b/backend/plugin/config/api/v1/sys/config.py index be94cb67..020589db 100644 --- a/backend/plugin/config/api/v1/sys/config.py +++ b/backend/plugin/config/api/v1/sys/config.py @@ -14,12 +14,21 @@ from backend.plugin.config.schema.config import ( CreateConfigParam, GetConfigDetail, UpdateConfigParam, + UpdateConfigsParam, ) from backend.plugin.config.service.config_service import config_service router = APIRouter() +@router.get('/all', summary='获取所有参数配置', dependencies=[DependsJwtAuth]) +async def get_all_configs( + type: Annotated[str | None, Query(description='参数配置类型')] = None, +) -> ResponseSchemaModel[list[GetConfigDetail]]: + configs = await config_service.get_all(type=type) + return response_base.success(data=configs) + + @router.get('/{pk}', summary='获取参数配置详情', dependencies=[DependsJwtAuth]) async def get_config(pk: Annotated[int, Path(description='参数配置 ID')]) -> ResponseSchemaModel[GetConfigDetail]: config = await config_service.get(pk=pk) @@ -57,6 +66,14 @@ async def create_config(obj: CreateConfigParam) -> ResponseModel: return response_base.success() +@router.put('', summary='批量更新参数配置', dependencies=[Depends(RequestPermission('sys.config.edits')), DependsRBAC]) +async def bulk_update_config(objs: list[UpdateConfigsParam]) -> ResponseModel: + count = await config_service.bulk_update(objs=objs) + if count > 0: + return response_base.success() + return response_base.fail() + + @router.put( '/{pk}', summary='更新参数配置', diff --git a/backend/plugin/config/crud/crud_config.py b/backend/plugin/config/crud/crud_config.py index 043fdd89..d0d39143 100644 --- a/backend/plugin/config/crud/crud_config.py +++ b/backend/plugin/config/crud/crud_config.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from typing import Sequence -from sqlalchemy import Select +from sqlalchemy import Select, update from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy_crud_plus import CRUDPlus @@ -23,7 +23,7 @@ class CRUDConfig(CRUDPlus[Config]): """ return await self.select_model_by_column(db, id=pk) - async def get_by_type(self, db: AsyncSession, type: str) -> Sequence[Config | None]: + async def get_all(self, db: AsyncSession, type: str) -> Sequence[Config | None]: """ 通过键名获取参数配置 @@ -81,6 +81,18 @@ class CRUDConfig(CRUDPlus[Config]): """ return await self.update_model(db, pk, obj) + async def bulk_update(self, db: AsyncSession, objs: list[UpdateConfigParam]) -> int: + """ + 批量更新参数配置 + + :param db: 数据库会话 + :param objs: 批量更新参数配置参数 + :return: + """ + params = [obj.model_dump(exclude_unset=True) for obj in objs] + await db.execute(update(self.model), params) + return len(params) + async def delete(self, db: AsyncSession, pks: list[int]) -> int: """ 批量删除参数配置 diff --git a/backend/plugin/config/plugin.toml b/backend/plugin/config/plugin.toml index 9a10c036..00fbf8f4 100644 --- a/backend/plugin/config/plugin.toml +++ b/backend/plugin/config/plugin.toml @@ -1,7 +1,7 @@ [plugin] summary = '参数配置' -version = '0.0.1' -description = '通常用于前端工程数据展示' +version = '0.0.2' +description = '通常用于动态配置系统参数/前端工程数据展示' author = 'wu-clan' [app] diff --git a/backend/plugin/config/schema/config.py b/backend/plugin/config/schema/config.py index 4d9dc8f4..becc39a8 100644 --- a/backend/plugin/config/schema/config.py +++ b/backend/plugin/config/schema/config.py @@ -26,6 +26,12 @@ class UpdateConfigParam(ConfigSchemaBase): """更新参数配置参数""" +class UpdateConfigsParam(UpdateConfigParam): + """批量更新参数配置参数""" + + id: int = Field(description='参数配置 ID') + + class GetConfigDetail(ConfigSchemaBase): """参数配置详情""" diff --git a/backend/plugin/config/service/config_service.py b/backend/plugin/config/service/config_service.py index d94228f0..c966c065 100644 --- a/backend/plugin/config/service/config_service.py +++ b/backend/plugin/config/service/config_service.py @@ -10,6 +10,7 @@ from backend.plugin.config.model import Config from backend.plugin.config.schema.config import ( CreateConfigParam, UpdateConfigParam, + UpdateConfigsParam, ) @@ -30,6 +31,17 @@ class ConfigService: raise errors.NotFoundError(msg='参数配置不存在') return config + @staticmethod + async def get_all(*, type: str | None): + """ + 获取所有参数配置 + + :param type: 参数配置类型 + :return: + """ + async with async_db_session() as db: + return await config_dao.get_all(db, type) + @staticmethod async def get_select(*, name: str | None, type: str | None) -> Select: """ @@ -75,6 +87,27 @@ class ConfigService: count = await config_dao.update(db, pk, obj) return count + @staticmethod + async def bulk_update(*, objs: list[UpdateConfigsParam]) -> int: + """ + 批量更新参数配置 + + :param objs: 参数配置批量更新参数 + :return: + """ + async with async_db_session.begin() as db: + for batch in range(0, len(objs), 1000): + for obj in objs: + config = await config_dao.get(db, obj.id) + if not config: + raise errors.NotFoundError(msg='参数配置不存在') + if config.key != obj.key: + config = await config_dao.get_by_key(db, obj.key) + if config: + raise errors.ConflictError(msg=f'参数配置 {obj.key} 已存在') + count = await config_dao.bulk_update(db, objs) + return count + @staticmethod async def delete(*, pks: list[int]) -> int: """