#!/usr/bin/env python # -*- coding: utf-8 -*- """报表管理 Schema""" from typing import Any, Dict, List, Optional from pydantic import BaseModel, Field, ConfigDict def _to_camel(string: str) -> str: parts = string.split("_") return parts[0] + "".join(p.capitalize() for p in parts[1:]) class CamelModel(BaseModel): """支持 camelCase 别名(与 JNPF 前端对齐)""" model_config = ConfigDict( populate_by_name=True, alias_generator=_to_camel, ) # ============ 模板 ============ class ReportTemplateBase(BaseModel): application_id: Optional[str] = Field(None, description="所属应用ID") name: str = Field(..., description="报表名称") code: str = Field(..., pattern=r"^[a-zA-Z][a-zA-Z0-9_]*$", description="报表编码") category: str = Field("", description="分类") description: str = Field("", description="描述") sort: int = Field(0, description="排序") class ReportTemplateCreateIn(ReportTemplateBase): pass class ReportTemplateUpdateIn(BaseModel): name: Optional[str] = None category: Optional[str] = None description: Optional[str] = None sort: Optional[int] = None allow_export: Optional[bool] = None allow_print: Optional[bool] = None allow_watermark: Optional[bool] = None watermark_config: Optional[Dict[str, Any]] = None class ReportTemplateOut(BaseModel): id: str application_id: Optional[str] = None name: str code: str category: str description: str status: str allow_export: bool allow_print: bool allow_watermark: bool watermark_config: Dict[str, Any] sort: int active_version_id: Optional[str] = None sys_create_datetime: str sys_update_datetime: str class ReportTemplateListOut(BaseModel): id: str application_id: Optional[str] = None application_name: str = "" application_code: str = "" name: str code: str category: str description: str status: str has_release_menu: bool = False sort: int sys_create_datetime: str sys_update_datetime: str # ============ 版本 ============ class ReportDatasetIn(CamelModel): data_source_id: str = Field(..., description="数据源ID") alias: str = Field(..., description="别名") field_mapping: Dict[str, Any] = Field(default_factory=dict) convert_config: Dict[str, Any] = Field(default_factory=dict) sort: int = 0 class ReportVersionOut(BaseModel): id: str template_id: str version: int state: int snapshot: Dict[str, Any] cells: Dict[str, Any] query_list: List[Any] sort_list: List[Any] column_list: List[Any] fence_list: List[Any] convert_config: Dict[str, Any] datasets: List[Dict[str, Any]] = Field(default_factory=list) sys_create_datetime: str sys_update_datetime: str class ReportVersionListOut(BaseModel): id: str template_id: str version: int state: int sys_create_datetime: str sys_update_datetime: str class ReportSaveIn(CamelModel): """保存版本(对标 JNPF POST /Report/Save)""" id: str = Field(..., description="模板ID") version_id: Optional[str] = Field(None, description="版本ID,空则新建设计中版本") type: int = Field(0, description="0仅保存 1发布") snapshot: Any = Field(default_factory=dict, description="Univer snapshot") cells: Any = Field(default_factory=dict) query_list: List[Any] = Field(default_factory=list) sort_list: List[Any] = Field(default_factory=list) column_list: List[Any] = Field(default_factory=list) fence_list: List[Any] = Field(default_factory=list) convert_config: Any = Field(default_factory=dict) data_set_list: List[ReportDatasetIn] = Field(default_factory=list, description="数据集列表") class ReportSaveOut(BaseModel): template_id: str version_id: str state: int # ============ 预览 ============ class ReportPreviewIn(CamelModel): params: Dict[str, Any] = Field(default_factory=dict, description="查询参数") snapshot: Any = Field(None, description="设计态预览:当前编辑器 snapshot") cells: Any = Field(None, description="设计态预览:当前编辑器 cells") query_list: Any = Field(None, description="设计态预览:当前查询条件") sort_list: Any = Field(None, description="设计态预览:当前排序") column_list: Any = Field(None, description="设计态预览:当前分栏") fence_list: Any = Field(None, description="设计态预览:当前分栏(fence)") convert_config: Any = Field(None, description="设计态预览:当前转换配置") class ReportDownImgIn(BaseModel): """远端/ Base64 图片转存""" model_config = ConfigDict(populate_by_name=True) img_value: str = Field("", alias="imgValue") img_type: str = Field("", alias="imgType", description="BASE64 或 URL") class ReportUploadOut(BaseModel): name: str = "" url: str = "" class ReportImportExcelOut(BaseModel): rowsCount: int = 0 colsCount: int = 0 data: List[List[Dict[str, Any]]] = Field(default_factory=list) class ReportPreviewOut(CamelModel): snapshot: Dict[str, Any] cells: Dict[str, Any] query_list: List[Any] = Field(default_factory=list) chart_data: List[Any] = Field(default_factory=list) allow_export: bool = True allow_print: bool = True allow_watermark: bool = False watermark_config: Dict[str, Any] = Field(default_factory=dict) full_name: str = "" # ============ 发布 / 导入导出 ============ class ReportPublishIn(BaseModel): menu_name: str = Field(..., description="菜单名称") menu_parent_id: Optional[str] = Field(None, description="上级菜单ID") menu_icon: str = Field("lucide:file-spreadsheet", description="菜单图标") menu_order: int = Field(0, description="菜单排序") class ReportImportCheckIn(BaseModel): code: str class ReportImportCheckOut(BaseModel): code_exists: bool can_import: bool class ReportImportIn(ReportTemplateBase): schema_version: int = Field(1, description="包格式版本") allow_export: Optional[bool] = None allow_print: Optional[bool] = None allow_watermark: Optional[bool] = None watermark_config: Optional[Dict[str, Any]] = None version: Optional[Dict[str, Any]] = Field(None, description="设计中版本内容") versions: List[Dict[str, Any]] = Field(default_factory=list, description="兼容旧字段") datasets: List[Dict[str, Any]] = Field(default_factory=list)