Files
tw/services/service_tuhui_dispatch.py
ZuoWei a6c42d505a feat: 完整功能部署 v1.0
新增功能:
- 天网协作系统 (HTTP API 端口 6060)
- 三种工作流 (查找图片/处理图片/转人工派单)
- 图片任务数据库 (支持客户后续增加需求)
- 图绘派单系统集成 (API: 8005)
- 文字检测与加价 (60-80 元高价值订单)
- 风险评估与接单判断
- 作图失败自动转人工

新增文档:
- 项目功能汇总.md
- 三种工作流功能说明.md
- 文字加价功能说明.md
- 风险评估功能说明.md
- 图片任务数据库功能说明.md
- 图绘派单系统集成说明.md
- 作图失败转接人工说明.md
- DEPLOYMENT.md
- TIANWANG_INTEGRATION.md

核心修改:
- core/pydantic_ai_agent.py
- core/workflow.py
- core/websocket_client.py
- image/image_analyzer.py
- services/service_tuhui_dispatch.py
- db/image_tasks_db.py

版本:v1.0
日期:2026-02-28
2026-02-28 11:20:40 +08:00

230 lines
7.7 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.
# -*- coding: utf-8 -*-
"""
图绘派单系统 API 客户端
"""
import httpx
import logging
from typing import List, Dict, Optional
logger = logging.getLogger(__name__)
class TuhuiDispatchClient:
"""图绘派单系统客户端"""
def __init__(self):
self.base_url = "http://1.12.50.92:8005"
self.api_key = "tuhui_dispatch_key_2026"
self.headers = {"X-API-Key": self.api_key}
self.timeout = 10.0
async def get_dispatch_queue(self) -> Optional[Dict]:
"""
获取派单队列
Returns:
dict: {
"pending_tasks": {"count": 3, "tasks": [...]},
"online_designers": {"count": 2, "designers": [...]},
"suggestion": "橘子"
}
"""
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.get(
f"{self.base_url}/dispatch/queue",
headers=self.headers
)
if response.status_code == 200:
return response.json()
else:
logger.error(f"获取派单队列失败HTTP {response.status_code}")
return None
except Exception as e:
logger.error(f"获取派单队列异常:{e}")
return None
async def get_online_designers(self) -> List[str]:
"""
获取在线设计师
Returns:
list: ["橘子", "婷婷", ...]
"""
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.get(
f"{self.base_url}/online/designers",
headers=self.headers
)
if response.status_code == 200:
data = response.json()
return data.get("online_users", [])
else:
logger.error(f"获取在线设计师失败HTTP {response.status_code}")
return []
except Exception as e:
logger.error(f"获取在线设计师异常:{e}")
return []
async def create_task(self, task_name: str, description: str = "",
task_type: str = "design", priority: int = 1,
deadline: str = None) -> Optional[str]:
"""
创建任务
Args:
task_name: 任务名称
description: 任务描述
task_type: 任务类型
priority: 优先级1-5
deadline: 截止时间
Returns:
task_id: 任务 ID失败返回 None
"""
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.post(
f"{self.base_url}/tasks",
headers={**self.headers, "Content-Type": "application/json"},
json={
"task_name": task_name,
"description": description,
"task_type": task_type,
"priority": priority,
"deadline": deadline
}
)
if response.status_code == 200:
data = response.json()
task_id = data.get("task_id")
logger.info(f"创建任务成功:{task_id}")
return task_id
else:
logger.error(f"创建任务失败HTTP {response.status_code}")
return None
except Exception as e:
logger.error(f"创建任务异常:{e}")
return None
async def assign_task(self, task_id: str, designer_name: str,
notes: str = "") -> bool:
"""
分配任务给设计师
Args:
task_id: 任务 ID
designer_name: 设计师姓名
notes: 备注信息
Returns:
bool: 是否成功
"""
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.post(
f"{self.base_url}/tasks/{task_id}/assign",
headers={**self.headers, "Content-Type": "application/json"},
json={
"designer_name": designer_name,
"notes": notes or "AI 客服自动派单"
}
)
if response.status_code == 200:
data = response.json()
logger.info(f"任务分配成功:{task_id}{designer_name}")
return True
else:
logger.error(f"分配任务失败HTTP {response.status_code}")
return False
except Exception as e:
logger.error(f"分配任务异常:{e}")
return False
async def get_task_status(self, task_id: str) -> Optional[Dict]:
"""
查询任务状态
Args:
task_id: 任务 ID
Returns:
dict: 任务状态信息
"""
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.get(
f"{self.base_url}/tasks/{task_id}",
headers=self.headers
)
if response.status_code == 200:
return response.json()
else:
logger.error(f"查询任务状态失败HTTP {response.status_code}")
return None
except Exception as e:
logger.error(f"查询任务状态异常:{e}")
return None
async def complete_task(self, task_id: str, notes: str = "") -> bool:
"""
完成任务
Args:
task_id: 任务 ID
notes: 备注信息
Returns:
bool: 是否成功
"""
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.post(
f"{self.base_url}/tasks/{task_id}/complete",
headers={**self.headers, "Content-Type": "application/json"},
json={
"notes": notes or "客户已确认,效果满意"
}
)
if response.status_code == 200:
logger.info(f"任务完成:{task_id}")
return True
else:
logger.error(f"完成任务失败HTTP {response.status_code}")
return False
except Exception as e:
logger.error(f"完成任务异常:{e}")
return False
async def health_check(self) -> bool:
"""健康检查"""
try:
async with httpx.AsyncClient(timeout=5.0) as client:
response = await client.get(f"{self.base_url}/health")
return response.status_code == 200
except:
return False
# 单例
_client: Optional[TuhuiDispatchClient] = None
def get_tuhui_dispatch_client() -> TuhuiDispatchClient:
"""获取派单客户端单例"""
global _client
if _client is None:
_client = TuhuiDispatchClient()
return _client