refactor: 统一项目代码风格并修复多处类型与调用问题

本次提交包含多项优化:
1.  移除大量冗余的文件头注释与过时的from __future__导入
2.  将CRUD的list方法统一重命名为get_list保持接口一致
3.  修复前后端状态字段类型不匹配问题,将string类型status改为number
4.  修正前端文案错别字,将"代办事项"修正为标准写法
5.  更新sqlalchemy版本并调整依赖配置
6.  新增缓存工具类替代fastapi-cache2,重构缓存调用逻辑
7.  新增开源授权函生成相关工具与数据库字段支持
8.  为多个业务模块添加防重复提交loading状态
9.  修复邮件模型的外键关联缺失问题
10. 优化pdf生成工具的导入时机与文档注释
This commit is contained in:
zhangtao
2026-06-21 17:34:11 +08:00
parent 3169ef2355
commit 7d2367e34e
106 changed files with 1968 additions and 966 deletions
@@ -4,19 +4,19 @@ from typing import Annotated
from fastapi import APIRouter, Depends, Path, Query, Request
from fastapi.responses import JSONResponse, RedirectResponse
from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache
from redis.asyncio.client import Redis
from sqlalchemy.ext.asyncio import AsyncSession
from app.common.response import ErrorResponse, ResponseSchema, SuccessResponse
from app.config.setting import settings
from app.core import cache_util
from app.core.base_schema import (
AuthSchema,
JWTOutSchema,
LogoutPayloadSchema,
RefreshTokenPayloadSchema,
)
from app.core.cache_util import cache
from app.core.dependencies import db_getter, get_current_user, redis_getter
from app.core.exceptions import CustomException
from app.core.logger import logger
@@ -180,7 +180,7 @@ async def select_tenant_controller(
redis: Annotated[Redis, Depends(redis_getter)],
) -> JSONResponse:
result = await LoginService(auth).select_tenant(request=request, redis=redis, tenant_id=data.tenant_id)
await FastAPICache.clear(namespace=_AUTH_TENANTS_NS)
await cache_util.clear(namespace=_AUTH_TENANTS_NS)
return SuccessResponse(data=result, msg="租户切换成功")
@@ -8,8 +8,6 @@
环境变量见 Settings 中 OAUTH_* 字段。
"""
from __future__ import annotations
import json
import secrets
from typing import Any, Literal
@@ -1,3 +1,4 @@
import json
import secrets
import uuid
@@ -2,11 +2,11 @@ from typing import Annotated
from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse
from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache
from app.common.response import ResponseSchema, SuccessResponse
from app.core import cache_util
from app.core.base_schema import AuthSchema, BatchSetAvailable
from app.core.cache_util import cache
from app.core.dependencies import AuthPermission
from app.core.router_class import OperationLogRoute
@@ -53,7 +53,7 @@ async def create_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:create"]))],
) -> JSONResponse:
result_dict = await DeptService(auth).create(data=data)
await FastAPICache.clear(namespace=_DEPT_NS)
await cache_util.clear(namespace=_DEPT_NS)
return SuccessResponse(data=result_dict, msg="创建部门成功")
@DeptRouter.put(
@@ -67,7 +67,7 @@ async def update_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:update"]))],
) -> JSONResponse:
result_dict = await DeptService(auth).update(id=id, data=data)
await FastAPICache.clear(namespace=_DEPT_NS)
await cache_util.clear(namespace=_DEPT_NS)
return SuccessResponse(data=result_dict, msg="修改部门成功")
@DeptRouter.delete(
@@ -80,7 +80,7 @@ async def delete_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:delete"]))],
) -> JSONResponse:
await DeptService(auth).delete(ids=ids)
await FastAPICache.clear(namespace=_DEPT_NS)
await cache_util.clear(namespace=_DEPT_NS)
return SuccessResponse(msg="删除部门成功")
@DeptRouter.patch(
@@ -93,5 +93,5 @@ async def batch_set_available_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:patch"]))],
) -> JSONResponse:
await DeptService(auth).batch_set_available(data=data)
await FastAPICache.clear(namespace=_DEPT_NS)
await cache_util.clear(namespace=_DEPT_NS)
return SuccessResponse(msg="批量修改部门状态成功")
@@ -1,3 +1,4 @@
from app.core.base_schema import AuthSchema, BatchSetAvailable
from app.core.exceptions import CustomException
from app.utils.common_util import (
@@ -83,7 +84,7 @@ class DeptService:
raise CustomException(msg="删除失败,删除对象不能为空")
# 获取所有部门列表,用于构建树形关系
all_depts = await DeptCRUD(self.auth).list()
all_depts = await DeptCRUD(self.auth).get_list()
# 构建子部门ID映射
child_id_map = get_child_id_map(model_list=all_depts)
@@ -95,7 +96,7 @@ class DeptService:
await DeptCRUD(self.auth).delete(ids=ids)
async def batch_set_available(self, data: BatchSetAvailable) -> None:
dept_list = await DeptCRUD(self.auth).list()
dept_list = await DeptCRUD(self.auth).get_list()
total_ids = []
if data.status == 0:
@@ -2,13 +2,13 @@ from typing import Annotated
from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache
from redis.asyncio.client import Redis
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core import cache_util
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
from app.core.cache_util import cache
from app.core.dependencies import AuthPermission, redis_getter
from app.core.router_class import OperationLogRoute
from app.utils.common_util import bytes2file_response
@@ -68,7 +68,7 @@ async def get_type_list_controller(
async def get_type_optionselect_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:query"]))],
) -> JSONResponse:
result_dict_list = await DictTypeService(auth).list()
result_dict_list = await DictTypeService(auth).get_list()
return SuccessResponse(data=result_dict_list, msg="获取字典类型列表成功")
@DictRouter.post(
@@ -82,7 +82,7 @@ async def create_type_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:create"]))],
) -> JSONResponse:
result_dict = await DictTypeService(auth).create(redis=redis, data=data)
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
await cache_util.clear(namespace=_DICT_TYPE_NS)
return SuccessResponse(data=result_dict, msg="创建字典类型成功")
@DictRouter.put(
@@ -97,7 +97,7 @@ async def update_type_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:update"]))],
) -> JSONResponse:
result_dict = await DictTypeService(auth).update(redis=redis, id=id, data=data)
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
await cache_util.clear(namespace=_DICT_TYPE_NS)
return SuccessResponse(data=result_dict, msg="修改字典类型成功")
@DictRouter.delete(
@@ -111,7 +111,7 @@ async def delete_type_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:delete"]))],
) -> JSONResponse:
await DictTypeService(auth).delete(redis=redis, ids=ids)
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
await cache_util.clear(namespace=_DICT_TYPE_NS)
return SuccessResponse(msg="删除字典类型成功")
@DictRouter.patch(
@@ -124,7 +124,7 @@ async def batch_set_available_dict_type_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:patch"]))],
) -> JSONResponse:
await DictTypeService(auth).set_available(data=data)
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
await cache_util.clear(namespace=_DICT_TYPE_NS)
return SuccessResponse(msg="批量修改字典类型状态成功")
@DictRouter.post(
@@ -137,7 +137,7 @@ async def export_type_list_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:export"]))],
) -> StreamingResponse:
# 获取全量数据并转为dict列表
result_dict_list = await DictTypeService(auth).list(search=search)
result_dict_list = await DictTypeService(auth).get_list(search=search)
export_data = [item.model_dump() for item in result_dict_list]
export_result = DictTypeService.export(data_list=export_data)
@@ -242,7 +242,7 @@ async def export_data_list_controller(
page: Annotated[PaginationQueryParam, Depends()],
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:export"]))],
) -> StreamingResponse:
result_dict_list = await DictDataService(auth).list(search=search, order_by=page.order_by)
result_dict_list = await DictDataService(auth).get_list(search=search, order_by=page.order_by)
export_data = [item.model_dump() for item in result_dict_list]
export_result = DictDataService.export(data_list=export_data)
@@ -54,7 +54,7 @@ class DictDataCRUD(CRUDBase[DictDataModel, DictDataCreateSchema, DictDataUpdateS
- int: 删除的记录数量
"""
if exclude_system:
system_data = await self.list(
system_data = await self.get_list(
search={
"id__in": ids,
"remark__contains": "系统默认",
@@ -81,4 +81,4 @@ class DictDataCRUD(CRUDBase[DictDataModel, DictDataCreateSchema, DictDataUpdateS
search = {"dict_type": dict_type}
if status is not None:
search["status"] = status
return await self.list(search=search, order_by=[{"id": "asc"}])
return await self.get_list(search=search, order_by=[{"id": "asc"}])
@@ -47,7 +47,7 @@ class DictTypeService:
"""
return await DictTypeCRUD(self.auth).get_or_404(id=id, out_schema=DictTypeOutSchema)
async def list(
async def get_list(
self,
search: DictTypeQueryParam | None = None,
order_by: list[dict] | None = None,
@@ -62,7 +62,7 @@ class DictTypeService:
返回:
- list[DictTypeOutSchema]: 字典类型响应模型列表
"""
obj_list = await DictTypeCRUD(self.auth).list(search=vars(search) if search else None, order_by=order_by)
obj_list = await DictTypeCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by)
return [DictTypeOutSchema.model_validate(obj) for obj in obj_list]
async def page(
@@ -149,7 +149,7 @@ class DictTypeService:
# 如果字典类型修改或状态变更,则修改对应字典数据的类型和状态
if exist_obj.dict_type != data.dict_type or exist_obj.status != data.status:
exist_obj_type_list = await DictDataCRUD(self.auth).list(search={"dict_type": exist_obj.dict_type})
exist_obj_type_list = await DictDataCRUD(self.auth).get_list(search={"dict_type": exist_obj.dict_type})
if exist_obj_type_list:
for item in exist_obj_type_list:
item.dict_type = data.dict_type
@@ -174,7 +174,7 @@ class DictTypeService:
redis_key = f"{RedisInitKeyConfig.SYSTEM_DICT.key}:{self.auth.user.tenant_id}:{data.dict_type}"
try:
# 获取当前字典类型的所有字典数据,确保包含最新状态
dict_data_list = await DictDataCRUD(self.auth).list(search={"dict_type": data.dict_type})
dict_data_list = await DictDataCRUD(self.auth).get_list(search={"dict_type": data.dict_type})
dict_data = [DictDataOutSchema.model_validate(row).model_dump(mode="json") for row in dict_data_list if row]
value = json.dumps(dict_data, ensure_ascii=False)
@@ -203,14 +203,14 @@ class DictTypeService:
"""
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
existing = await DictTypeCRUD(self.auth).list(search={"id": ("in", ids)})
existing = await DictTypeCRUD(self.auth).get_list(search={"id": ("in", ids)})
existing_map = {obj.id: obj for obj in existing}
for nid in ids:
if nid not in existing_map:
raise CustomException(msg="删除失败,该数据不存在")
exist_obj = existing_map[nid]
# 检查是否有字典数据
exist_obj_type_list = await DictDataCRUD(self.auth).list(search={"dict_type": exist_obj.dict_type})
exist_obj_type_list = await DictDataCRUD(self.auth).get_list(search={"dict_type": exist_obj.dict_type})
if len(exist_obj_type_list) > 0:
# 如果有字典数据,不能删除
raise CustomException(msg="删除失败,该数据字典类型下存在字典数据")
@@ -290,7 +290,7 @@ class DictDataService:
"""
return await DictDataCRUD(self.auth).get_or_404(id=id, out_schema=DictDataOutSchema)
async def list(
async def get_list(
self,
search: DictDataQueryParam | None = None,
order_by: list[dict] | None = None,
@@ -305,7 +305,7 @@ class DictDataService:
返回:
- list[DictDataOutSchema]: 字典数据响应模型列表
"""
obj_list = await DictDataCRUD(self.auth).list(search=vars(search) if search else None, order_by=order_by)
obj_list = await DictDataCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by)
return [DictDataOutSchema.model_validate(obj) for obj in obj_list]
async def page(
@@ -351,7 +351,7 @@ class DictDataService:
async with async_db_session() as session:
async with session.begin():
init_auth = AuthSchema(db=session, check_data_scope=False)
obj_list = await DictTypeCRUD(init_auth).list()
obj_list = await DictTypeCRUD(init_auth).get_list()
if not obj_list:
logger.warning("未找到任何字典类型数据")
return
@@ -360,7 +360,7 @@ class DictDataService:
dict_type = obj.dict_type
tenant_id = obj.tenant_id
try:
dict_data_list = await DictDataCRUD(init_auth).list(
dict_data_list = await DictDataCRUD(init_auth).get_list(
search={"dict_type": dict_type, "tenant_id": tenant_id}
)
dict_data = [
@@ -452,7 +452,7 @@ class DictDataService:
redis_key = f"{RedisInitKeyConfig.SYSTEM_DICT.key}:{self.auth.user.tenant_id}:{data.dict_type}"
try:
# 获取当前字典类型的所有字典数据
dict_data_list = await DictDataCRUD(self.auth).list(search={"dict_type": data.dict_type})
dict_data_list = await DictDataCRUD(self.auth).get_list(search={"dict_type": data.dict_type})
dict_data = [DictDataOutSchema.model_validate(row).model_dump(mode="json") for row in dict_data_list if row]
value = json.dumps(dict_data, ensure_ascii=False)
@@ -505,7 +505,7 @@ class DictDataService:
if dict_type:
redis_key = f"{RedisInitKeyConfig.SYSTEM_DICT.key}:{self.auth.user.tenant_id}:{dict_type.dict_type}"
try:
dict_data_list = await DictDataCRUD(self.auth).list(search={"dict_type": dict_type.dict_type})
dict_data_list = await DictDataCRUD(self.auth).get_list(search={"dict_type": dict_type.dict_type})
dict_data = [DictDataOutSchema.model_validate(row).model_dump(mode="json") for row in dict_data_list if row]
value = json.dumps(dict_data, ensure_ascii=False)
await RedisCURD(redis).set(
@@ -522,7 +522,7 @@ class DictDataService:
# 刷新新字典类型缓存
redis_key = f"{RedisInitKeyConfig.SYSTEM_DICT.key}:{self.auth.user.tenant_id}:{data.dict_type}"
try:
dict_data_list = await DictDataCRUD(self.auth).list(search={"dict_type": data.dict_type})
dict_data_list = await DictDataCRUD(self.auth).get_list(search={"dict_type": data.dict_type})
dict_data = [DictDataOutSchema.model_validate(row).model_dump(mode="json") for row in dict_data_list if row]
value = json.dumps(dict_data, ensure_ascii=False)
await RedisCURD(redis).set(
@@ -550,7 +550,7 @@ class DictDataService:
"""
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
existing = await DictDataCRUD(self.auth).list(search={"id": ("in", ids)})
existing = await DictDataCRUD(self.auth).get_list(search={"id": ("in", ids)})
existing_map = {obj.id: obj for obj in existing}
for nid in ids:
if nid not in existing_map:
@@ -560,7 +560,7 @@ class DictDataService:
redis_key = f"{RedisInitKeyConfig.SYSTEM_DICT.key}:{self.auth.user.tenant_id}:{exist_obj.dict_type}"
try:
# 重新拉取该类型所有字典数据并写回缓存(保持一致)
dict_data_list = await DictDataCRUD(self.auth).list(search={"dict_type": exist_obj.dict_type})
dict_data_list = await DictDataCRUD(self.auth).get_list(search={"dict_type": exist_obj.dict_type})
dict_data = [DictDataOutSchema.model_validate(row).model_dump(mode="json") for row in dict_data_list if row]
value = json.dumps(dict_data, ensure_ascii=False)
await RedisCURD(redis).set(
@@ -1,3 +1,4 @@
from app.core.base_schema import AuthSchema
from app.core.exceptions import CustomException
from app.core.logger import logger
@@ -49,7 +50,7 @@ class LoginLogService:
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
existing = await LoginLogCRUD(self.auth).list(search={"id": ("in", ids)})
existing = await LoginLogCRUD(self.auth).get_list(search={"id": ("in", ids)})
existing_map = {obj.id for obj in existing}
for nid in ids:
if nid not in existing_map:
@@ -128,7 +129,7 @@ class OperationLogService:
async def delete(self, ids: list[int]) -> None:
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
existing = await OperationLogCRUD(self.auth).list(search={"id": ("in", ids)})
existing = await OperationLogCRUD(self.auth).get_list(search={"id": ("in", ids)})
existing_map = {obj.id for obj in existing}
for nid in ids:
if nid not in existing_map:
@@ -2,12 +2,12 @@ from typing import Annotated
from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core import cache_util
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
from app.core.cache_util import cache
from app.core.dependencies import AuthPermission, get_current_user
from app.core.logger import logger
from app.core.router_class import OperationLogRoute
@@ -66,7 +66,7 @@ async def create_notice_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:create"]))],
) -> JSONResponse:
result_dict = await NoticeService(auth).create(data=data)
await FastAPICache.clear(namespace=_NOTICE_NS)
await cache_util.clear(namespace=_NOTICE_NS)
return SuccessResponse(data=result_dict, msg="创建公告成功")
@NoticeRouter.put(
@@ -80,7 +80,7 @@ async def update_notice_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:update"]))],
) -> JSONResponse:
result_dict = await NoticeService(auth).update(id=id, data=data)
await FastAPICache.clear(namespace=_NOTICE_NS)
await cache_util.clear(namespace=_NOTICE_NS)
return SuccessResponse(data=result_dict, msg="修改公告成功")
@NoticeRouter.delete(
@@ -93,7 +93,7 @@ async def delete_notice_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:delete"]))],
) -> JSONResponse:
await NoticeService(auth).delete(ids=ids)
await FastAPICache.clear(namespace=_NOTICE_NS)
await cache_util.clear(namespace=_NOTICE_NS)
return SuccessResponse(msg="删除公告成功")
@NoticeRouter.patch(
@@ -106,7 +106,7 @@ async def batch_set_available_notice_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:patch"]))],
) -> JSONResponse:
await NoticeService(auth).set_available(data=data)
await FastAPICache.clear(namespace=_NOTICE_NS)
await cache_util.clear(namespace=_NOTICE_NS)
return SuccessResponse(msg="批量修改公告状态成功")
@NoticeRouter.post(
@@ -117,7 +117,7 @@ async def export_notice_list_controller(
search: Annotated[NoticeQueryParam, Depends()],
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:export"]))],
) -> StreamingResponse:
result_dict_list = await NoticeService(auth).list(search=search)
result_dict_list = await NoticeService(auth).get_list(search=search)
export_data = [item.model_dump() for item in result_dict_list]
export_result = NoticeService.export(notice_list=export_data)
@@ -163,7 +163,7 @@ async def mark_read_controller(
) -> JSONResponse:
"""标记已读。通过 `sys_notice_read` 表记录已读时间。"""
await NoticeService(auth).mark_read(notice_id=id)
await FastAPICache.clear(namespace=_NOTICE_NS)
await cache_util.clear(namespace=_NOTICE_NS)
logger.info(f"用户[{auth.user.id}]标记通知[{id}]已读")
return SuccessResponse(msg="标记已读成功")
@@ -177,7 +177,7 @@ async def mark_all_read_controller(
) -> JSONResponse:
"""全部标记已读。返回本次操作标记的数量。"""
count = await NoticeService(auth).mark_all_read()
await FastAPICache.clear(namespace=_NOTICE_NS)
await cache_util.clear(namespace=_NOTICE_NS)
logger.info(f"用户[{auth.user.id}]全部已读, 数量={count}")
return SuccessResponse(data=count, msg=f"全部标记已读成功,共标记 {count}")
@@ -28,12 +28,12 @@ class NoticeService:
async def detail(self, id: int) -> NoticeOutSchema:
return await NoticeCRUD(self.auth).get_or_404(id=id, out_schema=NoticeOutSchema)
async def list(
async def get_list(
self,
search: NoticeQueryParam | None = None,
order_by: list[dict] | None = None,
) -> list[NoticeOutSchema]:
notice_obj_list = await NoticeCRUD(self.auth).list(search=vars(search) if search else None, order_by=order_by)
notice_obj_list = await NoticeCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by)
return [NoticeOutSchema.model_validate(notice_obj) for notice_obj in notice_obj_list]
async def page(
@@ -79,7 +79,7 @@ class NoticeService:
async def delete(self, ids: list[int]) -> None:
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
notices = await NoticeCRUD(self.auth).list(search={"id": ("in", ids)})
notices = await NoticeCRUD(self.auth).get_list(search={"id": ("in", ids)})
notice_map = {n.id: n for n in notices}
for nid in ids:
if nid not in notice_map:
@@ -117,7 +117,7 @@ async def delete_param_controller(
)
async def batch_set_status_controller(
ids: Annotated[list[int], Body(description="参数ID列表")],
status: Annotated[str, Body(description="状态值")],
status: Annotated[int, Body(description="状态值")],
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:patch"]))],
) -> JSONResponse:
await ParamsService(auth).batch_set_status(ids=ids, status=status)
@@ -132,7 +132,7 @@ async def export_param_list_controller(
search: Annotated[ParamsQueryParam, Depends()],
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:export"]))],
) -> StreamingResponse:
result_dict_list = await ParamsService(auth).list(search=search)
result_dict_list = await ParamsService(auth).get_list(search=search)
export_data = [item.model_dump() for item in result_dict_list]
export_result = ParamsService.export(data_list=export_data)
@@ -78,7 +78,7 @@ class ParamsService:
raise CustomException(msg="该数据不存在")
return obj.config_value
async def list(
async def get_list(
self,
search: ParamsQueryParam | None = None,
order_by: list[dict] | None = None,
@@ -93,7 +93,7 @@ class ParamsService:
返回:
- list[ParamsOutSchema]: 参数响应模型列表
"""
obj_list = await ParamsCRUD(self.auth).list(search=vars(search) if search else None, order_by=order_by)
obj_list = await ParamsCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by)
return [ParamsOutSchema.model_validate(obj) for obj in obj_list]
async def page(
@@ -215,7 +215,7 @@ class ParamsService:
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
# 批量校验参数存在性
objs = await ParamsCRUD(self.auth).list(search={"id": ("in", ids)})
objs = await ParamsCRUD(self.auth).get_list(search={"id": ("in", ids)})
obj_map = {o.id: o for o in objs}
for pid in ids:
obj = obj_map.get(pid)
@@ -235,7 +235,7 @@ class ParamsService:
logger.error(f"删除系统配置失败: {e}")
raise CustomException(msg="同步删除缓存失败") from e
async def batch_set_status(self, ids: list[int], status: str) -> None:
async def batch_set_status(self, ids: list[int], status: int) -> None:
"""
批量设置系统参数状态
@@ -297,7 +297,7 @@ class ParamsService:
async with async_db_session() as session:
async with session.begin():
init_auth = AuthSchema(db=session, check_data_scope=False)
config_obj = await ParamsCRUD(init_auth).list()
config_obj = await ParamsCRUD(init_auth).get_list()
if not config_obj:
raise CustomException(msg="该数据不存在")
try:
@@ -349,7 +349,7 @@ class ParamsService:
async with async_db_session() as session:
async with session.begin():
init_auth = AuthSchema(db=session, check_data_scope=False)
config_obj = await ParamsCRUD(init_auth).list()
config_obj = await ParamsCRUD(init_auth).get_list()
if config_obj:
try:
for config in config_obj:
@@ -2,12 +2,12 @@ from typing import Annotated
from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core import cache_util
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
from app.core.cache_util import cache
from app.core.dependencies import AuthPermission
from app.core.router_class import OperationLogRoute
from app.utils.common_util import bytes2file_response
@@ -68,7 +68,7 @@ async def create_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:create"]))],
) -> JSONResponse:
result_dict = await PositionService(auth).create(data=data)
await FastAPICache.clear(namespace=_POS_NS)
await cache_util.clear(namespace=_POS_NS)
return SuccessResponse(data=result_dict, msg="创建岗位成功")
@PositionRouter.put(
@@ -82,7 +82,7 @@ async def update_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:update"]))],
) -> JSONResponse:
result_dict = await PositionService(auth).update(id=id, data=data)
await FastAPICache.clear(namespace=_POS_NS)
await cache_util.clear(namespace=_POS_NS)
return SuccessResponse(data=result_dict, msg="修改岗位成功")
@PositionRouter.delete(
@@ -95,7 +95,7 @@ async def delete_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:delete"]))],
) -> JSONResponse:
await PositionService(auth).delete(ids=ids)
await FastAPICache.clear(namespace=_POS_NS)
await cache_util.clear(namespace=_POS_NS)
return SuccessResponse(msg="删除岗位成功")
@PositionRouter.patch(
@@ -108,7 +108,7 @@ async def batch_set_available_obj_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:patch"]))],
) -> JSONResponse:
await PositionService(auth).set_available(data=data)
await FastAPICache.clear(namespace=_POS_NS)
await cache_util.clear(namespace=_POS_NS)
return SuccessResponse(msg="批量修改岗位状态成功")
@PositionRouter.get(
@@ -120,7 +120,7 @@ async def export_obj_list_controller(
search: Annotated[PositionQueryParam, Depends()],
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:export"]))],
) -> StreamingResponse:
position_query_result = await PositionService(auth).list(search=search)
position_query_result = await PositionService(auth).get_list(search=search)
position_export_result = PositionService.export_list(position_list=position_query_result)
return StreamResponse(
@@ -24,12 +24,12 @@ class PositionService:
async def detail(self, id: int) -> PositionOutSchema:
return await PositionCRUD(self.auth).get_or_404(id=id, out_schema=PositionOutSchema)
async def list(
async def get_list(
self,
search: PositionQueryParam | None = None,
order_by: list[dict] | None = None,
) -> list[PositionOutSchema]:
position_list = await PositionCRUD(self.auth).list(search=vars(search) if search else None, order_by=order_by)
position_list = await PositionCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by)
return [PositionOutSchema.model_validate(position) for position in position_list]
async def page(
@@ -66,7 +66,7 @@ class PositionService:
async def delete(self, ids: list[int]) -> None:
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
positions = await PositionCRUD(self.auth).list(search={"id": ("in", ids)})
positions = await PositionCRUD(self.auth).get_list(search={"id": ("in", ids)})
position_map = {p.id: p for p in positions}
for pid in ids:
if pid not in position_map:
@@ -74,7 +74,7 @@ class PositionService:
await PositionCRUD(self.auth).delete(ids=ids)
async def set_available(self, data: BatchSetAvailable) -> None:
positions = await PositionCRUD(self.auth).list(search={"id": ("in", data.ids)})
positions = await PositionCRUD(self.auth).get_list(search={"id": ("in", data.ids)})
position_map = {p.id: p for p in positions}
for pid in data.ids:
if pid not in position_map:
@@ -2,12 +2,12 @@ from typing import Annotated
from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi_cache import FastAPICache
from fastapi_cache.decorator import cache
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core import cache_util
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
from app.core.cache_util import cache
from app.core.dependencies import AuthPermission
from app.core.router_class import OperationLogRoute
from app.utils.common_util import bytes2file_response
@@ -69,7 +69,7 @@ async def create_role_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:create"]))],
) -> JSONResponse:
result_dict = await RoleService(auth).create(data=data)
await FastAPICache.clear(namespace=_ROLE_NS)
await cache_util.clear(namespace=_ROLE_NS)
return SuccessResponse(data=result_dict, msg="创建角色成功")
@RoleRouter.put(
@@ -83,7 +83,7 @@ async def update_role_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:update"]))],
) -> JSONResponse:
result_dict = await RoleService(auth).update(id=id, data=data)
await FastAPICache.clear(namespace=_ROLE_NS)
await cache_util.clear(namespace=_ROLE_NS)
return SuccessResponse(data=result_dict, msg="修改角色成功")
@RoleRouter.delete(
@@ -96,7 +96,7 @@ async def delete_role_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:delete"]))],
) -> JSONResponse:
await RoleService(auth).delete(ids=ids)
await FastAPICache.clear(namespace=_ROLE_NS)
await cache_util.clear(namespace=_ROLE_NS)
return SuccessResponse(msg="删除角色成功")
@RoleRouter.patch(
@@ -109,7 +109,7 @@ async def batch_set_available_role_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:patch"]))],
) -> JSONResponse:
await RoleService(auth).set_available(data=data)
await FastAPICache.clear(namespace=_ROLE_NS)
await cache_util.clear(namespace=_ROLE_NS)
return SuccessResponse(msg="批量修改角色状态成功")
@RoleRouter.put(
@@ -122,7 +122,7 @@ async def set_role_permission_controller(
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:permission"]))],
) -> JSONResponse:
await RoleService(auth).set_permission(data=data)
await FastAPICache.clear(namespace=_ROLE_NS)
await cache_util.clear(namespace=_ROLE_NS)
return SuccessResponse(msg="授权角色成功")
@RoleRouter.get(
@@ -134,7 +134,7 @@ async def export_role_list_controller(
search: Annotated[RoleQueryParam, Depends()],
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:export"]))],
) -> StreamingResponse:
role_query_result = await RoleService(auth).list(search=search)
role_query_result = await RoleService(auth).get_list(search=search)
role_export_result = RoleService.export_list(role_list=role_query_result)
return StreamResponse(
@@ -25,8 +25,8 @@ class RoleCRUD(CRUDBase[RoleModel, RoleCreateSchema, RoleUpdateSchema]):
返回:
- None
"""
roles = await self.list(search={"id": ("in", role_ids)})
menus = [] if not menu_ids else await MenuCRUD(self.auth).list(search={"id": ("in", menu_ids)})
roles = await self.get_list(search={"id": ("in", role_ids)})
menus = [] if not menu_ids else await MenuCRUD(self.auth).get_list(search={"id": ("in", menu_ids)})
from app.api.v1.module_platform.package.service import PackageService
@@ -54,8 +54,8 @@ class RoleCRUD(CRUDBase[RoleModel, RoleCreateSchema, RoleUpdateSchema]):
返回:
- None
"""
roles = await self.list(search={"id": ("in", role_ids)})
depts = [] if not dept_ids else await DeptCRUD(self.auth).list(search={"id": ("in", dept_ids)})
roles = await self.get_list(search={"id": ("in", role_ids)})
depts = [] if not dept_ids else await DeptCRUD(self.auth).get_list(search={"id": ("in", dept_ids)})
for obj in roles:
relationship = obj.depts
@@ -37,7 +37,7 @@ class RoleService:
"""
return await RoleCRUD(self.auth).get_or_404(id=id, out_schema=RoleOutSchema)
async def list(
async def get_list(
self,
search: RoleQueryParam | None = None,
order_by: list[dict[str, str]] | None = None,
@@ -52,7 +52,7 @@ class RoleService:
返回:
- list[RoleOutSchema]: 角色响应模型列表
"""
role_list = await RoleCRUD(self.auth).list(search=vars(search) if search else None, order_by=order_by)
role_list = await RoleCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by)
return [RoleOutSchema.model_validate(role) for role in role_list]
async def page(
@@ -141,7 +141,7 @@ class RoleService:
raise CustomException(msg="删除失败,删除对象不能为空")
# 批量校验角色存在性
roles = await RoleCRUD(self.auth).list(search={"id": ("in", ids)})
roles = await RoleCRUD(self.auth).get_list(search={"id": ("in", ids)})
if len(roles) != len(ids):
raise CustomException(msg="删除失败,部分ID不存在")
@@ -179,7 +179,7 @@ class RoleService:
返回:
- None
"""
roles = await RoleCRUD(self.auth).list(search={"id": ("in", data.ids)})
roles = await RoleCRUD(self.auth).get_list(search={"id": ("in", data.ids)})
role_map = {r.id: r for r in roles}
for rid in data.ids:
if rid not in role_map:
@@ -1,3 +1,4 @@
from sqlalchemy import select
from app.api.v1.module_system.user.model import UserModel
@@ -212,7 +212,7 @@ async def export_user_list_controller(
search: Annotated[UserQueryParam, Depends()],
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:export"]))],
) -> StreamingResponse:
user_list = await UserService(auth).list(search=search, order_by=page.order_by)
user_list = await UserService(auth).get_list(search=search, order_by=page.order_by)
user_export_result = UserService.export_list(user_list=user_list)
return StreamResponse(
@@ -38,9 +38,9 @@ class UserCRUD(CRUDBase[UserModel, UserCreateSchema, UserUpdateSchema]):
返回:
- None
"""
user_objs = await self.list(search={"id": ("in", user_ids)})
user_objs = await self.get_list(search={"id": ("in", user_ids)})
if role_ids:
role_objs = await RoleCRUD(self.auth).list(search={"id": ("in", role_ids)})
role_objs = await RoleCRUD(self.auth).get_list(search={"id": ("in", role_ids)})
else:
role_objs = []
@@ -61,9 +61,9 @@ class UserCRUD(CRUDBase[UserModel, UserCreateSchema, UserUpdateSchema]):
返回:
- None
"""
user_objs = await self.list(search={"id": ("in", user_ids)})
user_objs = await self.get_list(search={"id": ("in", user_ids)})
if position_ids:
position_objs = await PositionCRUD(self.auth).list(search={"id": ("in", position_ids)})
position_objs = await PositionCRUD(self.auth).get_list(search={"id": ("in", position_ids)})
else:
position_objs = []
@@ -46,12 +46,12 @@ class UserService:
result.dept_name = dept.name if dept else None
return result
async def list(
async def get_list(
self,
search: UserQueryParam | None = None,
order_by: list[dict[str, str]] | None = None,
) -> list[UserOutSchema]:
user_list = await UserCRUD(self.auth).list(search=vars(search) if search else None, order_by=order_by)
user_list = await UserCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by)
return [UserOutSchema.model_validate(user) for user in user_list]
async def page(
@@ -125,7 +125,7 @@ class UserService:
new_user = await UserCRUD(self.auth).update(id=id, data=data)
if data.role_ids and len(data.role_ids) > 0:
roles = await RoleCRUD(self.auth).list(search={"id": ("in", data.role_ids)})
roles = await RoleCRUD(self.auth).get_list(search={"id": ("in", data.role_ids)})
if len(roles) != len(data.role_ids):
raise CustomException(msg="更新失败,部分角色不存在")
if not all(role.status == 0 for role in roles):
@@ -133,7 +133,7 @@ class UserService:
await UserCRUD(self.auth).set_user_roles(user_ids=[id], role_ids=data.role_ids)
if data.position_ids and len(data.position_ids) > 0:
positions = await PositionCRUD(self.auth).list(search={"id": ("in", data.position_ids)})
positions = await PositionCRUD(self.auth).get_list(search={"id": ("in", data.position_ids)})
if len(positions) != len(data.position_ids):
raise CustomException(msg="更新失败,部分岗位不存在")
if not all(position.status == 0 for position in positions):
@@ -145,7 +145,7 @@ class UserService:
async def delete(self, ids: list[int]) -> None:
if len(ids) < 1:
raise CustomException(msg="删除失败,删除对象不能为空")
users = await UserCRUD(self.auth).list(search={"id": ("in", ids)})
users = await UserCRUD(self.auth).get_list(search={"id": ("in", ids)})
user_map = {u.id: u for u in users}
for uid in ids:
user = user_map.get(uid)