nguyenminhduc9988/situroom

GitHub: nguyenminhduc9988/situroom

一个无需服务器和 API 密钥的纯静态全球态势监测仪表盘,在单一页面上实时聚合地震、灾害、冲突新闻与市场行情数据。

Stars: 0 | Forks: 0

# SITUROOM **零后端的全球态势室 —— 在一个静态页面中实时呈现地震、冲突、灾害与市场动态。无需服务器。无需 API 密钥。无需付费墙。** [![License: MIT](https://img.shields.io/badge/license-MIT-10b981.svg)](LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-22d3ee.svg)](#contributing) [![Dependencies](https://img.shields.io/badge/npm%20dependencies-zero-0a0a0f.svg)](package.json) [![Build](https://img.shields.io/badge/build%20step-none-64748b.svg)](#architecture) ![SITUROOM 仪表盘 —— 带有实时地震、事件、紧张局势热力图、头条新闻和市场的暗黑行动风格世界地图](https://static.pigsec.cn/wp-content/uploads/repos/cas/25/252c30d649fb7f2b9b9d97628d1178af4fc3184cfde377a3b92b1a2dfe9ba4ba.png) **在线演示:** https://nguyenminhduc9988.github.io/situroom/ ## 为什么 大多数“世界监测”情报仪表盘都是托管型产品:由庞大的服务器集群渲染画面,评分机制是不透明的黑盒,而真正有用的部分(API、agent 访问权限)则被付费密钥挡在门外。SITUROOM 则反其道而行之 —— 一个态势仪表盘所需的一切都可以从免费、无需密钥、对 CORS 友好的公共 API 获取,因此整个产品完全可以是**一个静态文件夹**。 | | SITUROOM | 典型的托管型情报仪表盘 | |---|---|---| | **License** | MIT,无商业版层级 | AGPL + 商业授权推销 | | **Backend** | 无 —— 纯静态文件 | 大量的 edge functions + Redis + relays | | **API / agent 访问权限** | 免费的本地 MCP server,内置 | 需付费 API 密钥 | | **评分** | 有文档记录的客户端公式 ([js/score.js](js/score.js)) —— 可在 devtools 中重新计算 | 不透明的服务端计算 | | **离线** | PWA + 内置数据快照兜底 | 仅限在线 | | **配置** | 打开一个 URL,或运行 `python3 -m http.server` | 云端部署 | 目前提供六个免费数据源,[欢迎提交 PR 添加更多](#contributing)。 ## 快速开始 **1. 直接打开** —— https://nguyenminhduc9988.github.io/situroom/ **2. 本地运行**(任何静态服务器均可;无需安装,无需构建): ``` git clone https://github.com/nguyenminhduc9988/situroom cd situroom python3 -m http.server 8080 # 打开 http://localhost:8080 ``` **3. 自行托管** —— fork 该仓库,启用 GitHub Pages(从 `main` 分支的根目录部署)。完成:它只是静态文件。 ## 功能 - **Canvas 世界地图** —— 内置 d3-geo 投影、经纬网、国家悬停、震级缩放的地震标记、按类别着色的自然事件、紧张局势热力斑块。图层可切换,脉冲动画(在 `prefers-reduced-motion` 下禁用)。 - **紧张局势指数** —— 基于当前新闻窗口的透明国家级评分,前 10 名的柱状图按绿→黄→红颜色显示。公式在[下方](#the-tension-index-formula)和 UI 中("formula?" 按钮)均有文档说明。 ![Tension index panel — ranked country bars](https://static.pigsec.cn/wp-content/uploads/repos/cas/9a/9a7fe8b6ab25867c212947a2eae673744f2e0d64feb54c14d450d0cff84313b5.png) - **新闻头条** —— 来自 GDELT 的冲突类世界新闻(默认为英语来源,设置中可切换至全语言)。 - **地震 / 事件 / 科技面板** —— USGS 地震、NASA EONET 自然事件、Hacker News 首页。 - **市场行情** —— BTC/ETH/SOL 及其 24 小时涨跌幅,美元外汇参考汇率。 - **各数据源的状态标签** —— LIVE / STALE(已缓存)/ SNAPSHOT / ERROR,让你随时了解当前查看的数据状态。 - **关注列表** —— 将你关注的国家置顶到紧张局势排行榜上。 - **响应式** —— 面板在窄视口下自动堆叠;六个状态标签会折叠成一个汇总标签。 手机尺寸视口下的 SITUROOM ## 数据源 全部免费、无需密钥,直接从你的浏览器获取(对 CORS 友好)。鸣谢与感谢: | 来源 | 数据 | 刷新频率 | |---|---|---| | [USGS Earthquake Hazards Program](https://earthquake.usgs.gov/) | 过去 24 小时的地震 | 5 分钟 | | [NASA EONET](https://eonet.gsfc.nasa.gov/) | 公开的自然事件(野火、风暴、火山等) | 10 分钟 | | [GDELT Project](https://www.gdeltproject.org/) DOC 2.0 | 冲突/军事/制裁/抗议相关的新闻头条,约 6 小时窗口 | 15 分钟 | | [CoinGecko](https://www.coingecko.com/) | BTC / ETH / SOL 现价及 24 小时涨跌幅 | 2 分钟 | | [Frankfurter](https://frankfurter.dev/) | USD→EUR/JPY/GBP/CNY 参考汇率 | 60 分钟 | | [HN Algolia](https://hn.algolia.com/api) | Hacker News 首页 | 10 分钟 | 每个数据源的降级机制都是独立的:实时获取 → 来自 localStorage 的最后一次有效响应(**STALE**)→ [`data/snapshot.json`](data/snapshot.json) 中内置的快照(**SNAPSHOT**)→ **ERROR** 标签。仪表盘永远不会显示为空白。 ## 紧张局势指数公式 没有黑盒 —— 整个计算过程都在你的浏览器中基于原始的 GDELT 文章列表执行,位于 [`js/score.js`](js/score.js): - **volume(C)** —— 在国家 C 发布或标题中提及 C(或常见别名)的文章数量 - **severity(C)** —— 标题关键词权重的平均值:`3` 战争/打击/攻击/导弹等,`2` 制裁/军事/核武等,`1` 抗议/动荡/冲突等,下限为 `0.5` - **score(C)** = `100 × norm(0.6·log1p(volume) + 0.4·severity)` —— 当前热度最高的国家得分为 100,其他所有国家均为相对得分 诚信说明:GDELT 的文章列表 API 并未公开其单篇文章的 tone 字段,因此严重度采用的是一个有文档记录的关键词代理指标 —— 虽然比 GDELT 的 tone 更粗略,但完全可审计,这正是我们的初衷。完整的国家/别名专有名词表和关键词对照表都是位于文件顶部的纯数据;[`test/score.test.js`](test/score.test.js) 中的单元测试锁定了其行为。 ## AI 态势简报(可选,自带密钥) 默认关闭且完全不强制使用。如果你将设置(齿轮图标)指向任何兼容 OpenAI 的 endpoint —— 包括运行在 `http://localhost:11434/v1` 的本地 Ollama —— 就会出现一个 **AI SITREP** 按钮,可将当前的新闻头条和紧张局势排行榜总结为包含 5 个要点的简报。你的 endpoint、密钥和模型**仅保存在你浏览器的 localStorage 中**,除了发往你配置的 endpoint 外,不会发送到任何其他地方。 ![Settings dialog — BYOK endpoint, watchlist, language toggle](https://static.pigsec.cn/wp-content/uploads/repos/cas/00/006bcc5586086db3c4eeb225f78fa8bf1c885d871a207d67d7c56e75500e1f68.png) ## MCP server(agent 免费获取数据订阅) [`mcp/situroom_mcp.py`](mcp/situroom_mcp.py) 是一个零依赖的 Python 3.10+ stdio MCP server,将相同的数据源作为工具公开:`get_quakes`、`get_events`、`get_headlines`、`get_tension`、`get_markets` —— 全部标准化为与 Web 应用相同的结构,紧张局势公式也如实从 `js/score.js` 移植了过来。针对 Claude Desktop/Code 和 Cursor 的配置代码片段见 [`mcp/README.md`](mcp/README.md)。 ``` claude mcp add situroom -- python3 /path/to/situroom/mcp/situroom_mcp.py ``` ## 架构 原生的 ES modules。没有框架,没有构建步骤,没有 npm install。唯一的第三方代码已经内置并提交:位于 [`vendor/`](vendor/) 的 d3 v7 + topojson-client(外加 world-atlas 110m 拓扑数据),因此该应用在完全无法访问任何 CDN 的情况下也能运行。 ``` index.html ├── css/app.css dark ops theme (system fonts only) ├── js/app.js boot, source registry, 60s scheduler, panels │ ├── js/map.js canvas map (offscreen-cached base + marker layer) │ ├── js/score.js tension index (pure, documented, tested) │ ├── js/store.js localStorage cache + settings │ ├── js/brief.js optional BYOK sitrep │ └── js/sources/*.js one module per feed: fetchX() + pure normalizeX() ├── sw.js PWA: precached shell, network-first API fallback └── data/snapshot.json committed real capture — the floor of the chain: live fetch ──fail──▶ localStorage last-good ──miss──▶ committed snapshot ──miss──▶ ERROR chip (LIVE) (STALE) (SNAPSHOT) ``` 运行测试(仅限纯函数,完全离线): ``` node --test test/*.test.js # or: npm test — 44 tests, zero dependencies ``` ## License [MIT](LICENSE) © 2026 Minh-Duc Nguyen 由 [BigWinner.work](https://bigwinner.work) 开发 —— AI 工具与咨询
标签:HTTP/HTTPS抓包, MCP, PWA, 态势感知, 自定义脚本, 静态网站