#!/usr/bin/env python # -*- coding: utf-8 -*- """ 表单管理 Schema 定义 """ from datetime import datetime from typing import Any, Dict, List, Optional from pydantic import BaseModel, Field, ConfigDict # ============ 表单元数据 Schema ============ class FormMetaBase(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="表单编码(字母开头,只能包含字母、数字和下划线)") form_type: str = Field("normal", description="表单类型: normal-普通表单, workflow-流程表单") description: str = Field("", description="描述") sort: int = Field(0, description="排序") show_in_mobile: bool = Field(False, description="是否在移动端显示") globally_visible: bool = Field(False, description="是否全局可见(供其他应用引用)") icon: str = Field("", description="图标") icon_bg_color: str = Field("", description="图标背景色") class FormSubTableSchema(BaseModel): """子表关联配置""" table_name: str = Field(..., description="从表名") table_schema: str = Field("", description="从表Schema") table_database: str = Field("", description="从表数据库") alias: str = Field("", description="别名") foreign_key: str = Field(..., description="外键字段") related_field: str = Field("id", description="关联主表字段") relation_type: str = Field("one-to-many", description="关联类型") sort: int = Field(0, description="排序") class FormMetaCreateIn(FormMetaBase): """创建表单请求""" db_config: str = Field(..., description="数据库配置名") main_table: str = Field(..., description="主表名") main_table_schema: str = Field("", description="主表Schema") main_table_database: str = Field("", description="主表数据库") form_config: Dict[str, Any] = Field(default_factory=dict, description="表单设计配置") list_config: Dict[str, Any] = Field(default_factory=dict, description="列表设计配置") sub_tables: List[FormSubTableSchema] = Field(default_factory=list, description="子表配置") class FormMetaUpdateIn(BaseModel): """更新表单请求""" name: Optional[str] = Field(None, description="表单名称") form_type: Optional[str] = Field(None, description="表单类型") description: Optional[str] = Field(None, description="描述") sort: Optional[int] = Field(None, description="排序") show_in_mobile: Optional[bool] = Field(None, description="是否在移动端显示") globally_visible: Optional[bool] = Field(None, description="是否全局可见(供其他应用引用)") icon: Optional[str] = Field(None, description="图标") icon_bg_color: Optional[str] = Field(None, description="图标背景色") db_config: Optional[str] = Field(None, description="数据库配置名") main_table: Optional[str] = Field(None, description="主表名") main_table_schema: Optional[str] = Field(None, description="主表Schema") main_table_database: Optional[str] = Field(None, description="主表数据库") form_config: Optional[Dict[str, Any]] = Field(None, description="表单设计配置") list_config: Optional[Dict[str, Any]] = Field(None, description="列表设计配置") sub_tables: Optional[List[FormSubTableSchema]] = Field(None, description="子表配置") class FormSubTableOut(BaseModel): """子表关联输出""" id: str table_name: str table_schema: str = "" table_database: str = "" alias: str = "" foreign_key: str related_field: str = "id" relation_type: str = "one-to-many" sort: int = 0 model_config = ConfigDict(from_attributes=True) class FormMetaOut(BaseModel): """表单详情输出""" id: str name: str code: str form_type: str description: str = "" status: str version: int db_config: str main_table: str main_table_schema: str = "" main_table_database: str = "" show_in_mobile: bool = False globally_visible: bool = False icon: str = "" icon_bg_color: str = "" form_config: Dict[str, Any] = {} list_config: Dict[str, Any] = {} sort: int = 0 sys_create_datetime: Optional[str] = None sys_update_datetime: Optional[str] = None sub_tables: List[FormSubTableOut] = [] model_config = ConfigDict(from_attributes=True) class FormMetaListOut(BaseModel): """表单列表输出""" id: str application_id: Optional[str] = None application_name: str = "主应用" application_code: str = "" name: str code: str form_type: str description: str = "" status: str version: int main_table: str show_in_mobile: bool = False globally_visible: bool = False icon: str = "" icon_bg_color: str = "" sort: int = 0 sys_create_datetime: Optional[str] = None sys_update_datetime: Optional[str] = None model_config = ConfigDict(from_attributes=True) # ============ 导入导出 Schema ============ class TableDDLSchema(BaseModel): """表 DDL 信息""" main_table: str = Field("", description="主表 DDL") sub_tables: Dict[str, str] = Field(default_factory=dict, description="子表 DDL,key 为表名") class FormExportOut(BaseModel): """表单配置导出""" name: str code: str form_type: str description: str = "" globally_visible: bool = False show_in_mobile: bool = False db_config: str main_table: str main_table_schema: str = "" main_table_database: str = "" form_config: Dict[str, Any] = {} list_config: Dict[str, Any] = {} sub_tables: List[FormSubTableSchema] = [] table_ddl: Optional[TableDDLSchema] = None class TableRenameMapping(BaseModel): """表重命名映射""" original_name: str = Field(..., description="原始表名") new_name: str = Field(..., description="新表名") new_schema: Optional[str] = Field(None, description="新Schema") class FormImportIn(BaseModel): """表单配置导入""" application_id: Optional[str] = Field(None, description="所属应用ID") name: str = Field(..., description="表单名称") code: str = Field(..., description="表单编码") form_type: str = Field("normal", description="表单类型") description: str = Field("", description="描述") db_config: str = Field(..., description="数据库配置名") main_table: str = Field(..., description="主表名") main_table_schema: str = Field("", description="主表Schema") main_table_database: str = Field("", description="主表数据库") form_config: Dict[str, Any] = Field(default_factory=dict, description="表单设计配置") list_config: Dict[str, Any] = Field(default_factory=dict, description="列表设计配置") show_in_mobile: bool = Field(False, description="是否在移动端显示") globally_visible: bool = Field(False, description="是否全局可见(供其他应用引用)") sub_tables: List[FormSubTableSchema] = Field(default_factory=list, description="子表配置") table_ddl: Optional[TableDDLSchema] = Field(None, description="表 DDL(用于自动建表)") auto_create_tables: bool = Field(False, description="是否自动创建不存在的表") create_schema_if_not_exists: bool = Field( False, description="目标 Schema 不存在时是否自动创建(PostgreSQL/SQL Server)" ) table_rename_mappings: List[TableRenameMapping] = Field(default_factory=list, description="表重命名映射列表") class TableCheckResult(BaseModel): """单表检查结果""" table_name: str = Field(..., description="表名") schema_name: str = Field("", description="Schema名") exists: bool = Field(..., description="表是否存在") has_ddl: bool = Field(False, description="导入数据中是否包含该表的 DDL") class FormImportCheckIn(BaseModel): """导入预检查请求""" code: str = Field(..., description="表单编码") db_config: str = Field("default", description="数据库配置名") main_table: str = Field(..., description="主表名") main_table_schema: str = Field("", description="主表 Schema") main_table_database: str = Field("", description="主表数据库") sub_tables: List[FormSubTableSchema] = Field(default_factory=list, description="子表配置") table_ddl: Optional[TableDDLSchema] = Field(None, description="表 DDL") class FormImportCheckOut(BaseModel): """导入预检查结果""" code_exists: bool = Field(..., description="表单编码是否已存在") main_table_check: TableCheckResult = Field(..., description="主表检查结果") sub_table_checks: List[TableCheckResult] = Field(default_factory=list, description="子表检查结果") can_import: bool = Field(..., description="是否可以直接导入(所有表都存在且编码不冲突)") available_schemas: List[str] = Field(default_factory=list, description="可用的Schema列表") target_db_type: str = Field("", description="目标连接数据库类型") class FormValidateTablesIn(BaseModel): """表单物理表校验请求""" db_config: str = Field("default", description="数据库连接 code") main_table: str = Field("", description="主表名") main_table_schema: str = Field("", description="主表 Schema") main_table_database: str = Field("", description="主表数据库") sub_tables: List[FormSubTableSchema] = Field(default_factory=list, description="子表配置") class FormValidateTablesOut(BaseModel): """表单物理表校验结果""" valid: bool = Field(..., description="是否全部通过") connection_ok: bool = Field(True, description="连接是否可用") connection_message: str = Field("", description="连接错误信息") db_config: str = Field("default", description="数据库连接 code") main_table_exists: bool = Field(False, description="主表是否存在") sub_table_checks: List[TableCheckResult] = Field(default_factory=list, description="子表检查") database_warnings: List[str] = Field( default_factory=list, description="库名/连接配置风险提示(不阻断 valid,供前端展示)", ) # ============ 发布配置 Schema ============ class FormPublishIn(BaseModel): """发布表单请求(含菜单配置)""" menu_name: str = Field(..., description="菜单名称") menu_parent_id: Optional[str] = Field(None, description="上级菜单ID") menu_icon: str = Field("lucide:file-text", description="菜单图标") menu_order: int = Field(0, description="菜单排序") # 功能开关 allow_add: bool = Field(True, description="允许新增") allow_edit: bool = Field(True, description="允许编辑") allow_delete: bool = Field(True, description="允许删除") allow_export: bool = Field(True, description="允许导出") allow_import: bool = Field(False, description="允许导入")