From 3f961146ed39ff9ea4890817c3ab8c1634d418b6 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Wed, 8 Jul 2026 11:06:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E8=83=BD=E6=BA=90?= =?UTF-8?q?=E6=8A=A5=E5=91=8A=E6=A8=A1=E6=9D=BF=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/v1/module_common/file/controller.py | 16 ++- app/api/v1/module_common/file/schema.py | 14 ++- app/api/v1/module_energy/__init__.py | 8 ++ .../module_energy/report_template/__init__.py | 1 + .../report_template/controller.py | 93 +++++++++++++++ .../v1/module_energy/report_template/crud.py | 13 ++ .../v1/module_energy/report_template/model.py | 35 ++++++ .../module_energy/report_template/schema.py | 72 +++++++++++ .../module_energy/report_template/service.py | 112 ++++++++++++++++++ .../v1/module_monitor/resource/controller.py | 7 +- app/api/v1/module_rule/rule/controller.py | 33 +++++- app/api/v1/module_rule/rule/service.py | 10 +- app/init_app.py | 2 + app/scripts/initialize.py | 2 + 14 files changed, 409 insertions(+), 9 deletions(-) create mode 100644 app/api/v1/module_energy/__init__.py create mode 100644 app/api/v1/module_energy/report_template/__init__.py create mode 100644 app/api/v1/module_energy/report_template/controller.py create mode 100644 app/api/v1/module_energy/report_template/crud.py create mode 100644 app/api/v1/module_energy/report_template/model.py create mode 100644 app/api/v1/module_energy/report_template/schema.py create mode 100644 app/api/v1/module_energy/report_template/service.py diff --git a/app/api/v1/module_common/file/controller.py b/app/api/v1/module_common/file/controller.py index 8dc57d6..d46f147 100644 --- a/app/api/v1/module_common/file/controller.py +++ b/app/api/v1/module_common/file/controller.py @@ -21,7 +21,7 @@ from app.core.dependencies import AuthPermission from app.core.router_class import OperationLogRoute from app.utils.upload_util import UploadUtil -from .schema import FileOutSchema, FileQueryParam +from .schema import FileOutSchema, FileQueryParam, FileUploadOutSchema from .service import FileService FileRouter = APIRouter(route_class=OperationLogRoute, prefix="/file", tags=["文件管理"]) @@ -63,7 +63,7 @@ async def get_file_detail_controller( @FileRouter.post( "/upload", summary="上传文件", - response_model=ResponseSchema[FileOutSchema], + response_model=ResponseSchema[FileUploadOutSchema], ) async def upload_controller( file: UploadFile, @@ -86,7 +86,17 @@ async def upload_controller( business_type=business_type, business_id=business_id, ) - return SuccessResponse(data=result, msg="上传文件成功") + return SuccessResponse( + data=FileUploadOutSchema( + id=result.id, + original_name=result.original_name, + file_name=result.file_name, + file_ext=result.file_ext, + file_size=result.file_size, + file_url=result.file_url, + ), + msg="上传文件成功", + ) @FileRouter.get( diff --git a/app/api/v1/module_common/file/schema.py b/app/api/v1/module_common/file/schema.py index e6a1838..bd42204 100644 --- a/app/api/v1/module_common/file/schema.py +++ b/app/api/v1/module_common/file/schema.py @@ -38,6 +38,19 @@ class FileOutSchema(FileCreateSchema, BaseSchema, UserBySchema, TenantBySchema): origin_name: str | None = Field(default=None, description="兼容旧接口的原始文件名") +class FileUploadOutSchema(BaseModel): + """文件上传精简响应模型。""" + + model_config = ConfigDict(from_attributes=True) + + id: int = Field(description="文件记录ID") + original_name: str = Field(description="原始文件名") + file_name: str = Field(description="存储文件名") + file_ext: str | None = Field(default=None, description="文件扩展名") + file_size: int = Field(default=0, description="文件大小,单位字节") + file_url: str | None = Field(default=None, description="文件访问地址") + + @dataclass class FileQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam): """文件记录查询参数。""" @@ -65,4 +78,3 @@ class FileQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam): self.business_type = (QueueEnum.eq.value, self.business_type) if isinstance(self.business_id, int): self.business_id = (QueueEnum.eq.value, self.business_id) - diff --git a/app/api/v1/module_energy/__init__.py b/app/api/v1/module_energy/__init__.py new file mode 100644 index 0000000..c792d77 --- /dev/null +++ b/app/api/v1/module_energy/__init__.py @@ -0,0 +1,8 @@ +from fastapi import APIRouter + +from app.api.v1.module_energy.report_template.controller import EnergyReportTemplateRouter + +energy_router = APIRouter() + +energy_router.include_router(EnergyReportTemplateRouter) + diff --git a/app/api/v1/module_energy/report_template/__init__.py b/app/api/v1/module_energy/report_template/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/api/v1/module_energy/report_template/__init__.py @@ -0,0 +1 @@ + diff --git a/app/api/v1/module_energy/report_template/controller.py b/app/api/v1/module_energy/report_template/controller.py new file mode 100644 index 0000000..5cf507b --- /dev/null +++ b/app/api/v1/module_energy/report_template/controller.py @@ -0,0 +1,93 @@ +from typing import Annotated + +from fastapi import APIRouter, Body, Depends, Path +from fastapi.responses import JSONResponse + +from app.common.response import ResponseSchema, SuccessResponse +from app.core.base_params import PaginationQueryParam +from app.core.base_schema import AuthSchema, PageResultSchema +from app.core.dependencies import AuthPermission +from app.core.router_class import OperationLogRoute + +from .schema import ( + EnergyReportTemplateCreateSchema, + EnergyReportTemplateOutSchema, + EnergyReportTemplateQueryParam, + EnergyReportTemplateUpdateSchema, +) +from .service import EnergyReportTemplateService + +EnergyReportTemplateRouter = APIRouter(route_class=OperationLogRoute, prefix="/attachment-template", tags=["能源报告模板"]) + + +@EnergyReportTemplateRouter.get( + "/list", + summary="查询能源报告模板列表", + response_model=ResponseSchema[PageResultSchema[EnergyReportTemplateOutSchema]], +) +async def get_energy_report_template_list_controller( + page: Annotated[PaginationQueryParam, Depends()], + search: Annotated[EnergyReportTemplateQueryParam, Depends()], + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_energy:attachment_template:query"]))], +) -> JSONResponse: + result = await EnergyReportTemplateService(auth).page( + page_no=page.page_no, + page_size=page.page_size, + search=search, + order_by=page.order_by or [{"order": "asc"}, {"id": "desc"}], + ) + return SuccessResponse(data=result, msg="查询能源报告模板列表成功") + + +@EnergyReportTemplateRouter.get( + "/detail/{id}", + summary="查询能源报告模板详情", + response_model=ResponseSchema[EnergyReportTemplateOutSchema], +) +async def get_energy_report_template_detail_controller( + id: Annotated[int, Path(description="能源报告模板ID")], + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_energy:attachment_template:detail"]))], +) -> JSONResponse: + result = await EnergyReportTemplateService(auth).detail(id=id) + return SuccessResponse(data=result, msg="查询能源报告模板详情成功") + + +@EnergyReportTemplateRouter.post( + "/create", + summary="创建能源报告模板", + response_model=ResponseSchema[EnergyReportTemplateOutSchema], +) +async def create_energy_report_template_controller( + data: EnergyReportTemplateCreateSchema, + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_energy:attachment_template:create"]))], +) -> JSONResponse: + result = await EnergyReportTemplateService(auth).create(data=data) + return SuccessResponse(data=result, msg="创建能源报告模板成功") + + +@EnergyReportTemplateRouter.put( + "/update/{id}", + summary="修改能源报告模板", + response_model=ResponseSchema[EnergyReportTemplateOutSchema], +) +async def update_energy_report_template_controller( + data: EnergyReportTemplateUpdateSchema, + id: Annotated[int, Path(description="能源报告模板ID")], + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_energy:attachment_template:update"]))], +) -> JSONResponse: + result = await EnergyReportTemplateService(auth).update(id=id, data=data) + return SuccessResponse(data=result, msg="修改能源报告模板成功") + + +@EnergyReportTemplateRouter.delete( + "/delete", + summary="删除能源报告模板", + response_model=ResponseSchema[None], +) +async def delete_energy_report_template_controller( + ids: Annotated[list[int], Body(description="ID列表")], + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_energy:attachment_template:delete"]))], +) -> JSONResponse: + await EnergyReportTemplateService(auth).delete(ids=ids) + return SuccessResponse(msg="删除能源报告模板成功") + diff --git a/app/api/v1/module_energy/report_template/crud.py b/app/api/v1/module_energy/report_template/crud.py new file mode 100644 index 0000000..950718b --- /dev/null +++ b/app/api/v1/module_energy/report_template/crud.py @@ -0,0 +1,13 @@ +from app.core.base_crud import CRUDBase +from app.core.base_schema import AuthSchema + +from .model import EnergyReportTemplateModel +from .schema import EnergyReportTemplateCreateSchema, EnergyReportTemplateUpdateSchema + + +class EnergyReportTemplateCRUD(CRUDBase[EnergyReportTemplateModel, EnergyReportTemplateCreateSchema, EnergyReportTemplateUpdateSchema]): + """能源报告模板数据层。""" + + def __init__(self, auth: AuthSchema) -> None: + super().__init__(model=EnergyReportTemplateModel, auth=auth) + diff --git a/app/api/v1/module_energy/report_template/model.py b/app/api/v1/module_energy/report_template/model.py new file mode 100644 index 0000000..07df493 --- /dev/null +++ b/app/api/v1/module_energy/report_template/model.py @@ -0,0 +1,35 @@ +from sqlalchemy import ForeignKey, Integer, String, Text, UniqueConstraint +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from app.core.base_model import ModelMixin, TenantMixin, UserMixin + + +class EnergyReportTemplateModel(ModelMixin, TenantMixin, UserMixin): + """能源报告模板模型。""" + + __tablename__: str = "energy_report_template" + __table_args__ = (UniqueConstraint("tenant_id", "template_name"), {"comment": "能源报告模板表"}) + __loader_options__: list[str] = [ + "file", + "created_by", + "updated_by", + "deleted_by", + "tenant_by", + ] + + template_name: Mapped[str] = mapped_column(String(128), nullable=False, comment="模板名称", index=True) + template_type: Mapped[str] = mapped_column(String(64), nullable=False, comment="模板类型", index=True) + version: Mapped[str | None] = mapped_column(String(32), default=None, nullable=True, comment="模板版本") + file_id: Mapped[int] = mapped_column( + Integer, + ForeignKey("common_file.id", ondelete="RESTRICT", onupdate="CASCADE"), + nullable=False, + index=True, + comment="文件记录ID", + ) + status: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="状态 0:启用 1:停用", index=True) + order: Mapped[int] = mapped_column(Integer, default=999, nullable=False, comment="显示排序") + description: Mapped[str | None] = mapped_column(Text, default=None, nullable=True, comment="描述") + + file = relationship("FileModel", lazy="selectin", foreign_keys=[file_id], uselist=False) + diff --git a/app/api/v1/module_energy/report_template/schema.py b/app/api/v1/module_energy/report_template/schema.py new file mode 100644 index 0000000..5ba9434 --- /dev/null +++ b/app/api/v1/module_energy/report_template/schema.py @@ -0,0 +1,72 @@ +from dataclasses import dataclass + +from fastapi import Query +from pydantic import BaseModel, ConfigDict, Field, field_validator + +from app.api.v1.module_common.file.schema import FileOutSchema +from app.common.enums import QueueEnum +from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam +from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema + + +class EnergyReportTemplateCreateSchema(BaseModel): + """能源报告模板创建模型。""" + + template_name: str = Field(..., min_length=1, max_length=128, description="模板名称") + template_type: str = Field(..., min_length=1, max_length=64, description="模板类型") + version: str | None = Field(default=None, max_length=32, description="模板版本") + file_id: int = Field(..., ge=1, description="文件记录ID") + status: int = Field(default=0, ge=0, le=1, description="状态 0:启用 1:停用") + order: int = Field(default=999, ge=0, description="显示排序") + description: str | None = Field(default=None, max_length=500, description="描述") + + @field_validator("template_name", "template_type") + @classmethod + def validate_required_text(cls, value: str) -> str: + value = value.strip() + if not value: + raise ValueError("必填字段不能为空") + return value + + @field_validator("status") + @classmethod + def validate_status(cls, value: int) -> int: + if value not in {0, 1}: + raise ValueError("状态仅支持 0(启用) 或 1(停用)") + return value + + +class EnergyReportTemplateUpdateSchema(EnergyReportTemplateCreateSchema): + """能源报告模板更新模型。""" + + +class EnergyReportTemplateOutSchema(EnergyReportTemplateCreateSchema, BaseSchema, UserBySchema, TenantBySchema): + """能源报告模板响应模型。""" + + model_config = ConfigDict(from_attributes=True) + + file: FileOutSchema | None = Field(default=None, description="文件记录") + file_url: str | None = Field(default=None, description="文件访问地址") + original_name: str | None = Field(default=None, description="原始文件名") + object_name: str | None = Field(default=None, description="MinIO对象名称") + + +@dataclass +class EnergyReportTemplateQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam): + """能源报告模板查询参数。""" + + template_name: str | None = Query(None, description="模板名称") + template_type: str | None = Query(None, description="模板类型") + version: str | None = Query(None, description="模板版本") + status: int | None = Query(None, ge=0, le=1, description="状态 0:启用 1:停用") + + def __post_init__(self) -> None: + if self.template_name: + self.template_name = (QueueEnum.like.value, self.template_name) + if self.template_type: + self.template_type = (QueueEnum.eq.value, self.template_type) + if self.version: + self.version = (QueueEnum.like.value, self.version) + if isinstance(self.status, int): + self.status = (QueueEnum.eq.value, self.status) + diff --git a/app/api/v1/module_energy/report_template/service.py b/app/api/v1/module_energy/report_template/service.py new file mode 100644 index 0000000..4d90633 --- /dev/null +++ b/app/api/v1/module_energy/report_template/service.py @@ -0,0 +1,112 @@ +from app.api.v1.module_common.file.crud import FileCRUD +from app.core.base_schema import AuthSchema +from app.core.exceptions import CustomException + +from .crud import EnergyReportTemplateCRUD +from .schema import ( + EnergyReportTemplateCreateSchema, + EnergyReportTemplateOutSchema, + EnergyReportTemplateQueryParam, + EnergyReportTemplateUpdateSchema, +) + +ENERGY_REPORT_TEMPLATE_BUSINESS_TYPE = "energy_report_template" + + +class EnergyReportTemplateService: + """能源报告模板服务。""" + + def __init__(self, auth: AuthSchema) -> None: + self.auth = auth + + async def detail(self, id: int) -> EnergyReportTemplateOutSchema: + template = await EnergyReportTemplateCRUD(self.auth).get_or_404(id=id) + return self._to_out_schema(template) + + async def page( + self, + page_no: int, + page_size: int, + search: EnergyReportTemplateQueryParam | None = None, + order_by: list[dict[str, str]] | None = None, + ) -> dict: + offset = (page_no - 1) * page_size + page_result = await EnergyReportTemplateCRUD(self.auth).page( + offset=offset, + limit=page_size, + order_by=order_by or [{"order": "asc"}, {"id": "desc"}], + search=vars(search) if search else None, + out_schema=EnergyReportTemplateOutSchema, + ) + for item in page_result.items: + file_info = item.get("file") or {} + item["file_url"] = file_info.get("file_url") + item["original_name"] = file_info.get("original_name") + item["object_name"] = file_info.get("object_name") + return page_result + + async def create(self, data: EnergyReportTemplateCreateSchema) -> EnergyReportTemplateOutSchema: + await self._validate_unique_name(template_name=data.template_name) + await self._validate_file(file_id=data.file_id) + template = await EnergyReportTemplateCRUD(self.auth).create(data=data) + await self._bind_file(file_id=data.file_id, template_id=template.id) + return self._to_out_schema(template) + + async def update(self, id: int, data: EnergyReportTemplateUpdateSchema) -> EnergyReportTemplateOutSchema: + old_template = await EnergyReportTemplateCRUD(self.auth).get_or_404(id=id, msg="更新失败,能源报告模板不存在") + await self._validate_unique_name(template_name=data.template_name, exclude_id=id) + await self._validate_file(file_id=data.file_id, current_template_id=id) + template = await EnergyReportTemplateCRUD(self.auth).update(id=id, data=data) + if old_template.file_id != data.file_id: + await self._unbind_file(file_id=old_template.file_id, template_id=id) + await self._bind_file(file_id=data.file_id, template_id=id) + return self._to_out_schema(template) + + async def delete(self, ids: list[int]) -> None: + if len(ids) < 1: + raise CustomException(msg="删除失败,删除对象不能为空") + templates = await EnergyReportTemplateCRUD(self.auth).get_list(search={"id": ("in", ids)}) + template_map = {template.id: template for template in templates} + for template_id in ids: + if template_id not in template_map: + raise CustomException(msg="删除失败,能源报告模板不存在") + for template in templates: + await self._unbind_file(file_id=template.file_id, template_id=template.id) + await EnergyReportTemplateCRUD(self.auth).delete(ids=ids) + + def _to_out_schema(self, template) -> EnergyReportTemplateOutSchema: + template_out = EnergyReportTemplateOutSchema.model_validate(template) + if template_out.file: + template_out.file_url = template_out.file.file_url + template_out.original_name = template_out.file.original_name + template_out.object_name = template_out.file.object_name + return template_out + + async def _validate_unique_name(self, template_name: str, exclude_id: int | None = None) -> None: + template = await EnergyReportTemplateCRUD(self.auth).get(template_name=template_name) + if template and template.id != exclude_id: + raise CustomException(msg="能源报告模板名称已存在") + + async def _validate_file(self, file_id: int, current_template_id: int | None = None) -> None: + file_record = await FileCRUD(self.auth).get(id=file_id) + if not file_record: + raise CustomException(msg="文件记录不存在") + if file_record.business_type and file_record.business_type != ENERGY_REPORT_TEMPLATE_BUSINESS_TYPE: + raise CustomException(msg="文件已绑定到其他业务类型") + if file_record.business_id and file_record.business_id != current_template_id: + raise CustomException(msg="文件已绑定到其他能源报告模板") + + async def _bind_file(self, file_id: int, template_id: int) -> None: + await FileCRUD(self.auth).set( + ids=[file_id], + business_type=ENERGY_REPORT_TEMPLATE_BUSINESS_TYPE, + business_id=template_id, + ) + + async def _unbind_file(self, file_id: int, template_id: int) -> None: + file_record = await FileCRUD(self.auth).get(id=file_id) + if not file_record: + return + if file_record.business_type == ENERGY_REPORT_TEMPLATE_BUSINESS_TYPE and file_record.business_id == template_id: + await FileCRUD(self.auth).set(ids=[file_id], business_id=None) + diff --git a/app/api/v1/module_monitor/resource/controller.py b/app/api/v1/module_monitor/resource/controller.py index 953bc15..feee537 100644 --- a/app/api/v1/module_monitor/resource/controller.py +++ b/app/api/v1/module_monitor/resource/controller.py @@ -7,7 +7,7 @@ from app.api.v1.module_common.file.service import FileService from app.common.request import PaginationService from app.common.response import ResponseSchema, StreamResponse, SuccessResponse, UploadFileResponse from app.core.base_params import PaginationQueryParam -from app.core.base_schema import UploadResponseSchema +from app.core.base_schema import AuthSchema, UploadResponseSchema from app.core.dependencies import AuthPermission from app.core.router_class import OperationLogRoute from app.utils.common_util import bytes2file_response @@ -49,20 +49,21 @@ async def get_directory_list_controller( "/upload", summary="上传文件", response_model=ResponseSchema[UploadResponseSchema], - dependencies=[Depends(AuthPermission(["module_monitor:resource:upload"]))], ) async def upload_file_controller( file: UploadFile, request: Request, + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_monitor:resource:upload"]))], target_path: Annotated[str | None, Form(description="目标目录路径")] = None, ) -> JSONResponse: result = await FileService.upload_service( + auth=auth, base_url=str(request.base_url), file=file, upload_type="resource", target_path=target_path, ) - return SuccessResponse(data=result, msg="上传文件成功") + return SuccessResponse(data=FileService.to_upload_response(result), msg="上传文件成功") @ResourceRouter.get( diff --git a/app/api/v1/module_rule/rule/controller.py b/app/api/v1/module_rule/rule/controller.py index 0fb7054..331861a 100644 --- a/app/api/v1/module_rule/rule/controller.py +++ b/app/api/v1/module_rule/rule/controller.py @@ -6,7 +6,7 @@ from fastapi.responses import JSONResponse from app.common.response import ResponseSchema, SuccessResponse from app.core import cache_util from app.core.base_params import PaginationQueryParam -from app.core.base_schema import AuthSchema, PageResultSchema +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 @@ -19,6 +19,23 @@ RuleRouter = APIRouter(route_class=OperationLogRoute, prefix="", tags=["规则 _RULE_NS = "rule" +@RuleRouter.get( + "/all", + summary="查询全部规则(不分页,下拉选择用)", + response_model=ResponseSchema[list[RuleOutSchema]], +) +@cache(expire=300, namespace=_RULE_NS) +async def get_rule_all_controller( + search: Annotated[RuleQueryParam, Depends()], + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_rule:rule:query"]))], +) -> JSONResponse: + result = await RuleService(auth).get_list( + search=search, + order_by=[{"id": "desc"}], + ) + return SuccessResponse(data=result, msg="查询全部规则成功") + + @RuleRouter.get( "/list", summary="查询规则列表", @@ -93,3 +110,17 @@ async def delete_rule_controller( await RuleService(auth).delete(ids=ids) await cache_util.clear(namespace=_RULE_NS) return SuccessResponse(msg="删除规则成功") + + +@RuleRouter.put( + "/status/batch", + summary="批量启用停用规则", + response_model=ResponseSchema[None], +) +async def batch_set_rule_status_controller( + data: BatchSetAvailable, + auth: Annotated[AuthSchema, Depends(AuthPermission(["module_rule:rule:patch"]))], +) -> JSONResponse: + await RuleService(auth).set_available(data=data) + await cache_util.clear(namespace=_RULE_NS) + return SuccessResponse(msg="批量修改规则状态成功") diff --git a/app/api/v1/module_rule/rule/service.py b/app/api/v1/module_rule/rule/service.py index 7060e11..e1a3ce4 100644 --- a/app/api/v1/module_rule/rule/service.py +++ b/app/api/v1/module_rule/rule/service.py @@ -1,5 +1,5 @@ from app.api.v1.module_rule.rule_category.crud import RuleCategoryCRUD -from app.core.base_schema import AuthSchema +from app.core.base_schema import AuthSchema, BatchSetAvailable from app.core.exceptions import CustomException from .crud import RuleCRUD @@ -66,6 +66,14 @@ class RuleService: raise CustomException(msg="删除失败,该规则不存在") await RuleCRUD(self.auth).delete(ids=ids) + async def set_available(self, data: BatchSetAvailable) -> None: + rules = await RuleCRUD(self.auth).get_list(search={"id": ("in", data.ids)}) + rule_map = {rule.id: rule for rule in rules} + for rule_id in data.ids: + if rule_id not in rule_map: + raise CustomException(msg="该规则不存在") + await RuleCRUD(self.auth).set(ids=data.ids, status=data.status) + def _to_out_schema(self, rule) -> RuleOutSchema: rule_out = RuleOutSchema.model_validate(rule) rule_out.category_name = rule_out.category_name_snapshot diff --git a/app/init_app.py b/app/init_app.py index 78098e4..8b0bae1 100644 --- a/app/init_app.py +++ b/app/init_app.py @@ -94,12 +94,14 @@ def register_exceptions(app: FastAPI) -> None: def register_routers(app: FastAPI) -> None: from app.api.v1.module_common import common_router + from app.api.v1.module_energy import energy_router from app.api.v1.module_monitor import monitor_router from app.api.v1.module_platform import platform_router from app.api.v1.module_rule import rule_router from app.api.v1.module_system import system_router app.include_router(common_router, dependencies=[Depends(RateLimiter(times=200, seconds=10))]) + app.include_router(energy_router, dependencies=[Depends(RateLimiter(times=200, seconds=10))]) app.include_router(monitor_router, dependencies=[Depends(RateLimiter(times=200, seconds=10))]) app.include_router(platform_router, dependencies=[Depends(RateLimiter(times=200, seconds=10))]) app.include_router(rule_router, dependencies=[Depends(RateLimiter(times=200, seconds=10))]) diff --git a/app/scripts/initialize.py b/app/scripts/initialize.py index 053d857..da3456a 100644 --- a/app/scripts/initialize.py +++ b/app/scripts/initialize.py @@ -15,6 +15,7 @@ from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.api.v1.module_common.file.model import FileModel +from app.api.v1.module_energy.report_template.model import EnergyReportTemplateModel from app.api.v1.module_platform.email.model import EmailConfigModel, EmailTemplateModel from app.api.v1.module_platform.invoice.model import InvoiceModel from app.api.v1.module_platform.menu.model import MenuModel @@ -78,6 +79,7 @@ class InitializeData: NoticeReadModel, TicketModel, FileModel, + EnergyReportTemplateModel, # ── 日志表(追加写入) ── LoginLogModel, OperationLogModel,