todo_list
This commit is contained in:
286
admin_routes.py
286
admin_routes.py
@@ -6,10 +6,11 @@ from typing import Optional, List
|
||||
import json
|
||||
import os
|
||||
import secrets
|
||||
from datetime import datetime
|
||||
|
||||
from database import get_db
|
||||
from models import Device as DeviceModel, Content as ContentModel
|
||||
from schemas import DeviceCreate, ContentCreate
|
||||
from models import Device as DeviceModel, Content as ContentModel, Todo as TodoModel
|
||||
from schemas import DeviceCreate, ContentCreate, TodoCreate, TodoUpdate
|
||||
from image_processor import image_processor
|
||||
from mqtt_manager import mqtt_manager
|
||||
|
||||
@@ -31,22 +32,33 @@ async def admin_dashboard(request: Request, db: Session = Depends(get_db)):
|
||||
|
||||
# 获取内容数量
|
||||
content_count = db.query(ContentModel).count()
|
||||
active_content_count = db.query(ContentModel).filter(ContentModel.is_active == True).count()
|
||||
|
||||
# 获取待办事项数量
|
||||
todo_count = db.query(TodoModel).count()
|
||||
completed_todo_count = db.query(TodoModel).filter(TodoModel.is_completed == True).count()
|
||||
pending_todo_count = todo_count - completed_todo_count
|
||||
|
||||
# 获取最近上线的设备
|
||||
recent_devices = db.query(DeviceModel).order_by(DeviceModel.last_online.desc()).limit(5).all()
|
||||
|
||||
# 获取最近创建的内容
|
||||
recent_contents = db.query(ContentModel).order_by(ContentModel.created_at.desc()).limit(5).all()
|
||||
# 获取最近创建的待办事项
|
||||
recent_todos_query = db.query(TodoModel, DeviceModel).join(
|
||||
DeviceModel, TodoModel.device_id == DeviceModel.device_id
|
||||
).order_by(TodoModel.created_at.desc()).limit(5).all()
|
||||
|
||||
# 转换为包含todo和device的对象列表
|
||||
recent_todos = [{"todo": todo, "device": device} for todo, device in recent_todos_query]
|
||||
|
||||
return templates.TemplateResponse("admin/dashboard.html", {
|
||||
"request": request,
|
||||
"device_count": device_count,
|
||||
"active_device_count": active_device_count,
|
||||
"content_count": content_count,
|
||||
"active_content_count": active_content_count,
|
||||
"todo_count": todo_count,
|
||||
"completed_todo_count": completed_todo_count,
|
||||
"pending_todo_count": pending_todo_count,
|
||||
"recent_devices": recent_devices,
|
||||
"recent_contents": recent_contents
|
||||
"recent_todos": recent_todos
|
||||
})
|
||||
|
||||
@admin_router.get("/devices", response_class=HTMLResponse)
|
||||
@@ -341,4 +353,262 @@ async def upload_image(request: Request, db: Session = Depends(get_db)):
|
||||
"request": request,
|
||||
"devices": devices,
|
||||
"error": f"图片处理失败: {str(e)}"
|
||||
})
|
||||
})
|
||||
|
||||
# 待办事项管理路由
|
||||
@admin_router.get("/todos", response_class=HTMLResponse)
|
||||
async def todos_list(request: Request, device_id: Optional[str] = None, db: Session = Depends(get_db)):
|
||||
"""
|
||||
待办事项列表页面
|
||||
"""
|
||||
if device_id:
|
||||
# 获取特定设备的待办事项
|
||||
device = db.query(DeviceModel).filter(DeviceModel.device_id == device_id).first()
|
||||
if not device:
|
||||
raise HTTPException(status_code=404, detail="设备不存在")
|
||||
|
||||
todos = db.query(TodoModel).filter(TodoModel.device_id == device_id).order_by(TodoModel.created_at.desc()).all()
|
||||
return templates.TemplateResponse("admin/todos.html", {
|
||||
"request": request,
|
||||
"todos": todos,
|
||||
"device": device,
|
||||
"filtered": True
|
||||
})
|
||||
else:
|
||||
# 获取所有待办事项
|
||||
todos = db.query(TodoModel).order_by(TodoModel.created_at.desc()).all()
|
||||
devices = db.query(DeviceModel).all()
|
||||
|
||||
# 为每个待办事项添加设备信息
|
||||
todo_list = []
|
||||
for todo in todos:
|
||||
device = db.query(DeviceModel).filter(DeviceModel.device_id == todo.device_id).first()
|
||||
todo_list.append({
|
||||
"todo": todo,
|
||||
"device": device
|
||||
})
|
||||
|
||||
return templates.TemplateResponse("admin/todos.html", {
|
||||
"request": request,
|
||||
"todo_list": todo_list,
|
||||
"devices": devices,
|
||||
"filtered": False
|
||||
})
|
||||
|
||||
@admin_router.get("/todos/add", response_class=HTMLResponse)
|
||||
@admin_router.post("/todos/add", response_class=HTMLResponse)
|
||||
async def add_todo(request: Request, device_id: Optional[str] = None, db: Session = Depends(get_db)):
|
||||
"""
|
||||
添加待办事项页面和处理
|
||||
"""
|
||||
if request.method == "GET":
|
||||
devices = db.query(DeviceModel).filter(DeviceModel.is_active == True).all()
|
||||
return templates.TemplateResponse("admin/todo_add.html", {
|
||||
"request": request,
|
||||
"devices": devices,
|
||||
"selected_device": device_id
|
||||
})
|
||||
|
||||
# 处理POST请求
|
||||
form = await request.form()
|
||||
device_id = form.get("device_id")
|
||||
title = form.get("title")
|
||||
description = form.get("description")
|
||||
due_date_str = form.get("due_date")
|
||||
|
||||
# 检查设备是否存在
|
||||
device = db.query(DeviceModel).filter(DeviceModel.device_id == device_id).first()
|
||||
if not device:
|
||||
devices = db.query(DeviceModel).filter(DeviceModel.is_active == True).all()
|
||||
return templates.TemplateResponse("admin/todo_add.html", {
|
||||
"request": request,
|
||||
"devices": devices,
|
||||
"error": "设备不存在"
|
||||
})
|
||||
|
||||
# 处理截止日期
|
||||
due_date = None
|
||||
if due_date_str:
|
||||
try:
|
||||
from datetime import datetime
|
||||
due_date = datetime.strptime(due_date_str, "%Y-%m-%dT%H:%M")
|
||||
except ValueError:
|
||||
devices = db.query(DeviceModel).filter(DeviceModel.is_active == True).all()
|
||||
return templates.TemplateResponse("admin/todo_add.html", {
|
||||
"request": request,
|
||||
"devices": devices,
|
||||
"error": "截止日期格式不正确"
|
||||
})
|
||||
|
||||
# 创建新的待办事项
|
||||
new_todo = TodoModel(
|
||||
title=title,
|
||||
description=description,
|
||||
device_id=device_id,
|
||||
due_date=due_date
|
||||
)
|
||||
|
||||
db.add(new_todo)
|
||||
db.commit()
|
||||
|
||||
# 发送MQTT通知给设备
|
||||
mqtt_manager.send_todo_command(device_id, "create", {
|
||||
"id": new_todo.id,
|
||||
"title": title,
|
||||
"description": description,
|
||||
"due_date": due_date.isoformat() if due_date else None
|
||||
})
|
||||
|
||||
return RedirectResponse(url="/admin/todos", status_code=303)
|
||||
|
||||
@admin_router.get("/todos/{todo_id}", response_class=HTMLResponse)
|
||||
async def todo_detail(request: Request, todo_id: int, db: Session = Depends(get_db)):
|
||||
"""
|
||||
待办事项详情页面
|
||||
"""
|
||||
todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first()
|
||||
if not todo:
|
||||
raise HTTPException(status_code=404, detail="待办事项不存在")
|
||||
|
||||
# 获取设备信息
|
||||
device = db.query(DeviceModel).filter(DeviceModel.device_id == todo.device_id).first()
|
||||
|
||||
return templates.TemplateResponse("admin/todo_detail.html", {
|
||||
"request": request,
|
||||
"todo": todo,
|
||||
"device": device
|
||||
})
|
||||
|
||||
@admin_router.post("/todos/{todo_id}/toggle", response_class=HTMLResponse)
|
||||
async def toggle_todo_status(todo_id: int, db: Session = Depends(get_db)):
|
||||
"""
|
||||
切换待办事项完成状态
|
||||
"""
|
||||
todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first()
|
||||
if not todo:
|
||||
raise HTTPException(status_code=404, detail="待办事项不存在")
|
||||
|
||||
# 切换状态
|
||||
todo.is_completed = not todo.is_completed
|
||||
if todo.is_completed:
|
||||
todo.completed_at = datetime.utcnow()
|
||||
else:
|
||||
todo.completed_at = None
|
||||
|
||||
todo.updated_at = datetime.utcnow()
|
||||
db.commit()
|
||||
|
||||
# 发送MQTT通知给设备
|
||||
mqtt_manager.send_todo_command(todo.device_id, "update", {
|
||||
"id": todo.id,
|
||||
"is_completed": todo.is_completed,
|
||||
"completed_at": todo.completed_at.isoformat() if todo.completed_at else None
|
||||
})
|
||||
|
||||
return RedirectResponse(url=f"/admin/todos/{todo_id}", status_code=303)
|
||||
|
||||
@admin_router.get("/todos/{todo_id}/edit", response_class=HTMLResponse)
|
||||
async def edit_todo_page(request: Request, todo_id: int, db: Session = Depends(get_db)):
|
||||
todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first()
|
||||
if not todo:
|
||||
raise HTTPException(status_code=404, detail="待办事项不存在")
|
||||
|
||||
devices = db.query(DeviceModel).all()
|
||||
|
||||
return templates.TemplateResponse("admin/todo_edit.html", {
|
||||
"request": request,
|
||||
"todo": todo,
|
||||
"devices": devices
|
||||
})
|
||||
|
||||
@admin_router.post("/todos/{todo_id}/edit")
|
||||
async def edit_todo(
|
||||
request: Request,
|
||||
todo_id: int,
|
||||
title: str = Form(...),
|
||||
description: str = Form(""),
|
||||
device_id: str = Form(...),
|
||||
due_date: Optional[str] = Form(None),
|
||||
is_completed: bool = Form(False),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first()
|
||||
if not todo:
|
||||
raise HTTPException(status_code=404, detail="待办事项不存在")
|
||||
|
||||
device = db.query(DeviceModel).filter(DeviceModel.device_id == device_id).first()
|
||||
if not device:
|
||||
raise HTTPException(status_code=404, detail="设备不存在")
|
||||
|
||||
# 更新待办事项
|
||||
todo.title = title
|
||||
todo.description = description if description else None
|
||||
todo.device_id = device_id
|
||||
todo.due_date = datetime.fromisoformat(due_date) if due_date else None
|
||||
|
||||
# 检查完成状态变化
|
||||
was_completed = todo.is_completed
|
||||
todo.is_completed = is_completed
|
||||
|
||||
# 如果从未完成变为已完成,设置完成时间
|
||||
if not was_completed and is_completed:
|
||||
todo.completed_at = datetime.utcnow()
|
||||
# 如果从已完成变为未完成,清除完成时间
|
||||
elif was_completed and not is_completed:
|
||||
todo.completed_at = None
|
||||
|
||||
todo.updated_at = datetime.utcnow()
|
||||
|
||||
db.commit()
|
||||
|
||||
# 发送MQTT通知到设备
|
||||
if hasattr(request.app.state, 'mqtt_manager') and request.app.state.mqtt_manager:
|
||||
try:
|
||||
await request.app.state.mqtt_manager.send_todo_command(
|
||||
device_id=device_id,
|
||||
action="update",
|
||||
todo_data={
|
||||
"id": todo.id,
|
||||
"title": todo.title,
|
||||
"description": todo.description,
|
||||
"due_date": todo.due_date.isoformat() if todo.due_date else None,
|
||||
"is_completed": todo.is_completed
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"发送待办事项更新MQTT消息失败: {e}")
|
||||
|
||||
return RedirectResponse(url=f"/admin/todos/{todo_id}", status_code=303)
|
||||
|
||||
@admin_router.post("/todos/{todo_id}/delete")
|
||||
async def delete_todo(
|
||||
request: Request,
|
||||
todo_id: int,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
删除待办事项
|
||||
"""
|
||||
todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first()
|
||||
if not todo:
|
||||
raise HTTPException(status_code=404, detail="待办事项不存在")
|
||||
|
||||
device_id = todo.device_id
|
||||
|
||||
# 发送MQTT通知到设备
|
||||
if hasattr(request.app.state, 'mqtt_manager') and request.app.state.mqtt_manager:
|
||||
try:
|
||||
await request.app.state.mqtt_manager.send_todo_command(
|
||||
device_id=device_id,
|
||||
action="delete",
|
||||
todo_data={
|
||||
"id": todo.id
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"发送待办事项删除MQTT消息失败: {e}")
|
||||
|
||||
db.delete(todo)
|
||||
db.commit()
|
||||
|
||||
return RedirectResponse(url=f"/admin/todos?device_id={device_id}", status_code=303)
|
||||
Reference in New Issue
Block a user