146 lines
5.4 KiB
Python
146 lines
5.4 KiB
Python
|
|
# =============================================================================
|
|||
|
|
# 企微IT智能服务台 — 消息 Pydantic Schema
|
|||
|
|
# =============================================================================
|
|||
|
|
# 说明:定义消息相关的请求/响应数据结构
|
|||
|
|
# 支持消息类型:文本(text)/图片(image)/文件(file)/系统(system)
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
from datetime import datetime
|
|||
|
|
from typing import Any, Dict, List, Optional
|
|||
|
|
|
|||
|
|
from pydantic import BaseModel, Field, field_validator
|
|||
|
|
|
|||
|
|
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
# 消息类型和发送者类型的合法值
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
VALID_MSG_TYPES = {"text", "image", "file", "system"}
|
|||
|
|
VALID_SENDER_TYPES = {"employee", "agent", "ai", "system"}
|
|||
|
|
|
|||
|
|
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
# 创建消息 Schema(坐席发送消息时使用)
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
class MessageCreate(BaseModel):
|
|||
|
|
"""创建消息请求 Schema。
|
|||
|
|
|
|||
|
|
坐席发送消息时使用。
|
|||
|
|
支持文本消息和文件/图片消息。
|
|||
|
|
|
|||
|
|
Attributes:
|
|||
|
|
content: 消息内容(文本消息为正文,文件消息为文件URL或描述)
|
|||
|
|
msg_type: 消息类型(默认 text,支持 image/file)
|
|||
|
|
media_url: 媒体文件URL(图片/文件消息时使用)
|
|||
|
|
file_name: 文件名(文件消息时使用)
|
|||
|
|
file_size: 文件大小(字节,文件消息时使用)
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
content: str = Field(..., min_length=1, description="消息内容")
|
|||
|
|
# 支持文本、图片、文件类型
|
|||
|
|
msg_type: str = Field(default="text", description="消息类型: text/image/file")
|
|||
|
|
# M1 新增:文件上传相关字段
|
|||
|
|
media_url: Optional[str] = Field(None, description="媒体文件URL(图片/文件消息时使用)")
|
|||
|
|
file_name: Optional[str] = Field(None, description="文件名")
|
|||
|
|
file_size: Optional[int] = Field(None, description="文件大小(字节)")
|
|||
|
|
# M1 新增:引用回复
|
|||
|
|
reply_to_id: Optional[str] = Field(None, description="引用回复:被回复的消息ID")
|
|||
|
|
|
|||
|
|
@field_validator("msg_type")
|
|||
|
|
@classmethod
|
|||
|
|
def validate_msg_type(cls, v: str) -> str:
|
|||
|
|
"""校验消息类型是否合法。"""
|
|||
|
|
if v not in VALID_MSG_TYPES:
|
|||
|
|
raise ValueError(f"无效的消息类型: {v},合法值为: {VALID_MSG_TYPES}")
|
|||
|
|
return v
|
|||
|
|
|
|||
|
|
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
# 企微回调消息 Schema(从企微接收到的消息)
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
class WecomInboundMessage(BaseModel):
|
|||
|
|
"""企微回调消息 Schema。
|
|||
|
|
|
|||
|
|
解析企微回调 XML 后得到的结构化消息。
|
|||
|
|
|
|||
|
|
Attributes:
|
|||
|
|
from_user_id: 发送者企微UserID
|
|||
|
|
content: 消息内容
|
|||
|
|
msg_type: 消息类型(text/image等)
|
|||
|
|
create_time: 消息创建时间戳
|
|||
|
|
agent_id: 应用AgentID
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from_user_id: str = Field(..., description="发送者企微UserID")
|
|||
|
|
content: str = Field(default="", description="消息内容")
|
|||
|
|
msg_type: str = Field(default="text", description="消息类型")
|
|||
|
|
create_time: Optional[int] = Field(None, description="消息创建时间戳")
|
|||
|
|
agent_id: Optional[str] = Field(None, description="应用AgentID")
|
|||
|
|
|
|||
|
|
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
# 消息响应 Schema(返回给前端的数据结构)
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
class MessageResponse(BaseModel):
|
|||
|
|
"""消息响应 Schema。
|
|||
|
|
|
|||
|
|
返回给前端的消息数据结构。
|
|||
|
|
使用 from_attributes=True 支持从 SQLAlchemy 模型直接转换。
|
|||
|
|
|
|||
|
|
Attributes:
|
|||
|
|
id: 消息ID
|
|||
|
|
conversation_id: 所属会话ID
|
|||
|
|
sender_type: 发送者类型
|
|||
|
|
sender_id: 发送者ID
|
|||
|
|
sender_name: 发送者姓名
|
|||
|
|
content: 消息内容
|
|||
|
|
msg_type: 消息类型
|
|||
|
|
media_url: 媒体文件URL
|
|||
|
|
file_name: 文件名
|
|||
|
|
file_size: 文件大小
|
|||
|
|
extra_data: 扩展元数据
|
|||
|
|
ai_suggestion: 是否为AI建议
|
|||
|
|
is_read: 是否已读
|
|||
|
|
created_at: 创建时间
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
id: str
|
|||
|
|
conversation_id: str
|
|||
|
|
sender_type: str
|
|||
|
|
sender_id: str
|
|||
|
|
sender_name: str
|
|||
|
|
content: str
|
|||
|
|
msg_type: str
|
|||
|
|
# M1 新增:媒体/文件相关字段
|
|||
|
|
media_url: Optional[str] = None
|
|||
|
|
file_name: Optional[str] = None
|
|||
|
|
file_size: Optional[int] = None
|
|||
|
|
extra_data: Optional[Dict[str, Any]] = None
|
|||
|
|
# M1 新增:引用回复
|
|||
|
|
reply_to_id: Optional[str] = None
|
|||
|
|
ai_suggestion: bool
|
|||
|
|
is_read: bool
|
|||
|
|
created_at: datetime
|
|||
|
|
# M2 新增:消息状态和可撤回时间
|
|||
|
|
status: str = "sent"
|
|||
|
|
recallable_until: Optional[datetime] = None
|
|||
|
|
|
|||
|
|
model_config = {"from_attributes": True}
|
|||
|
|
|
|||
|
|
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
# 消息列表响应 Schema
|
|||
|
|
# --------------------------------------------------------------------------
|
|||
|
|
class MessageListResponse(BaseModel):
|
|||
|
|
"""消息列表响应 Schema。
|
|||
|
|
|
|||
|
|
包含消息列表和是否还有更多消息的标志,
|
|||
|
|
用于向上加载历史消息。
|
|||
|
|
|
|||
|
|
Attributes:
|
|||
|
|
items: 消息列表
|
|||
|
|
has_more: 是否还有更多历史消息
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
items: List[MessageResponse]
|
|||
|
|
has_more: bool
|