feat: 2026-07-11 全量更新 - 代办集成+会议室预定+知识迭代修复+UI统一+Bug修复
== 已部署上线 (9项) == - 代办事项真实数据源集成 (企微审批API 8bug修复链) - H5/坐席端 Logo样式统一+绿色背景 - 视频引导页修复 (localStorage key v2) - 坐席端 v9 Vue版本修复 (ElMessage._context) - 截图按钮 v10 修复 (getDisplayMedia user gesture) - 扫码样式恢复+H5扫码登录跳转修复 - H5截图快捷键提示 == 代码完成待部署 (3项) == - 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查) - 会议室预定-小鱼易联终端 (40文件, 40/40测试通过) - IT资产升级审批推送 (asset_service.py) == 需求文档 (2项) == - 坐席端AI辅助消息框-PRD (4项新功能确认) - 坐席端布局优化建议 v2.0 (7天计划) == 新增文档 == - 日报-2026-07-11.md - 知识迭代Bug修复报告-20260711.md - 会议室预定-部署指南.md - CHANGELOG.md 更新 == 测试 == - test_todo_integration.py: 40/40 - test_meetingroom.py: 40/40 - test_bugfix_ki_suggestions.py: 21/21
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 认证 API Schema
|
||||
# =============================================================================
|
||||
# 说明:定义认证相关的请求/响应数据结构
|
||||
# 包含:统一认证API的请求/响应 Schema
|
||||
# 三端认证重构:取消OTP/账号密码登录,统一为企微扫码认证
|
||||
# =============================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 登录方式合法值
|
||||
# --------------------------------------------------------------------------
|
||||
VALID_LOGIN_METHODS = {"oauth", "qrcode", "bind"}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 登录来源合法值
|
||||
# --------------------------------------------------------------------------
|
||||
VALID_LOGIN_SOURCES = {"h5", "agent", "admin"}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 登录状态合法值
|
||||
# --------------------------------------------------------------------------
|
||||
VALID_LOGIN_STATUSES = {"success", "failed", "cancelled"}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Token 验证响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class TokenVerifyRequest(BaseModel):
|
||||
"""Token 验证请求 Schema。
|
||||
|
||||
用于验证 Token 有效性。
|
||||
|
||||
Attributes:
|
||||
token: 要验证的 Token 字符串
|
||||
"""
|
||||
|
||||
token: str = Field(..., description="要验证的 Token 字符串")
|
||||
|
||||
|
||||
class TokenVerifyResponse(BaseModel):
|
||||
"""Token 验证响应 Schema。
|
||||
|
||||
Attributes:
|
||||
valid: Token 是否有效
|
||||
employee_id: 员工ID
|
||||
name: 员工姓名
|
||||
roles: 角色列表
|
||||
current_role: 当前角色
|
||||
login_source: 登录来源
|
||||
expires_in: 剩余有效期(秒)
|
||||
"""
|
||||
|
||||
valid: bool = Field(..., description="Token 是否有效")
|
||||
employee_id: Optional[str] = Field(None, description="员工ID")
|
||||
name: Optional[str] = Field(None, description="员工姓名")
|
||||
roles: List[str] = Field(default_factory=list, description="角色列表")
|
||||
current_role: Optional[str] = Field(None, description="当前角色")
|
||||
login_source: Optional[str] = Field(None, description="登录来源")
|
||||
expires_in: Optional[int] = Field(None, description="剩余有效期(秒)")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 当前用户信息响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class CurrentUserResponse(BaseModel):
|
||||
"""当前用户信息响应 Schema。
|
||||
|
||||
Attributes:
|
||||
employee_id: 员工ID
|
||||
name: 员工姓名
|
||||
avatar: 头像URL
|
||||
department: 部门
|
||||
roles: 角色列表
|
||||
current_role: 当前角色
|
||||
login_source: 登录来源
|
||||
"""
|
||||
|
||||
employee_id: str = Field(..., description="员工ID")
|
||||
name: str = Field(..., description="员工姓名")
|
||||
avatar: str = Field(default="", description="头像URL")
|
||||
department: str = Field(default="", description="部门")
|
||||
roles: List[str] = Field(default_factory=list, description="角色列表")
|
||||
current_role: str = Field(..., description="当前角色")
|
||||
login_source: str = Field(default="", description="登录来源")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 登录日志响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class LoginLogResponse(BaseModel):
|
||||
"""登录日志响应 Schema。
|
||||
|
||||
Attributes:
|
||||
id: 日志ID
|
||||
employee_id: 员工ID
|
||||
corp_id: 企业ID
|
||||
login_method: 登录方式
|
||||
login_source: 登录来源
|
||||
ip_address: 客户端IP
|
||||
user_agent: 客户端User-Agent
|
||||
status: 登录状态
|
||||
fail_reason: 失败原因
|
||||
created_at: 登录时间
|
||||
"""
|
||||
|
||||
id: str = Field(..., description="日志ID")
|
||||
employee_id: Optional[str] = Field(None, description="员工ID")
|
||||
corp_id: str = Field(..., description="企业ID")
|
||||
login_method: str = Field(..., description="登录方式")
|
||||
login_source: str = Field(..., description="登录来源")
|
||||
ip_address: Optional[str] = Field(None, description="客户端IP")
|
||||
user_agent: Optional[str] = Field(None, description="客户端User-Agent")
|
||||
status: str = Field(..., description="登录状态")
|
||||
fail_reason: Optional[str] = Field(None, description="失败原因")
|
||||
created_at: datetime = Field(..., description="登录时间")
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 登录日志列表响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class LoginLogListResponse(BaseModel):
|
||||
"""登录日志列表响应 Schema。
|
||||
|
||||
Attributes:
|
||||
items: 日志列表
|
||||
total: 总数
|
||||
"""
|
||||
|
||||
items: List[LoginLogResponse] = Field(default_factory=list, description="日志列表")
|
||||
total: int = Field(..., description="总数")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 统一认证响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class UnifiedAuthResponse(BaseModel):
|
||||
"""统一认证响应 Schema。
|
||||
|
||||
Attributes:
|
||||
token: 访问令牌
|
||||
employee_id: 员工ID
|
||||
name: 员工姓名
|
||||
avatar: 头像URL
|
||||
department: 部门
|
||||
roles: 角色列表
|
||||
current_role: 当前角色
|
||||
login_source: 登录来源
|
||||
expires_in: 有效期(秒)
|
||||
"""
|
||||
|
||||
token: str = Field(..., description="访问令牌")
|
||||
employee_id: str = Field(..., description="员工ID")
|
||||
name: str = Field(..., description="员工姓名")
|
||||
avatar: str = Field(default="", description="头像URL")
|
||||
department: str = Field(default="", description="部门")
|
||||
roles: List[str] = Field(default_factory=list, description="角色列表")
|
||||
current_role: str = Field(..., description="当前角色")
|
||||
login_source: str = Field(..., description="登录来源")
|
||||
expires_in: int = Field(..., description="有效期(秒)")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 登出响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class LogoutResponse(BaseModel):
|
||||
"""登出响应 Schema。
|
||||
|
||||
Attributes:
|
||||
success: 是否成功
|
||||
message: 消息
|
||||
"""
|
||||
|
||||
success: bool = Field(..., description="是否成功")
|
||||
message: str = Field(..., description="消息")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 角色切换请求 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class SwitchRoleRequest(BaseModel):
|
||||
"""角色切换请求 Schema。
|
||||
|
||||
Attributes:
|
||||
role: 目标角色
|
||||
"""
|
||||
|
||||
role: str = Field(..., description="目标角色")
|
||||
|
||||
|
||||
class SwitchRoleResponse(BaseModel):
|
||||
"""角色切换响应 Schema。
|
||||
|
||||
Attributes:
|
||||
success: 是否成功
|
||||
current_role: 当前角色
|
||||
message: 消息
|
||||
"""
|
||||
|
||||
success: bool = Field(..., description="是否成功")
|
||||
current_role: str = Field(..., description="当前角色")
|
||||
message: str = Field(..., description="消息")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 账号绑定请求 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class BindAccountRequest(BaseModel):
|
||||
"""账号绑定请求 Schema。
|
||||
|
||||
用于互联企业用户绑定已有账号。
|
||||
|
||||
Attributes:
|
||||
employee_id: 员工UserID(企微 userid)
|
||||
corp_id: 企业ID(可选,默认使用系统配置的主企业ID)
|
||||
bind_type: 绑定方式(existing=绑定已有账号, new=申请新账号)
|
||||
employee_no: 员工工号(bind_type=existing 时必填)
|
||||
real_name: 真实姓名(bind_type=new 时必填)
|
||||
department: 部门
|
||||
phone: 手机号
|
||||
"""
|
||||
|
||||
employee_id: str = Field(..., description="员工UserID(企微 userid)")
|
||||
corp_id: Optional[str] = Field(None, description="企业ID(可选,默认使用系统配置)")
|
||||
bind_type: Optional[str] = Field("existing", description="绑定方式")
|
||||
employee_no: Optional[str] = Field(None, description="员工工号")
|
||||
real_name: Optional[str] = Field(None, description="真实姓名")
|
||||
department: Optional[str] = Field(None, description="部门")
|
||||
phone: Optional[str] = Field(None, description="手机号")
|
||||
@@ -128,6 +128,8 @@ class SessionResponse(BaseModel):
|
||||
resolved_at: Optional[str] = None
|
||||
closed_by: Optional[str] = None
|
||||
meta: Optional[dict] = None
|
||||
# 复杂场景重构:暂停时间戳
|
||||
paused_at: Optional[str] = None
|
||||
actions: List[ActionResponse] = Field(default_factory=list)
|
||||
approval: Optional[ApprovalTicketResponse] = None
|
||||
created_at: Optional[str] = None
|
||||
@@ -239,8 +241,230 @@ def serialize_session(
|
||||
resolved_at=_iso(session.resolved_at),
|
||||
closed_by=session.closed_by,
|
||||
meta=session.meta,
|
||||
paused_at=_iso(session.paused_at),
|
||||
actions=[serialize_action(a) for a in (actions or [])],
|
||||
approval=serialize_approval(ticket) if ticket else None,
|
||||
created_at=_iso(session.created_at),
|
||||
updated_at=_iso(session.updated_at),
|
||||
)
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# 复杂场景重构第一阶段 — 新增 Schema
|
||||
# ===========================================================================
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 全局意图识别结果(扩展 IntentResult)
|
||||
# --------------------------------------------------------------------------
|
||||
class GlobalIntentResult(BaseModel):
|
||||
"""全局意图识别结果。"""
|
||||
|
||||
global_intent: Optional[str] = None # pause / resume_task / correct / supplement / null
|
||||
scenario_key: Optional[str] = None # 未命中全局意图时走场景识别
|
||||
confidence: float = 0.0
|
||||
corrected_field: Optional[str] = None # CORRECT: 更正的字段名
|
||||
old_value: Optional[str] = None # CORRECT: 旧值
|
||||
new_value: Optional[str] = None # CORRECT: 新值
|
||||
supplement_field: Optional[str] = None # SUPPLEMENT: 补充的字段名
|
||||
supplement_value: Optional[str] = None # SUPPLEMENT: 补充的值
|
||||
raw: str = ""
|
||||
error: str = ""
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 请求模型(复杂场景重构)
|
||||
# --------------------------------------------------------------------------
|
||||
class PauseRequest(BaseModel):
|
||||
"""暂停会话请求(通常由意图识别触发,也可直接调用)。"""
|
||||
|
||||
reason: Optional[str] = None
|
||||
|
||||
|
||||
class ResumeRequest(BaseModel):
|
||||
"""恢复会话请求。"""
|
||||
|
||||
session_id: Optional[str] = None # 多任务时指定恢复哪个;None 则自动选择唯一的
|
||||
|
||||
|
||||
class CorrectRequest(BaseModel):
|
||||
"""信息更正请求。"""
|
||||
|
||||
field: str = Field(..., description="更正的字段名")
|
||||
new_value: str = Field(..., description="新值")
|
||||
old_value: Optional[str] = None
|
||||
|
||||
|
||||
class SupplementRequest(BaseModel):
|
||||
"""信息补充请求。"""
|
||||
|
||||
field: str = Field(..., description="补充的字段名")
|
||||
value: str = Field(..., description="补充的值")
|
||||
|
||||
|
||||
class AgentResumeRequest(BaseModel):
|
||||
"""坐席代恢复请求。"""
|
||||
|
||||
note: Optional[str] = None
|
||||
|
||||
|
||||
class AgentCloseRequest(BaseModel):
|
||||
"""坐席关闭会话请求。"""
|
||||
|
||||
note: Optional[str] = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 响应模型(复杂场景重构)
|
||||
# --------------------------------------------------------------------------
|
||||
class InformationItemResponse(BaseModel):
|
||||
"""信息项响应。"""
|
||||
|
||||
id: str
|
||||
session_id: str
|
||||
name: str
|
||||
value: str
|
||||
modifiers: List[str] = Field(default_factory=list)
|
||||
is_filled: bool
|
||||
is_locked: bool
|
||||
version: int
|
||||
update_history: List[dict] = Field(default_factory=list)
|
||||
updated_at: Optional[str] = None
|
||||
|
||||
|
||||
class ResumePointResponse(BaseModel):
|
||||
"""恢复点响应。"""
|
||||
|
||||
session_id: str
|
||||
title: str
|
||||
scenario_key: Optional[str] = None
|
||||
current_step: str
|
||||
paused_at: Optional[str] = None
|
||||
pending_items: List[str] = Field(default_factory=list)
|
||||
info_items: List[InformationItemResponse] = Field(default_factory=list)
|
||||
|
||||
|
||||
class PausedSessionItem(BaseModel):
|
||||
"""暂停会话列表项。"""
|
||||
|
||||
session_id: str
|
||||
title: str
|
||||
scenario_key: Optional[str] = None
|
||||
paused_at: Optional[str] = None
|
||||
paused_duration: str = "" # 如 "2h 15min"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 序列化辅助(复杂场景重构)
|
||||
# --------------------------------------------------------------------------
|
||||
def serialize_information_item(item: Any) -> InformationItemResponse:
|
||||
"""将 InformationItem ORM 对象序列化为响应模型。"""
|
||||
return InformationItemResponse(
|
||||
id=item.id,
|
||||
session_id=item.session_id,
|
||||
name=item.name,
|
||||
value=item.value,
|
||||
modifiers=item.modifiers or [],
|
||||
is_filled=item.is_filled,
|
||||
is_locked=item.is_locked,
|
||||
version=item.version,
|
||||
update_history=item.update_history or [],
|
||||
updated_at=_iso(item.updated_at),
|
||||
)
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# 复杂场景重构第二阶段 — P2/P3 新增 Schema
|
||||
# ===========================================================================
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# P3 请求模型
|
||||
# --------------------------------------------------------------------------
|
||||
class BatchCorrectRequest(BaseModel):
|
||||
"""批量更正请求。"""
|
||||
|
||||
corrections: List[dict] = Field(
|
||||
..., description="更正列表 [{field, new_value, old_value?}, ...]"
|
||||
)
|
||||
reason: Optional[str] = Field(None, description="更正备注")
|
||||
|
||||
|
||||
class UndoCorrectionRequest(BaseModel):
|
||||
"""撤销更正请求。"""
|
||||
|
||||
pass # 无参数,撤销最近一次更正
|
||||
|
||||
|
||||
class VersionDiffRequest(BaseModel):
|
||||
"""版本对比请求。"""
|
||||
|
||||
v1: int = Field(..., description="版本号1")
|
||||
v2: int = Field(..., description="版本号2")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# P3 响应模型
|
||||
# --------------------------------------------------------------------------
|
||||
class BatchCorrectResponse(BaseModel):
|
||||
"""批量更正响应。"""
|
||||
|
||||
corrected_items: List[dict] = Field(default_factory=list)
|
||||
snapshot_id: int
|
||||
dependency_warnings: List[dict] = Field(default_factory=list)
|
||||
|
||||
|
||||
class UndoCorrectionResponse(BaseModel):
|
||||
"""撤销更正响应。"""
|
||||
|
||||
undone_items: List[str] = Field(default_factory=list)
|
||||
restored_values: Dict[str, str] = Field(default_factory=dict)
|
||||
snapshot_id: int
|
||||
remaining_undo_count: int = 5
|
||||
|
||||
|
||||
class CorrectionHistoryResponse(BaseModel):
|
||||
"""更正历史响应。"""
|
||||
|
||||
history: List[dict] = Field(default_factory=list)
|
||||
|
||||
|
||||
class VersionChainResponse(BaseModel):
|
||||
"""版本链响应。"""
|
||||
|
||||
item_key: str
|
||||
chain: List[dict] = Field(default_factory=list)
|
||||
|
||||
|
||||
class VersionDiffResponse(BaseModel):
|
||||
"""版本对比响应。"""
|
||||
|
||||
item_key: str
|
||||
v1: int
|
||||
v1_value: str
|
||||
v2: int
|
||||
v2_value: str
|
||||
changed: bool
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# P2 响应模型
|
||||
# --------------------------------------------------------------------------
|
||||
class CompressionLogItem(BaseModel):
|
||||
"""压缩日志项。"""
|
||||
|
||||
id: int
|
||||
session_id: str
|
||||
tokens_before: int
|
||||
tokens_after: int
|
||||
compression_ratio: float
|
||||
task_node: Optional[str] = None
|
||||
duration_ms: int
|
||||
compression_level: int
|
||||
summary: Optional[str] = None
|
||||
created_at: Optional[str] = None
|
||||
|
||||
|
||||
class CompressionLogListResponse(BaseModel):
|
||||
"""压缩日志列表响应。"""
|
||||
|
||||
logs: List[CompressionLogItem] = Field(default_factory=list)
|
||||
total: int = 0
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 会议室预定 Pydantic 请求/响应模型
|
||||
# =============================================================================
|
||||
# 说明:定义会议室预定API的请求和响应数据模型
|
||||
# =============================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 会议室列表相关
|
||||
# =============================================================================
|
||||
|
||||
class MeetingroomItem(BaseModel):
|
||||
"""会议室信息项。"""
|
||||
|
||||
meetingroom_id: int = Field(..., description="企微会议室ID")
|
||||
name: str = Field(..., description="会议室名称")
|
||||
capacity: int = Field(0, description="容纳人数")
|
||||
location: str = Field("", description="位置描述")
|
||||
devices: List[int] = Field(default_factory=list, description="设备列表")
|
||||
need_approval: int = Field(0, description="是否需要审批(0=不需要, 1=需要)")
|
||||
|
||||
|
||||
class MeetingroomListResponse(BaseModel):
|
||||
"""会议室列表响应数据。"""
|
||||
|
||||
rooms: List[MeetingroomItem] = Field(default_factory=list, description="会议室列表")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 预定状态查询相关
|
||||
# =============================================================================
|
||||
|
||||
class BookingItem(BaseModel):
|
||||
"""预定记录项。"""
|
||||
|
||||
booking_id: str = Field(..., description="企微预定ID")
|
||||
subject: str = Field("", description="会议主题")
|
||||
booker: str = Field("", description="预定人userid")
|
||||
booker_name: str = Field("", description="预定人姓名")
|
||||
start_time: str = Field(..., description="开始时间(ISO 8601)")
|
||||
end_time: str = Field(..., description="结束时间(ISO 8601)")
|
||||
status: int = Field(0, description="预定状态(0=已预定, 1=已取消)")
|
||||
|
||||
|
||||
class BookingInfoResponse(BaseModel):
|
||||
"""预定状态查询响应数据。"""
|
||||
|
||||
bookings: List[BookingItem] = Field(default_factory=list, description="预定记录列表")
|
||||
|
||||
|
||||
class RoomStatusResponse(BaseModel):
|
||||
"""会议室实时状态响应数据。"""
|
||||
|
||||
status: str = Field(..., description="当前状态(free/busy/starting_soon)")
|
||||
current_meeting: Optional[BookingItem] = Field(None, description="当前进行中的会议")
|
||||
next_meeting: Optional[BookingItem] = Field(None, description="下一个会议")
|
||||
minutes_to_next: Optional[int] = Field(None, description="距下一个会议开始的分钟数")
|
||||
bookings: List[BookingItem] = Field(default_factory=list, description="当日预定列表")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 预定操作相关
|
||||
# =============================================================================
|
||||
|
||||
class BookRequest(BaseModel):
|
||||
"""预定会议室请求。"""
|
||||
|
||||
meetingroom_id: int = Field(..., description="企微会议室ID")
|
||||
subject: str = Field(..., min_length=1, max_length=200, description="会议主题")
|
||||
start_time: str = Field(..., description="开始时间(ISO 8601)")
|
||||
end_time: str = Field(..., description="结束时间(ISO 8601)")
|
||||
booker: str = Field(..., description="预定人userid")
|
||||
attendees: Optional[List[str]] = Field(None, description="参与人userid列表(可选)")
|
||||
|
||||
|
||||
class BookResponse(BaseModel):
|
||||
"""预定会议室响应数据。"""
|
||||
|
||||
booking_id: str = Field(..., description="企微预定ID")
|
||||
|
||||
|
||||
class CancelRequest(BaseModel):
|
||||
"""取消预定请求。"""
|
||||
|
||||
meetingroom_id: int = Field(..., description="企微会议室ID")
|
||||
|
||||
|
||||
class BookingDetailResponse(BaseModel):
|
||||
"""预定详情响应数据。"""
|
||||
|
||||
booking_id: str = Field(..., description="企微预定ID")
|
||||
subject: str = Field("", description="会议主题")
|
||||
booker: str = Field("", description="预定人userid")
|
||||
booker_name: str = Field("", description="预定人姓名")
|
||||
attendees: List[str] = Field(default_factory=list, description="参与人列表")
|
||||
start_time: str = Field(..., description="开始时间")
|
||||
end_time: str = Field(..., description="结束时间")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 终端绑定管理相关
|
||||
# =============================================================================
|
||||
|
||||
class TerminalBindingCreate(BaseModel):
|
||||
"""新增终端绑定请求。"""
|
||||
|
||||
terminal_sn: str = Field(..., min_length=1, max_length=64, description="终端序列号")
|
||||
terminal_name: str = Field("", max_length=100, description="终端名称")
|
||||
meetingroom_id: int = Field(..., description="企微会议室ID")
|
||||
meetingroom_name: str = Field("", max_length=100, description="会议室名称")
|
||||
location: str = Field("", max_length=200, description="位置描述")
|
||||
|
||||
|
||||
class TerminalBindingUpdate(BaseModel):
|
||||
"""更新终端绑定请求。"""
|
||||
|
||||
terminal_name: Optional[str] = Field(None, max_length=100, description="终端名称")
|
||||
meetingroom_id: Optional[int] = Field(None, description="企微会议室ID")
|
||||
meetingroom_name: Optional[str] = Field(None, max_length=100, description="会议室名称")
|
||||
location: Optional[str] = Field(None, max_length=200, description="位置描述")
|
||||
is_active: Optional[bool] = Field(None, description="是否启用")
|
||||
|
||||
|
||||
class TerminalBindingResponse(BaseModel):
|
||||
"""终端绑定响应数据。"""
|
||||
|
||||
id: int
|
||||
terminal_sn: str
|
||||
terminal_name: str
|
||||
meetingroom_id: int
|
||||
meetingroom_name: str
|
||||
location: str
|
||||
is_active: bool
|
||||
created_at: str
|
||||
updated_at: str
|
||||
|
||||
|
||||
class TerminalBindingListResponse(BaseModel):
|
||||
"""终端绑定列表响应数据。"""
|
||||
|
||||
list: List[TerminalBindingResponse] = Field(default_factory=list)
|
||||
total: int = 0
|
||||
@@ -128,6 +128,8 @@ class MessageResponse(BaseModel):
|
||||
recallable_until: Optional[datetime] = None
|
||||
# 服务端时间戳(毫秒)
|
||||
server_timestamp: Optional[int] = None
|
||||
# 发送者头像(AI用静态图,员工/坐席用企微API获取)
|
||||
sender_avatar: Optional[str] = None
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ from pydantic import BaseModel, Field, field_validator
|
||||
# --------------------------------------------------------------------------
|
||||
# 待办类型和优先级的合法值
|
||||
# --------------------------------------------------------------------------
|
||||
VALID_TODO_TYPES = {"ticket", "approval", "device"}
|
||||
VALID_TODO_TYPES = {"ticket", "approval"}
|
||||
VALID_TODO_PRIORITIES = {"urgent", "high", "normal"}
|
||||
VALID_TODO_STATUSES = {"pending", "processing", "resolved"}
|
||||
|
||||
@@ -26,7 +26,7 @@ class TodoItemCreate(BaseModel):
|
||||
"""创建待办事项请求 Schema。
|
||||
|
||||
Attributes:
|
||||
type: 待办类型(ticket/approval/device)
|
||||
type: 待办类型(ticket/approval)
|
||||
title: 待办标题
|
||||
priority: 优先级(urgent/high/normal)
|
||||
description: 详细描述(JSON)
|
||||
@@ -34,7 +34,7 @@ class TodoItemCreate(BaseModel):
|
||||
corp_id: 企业微信企业ID
|
||||
"""
|
||||
|
||||
type: str = Field(default="ticket", description="待办类型: ticket/approval/device")
|
||||
type: str = Field(default="ticket", description="待办类型: ticket/approval")
|
||||
title: str = Field(..., min_length=1, max_length=256, description="待办标题")
|
||||
priority: str = Field(default="normal", description="优先级: urgent/high/normal")
|
||||
description: Dict[str, Any] = Field(default_factory=dict, description="详细描述")
|
||||
@@ -75,7 +75,7 @@ class TodoItemUpdate(BaseModel):
|
||||
assigned_agent_id: 分配的坐席ID
|
||||
"""
|
||||
|
||||
type: Optional[str] = Field(None, description="待办类型: ticket/approval/device")
|
||||
type: Optional[str] = Field(None, description="待办类型: ticket/approval")
|
||||
title: Optional[str] = Field(None, max_length=256, description="待办标题")
|
||||
priority: Optional[str] = Field(None, description="优先级: urgent/high/normal")
|
||||
description: Optional[Dict[str, Any]] = Field(None, description="详细描述")
|
||||
|
||||
Reference in New Issue
Block a user