init: 初始化 dpb 桃育种系统代码库

前后端 + 后端 FastAPI 全量源码、部署脚本与文档。
This commit is contained in:
34047007@qq.com
2026-08-06 00:17:49 +08:00
commit b95053c52c
1469 changed files with 322298 additions and 0 deletions
@@ -0,0 +1,100 @@
from typing import Annotated
from fastapi import APIRouter, Body, Depends, Path, Query, Security, status
from fastapi.responses import JSONResponse
from sqlalchemy.ext.asyncio import AsyncSession
from app.common.response import ResponseSchema, SuccessResponse
from app.core.base_schema import AuthSchema, PageResultSchema, PaginationQueryParam
from app.core.dependencies import AuthPermission, db_getter
from app.core.router_class import OperationLogRoute
from .schema import (
VersionCreateSchema,
VersionOutSchema,
VersionQueryParam,
VersionStatusSchema,
VersionUpdateSchema,
)
from .service import VersionService
VersionRouter = APIRouter(route_class=OperationLogRoute, prefix="/versions", tags=["版本管理"])
@VersionRouter.get("/list", summary="分页查询版本", response_model=ResponseSchema[PageResultSchema[VersionOutSchema]])
async def get_version_list_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:query"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
page: Annotated[PaginationQueryParam, Depends()],
search: Annotated[VersionQueryParam, Query()],
) -> JSONResponse:
service = VersionService(auth, db)
result = await service.page(page_no=page.page_no, page_size=page.page_size, search=search)
return SuccessResponse(data=result, msg="查询版本列表成功")
@VersionRouter.get("/published", summary="已发布版本列表", response_model=ResponseSchema[list[VersionOutSchema]])
async def get_published_versions_controller(
db: Annotated[AsyncSession, Depends(db_getter)],
) -> JSONResponse:
auth = AuthSchema()
service = VersionService(auth, db)
result = await service.get_published()
return SuccessResponse(data=result, msg="查询成功")
@VersionRouter.get("/detail/{id}", summary="获取版本详情", response_model=ResponseSchema[VersionOutSchema])
async def get_version_detail_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:detail"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
id: Annotated[int, Path(description="版本ID")],
) -> JSONResponse:
service = VersionService(auth, db)
result = await service.detail(id=id)
return SuccessResponse(data=result, msg="获取版本详情成功")
@VersionRouter.post("/create", status_code=status.HTTP_201_CREATED, summary="创建版本", response_model=ResponseSchema[VersionOutSchema])
async def create_version_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:create"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
data: Annotated[VersionCreateSchema, Body(description="创建参数")],
) -> JSONResponse:
service = VersionService(auth, db)
result = await service.create(data=data)
return SuccessResponse(data=result, msg="创建版本成功")
@VersionRouter.put("/update/{id}", summary="修改版本", response_model=ResponseSchema[VersionOutSchema])
async def update_version_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:update"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
id: Annotated[int, Path(description="版本ID")],
data: Annotated[VersionUpdateSchema, Body(description="修改参数")],
) -> JSONResponse:
service = VersionService(auth, db)
result = await service.update(id=id, data=data)
return SuccessResponse(data=result, msg="修改版本成功")
@VersionRouter.delete("/delete", summary="删除版本", response_model=ResponseSchema[None])
async def delete_version_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:delete"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
ids: Annotated[list[int], Body(description="ID列表")],
) -> JSONResponse:
service = VersionService(auth, db)
await service.delete(ids=ids)
return SuccessResponse(msg="删除版本成功")
@VersionRouter.put("/{id}/status", summary="变更版本状态", response_model=ResponseSchema[VersionOutSchema])
async def set_version_status_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:version:update"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
id: Annotated[int, Path(description="版本ID")],
data: Annotated[VersionStatusSchema, Body(description="状态参数")],
) -> JSONResponse:
service = VersionService(auth, db)
result = await service.set_status(id=id, data=data)
return SuccessResponse(data=result, msg="状态变更成功")
@@ -0,0 +1,25 @@
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.base_crud import CRUDBase
from app.core.base_schema import AuthSchema
from app.core.exceptions import CustomException
from .model import VersionModel
from .schema import VersionCreateSchema, VersionUpdateSchema
class VersionCRUD(CRUDBase[VersionModel, VersionCreateSchema, VersionUpdateSchema]):
"""版本数据层"""
def __init__(self, auth: AuthSchema, db: AsyncSession) -> None:
super().__init__(model=VersionModel, auth=auth, db=db)
async def set_status(self, id: int, status: int) -> VersionModel:
"""更新版本状态"""
obj = await self.get(id=id)
if not obj:
raise CustomException(msg="版本不存在")
obj.status = status
await self.db.flush()
await self.db.refresh(obj)
return obj
@@ -0,0 +1,20 @@
from sqlalchemy import Boolean, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.base_model import ModelMixin, UserMixin
class VersionModel(ModelMixin, UserMixin):
"""版本管理(平台级)"""
__tablename__: str = "sys_version"
__table_args__: dict[str, str] = {"comment": "版本管理表"}
version: Mapped[str] = mapped_column(String(32), nullable=False, unique=True, comment="版本号")
title: Mapped[str] = mapped_column(String(200), nullable=False, comment="版本标题")
date: Mapped[str] = mapped_column(String(50), nullable=False, comment="发布日期")
content: Mapped[str | None] = mapped_column(Text, nullable=True, default=None, comment="版本富文本内容")
sort: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="排序")
status: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="状态: 0=草稿,1=已发布,2=已回滚")
description: Mapped[str | None] = mapped_column(String(500), nullable=True, default=None, comment="备注")
require_re_login: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False, comment="是否需要重新登录")
@@ -0,0 +1,50 @@
from pydantic import BaseModel, ConfigDict, Field, field_validator
from app.core.base_schema import BaseQueryParam
from app.core.validator import DateTimeStr
class VersionCreateSchema(BaseModel):
"""版本创建模型"""
version: str = Field(..., description="版本号")
title: str = Field(..., description="更新标题")
date: str = Field(..., description="发布日期")
content: str | None = Field(default=None, description="更新内容(富文本HTML)")
description: str | None = Field(default=None, description="备注")
sort: int = Field(default=0, description="排序")
status: int = Field(default=0, description="状态: 0=草稿,1=已发布,2=已回滚")
require_re_login: bool = Field(default=False, description="是否需要重新登录")
class VersionUpdateSchema(VersionCreateSchema):
"""版本更新模型"""
class VersionOutSchema(VersionCreateSchema):
"""版本响应模型"""
model_config = ConfigDict(from_attributes=True)
id: int = Field(description="主键ID")
created_time: DateTimeStr | None = Field(default=None, description="创建时间")
updated_time: DateTimeStr | None = Field(default=None, description="更新时间")
class VersionStatusSchema(BaseModel):
"""版本状态更新模型"""
status: int = Field(..., description="状态: 0=草稿,1=已发布,2=已回滚")
@field_validator("status")
@classmethod
def validate_status(cls, v: int) -> int:
if v not in (0, 1, 2):
raise ValueError("status must be 0, 1, or 2")
return v
class VersionQueryParam(BaseQueryParam):
"""版本查询参数"""
status: int | None = Field(default=None, description="状态: 0=草稿,1=已发布,2=已回滚", json_schema_extra={"q": "eq"})
@@ -0,0 +1,76 @@
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.base_schema import AuthSchema, PageResultSchema
from app.core.exceptions import CustomException
from app.utils.common_util import search_to_dict
from .crud import VersionCRUD
from .schema import (
VersionCreateSchema,
VersionOutSchema,
VersionQueryParam,
VersionStatusSchema,
VersionUpdateSchema,
)
class VersionService:
"""版本管理模块服务层"""
def __init__(self, auth: AuthSchema, db: AsyncSession) -> None:
self.auth = auth
self.db = db
async def detail(self, id: int) -> VersionOutSchema:
obj = await VersionCRUD(self.auth, self.db).get(id=id)
if not obj:
raise CustomException(msg="该数据不存在")
return VersionOutSchema.model_validate(obj)
async def page(
self,
page_no: int,
page_size: int,
search: VersionQueryParam | None = None,
order_by: list[dict[str, str]] | None = None,
) -> PageResultSchema[VersionOutSchema]:
offset = (page_no - 1) * page_size
return await VersionCRUD(self.auth, self.db).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"sort": "asc"}, {"id": "desc"}],
search=search_to_dict(search, {}),
out_schema=VersionOutSchema,
)
async def create(self, data: VersionCreateSchema) -> VersionOutSchema:
obj = await VersionCRUD(self.auth, self.db).create(data=data)
return VersionOutSchema.model_validate(obj)
async def update(self, id: int, data: VersionUpdateSchema) -> VersionOutSchema:
obj = await VersionCRUD(self.auth, self.db).get(id=id)
if not obj:
raise CustomException(msg="更新失败,该数据不存在")
obj = await VersionCRUD(self.auth, self.db).update(id=id, data=data)
return VersionOutSchema.model_validate(obj)
async def delete(self, ids: list[int]) -> None:
if not ids:
raise CustomException(msg="删除失败,删除对象不能为空")
objs = await VersionCRUD(self.auth, self.db).get_list(search={"id": ("in", ids)})
obj_map = {o.id: o for o in objs}
for id_ in ids:
if id_ not in obj_map:
raise CustomException(msg="删除失败,该数据不存在")
await VersionCRUD(self.auth, self.db).delete(ids=ids)
async def set_status(self, id: int, data: VersionStatusSchema) -> VersionOutSchema:
obj = await VersionCRUD(self.auth, self.db).set_status(id=id, status=data.status)
return VersionOutSchema.model_validate(obj)
async def get_published(self) -> list[VersionOutSchema]:
objs = await VersionCRUD(self.auth, self.db).get_list(
search={"status": ("eq", 1)},
order_by=[{"sort": "asc"}],
)
return [VersionOutSchema.model_validate(obj) for obj in objs]