硬要求(用户明确):不允许出现需要滚动才能看全的情况。
改动:
- 表格 table-layout: fixed + 百分比列宽(8/16/21/8/7/11/17/12%),
表头允许换行并裁剪、单元格裁剪、心率图与可用率条随宽度伸缩
- 卡片网格 minmax(min(300px,100%),1fr) + .card{min-width:0}
(修 grid 的 min-width:auto 撑破:320px 下曾溢出 495px)
- 截断的名称/目标补 title,悬停可看完整值
- 新增 scripts/verify-layout.cjs:自带极端配置(40 目标 / 6 分组 /
超长名称与 URL)+ 临时静态服务,扫描 13 视口 × 2 视图,26 项断言零横向滚动
验证:五套 115 项全通过(17+30+26+20+22)
557 lines
43 KiB
Markdown
557 lines
43 KiB
Markdown
# shiroko-monitor
|
||
|
||
轻量级服务监控面板。借鉴 Uptime Kuma 的交互思路,代码完全自研,**零运行时依赖**(Node ≥ 18 直接跑,无 npm install),纯静态前端 + 可插拔探针,支持本地 / GitHub Pages / Cloudflare Workers / EdgeOne Pages 等多种低成本部署。
|
||
|
||
## 功能特性
|
||
|
||
- **HTTP 可用性探测**:状态码(支持自定义期望值,如把 500 判为正常)、响应延迟、超时控制、不自动跟随重定向(保留 3xx 原始码)
|
||
- **TCP 端口探测**:连通性判定、连接耗时,区分「连接被拒绝」与「超时」
|
||
- **Banner 探测(SSH / SMTP / FTP / POP3 / IMAP 等)**:连接后**被动读取**服务端主动发送的标识串,支持 `expectBanner` 规则校验(可做版本合规检查);不做认证、不发任何数据,不会触发目标侧的 fail2ban 封禁。默认只输出协议族摘要,不回显版本号
|
||
- **90 天可用率**:按天聚合每次探测结果(保留 90 天,自动淘汰旧数据),卡片底部以 90 格色条展示每日可用率(≥99% 绿 / ≥95% 橙 / <95% 红 / 无数据灰),悬停显示当日「可用率(在线次数/总次数)」;顶部汇总整体可用率
|
||
- **两种面板形态**(顶部一键切换,也可用 `settings.view` / `?view=` 指定):
|
||
- **表格**:一行一服务的高密度列表(状态/名称/目标/延迟/结果/最近检测/心率/可用率),默认视图
|
||
- **卡片**:一服务一卡,含心率图与可用率条
|
||
- **数据源过滤**:`settings.dataFilter` 可选 `both`(默认,两边都展示)/ `config`(只看配置文件里的自建目标)/ `uptimerobot`(只看 UptimeRobot 数据);也可用 `?filter=` 临时切换,顶部统计随展示集合同步
|
||
- **可配置的自动刷新**:`settings.refreshInterval`(秒)决定面板自动刷新节奏;未显式配置时,「只看 UptimeRobot」模式默认 300 秒(UR 自身 5 分钟才更新一次,刷新更快没有意义)
|
||
- **监控面板**:
|
||
- 每个服务的在线 / 离线 / 等待检测状态(绿点脉冲动画)
|
||
- 响应延迟、结果(状态码 / 端口 / 标识串)、最近检测时间(相对时间 + 悬停显示精确时间)
|
||
- 最近 48 次检测的心率图(绿色 = 在线,红色 = 离线,柱高 = 延迟)
|
||
- 分组页签筛选,顶部统计摘要(监控数 / 在线 / 离线 / 平均延迟 / 90 天可用率)
|
||
- 自动刷新倒计时(基于截止时间,不受浏览器后台标签页定时器节流影响)、手动刷新按钮、暗色模式自适应(`prefers-color-scheme`)
|
||
- **配置即文件**:`public/monitors.json` 单一配置源,改完即生效(本地探针支持热重载)
|
||
- **刷新节奏由服务端驱动**:探测由服务端按各目标 `interval` 持续进行,快照里带上「数据最后更新时刻 + 服务端更新节奏」;面板的倒计时对齐到**服务端下次更新时间**,不因访客打开页面而重新计时(旧行为下每次进页面都要重等一整个周期,最坏会看到近两倍周期的旧数据)。自动刷新只读取数据,只有手动点「刷新」才触发一次重新检测
|
||
- **UptimeRobot 双向兼容**:
|
||
- *接入*:把 UptimeRobot 已有的监控结果当数据源拉进来,与自建探测并列展示(异地视角),状态、延迟、90 天可用率、心率图全部映射自 UR 官方数据;UR 读取失败时保留上次数据,绝不把服务误判为离线
|
||
- *输出*:提供 `/api/v2/getMonitors`,字段与状态码编码对齐 UptimeRobot v2,既有脚本/看板可直接消费
|
||
- **滥用防护与信息泄露控制**:刷新接口仅内网/回环可触发、按来源冷却(429 + Retry-After)、可整体关闭;支持 `hideTargets` / `redactDetails` 与 `local.monitors.json` 私有配置分层,公开配置里可以只有服务名 —— 详见 [docs/SECURITY.md](docs/SECURITY.md)
|
||
- **主题:砂狼白子**(默认启用,可一键切回默认主题):简约风插画形象(右下角立绘 + 头像 logo/favicon,宽屏不遮挡表格)、青色光环水印、天蓝围巾飘带顶栏、倒十字发饰、公路车轮加载态。素材来源见 [主题](#主题砂狼白子)
|
||
- **三种数据源自动解析**:边缘 API(实时)→ 静态快照 → 浏览器直连,也可用 `?source=` 强制指定
|
||
|
||
## 快速开始(本地)
|
||
|
||
```bash
|
||
# 常驻模式:周期探测 + 伺服面板(默认端口 8787)
|
||
node prober/node/index.js
|
||
# 或 npm start
|
||
|
||
# 单轮探测后退出(供 CI 使用,历史心率与 90 天分桶从已有 status.json 恢复)
|
||
node prober/node/index.js --once
|
||
# 或 npm run probe
|
||
|
||
# 生成演示数据(含 90 天可用率样例,用于静态部署首版占位)
|
||
node prober/node/index.js --once --demo
|
||
# 或 npm run demo
|
||
|
||
# 自定义快照输出路径(--demo 会覆盖真实快照,需要保留真实数据时用它写到别处)
|
||
node prober/node/index.js --once --demo --out=dist/status.json
|
||
```
|
||
|
||
启动后打开 <http://localhost:8787/> 即可看到面板。无需安装任何依赖。
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
shiroko-monitor/
|
||
├── monitors.json ─────────────── 已移至 public/monitors.json(单一配置源,见下)
|
||
├── package.json # 零依赖,仅封装常用命令
|
||
├── LICENSE # MIT
|
||
├── public/ # 纯静态面板(可整体部署到任意静态托管)
|
||
│ ├── index.html # 面板页面骨架
|
||
│ ├── monitors.json # ★ 监控目标配置(改这里)
|
||
│ ├── status.json # 探针输出的状态快照(面板读取)
|
||
│ └── assets/
|
||
│ ├── style.css # 基础样式(浅色 + 暗色自适应)
|
||
│ ├── theme-shiroko.css # 砂狼白子主题(仅在 body[data-theme=shiroko] 下生效)
|
||
│ ├── shiroko-figure.webp # 简约风立绘(AI 生成后抠底,见「主题」章节)
|
||
│ ├── shiroko-icon.webp # 简约风半身头像(同上)
|
||
│ ├── favicon-shiroko.png # 白子主题图标(由头像生成)
|
||
│ ├── shiroko-bike.webp # 简约风公路车插画(AI 生成后抠底)
|
||
│ ├── deco-scarf.svg # 自绘:天蓝围巾飘带
|
||
│ ├── app.js # 数据源解析 / 渲染 / 浏览器直连探测 / 主题切换
|
||
│ └── favicon.svg # 默认主题图标
|
||
├── prober/node/ # Node 探针(本地 / CI 用)
|
||
│ ├── index.js # 巡检循环 + 静态服务器 + /api/* + /api/v2/getMonitors + --once/--demo/--out/--config
|
||
│ └── lib/
|
||
│ ├── http-probe.js # HTTP 探测(fetch,redirect: manual)
|
||
│ ├── tcp-probe.js # TCP 探测(net.connect)
|
||
│ ├── banner-probe.js # Banner 探测(被动读取标识串,零认证零交互)
|
||
│ └── uptimerobot.js # UptimeRobot 只读数据源(API v2 映射)
|
||
├── scripts/ # 开发验证脚本(需 playwright)
|
||
│ ├── verify.cjs # 热重载 / 数据一致性 / 刷新语义 / 面板渲染
|
||
│ ├── verify-views.cjs # 视图渲染、切换持久化与数据源过滤
|
||
│ ├── verify-security.cjs # banner 探测 / 脱敏 / 私有分层 / 刷新限流
|
||
│ ├── verify-uptimerobot.cjs # UR 映射单测 / 兼容接口 / 失败路径 / 真实 Key 冒烟
|
||
│ ├── prepare-artwork.py # 从 assets-src/ 原图生成透明素材(边界 + 封闭区域两步抠图)
|
||
│ └── verify-layout.cjs # 布局回归:极端内容 × 13 视口 × 2 视图,断言零横向滚动
|
||
├── assets-src/ # 插画原始素材(AI 生成的白底原图,供重新处理)
|
||
├── local.monitors.json # 私有配置(不入库):真实地址、API Key
|
||
├── edge/cloudflare/ # Cloudflare Workers 边缘探针
|
||
│ ├── worker.js # cron 探针 + KV 存储 + /api/* + 静态伺服
|
||
│ └── wrangler.toml
|
||
├── .github/workflows/
|
||
│ ├── monitor.yml # 每 5 分钟跑一轮探针并提交 status.json
|
||
│ └── pages.yml # 推送 main 时部署 GitHub Pages
|
||
└── docs/
|
||
├── DEPLOYMENT.md # 四种部署方案详细步骤
|
||
├── SECURITY.md # 刷新滥用防护 / SSH 探测边界 / 信息泄露控制
|
||
└── screenshot-*.png # 各视图实测截图
|
||
```
|
||
|
||
> 配置源为什么放在 `public/` 下:面板用相对路径 `fetch('monitors.json')`,探针(Node/Worker)、静态托管(Pages)读取的都是同一份文件,零拷贝、零漂移。配置文件不含任何密钥,可安全公开。
|
||
|
||
## 配置说明(public/monitors.json)
|
||
|
||
```jsonc
|
||
{
|
||
"settings": {
|
||
"title": "Shiroko Monitor", // 面板标题
|
||
"description": "轻量级服务监控面板",
|
||
"view": "table", // 默认视图:table | cards
|
||
"theme": "shiroko", // shiroko(砂狼白子)| default
|
||
"artwork": "", // 立绘图片路径(相对 public/),留空则不显示
|
||
"decoOpacity": 0.78, // 人物/单车装饰的全局透明度(0~1,一个值同时作用于两者)
|
||
"dataFilter": "both", // both | config | uptimerobot(详见「面板形态与数据源」)
|
||
"refreshInterval": 30, // 面板检查数据的最大间隔(秒,最小 5);实际对齐服务端更新节奏
|
||
"dataSource": "auto", // auto | api | static | browser
|
||
"allowRefresh": true, // 是否允许触发强制探测(公网部署建议 false;详见 docs/SECURITY.md)
|
||
"refreshLocalOnly": true, // 仅内网/回环来源可触发强制探测
|
||
"refreshCooldownSec": 5, // 每个来源的触发冷却(秒)
|
||
"hideTargets": false, // true = 面板不渲染任何地址(对外发布用)
|
||
"redactDetails": false, // true = 快照 detail 只保留「正常/异常」
|
||
"uptimeRobot": { // UptimeRobot 只读数据源(Key 建议放 local.monitors.json)
|
||
"enabled": false,
|
||
"apiKey": "",
|
||
"pollIntervalSec": 300,
|
||
"group": "UptimeRobot"
|
||
}
|
||
},
|
||
"monitors": [
|
||
{
|
||
"id": "example-com", // 唯一 ID,状态数据按此关联
|
||
"name": "Example 站点", // 显示名称
|
||
"group": "公共服务", // 分组名(相同名字归为一组)
|
||
"type": "http", // http | tcp | banner
|
||
"url": "https://www.example.com",
|
||
"method": "GET", // 可选,默认 GET
|
||
"expectStatus": [200], // 判定为「在线」的状态码列表
|
||
"interval": 60, // 探测间隔(秒);无人打开面板时的后台节奏
|
||
"timeout": 10, // 超时(秒)
|
||
"probeOnRefresh": false // 可选:false = 该目标不参与「刷新即重新检测」,只按自己的 interval 探测
|
||
},
|
||
{
|
||
"id": "cloudflare-dns-tcp",
|
||
"name": "Cloudflare 443 端口",
|
||
"group": "基础设施",
|
||
"type": "tcp", // 只测端口连通性
|
||
"host": "1.1.1.1",
|
||
"port": 443,
|
||
"interval": 60,
|
||
"timeout": 10
|
||
},
|
||
{
|
||
"id": "ssh-gateway",
|
||
"name": "跳板机 SSH",
|
||
"group": "基础设施",
|
||
"type": "banner", // 被动读取标识串(SSH/SMTP/FTP/POP3/IMAP/HTTP…)
|
||
"host": "10.0.0.5",
|
||
"port": 22,
|
||
"expectBanner": "^SSH-2\\.0-", // 可选:正则策略,不匹配即判离线(可做版本合规检查)
|
||
"bannerFlags": "i", // 可选:正则 flags,默认 i
|
||
"revealBanner": false, // 默认 false:只输出「SSH 响应正常」,不回显版本号
|
||
"interval": 300,
|
||
"timeout": 5
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
添加监控目标 = 在 `monitors` 数组里加一项,保存即可(本地探针自动热重载;静态部署等下一次探针写入)。
|
||
|
||
`interval` 与 `refreshInterval` 的关系:
|
||
|
||
- `interval`(每个目标):**服务端**的探测节奏,与是否有访客无关;也决定 90 天可用率的样本量
|
||
- `refreshInterval`(面板):面板去服务端取数据的最长间隔。由于倒计时对齐服务端更新节奏,页面打开期间**不会**额外触发探测;服务端数据比我配置的节奏更新更快时,面板会跟着服务端走
|
||
- 探测只由服务端驱动 → 打开再多标签页也不会增加对目标的压力(旧版本下每个访客都会触发探测轮次)
|
||
- 需要立刻看一次实时结果时,手动点面板上的「刷新」(服务端限流/关闭策略见 [docs/SECURITY.md](docs/SECURITY.md))
|
||
|
||
> ⚠️ **注意目标限流**:探测本身会消耗目标的配额。例如 GitHub 未认证 API 每小时仅 60 次,按 30s 节奏探测会很快耗尽并返回 403,面板会如实记为离线(那不是面板故障,而是服务真的在拒绝请求)。对这类目标请调大 `interval`,并可设目标级 `probeOnRefresh: false` 让它退出强制检测。仓库默认配置里的 `github-api` 就是这样一个示例目标。
|
||
|
||
## 数据源模式
|
||
|
||
| 模式 | 触发条件 | 数据新鲜度 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `api` | 同源存在 `/api/status`(Node 服务器 / Cloudflare Worker) | 实时 | 首选 |
|
||
| `static` | 存在 `status.json`(GitHub Pages / EdgeOne 静态部署) | 取决于探针写入频率 | 次选 |
|
||
| `browser` | 以上都不可用 | 实时(浏览器直连) | 兜底,限制见下 |
|
||
|
||
`auto` 模式按上表顺序自动降级。可用 `?source=api|static|browser` 强制指定,便于调试。
|
||
|
||
## UptimeRobot 集成
|
||
|
||
### 一、把 UptimeRobot 当数据源(推荐)
|
||
|
||
UptimeRobot 的探测来自其多个节点,适合作为**异地视角**与自建探测并列。配置(**API Key 请放 `local.monitors.json`,不要写进公开配置**):
|
||
|
||
```jsonc
|
||
// local.monitors.json(已在 .gitignore 中)
|
||
{
|
||
"settings": {
|
||
"uptimeRobot": { "enabled": true, "apiKey": "ur123456-xxxxxxxxxxxxxxxxxxxxxxxx" }
|
||
}
|
||
}
|
||
```
|
||
|
||
```jsonc
|
||
// public/monitors.json 的 settings 里保留开关与默认值
|
||
"uptimeRobot": {
|
||
"enabled": false, // 公开配置默认关闭;由私有配置开启
|
||
"apiKey": "", // 留空;也可用环境变量 UPTIMEROBOT_API_KEY(适合 CI/Secrets)
|
||
"pollIntervalSec": 300, // 拉取间隔,别低于 UR 的检测间隔(免费版 5 分钟)
|
||
"group": "UptimeRobot", // 镜像目标在面板中的分组名
|
||
"includeTypes": [] // 可选,按 UR 类型过滤:1=HTTP 2=Keyword 3=Ping 4=Port
|
||
}
|
||
```
|
||
|
||
映射关系(全部来自 UR 官方 API,非我们的二次探测):
|
||
|
||
| 面板字段 | UptimeRobot 来源 |
|
||
| --- | --- |
|
||
| 在线/离线/等待 | `status`:2→在线,8/9→离线,0/1→等待检测 |
|
||
| 响应延迟 | 最新一条 `response_times`(缺失时用 `average_response_time`) |
|
||
| 心率图 | `response_times`(最多 48 个采样点,随 `response_times_average=30` 聚合) |
|
||
| 90 天可用率 | `custom_uptime_ratio`(1/7/30/90 天),逐日色条由本探针同步后自行累积 |
|
||
| 结果/原因 | 故障时取最近一次故障日志的 `reason.code/detail`,如 `403 Forbidden` |
|
||
| 类型徽标 | `UR·HTTP` / `UR·PORT` / `UR·KEYWORD`(与自建探测区分) |
|
||
|
||
行为约定:
|
||
|
||
- **只读**:仅调用 `getMonitors`,不做任何写操作,因此 `ur*` 开头的只读 Key 即可
|
||
- **不参与本地强制探测**:UR 镜像由 UR 自己探测,本探针只拉结果;面板「刷新」不会去跑它们
|
||
- **失败不误判**:Key 无效、限流、网络异常时只记录错误(页脚显示「UptimeRobot 同步异常」并给出原因),目标状态保持上一次的值
|
||
- 速率:一次请求取回全部监控,默认 5 分钟一次(12 次/小时),远低于 UR 的接口限制
|
||
|
||
### 二、对外提供 UptimeRobot 兼容接口
|
||
|
||
`GET|POST /api/v2/getMonitors` 返回与 UptimeRobot v2 同构的响应,便于已有脚本/看板迁移:
|
||
|
||
```jsonc
|
||
{
|
||
"stat": "ok",
|
||
"pagination": { "offset": 0, "limit": 50, "total": 14 },
|
||
"monitors": [{
|
||
"id": 536986782, // 由字符串 id 派生的稳定数字 id
|
||
"friendly_name": "Example 站点",
|
||
"url": "https://www.example.com",
|
||
"type": 1, // 1=HTTP/Keyword 4=Port(UR 编码)
|
||
"status": 2, // 2=在线 9=离线 1=未检测
|
||
"interval": 60,
|
||
"custom_uptime_ratio": "97.436-97.436-97.436-97.436", // 1-7-30-90 天,三位小数
|
||
"average_response_time": 1291,
|
||
"response_times": [{ "datetime": 1791880740, "value": 429 }]
|
||
}]
|
||
}
|
||
```
|
||
|
||
该端点不做鉴权(其内容与公开面板一致);如需鉴权请在其前方加代理。`api_key` 参数会被忽略。
|
||
|
||
## 面板形态与数据源
|
||
|
||
### 视图
|
||
|
||
| 视图 | 形态 | 适合 |
|
||
| --- | --- | --- |
|
||
| `table` 表格 | 一行一服务,列含状态/名称/目标/延迟/结果/最近检测/心率/可用率 | **默认**,目标多时可一屏扫完 |
|
||
| `cards` 卡片 | 一服务一卡 + 心率图 + 90 格可用率条 | 需要更大点击区域或看图细节 |
|
||
|
||
指定方式(优先级从高到低):URL 参数 `?view=table|cards` → 浏览器上次选择(localStorage)→ `settings.view` → 表格。
|
||
|
||
**移动端与窄窗口**:视口窄于 **1024px**(表格含心率图与可用率条,实测最小舒适宽度约 1010px)且用户没有显式选择过视图时,**自动使用卡片**;横竖屏切换时重算,显式选择(`?view=` 或点过切换器)始终优先。顶栏在 ≤820px 改为「标题 / 统计 / 控件」三行,立绘与固定装饰自动撤掉。
|
||
|
||
### 数据源过滤
|
||
|
||
| 值 | 含义 |
|
||
| --- | --- |
|
||
| `both` | 配置文件里的自建目标 + UptimeRobot 镜像目标都展示(默认) |
|
||
| `config` | 只看配置文件里的自建探测目标 |
|
||
| `uptimerobot` | 只看 UptimeRobot 的数据 |
|
||
|
||
配置在 `settings.dataFilter`;也可用 URL 临时覆盖(适合做固定链接,如挂墙看板):`?filter=uptimerobot`。
|
||
过滤只影响**展示与快照输出**,不影响探测——配置文件里的目标始终按各自 `interval` 探测。
|
||
|
||
顶部统计(监控数/在线/离线/平均延迟/可用率)按当前展示的集合实时汇总,不会出现「列表 8 行、统计 14 个」的不一致。
|
||
|
||
### 自动刷新节奏(服务端驱动)
|
||
|
||
```jsonc
|
||
"refreshInterval": 300 // 秒,最小 5;不配则默认 30,「只看 UptimeRobot」时默认 300
|
||
```
|
||
|
||
面板不再从「你打开页面的那一刻」重新计时,而是**对齐服务端的更新节奏**:
|
||
|
||
| 环节 | 由谁驱动 | 说明 |
|
||
| --- | --- | --- |
|
||
| 数据产出 | **服务端** | 自建目标按各自 `interval` 探测;UptimeRobot 按 `pollIntervalSec` 拉取。与是否有访客无关 |
|
||
| 面板检查时刻 | 对齐服务端 | 快照带 `dataUpdatedAt`(数据最后变更时刻)与 `updateIntervalSec`(服务端更新节奏),面板在「上次更新 + 一个周期」时去取一次 |
|
||
| `refreshInterval` | 上限 | 面板检查间隔不会超过它;服务端节奏更快时按服务端节奏走 |
|
||
| 手动「刷新」 | 你 | 唯一会触发**立即重新检测**的动作(服务端可拒绝/限流,见 docs/SECURITY.md)|
|
||
| 自愈 | 面板 | 若服务端数据超过 1.5 个周期没更新(如探针刚重启或被休眠),面板会自动触发一次重新检测 |
|
||
|
||
效果:无论你什么时候打开页面,倒计时都显示「距服务端下一次更新还有多久」——刚更新完打开是 300s,过了 4 分钟打开就只剩 60s。静态快照与浏览器直连模式没有可对齐的服务端节奏,仍按 `refreshInterval` 轮询。
|
||
|
||
## 主题(砂狼白子)
|
||
|
||
面板名称叫 shiroko-monitor,主题自然取了《蔚蓝档案》的**砂狼白子**:她的光环、围巾、狼耳与配色都被做进了界面。人物形象用的是**简约风插画**(扁平配色、无阴影,见下),不是官方立绘。
|
||
|
||
### 主题里的元素
|
||
|
||
| 位置 | 元素 | 取自设定 |
|
||
| --- | --- | --- |
|
||
| 左上 logo / 浏览器图标 | **简约风半身头像**(光环 + 狼耳 + 围巾)+ 青色光环环(呼吸式外扩动画) | 生成插画的半身裁切 |
|
||
| 右下角 | **简约风全身立绘**(透明底,窄身设计:实测 1280 / 1440 / 1920 下都不遮挡表格,页面也无横向滚动);全局半透明(`settings.decoOpacity`,默认 0.78)+ 上下渐隐,融入背景 | 生成插画 |
|
||
| 顶栏底边 | **天蓝色围巾飘带**:波浪形状 + 5 处褶皱纹路(自绘) | 天蓝色围巾是星野送给她的信物 |
|
||
| 页脚下方 | **光环水印**(自绘:倾斜椭圆环 + 四方位带圆头的短杆) | 白子的光环是倾斜的椭圆环,四个方位各有一条带圆头的短杆,整体形似全息瞄准镜准星 |
|
||
| 状态点 | **迷你光环**(外圈 + 中心点,在线时缓慢脉冲外扩) | 光环是基沃托斯学生的标志 |
|
||
| 分组标题 | **青色倒十字发饰**(旋转 45°,自绘) | 她左侧刘海上别的青色十字发夹 |
|
||
| 刷新按钮加载态 | **公路车轮**(轮圈 + 辐条 + 花鼓)旋转 | 她最爱的公路车(Bianchi ARIA 原型) |
|
||
| 左下角 | 公路车插画(简约扁平风,与人物同一套视觉语言;与人物共用同一个全局透明度 `decoOpacity` + 两端渐隐) | 她最爱的公路车(Bianchi ARIA 原型) |
|
||
| 配色 | 天蓝 / 青 + 藏蓝 + 灰白;「正常」色改为青绿(`#12b0a2`) | 阿拜多斯藏蓝校服 + 天蓝围巾 + 灰白发色 |
|
||
|
||
左下公路车、页脚光环、右下立绘构成页脚下方的一条装饰带,三者互不遮挡。
|
||
|
||
### 素材来源
|
||
|
||
| 类别 | 内容 | 来源 |
|
||
| --- | --- | --- |
|
||
| **插画(人物形象 + 座驾)** | `shiroko-figure.webp`(249×560)、`shiroko-icon.webp`(180×180)、`favicon-shiroko.png`(64×64)、`shiroko-bike.webp`(341×200) | **AI 生成**:按白子的设定要素(灰发狼耳 / 倾斜椭圆光环 / 天蓝围巾 / 藏蓝校服 / 公路车)描述生成,再用 Pillow 抠掉白底转为透明。**不是**官方美术素材,可自由替换或商用自行判断 |
|
||
| 自绘装饰(SVG/CSS) | 围巾飘带 `deco-scarf.svg`、光环水印、迷你光环状态点、倒十字图标、车轮加载图标 | 本仓库原创,按公开设定还原 |
|
||
| 设定资料(光环形状、发饰、围巾、配色、车型) | 设计依据 | [萌娘百科 · 砂狼白子](https://mzh.moegirl.org.cn/%E7%A0%82%E7%8B%BC%E7%99%BD%E5%AD%90)、[Blue Archive Wiki](https://bluearchive.fandom.com/zh/wiki/%E7%A0%82%E7%8B%BC%E7%99%BD%E5%AD%90)、[百度百科](https://baike.baidu.com/item/%E7%A0%82%E7%8B%BC%E7%99%BD%E5%AD%90/62839164) |
|
||
| 曾用素材(已移除) | 最早一版用过官方立绘与头像,为改成简约形象已从仓库删除 | [SchaleDB](https://schaledb.com):`images/student/portrait/10010.webp`、`images/student/icon/10010.webp`(Id `10010` = 砂狼白子),版权归 NEXON Games / Yostar;想换回官方图可再从该地址取 |
|
||
|
||
蔚蓝档案 / Blue Archive © NEXON Games · Yostar —— 角色与设定版权归原作者所有,本主题是个人自用面板的风格致敬。
|
||
|
||
### 切换与配置
|
||
|
||
```jsonc
|
||
"theme": "shiroko", // shiroko | default(默认主题);也可用地址栏 ?theme=default 临时覆盖
|
||
"artwork": "assets/shiroko-figure.webp" // 立绘图片路径(相对 public/),留空则不显示
|
||
```
|
||
|
||
优先级:`?theme=` → 浏览器上次选择(localStorage)→ `settings.theme`。顶栏右侧的光环图标按钮可一键切换。切回默认主题后,立绘、光环、斜纹、围巾飘带、公路车全部消失,回到最初的简洁样式。
|
||
|
||
**换成你自己的图**:把图片放进 `public/assets/`,再把 `artwork` 指向它即可(透明底 PNG/WebP 效果最好)。文件不存在时静默不显示,不会出现破图。
|
||
|
||
## 90 天可用率
|
||
|
||
探针每完成一次探测,就把它计入「当日分桶」:`monitors.<id>.daily["YYYY-MM-DD"] = { total, up }`,只保留最近 90 天(超出自动淘汰)。面板据此渲染 90 格色条与百分比。
|
||
|
||
- **数据积累**:从探针首次运行当天开始累积,跑满 90 天后色条填满;没有数据的日期显示灰色(悬停提示「无数据」)
|
||
- **判定口径**:可用率 = 当日在线探测次数 / 当日总探测次数。**提高探测频率会提高统计精度**(60s 间隔约 1440 次/天,GitHub Actions 5 分钟粒度约 288 次/天)
|
||
- **本地时区**:Node 探针按运行机器的本地日期分桶;Cloudflare Worker 无本地时区概念,按 UTC 日期分桶
|
||
- **跨重启保留**:分桶随 `status.json` 持久化,重启/CI 单轮模式都会先恢复再追加,不会断档
|
||
- **浏览器直连模式**:不记录历史,色条显示灰色、「可用率数据积累中」——需要可用率请使用 Node 探针或边缘 Worker
|
||
- **`--demo`** 会生成 90 天演示分桶(含绿/橙/红各档),仅用于界面预览;若不想覆盖真实快照,用 `--out=<path>` 写到别处
|
||
|
||
## 部署方案
|
||
|
||
| 方案 | 架构 | 数据更新 | 成本 | 适合场景 |
|
||
| --- | --- | --- | --- | --- |
|
||
| 本地 Node | 探针 + 面板同机伺服 | 实时(按 interval) | 免费 | 内网自用、开发调试 |
|
||
| GitHub Pages + Actions | 纯静态 + Actions 定时提交 status.json | 每 5 分钟(Actions 下限) | 免费 | 公网演示、个人项目 |
|
||
| Cloudflare Workers | 边缘函数 cron 探针 + KV | 每 1 分钟 | 免费版可用(TCP 需付费版) | 公网生产、多目标 |
|
||
| EdgeOne Pages | 纯静态 + 数据更新同 Pages 路径 | 每 5 分钟 | 免费额度 | 国内访问加速 |
|
||
|
||
四种方案的详细步骤见 [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md)。
|
||
|
||
## 浏览器直连模式的限制(重要)
|
||
|
||
浏览器没有原始 TCP 能力,且受同源策略约束,`browser` 模式下:
|
||
|
||
- HTTP:优先以 `cors` 模式请求,目标响应带 `Access-Control-Allow-Origin` 时可读到真实状态码;否则降级 `no-cors`,**只能判断可达性,读不到状态码**(显示「跨域可达」)
|
||
- TCP:以 HTTP 连接行为近似——快速拒绝判为端口关闭;连接后无响应直到超时判为端口开放(启发式,无法区分「开放但静默」与「被防火墙丢弃」)
|
||
- HTTPS 页面无法探测 HTTP 目标(浏览器混合内容拦截,会判为离线)
|
||
- 结论:**浏览器直连只作兜底**。要准确的状态码与 TCP 探测,请使用 Node 探针或边缘 Worker 提供 `/api/status`
|
||
|
||
## 已实现 vs 路线图
|
||
|
||
### v0.1.0 已实现
|
||
|
||
- [x] HTTP 探测:状态码 / 延迟 / 自定义期望值 / 超时 / 保留 3xx
|
||
- [x] TCP 探测:连通性 / 连接耗时 / 拒绝与超时区分
|
||
- [x] Node 探针:常驻巡检、周期调度、配置热重载、历史心率持久化(重启不断档)、原子写入 status.json
|
||
- [x] Node 探针附带静态服务器与 `/api/status`、`/api/monitors`、`/api/refresh`
|
||
- [x] `--once`(CI 单轮)与 `--demo`(演示数据)模式
|
||
- [x] 面板:状态卡片、心率图、分组页签、统计摘要、相对/绝对时间、自动刷新倒计时、暗色模式
|
||
- [x] 数据源三级自动降级 + `?source=` 强制指定
|
||
- [x] Cloudflare Worker 边缘探针(cron + KV + 静态伺服)
|
||
- [x] GitHub Actions:定时探测 + Pages 部署
|
||
- [x] 四种部署路径文档
|
||
|
||
### v0.2.0 已实现
|
||
|
||
- [x] **90 天可用率**:按天分桶聚合、90 天滚动保留、卡片 90 格分级色条 + 悬停明细、顶部整体可用率(Node 与 Worker 双端一致实现)
|
||
- [x] `--out=<path>` 自定义快照输出路径;`--demo` 覆盖真实快照前给出告警
|
||
- [x] 修复:配置热重载后 `/api/status` 永久冻结在旧数据(闭包捕获了被替换的旧 state 引用,改为持有器对象)
|
||
- [x] 修复:慢目标(如 10s 超时)会被每秒的调度 tick 重复探测,形成探测风暴(改为探测前同步占位 + inFlight 标记)
|
||
- [x] 修复:非法/缺失 `interval` 会算出 `NaN` 导致该目标永久不再被调度(改为回落默认 60s)
|
||
- [x] 修复:刷新倒计时改按截止时间计算,不再受浏览器后台标签页定时器节流影响
|
||
- [x] `scripts/verify.cjs` 端到端回归验证(15 项断言,覆盖上述修复)
|
||
|
||
### v0.2.1 已实现
|
||
|
||
- [x] **刷新即重新检测**:`/api/refresh` 等待本轮探测完成后返回最新快照,面板自动刷新与手动「刷新」按钮都会真正重新探测目标(此前只是重读旧快照,导致「部分卡片停留在几十秒前、手动刷新也没变化」)
|
||
- [x] 服务端强制轮次去重:多标签页/多客户端同时刷新共享同一轮探测,2s 内的重复请求直接复用快照(避免对目标重复施压);强制轮次先等在途探测收尾,保证不跳过任何目标
|
||
- [x] `settings.probeOnRefresh`(默认 `true`):关闭后自动刷新退回只读轮询,手动刷新仍然强制检测
|
||
- [x] 目标级 `probeOnRefresh: false`:单个目标可退出「刷新即检测」(适合有限流的 API),只按自身 `interval` 探测;默认配置新增示例目标说明该用法
|
||
- [x] Cloudflare Worker 的 `/api/refresh` 同步改为「等待完成再返回」+ 同隔离体去重
|
||
|
||
### v0.3.0 已实现
|
||
|
||
- [x] **Banner 探测**(`type: banner`):被动读取 SSH/SMTP/FTP/POP3/IMAP 等标识串,`expectBanner` 正则策略校验(可做版本合规)、`revealBanner` 显式开启才回显;不做认证、不发数据,不触发目标封禁
|
||
- [x] **四种面板形态**:卡片 / 表格 / 大屏(深色 NOC)/ 极简(对外状态页),顶部一键切换 + `?view=` + `settings.view` + localStorage 记忆
|
||
- [x] **刷新接口滥用防护**:内网/回环来源限制(不信任 X-Forwarded-For)、每来源冷却 429 + Retry-After、轮次去重、总开关 `allowRefresh`;Worker 需 `REFRESH_TOKEN` 才开放
|
||
- [x] **信息泄露控制**:`local.monitors.json` 私有配置分层(公开配置可只留 id/name/group)、`hideTargets`、`redactDetails`、TCP 详情不再回显地址、banner 默认不回显版本
|
||
- [x] 私有配置分层 + `--config` / `--local-config`(多实例与测试用)
|
||
- [x] 修复:客户端中断请求(切页/关标签)后向已断开 socket 写响应会抛出未捕获异常,可能终止探针进程
|
||
- [x] 修复:非卡片视图的状态点沿用胶囊色(着色规则作用域写死在 `.card` 上)
|
||
- [x] 修复:首次打开面板时需等强制检测完成才出数据,期间显示空白「等待检测」——改为先用已有快照立即渲染
|
||
- [x] 新增 `docs/SECURITY.md`(滥用防护 / SSH 探测边界 / 信息泄露控制)与 `scripts/verify-security.cjs`、`scripts/verify-views.cjs`
|
||
|
||
### v0.4.0 已实现
|
||
|
||
- [x] **UptimeRobot 数据源(只读)**:把 UR 已有监控作为「异地视角」接入面板,状态/延迟/心率/90 天可用率/故障原因全部映射自 UR 官方字段;镜像目标不参与本地强制探测;同步失败只记录错误并保留上次数据
|
||
- [x] **UptimeRobot 兼容接口**:`/api/v2/getMonitors` 输出与 UR v2 同构(含 `custom_uptime_ratio`、`response_times`、数字 id 与状态码编码)
|
||
- [x] `stats.memory`:探针自报内存占用(RSS/heapUsed),方便观察「监控器自身」的开销
|
||
- [x] 配置分层增强:`--config` / `--local-config` 指定配置文件路径;UR API Key 支持私有配置或 `UPTIMEROBOT_API_KEY` 环境变量
|
||
- [x] 修复:非 http/tcp 类型的目标行渲染为 `undefined:undefined`(改为有 url 用 url、有 host 用 host:port)
|
||
- [x] 修复:热重载会丢弃 UptimeRobot 镜像目标已累积的逐日分桶
|
||
- [x] 修复(实测发现):`custom_down_durations` 不能作为请求参数传给 UR v2(返回 `invalid_parameter`),改为只从响应中读取
|
||
- [x] 新增 `scripts/verify-uptimerobot.cjs`(22 项:映射单测 / 兼容接口 / 失败路径 / 真实 Key 冒烟)
|
||
|
||
### v0.5.0 已实现
|
||
|
||
- [x] **表格设为默认视图**,移除大屏与极简两种形态(面板只保留表格/卡片,切换器更精简)
|
||
- [x] **数据源过滤** `settings.dataFilter`:`both` / `config`(仅配置文件)/ `uptimerobot`(仅 UR),支持 `?filter=` 临时覆盖;服务端快照与面板共用同一口径(私有配置覆盖后也不会错位)
|
||
- [x] **顶部统计按展示集合汇总**:切换过滤后不再出现「列表 8 行、统计 14 个」
|
||
- [x] **自动刷新间隔可配置**并按数据源自适应:`refreshInterval`(秒);只看 UptimeRobot 时默认 300 秒(UR 自身 5 分钟才更新)
|
||
- [x] `/api/refresh?scope=external`:只看 UR 的刷新只同步 UR 数据,不跑本地探测轮次;普通刷新也会顺带同步 UR(最小间隔 60 秒,尊重 UR 接口限流)
|
||
|
||
### v0.6.0 已实现
|
||
|
||
- [x] **刷新节奏改为服务端驱动**:快照新增 `dataUpdatedAt`(数据最后变更时刻)与 `updateIntervalSec`(服务端更新节奏),面板倒计时对齐到服务端下次更新,**不再每次打开页面从整周期重新计时**(旧行为最坏会看到近两倍周期的旧数据;实测:两次打开间隔 25s,倒计时差值 28s)
|
||
- [x] 自动刷新改为**只读**:探测完全由服务端按 `interval` / `pollIntervalSec` 驱动,访客数量不再影响对目标的压力;只有手动点「刷新」才触发立即重新检测
|
||
- [x] 新增自愈:服务端数据超过 1.5 个周期未更新时(探针刚重启、机器休眠过)面板自动触发一次重新检测
|
||
- [x] 移除已无意义的全局 `probeOnRefresh` 开关(目标级 `probeOnRefresh: false` 保留:该目标不参与强制检测);`refreshInterval` 语义澄清为「面板检查数据的最大间隔」
|
||
- [x] 页脚改为展示「数据更新于 … + 下次检查 Ns」,tooltip 内含服务端更新节奏与快照生成时间
|
||
- [x] `scripts/verify.cjs` 适配纯外部数据源部署(自动跳过不适用的探测类断言),并新增「倒计时对齐服务端」断言
|
||
|
||
### v0.9.1 已实现
|
||
|
||
- [x] **「任何情况下都不需要横向滚动」定为硬要求并落地**:表格改为**流式列宽**(`table-layout: fixed` + 百分比列宽),表头允许换行、单元格裁剪,心率图与可用率条随宽度伸缩;从结构上不可能撑出横向滚动
|
||
- [x] 修复两个只有极端内容才暴露的撑破(普通数据下测不出来):
|
||
- **卡片视图**在 <768px 曾溢出最多 495px —— grid 轨道 `minmax(300px, 1fr)` + 网格项默认 `min-width: auto`,被超长 URL 撑到 801px;改为 `minmax(min(300px, 100%), 1fr)` + `.card { min-width: 0 }`
|
||
- **表格**在 <768px 曾溢出 8~42px —— 表头 `white-space: nowrap` 在窄列里溢出;改为换行 + 裁剪
|
||
- [x] 新增 `scripts/verify-layout.cjs`:自带极端配置(40 目标 / 6 分组 / 超长名称与 URL)+ 临时静态服务,扫描 **13 种视口 × 2 视图**,26 项断言零横向滚动
|
||
- [x] 被截断的名称/目标补 `title`,鼠标悬停可看完整值
|
||
|
||
### v0.9.0 已实现
|
||
|
||
**修复你反馈的两个问题**
|
||
|
||
- [x] **装饰遮罩「看不出效果」**:人物与单车改为**统一全局半透明**(`settings.decoOpacity`,默认 0.78,一个值同时作用于两者)+ 各自的边缘渐隐;此前立绘是 0.92(几乎无感)、单车 0.80,两者还不一致
|
||
- [x] **切换视图时人物比例变化**:删掉了「卡片视图把立绘缩到 300px」的规则(那是上一版为躲让卡片加的),现在两种视图尺寸完全一致
|
||
- [x] **保留原始素材**:AI 生成的白底原图归档到 `assets-src/`,处理流程写成可复现脚本 `scripts/prepare-artwork.py`(边界洪泛 + 封闭区域补抠 + 裁边缩放 + 补白)
|
||
|
||
**全局审阅发现并修复的问题**
|
||
|
||
- [x] 🔴 **无障碍对比度不达标(两套主题都中招)**:状态色直接当文字色用时远低于 WCAG AA 4.5:1(白子主题「在线」2.71:1、「等待」2.56:1;默认主题 3.30:1 / 3.19:1)。改为**双色体系**:填充色(圆点、心率条、边框)保持鲜亮并保证 ≥3:1,文字色用同色系加深值并保证 ≥4.5:1;暗色模式同步。新增 8 条对比度断言(逐层合成实际背景色,正确处理 `color-mix` 半透明底)
|
||
- [x] 🔴 **暗色模式下主题是坏的**:顶栏/卡片/表头/分组行是硬编码白色渐变,配上深色页面就是「白顶栏 + 深底」;改为随明暗模式切换的变量(新增 `docs/screenshot-dark.png`)
|
||
- [x] 🟠 **平板竖屏(768px)表格要内部横滚 242px**:自动切卡片的阈值从 700px 提到 **1024px**(= 表格实测最小舒适宽度),显式选择视图仍然优先
|
||
- [x] 🟠 **Cloudflare Worker 快照缺字段**:补 `dataUpdatedAt` / `updateIntervalSec` / `dataFilter`,边缘部署与本地探针口径一致(否则倒计时不会对齐服务端)
|
||
- [x] 🟡 清理失效 CSS(`.logo .halo`,随内联光环 SVG 移除后遗留)
|
||
|
||
**测试脚本自身修掉的两个 bug**(都会导致误报)
|
||
|
||
- 对比度取样把 `color(srgb r g b / a)` 的 0~1 分量当成 0~255、把半透明底色当不透明 → 改为逐层合成实际背景色
|
||
- 「立绘不影响阅读」把**渐变背景**(卡片用 `background-image`)误判为透明 → 判定补上背景图检查
|
||
|
||
### v0.8.3 已实现
|
||
|
||
- [x] **修复抠图漏区**:此前只用「边界洪泛」抠底,光环**环内**、单车**车架三角区与轮圈内扇形**这些被围起来的封闭白色区域没被处理,会留成白块。改为再补一次「封闭白色区域」按面积清理(人物/单车/图标三张图都处理了;脸部、袜子等服装白已确认保留)
|
||
- [x] **人物与单车加半透明 + 渐隐遮罩**:立绘 `opacity .92` + 上下渐隐,单车 `opacity .8` + 两端渐隐 + 轻微降饱和,不再像贴上去的贴纸
|
||
|
||
### v0.8.2 已实现
|
||
|
||
- [x] 左下角公路车换成**简约扁平风插画**(AI 生成 + 抠底,与人物同一套视觉语言),替换掉此前自绘的线稿 SVG;页脚下方装饰带(公路车 / 光环 / 人物)风格统一
|
||
|
||
### v0.8.1 已实现
|
||
|
||
- [x] **修复移动端顶栏塌陷**:窄屏(≤820px)改为「标题 / 统计 / 控件」三行布局,统计均分视口宽度,页脚改纵向堆叠 —— 此前统计数字会挤成竖排并压住标题
|
||
- [x] **窄屏默认卡片视图**(≤700px):表格在手机上必须横向拖动,改由卡片呈现;横竖屏切换时重算,用户显式选过视图则尊重其选择
|
||
- [x] 窄屏与横屏手机自动撤掉立绘、公路车、光环水印等固定装饰,避免压住内容或溢出
|
||
- [x] `verify-views` 新增移动端专项断言 7 项(默认卡片 / 无横向溢出 / 顶栏三行 / 统计铺满 / 装饰隐藏 / 页脚不裁切 / 无 JS 错误)
|
||
|
||
### v0.8.0 已实现
|
||
|
||
- [x] **形象换成简约风插画**(AI 生成 + 抠底,非官方美术素材):右下角全身立绘、logo 与 favicon 用同款半身像;官方立绘/头像已从仓库移除
|
||
- [x] **修复:桌面端表格需要横向拖动** —— 上一版为避让立绘给内容区加了 240px 右内边距,而 `.grid` 是 `max-width: 1200px`,内边距在 1200 内部吃掉宽度,导致 1200px 以上的屏幕也必然溢出。改为「立绘收窄 + 置于内容之下」,实测 1280 / 1440 / 1920 三种宽度下页面与表格均 **0 溢出、0 重叠**
|
||
- [x] **修复:立绘遮挡光环水印** —— 光环水印移到页脚下方空带,与左下公路车、右下立绘形成一条装饰带,互不遮挡
|
||
|
||
### v0.7.0 已实现
|
||
|
||
- [x] **砂狼白子主题**(默认启用):官方立绘(右下角,宽屏自动为它让位)+ 头像 logo/favicon(光环环呼吸动画)+ 天蓝围巾飘带顶栏 + 倒十字发饰分组标识 + 公路车轮加载态 + 按官方造型还原的倾斜椭圆光环水印;配套青绿主色调
|
||
- [x] 主题切换:`settings.theme` / `?theme=` / 顶栏光环按钮(localStorage 记忆),默认主题完整保留
|
||
- [x] `settings.artwork` 立绘位,默认指向内置立绘;未配置或文件缺失时静默不显示
|
||
- [x] 修复:`dataFilter=uptimerobot`(只展示外部数据源)时「平均延迟」恒为「–」——原规则一律排除 UR 延迟,改为「混合来源时排除、纯外部来源时以其为唯一口径」,服务端与面板同步调整
|
||
|
||
### 路线图(后续迭代)
|
||
|
||
- [ ] 通知渠道:Webhook / Server 酱 / Telegram / Bark / 邮件
|
||
- [ ] 故障事件记录:连续失败次数、事件时间线、状态变更历史
|
||
- [ ] 状态徽章:SVG badge(shields.io 风格)
|
||
- [ ] 更多探测类型:证书到期天数、响应体关键字、DNS 解析、ICMP(边缘端)、HTTP 重定向链
|
||
- [ ] 主动协议探测(Redis `PING`、MySQL 握手等):需先设计「发送探测字节」的安全边界与白名单,避免退化成通用交互工具
|
||
- [ ] 只读分享令牌:给 `hideTargets` 之外的场景做「带令牌才能看到真实名称」的分级
|
||
- [ ] 多区域探针:多 Worker 部署 + 结果合并,取容错视图
|
||
- [ ] 配置 Web UI(可选加密编辑),替代手改 JSON
|
||
- [ ] 面板:更多形态(如时间线视图、地图视图)、明暗主题手动切换、可用率区间可配置(7/30/90 天)
|
||
- [ ] 状态页 JSON API 的 CORS 开放与缓存策略细化
|
||
|
||
## 开发
|
||
|
||
```bash
|
||
# 本地起服务(含探针)
|
||
node prober/node/index.js
|
||
|
||
# 只验证探针逻辑
|
||
node prober/node/index.js --once
|
||
|
||
# UI 自动化实测(需 playwright,仅开发验证用,驱动系统 Chrome)
|
||
NODE_PATH=<playwright 的 node_modules> node scripts/verify.cjs # 热重载 / 数据一致性 / 刷新语义 / 面板(21 项)
|
||
NODE_PATH=<playwright 的 node_modules> node scripts/verify-views.cjs # 视图与数据源过滤(10 项)
|
||
node scripts/verify-security.cjs # banner 探测 / 脱敏 / 私有分层 / 刷新限流(20 项)
|
||
UPTIMEROBOT_API_KEY=ur... node scripts/verify-uptimerobot.cjs # UR 映射/兼容接口/失败路径/冒烟(22 项)
|
||
```
|
||
|
||
`verify-security.cjs` 会临时起一个假 SSH 服务与静默端口,验证 banner 探测的在线/不匹配/超时三种判定、默认不回显版本、脱敏与私有配置分层,以及刷新接口的 429/403 行为。`verify-uptimerobot.cjs` 用合成 payload 做无网映射单测,真实 Key 冒烟为可选(未设置环境变量则跳过)。
|
||
|
||
代码约定:探针与面板通过 `status.json` / `/api/status` 的同一份 JSON 契约协作;新增探测类型时只需在 `prober/node/lib/` 与 `edge/cloudflare/worker.js` 各实现一个 `probeXxx(monitor)`,返回 `{ status, latency, code, detail }` 即可被面板直接渲染。
|
||
|
||
## 界面截图
|
||
|
||
| 砂狼白子主题(默认,表格视图) | 默认主题 |
|
||
| --- | --- |
|
||
|  |  |
|
||
|
||
| 深色模式(白子主题) | 卡片视图(白子主题) |
|
||
| --- | --- |
|
||
|  |  |
|
||
|
||
移动端(390×844,自动切卡片 + 顶栏三行):`docs/screenshot-mobile.png`
|
||
|
||
UptimeRobot 数据源(`?filter=uptimerobot`,截图中含真实监控名与域名,公开发布前可自行删除):`docs/screenshot-uptimerobot.png`;演示数据 90 天满档:`docs/screenshot-demo.png`
|
||
|
||
## 致谢与定位
|
||
|
||
交互设计参考 Uptime Kuma(心跳图、90 天可用率条、分组卡片、汇总统计),实现为自研轻量版:不追求 Kuma 的通知/多用户/数据库体系,只保留「配置文件 → 探针 → 状态面板」的最小闭环,并对静态/边缘部署友好。
|