开发指南
主题开发
主题生态完全通用—— CF-Server-Monitor 原版的主题可以直接装。完整契约见仓库里的 theme-develop.md(61KB)和 API.md(108KB),这里是最常用的部分。
主题链接形态
主题文件的 raw 地址 =
https://raw.githubusercontent.com/<owner>/<repo>/<ref>/<产物内相对路径>
<ref> 是分支名或 commit,与文件路径直接拼接,不会自动加 dist/ 子目录——所以产物要放在分支根目录。
| 链接形态 | 面板内存缓存 | 浏览器 Cache-Control |
|---|---|---|
分支引用(/tree/main) | 3600 秒 | public, max-age=3600 |
固定 commit(/tree/<40位sha>) | 86400 秒 | public, max-age=31536000, immutable |
正式发布必须用固定 40 位 commit。填 7 位短 sha 会被面板当成「分支名」处理,走分支那行的 1 小时缓存规则——这是最常见的「我明明改了却没生效」。
git rev-parse HEAD # 取完整 40 位 shabash更新后不生效
排查顺序:
curlGitHub raw 地址,确认源文件确实更新了curl -sI <面板>/assets/<文件>看cf-cache-status- Cloudflare 清缓存
- 无痕窗口复测;浏览器侧
Ctrl+Shift+R硬刷新
面板前面挂了 Cloudflare 的话,commit 引用带 immutable,边缘可能一直吐旧文件。
面板运行时设置
下面这些通过 GET /api/config 下发,主题必须动态读取,不要写死:
| 设置 | 说明 |
|---|---|
online_threshold_seconds | 在线判定阈值(秒),默认 300,可调 60–3600 |
public_history_hours | 访客可查询的历史范围上限(小时),默认 24 |
frontend_ws_timeout_minutes | 实时订阅单次连接时长(分钟),0 = 不按时间断开 |
long_history_points | 长历史查询的采样点数(60/120/180/240) |
latency_window | ping / loss 窗口参数 |
site_title、display_mode、preferred_theme | 站点标题、默认展示模式、默认主题 |
default_language | 默认语言 |
theme_options | 主题自身配置,配合 POST /api/theme_options 读写 |
从 CF 原版搬主题时的 4 处差异
公开 API 是上游超集,所以搬过来的主题不会少数据。但这 4 处会表现出差异,移植时逐条确认:
- 历史范围:原版上限 168 小时;本面板支持到 720 小时,访客范围由
public_history_hours决定。原版主题的时间档位写死在产物里(通常只到 7 天),要支持 14 / 30 天必须改档位表。 - 在线判定:原版硬编码 300 秒;本面板由
online_threshold_seconds决定。主题写死会导致页面上的在线状态与面板不一致。 - 访客字段:原版只在前端隐藏价格/到期/流量,接口照发;本面板在后台关闭对应开关时 "服务端直接剥离字段",字段可能整个不存在——主题必须兼容缺失,不能假设它一定在。
- 配置字段:本面板多出
online_threshold_seconds、public_history_hours;原版有github_oauth_enabled(本面板没有)。其余接口、WS 消息、鉴权方式与上游完全一致。
实时推送下的引用稳定性
这是移植时最容易踩的坑,单独拎出来说。
不要把「每次推送都会换引用」的对象直接当依赖 / 缓存键。详情页的单台订阅是实时推送(每秒级),前端数据层每次合并 batchUpdate 都会给对应的服务器对象、列表数组换一份新引用(内容往往只有实时指标在变)。
把这类对象(或由它派生的名字表、可见线路集合、id 数组)直接放进 useMemo 依赖 /
图表配置依赖 / 缓存键时,整条链会跟着推送节奏重算:
- 轻则每帧白算一遍
- 重则图表被整个销毁重建(如
uplot-react的options引用一变就destroy + create)
症状是「延迟图每秒闪一下 / 一直刷新」,而数据其实没变。
排查这类问题看元素身份,不要只看像素 / 文本。图表被销毁重建时画面内容相同、旧 canvas 引用已失效——截图对比、像素散列、文本 diff 都测不出来。正确测法:每秒检查图表根节点(document.querySelector('.uplot'))是否还是同一个 DOM 节点,或用 MutationObserver 观察图表容器是否被整体替换。
按内容判断、按内容稳定引用:给派生值算一个内容键(名字表按线路拼串、id 集合拼串等),键没变就复用上一次的对象。