# ============================================================================= # 企微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} 不存在")