Files

440 lines
14 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智能服务台 — 待办事项 API
# =============================================================================
# 说明:提供待办事项的 CRUD 接口
# 接口列表:
# GET /api/todo-items — 获取当前坐席待办列表
# GET /api/todo-items/{id} — 获取待办详情
# PUT /api/todo-items/{id}/status — 更新待办状态
# Mock: 预置示例待办数据,不连接真实外部系统
# =============================================================================
from datetime import datetime
from typing import List, Optional
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field
from app.utils.response import success_response, AppException
# 创建路由器
router = APIRouter(prefix="/todo-items", tags=["待办事项"])
# --------------------------------------------------------------------------
# 请求/响应 Schema
# --------------------------------------------------------------------------
class TodoStatusUpdateRequest(BaseModel):
"""更新待办状态请求 Schema。"""
status: str = Field(..., description="新状态: pending/processing/resolved")
class TodoItemResponse(BaseModel):
"""待办事项响应 Schema。"""
id: str
type: str
title: str
priority: str
description: dict
status: str
assigned_agent_id: Optional[str] = None
corp_id: str = ""
created_at: str
updated_at: str
class TodoItemListResponse(BaseModel):
"""待办事项列表响应 Schema。"""
items: List[TodoItemResponse]
total: int
# --------------------------------------------------------------------------
# Mock 数据 — 预置示例待办(共 20 条,覆盖全部类型 × 状态)
# --------------------------------------------------------------------------
MOCK_TODO_ITEMS: List[dict] = [
# ========== 工单(ticket==========
# 待处理
{
"id": "todo-001",
"type": "ticket",
"title": "VPN连接失败 — 财务部张伟",
"priority": "urgent",
"description": {
"employee_name": "张伟",
"department": "财务部",
"error": "VPN Error 691",
"steps": ["检查账号状态", "重置密码", "检查VPN配置"],
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T09:15:00Z",
"updated_at": "2026-06-05T09:15:00Z",
},
{
"id": "todo-007",
"type": "ticket",
"title": "OA系统登录异常 — 人事部刘芳",
"priority": "urgent",
"description": {
"employee_name": "刘芳",
"department": "人事部",
"error": "页面白屏,控制台报500错误",
"affected_count": 15,
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T11:30:00Z",
"updated_at": "2026-06-05T11:30:00Z",
},
{
"id": "todo-009",
"type": "ticket",
"title": "WiFi 无法连接 — 研发部开放区",
"priority": "urgent",
"description": {
"employee_name": "陈明",
"department": "研发部",
"error": "获取IP失败,提示无法连接到此网络",
"location": "3楼开放区",
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-06T08:00:00Z",
"updated_at": "2026-06-06T08:00:00Z",
},
{
"id": "todo-017",
"type": "ticket",
"title": "鼠标失灵 — 行政部周婷",
"priority": "normal",
"description": {
"employee_name": "周婷",
"department": "行政部",
"error": "USB鼠标间歇性失灵,更换接口无效",
"os": "Windows 11",
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-06T09:00:00Z",
"updated_at": "2026-06-06T09:00:00Z",
},
# 进行中
{
"id": "todo-004",
"type": "ticket",
"title": "邮箱容量告警 — 市场部王强",
"priority": "high",
"description": {
"employee_name": "王强",
"department": "市场部",
"current_usage": "4.8GB / 5GB",
"action": "协助清理或申请扩容",
},
"status": "processing",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-04T14:30:00Z",
"updated_at": "2026-06-05T08:00:00Z",
},
{
"id": "todo-010",
"type": "ticket",
"title": "ERP系统响应慢 — 全公司反馈",
"priority": "high",
"description": {
"employee_name": "多个员工",
"department": "全公司",
"error": "ERP首页加载超过15秒",
"affected_count": 50,
},
"status": "processing",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T10:00:00Z",
"updated_at": "2026-06-05T15:00:00Z",
},
# 已完成
{
"id": "todo-011",
"type": "ticket",
"title": "打印机驱动安装 — 市场部赵敏",
"priority": "normal",
"description": {
"employee_name": "赵敏",
"department": "市场部",
"device_model": "Canon LBP2900",
"solution": "从官网下载驱动并安装,测试打印正常",
},
"status": "resolved",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-01T09:00:00Z",
"updated_at": "2026-06-02T16:00:00Z",
},
# ========== 审批(approval==========
# 待处理
{
"id": "todo-002",
"type": "approval",
"title": "软件安装审批 — 设计部PS申请",
"priority": "high",
"description": {
"employee_name": "李娜",
"department": "设计部",
"software": "Adobe Photoshop 2026",
"license_type": "企业许可",
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T10:20:00Z",
"updated_at": "2026-06-05T10:20:00Z",
},
{
"id": "todo-005",
"type": "approval",
"title": "权限升级审批 — 研发部数据库访问",
"priority": "high",
"description": {
"employee_name": "陈明",
"department": "研发部",
"target_system": "生产数据库",
"access_level": "只读",
"approver": "研发总监",
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T08:45:00Z",
"updated_at": "2026-06-05T08:45:00Z",
},
{
"id": "todo-008",
"type": "approval",
"title": "新员工设备采购审批 — Q3批次",
"priority": "normal",
"description": {
"batch": "Q3新员工",
"count": 5,
"items": ["笔记本x5", "显示器x5", "键鼠套装x5"],
"budget": "65,000元",
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T07:00:00Z",
"updated_at": "2026-06-05T07:00:00Z",
},
{
"id": "todo-018",
"type": "approval",
"title": "弹性福利审批 — 全体员工Q3",
"priority": "normal",
"description": {
"applicant": "人事部",
"type": "弹性福利",
"budget_per_person": "3000元",
"total_count": 120,
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-06T07:00:00Z",
"updated_at": "2026-06-06T07:00:00Z",
},
# 进行中
{
"id": "todo-012",
"type": "approval",
"title": "预算审批 — IT部Q3采购",
"priority": "high",
"description": {
"department": "IT部",
"amount": "280,000元",
"items": ["服务器x2", "防火墙x2", "交换机x4"],
"approver": "CFO",
},
"status": "processing",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-04T09:00:00Z",
"updated_at": "2026-06-05T14:00:00Z",
},
# 已完成
{
"id": "todo-013",
"type": "approval",
"title": "会议室预订审批 — 销售部Q3客户拜访",
"priority": "normal",
"description": {
"employee_name": "刘军",
"department": "销售部",
"room": "5楼大会议室",
"time": "2026-06-10 14:00-17:00",
"result": "已批准",
},
"status": "resolved",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-05-28T08:00:00Z",
"updated_at": "2026-05-29T10:00:00Z",
},
# ========== 设备(device==========
# 待处理
{
"id": "todo-003",
"type": "device",
"title": "工位打印机故障 — 3楼A区",
"priority": "normal",
"description": {
"location": "3楼A区打印间",
"device_model": "HP LaserJet Pro M404",
"issue": "卡纸,无法打印",
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T11:05:00Z",
"updated_at": "2026-06-05T11:05:00Z",
},
{
"id": "todo-014",
"type": "device",
"title": "核心交换机故障 — 机房",
"priority": "urgent",
"description": {
"location": "机房A区",
"device_model": "Cisco Catalyst 9300",
"issue": "端口3-12全部down,影响2楼所有工位",
"affected_count": 45,
},
"status": "pending",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-06T00:30:00Z",
"updated_at": "2026-06-06T00:30:00Z",
},
# 进行中
{
"id": "todo-006",
"type": "device",
"title": "会议室投影仪维修 — 5楼大会议室",
"priority": "normal",
"description": {
"location": "5楼大会议室",
"device_model": "Epson EB-X51",
"issue": "投影模糊,可能灯泡老化",
},
"status": "processing",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-03T16:00:00Z",
"updated_at": "2026-06-04T10:00:00Z",
},
{
"id": "todo-015",
"type": "device",
"title": "服务器硬盘更换 — 虚拟化集群",
"priority": "high",
"description": {
"location": "机房B区",
"device_model": "Dell R740",
"issue": "硬盘预警,需更换并做好数据迁移",
"affected_vms": 12,
},
"status": "processing",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-06-05T09:00:00Z",
"updated_at": "2026-06-05T16:00:00Z",
},
# 已完成
{
"id": "todo-016",
"type": "device",
"title": "员工笔记本磁盘扩容 — 人事部吴婷",
"priority": "normal",
"description": {
"employee_name": "吴婷",
"department": "人事部",
"device_model": "ThinkPad X1 Carbon",
"solution": "更换1TB SSD,克隆系统,测试正常",
},
"status": "resolved",
"assigned_agent_id": "agent-001",
"corp_id": "ww1234567890",
"created_at": "2026-05-20T13:00:00Z",
"updated_at": "2026-05-22T17:00:00Z",
},
]
# --------------------------------------------------------------------------
# API 接口
# --------------------------------------------------------------------------
@router.get("")
async def list_todo_items(
status: Optional[str] = None,
priority: Optional[str] = None,
):
"""获取当前坐席待办列表。
支持按状态和优先级过滤。
"""
items = MOCK_TODO_ITEMS
# 按状态过滤
if status:
items = [item for item in items if item["status"] == status]
# 按优先级过滤
if priority:
items = [item for item in items if item["priority"] == priority]
# 按优先级排序:urgent → high → normal
priority_order = {"urgent": 0, "high": 1, "normal": 2}
items = sorted(items, key=lambda x: priority_order.get(x["priority"], 3))
return success_response(data={
"items": [TodoItemResponse(**item).model_dump() for item in items],
"total": len(items),
})
@router.get("/{item_id}")
async def get_todo_item(item_id: str):
"""获取待办事项详情。"""
for item in MOCK_TODO_ITEMS:
if item["id"] == item_id:
return success_response(data=TodoItemResponse(**item).model_dump())
raise AppException(code=1003, message=f"待办事项 {item_id} 不存在")
@router.put("/{item_id}/status")
async def update_todo_item_status(item_id: str, request: TodoStatusUpdateRequest):
"""更新待办事项状态。"""
# 校验状态值
valid_statuses = {"pending", "processing", "resolved"}
if request.status not in valid_statuses:
raise HTTPException(
status_code=400,
detail=f"无效的状态值: {request.status},合法值为: {valid_statuses}",
)
for item in MOCK_TODO_ITEMS:
if item["id"] == item_id:
item["status"] = request.status
item["updated_at"] = datetime.now().isoformat()
return success_response(data=TodoItemResponse(**item).model_dump())
raise AppException(code=1003, message=f"待办事项 {item_id} 不存在")