diff --git a/reaction_board/web/queries.py b/reaction_board/web/queries.py index 382bc87..f2efe07 100644 --- a/reaction_board/web/queries.py +++ b/reaction_board/web/queries.py @@ -894,9 +894,17 @@ class DashboardQueries: # ------------------------------------------------------------ fans - def fans(self, mid: int | None = None, *, days: int = 90) -> dict[str, Any]: + def fans( + self, + mid: int | None = None, + *, + days: int = 90, + recent_days: int = 14, + ) -> dict[str, Any]: if days < 1: raise ValueError("days 必须大于 0") + if recent_days < 1 or recent_days > 3650: + raise ValueError("recent_days 必须在 1~3650 之间") def run(conn: sqlite3.Connection) -> dict[str, Any]: cfg = self.config_store.get() @@ -916,7 +924,8 @@ class DashboardQueries: return { "mid": None, "name": None, "available": False, "options": options, "dates": [], "series": [], - "points": [], "days": days, + "points": [], "recent_points": [], "days": days, + "recent_days": recent_days, } rows = [ dict(row) for row in conn.execute( @@ -933,10 +942,16 @@ class DashboardQueries: "dates": [], "series": [], "points": [], + "recent_points": [], "days": days, + "recent_days": recent_days, } latest = max(str(row["stat_date"]) for row in rows if int(row["ok"]) == 1) if any(int(row["ok"]) == 1 for row in rows) else str(rows[-1]["stat_date"]) first_date = str(rows[0]["stat_date"]) + recent_start = _date_minus(latest, recent_days - 1) + recent_points = [ + row for row in rows if str(row["stat_date"]) >= recent_start + ] start = max(_date_minus(latest, days - 1), first_date) dates = _date_range(start, latest) by_date = {str(row["stat_date"]): row for row in rows} @@ -973,6 +988,8 @@ class DashboardQueries: "dates": dates, "series": series, "points": rows, + "recent_points": recent_points, + "recent_days": recent_days, "stat_date": current["stat_date"], "follower": current.get("follower"), "following": current.get("following"), diff --git a/reaction_board/web/server.py b/reaction_board/web/server.py index 220e2be..1dd5517 100644 --- a/reaction_board/web/server.py +++ b/reaction_board/web/server.py @@ -365,6 +365,7 @@ border-color:#3a2c22;color:#f3e9dc}button{background:#e9b97c;color:#2a1a10}} self._send_json(HTTPStatus.OK, queries.fans( _optional_int(query, "mid"), days=_int_param(query, "days", 90, 1, 3650), + recent_days=_int_param(query, "recent_days", 14, 1, 3650), )) return if path == "/api/candidates": diff --git a/reaction_board/web/static/views/fans.js b/reaction_board/web/static/views/fans.js index 9e54273..4e12f8b 100644 --- a/reaction_board/web/static/views/fans.js +++ b/reaction_board/web/static/views/fans.js @@ -2,7 +2,7 @@ import { api } from "../api.js"; import { centerActiveChips, emptyState, sectionHeader } from "../components.js"; import { lineChart, themeColor } from "../charts.js"; import { - escapeAttr, escapeHtml, formatCount, formatDate, formatDelta, + escapeHtml, formatCount, formatDelta, formatNumber, } from "../format.js"; import { replaceQuery } from "../router.js"; @@ -36,8 +36,7 @@ export async function renderFans(root, { query }) {
默认展示最近 ${fans.recent_days || 14} 天;更早的数据只在曲线中显示。
| 日期 | 粉丝 | 关注 | 状态 | |
|---|---|---|---|---|
| 日期 | 粉丝 | 状态 | ||
| ${escapeHtml(point.stat_date)} | -${point.ok ? formatCount(point.follower) : "—"} | -${point.ok ? formatCount(point.following) : "—"} | +${point.ok ? formatNumber(point.follower) : "—"} | ${point.ok ? "成功" : "失败"} |