WIP-CHECKPOINT[auth-refactor]: 固化工程师崩溃前部分成果 + 同树其他未提交WIP(仅源码,不含密钥/二进制)-- 待重激活工程师续作
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 管理员用户 Schema
|
||||
# =============================================================================
|
||||
# 说明:定义管理员用户相关的请求/响应数据结构
|
||||
# 用于用户管理 CRUD 操作
|
||||
# =============================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class AdminUserCreateRequest(BaseModel):
|
||||
"""创建管理员请求 Schema。
|
||||
|
||||
Attributes:
|
||||
user_id: 企微用户ID(唯一)
|
||||
name: 姓名
|
||||
role: 角色(admin/super_admin)
|
||||
password: 初始密码(可选,不传则生成随机密码)
|
||||
"""
|
||||
|
||||
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="admin", description="角色: admin=管理员, super_admin=超级管理员")
|
||||
password: Optional[str] = Field(None, min_length=6, max_length=128, description="初始密码(可选)")
|
||||
|
||||
|
||||
class AdminUserUpdateRequest(BaseModel):
|
||||
"""更新管理员请求 Schema。
|
||||
|
||||
所有字段可选,只更新传入的字段。
|
||||
|
||||
Attributes:
|
||||
name: 姓名
|
||||
role: 角色
|
||||
is_active: 是否激活
|
||||
"""
|
||||
|
||||
name: Optional[str] = Field(None, min_length=1, max_length=128, description="姓名")
|
||||
role: Optional[str] = Field(None, description="角色: admin=管理员, super_admin=超级管理员")
|
||||
is_active: Optional[bool] = Field(None, description="是否激活")
|
||||
|
||||
|
||||
class AdminUserResetPasswordRequest(BaseModel):
|
||||
"""重置密码请求 Schema。
|
||||
|
||||
Attributes:
|
||||
new_password: 新密码
|
||||
"""
|
||||
|
||||
new_password: str = Field(..., min_length=6, max_length=128, description="新密码")
|
||||
|
||||
|
||||
class AdminUserResponse(BaseModel):
|
||||
"""管理员用户响应 Schema。
|
||||
|
||||
Attributes:
|
||||
id: 用户ID
|
||||
user_id: 企微用户ID
|
||||
name: 姓名
|
||||
role: 角色
|
||||
is_active: 是否激活
|
||||
password_hash: 密码哈希(不返回给前端)
|
||||
mfa_enabled: 是否启用MFA
|
||||
mfa_secret: MFA密钥(不返回给前端)
|
||||
created_at: 创建时间
|
||||
updated_at: 更新时间
|
||||
"""
|
||||
|
||||
id: str
|
||||
user_id: str
|
||||
name: str
|
||||
role: str
|
||||
is_active: bool
|
||||
mfa_enabled: bool
|
||||
mfa_bound_at: Optional[datetime] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class AdminUserListResponse(BaseModel):
|
||||
"""管理员列表响应 Schema。
|
||||
|
||||
Attributes:
|
||||
items: 用户列表
|
||||
total: 总数
|
||||
"""
|
||||
|
||||
items: list[AdminUserResponse] = Field(default_factory=list, description="用户列表")
|
||||
total: int = Field(default=0, description="总数")
|
||||
|
||||
|
||||
class AuthLoginRequest(BaseModel):
|
||||
"""账号密码登录请求 Schema。
|
||||
|
||||
Attributes:
|
||||
username: 用户名/账号
|
||||
password: 密码
|
||||
otp_code: OTP 验证码(可选,MFA启用时必填)
|
||||
"""
|
||||
|
||||
username: str = Field(..., min_length=1, description="用户名/账号")
|
||||
password: str = Field(..., min_length=1, description="密码")
|
||||
otp_code: Optional[str] = Field(None, min_length=6, max_length=6, description="OTP 验证码(可选)")
|
||||
|
||||
|
||||
class AuthLoginResponse(BaseModel):
|
||||
"""登录成功响应 Schema。
|
||||
|
||||
Attributes:
|
||||
token: 认证 Token
|
||||
user_id: 用户ID
|
||||
name: 姓名
|
||||
roles: 角色列表
|
||||
require_otp: 是否需要 OTP 验证
|
||||
"""
|
||||
|
||||
token: str
|
||||
user_id: str
|
||||
name: str
|
||||
roles: list[str]
|
||||
require_otp: bool = False
|
||||
@@ -41,9 +41,17 @@ class AgentLogin(BaseModel):
|
||||
|
||||
user_id: str = Field(..., min_length=1, max_length=64, description="企微用户ID")
|
||||
name: str = Field(..., min_length=1, max_length=128, description="坐席姓名")
|
||||
otp_code: Optional[str] = Field(None, min_length=6, max_length=6, description="OTP动态码(6位数字)")
|
||||
otp_code: Optional[str] = Field(None, description="OTP动态码(6位数字)")
|
||||
password: Optional[str] = Field(None, description="本地密码(可选)")
|
||||
|
||||
@field_validator('otp_code')
|
||||
@classmethod
|
||||
def validate_otp_code(cls, v):
|
||||
"""OTP验证码验证:有值时必须是6位数字"""
|
||||
if v is not None and (len(v) != 6 or not v.isdigit()):
|
||||
raise ValueError('OTP验证码必须是6位数字')
|
||||
return v
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 坐席状态更新 Schema
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 阶段5 自动化闭环 Schema
|
||||
# =============================================================================
|
||||
# 说明:定义自动化会话相关接口的 Pydantic 请求/响应模型,以及 ORM → dict
|
||||
# 序列化辅助函数。所有响应沿用项目 {code, data, message} 约定,
|
||||
# 此处只描述 data 结构。
|
||||
# =============================================================================
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 请求模型
|
||||
# --------------------------------------------------------------------------
|
||||
class CreateSessionRequest(BaseModel):
|
||||
"""创建自动化会话请求。"""
|
||||
|
||||
conversation_id: Optional[str] = Field(None, description="关联工单ID(弱关联)")
|
||||
employee_id: str = Field(..., description="发起员工企微 UserID")
|
||||
description: str = Field(..., description="员工诉求/原始消息")
|
||||
mode: str = Field("real_exec", description="执行模式:plan_only / real_exec")
|
||||
|
||||
|
||||
class ApprovalDecisionRequest(BaseModel):
|
||||
"""坐席审批决策请求。"""
|
||||
|
||||
decision: str = Field(..., description="approve / reject")
|
||||
note: Optional[str] = Field(None, description="审批意见")
|
||||
|
||||
|
||||
class ConfirmRequest(BaseModel):
|
||||
"""员工 H5 二次确认请求。"""
|
||||
|
||||
confirmed: bool = Field(..., description="是否确认执行")
|
||||
note: Optional[str] = Field(None, description="备注")
|
||||
|
||||
|
||||
class TakeoverRequest(BaseModel):
|
||||
"""转人工接管请求。"""
|
||||
|
||||
agent_id: str = Field(..., description="接管坐席ID")
|
||||
note: Optional[str] = Field(None, description="接管说明")
|
||||
|
||||
|
||||
class ResolveFeedbackRequest(BaseModel):
|
||||
"""处置结果反馈(员工是否满意)。"""
|
||||
|
||||
satisfied: bool = Field(True, description="是否满意")
|
||||
note: Optional[str] = Field(None, description="反馈备注")
|
||||
|
||||
|
||||
class ScenarioConfigUpdate(BaseModel):
|
||||
"""场景配置更新请求(管理端)。"""
|
||||
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
enabled: Optional[bool] = None
|
||||
trigger_conditions: Optional[dict] = None
|
||||
actions: Optional[list] = None
|
||||
approval_strategy: Optional[dict] = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 响应模型
|
||||
# --------------------------------------------------------------------------
|
||||
class IntentResult(BaseModel):
|
||||
"""意图识别结果。"""
|
||||
|
||||
scenario_key: Optional[str] = None
|
||||
confidence: float = 0.0
|
||||
raw: str = ""
|
||||
error: str = ""
|
||||
|
||||
|
||||
class ActionResponse(BaseModel):
|
||||
"""处置动作响应。"""
|
||||
|
||||
id: str
|
||||
session_id: str
|
||||
action_index: int
|
||||
action_type: str
|
||||
adapter: str
|
||||
risk_level: str
|
||||
title: str
|
||||
description: str
|
||||
status: str
|
||||
payload: Optional[dict] = None
|
||||
result: Optional[dict] = None
|
||||
error: Optional[str] = None
|
||||
approved_by: Optional[str] = None
|
||||
approved_at: Optional[str] = None
|
||||
|
||||
|
||||
class ApprovalTicketResponse(BaseModel):
|
||||
"""审批单响应。"""
|
||||
|
||||
id: str
|
||||
action_id: str
|
||||
session_id: str
|
||||
approver_id: Optional[str] = None
|
||||
channel: str
|
||||
status: str
|
||||
reason: Optional[str] = None
|
||||
decision_note: Optional[str] = None
|
||||
decided_at: Optional[str] = None
|
||||
|
||||
|
||||
class SessionResponse(BaseModel):
|
||||
"""自动化会话响应。"""
|
||||
|
||||
id: str
|
||||
conversation_id: Optional[str] = None
|
||||
employee_id: str
|
||||
agent_id: Optional[str] = None
|
||||
scenario_key: Optional[str] = None
|
||||
status: str
|
||||
mode: str
|
||||
confidence: float
|
||||
title: str
|
||||
intent: Optional[dict] = None
|
||||
current_action_id: Optional[str] = None
|
||||
auto_close_at: Optional[str] = None
|
||||
resolved_at: Optional[str] = None
|
||||
closed_by: Optional[str] = None
|
||||
meta: Optional[dict] = None
|
||||
actions: List[ActionResponse] = Field(default_factory=list)
|
||||
approval: Optional[ApprovalTicketResponse] = None
|
||||
created_at: Optional[str] = None
|
||||
updated_at: Optional[str] = None
|
||||
|
||||
|
||||
class ScenarioConfigResponse(BaseModel):
|
||||
"""场景配置响应。"""
|
||||
|
||||
id: str
|
||||
scenario_key: str
|
||||
name: str
|
||||
description: str
|
||||
enabled: bool
|
||||
trigger_conditions: Optional[dict] = None
|
||||
actions: Optional[list] = None
|
||||
approval_strategy: Optional[dict] = None
|
||||
current_version_id: Optional[str] = None
|
||||
|
||||
|
||||
class RuleVersionResponse(BaseModel):
|
||||
"""规则版本响应。"""
|
||||
|
||||
id: str
|
||||
scenario_key: str
|
||||
version: int
|
||||
content: Optional[dict] = None
|
||||
status: str
|
||||
canary_percent: int
|
||||
created_by: Optional[str] = None
|
||||
remark: str
|
||||
created_at: Optional[str] = None
|
||||
|
||||
|
||||
class AutoMetricsResponse(BaseModel):
|
||||
"""自动化看板指标响应。"""
|
||||
|
||||
total_sessions: int = 0
|
||||
resolved_sessions: int = 0
|
||||
handoff_sessions: int = 0
|
||||
error_sessions: int = 0
|
||||
auto_executed_actions: int = 0
|
||||
approval_required_actions: int = 0
|
||||
by_scenario: Dict[str, int] = Field(default_factory=dict)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 序列化辅助
|
||||
# --------------------------------------------------------------------------
|
||||
def _iso(dt: Optional[datetime]) -> Optional[str]:
|
||||
"""将 datetime 转为 ISO 字符串(None 透传)。"""
|
||||
return dt.isoformat() if dt else None
|
||||
|
||||
|
||||
def serialize_action(action: Any) -> ActionResponse:
|
||||
"""将 AutoAction ORM 对象序列化为响应模型。"""
|
||||
return ActionResponse(
|
||||
id=action.id,
|
||||
session_id=action.session_id,
|
||||
action_index=action.action_index,
|
||||
action_type=action.action_type,
|
||||
adapter=action.adapter,
|
||||
risk_level=action.risk_level,
|
||||
title=action.title,
|
||||
description=action.description,
|
||||
status=action.status,
|
||||
payload=action.payload,
|
||||
result=action.result,
|
||||
error=action.error,
|
||||
approved_by=action.approved_by,
|
||||
approved_at=_iso(action.approved_at),
|
||||
)
|
||||
|
||||
|
||||
def serialize_approval(ticket: Any) -> ApprovalTicketResponse:
|
||||
"""将 ApprovalTicket ORM 对象序列化为响应模型。"""
|
||||
return ApprovalTicketResponse(
|
||||
id=ticket.id,
|
||||
action_id=ticket.action_id,
|
||||
session_id=ticket.session_id,
|
||||
approver_id=ticket.approver_id,
|
||||
channel=ticket.channel,
|
||||
status=ticket.status,
|
||||
reason=ticket.reason,
|
||||
decision_note=ticket.decision_note,
|
||||
decided_at=_iso(ticket.decided_at),
|
||||
)
|
||||
|
||||
|
||||
def serialize_session(
|
||||
session: Any,
|
||||
actions: Optional[List[Any]] = None,
|
||||
ticket: Optional[Any] = None,
|
||||
) -> SessionResponse:
|
||||
"""将 AutoSession ORM 对象序列化为响应模型。"""
|
||||
return SessionResponse(
|
||||
id=session.id,
|
||||
conversation_id=session.conversation_id,
|
||||
employee_id=session.employee_id,
|
||||
agent_id=session.agent_id,
|
||||
scenario_key=session.scenario_key,
|
||||
status=session.status,
|
||||
mode=session.mode,
|
||||
confidence=session.confidence,
|
||||
title=session.title,
|
||||
intent=session.intent,
|
||||
current_action_id=session.current_action_id,
|
||||
auto_close_at=_iso(session.auto_close_at),
|
||||
resolved_at=_iso(session.resolved_at),
|
||||
closed_by=session.closed_by,
|
||||
meta=session.meta,
|
||||
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),
|
||||
)
|
||||
@@ -0,0 +1,46 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 会话标注 Pydantic Schema
|
||||
# =============================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 创建会话标注 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class AnnotationCreate(BaseModel):
|
||||
"""创建会话标注请求 Schema。"""
|
||||
|
||||
conversation_id: str = Field(..., description="会话ID")
|
||||
message_id: str = Field(..., description="被标注的消息ID")
|
||||
feedback: str = Field(..., description="useful=有用/useless=无用")
|
||||
comment: Optional[str] = Field(None, description="备注")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 会话标注响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class AnnotationResponse(BaseModel):
|
||||
"""会话标注响应 Schema。"""
|
||||
|
||||
id: str
|
||||
conversation_id: str
|
||||
agent_id: str
|
||||
message_id: str
|
||||
feedback: str
|
||||
comment: Optional[str] = None
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 会话标注列表响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class AnnotationListResponse(BaseModel):
|
||||
"""会话标注列表响应 Schema。"""
|
||||
|
||||
items: list[AnnotationResponse]
|
||||
@@ -0,0 +1,140 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 满意度评价 Pydantic Schema
|
||||
# =============================================================================
|
||||
# 说明:定义满意度评价的请求/响应数据结构
|
||||
# 包含:评价提交、评价查询、评价统计等
|
||||
# =============================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 评价提交请求 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class EvaluationSubmitRequest(BaseModel):
|
||||
"""满意度评价提交请求 Schema。
|
||||
|
||||
员工提交服务评价时发送的请求。
|
||||
|
||||
Attributes:
|
||||
star_rating: 星级评分(1-5,必选)
|
||||
emoji: 表情评价(satisfied/neutral/dissatisfied,必选)
|
||||
feedback_text: 文字反馈(可选,最大200字)
|
||||
"""
|
||||
|
||||
star_rating: int = Field(
|
||||
...,
|
||||
ge=1,
|
||||
le=5,
|
||||
description="星级评分(1-5)",
|
||||
)
|
||||
emoji: str = Field(
|
||||
...,
|
||||
description="表情评价(satisfied/neutral/dissatisfied)",
|
||||
)
|
||||
feedback_text: Optional[str] = Field(
|
||||
None,
|
||||
max_length=200,
|
||||
description="文字反馈(可选,限200字)",
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 评价记录响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class EvaluationResponse(BaseModel):
|
||||
"""满意度评价响应 Schema。
|
||||
|
||||
返回评价记录详情。
|
||||
|
||||
Attributes:
|
||||
id: 评价记录ID
|
||||
conversation_id: 关联的会话ID
|
||||
employee_id: 评价员工UserID
|
||||
employee_name: 评价员工姓名
|
||||
star_rating: 星级评分
|
||||
emoji: 表情评价
|
||||
feedback_text: 文字反馈
|
||||
created_at: 评价时间
|
||||
"""
|
||||
|
||||
id: str = Field(..., description="评价记录ID")
|
||||
conversation_id: str = Field(..., description="关联的会话ID")
|
||||
employee_id: str = Field(..., description="评价员工UserID")
|
||||
employee_name: str = Field(default="", description="评价员工姓名")
|
||||
star_rating: int = Field(..., description="星级评分(1-5)")
|
||||
emoji: str = Field(..., description="表情评价")
|
||||
feedback_text: Optional[str] = Field(None, description="文字反馈")
|
||||
created_at: datetime = Field(..., description="评价时间")
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 评价统计项 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class EvaluationStatsItem(BaseModel):
|
||||
"""评价统计项 Schema。
|
||||
|
||||
某个具体的统计维度。
|
||||
|
||||
Attributes:
|
||||
label: 统计标签(如"5星"、"满意"等)
|
||||
count: 数量
|
||||
percentage: 占比(百分比)
|
||||
"""
|
||||
|
||||
label: str = Field(..., description="统计标签")
|
||||
count: int = Field(..., description="数量")
|
||||
percentage: float = Field(..., description="占比(百分比)")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 评价统计响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class EvaluationStatsResponse(BaseModel):
|
||||
"""满意度评价统计响应 Schema。
|
||||
|
||||
返回评价数据的统计分析结果,供管理后台使用。
|
||||
|
||||
Attributes:
|
||||
total_count: 总评价数
|
||||
avg_star_rating: 平均星级
|
||||
star_distribution: 星级分布统计
|
||||
emoji_distribution: 表情分布统计
|
||||
recent_evaluations: 最近评价记录(可选)
|
||||
"""
|
||||
|
||||
total_count: int = Field(..., description="总评价数")
|
||||
avg_star_rating: float = Field(..., description="平均星级")
|
||||
star_distribution: List[EvaluationStatsItem] = Field(
|
||||
..., description="星级分布统计"
|
||||
)
|
||||
emoji_distribution: List[EvaluationStatsItem] = Field(
|
||||
..., description="表情分布统计"
|
||||
)
|
||||
recent_evaluations: Optional[List[EvaluationResponse]] = Field(
|
||||
None, description="最近评价记录"
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 评价邀请推送 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class EvaluationInviteRequest(BaseModel):
|
||||
"""评价邀请推送请求 Schema。
|
||||
|
||||
坐席结单后,系统向员工推送评价邀请。
|
||||
|
||||
Attributes:
|
||||
conversation_id: 会话ID
|
||||
employee_id: 员工UserID
|
||||
"""
|
||||
|
||||
conversation_id: str = Field(..., description="会话ID")
|
||||
employee_id: str = Field(..., description="员工UserID")
|
||||
employee_name: str = Field(default="", description="员工姓名")
|
||||
agent_name: str = Field(default="IT服务台", description="坐席姓名")
|
||||
@@ -0,0 +1,63 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 知识库 Pydantic Schema
|
||||
# =============================================================================
|
||||
# 说明:定义知识库FAQ的请求/响应数据结构
|
||||
# 支持 CRUD 操作:创建、读取、更新、删除
|
||||
# =============================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 创建知识库条目 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class KnowledgeBaseCreate(BaseModel):
|
||||
"""创建知识库条目请求 Schema。"""
|
||||
|
||||
category: str = Field(default="其他", max_length=64, description="分类")
|
||||
title: str = Field(..., min_length=1, max_length=256, description="问题标题")
|
||||
content: str = Field(..., min_length=1, description="答案内容")
|
||||
tags: List[str] = Field(default_factory=list, description="标签列表")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 更新知识库条目 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class KnowledgeBaseUpdate(BaseModel):
|
||||
"""更新知识库条目请求 Schema。"""
|
||||
|
||||
category: Optional[str] = Field(None, max_length=64, description="分类")
|
||||
title: Optional[str] = Field(None, max_length=256, description="问题标题")
|
||||
content: Optional[str] = Field(None, description="答案内容")
|
||||
tags: Optional[List[str]] = Field(None, description="标签列表")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 知识库条目响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class KnowledgeBaseResponse(BaseModel):
|
||||
"""知识库条目响应 Schema。"""
|
||||
|
||||
id: str
|
||||
category: str
|
||||
title: str
|
||||
content: str
|
||||
tags: List[str]
|
||||
view_count: int = 0
|
||||
use_count: int = 0
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 知识库列表响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class KnowledgeBaseListResponse(BaseModel):
|
||||
"""知识库列表响应 Schema。"""
|
||||
|
||||
items: List[KnowledgeBaseResponse]
|
||||
@@ -0,0 +1,108 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 知识库优化建议 Pydantic Schema
|
||||
# =============================================================================
|
||||
# 说明:定义知识库优化建议的请求/响应数据结构
|
||||
# 包含:建议创建、审核、列表查询等
|
||||
# =============================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 创建建议请求 Schema
|
||||
# -----------------------------------------------------------------------------
|
||||
class KnowledgeSuggestionCreate(BaseModel):
|
||||
"""创建知识库优化建议请求 Schema。
|
||||
|
||||
通常由AI分析服务自动创建,也可手动创建。
|
||||
"""
|
||||
|
||||
suggestion_type: str = Field(
|
||||
...,
|
||||
description="建议类型:new_faq=新增FAQ/update=更新/outdated=标记过时",
|
||||
)
|
||||
title: str = Field(..., description="建议标题", max_length=256)
|
||||
content: str = Field(..., description="答案内容")
|
||||
category: str = Field(default="其他", description="分类")
|
||||
tags: List[str] = Field(default_factory=list, description="标签列表")
|
||||
source_type: str = Field(
|
||||
...,
|
||||
description="分析来源:annotation=标注数据/conversation=会话数据/ai_uncertain=AI不确定",
|
||||
)
|
||||
source_data: Optional[List[str]] = Field(
|
||||
default=None, description="相关会话ID或标注ID列表"
|
||||
)
|
||||
reason: Optional[str] = Field(default=None, description="生成理由")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 审核建议请求 Schema
|
||||
# -----------------------------------------------------------------------------
|
||||
class KnowledgeSuggestionApprove(BaseModel):
|
||||
"""审核通过知识库优化建议请求 Schema。"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class KnowledgeSuggestionReject(BaseModel):
|
||||
"""拒绝知识库优化建议请求 Schema。"""
|
||||
|
||||
reject_reason: str = Field(..., description="拒绝理由", max_length=500)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 知识库优化建议响应 Schema
|
||||
# -----------------------------------------------------------------------------
|
||||
class KnowledgeSuggestionResponse(BaseModel):
|
||||
"""知识库优化建议响应 Schema。
|
||||
|
||||
返回建议记录详情。
|
||||
"""
|
||||
|
||||
id: str = Field(..., description="建议ID")
|
||||
suggestion_type: str = Field(..., description="建议类型")
|
||||
status: str = Field(..., description="状态")
|
||||
title: str = Field(..., description="标题")
|
||||
content: str = Field(..., description="内容")
|
||||
category: str = Field(..., description="分类")
|
||||
tags: List[str] = Field(default_factory=list, description="标签列表")
|
||||
source_type: str = Field(..., description="分析来源")
|
||||
source_data: Optional[List[str]] = Field(default=None, description="来源数据")
|
||||
reason: Optional[str] = Field(default=None, description="生成理由")
|
||||
reject_reason: Optional[str] = Field(default=None, description="拒绝理由")
|
||||
reviewer_id: Optional[str] = Field(default=None, description="审核人ID")
|
||||
reviewed_at: Optional[datetime] = Field(default=None, description="审核时间")
|
||||
created_at: datetime = Field(..., description="创建时间")
|
||||
updated_at: datetime = Field(..., description="更新时间")
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 知识库优化建议列表响应 Schema
|
||||
# -----------------------------------------------------------------------------
|
||||
class KnowledgeSuggestionListResponse(BaseModel):
|
||||
"""知识库优化建议列表响应 Schema。"""
|
||||
|
||||
total: int = Field(..., description="总数量")
|
||||
items: List[KnowledgeSuggestionResponse] = Field(..., description="建议列表")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 知识库优化建议统计 Schema
|
||||
# -----------------------------------------------------------------------------
|
||||
class KnowledgeSuggestionStatsResponse(BaseModel):
|
||||
"""知识库优化建议统计响应 Schema。"""
|
||||
|
||||
total: int = Field(..., description="总建议数")
|
||||
pending: int = Field(..., description="待审核数")
|
||||
approved: int = Field(..., description="已通过数")
|
||||
rejected: int = Field(..., description="已拒绝数")
|
||||
applied: int = Field(..., description="已应用数")
|
||||
new_faq_count: int = Field(..., description="新增FAQ建议数")
|
||||
update_count: int = Field(..., description="更新建议数")
|
||||
outdated_count: int = Field(..., description="过时标记数")
|
||||
@@ -35,7 +35,7 @@ class MessageCreate(BaseModel):
|
||||
file_size: 文件大小(字节,文件消息时使用)
|
||||
"""
|
||||
|
||||
content: str = Field(..., min_length=1, description="消息内容")
|
||||
content: str = Field(default="", description="消息内容")
|
||||
# 支持文本、图片、文件类型
|
||||
msg_type: str = Field(default="text", description="消息类型: text/image/file")
|
||||
# M1 新增:文件上传相关字段
|
||||
@@ -47,8 +47,11 @@ class MessageCreate(BaseModel):
|
||||
|
||||
@field_validator("msg_type")
|
||||
@classmethod
|
||||
def validate_msg_type(cls, v: str) -> str:
|
||||
def validate_msg_type(cls, v: Optional[str]) -> str:
|
||||
"""校验消息类型是否合法。"""
|
||||
# 处理 None 或 undefined 的情况
|
||||
if v is None or v == "undefined":
|
||||
return "text"
|
||||
if v not in VALID_MSG_TYPES:
|
||||
raise ValueError(f"无效的消息类型: {v},合法值为: {VALID_MSG_TYPES}")
|
||||
return v
|
||||
|
||||
@@ -93,6 +93,25 @@ class QuickReplyResponse(BaseModel):
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 审核快速回复模板 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
class QuickReplyApprove(BaseModel):
|
||||
"""审核通过快速回复模板请求 Schema。"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class QuickReplyReject(BaseModel):
|
||||
"""驳回快速回复模板请求 Schema。
|
||||
|
||||
Attributes:
|
||||
reason: 驳回原因
|
||||
"""
|
||||
|
||||
reason: str = Field(..., min_length=1, max_length=500, description="驳回原因")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 快速回复模板列表响应 Schema
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user