mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-25 13:51:04 +00:00
refactor: 大规模代码整理与功能优化
1. 重构后端API路由、CRUD与模块结构,整合日志管理,移除废弃demo代码 2. 优化前端组件类型定义、样式与路由配置,修复权限判断逻辑 3. 调整默认排序规则、滚动条样式与工具类函数,更新依赖与配置文件 4. 修复多处类型不匹配与默认值问题,完善表单与菜单验证逻辑
This commit is contained in:
@@ -1,239 +1,243 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import urllib.parse
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, UploadFile, Body, Path, Query
|
||||
from fastapi.responses import StreamingResponse, JSONResponse
|
||||
from fastapi import APIRouter, Body, Depends, Path, UploadFile
|
||||
from fastapi.responses import JSONResponse, StreamingResponse
|
||||
|
||||
from app.common.response import SuccessResponse, StreamResponse
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from app.utils.common_util import bytes2file_response
|
||||
from app.core.logger import log
|
||||
from app.core.base_schema import BatchSetAvailable
|
||||
|
||||
from .schema import {{ class_name }}CreateSchema, {{ class_name }}OutSchema, {{ class_name }}QueryParam, {{ class_name }}UpdateSchema
|
||||
from .service import {{ class_name }}Service
|
||||
from .schema import {{ class_name }}CreateSchema, {{ class_name }}UpdateSchema, {{ class_name }}QueryParam
|
||||
|
||||
# 动态路由容器前缀由 module_xxx 决定(discover: module_xxx -> /xxx)
|
||||
# 对齐 module_example/demo:业务路由前缀固定为 /{module_name}
|
||||
{{ class_name }}Router = APIRouter(prefix='/{{ module_name }}', tags=["{{ function_name }}模块"])
|
||||
{{ class_name }}Router = APIRouter(route_class=OperationLogRoute, prefix="/{{ module_name }}", tags=["{{ function_name }}模块"])
|
||||
|
||||
|
||||
@{{ class_name }}Router.get(
|
||||
"/detail/{id}",
|
||||
summary="获取{{ function_name }}详情",
|
||||
description="获取{{ function_name }}详情"
|
||||
response_model=ResponseSchema[{{ class_name }}OutSchema],
|
||||
)
|
||||
async def get_{{ business_name_slug }}_detail_controller(
|
||||
id: int = Path(..., description="ID"),
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:query"]))
|
||||
async def get_obj_detail_controller(
|
||||
id: Annotated[int, Path(description="{{ function_name }}ID")],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:detail"]))],
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
获取{{ function_name }}详情接口
|
||||
|
||||
获取{{ function_name }}详情
|
||||
|
||||
参数:
|
||||
- id: int - 数据ID
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
- id (int): {{ function_name }}ID
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- JSONResponse - 包含{{ function_name }}详情的JSON响应
|
||||
- JSONResponse: 包含{{ function_name }}详情的JSON响应
|
||||
"""
|
||||
result_dict = await {{ class_name }}Service.detail_{{ business_name_slug }}_service(auth=auth, id=id)
|
||||
log.info(f"获取{{ function_name }}详情成功 {id}")
|
||||
result_dict = await {{ class_name }}Service.detail_service(id=id, auth=auth)
|
||||
return SuccessResponse(data=result_dict, msg="获取{{ function_name }}详情成功")
|
||||
|
||||
|
||||
@{{ class_name }}Router.get(
|
||||
"/list",
|
||||
summary="查询{{ function_name }}列表",
|
||||
description="查询{{ function_name }}列表"
|
||||
summary="分页查询{{ function_name }}",
|
||||
response_model=ResponseSchema[PageResultSchema[{{ class_name }}OutSchema]],
|
||||
)
|
||||
async def get_{{ business_name_slug }}_list_controller(
|
||||
page: PaginationQueryParam = Depends(),
|
||||
search: {{ class_name }}QueryParam = Depends(),
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:query"]))
|
||||
async def get_obj_list_controller(
|
||||
page: Annotated[PaginationQueryParam, Depends()],
|
||||
search: Annotated[{{ class_name }}QueryParam, Depends()],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:query"]))],
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
查询{{ function_name }}列表接口(数据库分页)
|
||||
|
||||
查询{{ function_name }}列表
|
||||
|
||||
参数:
|
||||
- page: PaginationQueryParam - 分页参数
|
||||
- search: {{ class_name }}QueryParam - 查询参数
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
- page (PaginationQueryParam): 分页查询参数
|
||||
- search ({{ class_name }}QueryParam): 查询参数
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- JSONResponse - 包含{{ function_name }}列表的JSON响应
|
||||
- JSONResponse: 包含{{ function_name }}列表分页信息的JSON响应
|
||||
"""
|
||||
result_dict = await {{ class_name }}Service.page_{{ business_name_slug }}_service(
|
||||
result_dict = await {{ class_name }}Service.page_service(
|
||||
auth=auth,
|
||||
page_no=page.page_no if page.page_no is not None else 1,
|
||||
page_size=page.page_size if page.page_size is not None else 10,
|
||||
page_no=page.page_no,
|
||||
page_size=page.page_size,
|
||||
search=search,
|
||||
order_by=page.order_by
|
||||
order_by=page.order_by,
|
||||
)
|
||||
log.info("查询{{ function_name }}列表成功")
|
||||
return SuccessResponse(data=result_dict, msg="查询{{ function_name }}列表成功")
|
||||
|
||||
|
||||
@{{ class_name }}Router.post(
|
||||
"/create",
|
||||
summary="创建{{ function_name }}",
|
||||
description="创建{{ function_name }}"
|
||||
response_model=ResponseSchema[{{ class_name }}OutSchema],
|
||||
)
|
||||
async def create_{{ business_name_slug }}_controller(
|
||||
async def create_obj_controller(
|
||||
data: {{ class_name }}CreateSchema,
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:create"]))
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:create"]))],
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
创建{{ function_name }}接口
|
||||
|
||||
创建{{ function_name }}
|
||||
|
||||
参数:
|
||||
- data: {{ class_name }}CreateSchema - 创建数据
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
- data ({{ class_name }}CreateSchema): {{ function_name }}创建模型
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- JSONResponse - 包含创建{{ function_name }}结果的JSON响应
|
||||
- JSONResponse: 包含创建{{ function_name }}详情的JSON响应
|
||||
"""
|
||||
result_dict = await {{ class_name }}Service.create_{{ business_name_slug }}_service(auth=auth, data=data)
|
||||
log.info("创建{{ function_name }}成功")
|
||||
result_dict = await {{ class_name }}Service.create_service(auth=auth, data=data)
|
||||
return SuccessResponse(data=result_dict, msg="创建{{ function_name }}成功")
|
||||
|
||||
|
||||
@{{ class_name }}Router.put(
|
||||
"/update/{id}",
|
||||
summary="修改{{ function_name }}",
|
||||
description="修改{{ function_name }}"
|
||||
response_model=ResponseSchema[{{ class_name }}OutSchema],
|
||||
)
|
||||
async def update_{{ business_name_slug }}_controller(
|
||||
async def update_obj_controller(
|
||||
data: {{ class_name }}UpdateSchema,
|
||||
id: int = Path(..., description="ID"),
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:update"]))
|
||||
id: Annotated[int, Path(description="{{ function_name }}ID")],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:update"]))],
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
修改{{ function_name }}接口
|
||||
|
||||
修改{{ function_name }}
|
||||
|
||||
参数:
|
||||
- id: int - 数据ID
|
||||
- data: {{ class_name }}UpdateSchema - 更新数据
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
- data ({{ class_name }}UpdateSchema): {{ function_name }}更新模型
|
||||
- id (int): {{ function_name }}ID
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- JSONResponse - 包含修改{{ function_name }}结果的JSON响应
|
||||
- JSONResponse: 包含修改{{ function_name }}详情的JSON响应
|
||||
"""
|
||||
result_dict = await {{ class_name }}Service.update_{{ business_name_slug }}_service(auth=auth, id=id, data=data)
|
||||
log.info("修改{{ function_name }}成功")
|
||||
result_dict = await {{ class_name }}Service.update_service(auth=auth, id=id, data=data)
|
||||
return SuccessResponse(data=result_dict, msg="修改{{ function_name }}成功")
|
||||
|
||||
|
||||
@{{ class_name }}Router.delete(
|
||||
"/delete",
|
||||
summary="删除{{ function_name }}",
|
||||
description="删除{{ function_name }}"
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
async def delete_{{ business_name_slug }}_controller(
|
||||
ids: list[int] = Body(..., description="ID列表"),
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:delete"]))
|
||||
async def delete_obj_controller(
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:delete"]))],
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
删除{{ function_name }}接口
|
||||
|
||||
删除{{ function_name }}
|
||||
|
||||
参数:
|
||||
- ids: list[int] - 数据ID列表
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
- ids (list[int]): {{ function_name }}ID列表
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- JSONResponse - 包含删除{{ function_name }}结果的JSON响应
|
||||
- JSONResponse: 包含删除{{ function_name }}详情的JSON响应
|
||||
"""
|
||||
await {{ class_name }}Service.delete_{{ business_name_slug }}_service(auth=auth, ids=ids)
|
||||
log.info(f"删除{{ function_name }}成功: {ids}")
|
||||
await {{ class_name }}Service.delete_service(auth=auth, ids=ids)
|
||||
return SuccessResponse(msg="删除{{ function_name }}成功")
|
||||
|
||||
|
||||
@{{ class_name }}Router.patch(
|
||||
"/status/batch",
|
||||
"/available/setting",
|
||||
summary="批量修改{{ function_name }}状态",
|
||||
description="批量修改{{ function_name }}状态"
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
async def batch_set_available_{{ business_name_slug }}_controller(
|
||||
async def batch_set_available_obj_controller(
|
||||
data: BatchSetAvailable,
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:patch"]))
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:patch"]))],
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
批量修改{{ function_name }}状态接口
|
||||
|
||||
批量修改{{ function_name }}状态
|
||||
|
||||
参数:
|
||||
- data: BatchSetAvailable - 批量修改状态数据
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
- data (BatchSetAvailable): 批量修改{{ function_name }}状态模型
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- JSONResponse - 包含批量修改{{ function_name }}状态结果的JSON响应
|
||||
- JSONResponse: 包含批量修改{{ function_name }}状态详情的JSON响应
|
||||
"""
|
||||
await {{ class_name }}Service.set_available_{{ business_name_slug }}_service(auth=auth, data=data)
|
||||
log.info(f"批量修改{{ function_name }}状态成功: {data.ids}")
|
||||
await {{ class_name }}Service.set_available_service(auth=auth, data=data)
|
||||
return SuccessResponse(msg="批量修改{{ function_name }}状态成功")
|
||||
|
||||
|
||||
@{{ class_name }}Router.post(
|
||||
'/export',
|
||||
"/export",
|
||||
summary="导出{{ function_name }}",
|
||||
description="导出{{ function_name }}"
|
||||
)
|
||||
async def export_{{ business_name_slug }}_list_controller(
|
||||
search: {{ class_name }}QueryParam = Depends(),
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:export"]))
|
||||
async def export_obj_list_controller(
|
||||
search: Annotated[{{ class_name }}QueryParam, Depends()],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:export"]))],
|
||||
) -> StreamingResponse:
|
||||
"""
|
||||
导出{{ function_name }}接口
|
||||
|
||||
导出{{ function_name }}
|
||||
|
||||
参数:
|
||||
- search: {{ class_name }}QueryParam - 查询参数
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
- search ({{ class_name }}QueryParam): 查询参数
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- StreamingResponse - 包含导出{{ function_name }}数据的流式响应
|
||||
- StreamingResponse: 包含{{ function_name }}列表的Excel文件流响应
|
||||
"""
|
||||
result_dict_list = await {{ class_name }}Service.list_{{ business_name_slug }}_service(search=search, auth=auth)
|
||||
export_result = await {{ class_name }}Service.batch_export_{{ business_name_slug }}_service(obj_list=result_dict_list)
|
||||
log.info('导出{{ function_name }}成功')
|
||||
result_dict_list = await {{ class_name }}Service.list_service(search=search, auth=auth)
|
||||
export_result = await {{ class_name }}Service.batch_export_service(obj_list=result_dict_list)
|
||||
|
||||
return StreamResponse(
|
||||
data=bytes2file_response(export_result),
|
||||
media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
headers={'Content-Disposition': 'attachment; filename={{ table_name }}.xlsx'}
|
||||
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
headers={"Content-Disposition": "attachment; filename={{ table_name }}.xlsx"},
|
||||
)
|
||||
|
||||
@{{ class_name }}Router.post(
|
||||
'/import',
|
||||
summary="导入{{ function_name }}",
|
||||
description="导入{{ function_name }}"
|
||||
)
|
||||
async def import_{{ business_name_slug }}_list_controller(
|
||||
file: UploadFile,
|
||||
auth: AuthSchema = Depends(AuthPermission(["{{ permission_prefix }}:import"]))
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
导入{{ function_name }}接口
|
||||
|
||||
参数:
|
||||
- file: UploadFile - 上传的Excel文件
|
||||
- auth: AuthSchema - 认证信息
|
||||
|
||||
返回:
|
||||
- JSONResponse - 包含导入{{ function_name }}结果的JSON响应
|
||||
"""
|
||||
batch_import_result = await {{ class_name }}Service.batch_import_{{ business_name_slug }}_service(file=file, auth=auth, update_support=True)
|
||||
log.info("导入{{ function_name }}成功")
|
||||
return SuccessResponse(data=batch_import_result, msg="导入{{ function_name }}成功")
|
||||
|
||||
@{{ class_name }}Router.post(
|
||||
'/download/template',
|
||||
summary="获取{{ function_name }}导入模板",
|
||||
description="获取{{ function_name }}导入模板",
|
||||
dependencies=[Depends(AuthPermission(["{{ permission_prefix }}:download"]))]
|
||||
"/import",
|
||||
summary="导入{{ function_name }}",
|
||||
response_model=ResponseSchema[str],
|
||||
)
|
||||
async def export_{{ business_name_slug }}_template_controller() -> StreamingResponse:
|
||||
async def import_obj_list_controller(
|
||||
file: UploadFile,
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["{{ permission_prefix }}:import"]))],
|
||||
) -> JSONResponse:
|
||||
"""
|
||||
获取{{ function_name }}导入模板接口
|
||||
|
||||
导入{{ function_name }}
|
||||
|
||||
参数:
|
||||
- file (UploadFile): 导入的Excel文件
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
|
||||
返回:
|
||||
- StreamingResponse - 包含{{ function_name }}导入模板的流式响应
|
||||
- JSONResponse: 包含导入{{ function_name }}详情的JSON响应
|
||||
"""
|
||||
import_template_result = await {{ class_name }}Service.import_template_download_{{ business_name_slug }}_service()
|
||||
log.info('获取{{ function_name }}导入模板成功')
|
||||
batch_import_result = await {{ class_name }}Service.batch_import_service(
|
||||
file=file, auth=auth, update_support=True
|
||||
)
|
||||
return SuccessResponse(data=batch_import_result, msg="导入{{ function_name }}成功")
|
||||
|
||||
|
||||
@{{ class_name }}Router.post(
|
||||
"/download/template",
|
||||
summary="获取{{ function_name }}导入模板",
|
||||
dependencies=[Depends(AuthPermission(["{{ permission_prefix }}:download"]))],
|
||||
)
|
||||
async def export_obj_template_controller() -> StreamingResponse:
|
||||
"""
|
||||
获取{{ function_name }}导入模板
|
||||
|
||||
返回:
|
||||
- StreamingResponse: 包含{{ function_name }}导入模板的Excel文件流响应
|
||||
"""
|
||||
import_template_result = await {{ class_name }}Service.import_template_download_service()
|
||||
|
||||
return StreamResponse(
|
||||
data=bytes2file_response(import_template_result),
|
||||
media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
headers={'Content-Disposition': 'attachment; filename={{ table_name }}_template.xlsx'}
|
||||
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename={urllib.parse.quote('{{ function_name }}导入模板.xlsx')}",
|
||||
"Access-Control-Expose-Headers": "Content-Disposition",
|
||||
},
|
||||
)
|
||||
@@ -1,11 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Sequence
|
||||
|
||||
from app.core.base_crud import CRUDBase
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .model import {{ class_name }}Model
|
||||
from .schema import {{ class_name }}CreateSchema, {{ class_name }}UpdateSchema, {{ class_name }}OutSchema
|
||||
from .schema import {{ class_name }}CreateSchema, {{ class_name }}UpdateSchema
|
||||
|
||||
|
||||
class {{ class_name }}CRUD(CRUDBase[{{ class_name }}Model, {{ class_name }}CreateSchema, {{ class_name }}UpdateSchema]):
|
||||
@@ -14,110 +12,8 @@ class {{ class_name }}CRUD(CRUDBase[{{ class_name }}Model, {{ class_name }}Creat
|
||||
def __init__(self, auth: AuthSchema) -> None:
|
||||
"""
|
||||
初始化CRUD数据层
|
||||
|
||||
|
||||
参数:
|
||||
- auth (AuthSchema): 认证信息模型
|
||||
"""
|
||||
super().__init__(model={{ class_name }}Model, auth=auth)
|
||||
|
||||
async def get_by_id_{{ business_name_slug }}_crud(self, id: int, preload: list | None = None) -> {{ class_name }}Model | None:
|
||||
"""
|
||||
详情
|
||||
|
||||
参数:
|
||||
- id (int): 对象ID
|
||||
- preload (list | None): 预加载关系,未提供时使用模型默认项
|
||||
|
||||
返回:
|
||||
- {{ class_name }}Model | None: 模型实例或None
|
||||
"""
|
||||
return await self.get(id=id, preload=preload)
|
||||
|
||||
async def list_{{ business_name_slug }}_crud(self, search: dict | None = None, order_by: list[dict] | None = None, preload: list | None = None) -> Sequence[{{ class_name }}Model]:
|
||||
"""
|
||||
列表查询
|
||||
|
||||
参数:
|
||||
- search (dict | None): 查询参数
|
||||
- order_by (list[dict] | None): 排序参数,未提供时使用模型默认项
|
||||
- preload (list | None): 预加载关系,未提供时使用模型默认项
|
||||
|
||||
返回:
|
||||
- Sequence[{{ class_name }}Model]: 模型实例序列
|
||||
"""
|
||||
return await self.list(search=search, order_by=order_by, preload=preload)
|
||||
|
||||
async def create_{{ business_name_slug }}_crud(self, data: {{ class_name }}CreateSchema) -> {{ class_name }}Model | None:
|
||||
"""
|
||||
创建
|
||||
|
||||
参数:
|
||||
- data ({{ class_name }}CreateSchema): 创建模型
|
||||
|
||||
返回:
|
||||
- {{ class_name }}Model | None: 模型实例或None
|
||||
"""
|
||||
return await self.create(data=data)
|
||||
|
||||
async def update_{{ business_name_slug }}_crud(self, id: int, data: {{ class_name }}UpdateSchema) -> {{ class_name }}Model | None:
|
||||
"""
|
||||
更新
|
||||
|
||||
参数:
|
||||
- id (int): 对象ID
|
||||
- data ({{ class_name }}UpdateSchema): 更新模型
|
||||
|
||||
返回:
|
||||
- {{ class_name }}Model | None: 模型实例或None
|
||||
"""
|
||||
return await self.update(id=id, data=data)
|
||||
|
||||
async def delete_{{ business_name_slug }}_crud(self, ids: list[int]) -> None:
|
||||
"""
|
||||
批量删除
|
||||
|
||||
参数:
|
||||
- ids (list[int]): 对象ID列表
|
||||
|
||||
返回:
|
||||
- None
|
||||
"""
|
||||
return await self.delete(ids=ids)
|
||||
|
||||
async def set_available_{{ business_name_slug }}_crud(self, ids: list[int], status: str) -> None:
|
||||
"""
|
||||
批量设置可用状态
|
||||
|
||||
参数:
|
||||
- ids (list[int]): 对象ID列表
|
||||
- status (str): 可用状态
|
||||
|
||||
返回:
|
||||
- None
|
||||
"""
|
||||
return await self.set(ids=ids, status=status)
|
||||
|
||||
async def page_{{ business_name_slug }}_crud(self, offset: int, limit: int, order_by: list[dict] | None = None, search: dict | None = None, preload: list | None = None) -> dict:
|
||||
"""
|
||||
分页查询
|
||||
|
||||
参数:
|
||||
- offset (int): 偏移量
|
||||
- limit (int): 每页数量
|
||||
- order_by (list[dict] | None): 排序参数,未提供时使用模型默认项
|
||||
- search (dict | None): 查询参数,未提供时查询所有
|
||||
- preload (list | None): 预加载关系,未提供时使用模型默认项
|
||||
|
||||
返回:
|
||||
- Dict: 分页数据
|
||||
"""
|
||||
order_by_list = order_by or [{'{{ pk_column_name }}': 'asc'}]
|
||||
search_dict = search or {}
|
||||
return await self.page(
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
order_by=order_by_list,
|
||||
search=search_dict,
|
||||
out_schema={{ class_name }}OutSchema,
|
||||
preload=preload
|
||||
)
|
||||
@@ -7,7 +7,6 @@ from fastapi import UploadFile
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from app.core.base_schema import BatchSetAvailable
|
||||
from app.core.exceptions import CustomException
|
||||
from app.core.logger import log
|
||||
from app.utils.excel_util import ExcelUtil
|
||||
|
||||
from .crud import {{ class_name }}CRUD
|
||||
@@ -18,166 +17,166 @@ from .schema import (
|
||||
{{ class_name }}QueryParam
|
||||
)
|
||||
|
||||
|
||||
class {{ class_name }}Service:
|
||||
"""
|
||||
{{ function_name }}服务层
|
||||
"""
|
||||
|
||||
|
||||
@classmethod
|
||||
async def detail_{{ business_name_slug }}_service(cls, auth: AuthSchema, id: int) -> dict:
|
||||
"""
|
||||
详情
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- id: int - 数据ID
|
||||
|
||||
|
||||
返回:
|
||||
- dict - 数据详情
|
||||
"""
|
||||
obj = await {{ class_name }}CRUD(auth).get_by_id_{{ business_name_slug }}_crud(id=id)
|
||||
obj = await {{ class_name }}CRUD(auth).get(id=id)
|
||||
if not obj:
|
||||
raise CustomException(msg="该数据不存在")
|
||||
return {{ class_name }}OutSchema.model_validate(obj).model_dump()
|
||||
|
||||
|
||||
@classmethod
|
||||
async def list_{{ business_name_slug }}_service(cls, auth: AuthSchema, search: {{ class_name }}QueryParam | None = None, order_by: list[dict] | None = None) -> list[dict]:
|
||||
"""
|
||||
列表查询
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- search: {{ class_name }}QueryParam | None - 查询参数
|
||||
- order_by: list[dict] | None - 排序参数
|
||||
|
||||
|
||||
返回:
|
||||
- list[dict] - 数据列表
|
||||
"""
|
||||
search_dict = search.__dict__ if search else None
|
||||
obj_list = await {{ class_name }}CRUD(auth).list_{{ business_name_slug }}_crud(search=search_dict, order_by=order_by)
|
||||
obj_list = await {{ class_name }}CRUD(auth).list(search=search_dict, order_by=order_by)
|
||||
return [{{ class_name }}OutSchema.model_validate(obj).model_dump() for obj in obj_list]
|
||||
|
||||
@classmethod
|
||||
async def page_{{ business_name_slug }}_service(cls, auth: AuthSchema, page_no: int, page_size: int, search: {{ class_name }}QueryParam | None = None, order_by: list[dict] | None = None) -> dict:
|
||||
"""
|
||||
分页查询(数据库分页)
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- page_no: int - 页码
|
||||
- page_size: int - 每页数量
|
||||
- search: {{ class_name }}QueryParam | None - 查询参数
|
||||
- order_by: list[dict] | None - 排序参数
|
||||
|
||||
|
||||
返回:
|
||||
- dict - 分页查询结果
|
||||
"""
|
||||
search_dict = search.__dict__ if search else {}
|
||||
order_by_list = order_by or [{'{{ pk_column_name }}': 'asc'}]
|
||||
offset = (page_no - 1) * page_size
|
||||
result = await {{ class_name }}CRUD(auth).page_{{ business_name_slug }}_crud(
|
||||
result = await {{ class_name }}CRUD(auth).page(
|
||||
offset=offset,
|
||||
limit=page_size,
|
||||
order_by=order_by_list,
|
||||
search=search_dict
|
||||
search=search_dict,
|
||||
out_schema={{ class_name }}OutSchema
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
@classmethod
|
||||
async def create_{{ business_name_slug }}_service(cls, auth: AuthSchema, data: {{ class_name }}CreateSchema) -> dict:
|
||||
"""
|
||||
创建
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- data: {{ class_name }}CreateSchema - 创建数据
|
||||
|
||||
|
||||
返回:
|
||||
- dict - 创建结果
|
||||
"""
|
||||
{% for column in columns %}
|
||||
{% if column.is_unique == '1' %}
|
||||
{% if column.is_unique %}
|
||||
obj = await {{ class_name }}CRUD(auth).get({{ column.column_name }}=data.{{ column.column_name }})
|
||||
if obj:
|
||||
raise CustomException(msg='创建失败,{{ column.column_comment }}已存在')
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
obj = await {{ class_name }}CRUD(auth).create_{{ business_name_slug }}_crud(data=data)
|
||||
obj = await {{ class_name }}CRUD(auth).create(data=data)
|
||||
return {{ class_name }}OutSchema.model_validate(obj).model_dump()
|
||||
|
||||
|
||||
@classmethod
|
||||
async def update_{{ business_name_slug }}_service(cls, auth: AuthSchema, id: int, data: {{ class_name }}UpdateSchema) -> dict:
|
||||
"""
|
||||
更新
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- id: int - 数据ID
|
||||
- data: {{ class_name }}UpdateSchema - 更新数据
|
||||
|
||||
|
||||
返回:
|
||||
- dict - 更新结果
|
||||
"""
|
||||
# 检查数据是否存在
|
||||
obj = await {{ class_name }}CRUD(auth).get_by_id_{{ business_name_slug }}_crud(id=id)
|
||||
obj = await {{ class_name }}CRUD(auth).get(id=id)
|
||||
if not obj:
|
||||
raise CustomException(msg='更新失败,该数据不存在')
|
||||
|
||||
|
||||
# 检查唯一性约束
|
||||
{% for column in columns %}
|
||||
{% if column.is_unique == '1' %}
|
||||
{% if column.is_unique %}
|
||||
exist_obj = await {{ class_name }}CRUD(auth).get({{ column.column_name }}=data.{{ column.column_name }})
|
||||
if exist_obj and getattr(exist_obj, '{{ pk_column_name }}') != id:
|
||||
raise CustomException(msg='更新失败,{{ column.column_comment }}重复')
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
obj = await {{ class_name }}CRUD(auth).update_{{ business_name_slug }}_crud(id=id, data=data)
|
||||
|
||||
obj = await {{ class_name }}CRUD(auth).update(id=id, data=data)
|
||||
return {{ class_name }}OutSchema.model_validate(obj).model_dump()
|
||||
|
||||
|
||||
@classmethod
|
||||
async def delete_{{ business_name_slug }}_service(cls, auth: AuthSchema, ids: list[int]) -> None:
|
||||
"""
|
||||
删除
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- ids: list[int] - 数据ID列表
|
||||
|
||||
|
||||
返回:
|
||||
- None
|
||||
"""
|
||||
if len(ids) < 1:
|
||||
raise CustomException(msg='删除失败,删除对象不能为空')
|
||||
for id in ids:
|
||||
obj = await {{ class_name }}CRUD(auth).get_by_id_{{ business_name_slug }}_crud(id=id)
|
||||
obj = await {{ class_name }}CRUD(auth).get(id=id)
|
||||
if not obj:
|
||||
raise CustomException(msg=f'删除失败,ID为{id}的数据不存在')
|
||||
await {{ class_name }}CRUD(auth).delete_{{ business_name_slug }}_crud(ids=ids)
|
||||
|
||||
await {{ class_name }}CRUD(auth).delete(ids=ids)
|
||||
|
||||
@classmethod
|
||||
async def set_available_{{ business_name_slug }}_service(cls, auth: AuthSchema, data: BatchSetAvailable) -> None:
|
||||
"""
|
||||
批量设置状态
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- data: BatchSetAvailable - 批量设置状态数据
|
||||
|
||||
|
||||
返回:
|
||||
- None
|
||||
"""
|
||||
await {{ class_name }}CRUD(auth).set_available_{{ business_name_slug }}_crud(ids=data.ids, status=data.status)
|
||||
|
||||
await {{ class_name }}CRUD(auth).set(ids=data.ids, status=data.status)
|
||||
|
||||
@classmethod
|
||||
async def batch_export_{{ business_name_slug }}_service(cls, obj_list: list[dict]) -> bytes:
|
||||
"""
|
||||
批量导出
|
||||
|
||||
|
||||
参数:
|
||||
- obj_list: list[dict] - 数据列表
|
||||
|
||||
|
||||
返回:
|
||||
- bytes - 导出的Excel文件内容
|
||||
"""
|
||||
@@ -190,7 +189,7 @@ class {{ class_name }}Service:
|
||||
data = obj_list.copy()
|
||||
for item in data:
|
||||
# 处理状态
|
||||
item["status"] = "启用" if item.get("status") == "0" else "停用"
|
||||
item["status"] = "启用" if item.get("status") == 0 else "停用"
|
||||
# 处理创建者
|
||||
creator_info = item.get("created_id")
|
||||
if isinstance(creator_info, dict):
|
||||
@@ -204,12 +203,12 @@ class {{ class_name }}Service:
|
||||
async def batch_import_{{ business_name_slug }}_service(cls, auth: AuthSchema, file: UploadFile, update_support: bool = False) -> str:
|
||||
"""
|
||||
批量导入
|
||||
|
||||
|
||||
参数:
|
||||
- auth: AuthSchema - 认证信息
|
||||
- file: UploadFile - 上传的Excel文件
|
||||
- update_support: bool - 是否支持更新存在数据
|
||||
|
||||
|
||||
返回:
|
||||
- str - 导入结果信息
|
||||
"""
|
||||
@@ -235,25 +234,25 @@ class {{ class_name }}Service:
|
||||
|
||||
# 重命名列名
|
||||
df.rename(columns=header_dict, inplace=True)
|
||||
|
||||
# 验证必填字段
|
||||
|
||||
# 验证必填字段(非主键且不允许为空的列)
|
||||
{% for column in columns %}
|
||||
{% if column.required == '1' %}
|
||||
{% if column.is_nullable is false and column.is_pk is false %}
|
||||
errors = []
|
||||
missing_rows = df[df['{{ column.column_name }}'].isnull()].index.tolist()
|
||||
if missing_rows:
|
||||
field_name = [k for k,v in header_dict.items() if v == field][0]
|
||||
field_name = [k for k,v in header_dict.items() if v == '{{ column.column_name }}'][0]
|
||||
rows_str = "、".join([str(i+1) for i in missing_rows])
|
||||
errors.append(f"{field_name}不能为空,第{rows_str}行")
|
||||
if errors:
|
||||
raise CustomException(msg=f"导入失败,以下行缺少必要字段:\n{'; '.join(errors)}")
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
error_msgs = []
|
||||
success_count = 0
|
||||
count = 0
|
||||
|
||||
|
||||
for _index, row in df.iterrows():
|
||||
count += 1
|
||||
try:
|
||||
@@ -264,10 +263,10 @@ class {{ class_name }}Service:
|
||||
}
|
||||
# 使用CreateSchema做校验后入库
|
||||
create_schema = {{ class_name }}CreateSchema.model_validate(data)
|
||||
|
||||
|
||||
# 检查唯一性约束
|
||||
{% for column in columns %}
|
||||
{% if column.is_unique == '1' %}
|
||||
{% if column.is_unique %}
|
||||
exists_obj = await {{ class_name }}CRUD(auth).get({{ column.column_name }}=create_schema.{{ column.column_name }})
|
||||
if exists_obj:
|
||||
if update_support:
|
||||
@@ -278,8 +277,8 @@ class {{ class_name }}Service:
|
||||
continue
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
await {{ class_name }}CRUD(auth).create_{{ business_name_slug }}_crud(data=create_schema)
|
||||
|
||||
await {{ class_name }}CRUD(auth).create(data=create_schema)
|
||||
success_count += 1
|
||||
except Exception as e:
|
||||
error_msgs.append(f"第{count}行: {str(e)}")
|
||||
@@ -289,16 +288,16 @@ class {{ class_name }}Service:
|
||||
if error_msgs:
|
||||
result += "\n错误信息:\n" + "\n".join(error_msgs)
|
||||
return result
|
||||
|
||||
|
||||
except Exception as e:
|
||||
log.error(f"批量导入失败: {str(e)}")
|
||||
logger.error(f"批量导入失败: {str(e)}")
|
||||
raise CustomException(msg=f"导入失败: {str(e)}")
|
||||
|
||||
|
||||
@classmethod
|
||||
async def import_template_download_{{ business_name_slug }}_service(cls) -> bytes:
|
||||
"""
|
||||
下载导入模板
|
||||
|
||||
|
||||
返回:
|
||||
- bytes - Excel文件的二进制数据
|
||||
"""
|
||||
@@ -309,16 +308,16 @@ class {{ class_name }}Service:
|
||||
]
|
||||
selector_header_list = []
|
||||
option_list = []
|
||||
|
||||
|
||||
{% for column in columns %}
|
||||
{% if column.html_type == 'select' and column.dict_type %}
|
||||
selector_header_list.append('{{ column.column_comment }}')
|
||||
option_list.append({'{{ column.column_comment }}': []})
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
return ExcelUtil.get_excel_template(
|
||||
header_list=header_list,
|
||||
selector_header_list=selector_header_list,
|
||||
option_list=option_list
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user