Files
tuhui/backend/dispatch_api_backup2.py
2026-03-08 19:28:32 +08:00

347 lines
11 KiB
Python

from fastapi import FastAPI, HTTPException, Header, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Optional, List
from datetime import datetime
import sqlite3
from pathlib import Path
import requests
# 数据库路径
DB_PATH = Path("/root/tuhui/backend/dispatch.db")
DESIGNER_DB_PATH = Path("/root/tuhui/backend/designer_status.db")
# API 密钥
API_KEY = "tuhui_dispatch_key_2026"
# 企业微信 Webhook
WECHAT_WEBHOOK = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=cc88bdef-a13f-4d7e-bdb6-ee51b68b8205"
app = FastAPI(
title="图汇派单系统 API",
description="专业的设计师派单管理系统",
version="1.0.0"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class TaskCreate(BaseModel):
task_name: str
description: str = ""
task_type: str = "design"
priority: int = 1
deadline: Optional[str] = None
class TaskAssign(BaseModel):
designer_name: str
notes: Optional[str] = ""
class TaskComplete(BaseModel):
notes: Optional[str] = ""
def verify_api_key(x_api_key: str = Header(..., alias="X-API-Key")):
if x_api_key != API_KEY:
raise HTTPException(status_code=401, detail="Invalid API Key")
return x_api_key
def get_db_connection(db_path: Path):
conn = sqlite3.connect(str(db_path))
conn.row_factory = sqlite3.Row
return conn
def get_online_designers() -> List[str]:
conn = get_db_connection(DESIGNER_DB_PATH)
cursor = conn.cursor()
cursor.execute("SELECT real_name FROM designer_status WHERE status = 'online'")
designers = [row["real_name"] for row in cursor.fetchall()]
conn.close()
return designers
def send_wechat_notification(message: str):
"""发送企业微信通知"""
try:
requests.post(WECHAT_WEBHOOK, json={
"msgtype": "text",
"text": {"content": message}
}, timeout=5)
print(f"✅ 通知已发送")
except Exception as e:
print(f"❌ 发送通知失败:{e}")
@app.get("/health")
def health_check():
return {"status": "ok", "timestamp": datetime.now().isoformat()}
@app.get("/online/designers")
def get_online_designers_api():
designers = get_online_designers()
return {
"online_count": len(designers),
"online_users": designers,
"update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
@app.post("/tasks", tags=["任务管理"])
def create_task(task: TaskCreate, api_key: str = Depends(verify_api_key)):
import uuid
task_id = str(uuid.uuid4())[:8]
conn = get_db_connection(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
INSERT INTO dispatch_tasks (id, task_name, task_description, task_type, priority, status, deadline)
VALUES (?, ?, ?, ?, ?, 'pending', ?)
''', (task_id, task.task_name, task.description, task.task_type, task.priority, task.deadline))
conn.commit()
conn.close()
return {
"task_id": task_id,
"task_name": task.task_name,
"status": "pending",
"created_at": datetime.now().isoformat()
}
@app.get("/tasks/pending", tags=["任务管理"])
def get_pending_tasks(limit: int = 10, api_key: str = Depends(verify_api_key)):
conn = get_db_connection(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
SELECT id, task_name, task_description, task_type, priority, created_at, deadline
FROM dispatch_tasks
WHERE status = 'pending'
ORDER BY priority DESC, created_at ASC
LIMIT ?
''', (limit,))
tasks = []
for row in cursor.fetchall():
tasks.append({
"task_id": row["id"],
"task_name": row["task_name"],
"description": row["task_description"],
"type": row["task_type"],
"priority": row["priority"],
"created_at": row["created_at"],
"deadline": row["deadline"]
})
conn.close()
return {"total": len(tasks), "tasks": tasks}
@app.post("/tasks/{task_id}/assign", tags=["任务管理"])
def assign_task(task_id: str, assign_data: TaskAssign, api_key: str = Depends(verify_api_key)):
conn = get_db_connection(DB_PATH)
cursor = conn.cursor()
cursor.execute('SELECT id, task_name, status FROM dispatch_tasks WHERE id = ?', (task_id,))
task = cursor.fetchone()
if not task:
conn.close()
raise HTTPException(status_code=404, detail="Task not found")
if task["status"] != "pending":
conn.close()
raise HTTPException(status_code=400, detail=f"Task status is {task['status']}, cannot assign")
cursor.execute('''
UPDATE dispatch_tasks
SET status = 'assigned', assigned_to = ?, assigned_at = ?
WHERE id = ?
''', (assign_data.designer_name, datetime.now(), task_id))
cursor.execute('''
INSERT INTO dispatch_history (task_id, designer_name, action, notes)
VALUES (?, ?, 'assigned', ?)
''', (task_id, assign_data.designer_name, assign_data.notes))
cursor.execute('''
INSERT OR REPLACE INTO designer_workload (designer_name, pending_tasks, total_tasks, last_updated)
VALUES (
?,
COALESCE((SELECT pending_tasks FROM designer_workload WHERE designer_name = ?), 0) + 1,
COALESCE((SELECT total_tasks FROM designer_workload WHERE designer_name = ?), 0) + 1,
?
)
''', (assign_data.designer_name, assign_data.designer_name, assign_data.designer_name, datetime.now()))
conn.commit()
conn.close()
# 发送群通知
notification = f"""📢【新任务派发】
🎯 任务:{task['task_name']}
👤 派给:{assign_data.designer_name}
📝 备注:{assign_data.notes or ''}
💪 加油,看好你哦!"""
send_wechat_notification(notification)
return {
"task_id": task_id,
"assigned_to": assign_data.designer_name,
"status": "assigned",
"assigned_at": datetime.now().isoformat()
}
@app.get("/tasks/{task_id}", tags=["任务管理"])
def get_task_status(task_id: str, api_key: str = Depends(verify_api_key)):
conn = get_db_connection(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
SELECT id, task_name, status, assigned_to, created_at, assigned_at, completed_at, deadline
FROM dispatch_tasks
WHERE id = ?
''', (task_id,))
row = cursor.fetchone()
conn.close()
if not row:
raise HTTPException(status_code=404, detail="Task not found")
return {
"task_id": row["id"],
"task_name": row["task_name"],
"status": row["status"],
"assigned_to": row["assigned_to"],
"created_at": row["created_at"],
"assigned_at": row["assigned_at"],
"completed_at": row["completed_at"],
"deadline": row["deadline"]
}
@app.post("/tasks/{task_id}/complete", tags=["任务管理"])
def complete_task(task_id: str, complete_data: TaskComplete, api_key: str = Depends(verify_api_key)):
conn = get_db_connection(DB_PATH)
cursor = conn.cursor()
cursor.execute('SELECT assigned_to, status FROM dispatch_tasks WHERE id = ?', (task_id,))
row = cursor.fetchone()
if not row:
conn.close()
raise HTTPException(status_code=404, detail="Task not found")
if row["status"] != "assigned" and row["status"] != "in_progress":
conn.close()
raise HTTPException(status_code=400, detail=f"Task status is {row['status']}, cannot complete")
designer_name = row["assigned_to"]
cursor.execute('''
UPDATE dispatch_tasks
SET status = 'completed', completed_at = ?
WHERE id = ?
''', (datetime.now(), task_id))
cursor.execute('''
INSERT INTO dispatch_history (task_id, designer_name, action, notes)
VALUES (?, ?, 'completed', ?)
''', (task_id, designer_name, complete_data.notes))
cursor.execute('''
UPDATE designer_workload
SET pending_tasks = pending_tasks - 1,
completed_tasks = completed_tasks + 1,
last_updated = ?
WHERE designer_name = ?
''', (datetime.now(), designer_name))
conn.commit()
conn.close()
# 发送完成通知
notification = f"""✅【任务完成】
🎯 任务:{row['task_name']}
👤 设计师:{designer_name}
📝 备注:{complete_data.notes or ''}
🎉 辛苦啦,棒棒哒!"""
send_wechat_notification(notification)
return {
"task_id": task_id,
"status": "completed",
"completed_at": datetime.now().isoformat()
}
@app.get("/designers/workload", tags=["设计师管理"])
def get_designer_workload(api_key: str = Depends(verify_api_key)):
conn = get_db_connection(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
SELECT designer_name, total_tasks, completed_tasks, pending_tasks, last_updated
FROM designer_workload
ORDER BY total_tasks DESC
''')
workload = []
for row in cursor.fetchall():
workload.append({
"designer": row["designer_name"],
"total_tasks": row["total_tasks"],
"completed_tasks": row["completed_tasks"],
"pending_tasks": row["pending_tasks"],
"last_updated": row["last_updated"]
})
conn.close()
return {"total_designers": len(workload), "designers": workload}
@app.get("/dispatch/queue", tags=["派单队列"])
def get_dispatch_queue(api_key: str = Depends(verify_api_key)):
conn = get_db_connection(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
SELECT id, task_name, task_description, task_type, priority, created_at, deadline
FROM dispatch_tasks
WHERE status = 'pending'
ORDER BY priority DESC, created_at ASC
LIMIT 20
''')
pending_tasks = []
for row in cursor.fetchall():
pending_tasks.append({
"task_id": row["id"],
"task_name": row["task_name"],
"description": row["task_description"],
"type": row["task_type"],
"priority": row["priority"],
"created_at": row["created_at"],
"deadline": row["deadline"]
})
conn.close()
online_designers = get_online_designers()
return {
"timestamp": datetime.now().isoformat(),
"pending_tasks": {"count": len(pending_tasks), "tasks": pending_tasks},
"online_designers": {"count": len(online_designers), "designers": online_designers},
"suggestion": online_designers[0] if online_designers and pending_tasks else None
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8005)