mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-23 05:10:57 +00:00
refactor(module): 重构模块结构和代码生成模板
- 删除废弃的ticket和version模块相关代码 - 将resource模块从system迁移到monitor - 移除前端资源管理相关配置 - 重构代码生成模板路径和配置 - 修复CRUD基类初始化参数问题 - 优化模板工具类路径处理 - 更新基础模型字段和配置
This commit is contained in:
@@ -1,71 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from fastapi import APIRouter, Body, Depends, Path
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.common.response import SuccessResponse
|
||||
from app.common.request import PaginationService
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.core.logger import logger
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .param import TicketQueryParam
|
||||
from .service import TicketService
|
||||
from .schema import TicketCreateSchema, TicketUpdateSchema
|
||||
|
||||
|
||||
TicketRouter = APIRouter(route_class=OperationLogRoute, prefix="/ticket", tags=["工单管理"])
|
||||
|
||||
|
||||
@TicketRouter.get("/detail/{id}", summary="获取工单详情", description="获取工单详情")
|
||||
async def get_ticket_detail_controller(
|
||||
id: int = Path(..., description="工单ID"),
|
||||
auth: AuthSchema = Depends(AuthPermission(permissions=["system:ticket:query"]))
|
||||
) -> JSONResponse:
|
||||
result_dict = await TicketService.get_ticket_detail_service(auth=auth, id=id)
|
||||
logger.info(f"获取工单详情成功 {id}")
|
||||
return SuccessResponse(data=result_dict, msg="获取工单详情成功")
|
||||
|
||||
|
||||
@TicketRouter.get("/list", summary="查询工单列表", description="查询工单列表")
|
||||
async def get_ticket_list_controller(
|
||||
page: PaginationQueryParam = Depends(),
|
||||
search: TicketQueryParam = Depends(),
|
||||
auth: AuthSchema = Depends(AuthPermission(permissions=["system:ticket:query"]))
|
||||
) -> JSONResponse:
|
||||
result_dict_list = await TicketService.get_ticket_list_service(auth=auth, search=search, order_by=page.order_by)
|
||||
result_dict = await PaginationService.paginate(data_list=result_dict_list, page_no=page.page_no, page_size=page.page_size)
|
||||
logger.info("查询工单列表成功")
|
||||
return SuccessResponse(data=result_dict, msg="查询工单列表成功")
|
||||
|
||||
|
||||
@TicketRouter.post("/create", summary="创建工单", description="创建工单")
|
||||
async def create_ticket_controller(
|
||||
data: TicketCreateSchema,
|
||||
auth: AuthSchema = Depends(AuthPermission(permissions=["system:ticket:create"]))
|
||||
) -> JSONResponse:
|
||||
result_dict = await TicketService.create_ticket_service(auth=auth, data=data)
|
||||
logger.info(f"创建工单成功: {result_dict}")
|
||||
return SuccessResponse(data=result_dict, msg="创建工单成功")
|
||||
|
||||
|
||||
@TicketRouter.put("/update/{id}", summary="修改工单", description="修改工单")
|
||||
async def update_ticket_controller(
|
||||
data: TicketUpdateSchema,
|
||||
id: int = Path(..., description="工单ID"),
|
||||
auth: AuthSchema = Depends(AuthPermission(permissions=["system:ticket:update"]))
|
||||
) -> JSONResponse:
|
||||
result_dict = await TicketService.update_ticket_service(auth=auth, id=id, data=data)
|
||||
logger.info(f"修改工单成功: {result_dict}")
|
||||
return SuccessResponse(data=result_dict, msg="修改工单成功")
|
||||
|
||||
|
||||
@TicketRouter.delete("/delete", summary="删除工单", description="删除工单")
|
||||
async def delete_ticket_controller(
|
||||
ids: list[int] = Body(..., description="ID列表"),
|
||||
auth: AuthSchema = Depends(AuthPermission(permissions=["system:ticket:delete"]))
|
||||
) -> JSONResponse:
|
||||
await TicketService.delete_ticket_service(auth=auth, ids=ids)
|
||||
logger.info(f"删除工单成功: {ids}")
|
||||
return SuccessResponse(msg="删除工单成功")
|
||||
@@ -1,56 +0,0 @@
|
||||
from typing import Dict, List, Optional, Sequence
|
||||
|
||||
from app.core.base_crud import CRUDBase
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .model import TicketModel
|
||||
from .schema import TicketCreateSchema, TicketUpdateSchema
|
||||
|
||||
|
||||
class TicketCRUD(CRUDBase[TicketModel, TicketCreateSchema, TicketUpdateSchema]):
|
||||
"""工单 CRUD 操作"""
|
||||
|
||||
def __init__(self, auth: AuthSchema) -> None:
|
||||
"""初始化工单CRUD"""
|
||||
self.auth = auth
|
||||
super().__init__(model=TicketModel, auth=auth)
|
||||
|
||||
async def get_by_id_crud(self, id: int) -> Optional[TicketModel]:
|
||||
"""根据id获取工单信息
|
||||
|
||||
:param id: 工单ID
|
||||
:return: 工单信息
|
||||
"""
|
||||
return await self.get(id=id)
|
||||
|
||||
async def get_list_crud(self, search: Optional[Dict] = None, order_by: Optional[List[Dict[str, str]]] = None) -> Sequence[TicketModel]:
|
||||
"""获取工单列表
|
||||
|
||||
:param search: 搜索条件
|
||||
:param order_by: 排序字段
|
||||
:return: 工单列表
|
||||
"""
|
||||
return await self.list(search=search or {}, order_by=order_by or [])
|
||||
|
||||
async def create_crud(self, data: TicketCreateSchema) -> Optional[TicketModel]:
|
||||
"""创建工单
|
||||
|
||||
:param data: 工单创建数据
|
||||
:return: 创建的工单
|
||||
"""
|
||||
return await self.create(data=data)
|
||||
|
||||
async def update_crud(self, id: int, data: TicketUpdateSchema) -> Optional[TicketModel]:
|
||||
"""更新工单
|
||||
|
||||
:param id: 工单ID
|
||||
:param data: 工单更新数据
|
||||
:return: 更新的工单
|
||||
"""
|
||||
return await self.update(id=id, data=data)
|
||||
|
||||
async def delete_crud(self, ids: List[int]) -> None:
|
||||
"""批量删除工单
|
||||
|
||||
:param ids: 工单ID列表
|
||||
"""
|
||||
return await self.delete(ids=ids)
|
||||
@@ -1,30 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Optional
|
||||
from sqlalchemy import String, Text, DateTime, ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from datetime import datetime
|
||||
|
||||
from app.core.base_model import CreatorMixin
|
||||
|
||||
|
||||
class TicketModel(CreatorMixin):
|
||||
"""
|
||||
工单模型 - SQLAlchemy 2.0 语法
|
||||
兼容 MySQL 和 PostgreSQL
|
||||
"""
|
||||
__tablename__ = 'system_ticket'
|
||||
__table_args__ = ({'comment': '工单表'})
|
||||
|
||||
title: Mapped[str] = mapped_column(String(255), nullable=False, comment='工单标题')
|
||||
status: Mapped[str] = mapped_column(String(50), default='pending', comment='工单状态(pending:待处理 progress:处理中 resolved:已解决 closed:已关闭)')
|
||||
priority: Mapped[str] = mapped_column(String(50), default='medium', comment='优先级(low:低, medium:中, high:高, urgent:紧急)')
|
||||
type: Mapped[Optional[str]] = mapped_column(String(50), comment='工单类型(bug:缺陷, feature:功能, task:任务)')
|
||||
assignee_id: Mapped[Optional[int]] = mapped_column(ForeignKey('system_users.id'), comment='指派给用户ID')
|
||||
reporter_id: Mapped[Optional[int]] = mapped_column(ForeignKey('system_users.id'), comment='报告人ID')
|
||||
project: Mapped[Optional[str]] = mapped_column(String(100), comment='所属项目或模块')
|
||||
version: Mapped[Optional[str]] = mapped_column(String(50), comment='版本号')
|
||||
|
||||
# 关系
|
||||
assignee = relationship('UserModel', foreign_keys=[assignee_id])
|
||||
reporter = relationship('UserModel', foreign_keys=[reporter_id])
|
||||
@@ -1,36 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from fastapi import Query
|
||||
|
||||
from app.core.validator import DateTimeStr
|
||||
|
||||
|
||||
class TicketQueryParam:
|
||||
"""工单管理查询参数"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
title: Optional[str] = Query(None, description="工单标题"),
|
||||
status: Optional[bool] = Query(None, description="工单状态"),
|
||||
priority: Optional[str] = Query(None, description="优先级"),
|
||||
creator: Optional[int] = Query(None, description="创建人"),
|
||||
start_time: Optional[DateTimeStr] = Query(None, description="开始时间", example="2023-01-01 00:00:00"),
|
||||
end_time: Optional[DateTimeStr] = Query(None, description="结束时间", example="2023-12-31 23:59:59"),
|
||||
) -> None:
|
||||
super().__init__()
|
||||
|
||||
# 模糊查询字段
|
||||
self.title = ("like", title)
|
||||
|
||||
# 精确查询字段
|
||||
self.creator_id = creator
|
||||
self.status = status
|
||||
self.priority = priority
|
||||
|
||||
# 时间范围查询
|
||||
if start_time and end_time:
|
||||
start_datetime = datetime.strptime(str(start_time), '%Y-%m-%d %H:%M:%S')
|
||||
end_datetime = datetime.strptime(str(end_time), '%Y-%m-%d %H:%M:%S')
|
||||
self.created_at = ("between", (start_datetime, end_datetime))
|
||||
@@ -1,31 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from datetime import datetime
|
||||
|
||||
from app.core.base_schema import BaseSchema
|
||||
|
||||
|
||||
class TicketCreateSchema(BaseModel):
|
||||
"""创建工单"""
|
||||
title: str = Field(..., max_length=255, description='工单标题')
|
||||
description: Optional[str] = Field(default=None, description='工单描述')
|
||||
status: Optional[str] = Field(default='pending', description='工单处理状态(pending:待处理 progress:处理中 resolved:已解决 closed:已关闭)')
|
||||
priority: Optional[str] = Field(default='medium', description='优先级(low, medium, high, urgent)')
|
||||
type: Optional[str] = Field(default='bug', description='工单类型(bug, feature, task)')
|
||||
assignee_id: Optional[int] = Field(default=None, description='指派给用户ID')
|
||||
reporter_id: int = Field(..., description='报告人ID')
|
||||
project: Optional[str] = Field(default=None, max_length=100, description='所属项目')
|
||||
version: Optional[str] = Field(default=None, max_length=50, description='版本号')
|
||||
|
||||
|
||||
class TicketUpdateSchema(TicketCreateSchema):
|
||||
"""更新工单"""
|
||||
...
|
||||
|
||||
|
||||
class TicketOutSchema(TicketCreateSchema, BaseSchema):
|
||||
"""工单输出"""
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
...
|
||||
@@ -1,60 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Dict, List, Optional, Union
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from app.core.exceptions import CustomException
|
||||
from .crud import TicketCRUD
|
||||
from .schema import TicketCreateSchema, TicketUpdateSchema, TicketOutSchema
|
||||
from .param import TicketQueryParam
|
||||
|
||||
|
||||
class TicketService:
|
||||
"""工单模块服务层"""
|
||||
|
||||
@classmethod
|
||||
async def get_ticket_detail_service(cls, auth: AuthSchema, id: int) -> Dict:
|
||||
"""获取工单详情"""
|
||||
obj = await TicketCRUD(auth).get_by_id_crud(id=id)
|
||||
return TicketOutSchema.model_validate(obj).model_dump()
|
||||
|
||||
@classmethod
|
||||
async def get_ticket_list_service(cls, auth: AuthSchema, search: Optional[TicketQueryParam] = None, order_by: Optional[Union[str, List[Dict[str, str]]]] = None) -> List[Dict]:
|
||||
"""获取工单列表"""
|
||||
# 处理排序参数
|
||||
processed_order_by = None
|
||||
if order_by:
|
||||
if isinstance(order_by, str):
|
||||
processed_order_by = eval(order_by)
|
||||
else:
|
||||
processed_order_by = order_by
|
||||
|
||||
obj_list = await TicketCRUD(auth).get_list_crud(search=search.__dict__ if search else None, order_by=processed_order_by)
|
||||
return [TicketOutSchema.model_validate(obj).model_dump() for obj in obj_list]
|
||||
|
||||
@classmethod
|
||||
async def create_ticket_service(cls, auth: AuthSchema, data: TicketCreateSchema) -> Dict:
|
||||
"""创建工单"""
|
||||
obj = await TicketCRUD(auth).create_crud(data=data)
|
||||
return TicketOutSchema.model_validate(obj).model_dump()
|
||||
|
||||
@classmethod
|
||||
async def update_ticket_service(cls, auth: AuthSchema, id: int, data: TicketUpdateSchema) -> Dict:
|
||||
"""更新工单"""
|
||||
# 检查工单是否存在
|
||||
obj = await TicketCRUD(auth).get_by_id_crud(id=id)
|
||||
if not obj:
|
||||
raise CustomException(msg='更新失败,该工单不存在')
|
||||
|
||||
obj = await TicketCRUD(auth).update_crud(id=id, data=data)
|
||||
return TicketOutSchema.model_validate(obj).model_dump()
|
||||
|
||||
@classmethod
|
||||
async def delete_ticket_service(cls, auth: AuthSchema, ids: List[int]) -> None:
|
||||
"""删除工单"""
|
||||
if len(ids) < 1:
|
||||
raise CustomException(msg='删除失败,删除对象不能为空')
|
||||
for id in ids:
|
||||
obj = await TicketCRUD(auth).get_by_id_crud(id=id)
|
||||
if not obj:
|
||||
raise CustomException(msg='删除失败,该工单不存在')
|
||||
await TicketCRUD(auth).delete_crud(ids=ids)
|
||||
Reference in New Issue
Block a user