# 62 · 插件目录:缓存状态可见化 + 「重新拉取目录」按钮 - 日期:2026-09-12 - 状态:✅ **已实施并验证**(服务器已生效;代码仓库已提交 `0e141a4`) - 触发:用户「**拉取的官方目录可以缓存,不用每次都拉取,增加一个主动刷新开关**」 - 关联:档案 29(官方目录接入)、31(插件管理页双 Tab)、61(同页列表高度) --- ## 一、取证结论:**功能早已存在,只是完全看不出来** | 能力 | 改前现状(`src/web/routes/whitelist.ts`)| |---|---| | **磁盘缓存** | `/whitelist-cache/index.json` | | **TTL** | **6 小时**(`CACHE_TTL`;TTL 内 `getIndex()` 直接返回缓存,**不联网**)| | **主动刷新端点** | `POST /api/plugins/whitelist/refresh`(内部 `getIndex(true)` 强制拉取)| | **降级** | 拉取失败 → 沿用旧缓存并标 `stale: true` | | **返回字段** | `GET /api/plugins/whitelist` **已带 `fetchedAt` + `stale`** | ⇒ **"每次都拉取"是错觉**。真实原因是前端有三处**误导**: 1. 加载提示写「**拉取官方目录中…(首次约数秒)**」→ 让人以为每次打开都在下载 2. `wlInfo` **只显示 `stale`、不显示 `fetchedAt`** → 看不出缓存是否生效、也不知道多久没更新 3. 按钮叫「**刷新清单**」→ 看不出它就是"**绕过缓存从官方站重拉**" ## 二、改动(**仅前端 4 处**,`git diff --numstat` = **13 增 4 删**;**后端零改动**) | 位置 | 改动 | |---|---| | `portal.html` L402 | 按钮「刷新清单」→ **「重新拉取目录」**,并加 `title`:「绕过本地缓存,从官方站重新下载插件目录(约数秒;平时打开本页不会下载,直接读本地缓存)」| | L458 | 新增 `relTime(ts)` 工具函数(刚刚 / X 分钟前 / X 小时前 / X 天前)| | L458 | 加载提示 → **「加载目录中…(首次会从官方站下载一次,之后读本地缓存)」** | | L477 | `wlInfo` 增显 **「目录缓存更新于 X 前(6 小时内直接复用,不联网)」** —— 消费后端**已经返回**的 `fetchedAt` | | L509 | 按钮流程提示明确化:「✓ 目录已重新拉取(缓存已更新)」/「重新拉取失败(网络或官方站不可达)」| **设计取向**:不新增后端参数、不改动缓存策略(现状已合理),只把**既有事实暴露给用户**。这是最小改动的正解 —— 用户要的"缓存 + 主动刷新"**本来就工作**,缺的只是可见性。 ## 三、验证 - `git diff --numstat` = **13 增 4 删**(**无整文件 diff**) - 部署:`scp` + 服务器 `sed -i 's/\r$//'` 转回 LF(保持与仓库 blob 一致) - `curl https://alotbuy.com/portal.html` 命中新文案 ✓(`重新拉取目录` 2 处、`function relTime` 1 处) - **`portal.html` 是静态文件 → 改完立即生效,无需重启服务**(不涉及 R8) ## 四、回滚 ```bash git -C D:/github/dsh_shenxian checkout HEAD~1 -- web/portal.html # 或 HEAD~2(视改动批) scp web/portal.html bt-server:/opt/dshs/web/portal.html ``` 静态文件,无需重启;浏览器需硬刷新。 ## 五、附:若还需要「自动更新开关」(**需后端,本次未做**) 当前语义 = 「**6 小时内自动复用缓存 + 按钮可随时强制重拉**」。 若你要的是一个 **「自动更新:开 / 关」的 toggle** —— 关掉后**连 TTL 到期也不联网**、只能手动点按钮 —— 则需给 `GET /api/plugins/whitelist` 增加一个 `cacheOnly=1` 参数(**只读缓存、不触发拉取**,缓存缺失时返回明确错误而非阻塞拉取),前端开关用 `localStorage` 记忆。 **这属于后端改动 → 需 `npm run build` + 重启平台 → 会中断在线用户**(按 R8 须先知会)。**本次未做,等确认。**