release: bump version to 0.28.1

This commit is contained in:
linkong
2026-04-20 15:14:53 +08:00
parent 4c21973197
commit 75cb214f23
42 changed files with 8556 additions and 89 deletions

17
docs/deprecated/README.md Normal file
View File

@@ -0,0 +1,17 @@
# Deprecated Docs
这个目录用于存放两类文档:
1. 已经完成、主要保留为历史记录的实施计划
2. 已被现有实现或新方案替代的旧计划
放到这里并不代表这些文档“错误”,而是表示:
- 它们不再适合作为当前开发的主指导文档
- 如果要了解历史决策、演进路径或旧设计背景,仍然可以参考
当前归档原则:
- 明确写明“已完成”的计划,优先归档
- 已被正式实现替代、继续放在 `docs/` 根目录会误导后续开发的计划,归档
- 仍然指导未来开发、尚未完成或仍有明确执行价值的文档,继续保留在 `docs/`

View File

@@ -0,0 +1,207 @@
# collected_data 强耦合列拆除计划
## 背景
当前 `collected_data` 同时承担了两类职责:
1. 通用采集事实表
2. 少数数据源的宽表字段承载
典型强耦合列包括:
- `country`
- `city`
- `latitude`
- `longitude`
- `value`
- `unit`
以及 API 层临时平铺出来的:
- `cores`
- `rmax`
- `rpeak`
- `power`
这些字段并不适合作为统一事实表的长期 schema。
推荐方向是:
- 表内保留通用稳定字段
- 业务差异字段全部归入 `metadata`
- API 和前端动态读取 `metadata`
## 拆除目标
最终希望 `collected_data` 只保留:
- `id`
- `snapshot_id`
- `task_id`
- `source`
- `source_id`
- `entity_key`
- `data_type`
- `name`
- `title`
- `description`
- `metadata`
- `collected_at`
- `reference_date`
- `is_valid`
- `is_current`
- `previous_record_id`
- `change_type`
- `change_summary`
- `deleted_at`
## 计划阶段
### Phase 1读取层去依赖
目标:
- API / 可视化 / 前端不再优先依赖宽列表字段
- 所有动态字段优先从 `metadata`
当前已完成:
- 新写入数据时,将 `country/city/latitude/longitude/value/unit` 自动镜像到 `metadata`
- `/api/v1/collected` 优先从 `metadata` 取动态字段
- `visualization` 接口优先从 `metadata` 取动态字段
- 国家筛选已改成只走 `metadata->>'country'`
- `CollectedData.to_dict()` 已切到 metadata-first
- 变更比较逻辑已切到 metadata-first
- 已新增历史回填脚本:
[scripts/backfill_collected_data_metadata.py](/home/ray/dev/linkong/planet/scripts/backfill_collected_data_metadata.py)
- 已新增删列脚本:
[scripts/drop_collected_data_legacy_columns.py](/home/ray/dev/linkong/planet/scripts/drop_collected_data_legacy_columns.py)
涉及文件:
- [backend/app/core/collected_data_fields.py](/home/ray/dev/linkong/planet/backend/app/core/collected_data_fields.py)
- [backend/app/services/collectors/base.py](/home/ray/dev/linkong/planet/backend/app/services/collectors/base.py)
- [backend/app/api/v1/collected_data.py](/home/ray/dev/linkong/planet/backend/app/api/v1/collected_data.py)
- [backend/app/api/v1/visualization.py](/home/ray/dev/linkong/planet/backend/app/api/v1/visualization.py)
### Phase 2写入层去依赖
目标:
- 采集器内部不再把这些字段当作数据库一级列来理解
- 统一只写:
- 通用主字段
- `metadata`
建议动作:
1. Collector 内部仍可使用 `country/city/value` 这种临时字段作为采集过程变量
2. 进入 `BaseCollector._save_data()` 后统一归档到 `metadata`
3. `CollectedData` 模型中的强耦合列已从 ORM 移除,写入统一归档到 `metadata`
### Phase 3数据库删列
目标:
-`collected_data` 真正移除以下列:
- `country`
- `city`
- `latitude`
- `longitude`
- `value`
- `unit`
注意:
- `cores / rmax / rpeak / power` 当前本来就在 `metadata` 里,不是表列
- 这四个主要是 API 平铺字段,不需要数据库删列
## 当前阻塞点
在正式删列前,还需要确认这些地方已经完全不再直接依赖数据库列:
### 1. `CollectedData.to_dict()`
文件:
- [backend/app/models/collected_data.py](/home/ray/dev/linkong/planet/backend/app/models/collected_data.py)
状态:
- 已完成
### 2. 差异计算逻辑
文件:
- [backend/app/services/collectors/base.py](/home/ray/dev/linkong/planet/backend/app/services/collectors/base.py)
状态:
- 已完成
- 当前已改成比较归一化后的 metadata-first payload
### 3. 历史数据回填
问题:
- 老数据可能只有列值,没有对应 `metadata`
当前方案:
- 在删列前执行一次回填脚本:
- [scripts/backfill_collected_data_metadata.py](/home/ray/dev/linkong/planet/scripts/backfill_collected_data_metadata.py)
### 4. 导出格式兼容
文件:
- [backend/app/api/v1/collected_data.py](/home/ray/dev/linkong/planet/backend/app/api/v1/collected_data.py)
现状:
- CSV/JSON 导出已基本切成 metadata-first
建议:
- 删列前再回归检查一次导出字段是否一致
## 推荐执行顺序
1. 保持新数据写入时 `metadata` 完整
2. 把模型和 diff 逻辑完全切成 metadata-first
3. 写一条历史回填脚本
4. 回填后观察一轮
5. 正式执行删列迁移
## 推荐迁移 SQL
仅在确认全部读取链路已去依赖后执行:
```sql
ALTER TABLE collected_data
DROP COLUMN IF EXISTS country,
DROP COLUMN IF EXISTS city,
DROP COLUMN IF EXISTS latitude,
DROP COLUMN IF EXISTS longitude,
DROP COLUMN IF EXISTS value,
DROP COLUMN IF EXISTS unit;
```
## 风险提示
1. 地图类接口对经纬度最敏感
必须确保所有地图需要的记录,其 `metadata.latitude/longitude` 已回填完整。
2. 历史老数据如果没有回填,删列后会直接丢失这些信息。
3. 某些 collector 可能仍隐式依赖这些宽字段做差异比较,删列前必须做一次全量回归。
## 当前判断
当前项目已经完成“代码去依赖 + 历史回填 + readiness 检查”。
下一步执行顺序建议固定为:
1. 先部署当前代码版本并重启后端
2. 再做一轮功能回归
3. 最后执行:
`uv run python scripts/drop_collected_data_legacy_columns.py`

View File

@@ -0,0 +1,210 @@
# Earth 模块整治计划
## 背景
`planet` 前端中的 Earth 模块是当前最重要的大屏 3D 星球展示能力,但它仍以 legacy iframe 页面形式存在:
- React 页面入口仅为 [Earth.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/Earth/Earth.tsx)
- 实际 3D 实现位于 [frontend/public/earth](/home/ray/dev/linkong/planet/frontend/public/earth)
当前模块已经具备基础展示能力,但在生命周期、性能、可恢复性、可维护性方面存在明显隐患,不适合长期无人值守的大屏场景直接扩展。
## 目标
本计划的目标不是立刻重写 Earth而是分阶段把它从“能跑的 legacy 展示页”提升到“可稳定运行、可持续演进的大屏核心模块”。
核心目标:
1. 先止血,解决资源泄漏、重载污染、假性卡顿等稳定性问题
2. 再梳理数据加载、交互和渲染循环,降低性能风险
3. 最后逐步从 iframe legacy 向可控模块化架构迁移
## 现阶段主要问题
### 1. 生命周期缺失
- 没有统一 `destroy()` / 卸载清理逻辑
- `requestAnimationFrame`
- `window/document/dom listeners`
- `THREE` geometry / material / texture
- 运行时全局状态
都没有系统回收
### 2. 数据重载不完整
- `reloadData()` 没有彻底清理旧场景对象
- cable、landing point、satellite 相关缓存与对象存在累积风险
### 3. 渲染与命中检测成本高
- 鼠标移动时频繁创建 `Raycaster` / `Vector2`
- cable 命中前会重复做 bounding box 计算
- 卫星每帧计算量偏高
### 4. 状态管理分裂
- 大量依赖 `window.*` 全局桥接
- 模块之间靠隐式共享状态通信
- React 外层无法有效感知 Earth 内部状态
### 5. 错误恢复弱
- 数据加载失败主要依赖 `console` 和轻提示
- 缺少统一重试、降级、局部失败隔离机制
## 分阶段计划
## Phase 1稳定性止血
目标:
- 不改视觉主形态
- 优先解决泄漏、卡死、重载污染
### 任务
1. 补 Earth 生命周期管理
- 为 [main.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/main.js) 增加:
- `init()`
- `destroy()`
- `reloadData()`
三类明确入口
- 统一记录并释放:
- animation frame id
- interval / timeout
- DOM 事件监听
- `window` 暴露对象
2. 增加场景对象清理层
- 为 cable / landing point / satellite sprite / orbit line 提供统一清理函数
- reload 前先 dispose 旧对象,再重新加载
3. 增加 stale 状态恢复
- 页面重新进入时先清理上一次遗留选择态、hover 态、锁定态
- 避免 iframe reload 后出现旧状态残留
4. 加强失败提示
- 电缆、登陆点、卫星加载拆分为独立状态
- 某一类数据失败时,其它类型仍可继续显示
- 提供明确的页面内提示而不是只打 console
### 验收标准
- 页面重复进入 / 离开后内存不持续上涨
- 连续多次点“重新加载数据”后对象数量不异常增加
- 单一数据源加载失败时页面不整体失效
## Phase 2性能优化
目标:
- 控制鼠标交互和动画循环成本
- 提升大屏长时间运行的稳定帧率
### 任务
1. 复用交互对象
- 复用 `Raycaster``Vector2`、中间 `Vector3`
- 避免 `mousemove` 热路径中频繁 new 对象
2. 优化 cable 命中逻辑
- 提前缓存 cable 中心点 / bounding 数据
- 移除 `mousemove` 内重复 `computeBoundingBox()`
- 必要时增加分层命中:
- 先粗筛
- 再精确相交
3. 改造动画循环
- 使用真实 `deltaTime`
- 把卫星位置更新、呼吸动画、视觉状态更新拆成独立阶段
- 为不可见对象减少无意义更新
4. 卫星轨迹与预测轨道优化
- 评估轨迹更新频率
- 对高开销几何计算增加缓存
- 限制预测轨道生成频次
### 验收标准
- 鼠标移动时不明显掉帧
- 中高数据量下动画速度不受帧率明显影响
- 长时间运行 CPU/GPU 占用更平稳
## Phase 3架构收编
目标:
- 降低 legacy iframe 架构带来的维护成本
- 让 React 主应用重新获得对 Earth 模块的控制力
### 任务
1. 抽离 Earth App Shell
- 将数据加载、错误状态、控制面板状态抽到更明确的模块边界
- 减少 `window.*` 全局依赖
2. 规范模块通信
- 统一 `main / controls / cables / satellites / ui` 的状态流
- 明确只读配置、运行时状态、渲染对象的职责分层
3. 评估去 iframe 迁移
- 中期可以保留 public/legacy 资源目录
- 但逐步把 Earth 作为前端内嵌模块而不是完全孤立页面
### 验收标准
- Earth 内部状态不再大量依赖全局变量
- React 外层可以感知 Earth 加载状态和错误状态
- 后续功能开发不再必须修改多个 legacy 文件才能完成
## 优先级建议
### P0
- 生命周期清理
- reload 清理
- stale 状态恢复
### P1
- 命中检测优化
- 动画 `deltaTime`
- 数据加载失败隔离
### P2
- 全局状态收编
- iframe 架构迁移
## 推荐实施顺序
1. 先做 Phase 1
2. 再做交互热路径与动画循环优化
3. 最后再考虑架构迁移
## 风险提示
1. Earth 是 legacy 模块,修复时容易牵一发而动全身
2. 如果不先补清理逻辑,后续所有性能优化收益都会被泄漏问题吃掉
3. 如果过早重写而不先止血,短期会影响现有演示稳定性
## 当前建议
最值得马上启动的是一个小范围稳定性 sprint
- 生命周期清理
- reload 全量清理
- 错误状态隔离
这个阶段不追求“更炫”,先追求“更稳”。稳定下来之后,再进入性能和架构层的优化。

View File

@@ -0,0 +1,117 @@
# Earth 电视直播模块计划
## 目标
`Earth` 页面增加一个可配置、可扩展、可拖拽的电视直播模块:
- 后台可配置新闻直播源
- 默认兜底源为央视 `CCTV-4`
- 未来可通过采集器接入世界各地新闻直播源
- Earth 工具栏 `显示控制` 子菜单新增电视按钮
- 点击后打开一个与其他 HUD 一致的可拖拽/可关闭窗口
- 窗口内部可播放或承载新闻直播页面
## 设计原则
- 第一阶段先交付“后台可配 + Earth 可用 + 默认可回退”的版本
- 公开读取接口与后台管理接口分离
- 手工配置源与采集器源共用统一的前端消费结构
- Earth 里的电视窗口必须复用现有 HUD 拖拽、关闭、布局最大化逻辑
- 小屏下优先保证窗口完整显示,超出部分在窗口内部滚动
## 分阶段实现
### Phase 1后端配置与公开读取
- 在系统设置中新增 `tv` 分类
- 定义直播源配置结构:
- `default_source_id`
- `auto_fallback`
- `sources[]`
- 每个直播源至少包含:
- `id`
- `name`
- `provider`
- `region`
- `language`
- `source_type`
- `embed_url`
- `stream_url`
- `homepage_url`
- `is_enabled`
- `is_fallback`
- `sort_order`
- `collector_source`
- `notes`
- 默认兜底源使用央视官网 `CCTV-4` 直播页
- 新增公开读取接口,供 Earth 页面无登录态读取直播源配置
### Phase 2采集器扩展位
- 新增 `news_live_streams` collector 占位
- 规范采集器入库数据结构,使其能与后台手工配置源合并
- TV 公开接口支持合并:
- 后台手工配置源
- 采集器入库源
- 保持手工配置源优先级更高,避免采集器覆盖人工兜底配置
### Phase 3后台配置界面
- 在系统配置页新增 `电视直播` tab
- 支持:
- 查看当前默认源
- 开关自动回退
- 新增直播源
- 编辑直播源
- 删除直播源
- 启用/禁用直播源
- 将某个直播源设为默认源
- 明确区分:
- 手工配置源
- 采集器来源
### Phase 4Earth HUD 集成
-`显示控制` 子菜单加入电视按钮
- 新增 TV HUD 面板:
- 可拖拽
- 可关闭
- 支持显示/隐藏状态同步
- 参与布局最大化与恢复布局
- 面板内容至少包含:
- 当前频道标题
- 源切换下拉菜单
- 刷新按钮
- 打开官网按钮
- 播放区域
### Phase 5播放策略
- 第一版优先支持 `iframe`/嵌入页类直播源
- 为未来扩展保留:
- `hls`
- `video`
- `external`
- 如果默认源不可用:
- 优先回退到标记为 `is_fallback=true` 的源
- 若无明确回退源,则回退到第一个可用源
- 面板内要有清晰的加载、错误、回退提示
### Phase 6打磨与清理
- 统一 HUD 风格
- 小屏下限制窗口尺寸并启用内部滚动
- 避免窗口超出屏幕
- 补最小验证
- 清理临时代码、重复样式和无用资源
## 首版交付定义
当以下条件满足时,认为首版可用:
- 后台可以配置新闻直播源
- Earth 可以读取并显示默认直播源
- 工具栏可打开电视窗口
- 电视窗口可拖拽、可关闭
- 央视 `CCTV-4` 作为默认兜底源可被使用
- 代码结构已为后续采集器接入预留统一接口

View File

@@ -0,0 +1,165 @@
# HUD Panel Component Plan
## Goal
Unify Earth HUD panels into a reusable component layer so new panels can share:
- a consistent shell
- a consistent header
- a consistent action-button system
- a consistent body and collapse pattern
## Scope
Target panels:
- `tv-panel`
- `news-panel`
- `legend`
- `layer-panel`
- `earth-stats`
- `info-card`
- settings modal header/actions
## Component Model
### Base shell
- `.hud-panel`
- `.hud-panel--compact`
- `.hud-panel--media`
- `.hud-panel--collapsed`
- `.hud-panel-hidden`
- `.hud-panel.is-dragging`
- `.hud-panel.is-layout-animating`
### Header
- `.hud-panel__header`
- `.hud-panel__title-group`
- `.hud-panel__title`
- `.hud-panel__subtitle`
- `.hud-panel__chip`
- `.hud-panel__actions`
Header baseline rule:
- Header title styling is fixed by the component layer and should not drift per panel
- Title font size, font weight, letter spacing, line height, text color, and vertical alignment come from the shared header tokens and structure
- Header divider, border treatment, inner spacing, and title-to-actions alignment are part of the same shared baseline
- Panel-specific header differences should be limited to explicit variants such as `compact` or `media`, or token overrides with documented intent
- “Looks close enough” local header overrides should be treated as temporary compatibility code and removed during migration
### Actions
- `.hud-panel__action`
- `.hud-panel__action--icon`
- `.hud-panel__action--collapse`
- `.hud-panel__action--close`
- `.hud-panel__action--refresh`
- `.hud-panel__action--external`
Action-button baseline rule:
- Header action buttons must have one fixed default style baseline across all HUD panels
- Default width behavior, padding, icon size, radius, alignment, hover, and active feedback all come from `.hud-panel__action`
- Panel-specific differences must be expressed through explicit variants or token overrides, not ad-hoc local button rewrites
- `close` buttons are part of the same default action system and must not silently fall back to a separate legacy box model
### Body
- `.hud-panel__body`
- `.hud-panel__body--scroll`
- `.hud-panel__body--collapsible`
### Collapse behavior
- `.hud-panel--collapsed`
- `.hud-panel--expand-up`
- `.hud-panel--expand-down`
Adaptive collapse / expand rule:
- HUD panels support two expansion directions:
- top-to-bottom expansion
- bottom-to-top expansion
- Expansion direction should be decided at runtime from available viewport space rather than hardcoded per panel
- Use:
- `d` = available distance from the header anchor to the viewport bottom edge
- `h` = expected expanded panel height
- buffer = `20px`
- Collapsed-state direction rule:
- if `d > h + 20px`, the next action direction is `expand-up`
- if `d <= h + 20px`, the next action direction is `expand-down`
- To avoid jitter around the threshold, the shared controller should keep a small hysteresis band:
- if the current direction is already `up`, keep it until `d <= h`
- if the current direction is already `down`, keep it until `d > h + 20px`
- The opposite edge is still a safety guard:
- if the chosen side cannot fit at all, fall back to the other side if it can fit
- if neither side fully fits, choose the side with more space and let the body scroll
- If neither direction fully fits, choose the direction with more available space and let the body scroll
- Collapse icon direction must match the active expansion direction so the icon always describes the real open/close motion
- The collapse icon describes the next action, not the current state
- This mapping is fixed component behavior and must not drift per panel:
- collapsed + expand-down => `expand_more`
- expanded + expand-down => `expand_less`
- collapsed + expand-up => `expand_less`
- expanded + expand-up => `expand_more`
- Panels must not combine icon-name swapping with extra CSS rotation for the same collapse control
- Expansion direction and icon direction must come from one shared source of truth in the component controller
- The direction decision should be recomputed when opening, resizing the viewport, or restoring a dragged panel near another edge
## Tokens
Promote panel differences into CSS variables instead of duplicating selectors:
- `--hud-panel-padding`
- `--hud-header-padding`
- `--hud-header-gap`
- `--hud-action-padding`
- `--hud-action-gap`
- `--hud-action-icon-size`
- `--hud-body-gap`
- `--hud-body-max-height`
- `--hud-chip-radius`
- `--hud-title-font-size`
- `--hud-title-font-weight`
- `--hud-title-letter-spacing`
- `--hud-title-line-height`
- `--hud-title-color`
- `--hud-header-border-color`
- `--hud-header-divider-opacity`
- `--hud-expand-direction`
## Migration Order
1. Build the shared component layer in `frontend/public/earth/css/hud.css`
2. Migrate `tv-panel` and `news-panel` first as the reference implementation
3. Migrate `legend` and `layer-panel` into a compact variant
4. Migrate `earth-stats` and `info-card`
5. Align settings modal header/actions with the same action system
6. Remove legacy one-off button selectors after verification
## Guardrails
- Do not change panel behavior and data flow during the first pass
- Keep old class names temporarily as compatibility hooks
- Prefer variable overrides over per-panel reimplementation
- Treat header action-button default styling as fixed component API, not per-panel design space
- Treat header title typography, border, and divider styling as fixed component API, not per-panel design space
- Treat collapse direction as a component behavior contract, not a one-off panel trick
- Treat collapse icon semantics as a component behavior contract, not a per-panel visual preference
- Verify header alignment and drag/collapse behavior after each migration batch
## First Implementation Batch
Batch 1 should only do:
- shared header structure
- shared action-button system
- shared title typography and header border/divider baseline
- shared collapsible body pattern
- adaptive collapse direction logic and direction-aware collapse icons
- migration of `tv-panel` and `news-panel`
That keeps risk low while giving the rest of the HUD a stable target to migrate toward.