"""Pydantic 请求/响应模型定义。 所有 API 的请求体和响应体均在此定义,涵盖: - 认证(登录/令牌) - 用户、部门、角色、权限的增删改查 - 任务管理 - 审批流引擎(Flow):节点/边/版本/执行 - 自定义工具(CustomTool) - MCP 服务 - Agent 配置 - 通知模板 - 文档上传与解析 - 审计日志 - 系统监控指标 - 通用 API 响应包装 """ import uuid from datetime import datetime from pydantic import BaseModel, Field, ConfigDict # --- Auth --- class LoginRequest(BaseModel): """登录请求体:用户名 + 密码。""" username: str password: str class TokenResponse(BaseModel): """令牌响应体:Bearer 令牌 + 用户信息。""" access_token: str token_type: str = "bearer" user: "UserOut" # --- User --- class UserCreate(BaseModel): """创建用户请求体。""" username: str password: str display_name: str email: str | None = None phone: str | None = None wecom_user_id: str | None = None department_id: uuid.UUID | None = None position: str | None = None manager_id: uuid.UUID | None = None role_ids: list[uuid.UUID] = [] class UserUpdate(BaseModel): """更新用户请求体(所有字段可选)。""" display_name: str | None = None email: str | None = None phone: str | None = None department_id: uuid.UUID | None = None position: str | None = None manager_id: uuid.UUID | None = None status: str | None = None role_ids: list[uuid.UUID] | None = None class UserOut(BaseModel): """用户响应体(ORM 映射)。""" id: uuid.UUID username: str display_name: str email: str | None = None phone: str | None = None wecom_user_id: str | None = None department_id: uuid.UUID | None = None position: str | None = None manager_id: uuid.UUID | None = None status: str roles: list["RoleOut"] = [] created_at: datetime | None = None class Config: from_attributes = True # --- Department --- class DepartmentCreate(BaseModel): """创建部门请求体。""" name: str parent_id: uuid.UUID | None = None sort_order: int = 0 class DepartmentUpdate(BaseModel): """更新部门请求体。""" name: str | None = None parent_id: uuid.UUID | None = None sort_order: int | None = None class DepartmentOut(BaseModel): """部门响应体,含嵌套子部门列表。""" id: uuid.UUID name: str parent_id: uuid.UUID | None = None path: str level: int sort_order: int children: list["DepartmentOut"] = [] class Config: from_attributes = True # --- Role --- class RoleCreate(BaseModel): """创建角色/岗位请求体。""" name: str code: str = "" description: str | None = None role_type: str = "position" data_scope: str = "self_only" permission_ids: list[uuid.UUID] = [] class RoleUpdate(BaseModel): """更新角色请求体。""" name: str | None = None description: str | None = None role_type: str | None = None data_scope: str | None = None permission_ids: list[uuid.UUID] | None = None class RoleOut(BaseModel): """角色/岗位响应体,含权限编码列表。""" id: uuid.UUID name: str code: str = "" description: str | None = None role_type: str = "position" is_system: bool data_scope: str permissions: list[str] = [] class Config: from_attributes = True # --- Permission --- class PermissionOut(BaseModel): """权限响应体。""" id: uuid.UUID code: str name: str resource: str action: str class Config: from_attributes = True # --- Task --- class TaskCreate(BaseModel): """创建任务请求体。""" title: str content: str | None = None assignee_id: uuid.UUID priority: str = "normal" deadline: datetime | None = None push_to_wecom: bool = True class TaskUpdate(BaseModel): """更新任务请求体。""" title: str | None = None content: str | None = None status: str | None = None priority: str | None = None deadline: datetime | None = None class TaskOut(BaseModel): """任务响应体。""" id: uuid.UUID title: str content: str | None = None assigner_id: uuid.UUID | None = None assignee_id: uuid.UUID status: str priority: str deadline: datetime | None = None created_at: datetime | None = None updated_at: datetime | None = None class Config: from_attributes = True # --- Employee Analysis --- class EmployeeAnalysis(BaseModel): """员工分析报告响应体。""" employee_name: str department: str period: str task_completion_rate: float active_days: int total_interactions: int main_topics: list[str] efficiency_trend: str efficiency_detail: str strengths: list[str] growth_suggestions: list[str] personality_traits: str # --- Flow --- class TriggerNodeConfig(BaseModel): """触发节点配置。""" event_type: str = "text_message" channels: list[str] = ["wecom"] callback_url: str = "" class LLMNodeConfig(BaseModel): """LLM 调用节点配置。""" system_prompt: str = "" model: str = "gpt-4o-mini" temperature: float = 0.7 agent_id: str = "" max_tokens: int = 2000 context_length: int = 5 memory_mode: str = "short_term" stream: bool = True tool_call: bool = False class ToolNodeConfig(BaseModel): """内置工具节点配置。""" tool_name: str = "" tool_type: str = "" tool_params: dict = {} timeout: int = 30 retry_count: int = 0 error_handling: str = "throw" class MCPNodeConfig(BaseModel): """MCP 服务节点配置。""" mcp_server: str = "" tool_name: str = "" input_params: dict = {} timeout: int = 30 response_parser: str = "json" error_handling: str = "throw" class NotifyNodeConfig(BaseModel): """通知节点配置。""" channels: dict = {"wecom": True, "web": False} message_template: str = "" web_template: str = "" target: str = "" message_type: str = "text" async_send: bool = False error_handling: str = "throw" class ConditionNodeConfig(BaseModel): """条件分支节点配置。""" condition: str = "" condition_type: str = "expression" true_label: str = "是" false_label: str = "否" default_branch: str = "false" class RAGNodeConfig(BaseModel): """RAG 检索节点配置。""" knowledge_base: str = "" top_k: int = 5 search_mode: str = "hybrid" similarity_threshold: float = 0.7 result_sort: str = "similarity" include_metadata: bool = True class OutputNodeConfig(BaseModel): """输出节点配置。""" format: str = "text" output_template: str = "" indent: int = 2 encoding: str = "utf-8" truncate: bool = False max_length: int = 2000 class LoopNodeConfig(BaseModel): """循环节点配置。""" loop_type: str = "fixed" max_iterations: int = 10 count: int = 3 iterator_variable: str = "item" class CodeNodeConfig(BaseModel): """代码执行节点配置。""" language: str = "python" code: str = "" timeout: int = 30 sandbox: bool = True class FlowNode(BaseModel): """流程图中单个节点的定义。""" id: str | None = None type: str label: str | None = None config: dict = {} class FlowEdge(BaseModel): """流程图中连接边的定义。""" source: str | None = None target: str | None = None from_field: str | None = Field(None, alias="from") to_field: str | None = Field(None, alias="to") class Config: populate_by_name = True class FlowDefinitionCreate(BaseModel): """创建流程定义请求体。""" name: str description: str | None = None trigger: dict = {} nodes: list[FlowNode] edges: list[FlowEdge] flow_mode: str = "chatflow" class FlowDefinitionUpdate(BaseModel): """更新流程定义请求体。""" name: str | None = None description: str | None = None nodes: list[FlowNode] | None = None edges: list[FlowEdge] | None = None trigger: dict | None = None class FlowDefinitionOut(BaseModel): """流程定义响应体。""" id: uuid.UUID name: str description: str | None = None version: int status: str definition_json: dict published_version_id: uuid.UUID | None = None published_to_wecom: bool published_to_web: bool = False flow_mode: str = "chatflow" created_at: datetime | None = None updated_at: datetime | None = None class Config: from_attributes = True class FlowVersionOut(BaseModel): """流程版本响应体。""" id: uuid.UUID flow_id: uuid.UUID version: int definition_json: dict changelog: str = "" published_to_wecom: bool = False published_to_web: bool = False published_by: uuid.UUID | None = None created_at: datetime | None = None class Config: from_attributes = True class FlowApiKeyCreate(BaseModel): """创建流程 API 密钥请求体。""" name: str class FlowApiKeyOut(BaseModel): """流程 API 密钥响应体。""" id: uuid.UUID flow_id: uuid.UUID name: str key_prefix: str last_used_at: datetime | None = None created_at: datetime | None = None class Config: from_attributes = True class FlowExecuteRequest(BaseModel): """流程执行请求体。""" input_text: str = "" session_id: str | None = None user_id: str | None = None class FlowChatMessageRequest(BaseModel): """流程聊天消息请求体。""" query: str inputs: dict = {} response_mode: str = "blocking" user: str = "" session_id: str | None = None class OpenAPIImportRequest(BaseModel): """OpenAPI 导入请求体。""" openapi_url: str base_url_override: str | None = None class CustomToolCreate(BaseModel): """创建自定义工具请求体。""" model_config = ConfigDict(protected_namespaces=()) name: str description: str | None = None openapi_url: str | None = None endpoint_url: str | None = None method: str = "GET" path: str = "" headers: dict = {} auth_type: str = "none" auth_config: dict = {} tool_schema: dict | None = None class CustomToolUpdate(BaseModel): """更新自定义工具请求体。""" model_config = ConfigDict(protected_namespaces=()) name: str | None = None description: str | None = None endpoint_url: str | None = None method: str | None = None path: str | None = None headers: dict | None = None auth_type: str | None = None auth_config: dict | None = None tool_schema: dict | None = None is_active: bool | None = None class CustomToolOut(BaseModel): """自定义工具响应体(ORM 映射)。""" model_config = ConfigDict(from_attributes=True, populate_by_name=True, protected_namespaces=()) id: uuid.UUID name: str description: str | None = None tool_schema: dict = Field(alias="schema_json") endpoint_url: str method: str path: str auth_type: str is_active: bool created_at: datetime | None = None # --- MCP --- class MCPServiceCreate(BaseModel): """创建 MCP 服务请求体。""" name: str transport: str = "http" url: str | None = None command: str | None = None args: list[str] = [] env: dict[str, str] = {} class MCPServiceUpdate(BaseModel): """更新 MCP 服务请求体。""" transport: str | None = None url: str | None = None command: str | None = None args: list[str] | None = None env: dict[str, str] | None = None class MCPServiceOut(BaseModel): """MCP 服务响应体。""" id: uuid.UUID name: str transport: str url: str | None = None command: str | None = None status: str = "disconnected" tools: list[dict] = [] creator_id: uuid.UUID | None = None created_at: datetime | None = None class Config: from_attributes = True # --- Agent Config --- class AgentConfigCreate(BaseModel): """创建 Agent 配置请求体。""" name: str description: str | None = None system_prompt: str = "" model: str = "gpt-4o-mini" temperature: float = 0.7 tools: list[str] = [] class AgentConfigUpdate(BaseModel): """更新 Agent 配置请求体。""" name: str | None = None description: str | None = None system_prompt: str | None = None model: str | None = None temperature: float | None = None tools: list[str] | None = None status: str | None = None class AgentConfigOut(BaseModel): """Agent 配置响应体。""" id: uuid.UUID name: str description: str | None = None system_prompt: str model: str temperature: float tools: list[str] = [] status: str creator_id: uuid.UUID | None = None created_at: datetime | None = None updated_at: datetime | None = None class Config: from_attributes = True # --- Notification --- class NotificationTemplateCreate(BaseModel): """创建通知模板请求体。""" name: str code: str channel: str = "wecom" title_template: str | None = None body_template: str variables: list[str] = [] class NotificationTemplateOut(BaseModel): """通知模板响应体。""" id: uuid.UUID name: str code: str channel: str title_template: str | None = None body_template: str variables: list[str] = [] is_system: bool = False class Config: from_attributes = True # --- Document --- class DocumentUploadOut(BaseModel): """文档上传结果响应体。""" file_id: uuid.UUID filename: str file_size: int content_type: str upload_time: datetime class DocumentParseResult(BaseModel): """文档解析结果响应体。""" file_id: uuid.UUID filename: str content: str metadata: dict = {} # --- Audit --- class AuditQueryParams(BaseModel): """审计日志查询参数。""" page: int = 1 page_size: int = 20 action: str | None = None resource: str | None = None operator_id: uuid.UUID | None = None date_from: datetime | None = None date_to: datetime | None = None class AuditLogOut(BaseModel): """审计日志条目响应体。""" id: uuid.UUID operator_id: uuid.UUID | None = None action: str resource: str | None = None resource_id: str | None = None detail: dict | None = None ip_address: str | None = None created_at: datetime | None = None class Config: from_attributes = True class AuditLogPage(BaseModel): """审计日志分页响应体。""" items: list[AuditLogOut] total: int page: int page_size: int # --- System Metrics --- class SystemMetricOut(BaseModel): """系统监控指标响应体。""" id: uuid.UUID metric_type: str value: dict collected_at: datetime class Config: from_attributes = True class SystemHealthOut(BaseModel): """系统健康状态响应体。""" status: str service: str uptime_seconds: float db_connected: bool redis_connected: bool active_users: int memory_mb: float cpu_percent: float class UsageStatsOut(BaseModel): """使用统计响应体。""" total_users: int active_users_today: int total_sessions: int total_messages: int total_tasks: int total_flows: int published_flows: int api_calls_today: int avg_response_time_ms: float # --- Generic Response --- class ApiResponse(BaseModel): """通用 API 响应包装。""" code: int = 200 message: str = "success" data: dict | list | None = None