chore: initialize tuhui repository
This commit is contained in:
346
backend/dispatch_api_backup2.py
Normal file
346
backend/dispatch_api_backup2.py
Normal file
@@ -0,0 +1,346 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user