[0.2.7.7][ci]
All checks were successful
CI / docker-ci (push) Successful in 35s

This commit is contained in:
DSQ
2026-03-23 10:37:46 +08:00
parent fe7f08ed1c
commit c9611fa622
2 changed files with 95 additions and 86 deletions

View File

@@ -445,6 +445,11 @@ async function generateReport() {
try { try {
const params = buildReportParams(); const params = buildReportParams();
const resp = await fetch(`/elastic/report/?${params.toString()}`, { credentials: 'same-origin' }); const resp = await fetch(`/elastic/report/?${params.toString()}`, { credentials: 'same-origin' });
const ct = (resp.headers.get('content-type') || '').toLowerCase();
if (!ct.includes('application/json')) {
const text = await resp.text();
throw new Error(text ? String(text).slice(0, 200) : `HTTP ${resp.status}`);
}
const data = await resp.json(); const data = await resp.json();
if (data.status !== 'success') { if (data.status !== 'success') {
reportBox.className = 'search-result error'; reportBox.className = 'search-result error';

View File

@@ -8,6 +8,7 @@ import base64
import json import json
import csv import csv
import io import io
from datetime import datetime, timezone, timedelta
import tempfile import tempfile
import concurrent.futures import concurrent.futures
from django.conf import settings from django.conf import settings
@@ -1580,104 +1581,107 @@ def _dt_label(dt, interval: str):
@require_http_methods(["GET"]) @require_http_methods(["GET"])
def report_view(request): def report_view(request):
session_user_id = request.session.get("user_id") try:
if session_user_id is None: session_user_id = request.session.get("user_id")
return JsonResponse({"status": "error", "message": "未登录"}, status=401) if session_user_id is None:
is_admin = int(request.session.get("permission", 1)) == 0 return JsonResponse({"status": "error", "message": "未登录"}, status=401)
me = get_user_by_id(session_user_id) or {} is_admin = int(request.session.get("permission", 1)) == 0
has_manage_key = bool(me.get("manage_key") or []) me = get_user_by_id(session_user_id) or {}
if (not is_admin) and (not has_manage_key): has_manage_key = bool(me.get("manage_key") or [])
return JsonResponse({"status": "error", "message": "无权限"}, status=403) if (not is_admin) and (not has_manage_key):
return JsonResponse({"status": "error", "message": "无权限"}, status=403)
gte = (request.GET.get("from") or "").strip() gte = (request.GET.get("from") or "").strip()
lte = (request.GET.get("to") or "").strip() lte = (request.GET.get("to") or "").strip()
interval = (request.GET.get("interval") or "day").strip() interval = (request.GET.get("interval") or "day").strip()
key = (request.GET.get("key") or "").strip() key = (request.GET.get("key") or "").strip()
typ = (request.GET.get("type") or "").strip() typ = (request.GET.get("type") or "").strip()
gte_dt = _parse_dt(gte) if gte else None gte_dt = _parse_dt(gte) if gte else None
lte_dt = _parse_dt(lte) if lte else None lte_dt = _parse_dt(lte) if lte else None
results = search_all() results = search_all()
results = _filter_results_for_user(request, results) results = _filter_results_for_user(request, results)
filtered = list(results or []) filtered = list(results or [])
if key: if key:
selected = str(key).strip() selected = str(key).strip()
try:
users = get_all_users() or []
except Exception:
users = []
writer_keys_by_id = {}
for u in users:
try: try:
u_id = str(u.get("user_id", "")).strip() users = get_all_users() or []
except Exception: except Exception:
u_id = "" users = []
if not u_id: writer_keys_by_id = {}
continue for u in users:
try: try:
u_keys = {str(k).strip() for k in (u.get("key") or []) if str(k).strip()} u_id = str(u.get("user_id", "")).strip()
except Exception: except Exception:
u_keys = set() u_id = ""
writer_keys_by_id[u_id] = u_keys if not u_id:
continue
try:
u_keys = {str(k).strip() for k in (u.get("key") or []) if str(k).strip()}
except Exception:
u_keys = set()
writer_keys_by_id[u_id] = u_keys
tmp = [] tmp = []
for r in filtered:
writer_id = str(r.get("writer_id", "")).strip()
writer_keys = writer_keys_by_id.get(writer_id)
if writer_keys and selected in writer_keys:
tmp.append(r)
continue
if selected and selected in str(r.get("data", "")):
tmp.append(r)
filtered = tmp
if typ:
tsel = str(typ).strip()
filtered = [r for r in filtered if _extract_type_from_data(r.get("data")) == tsel]
ranged = []
for r in filtered: for r in filtered:
writer_id = str(r.get("writer_id", "")).strip() t = _parse_dt(r.get("time"))
writer_keys = writer_keys_by_id.get(writer_id) if (gte_dt or lte_dt) and (t is None):
if writer_keys and selected in writer_keys:
tmp.append(r)
continue continue
if selected and selected in str(r.get("data", "")): if gte_dt and t and t < gte_dt:
tmp.append(r) continue
filtered = tmp if lte_dt and t and t > lte_dt:
continue
rr = dict(r)
rr["_time_dt"] = t
ranged.append(rr)
if typ: by_type = {}
tsel = str(typ).strip() by_bucket = {}
filtered = [r for r in filtered if _extract_type_from_data(r.get("data")) == tsel] for r in ranged:
tval = _extract_type_from_data(r.get("data"))
if tval:
by_type[tval] = by_type.get(tval, 0) + 1
bucket_dt = _floor_dt(r.get("_time_dt"), interval)
if bucket_dt:
label = _dt_label(bucket_dt, interval)
if label:
by_bucket[label] = by_bucket.get(label, 0) + 1
ranged = [] by_type_arr = [{"type": k, "count": int(v)} for k, v in sorted(by_type.items(), key=lambda x: (-x[1], x[0]))]
for r in filtered: by_time_arr = [{"bucket": k, "count": int(v)} for k, v in sorted(by_bucket.items(), key=lambda x: x[0])]
t = _parse_dt(r.get("time"))
if (gte_dt or lte_dt) and (t is None):
continue
if gte_dt and t and t < gte_dt:
continue
if lte_dt and t and t > lte_dt:
continue
rr = dict(r)
rr["_time_dt"] = t
ranged.append(rr)
by_type = {} return JsonResponse(
by_bucket = {} {
for r in ranged: "status": "success",
tval = _extract_type_from_data(r.get("data")) "data": {
if tval: "generated_at": datetime.now(timezone.utc).isoformat(),
by_type[tval] = by_type.get(tval, 0) + 1 "range": {"from": gte or "", "to": lte or ""},
bucket_dt = _floor_dt(r.get("_time_dt"), interval) "filters": {"key": key or "", "type": typ or "", "interval": interval or "day"},
if bucket_dt: "total": len(ranged),
label = _dt_label(bucket_dt, interval) "by_type": by_type_arr,
if label: "by_time": by_time_arr,
by_bucket[label] = by_bucket.get(label, 0) + 1 },
}
by_type_arr = [{"type": k, "count": int(v)} for k, v in sorted(by_type.items(), key=lambda x: (-x[1], x[0]))] )
by_time_arr = [{"bucket": k, "count": int(v)} for k, v in sorted(by_bucket.items(), key=lambda x: x[0])] except Exception as e:
return JsonResponse({"status": "error", "message": str(e) or "生成失败"}, status=500)
return JsonResponse(
{
"status": "success",
"data": {
"generated_at": datetime.now(timezone.utc).isoformat(),
"range": {"from": gte or "", "to": lte or ""},
"filters": {"key": key or "", "type": typ or "", "interval": interval or "day"},
"total": len(ranged),
"by_type": by_type_arr,
"by_time": by_time_arr,
},
}
)
@require_http_methods(["GET"]) @require_http_methods(["GET"])