feat(api): 添加Ticket和Version模块路由

- 引入TicketRouter和VersionRouter
- 将TicketRouter和VersionRouter加入SYSTEM_MODULES路由列表
- 移除未使用的ResourceRouter导入声明
This commit is contained in:
zhangtao
2025-09-15 08:22:56 +08:00
parent 02fefc7aae
commit 046957654a
13 changed files with 416 additions and 2 deletions
+4 -2
View File
@@ -12,6 +12,8 @@ from .module_system.position.controller import PositionRouter
from .module_system.notice.controller import NoticeRouter
from .module_system.params.controller import ParamsRouter
from .module_system.dict.controller import DictRouter
from .module_system.ticket.controller import router as TicketRouter
from .module_system.version.controller import router as VersionRouter
from .module_monitor.cache.controller import CacheRouter
from .module_monitor.job.controller import JobRouter
@@ -28,8 +30,6 @@ from .module_application.myapp.controller import MyAppRouter
from .module_ai.mcp.controller import MCPRouter
from .module_resource.resource.controller import ResourceRouter
# 定义路由模块映射,按模块分组
SYSTEM_MODULES = [
@@ -43,6 +43,8 @@ SYSTEM_MODULES = [
{"router": NoticeRouter},
{"router": ParamsRouter},
{"router": DictRouter},
{"router": TicketRouter},
{"router": VersionRouter},
]
MONITOR_MODULES = [
@@ -0,0 +1 @@
# 工单管理模块
@@ -0,0 +1,58 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.api.v1.module_system.ticket.schema import TicketCreate, TicketUpdate, TicketOut
from app.api.v1.module_system.ticket.service import ticket_service
from app.core.database import get_db
router = APIRouter(prefix="/tickets", tags=["工单管理"])
@router.post("/", response_model=TicketOut)
def create_ticket(ticket: TicketCreate, db: Session = Depends(get_db)):
"""创建工单"""
return ticket_service.create_ticket(db, ticket)
@router.get("/{ticket_id}", response_model=TicketOut)
def get_ticket(ticket_id: int, db: Session = Depends(get_db)):
"""获取工单详情"""
db_ticket = ticket_service.get_ticket(db, ticket_id)
if db_ticket is None:
raise HTTPException(status_code=404, detail="工单不存在")
return db_ticket
@router.get("/", response_model=list[TicketOut])
def get_tickets(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
"""获取工单列表"""
return ticket_service.get_tickets(db, skip=skip, limit=limit)
@router.put("/{ticket_id}", response_model=TicketOut)
def update_ticket(ticket_id: int, ticket: TicketUpdate, db: Session = Depends(get_db)):
"""更新工单"""
db_ticket = ticket_service.update_ticket(db, ticket_id, ticket)
if db_ticket is None:
raise HTTPException(status_code=404, detail="工单不存在")
return db_ticket
@router.delete("/{ticket_id}", response_model=TicketOut)
def delete_ticket(ticket_id: int, db: Session = Depends(get_db)):
"""删除工单"""
db_ticket = ticket_service.get_ticket(db, ticket_id)
if db_ticket is None:
raise HTTPException(status_code=404, detail="工单不存在")
return ticket_service.delete_ticket(db, ticket_id)
@router.get("/status/{status}", response_model=list[TicketOut])
def get_tickets_by_status(status: str, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
"""根据状态获取工单列表"""
return ticket_service.get_tickets_by_status(db, status=status, skip=skip, limit=limit)
@router.get("/assignee/{assignee_id}", response_model=list[TicketOut])
def get_tickets_by_assignee(assignee_id: int, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
"""根据指派用户获取工单列表"""
return ticket_service.get_tickets_by_assignee(db, assignee_id=assignee_id, skip=skip, limit=limit)
@@ -0,0 +1,28 @@
from sqlalchemy.orm import Session
from typing import List
from app.api.v1.module_system.ticket.model import Ticket
from app.api.v1.module_system.ticket.schema import TicketCreate, TicketUpdate
from app.core.base_crud import CRUDBase
class CRUDTicket(CRUDBase[Ticket, TicketCreate, TicketUpdate]):
"""工单 CRUD 操作"""
def get_ticket_by_id(self, db: Session, ticket_id: int) -> Ticket:
"""根据ID获取工单"""
return db.query(self.model).filter(self.model.id == ticket_id).first()
def get_tickets(self, db: Session, skip: int = 0, limit: int = 100) -> List[Ticket]:
"""获取工单列表"""
return db.query(self.model).offset(skip).limit(limit).all()
def get_tickets_by_status(self, db: Session, status: str, skip: int = 0, limit: int = 100) -> List[Ticket]:
"""根据状态获取工单列表"""
return db.query(self.model).filter(self.model.status == status).offset(skip).limit(limit).all()
def get_tickets_by_assignee(self, db: Session, assignee_id: int, skip: int = 0, limit: int = 100) -> List[Ticket]:
"""根据指派用户获取工单列表"""
return db.query(self.model).filter(self.model.assignee_id == assignee_id).offset(skip).limit(limit).all()
ticket_crud = CRUDTicket(Ticket)
@@ -0,0 +1,30 @@
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from app.core.base_model import BaseModel
from app.api.v1.module_system.user.model import User
from datetime import datetime
class Ticket(BaseModel):
"""工单模型"""
__tablename__ = "ticket"
id = Column(Integer, primary_key=True, index=True, comment="工单ID")
title = Column(String(255), nullable=False, comment="工单标题")
status = Column(String(50), default="open", comment="工单状态(open, in_progress, resolved, closed)")
priority = Column(String(50), default="medium", comment="优先级(low, medium, high, urgent)")
type = Column(String(50), comment="工单类型(bug, feature, task)")
assignee_id = Column(Integer, ForeignKey("system_user.id"), comment="指派给用户ID")
reporter_id = Column(Integer, ForeignKey("system_user.id"), comment="报告人ID")
project = Column(String(100), comment="所属项目")
version = Column(String(50), comment="版本号")
description = Column(Text, comment="工单描述")
created_at = Column(DateTime, default=datetime.now, comment="创建时间")
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment="更新时间")
# 关系
assignee = relationship("User", foreign_keys=[assignee_id])
reporter = relationship("User", foreign_keys=[reporter_id])
@@ -0,0 +1,47 @@
from pydantic import BaseModel
from typing import Optional, List
from datetime import datetime
class TicketCreate(BaseModel):
"""创建工单"""
title: str
description: Optional[str] = None
status: Optional[str] = "open"
priority: Optional[str] = "medium"
type: Optional[str] = "bug"
assignee_id: Optional[int] = None
reporter_id: int
project: Optional[str] = None
version: Optional[str] = None
class TicketUpdate(BaseModel):
"""更新工单"""
title: Optional[str] = None
description: Optional[str] = None
status: Optional[str] = None
priority: Optional[str] = None
type: Optional[str] = None
assignee_id: Optional[int] = None
project: Optional[str] = None
version: Optional[str] = None
class TicketOut(BaseModel):
"""工单输出"""
id: int
title: str
description: Optional[str] = None
status: str
priority: str
type: str
assignee_id: Optional[int] = None
reporter_id: int
project: Optional[str] = None
version: Optional[str] = None
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
@@ -0,0 +1,48 @@
from sqlalchemy.orm import Session
from app.api.v1.module_system.ticket.crud import ticket_crud
from app.api.v1.module_system.ticket.schema import TicketCreate, TicketUpdate
class TicketService:
"""工单服务类"""
@staticmethod
def create_ticket(db: Session, ticket_create: TicketCreate):
"""创建工单"""
return ticket_crud.create(db, obj_in=ticket_create)
@staticmethod
def get_ticket(db: Session, ticket_id: int):
"""获取工单"""
return ticket_crud.get(db, id=ticket_id)
@staticmethod
def get_tickets(db: Session, skip: int = 0, limit: int = 100):
"""获取工单列表"""
return ticket_crud.get_multi(db, skip=skip, limit=limit)
@staticmethod
def update_ticket(db: Session, ticket_id: int, ticket_update: TicketUpdate):
"""更新工单"""
db_ticket = ticket_crud.get(db, id=ticket_id)
if db_ticket:
return ticket_crud.update(db, db_obj=db_ticket, obj_in=ticket_update)
return None
@staticmethod
def delete_ticket(db: Session, ticket_id: int):
"""删除工单"""
return ticket_crud.remove(db, id=ticket_id)
@staticmethod
def get_tickets_by_status(db: Session, status: str, skip: int = 0, limit: int = 100):
"""根据状态获取工单列表"""
return ticket_crud.get_tickets_by_status(db, status=status, skip=skip, limit=limit)
@staticmethod
def get_tickets_by_assignee(db: Session, assignee_id: int, skip: int = 0, limit: int = 100):
"""根据指派用户获取工单列表"""
return ticket_crud.get_tickets_by_assignee(db, assignee_id=assignee_id, skip=skip, limit=limit)
ticket_service = TicketService()
@@ -0,0 +1 @@
# 版本管理模块
@@ -0,0 +1,61 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.api.v1.module_system.version.schema import VersionCreate, VersionUpdate, VersionOut
from app.api.v1.module_system.version.service import version_service
from app.core.database import get_db
router = APIRouter(prefix="/versions", tags=["版本管理"])
@router.post("/", response_model=VersionOut)
def create_version(version: VersionCreate, db: Session = Depends(get_db)):
"""创建版本"""
return version_service.create_version(db, version)
@router.get("/{version_id}", response_model=VersionOut)
def get_version(version_id: int, db: Session = Depends(get_db)):
"""获取版本详情"""
db_version = version_service.get_version(db, version_id)
if db_version is None:
raise HTTPException(status_code=404, detail="版本不存在")
return db_version
@router.get("/", response_model=list[VersionOut])
def get_versions(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
"""获取版本列表"""
return version_service.get_versions(db, skip=skip, limit=limit)
@router.put("/{version_id}", response_model=VersionOut)
def update_version(version_id: int, version: VersionUpdate, db: Session = Depends(get_db)):
"""更新版本"""
db_version = version_service.update_version(db, version_id, version)
if db_version is None:
raise HTTPException(status_code=404, detail="版本不存在")
return db_version
@router.delete("/{version_id}", response_model=VersionOut)
def delete_version(version_id: int, db: Session = Depends(get_db)):
"""删除版本"""
db_version = version_service.get_version(db, version_id)
if db_version is None:
raise HTTPException(status_code=404, detail="版本不存在")
return version_service.delete_version(db, version_id)
@router.get("/number/{version_number}", response_model=VersionOut)
def get_version_by_number(version_number: str, db: Session = Depends(get_db)):
"""根据版本号获取版本"""
db_version = version_service.get_version_by_number(db, version_number)
if db_version is None:
raise HTTPException(status_code=404, detail="版本不存在")
return db_version
@router.get("/status/{status}", response_model=list[VersionOut])
def get_versions_by_status(status: str, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
"""根据状态获取版本列表"""
return version_service.get_versions_by_status(db, status=status, skip=skip, limit=limit)
@@ -0,0 +1,28 @@
from sqlalchemy.orm import Session
from typing import List
from app.api.v1.module_system.version.model import Version
from app.api.v1.module_system.version.schema import VersionCreate, VersionUpdate
from app.core.base_crud import CRUDBase
class CRUDVersion(CRUDBase[Version, VersionCreate, VersionUpdate]):
"""版本 CRUD 操作"""
def get_version_by_id(self, db: Session, version_id: int) -> Version:
"""根据ID获取版本"""
return db.query(self.model).filter(self.model.id == version_id).first()
def get_versions(self, db: Session, skip: int = 0, limit: int = 100) -> List[Version]:
"""获取版本列表"""
return db.query(self.model).offset(skip).limit(limit).all()
def get_version_by_number(self, db: Session, version_number: str) -> Version:
"""根据版本号获取版本"""
return db.query(self.model).filter(self.model.version_number == version_number).first()
def get_versions_by_status(self, db: Session, status: str, skip: int = 0, limit: int = 100) -> List[Version]:
"""根据状态获取版本列表"""
return db.query(self.model).filter(self.model.status == status).offset(skip).limit(limit).all()
version_crud = CRUDVersion(Version)
@@ -0,0 +1,20 @@
from sqlalchemy import Column, Integer, String, Text, DateTime
from app.core.base_model import BaseModel
from datetime import datetime
class Version(BaseModel):
"""版本模型"""
__tablename__ = "version"
id = Column(Integer, primary_key=True, index=True, comment="版本ID")
version_number = Column(String(50), nullable=False, comment="版本号")
title = Column(String(255), nullable=False, comment="版本标题")
release_notes = Column(Text, comment="发布说明")
status = Column(String(50), default="draft", comment="版本状态(draft, released, archived)")
project = Column(String(100), comment="所属项目")
released_at = Column(DateTime, comment="发布时间")
description = Column(Text, comment="版本描述")
created_at = Column(DateTime, default=datetime.now, comment="创建时间")
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment="更新时间")
@@ -0,0 +1,42 @@
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
class VersionCreate(BaseModel):
"""创建版本"""
version_number: str
title: str
description: Optional[str] = None
release_notes: Optional[str] = None
status: Optional[str] = "draft"
project: Optional[str] = None
released_at: Optional[datetime] = None
class VersionUpdate(BaseModel):
"""更新版本"""
version_number: Optional[str] = None
title: Optional[str] = None
description: Optional[str] = None
release_notes: Optional[str] = None
status: Optional[str] = None
project: Optional[str] = None
released_at: Optional[datetime] = None
class VersionOut(BaseModel):
"""版本输出"""
id: int
version_number: str
title: str
description: Optional[str] = None
release_notes: Optional[str] = None
status: str
project: Optional[str] = None
released_at: Optional[datetime] = None
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
@@ -0,0 +1,48 @@
from sqlalchemy.orm import Session
from app.api.v1.module_system.version.crud import version_crud
from app.api.v1.module_system.version.schema import VersionCreate, VersionUpdate
class VersionService:
"""版本服务类"""
@staticmethod
def create_version(db: Session, version_create: VersionCreate):
"""创建版本"""
return version_crud.create(db, obj_in=version_create)
@staticmethod
def get_version(db: Session, version_id: int):
"""获取版本"""
return version_crud.get(db, id=version_id)
@staticmethod
def get_versions(db: Session, skip: int = 0, limit: int = 100):
"""获取版本列表"""
return version_crud.get_multi(db, skip=skip, limit=limit)
@staticmethod
def update_version(db: Session, version_id: int, version_update: VersionUpdate):
"""更新版本"""
db_version = version_crud.get(db, id=version_id)
if db_version:
return version_crud.update(db, db_obj=db_version, obj_in=version_update)
return None
@staticmethod
def delete_version(db: Session, version_id: int):
"""删除版本"""
return version_crud.remove(db, id=version_id)
@staticmethod
def get_version_by_number(db: Session, version_number: str):
"""根据版本号获取版本"""
return version_crud.get_version_by_number(db, version_number=version_number)
@staticmethod
def get_versions_by_status(db: Session, status: str, skip: int = 0, limit: int = 100):
"""根据状态获取版本列表"""
return version_crud.get_versions_by_status(db, status=status, skip=skip, limit=limit)
version_service = VersionService()