Files

493 lines
17 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# 企微IT智能服务台 — 管理后台 Pydantic Schema
# =============================================================================
# 说明:定义管理后台专用请求/响应数据结构
# 包含:仪表盘、配置管理、坐席管理、集成配置、快速回复审核、
# 分配模式、会话监控、全局搜索等全部 Schema
# =============================================================================
from datetime import datetime
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
# ==========================================================================
# 配置管理 Schema
# ==========================================================================
class ConfigItemResponse(BaseModel):
"""单个配置项响应 Schema。
Attributes:
key: 配置键
value: 配置值
description: 配置说明
value_type: 值类型(boolean/number/string/json_array/json_object
"""
key: str = Field(..., description="配置键")
value: str = Field(..., description="配置值")
description: str = Field(default="", description="配置说明")
value_type: str = Field(default="string", description="值类型: boolean/number/string/json_array/json_object")
model_config = {"from_attributes": True}
class ConfigGroupResponse(BaseModel):
"""配置分组响应 Schema。
按功能前缀将配置项分组,方便前端展示。
Attributes:
name: 分组名称
key_prefix: 配置键前缀
items: 该分组下的配置项列表
"""
name: str = Field(..., description="分组名称")
key_prefix: str = Field(..., description="配置键前缀")
items: List[ConfigItemResponse] = Field(default_factory=list, description="配置项列表")
class ConfigUpdateRequest(BaseModel):
"""配置更新请求 Schema。
Attributes:
value: 新的配置值
"""
value: str = Field(..., min_length=1, description="新的配置值")
class ConfigHistoryItem(BaseModel):
"""配置变更历史条目 Schema。
Attributes:
id: 日志ID
config_key: 配置键
old_value: 变更前的值
new_value: 变更后的值
changed_by: 变更操作人 agent_id
changed_by_name: 变更操作人姓名
changed_at: 变更时间
"""
id: str = Field(..., description="日志ID")
config_key: str = Field(..., description="配置键")
old_value: str = Field(..., description="变更前的值")
new_value: str = Field(..., description="变更后的值")
changed_by: str = Field(..., description="变更操作人 agent_id")
changed_by_name: str = Field(default="", description="变更操作人姓名")
changed_at: datetime = Field(..., description="变更时间")
model_config = {"from_attributes": True}
class ConfigHistoryResponse(BaseModel):
"""配置变更历史响应 Schema。
Attributes:
items: 变更历史条目列表
"""
items: List[ConfigHistoryItem] = Field(default_factory=list, description="变更历史列表")
# ==========================================================================
# 坐席管理 Schema
# ==========================================================================
class AgentCreateRequest(BaseModel):
"""创建坐席请求 Schema。
Attributes:
user_id: 企微用户ID
name: 坐席姓名
role: 角色(admin=组长, agent=坐席)
skill_tags: 技能标签列表
max_load: 最大同时服务数
"""
user_id: str = Field(..., min_length=1, max_length=64, description="企微用户ID")
name: str = Field(..., min_length=1, max_length=128, description="坐席姓名")
role: str = Field(default="agent", description="角色: admin=组长, agent=坐席")
skill_tags: List[str] = Field(default_factory=list, description="技能标签列表")
max_load: int = Field(default=5, ge=1, le=50, description="最大同时服务数")
class AgentUpdateRequest(BaseModel):
"""更新坐席请求 Schema。
所有字段可选,只更新传入的字段。
Attributes:
role: 角色
skill_tags: 技能标签列表
max_load: 最大同时服务数
"""
role: Optional[str] = Field(None, description="角色: admin=组长, agent=坐席")
skill_tags: Optional[List[str]] = Field(None, description="技能标签列表")
max_load: Optional[int] = Field(None, ge=1, le=50, description="最大同时服务数")
class AdminAgentResponse(BaseModel):
"""管理后台坐席响应 Schema(含角色/技能标签/今日结单数)。
Attributes:
id: 坐席ID
user_id: 企微用户ID
name: 坐席姓名
status: 坐席状态
role: 角色
skill_tags: 技能标签列表
current_load: 当前服务会话数
max_load: 最大同时服务数
today_resolved: 今日结单数
created_at: 创建时间
updated_at: 更新时间
"""
id: str
user_id: str
name: str
status: str
role: str = "agent"
skill_tags: List[str] = []
current_load: int = 0
max_load: int = 5
today_resolved: int = 0
otp_secret: Optional[str] = None
otp_enabled: bool = False
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
# =========================================================================
# 集成配置 Schema
# =========================================================================
class IntegrationConfig(BaseModel):
"""集成系统配置 Schema(通用,支持 url_key 和 access_key 两种模式)。
Attributes:
# url_key 模式(Dify / RAGFlow
api_url: API 地址
api_key_set: API Key 是否已设置
# access_key 模式(火绒安全)
access_key_id_set: AccessKey ID 是否已设置
access_key_secret_set: AccessKey Secret 是否已设置
base_url: 内网 Base URL
"""
# url_key 模式(Dify / RAGFlow
api_url: str = Field(default="", description="API 地址")
api_key_set: bool = Field(default=False, description="API Key 是否已设置")
# access_key 模式(火绒安全)
access_key_id_set: bool = Field(default=False, description="AccessKey ID 是否已设置")
access_key_secret_set: bool = Field(default=False, description="AccessKey Secret 是否已设置")
base_url: Optional[str] = Field(default=None, description="内网 Base URL")
# account_password 模式(联软LV7000
api_account_set: bool = Field(default=False, description="API账号是否已设置")
api_password_set: bool = Field(default=False, description="API密码是否已设置")
class IntegrationResponse(BaseModel):
"""集成系统响应 Schema。
Attributes:
id: 集成系统ID(如 dify/ragflow/huorong
name: 集成系统名称
status: 连接状态(connected/partial/disconnected/pending
configurable: 是否可配置
config_type: 配置类型(url_key/access_key),前端据此显示不同表单
config: 配置信息(不可配置时为 None)
"""
id: str = Field(..., description="集成系统ID")
name: str = Field(..., description="集成系统名称")
status: str = Field(default="disconnected", description="连接状态: connected/partial/disconnected/pending")
configurable: bool = Field(default=False, description="是否可配置")
config_type: Optional[str] = Field(default=None, description="配置类型: url_key/access_key/account_password")
config: Optional[IntegrationConfig] = Field(default=None, description="配置信息")
class IntegrationUpdateRequest(BaseModel):
"""集成系统配置更新请求 Schema。
支持三种模式:
- url_key 模式(Dify / RAGFlow):传入 api_url + api_key
- access_key 模式(火绒安全):传入 access_key_id + access_key_secret + base_url
- account_password 模式(联软LV7000):传入 api_account + api_password + base_url + validate_key(可选)
Attributes:
# url_key 模式
api_url: API 地址(可选,火绒/联软模式不需要)
api_key: API Key(可选,火绒/联软模式不需要)
# access_key 模式(火绒)
access_key_id: AccessKey ID(可选)
access_key_secret: AccessKey Secret(可选)
base_url: 内网 Base URL(可选)
# account_password 模式(联软)
api_account: API账号(可选,联软模式)
api_password: API密码(可选,联软模式)
validate_key: 验证密钥(可选,联软模式)
"""
# url_key 模式(Dify / RAGFlow
api_url: Optional[str] = Field(default=None, description="API 地址(Dify/RAGFlow 模式)")
api_key: Optional[str] = Field(default=None, description="API KeyDify/RAGFlow 模式)")
# access_key 模式(火绒安全)
access_key_id: Optional[str] = Field(default=None, description="AccessKey ID(火绒模式)")
access_key_secret: Optional[str] = Field(default=None, description="AccessKey Secret(火绒模式)")
base_url: Optional[str] = Field(default=None, description="内网 Base URL(火绒/联软模式)")
# account_password 模式(联软LV7000
api_account: Optional[str] = Field(default=None, description="API账号(联软模式)")
api_password: Optional[str] = Field(default=None, description="API密码(联软模式)")
validate_key: Optional[str] = Field(default=None, description="验证密钥(联软模式,可选)")
# ==========================================================================
# 快速回复审核 Schema
# ==========================================================================
class QuickReplyReviewRequest(BaseModel):
"""快速回复审核请求 Schema。
Attributes:
action: 审核动作(approve=通过, reject=驳回)
reason: 审核原因/意见(驳回时建议填写)
"""
action: str = Field(..., description="审核动作: approve/reject")
reason: str = Field(default="", description="审核原因/意见")
class AdminQuickReplyResponse(BaseModel):
"""管理后台快速回复响应 Schema(含审核信息)。
Attributes:
id: 模板ID
category: 分类
title: 模板标题
content: 模板内容
variables: 可用变量列表
status: 状态
version: 版本号
submitted_by: 提交人 agent_id
submitted_by_name: 提交人姓名
sort_order: 排序权重
created_at: 创建时间
updated_at: 更新时间
"""
id: str
category: str
title: str
content: str
variables: List[str]
status: str = "approved"
version: int = 1
submitted_by: Optional[str] = None
submitted_by_name: str = ""
sort_order: int = 0
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
# ==========================================================================
# 分配模式 Schema
# ==========================================================================
class AssignmentModeItem(BaseModel):
"""分配模式条目 Schema。
Attributes:
id: 模式ID
name: 模式名称
enabled: 是否启用
locked: 是否锁定(阶段一锁定部分模式)
unlock_at: 解锁阶段说明
"""
id: str = Field(..., description="模式ID")
name: str = Field(..., description="模式名称")
enabled: bool = Field(default=False, description="是否启用")
locked: bool = Field(default=True, description="是否锁定")
unlock_at: str = Field(default="", description="解锁阶段说明")
class AssignmentModeResponse(BaseModel):
"""分配模式响应 Schema。
Attributes:
current_mode: 当前启用的分配模式
modes: 所有分配模式列表
"""
current_mode: str = Field(default="manual", description="当前分配模式")
modes: List[AssignmentModeItem] = Field(default_factory=list, description="分配模式列表")
class AssignmentModeUpdateRequest(BaseModel):
"""分配模式更新请求 Schema。
Attributes:
mode: 要切换的分配模式ID
"""
mode: str = Field(..., description="分配模式ID")
# ==========================================================================
# 仪表盘 Schema
# ==========================================================================
class SystemAlertItem(BaseModel):
"""单条系统告警 Schema。
与前端 SystemAlert 接口对齐,支持结构化告警展示。
Attributes:
type: 告警类型(如 quick_reply_pending / agent_offline / system_error
content: 告警内容描述
submitter: 提交人姓名(仅快速回复待审核类告警有值)
time: 告警发生时间(ISO 8601 格式)
severity: 严重程度(info/warning/critical
"""
type: str = Field(..., description="告警类型")
content: str = Field(..., description="告警内容")
submitter: Optional[str] = Field(default=None, description="提交人")
time: str = Field(..., description="告警时间")
severity: str = Field(default="info", description="严重程度: info/warning/critical")
class IntegrationHealthItem(BaseModel):
"""集成系统健康状态条目 Schema。
Attributes:
system: 系统名称
status: 连接状态
"""
system: str = Field(..., description="系统名称")
status: str = Field(default="disconnected", description="连接状态")
class DashboardOverviewResponse(BaseModel):
"""仪表盘总览响应 Schema。
Attributes:
online_agents: 在线坐席数
today_conversations: 今日会话数
avg_response_time: 平均响应时间(阶段一占位)
ai_hit_rate: AI 命中率(阶段一占位)
pending_reviews: 待审核快速回复数
system_alerts: 系统告警列表
integrations_health: 集成系统健康状态
"""
online_agents: int = Field(default=0, description="在线坐席数")
today_conversations: int = Field(default=0, description="今日会话数")
avg_response_time: str = Field(default="", description="平均响应时间(阶段一占位)")
ai_hit_rate: str = Field(default="", description="AI命中率(阶段一占位)")
pending_reviews: int = Field(default=0, description="待审核快速回复数")
system_alerts: List[SystemAlertItem] = Field(default_factory=list, description="系统告警列表")
integrations_health: List[IntegrationHealthItem] = Field(default_factory=list, description="集成系统健康状态")
# ==========================================================================
# 会话监控 Schema
# ==========================================================================
class SessionStats(BaseModel):
"""会话统计 Schema。
Attributes:
in_progress: 服务中会话数
queued: 排队中会话数
resolved_today: 今日已结单数
alerts: 告警数
"""
in_progress: int = Field(default=0, description="服务中会话数")
queued: int = Field(default=0, description="排队中会话数")
resolved_today: int = Field(default=0, description="今日已结单数")
alerts: int = Field(default=0, description="告警数")
class SessionItem(BaseModel):
"""会话条目 Schema(监控列表用)。
Attributes:
id: 会话ID
employee_name: 员工姓名
status: 会话状态
assigned_agent_name: 负责坐席姓名
urgency_score: 紧急度评分
created_at: 创建时间
last_message_summary: 最后消息摘要
"""
id: str = Field(..., description="会话ID")
employee_name: str = Field(default="", description="员工姓名")
status: str = Field(default="queued", description="会话状态")
assigned_agent_name: str = Field(default="", description="负责坐席姓名")
urgency_score: int = Field(default=1, description="紧急度评分")
created_at: datetime = Field(..., description="创建时间")
last_message_summary: str = Field(default="", description="最后消息摘要")
class MonitorSessionsResponse(BaseModel):
"""会话监控响应 Schema。
Attributes:
stats: 会话统计
items: 会话列表
"""
stats: SessionStats = Field(..., description="会话统计")
items: List[SessionItem] = Field(default_factory=list, description="会话列表")
# ==========================================================================
# 全局搜索 Schema
# ==========================================================================
class SearchItem(BaseModel):
"""搜索结果条目 Schema。
Attributes:
type: 结果类型(config/agent/quick_reply
id: 对象ID
name: 对象名称/标题
route: 前端路由路径
"""
type: str = Field(..., description="结果类型: config/agent/quick_reply")
id: str = Field(..., description="对象ID")
name: str = Field(..., description="对象名称/标题")
route: str = Field(..., description="前端路由路径")
class SearchResponse(BaseModel):
"""搜索结果响应 Schema。
Attributes:
items: 搜索结果列表
"""
items: List[SearchItem] = Field(default_factory=list, description="搜索结果列表")