feat: 设备日志增加时间范围查询 + CSV 导出

- 查询 API 增加 date_from/date_to 参数(前端日期+时间选择器)
- 新增 /api/device-logs/export CSV 导出端点
- 新增 export_device_logs() 模型函数(全量不分页)
- 删除校验放宽:允许纯时间范围作为删除条件
- 前端增加导出 CSV 按钮,遵循 test_data 页面模式
This commit is contained in:
wangfq
2026-06-10 10:44:19 +08:00
parent 6b35d07025
commit d3b6d79a03
3 changed files with 125 additions and 7 deletions

View File

@@ -1,8 +1,11 @@
"""设备事件日志 API"""
from flask import Blueprint, jsonify, render_template, request
import csv
import io
from flask import Blueprint, jsonify, render_template, request, Response
from flask_login import login_required, current_user
from app.models import get_device_logs, delete_device_logs, insert_log
from app.models import get_device_logs, export_device_logs, delete_device_logs, insert_log
bp = Blueprint("device_logs", __name__)
@@ -22,15 +25,49 @@ def api_device_logs():
per_page = request.args.get("per_page", 30, type=int)
serial = request.args.get("serial", "", type=str)
event_type = request.args.get("event_type", "", type=str)
date_from = request.args.get("date_from", "", type=str)
date_to = request.args.get("date_to", "", type=str)
records, total = get_device_logs(
page=page, per_page=per_page,
serial=serial, event_type=event_type,
date_from=date_from, date_to=date_to,
)
pages = max(1, (total + per_page - 1) // per_page)
return jsonify({"records": records, "total": total, "pages": pages})
@bp.route("/api/device-logs/export")
@login_required
def api_export():
"""导出设备事件日志为 CSV"""
serial = request.args.get("serial", "", type=str)
event_type = request.args.get("event_type", "", type=str)
date_from = request.args.get("date_from", "", type=str)
date_to = request.args.get("date_to", "", type=str)
records = export_device_logs(
serial=serial, event_type=event_type,
date_from=date_from, date_to=date_to,
)
output = io.StringIO()
writer = csv.writer(output)
if records:
headers = list(records[0].keys())
writer.writerow(headers)
for r in records:
writer.writerow(r.values())
output.seek(0)
return Response(
output.getvalue(),
mimetype="text/csv",
headers={"Content-Disposition": "attachment; filename=device_logs.csv"},
)
@bp.route("/api/device-logs/delete", methods=["POST"])
@login_required
def api_device_logs_delete():