todo_list

This commit is contained in:
jeremygan2021
2025-11-16 17:36:42 +08:00
parent a2682dc040
commit bb04bd8fa5
25 changed files with 1198 additions and 34 deletions

View File

@@ -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)