#!/usr/bin/env python # -*- coding: utf-8 -*- """ 文档生成Schema定义 """ from datetime import datetime from typing import Optional, List, Dict, Any from pydantic import BaseModel, ConfigDict, Field # ==================== 文档模板 ==================== class PageMargin(BaseModel): """页边距配置""" top: int = 20 right: int = 20 bottom: int = 20 left: int = 20 class SealPosition(BaseModel): """签章位置配置""" seal_type: str = Field(..., description="签章类型: company/department/personal/signature") position_type: str = Field(default="fixed", description="定位方式: fixed/relative") x: int = Field(default=0, description="X坐标(mm)") y: int = Field(default=0, description="Y坐标(mm)") page: int = Field(default=-1, description="页码(-1表示最后一页)") width: int = Field(default=40, description="宽度(mm)") height: int = Field(default=40, description="高度(mm)") field_name: Optional[str] = Field(default=None, description="关联字段名(用于手写签名)") class CalculationField(BaseModel): """计算字段配置""" name: str = Field(..., description="字段名") label: str = Field(default="", description="字段标签") formula: str = Field(..., description="计算公式,如: quantity * unit_price") format: str = Field(default="number", description="格式化类型: number/money/percent/chinese") decimal_places: int = Field(default=2, description="小数位数") class AggregationField(BaseModel): """聚合字段配置""" name: str = Field(..., description="字段名") label: str = Field(default="", description="字段标签") source: str = Field(..., description="数据源(子表名)") field: str = Field(..., description="聚合字段") function: str = Field(default="sum", description="聚合函数: sum/avg/max/min/count") format: str = Field(default="number", description="格式化类型: number/money/percent/chinese") decimal_places: int = Field(default=2, description="小数位数") class CalculationRules(BaseModel): """计算规则配置""" fields: List[CalculationField] = Field(default_factory=list, description="计算字段列表") aggregations: List[AggregationField] = Field(default_factory=list, description="聚合字段列表") class DocumentTemplateBase(BaseModel): """文档模板基础Schema""" name: str = Field(..., min_length=1, max_length=100, description="模板名称") code: str = Field(..., min_length=1, max_length=100, pattern=r"^[a-zA-Z][a-zA-Z0-9_]*$", description="模板编码(字母开头,只能包含字母、数字和下划线)") category: str = Field(default="other", description="分类") description: Optional[str] = Field(default="", description="描述") form_code: Optional[str] = Field(default=None, description="关联表单编码") workflow_code: Optional[str] = Field(default=None, description="关联流程编码") template_type: str = Field(default="designer", description="模板类型: designer/html") template_content: Optional[str] = Field(default=None, description="模板内容") template_css: Optional[str] = Field(default=None, description="自定义CSS") page_size: str = Field(default="A4", description="页面大小") page_orientation: str = Field(default="portrait", description="页面方向") page_margin: Optional[PageMargin] = Field(default_factory=PageMargin, description="页边距") watermark_enabled: bool = Field(default=False, description="是否启用水印") watermark_text: Optional[str] = Field(default=None, description="水印文字") watermark_type: str = Field(default="text", description="水印类型") watermark_image_id: Optional[str] = Field(default=None, description="水印图片ID") watermark_opacity: int = Field(default=30, ge=0, le=100, description="水印透明度") watermark_angle: int = Field(default=-45, description="水印角度") seal_enabled: bool = Field(default=False, description="是否启用签章") seal_positions: Optional[List[SealPosition]] = Field(default=None, description="签章位置配置") header_enabled: bool = Field(default=False, description="是否启用页眉") header_template: Optional[str] = Field(default=None, description="页眉模板") footer_enabled: bool = Field(default=False, description="是否启用页脚") footer_template: Optional[str] = Field(default=None, description="页脚模板") show_page_number: bool = Field(default=True, description="是否显示页码") calculation_rules: Optional[CalculationRules] = Field(default=None, description="计算规则配置") class DocumentTemplateCreate(DocumentTemplateBase): """创建文档模板""" application_id: Optional[str] = Field(default=None, description="所属应用ID") class DocumentTemplateUpdate(BaseModel): """更新文档模板""" name: Optional[str] = Field(default=None, max_length=100, description="模板名称") category: Optional[str] = Field(default=None, description="分类") description: Optional[str] = Field(default=None, description="描述") form_code: Optional[str] = Field(default=None, description="关联表单编码") workflow_code: Optional[str] = Field(default=None, description="关联流程编码") template_type: Optional[str] = Field(default=None, description="模板类型") template_content: Optional[str] = Field(default=None, description="模板内容") template_css: Optional[str] = Field(default=None, description="自定义CSS") page_size: Optional[str] = Field(default=None, description="页面大小") page_orientation: Optional[str] = Field(default=None, description="页面方向") page_margin: Optional[PageMargin] = Field(default=None, description="页边距") watermark_enabled: Optional[bool] = Field(default=None, description="是否启用水印") watermark_text: Optional[str] = Field(default=None, description="水印文字") watermark_type: Optional[str] = Field(default=None, description="水印类型") watermark_image_id: Optional[str] = Field(default=None, description="水印图片ID") watermark_opacity: Optional[int] = Field(default=None, description="水印透明度") watermark_angle: Optional[int] = Field(default=None, description="水印角度") seal_enabled: Optional[bool] = Field(default=None, description="是否启用签章") seal_positions: Optional[List[SealPosition]] = Field(default=None, description="签章位置配置") header_enabled: Optional[bool] = Field(default=None, description="是否启用页眉") header_template: Optional[str] = Field(default=None, description="页眉模板") footer_enabled: Optional[bool] = Field(default=None, description="是否启用页脚") footer_template: Optional[str] = Field(default=None, description="页脚模板") show_page_number: Optional[bool] = Field(default=None, description="是否显示页码") calculation_rules: Optional[CalculationRules] = Field(default=None, description="计算规则配置") status: Optional[str] = Field(default=None, description="状态") class DocumentTemplateOut(DocumentTemplateBase): """文档模板输出""" id: str application_id: Optional[str] = None calculation_rules: Optional[Dict[str, Any]] = None status: str = "draft" is_builtin: bool = False version: int = 1 sys_create_datetime: Optional[datetime] = None sys_update_datetime: Optional[datetime] = None model_config = ConfigDict(from_attributes=True) class DocumentTemplateListOut(BaseModel): """文档模板列表输出""" id: str name: str code: str category: str description: Optional[str] = None form_code: Optional[str] = None workflow_code: Optional[str] = None status: str = "draft" is_builtin: bool = False version: int = 1 sys_create_datetime: Optional[datetime] = None model_config = ConfigDict(from_attributes=True) # ==================== 导入导出 ==================== class DocumentTemplateImportCheckIn(BaseModel): """单据模板导入预检查""" code: str = Field(..., description="模板编码") class DocumentTemplateImportCheckOut(BaseModel): """单据模板导入预检查结果""" code_exists: bool = Field(..., description="模板编码是否已存在") can_import: bool = Field(..., description="是否可以直接导入") class DocumentTemplateImportIn(DocumentTemplateBase): """单据模板配置导入""" application_id: Optional[str] = Field(None, description="所属应用ID") # ==================== 生成的文档 ==================== class GeneratedDocumentOut(BaseModel): """生成的文档输出""" id: str template_id: str template_code: Optional[str] = None template_name: Optional[str] = None form_code: Optional[str] = None form_data_id: Optional[str] = None workflow_code: Optional[str] = None instance_id: Optional[str] = None document_name: str document_no: Optional[str] = None file_id: str file_size: int = 0 page_count: int = 1 generate_type: str = "manual" generator_id: Optional[str] = None generator_name: Optional[str] = None status: str = "generated" download_count: int = 0 sealed: bool = False seal_info: Optional[Dict[str, Any]] = None sys_create_datetime: Optional[datetime] = None model_config = ConfigDict(from_attributes=True) class GenerateDocumentIn(BaseModel): """生成文档请求""" template_id: str = Field(..., description="模板ID") form_data_id: Optional[str] = Field(default=None, description="表单数据ID") instance_id: Optional[str] = Field(default=None, description="流程实例ID") document_name: Optional[str] = Field(default=None, description="文档名称(可选)") seal_ids: Optional[List[str]] = Field(default=None, description="要使用的签章ID列表") signature_file_ids: Optional[Dict[str, str]] = Field(default=None, description="手写签名文件ID映射") class BatchGenerateDocumentIn(BaseModel): """批量生成文档请求""" template_id: str = Field(..., description="模板ID") form_data_ids: List[str] = Field(..., description="表单数据ID列表") # ==================== 预览 ==================== class PreviewDocumentIn(BaseModel): """预览文档请求""" template_id: Optional[str] = Field(default=None, description="模板ID(与template_content二选一)") template_content: Optional[str] = Field(default=None, description="模板内容JSON(与template_id二选一)") calculation_rules: Optional[Dict[str, Any]] = Field(default=None, description="计算规则配置(用于未保存的模板预览)") form_data_id: Optional[str] = Field(default=None, description="表单数据ID") instance_id: Optional[str] = Field(default=None, description="流程实例ID") test_data: Optional[Dict[str, Any]] = Field(default=None, description="测试数据(优先使用)") # ==================== 通用响应 ==================== class TemplateCategory(BaseModel): """模板分类""" value: str label: str count: int = 0 class DocumentStats(BaseModel): """文档统计""" total_templates: int = 0 published_templates: int = 0 total_documents: int = 0 today_documents: int = 0