4.9 KiB
Dashboard Overview API
本文档说明 Issue #2277 的后端契约阶段。首页看板必须通过单一只读端点消费持久化/缓存状态,不在浏览器用当前分页数组猜测全量指标,也不在刷新时启动分析或 LLM。
端点
GET /api/v1/dashboard/overview
响应分为 market、personal、activity、system 和第一等的 what_changed。每个块包含:
quality:fresh、partial或unavailable。sources:该块实际读取的持久化/缓存来源。stale:只有来源能可靠判断时才给布尔值;无法证明时为null,不伪造 freshness。limitations:稳定的降级 code,不返回原始异常或配置秘密。
指标语义
market.review_count使用 History API repository 返回的total,不使用当前已加载页的数组长度。personal.watchlist_count每次请求读取当前 runtime config;active_monitor_count使用 Alert repository 的total,不受page_size=100限制。personal.cached_position_count只读取非零缓存仓位 identity,不触发实时估值或写 snapshot,因此块包含cached_positions_only。activity.recent_reports排除 market review,并在一次数据库语句中读取最近 100 条历史及同一快照下的总数,再从该固定窗口选择最近 5 条非 market 报告;窗口外仍有历史且窗口内不足 5 条时返回recent_reports_history_scan_incomplete。task_stats只读当前 task queue 统计。system.refresh_starts_analysis固定为false。该 service 不依赖 analyzer、LLM client、market-review generation 或 task submission 方法。
What Changed
首阶段的 comparison_mode 固定为 previous_completed_snapshot。服务从已经持久化的 market review history 中分页读取结构化 context_snapshot.market_light_snapshots,每页在同一次历史查询中投影所需快照,不为每条记录再发详情查询;单次请求最多扫描最近 100 条复盘记录。若历史仍未耗尽,会返回 market_review_history_scan_incomplete 并将 market/what_changed 降级为 partial。扫描窗口内按 trade_date 排序并去重,对每个 region 比较最新日期与严格更早的基线,不把同日重跑或乱序写入直接当作 previous:
- score 变化输出
market.<region>.score,并给出 before/after 与 increased/decreased。 - red/yellow/green 状态变化输出
market.<region>.status。 - change item 的 quality 取 current/previous 两份快照中较差的一侧;任一侧 partial 会降低整个 what_changed 块,任一侧 unavailable 不生成可靠变化项。
- 没有第二份有效快照时,返回
previous_completed_snapshot_unavailable;部分 region 缺基线时整个块标记为partial,并追加previous_completed_snapshot_unavailable:<region>,避免把“缺少基线”误解为“没有变化”。不会临时拉行情或生成一份“当前”快照冒充基线。 - 历史详情读取失败、投影出的
context_snapshot不是 JSON object、其中已存在的market_light_snapshots不是 object(例如损坏的 JSON 字符串/数组),或已声明 review scope 的记录完全缺少/只保存空的 snapshot container 时,不再把其余更旧记录提升为 current/latest;对应快照和变化对比保持不可用并返回 limitation。没有可识别 scope 的旧记录仍按 legacy 无快照记录处理,避免它们无差别阻断所有市场。 - 快照校验失败时仍保留其
trade_date的目标位置:最新日期无有效快照时不回退到更旧 current,最近更早日期无有效快照时不越过它继续寻找更旧 previous。同一目标日期存在其他有效重跑快照时,仍可使用该日期的有效版本。 - 外层市场键必须与快照内部
region一致;例如cn键下的region=us快照会按无效快照处理,不能进入 A 股的 current/previous 或变化项。 market_light_snapshotsobject 中任何已出现的 region 条目都必须仍是 object;例如最新记录里的cn: []会把 CN current 标为不可用,不能被过滤后再让旧 CN 快照冒充最新。- 历史扫描被截断等 market limitations 会同步进入 what_changed;剩余快照不能在来源历史不完整时被标记为 fresh。
后续阶段可以在已有持久化契约上增加 watchlist score、portfolio exposure、ranking 和 thesis invalidation 变化;必须先有可靠的 current/previous snapshot identity,不能从页面当前分页或 target 文本猜测。
阶段边界与回滚
本阶段不修改 Home 默认选择逻辑、不新增 Web 卡片、不接线刷新按钮,因此旧 PR #2290 的“返回用户自动打开报告导致看板不可达”问题不被带入。后续 Web PR 需消费本 API,并补 loading/partial/empty/success、移动端布局和截图证据。
回滚时 revert 本 PR 即可移除 schema、service、endpoint、测试和文档。没有数据库迁移、配置写入或数据清理步骤。