v2.6.0 历史分页+筛选+搜索+表头升降排序;一键清空历史(DELETE /api/tests);右下角置顶/置底悬浮按钮

This commit is contained in:
2026-09-06 02:32:35 +08:00
parent 901232c75f
commit edbaedce15
7 changed files with 346 additions and 49 deletions
+70 -3
View File
@@ -2,6 +2,7 @@
"""SQLite 存储:提供商配置 / 测试记录 / 每次采样指标 / 全量日志"""
import os
import json
import math
import sqlite3
import threading
import time
@@ -204,20 +205,86 @@ def get_test(tid: int):
conn.close()
def list_tests(limit=100):
# 历史列表排序字段 → 取值函数(数值字段取 summary 聚合值,None 恒排最后)
SORT_KEYS = {
"id": lambda t: t["id"],
"created_at": lambda t: t["created_at"],
"name": lambda t: (t.get("name") or "").lower(),
"provider": lambda t: (t.get("provider") or "").lower(),
"model": lambda t: (t.get("model") or "").lower(),
"status": lambda t: t.get("status") or "",
"samples": lambda t: (t.get("summary") or {}).get("samples_ok"),
"ttft": lambda t: (t.get("summary") or {}).get("avg_ttft_ms"),
"prefill": lambda t: (t.get("summary") or {}).get("avg_prefill_speed"),
"decode": lambda t: (t.get("summary") or {}).get("avg_decode_speed"),
"total_ms": lambda t: (t.get("summary") or {}).get("avg_total_ms"),
}
def query_tests(q="", status="", provider="", sort="id", order="desc",
page=1, page_size=20):
"""历史记录:关键词搜索 + 状态/提供商筛选 + 字段排序 + 分页。
返回 {"items": [...], "total": N, "page": p, "page_size": s, "total_pages": n}"""
with _lock:
conn = _connect()
try:
where, args = [], []
if q:
like = "%" + q + "%"
where.append("(id LIKE ? OR name LIKE ? OR model LIKE ? OR provider LIKE ?"
" OR status LIKE ? OR created_at LIKE ?)")
args += [like] * 6
if status:
sts = [s.strip() for s in status.split(",") if s.strip()]
if sts:
where.append("status IN (%s)" % ",".join("?" * len(sts)))
args += sts
if provider:
where.append("provider = ?")
args.append(provider)
wsql = ("WHERE " + " AND ".join(where)) if where else ""
rows = conn.execute(
"SELECT id,created_at,status,provider,model,name,summary_json,gen_cfg_json,error "
"FROM tests ORDER BY id DESC LIMIT ?", (limit,)).fetchall()
"FROM tests " + wsql + " ORDER BY id DESC", args).fetchall()
out = []
for r in rows:
d = dict(r)
d["summary"] = json.loads(d.pop("summary_json") or "{}")
d["gen"] = json.loads(d.pop("gen_cfg_json") or "{}")
out.append(d)
return out
# Python 侧排序:None 值恒排最后(无论升降序)
keyfn = SORT_KEYS.get(sort) or SORT_KEYS["id"]
present = [t for t in out if keyfn(t) is not None]
absent = [t for t in out if keyfn(t) is None]
present.sort(key=keyfn, reverse=(order == "desc"))
out = present + absent
total = len(out)
total_pages = max(1, math.ceil(total / page_size))
page = min(max(1, page), total_pages)
start = (page - 1) * page_size
return {
"items": out[start:start + page_size],
"total": total,
"page": page,
"page_size": page_size,
"total_pages": total_pages,
}
finally:
conn.close()
def clear_tests():
"""一键清空全部历史(测试记录 + 采样指标 + 日志)"""
with _lock:
conn = _connect()
try:
conn.execute("DELETE FROM test_runs")
conn.execute("DELETE FROM logs")
conn.execute("DELETE FROM tests")
conn.commit()
finally:
conn.close()