From 00f8bc674a66741592ccc3a98ead1199337295e2 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Mon, 17 Aug 2026 18:23:04 +0800 Subject: [PATCH] feat: webapp/card delivery server example --- README.md | 67 +++++++++++++++++++++++++++++++++++++++- apps/demo/index.html | 57 ++++++++++++++++++++++++++++++++++ cards/catalog.json | 10 ++++++ cards/weather/card.html | 24 ++++++++++++++ icons/cloudmusic.svg | 6 ++++ icons/demo.svg | 4 +++ manifest.json | 22 +++++++++++++ offlines/demo.zip | Bin 0 -> 1166 bytes 8 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 apps/demo/index.html create mode 100644 cards/catalog.json create mode 100644 cards/weather/card.html create mode 100644 icons/cloudmusic.svg create mode 100644 icons/demo.svg create mode 100644 manifest.json create mode 100644 offlines/demo.zip diff --git a/README.md b/README.md index 673658e..7a9b16d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,67 @@ -# Hearth_Server +# Hearth Server 示例 +Hearth 启动器的 webAPP / 卡片下发服务端示例。**本质是纯静态文件**,无需后端逻辑。 + +## 目录结构 + +``` +Hearth_Server/ +├── manifest.json # webAPP 清单(客户端启动时拉取) +├── apps//index.html # 各 webAPP 入口页 +├── icons/.svg # 图标 +├── offlines/.zip # 可选离线包(整站资源打成 zip) +└── cards/ + ├── catalog.json # 首页卡片目录 + └── /card.html # 单个卡片 +``` + +## 快速启动(测试用) + +```bash +cd ~/Project/Hearth_Server +python3 -m http.server 8080 +``` + +然后在 Hearth 设置页 →「webAPP 服务器地址」填 `http://<本机IP>:8080`。 + +## 正式部署 + +- nginx:`location / { root /path/to/Hearth_Server; }` +- 或传云对象存储(OSS/COS)+ CDN,整个目录原样上传 + +## 更新流程 + +1. 改 webAPP 资源(`apps/` 下的文件) +2. 改 `manifest.json` 的 `version`(+1) +3. 客户端「检查更新」或重启即可拉取 + +## manifest.json 字段 + +| 字段 | 说明 | +|---|---| +| `version` | 清单版本号,客户端据此判断更新 | +| `apps[].id` | 唯一 id | +| `apps[].name` | 显示名 | +| `apps[].icon` | 图标地址(建议 SVG) | +| `apps[].url` | 入口页地址(相对地址即可) | +| `apps[].offline.package` | 可选离线包 zip 路径 | +| `apps[].offline.version` | 离线包版本 | + +## 离线包 + +- 把某个 webAPP 的**全部资源**(`apps//` 下所有文件,含子目录)打成 zip,放 `offlines/.zip` +- zip 内需**包含 index.html**(作为离线入口) +- 生成示例:`cd apps/demo && zip -r ../../offlines/demo.zip .` + +## 离线包使用与版本管理 + +- **下载时机**:客户端拉取清单时**只同步列表,不自动下载程序包**;只有首次点开某 webAPP 时才下载(显示进度覆盖层)。 +- **本地优先**:下载后解压到本地目录,之后点开直接本地加载;**服务端删除该离线包不影响本地运行**。 +- **手动导入**:长按 webAPP 卡片 →「导入离线包」→ 选择本地 zip(适用于无服务器或离线分发场景)。 +- **版本更新**: + - `manifest.json` 里把 `offline.version` 升版本后,客户端列表该 webAPP 显示「**可更新**」标签(**不强制**,点开仍运行本地旧版)。 + - 长按卡片弹出菜单: + - `更新离线包`(删除本地并重新下载,显示版本 x → y) + - `删除本地包` + - `属性`(查看本地 / 云端版本号) + - 云端版本号 ≤ 本地版本号时不提示更新。 diff --git a/apps/demo/index.html b/apps/demo/index.html new file mode 100644 index 0000000..9e11985 --- /dev/null +++ b/apps/demo/index.html @@ -0,0 +1,57 @@ + + + + + +示例应用 + + + +
🎨
+

示例应用

+
+
来源远程服务器
+
当前时间--:--:--
+
+

这是 Hearth 服务端的示例 webapp
用于演示远程下发 / 加载进度 / 离线包

+ + + diff --git a/cards/catalog.json b/cards/catalog.json new file mode 100644 index 0000000..7a1a415 --- /dev/null +++ b/cards/catalog.json @@ -0,0 +1,10 @@ +{ + "cards": [ + { + "id": "weather", + "name": "天气", + "priority": 2, + "entry": "cards/weather/card.html" + } + ] +} diff --git a/cards/weather/card.html b/cards/weather/card.html new file mode 100644 index 0000000..1bd1c13 --- /dev/null +++ b/cards/weather/card.html @@ -0,0 +1,24 @@ + + + + + + + +
+
+
+
26°
+
+
+
+ + diff --git a/icons/cloudmusic.svg b/icons/cloudmusic.svg new file mode 100644 index 0000000..5e9fb37 --- /dev/null +++ b/icons/cloudmusic.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/icons/demo.svg b/icons/demo.svg new file mode 100644 index 0000000..5eaeb7b --- /dev/null +++ b/icons/demo.svg @@ -0,0 +1,4 @@ + + + H + diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..ce989c0 --- /dev/null +++ b/manifest.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "updatedAt": 1723785600, + "apps": [ + { + "id": "demo", + "name": "示例应用", + "icon": "icons/demo.svg", + "url": "apps/demo/index.html", + "offline": { + "package": "offlines/demo.zip", + "version": "1.0.0" + } + }, + { + "id": "cloudmusic", + "name": "网易云音乐", + "icon": "icons/cloudmusic.svg", + "url": "https://music.163.com/st/webplayer" + } + ] +} diff --git a/offlines/demo.zip b/offlines/demo.zip new file mode 100644 index 0000000000000000000000000000000000000000..015ae2051c53fbe83e41399f42845364b51cd6fc GIT binary patch literal 1166 zcmWIWW@Zs#U|`^2kj@Z{O%}Y6{e+o;!GoQFfr~+gAu}%}wL&kWBsV8Cgp+}}b!t-< z2$xoHGcdBe04f9%y`ks(Z@Y->`@X(HVxfiVWQ)jI@6`PGa-z4kPxI1b?-Q=h;eXw; z_M^(pEsxyz-)>_);+4CQW5R-{PG^0Ng$FkMKcg0z_lI-O$9|RB>ja8K&exp({O8{H zecyBT7r$M6w|f4ay?l*QEqA@Q?Q`^Ky>IxAJ>`4fLPNLMJ-jm(Jzxn@^C|7=e}7lu zwi_e2Rf25tk((BMONNNwkJzqwylZhn3`L*tIvp4YJlUuUHiEHaqXadqWBqnrb*oD$!euQu&U?QP;I zs}yP%Y5w4}ZN6ibYmDB^#T6}*i?%;>NHLQtiWlfBRLgKknt6t2KA-T>y__e1+U0-A z?9tCX_LF;Bjj7!U1z*3Zk1x)dyTwL#$1MkA5y$l1bAml%?T!dYg*_~p+cSaNP4(l~ zV2QTK`@0?)?Qc@4JS%(JOWb;0>Qwzl4-U!vx8A>HRz&HwCf&K0HZjb5F8Y(TROIZf z=FE4J2Iq`(qQcasta4sDySQ-Qi5K~ko2FbBU0$`@&D&2k?9X1atg`t}4ulmSoii=R z;ci9`7h8(tt6%=VYO|t5YeUzjRYs~y_8Ly+J$G-BdZ*^M$oVS`laqA!ye*3gygQ(yi{^gq=uTSrvcW(awZ{I)1 zUyo%jH{4}V^g+@o>Sg}rzgdFfa;87o+P)V3d&GO^$h#oMl!v-?m79M&``p7XvDuE# zc(?xU6Q^H(x%ub3^OlsGbNoyTw`_gk?ux(1ld6oWKV4XN zwCa@Aq~l)u?@D)-urxk8H!t#>bdrlIhlm$Di}YdBRWoLO-?;5ahyMAQO#F>0SsJWg zrns;wg}54i6G=-j(+b$+l`7(F$Dx#N;czshcG0H??i82|tP literal 0 HcmV?d00001