2047 lines
146 KiB
Markdown
2047 lines
146 KiB
Markdown
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
||||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、追加(2026-09-13 19:3x–19:5x):**从「只读」升级为「就地全量管理」**(用户要求)
|
|||
|
|
|
|||
|
|
### 10.1 用户的三条要求
|
|||
|
|
1. **dsh 设置里的「用户管理」改名为「用户设置」**,且**去掉里面的「打开管理平台」入口**
|
|||
|
|
2. **「平台管理」不要再跳新页面** —— **把所有管理项都放进「系统管理」,每项点开是弹窗**
|
|||
|
|
|
|||
|
|
### 10.2 落地
|
|||
|
|
|
|||
|
|
| 项 | 改动 | 产物 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 「用户管理」→**「用户设置」** | `@dsh-local/portal-entry`:section `id: user-management → user-settings`、`label` 改名、**order 102 → 103**(让位给平台管理);**删除「打开管理台」按钮**;内容改为「账号:<用户名> 角色:<管理员/普通用户>」+ 退出登录 | **`portal-entry-0.5.2.tgz`**(已铺发到 admin+guest) |
|
|||
|
|
| 「平台管理」→**「系统管理」+ 管理项 + 弹窗** | `@dsh-local/business-plugins`:**删掉 `window.open(portal.html)` 跳转按钮**;分区改为「**管理项列表**」,5 项(用户管理 / 候选池 / 运行时 / 存储 / 当前实例)**每项点开是原生弹窗**;**用户管理弹窗内可直接 通过 / 禁用 / 启用 / 删除**(调平台既有 admin API,不跳门户) | **`business-plugins-0.3.0.tgz`**(已铺发) |
|
|||
|
|
|
|||
|
|
### 10.3 验收(`npm run verify` 内)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ admin:含分区标题「系统管理」 ✓ admin:5 个管理项齐全
|
|||
|
|
✓ admin:不再是只读(提示改为弹窗内管理)
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何管理项
|
|||
|
|
结论:全绿 ✅
|
|||
|
|
```
|
|||
|
|
另:**磁盘复核** —— 两 profile 的 `business-plugins` 均 **0.3.0**、含「系统管理」、**`window.open` 计数 = 0**(跳新页彻底移除)✓
|
|||
|
|
|
|||
|
|
### 10.4 尚未做的(下一批)
|
|||
|
|
|
|||
|
|
- 弹窗内**目前只有「用户管理」是可写**的;**候选池 / 运行时 / 存储 / 实例** 三项为**只读列表**(写操作待补)。
|
|||
|
|
- **portal-entry 源码不在仓库**(只有铺发脚本 + artifacts 里的 tgz)⇒ 本次是**在产物上改**的。**建议**:把 `portal-entry`/`business-plugins` 源码纳入仓库(档案 75 · B5 的旧账)。
|
|||
|
|
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、追加(2026-09-13 19:3x–19:5x):**从「只读」升级为「就地全量管理」**(用户要求)
|
|||
|
|
|
|||
|
|
### 10.1 用户的三条要求
|
|||
|
|
1. **dsh 设置里的「用户管理」改名为「用户设置」**,且**去掉里面的「打开管理平台」入口**
|
|||
|
|
2. **「平台管理」不要再跳新页面** —— **把所有管理项都放进「系统管理」,每项点开是弹窗**
|
|||
|
|
|
|||
|
|
### 10.2 落地
|
|||
|
|
|
|||
|
|
| 项 | 改动 | 产物 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 「用户管理」→**「用户设置」** | `@dsh-local/portal-entry`:section `id: user-management → user-settings`、`label` 改名、**order 102 → 103**(让位给平台管理);**删除「打开管理台」按钮**;内容改为「账号:<用户名> 角色:<管理员/普通用户>」+ 退出登录 | **`portal-entry-0.5.2.tgz`**(已铺发到 admin+guest) |
|
|||
|
|
| 「平台管理」→**「系统管理」+ 管理项 + 弹窗** | `@dsh-local/business-plugins`:**删掉 `window.open(portal.html)` 跳转按钮**;分区改为「**管理项列表**」,5 项(用户管理 / 候选池 / 运行时 / 存储 / 当前实例)**每项点开是原生弹窗**;**用户管理弹窗内可直接 通过 / 禁用 / 启用 / 删除**(调平台既有 admin API,不跳门户) | **`business-plugins-0.3.0.tgz`**(已铺发) |
|
|||
|
|
|
|||
|
|
### 10.3 验收(`npm run verify` 内)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ admin:含分区标题「系统管理」 ✓ admin:5 个管理项齐全
|
|||
|
|
✓ admin:不再是只读(提示改为弹窗内管理)
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何管理项
|
|||
|
|
结论:全绿 ✅
|
|||
|
|
```
|
|||
|
|
另:**磁盘复核** —— 两 profile 的 `business-plugins` 均 **0.3.0**、含「系统管理」、**`window.open` 计数 = 0**(跳新页彻底移除)✓
|
|||
|
|
|
|||
|
|
### 10.4 尚未做的(下一批)
|
|||
|
|
|
|||
|
|
- 弹窗内**目前只有「用户管理」是可写**的;**候选池 / 运行时 / 存储 / 实例** 三项为**只读列表**(写操作待补)。
|
|||
|
|
- **portal-entry 源码不在仓库**(只有铺发脚本 + artifacts 里的 tgz)⇒ 本次是**在产物上改**的。**建议**:把 `portal-entry`/`business-plugins` 源码纳入仓库(档案 75 · B5 的旧账)。
|
|||
|
|
|
|||
|
|
### 10.5 视觉层补齐(2026-09-13 20:1x,用户反馈「像毛坯房、参考门户样式、把 UI 规范记脑袋里」)
|
|||
|
|
|
|||
|
|
**做法**:按 `06-工作台UI规范` 重做视觉层(此前只做了功能骨架、无样式):
|
|||
|
|
|
|||
|
|
| 元素 | 采纳的规范条目 | 取值 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 管理项卡片 | **§4.5 `.data-card`** | **r12** / `16px 18px` / `box-shadow: 0 1px 3px rgba(0,0,0,.08)` / **hover 上浮 `translateY(-2px)` + 蓝边 + `0 4px 12px rgba(47,111,237,.15)`** / `transition .15s cubic-bezier(.16,1,.3,1)` |
|
|||
|
|
| 卡片布局 | §3 | `grid-template-columns: repeat(auto-fill, minmax(158px, 1fr))` + gap 12;`minHeight 104px` 保证等高 |
|
|||
|
|
| 弹窗 | **§4.7 `.modal` / `.modal-mask`** | mask `rgba(0,0,0,.35)` + flex 居中;面板 **r14 / `22px 26px` / `width 520px` / `max-width 92vw` / `0 8px 30px`**;进场 `paIn .18s` |
|
|||
|
|
| 按钮 | §4.1 `.btn-sm` 量级 | `3px 10px` / r6 / 12–13px;hover 蓝边蓝字 + 淡蓝底 |
|
|||
|
|
| 数值 | **§5** | 计数**右对齐 + `font-variant-numeric: tabular-nums`** |
|
|||
|
|
| 字号 | §2.2 阶梯 | 卡片标题 15/500、说明 13/次级色、计数 17/500 |
|
|||
|
|
| 动效降级 | §4.5 | `@media (prefers-reduced-motion: reduce)` 关动画与位移 |
|
|||
|
|
|
|||
|
|
**色彩**:继续用 dsh 官方 token `--dsw-*`(**刻意不硬编码亮色**——本 section 嵌在 dsh 设置面板内,须自动跟随 dsh 主题;硬编码会在暗色主题下瞎)。规范里的硬色值是给**门户静态页**的。
|
|||
|
|
|
|||
|
|
**产物**:`business-plugins-0.3.1.tgz`(已铺发 admin+guest);`npm run verify` 全绿。
|
|||
|
|
|
|||
|
|
⚠️ **教训(已入库)**:上一轮**只做了功能、没做视觉**就交付,被指「像毛坯房」。**做页面的默认动作必须包含「查规范 → 落地 §4.5/§4.7 等具体条目」**,不能等用户来提。
|
|||
|
|
|
|||
|
|
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、追加(2026-09-13 19:3x–19:5x):**从「只读」升级为「就地全量管理」**(用户要求)
|
|||
|
|
|
|||
|
|
### 10.1 用户的三条要求
|
|||
|
|
1. **dsh 设置里的「用户管理」改名为「用户设置」**,且**去掉里面的「打开管理平台」入口**
|
|||
|
|
2. **「平台管理」不要再跳新页面** —— **把所有管理项都放进「系统管理」,每项点开是弹窗**
|
|||
|
|
|
|||
|
|
### 10.2 落地
|
|||
|
|
|
|||
|
|
| 项 | 改动 | 产物 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 「用户管理」→**「用户设置」** | `@dsh-local/portal-entry`:section `id: user-management → user-settings`、`label` 改名、**order 102 → 103**(让位给平台管理);**删除「打开管理台」按钮**;内容改为「账号:<用户名> 角色:<管理员/普通用户>」+ 退出登录 | **`portal-entry-0.5.2.tgz`**(已铺发到 admin+guest) |
|
|||
|
|
| 「平台管理」→**「系统管理」+ 管理项 + 弹窗** | `@dsh-local/business-plugins`:**删掉 `window.open(portal.html)` 跳转按钮**;分区改为「**管理项列表**」,5 项(用户管理 / 候选池 / 运行时 / 存储 / 当前实例)**每项点开是原生弹窗**;**用户管理弹窗内可直接 通过 / 禁用 / 启用 / 删除**(调平台既有 admin API,不跳门户) | **`business-plugins-0.3.0.tgz`**(已铺发) |
|
|||
|
|
|
|||
|
|
### 10.3 验收(`npm run verify` 内)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ admin:含分区标题「系统管理」 ✓ admin:5 个管理项齐全
|
|||
|
|
✓ admin:不再是只读(提示改为弹窗内管理)
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何管理项
|
|||
|
|
结论:全绿 ✅
|
|||
|
|
```
|
|||
|
|
另:**磁盘复核** —— 两 profile 的 `business-plugins` 均 **0.3.0**、含「系统管理」、**`window.open` 计数 = 0**(跳新页彻底移除)✓
|
|||
|
|
|
|||
|
|
### 10.4 尚未做的(下一批)
|
|||
|
|
|
|||
|
|
- 弹窗内**目前只有「用户管理」是可写**的;**候选池 / 运行时 / 存储 / 实例** 三项为**只读列表**(写操作待补)。
|
|||
|
|
- **portal-entry 源码不在仓库**(只有铺发脚本 + artifacts 里的 tgz)⇒ 本次是**在产物上改**的。**建议**:把 `portal-entry`/`business-plugins` 源码纳入仓库(档案 75 · B5 的旧账)。
|
|||
|
|
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。# 82 · R2 管理面就地化(原生「平台管理」分区)
|
|||
|
|
|
|||
|
|
- 日期:2026-09-13
|
|||
|
|
- 状态:🚧 **代码完成、产物已出;待投放 + 启用 + 浏览器验收**
|
|||
|
|
- 触发:档案 81 §四 R2(原「实例内弹窗 iframe」);形态经用户 2026-09-13 拍板改为**原生弹窗**(§9.2b)
|
|||
|
|
- 原则:**只读优先**(写操作回跳平台域);**不改官方 dsh**;**不把门户 UI 复制进插件**
|
|||
|
|
|
|||
|
|
> **TL;DR**|① R2 的 **R5 权限影响评估**已在档案 81 §9.2 出齐并获批(扩大点=实例内出现可操作的管理入口 ⇒ **仅 admin 可见** + **只读** + 写操作回跳);
|
|||
|
|
> ② 本轮把「**平台管理**」分区**写进 `@dsh-local/business-plugins` 插件**(原生渲染,非 iframe)—— 数据直接调平台只读 API;
|
|||
|
|
> ③ 产物 `dsh-local-business-plugins-0.2.9.tgz` 已出(`node --check` 通过、包结构合规);
|
|||
|
|
> ④ **未做**:投放候选池 / 实例启用 / 浏览器验收(**卡在需要 admin 登录态**,见 §五);`/admin` 路由族 + 删 3 桩页 亦未做。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、形态(与档案 81 §9.2b 一致)
|
|||
|
|
|
|||
|
|
| 维度 | 取值 |
|
|||
|
|
|---|---|
|
|||
|
|
| 渲染 | **原生渲染**(复用插件自有 token `--dsw-*` + `06-工作台UI规范` 字号阶梯),**非 iframe** |
|
|||
|
|
| 数据 | 直接调平台**只读** API(跨子域 fetch + `credentials: "include"`,门户 CORS 白名单已就绪) |
|
|||
|
|
| 范围 | **只读子集**:实例 / 熔断 / 用户 / 存储 / 候选池 / 运行时 |
|
|||
|
|
| 写操作 | **一律回跳平台管理台**(`portalHost() + "/portal.html"`)—— 不复制门户写 UI(否则双源维护 + 与档案 39「收窄执行面」相冲) |
|
|||
|
|
| 可见性 | **仅 admin**:先 `GET /api/auth/me` 判 `role === "admin"`,否则只渲染一行说明 |
|
|||
|
|
| 落点 | `poc/business-plugins/lib/client.js`(设置面板 `settings.section`,`id: platform-admin`, `order: 102`) |
|
|||
|
|
|
|||
|
|
## 二、改了哪些文件
|
|||
|
|
|
|||
|
|
| 文件 | 改动 |
|
|||
|
|
|---|---|
|
|||
|
|
| `poc/business-plugins/lib/client.js` | **895 → 1083 行**:① zh/en 词典各 +**29** 个 `pa.*` 键;② 新增 `PaCard`(指标卡)+ `PlatformAdminSection`;③ 新增一个 `settings.section` 注册(`platform-admin`) |
|
|||
|
|
| `poc/business-plugins/package.json` | 版本 `0.2.8` → **`0.2.9`** |
|
|||
|
|
| 产物 | **`dsh-local-business-plugins-0.2.9.tgz`**(16,712 B;顶层仅 `package/`;无 `.tgz`/`node_modules`/`.bak`) |
|
|||
|
|
|
|||
|
|
## 三、数据来源(均为平台既有路由,零新增后端)
|
|||
|
|
|
|||
|
|
| 卡片 | API | 权限 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 角色门禁 | `GET /api/auth/me` | requireAuth |
|
|||
|
|
| 当前实例 / 熔断 | `GET /api/dsh/status` | requireAuth |
|
|||
|
|
| 用户 | `GET /api/admin/users` | requireAdmin |
|
|||
|
|
| 存储 | `GET /api/admin/storage` | requireAdmin |
|
|||
|
|
| 候选池 | `GET /api/plugins/business` | requireAdmin |
|
|||
|
|
| 运行时 | `GET /api/admin/runtime` | requireAdmin |
|
|||
|
|
|
|||
|
|
> 全部**只读**;任一失败降级为 `null` 并照常渲染其余卡片(不整页报错)。
|
|||
|
|
|
|||
|
|
## 四、已验证 / 未验证
|
|||
|
|
|
|||
|
|
| 项 | 状态 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 语法 | ✅ | `node --check lib/client.js` 通过 |
|
|||
|
|
| 包结构 | ✅ | 顶层仅 `package/`;4 条目;无违规文件;`lib/client.js` 在内 |
|
|||
|
|
| 词条键集 | ✅ | zh/en 各 +29 键,键名一一对应 |
|
|||
|
|
| 渲染 / 交互 / 权限门禁 | ⏸ **未验证** | 需投放 + 启用(见 §五) |
|
|||
|
|
|
|||
|
|
## 五、⛔ 未完成:投放与验收需要 **admin 登录态**
|
|||
|
|
|
|||
|
|
- 投放走 **`POST /api/plugins/business`**(`requireAdmin`)⇒ 必须有 admin 的会话。
|
|||
|
|
- 平台 CLI 只有 `start` / `bootstrap-admin` / `file-service`,**无投放命令**;文档内**无**测试口令 ⇒ **执行会话拿不到凭据**。
|
|||
|
|
- 三条可选路径(待用户定):① 用户自己在门户投放(2 分钟);② 给 admin 口令;③ 用 `bootstrap-admin` 建**临时 admin**,用完删(会动生产 auth)。
|
|||
|
|
|
|||
|
|
## 六、R2 剩余(本次**未**做,属同期的另一半)
|
|||
|
|
|
|||
|
|
1. **`/admin` 路由族 + 删 3 个跳转桩页**(`web/desktop.html` / `plugins.html` / `skills.html`,各 247–265 B,`title=跳转中…`)—— 档案 81 §四表格口径;⚠️ 删桩页**必须同时加 301 到 `/admin`**(否则既有书签断)。删后**静态页 9 → 6**,需同步改 `scripts/verify-static.mjs` 的页数断言。
|
|||
|
|
2. **注入层 CSS 类统一为 `.dshs-*`**(档案 81 §四:`.__dsh-*` / `.wk-*` → `.dshs-*`)。
|
|||
|
|
|
|||
|
|
## 七、回滚
|
|||
|
|
|
|||
|
|
- 插件侧:把候选池里的 `business-plugins` **回落 0.2.8**(旧 tgz 若已删,可从本机 git 历史取 `lib/client.js` 重建)。
|
|||
|
|
- 本轮改动**全部在 `poc/business-plugins/`**,未动 `src/`、未动官方 dsh、未动服务器 ⇒ 回滚只需还原该目录 + 重新投放。
|
|||
|
|
|
|||
|
|
## 八、口径提醒
|
|||
|
|
|
|||
|
|
> ⚠️ **不能两头都要**(档案 81 §9.2b):若日后要求「弹窗里能完成**全部**管理动作」,那就等于把整个门户重写进插件(双源维护 + 扩大执行面)⇒ 届时应把**门户收敛成 API 客户端**,而不是继续复制 UI。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、追加(2026-09-13 18:1x–19:2x):**部署完成 + 无浏览器渲染验收通过 + 一并做掉档案 80 第 7 项**
|
|||
|
|
|
|||
|
|
### 9.1 部署链路(**关键:不走候选池**)
|
|||
|
|
|
|||
|
|
`@dsh-local/business-plugins` **不是池内插件** —— 它由 **`scripts/ensure-biz-plugins.cjs`** 铺发:从 **`/opt/dsh/artifacts/`** 取**版本号最大**的 `business-plugins-*.tgz`(`--all` 含 admin;`--restart` 让 bundle 生效)。
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 投放产物 | `business-plugins-0.2.9.tgz` → `/opt/dsh/artifacts/`(前一版为 0.2.8) |
|
|||
|
|
| 铺发 | `node scripts/ensure-biz-plugins.cjs --all --restart` ⇒ **admin 与 guest 的 profile 均 0.2.8 → 0.2.9**、`bundles` 均含该包 ✓ |
|
|||
|
|
| 磁盘层断言 | 两实例 `node_modules/@dsh-local/business-plugins/lib/client.js` 含「平台管理」× **5** ✓ |
|
|||
|
|
| 实例 | 两实例均已重启并 running;实例页 **HTTP 200** ✓ |
|
|||
|
|
|
|||
|
|
### 9.2 渲染验收:**改用无浏览器 harness**(因 `agent-browser` daemon 起不来)
|
|||
|
|
|
|||
|
|
- ⚠️ **本机 `[email protected]` 的 daemon 起不来**:`open` **挂住且零输出**(`--version` / `node -e` 均正常;`~/.agent-browser` 里留下的 `default.port` 实测**不通**、清掉僵尸状态后仍不通)。Chrome 153 已由 `agent-browser install` 装好,但 daemon 不通 ⇒ **浏览器截图验收受阻**(属环境问题,未解)。
|
|||
|
|
- ⚠️ `06-工作台UI规范 §7.3` 的三段式在**按需动态加载的 bundle** 上拿不到带 `rev` 的完整 URL(该 bundle 不出现在实例首页 HTML 里)⇒ ②③ 段也不适用。
|
|||
|
|
- ✅ **替代做法(已沉淀为可复跑脚本)**:`scripts/verify-platform-admin-section.mjs` —— 打桩 `react` / `react/jsx-runtime` + **最小 hooks 渲染循环** + **真执行** `client.js`,直接断言结构与门禁。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 存在 platform-admin 分区 ✓ 其 order = 102
|
|||
|
|
✓ admin:含分区标题「平台管理」 ✓ admin:6 张卡齐全 ✓ admin:含只读声明
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何指标卡
|
|||
|
|
结论:全绿 ✅ exit=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
admin 视角实际渲染文本(实测):
|
|||
|
|
|
|||
|
|
> 平台管理 | 只读 | 本分区为只读;写操作请在平台管理台完成。
|
|||
|
|
> 当前实例 | 运行中 | 端口 43095 · 自动重启 2 | 熔断 | 正常 | —
|
|||
|
|
> 用户 | 4 | 待审核 1 · 已禁用 1 | 存储 | 2 | 报告每小时刷新
|
|||
|
|
> 候选池 | 3 | 已投放插件 | 运行时 | 5 | 条目 | 打开完整管理台
|
|||
|
|
|
|||
|
|
已接入 **`npm run verify`**(`&& node scripts/verify-platform-admin-section.mjs`)⇒ 今后 UI 改动可 CI 式防回归。
|
|||
|
|
|
|||
|
|
### 9.3 一并做掉:档案 80 第 7 项 / 档案 81 §四「删 3 个跳转桩页」
|
|||
|
|
|
|||
|
|
- 删 `web/{desktop,plugins,skills}.html` ⇒ **静态页 9 → 6** ✓;改 **5 处引用**(`admin.html` / `index.html` / `login.html`×2 / `dsh.ts` 注释)。`verify-static.mjs` 是**自动发现页面**的,无需改。
|
|||
|
|
- nginx `alotbuy.com.conf` **两个 server 块**各加 3 条精确匹配 301 ⇒ 实测 `/desktop.html`→301 `/portal.html`、`/plugins.html`→`#/plugins`、`/skills.html`→`#/skills` ✓;`login.html` 仍 200 ✓。
|
|||
|
|
- ⚠️ 本机 nginx 由**宝塔**托管:`systemctl reload nginx` **失效**,须用 **`nginx -s reload`**。
|
|||
|
|
|
|||
|
|
### 9.4 🔴 期间修掉一个**由本次改名引入的真回归**(如实记录)
|
|||
|
|
|
|||
|
|
- 症状:**admin 实例页 502**,journal = `plugin tree failed to load … corrupt session log`。
|
|||
|
|
- 根因:会话日志是 **`session.jsonl.zstd`(zstd 压缩)**。改名只改了**目录名**与**纯文本文件**,**压缩流 header 里的 `cwd` 仍是旧路径** ⇒ dsh 启动做一致性校验(header cwd vs 目录推导 cwd)**不匹配 ⇒ 抛错 ⇒ 插件树加载失败 ⇒ 崩溃循环**。
|
|||
|
|
- 修复:`_fix_sesslog.cjs`(node 内置 `zlib.zstdDecompressSync/zstdCompressSync`,22.15+)—— 解压 → 替换 → 重压 → **回读校验**。**26 个文件 24 个待修 → 全修完,复查 0 残留** ✓;实例恢复 200,`corrupt session log` 归零。
|
|||
|
|
- 📌 **教训**:**压缩文件里的路径 `grep`/`sed` 够不到** —— 与「SQLite 改名必须带 `-wal`/`-shm`」同类。已写进项目 `MEMORY.md` 铁律。
|
|||
|
|
|
|||
|
|
### 9.5 期间发现的两个平台缺陷(**待修**)
|
|||
|
|
|
|||
|
|
1. **`op-lock` 不可用**:锁根 `/opt/dsh/state/.op-lock` **不存在**,且 `scripts/op-lock.sh` 自身解析 `bt-server` 失败 ⇒ 它报「已存在 → 停手」是**假警报**,无法用于互斥。
|
|||
|
|
2. **`agent-browser` daemon 起不来**(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
|
|||
|
|
|
|||
|
|
### 9.6 尚未做
|
|||
|
|
|
|||
|
|
- **D / J / Q**(T03 遗留)与**登录/注册/门户/设置面板的体验审计**(用户 18:1x 关注的第三块)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、追加(2026-09-13 19:3x–19:5x):**从「只读」升级为「就地全量管理」**(用户要求)
|
|||
|
|
|
|||
|
|
### 10.1 用户的三条要求
|
|||
|
|
1. **dsh 设置里的「用户管理」改名为「用户设置」**,且**去掉里面的「打开管理平台」入口**
|
|||
|
|
2. **「平台管理」不要再跳新页面** —— **把所有管理项都放进「系统管理」,每项点开是弹窗**
|
|||
|
|
|
|||
|
|
### 10.2 落地
|
|||
|
|
|
|||
|
|
| 项 | 改动 | 产物 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 「用户管理」→**「用户设置」** | `@dsh-local/portal-entry`:section `id: user-management → user-settings`、`label` 改名、**order 102 → 103**(让位给平台管理);**删除「打开管理台」按钮**;内容改为「账号:<用户名> 角色:<管理员/普通用户>」+ 退出登录 | **`portal-entry-0.5.2.tgz`**(已铺发到 admin+guest) |
|
|||
|
|
| 「平台管理」→**「系统管理」+ 管理项 + 弹窗** | `@dsh-local/business-plugins`:**删掉 `window.open(portal.html)` 跳转按钮**;分区改为「**管理项列表**」,5 项(用户管理 / 候选池 / 运行时 / 存储 / 当前实例)**每项点开是原生弹窗**;**用户管理弹窗内可直接 通过 / 禁用 / 启用 / 删除**(调平台既有 admin API,不跳门户) | **`business-plugins-0.3.0.tgz`**(已铺发) |
|
|||
|
|
|
|||
|
|
### 10.3 验收(`npm run verify` 内)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
✓ 注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ admin:含分区标题「系统管理」 ✓ admin:5 个管理项齐全
|
|||
|
|
✓ admin:不再是只读(提示改为弹窗内管理)
|
|||
|
|
✓ 非 admin:被门禁挡住 ✓ 非 admin:不出现任何管理项
|
|||
|
|
结论:全绿 ✅
|
|||
|
|
```
|
|||
|
|
另:**磁盘复核** —— 两 profile 的 `business-plugins` 均 **0.3.0**、含「系统管理」、**`window.open` 计数 = 0**(跳新页彻底移除)✓
|
|||
|
|
|
|||
|
|
### 10.4 尚未做的(下一批)
|
|||
|
|
|
|||
|
|
- 弹窗内**目前只有「用户管理」是可写**的;**候选池 / 运行时 / 存储 / 实例** 三项为**只读列表**(写操作待补)。
|
|||
|
|
- **portal-entry 源码不在仓库**(只有铺发脚本 + artifacts 里的 tgz)⇒ 本次是**在产物上改**的。**建议**:把 `portal-entry`/`business-plugins` 源码纳入仓库(档案 75 · B5 的旧账)。
|
|||
|
|
|
|||
|
|
### 10.5 视觉层补齐(2026-09-13 20:1x,用户反馈「像毛坯房、参考门户样式、把 UI 规范记脑袋里」)
|
|||
|
|
|
|||
|
|
**做法**:按 `06-工作台UI规范` 重做视觉层(此前只做了功能骨架、无样式):
|
|||
|
|
|
|||
|
|
| 元素 | 采纳的规范条目 | 取值 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 管理项卡片 | **§4.5 `.data-card`** | **r12** / `16px 18px` / `box-shadow: 0 1px 3px rgba(0,0,0,.08)` / **hover 上浮 `translateY(-2px)` + 蓝边 + `0 4px 12px rgba(47,111,237,.15)`** / `transition .15s cubic-bezier(.16,1,.3,1)` |
|
|||
|
|
| 卡片布局 | §3 | `grid-template-columns: repeat(auto-fill, minmax(158px, 1fr))` + gap 12;`minHeight 104px` 保证等高 |
|
|||
|
|
| 弹窗 | **§4.7 `.modal` / `.modal-mask`** | mask `rgba(0,0,0,.35)` + flex 居中;面板 **r14 / `22px 26px` / `width 520px` / `max-width 92vw` / `0 8px 30px`**;进场 `paIn .18s` |
|
|||
|
|
| 按钮 | §4.1 `.btn-sm` 量级 | `3px 10px` / r6 / 12–13px;hover 蓝边蓝字 + 淡蓝底 |
|
|||
|
|
| 数值 | **§5** | 计数**右对齐 + `font-variant-numeric: tabular-nums`** |
|
|||
|
|
| 字号 | §2.2 阶梯 | 卡片标题 15/500、说明 13/次级色、计数 17/500 |
|
|||
|
|
| 动效降级 | §4.5 | `@media (prefers-reduced-motion: reduce)` 关动画与位移 |
|
|||
|
|
|
|||
|
|
**色彩**:继续用 dsh 官方 token `--dsw-*`(**刻意不硬编码亮色**——本 section 嵌在 dsh 设置面板内,须自动跟随 dsh 主题;硬编码会在暗色主题下瞎)。规范里的硬色值是给**门户静态页**的。
|
|||
|
|
|
|||
|
|
**产物**:`business-plugins-0.3.1.tgz`(已铺发 admin+guest);`npm run verify` 全绿。
|
|||
|
|
|
|||
|
|
⚠️ **教训(已入库)**:上一轮**只做了功能、没做视觉**就交付,被指「像毛坯房」。**做页面的默认动作必须包含「查规范 → 落地 §4.5/§4.7 等具体条目」**,不能等用户来提。
|
|||
|
|
|
|||
|
|
### 10.6 修复:**普通用户不该看到「系统管理」**(2026-09-13 20:3x,用户指出)
|
|||
|
|
|
|||
|
|
**问题**:此前只对**内容**做了门禁 ⇒ **section 本身仍对所有人注册**,普通用户在设置里能看到「系统管理」这一栏(点进去只有一行「仅管理员」)。
|
|||
|
|
|
|||
|
|
**正解(不再注册,而非注册后藏内容)**:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
// apply() 里先异步判角色,非 admin 干脆不注册
|
|||
|
|
fetch(portalHost() + "/api/auth/me", { credentials: "include" })
|
|||
|
|
.then(r => r.ok ? r.json() : null)
|
|||
|
|
.then(d => { if (d?.user?.role !== "admin") return; ctx.slots.inject(...register...) })
|
|||
|
|
.catch(() => {}) // fail-closed:判角色失败按非 admin 处理
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**依据(有实证,不是猜)**:官方 settings 外壳的导航是这样算的 ——
|
|||
|
|
`dsh-client-ui-settings/lib/client.js:560`:`const version = ctx.slots.getVersion("settings.section")` ⇒ **版本变化会重算导航行** ⇒ **晚注册(异步 inject)会被正确反映** ✓。
|
|||
|
|
|
|||
|
|
**验收(已进 `npm run verify`)**:
|
|||
|
|
```
|
|||
|
|
✓ admin 视角下注册了两个 settings.section -> business-plugins, platform-admin
|
|||
|
|
✓ 非 admin 视角下只注册 1 个分区(不含系统管理) -> business-plugins
|
|||
|
|
结论:全绿 ✅
|
|||
|
|
```
|
|||
|
|
(验收脚本原先没等异步注册 ⇒ 一并修好:`apply` 后 `await 80ms` 再断言。)
|
|||
|
|
|
|||
|
|
**产物**:`business-plugins-0.3.2.tgz`(已铺发 admin+guest)。
|
|||
|
|
|
|||
|
|
### 10.7 视觉层第 2 轮:**「照抄门户源码」而不是「照抄规范条目」**(2026-09-13 20:4x,用户第 2 次反馈)
|
|||
|
|
|
|||
|
|
**用户原话**:「点击卡片后的弹窗样式还是没变呢,说了要用之前门户的里面的对应样式」。
|
|||
|
|
|
|||
|
|
#### 🔴 真因有两个(都查明并已修)
|
|||
|
|
|
|||
|
|
| # | 真因 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| **1** | **我上一步的改动根本没出厂** —— `lib/client.js` 的 mtime = `20:33`,而线上最新产物 `business-plugins-0.3.2.tgz` 打包于 `20:17` | `ls -la` 时间戳对比;解包 0.3.2 与工作副本 `diff` 显示 109 行差异全在「未打包」那一侧 |
|
|||
|
|
| **2** | 更要命:**上一版只有「用户管理」1 个弹窗是门户表格**,另外 4 个(候选池 / 运行时 / 存储 / 当前实例)**仍是裸 `div` + 内联样式**(`padding:8px 10px; border:1px solid …; borderRadius:8px; fontSize:13px`)⇒ 点开就是「毛坯房」 | `git diff` 原文:4 个分支返回 `jsxRuntime.jsx("div", { style: { display:"flex" … } })`,无任何 `className` |
|
|||
|
|
|
|||
|
|
⇒ **我上一轮「照抄」抄的是 `06-工作台UI规范` 的抽象条目(§4.5 `.data-card` / §4.7 `.modal`),而用户要的是 `web/portal.html` 里那套已经跑着的实际组件。** 规范条目 ≠ 门户真实样式。
|
|||
|
|
|
|||
|
|
#### 本轮做法:**读门户源码,逐值对应**
|
|||
|
|
|
|||
|
|
| 「系统管理」元素 | 门户来源(`web/portal.html`) | 落地类名 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 卡片网格 | `.nav-grid`(`repeat(auto-fill,minmax(200px,1fr))` / gap `14px`) | `.pa-grid` |
|
|||
|
|
| 管理项卡片 | `.nav-card`(**r10** / `18px 16px` / hover:蓝边 + `0 4px 12px rgba(47,111,237,.12)` + 上浮 `-2px`) | `.pa-card` |
|
|||
|
|
| 卡片内三行 | `.nav-card .ic`(主色)/ `.t`(15-600)/ `.d`(12 dim) | `.pa-ic` / `.pa-t` / `.pa-d` |
|
|||
|
|
| 卡片计数 | `.pg-tab .pg-cnt`(12-600 胶囊 / 主色底) | `.pa-cnt` |
|
|||
|
|
| **弹窗正文(全部 5 个)** | `.table-wrap` + `table.tbl`(th 灰底 `8px 10px`-600 / td `7px 10px` / 行 hover 浅蓝 / 末行去下边框) | `.pa-wrap` + `.pa-tbl` |
|
|||
|
|
| 表格空态 | 门户 `emptyRow()`(居中 + `40px 10px`) | `.pa-tbl td.pa-empty-cell` |
|
|||
|
|
| 角色徽章 | `.badge` + 四色 `.admin/.active/.pending/.disabled` | `.pa-badge` |
|
|||
|
|
| 操作按钮 | `.btn-sm`(`3px 10px` / r6 / 14px;`.danger` 红字红边) | `.pa-sm` / `.pa-sm.danger` |
|
|||
|
|
| 弹窗头 | `.card-h`(15-600,可带 13 dim 副标题) | `.pa-card-h` |
|
|||
|
|
| 标题 / 副标题 | `.page-title`(20-600)/ `.page-sub`(13 dim) | `.pa-hd` / `.pa-sub` |
|
|||
|
|
| 分组小标题 | `.home-section-title`(13 dim 600) | `.pa-sec` |
|
|||
|
|
| **弹窗外壳** | 门户**没有弹窗** ⇒ 面板取 `.card`(r10 / `18px`)+ 门户家族阴影(`design.css` `--shadow` = `0 18px 50px -18px rgba(9,24,58,.35)`) | `.pa-overlay` + `.pa-modal` |
|
|||
|
|
|
|||
|
|
**5 个弹窗逐个改完**:
|
|||
|
|
|
|||
|
|
| 弹窗 | 表头 | 说明 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 用户管理 | 用户名 / 角色 / 操作 | 可写:通过 · 启用 · 禁用 · 删除(`.btn-sm.danger`) |
|
|||
|
|
| 候选池 | 插件 / 版本 | 只读 |
|
|||
|
|
| 运行时 | 项目 / 版本 | 只读 |
|
|||
|
|
| 存储 | 用户 / 已用(`.pa-num` 右对齐 tabular-nums) | 只读 |
|
|||
|
|
| 当前实例 | 项目 / 值(键值表) | 只读 |
|
|||
|
|
|
|||
|
|
⚠️ **唯一的刻意差异**:颜色走 dsh 官方 token `--dsw-*`(本 section 嵌在 dsh 设置面板内、须自动跟随 dsh 主题);门户那套 `--bp-*` 是给亮色静态页的硬编码。**字号 / 间距 / 圆角 / 动效与门户逐值一致。**
|
|||
|
|
|
|||
|
|
#### 三层验收(这次不只看单测)
|
|||
|
|
|
|||
|
|
**① 单测层**(已进 `npm run verify`,脚本 `scripts/verify-platform-admin-section.mjs` 新增「结构层」断言):
|
|||
|
|
```
|
|||
|
|
✓ 首页:卡片网格取门户 .nav-grid 值
|
|||
|
|
✓ 首页:卡片取门户 .nav-card 值(.pa-card)
|
|||
|
|
✓ 首页:计数胶囊取门户 .pg-cnt 值(.pa-cnt)
|
|||
|
|
✓ 首页:标题/副标题取门户 .page-title/.page-sub 值
|
|||
|
|
✓ 5 个弹窗全部 = 门户弹窗外壳 + portal 表格 + .btn-sm -> users/plugins/runtime/storage/instance 均通过
|
|||
|
|
✓ 用户弹窗:角色用门户 .badge 四色 -> 4 枚
|
|||
|
|
✓ 用户弹窗:删除按钮用门户 .btn-sm.danger
|
|||
|
|
✓ 实例弹窗:键值齐全
|
|||
|
|
结论:全绿 ✅
|
|||
|
|
```
|
|||
|
|
(写这套断言时踩到校验脚本自身的坑:树遍历 `depth > 12` 上限会把 `表格>tbody>tr>td>文本` 这一支截断 ⇒ 表头有、行文本丢;**已放宽到 20 并加注释**。属校验脚本缺陷,不是产物缺陷。)
|
|||
|
|
|
|||
|
|
**② 服务器实装层**(md5 三处一致):
|
|||
|
|
```
|
|||
|
|
dep: business-plugins-0.3.3.tgz ← 两个 profile 都指向 0.3.3
|
|||
|
|
实链: business-plugins@file+…+business-plugins-0.3.3.tgz
|
|||
|
|
md5: 5800ba4f77e1c786063aed8a91f9f4b4 ← admin / guest / 本地产物 三方完全相同
|
|||
|
|
旧版残留(.pa-n{|pa-go): 0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**③ 端到端层**(**真正下发到浏览器的那份**):临时会话 `mksess.cjs` → 取实例首页 → 解出模块 URL → 取回 bundle(`用完即删临时会话`):
|
|||
|
|
```
|
|||
|
|
实例首页 http=200
|
|||
|
|
模块 URL: /plugins/??…,@dsh-local/business-plugins/client.js,…&rev=fd084d6aa33a
|
|||
|
|
bundle http=200 bytes=4260682
|
|||
|
|
pa-empty-cell 3 处 / pa-card-h 4 处 / pa-overlay 2 处 / pa-cnt 3 处
|
|||
|
|
pa-grid 3 处 / pa-tbl 10 处 / border-radius:10px;padding:18px 16px 1 处
|
|||
|
|
旧版残留:pa-go 0 / .pa-n{ 0 / 0 8px 30px rgba(0,0,0,.28) 0
|
|||
|
|
清理临时会话: 1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 缓存问题(这次一并确认,不是它导致的)
|
|||
|
|
`src/supervisor/proxy.ts:383` 对 `/plugins/` 与 `/assets/` 统一下发 `Cache-Control: no-cache`(**允许缓存但每次回源校验**);且 dsh 的模块 URL 自带 **内容 sha1 的 `rev`**。⇒ 本轮 `rev` 已从旧值变为 `fd084d6aa33a`,**用户无需清缓存 / 换无痕**。
|
|||
|
|
|
|||
|
|
#### 产物与部署
|
|||
|
|
- `business-plugins-0.3.3.tgz`(本地 `dsh-local-business-plugins-0.3.3.tgz`)
|
|||
|
|
- 铺发:`node /opt/dshs/scripts/ensure-biz-plugins.cjs --all --restart` ⇒ `admin: ✓ bundles=6` / `guest: ✓ bundles=7`,均已停实例(下次访问自动拉起新 bundle)
|
|||
|
|
- ⚠️ **顺手清掉一个自作的地雷**:打包脚本第一次因断言锚点写错(description 不以 `v0.2.8` 开头)**在写文件前就抛错**,但我已先跑了 `npm pack` ⇒ 生成了一个**内容是新版、版本号却仍写 0.3.2** 的本地 tgz。**已删除该文件**并改用正确锚点重新升到 0.3.3(服务器侧的 `business-plugins-0.3.2.tgz` 是真正的旧版,未受影响)。
|
|||
|
|
|
|||
|
|
#### 🔴 教训(已入库)
|
|||
|
|
**「按规范条目做样式」≠「用门户已经跑着的样式」。** 用户说「参考门户里的对应样式」时,正确动作是 **打开 `web/portal.html` / `admin.html` 的源码,把 `.nav-card` / `table.tbl` / `.badge` / `.btn-sm` 的**实际取值**逐条搬过来**,而不是去引规范里的抽象条目再自行演绎。另外:**交付前必须自问「这份改动出厂了吗」**——本轮真因 1 就是改完没打包没铺发。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十一、追加(2026-09-13 21:0x–21:3x):**功能名与内容全面改为「门户 6 个功能页」**(用户第 3 次反馈)
|
|||
|
|
|
|||
|
|
> 用户在铺发 0.3.3 之后当场反馈(原话):
|
|||
|
|
> 「怎么设置系统管理里面还是老样子呢,和之前门户那个**功能名称**、**页面样式**完全不一样呢,你要不要把之前那个 portal 页面打开看看,**我要点开弹窗里面展示的内容是和 portal 点击功能后那种详细的表格和功能**」
|
|||
|
|
|
|||
|
|
### 11.1 先定位「还是老样子」的真因(**不是没出厂**)
|
|||
|
|
|
|||
|
|
| 检查 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| 线上实际装的版本 | 实例 profile → `.dsh-stage/business-plugins-0.3.3.tgz`,`package.json` 解析 `"version": "0.3.3"` ⇒ **第 2 轮确实已生效** |
|
|||
|
|
| 那用户为什么说"老样子" | **第 2 轮只改了「视觉层」(class / 字号 / 颜色),没动「信息架构」** —— 管理项仍是自造的 5 项只读摘要(用户管理 / 候选池 / 运行时 / 存储 / 当前实例),而门户是 6 个功能页(服务管理 / 密钥管理 / 用户管理 / 技能管理 / 插件管理 / 运行环境)。**名字对不上、表对不上** ⇒ 用户一眼就看出"不一样" |
|
|||
|
|
|
|||
|
|
⇒ **教训**:说"照抄门户",只抄样式不算抄;**功能名 / 表格列 / 操作按钮**才是用户眼里的"是不是同一个东西"。
|
|||
|
|
|
|||
|
|
### 11.2 口径变更(**推翻 §一 表里的两行**)
|
|||
|
|
|
|||
|
|
| 维度 | §一(初版) | 本轮(现行) |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 范围 | 只读子集(实例/用户/存储/候选池/运行时) | **门户 6 个功能页,同名同构** |
|
|||
|
|
| 写操作 | 一律回跳门户管理台 | **就地调用平台 admin API**(跨子域 + `credentials:include`;门户 CORS 白名单已含 `GET,POST,DELETE,OPTIONS`) |
|
|||
|
|
| 形态 | 原生弹窗(非 iframe) | **不变**(用户 09-13 已拍板;本轮仍不做 iframe) |
|
|||
|
|
|
|||
|
|
> ⚠️ §八「口径提醒」原文(*不能两头都要…届时应把门户收敛成 API 客户端*)**仍然成立**:本轮选择了「复制 UI」这条路,代价是**双源维护**。为把代价压到最低,移植采用**逐函数照抄**并逐条注释对应关系(将来门户改了,按同名函数对照即可)。若日后要收敛,方向仍是「门户与弹窗共用一份渲染」。
|
|||
|
|
|
|||
|
|
### 11.3 落地(`poc/business-plugins/lib/client.js`,1624 → 2218 行)
|
|||
|
|
|
|||
|
|
| 新增 | 内容 |
|
|||
|
|
|---|---|
|
|||
|
|
| `PA_PAGES` | **6 个功能页**,每页 = `{ icon, title, desc, sub, html(), init($, root) }`,其中 `html()` ≡ 门户 `renderXxx()`、`init()` ≡ 门户 `initXxx()` |
|
|||
|
|
| `PA_GROUPS` | 首页分组 ← 门户 `renderHome()` 的 `sec1`(服务)+ `sec2`(管理),顺序一致 |
|
|||
|
|
| `PortalPage` | 页面宿主:`dangerouslySetInnerHTML` 注入门户原文 + `useEffect` 里跑门户 `init`(`$` = 弹窗子树内的局部查询器) |
|
|||
|
|
| 工具函数 | `pafmt`(`{占位符}`)/ `paesc` / `pafmtSize` / `pawhen` / `paemptyRow` / `pareadAsBase64` / `parelTime` / `paReq` / `papostJson` —— 均为门户同名函数移植 |
|
|||
|
|
| 词典 | `pa.*` 由 **91 → 225 条**(zh/en 键集一一对应,新增断言把关);弹窗内 **182 条** 文案**逐字取自门户** |
|
|||
|
|
| CSS | 门户页面级组件逐条译为 `.pa-*`:`.card→.pa-box`、`.btn/.btn-primary→.pa-btn*`、`.page-head→.pa-phead`、`.pg-tabs/.pg-tab/.pg-cnt→.pa-tabs/.pa-tab/.pa-tcnt`、`.dsh-bar/.dot→.pa-dshbar/.pa-dot`、`.pathbar/.crumb→.pa-pathbar/.pa-crumb`、`.upload-row/.hint→.pa-row/.pa-hint`、`.key-row→.pa-keyrow`、`.wl-*→.pa-wl*`、`.empty→.pa-empty`、`.toast→.pa-toast` |
|
|||
|
|
|
|||
|
|
**三处机械改写**(除此外结构 / 表格列 / 文案**逐字保持一致**):
|
|||
|
|
1. `document.getElementById(x)` → `$("x")`(局部查询器,避免与 dsh 面板同名 id 撞车);
|
|||
|
|
2. `fetch("/api/…")` → `paReq("/api/…")`(跨子域 + `credentials:"include"`);
|
|||
|
|
3. `location.hash` 路由 → 弹窗内页签状态(门户靠 hash 深链,弹窗不需要)。
|
|||
|
|
|
|||
|
|
**弹窗尺寸**(用户要求「需要多大就多大,不用做的太小」):`.pa-modal.pa-wide` = `width:min(1440px,96vw)`(对齐门户功能页 `.page` 的 1440)+ `height:min(92vh,1040px)`;头固定(门户 `.page-head` = ← 返回 + 标题 + 副标题 + 关闭),体内部滚动。
|
|||
|
|
|
|||
|
|
**两处对门户的有意偏离**(均已在代码注释里标注):
|
|||
|
|
- 🐛 **修掉门户 `readAsBase64()` 的缺陷**:门户原文 `return String(new Promise(…)).split(",")[1] ?? ""` **缺 `await`** ⇒ 恒得 `"[object Promise]"` ⇒ 返回空串 ⇒ **门户的「上传文件 / 上传技能 zip / 上传插件 tgz」实际传的是空数据**(三个上传入口全受影响)。弹窗侧改为返回真 Promise;**门户侧未动,待同修**。
|
|||
|
|
- `.pa-dir` 补了手型 + 主色(门户的文件夹行**没有任何可点提示**,弹窗里若照抄会没法导航文件树)。
|
|||
|
|
|
|||
|
|
### 11.4 验收
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
node scripts/verify-platform-admin-section.mjs ⇒ 全绿(0 退出码)
|
|||
|
|
node --check poc/business-plugins/lib/client.js ⇒ 通过
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
验收脚本本轮同步升级:新增**词典键集一一对应 / 占位符键一致**两条断言;断言口径从「5 项只读摘要」换成「门户 6 个功能页同名同构 + 6 个弹窗外壳 + 各页表头/按钮文本」;并新增 `clsAll()` —— **同时扫 React 节点与 `dangerouslySetInnerHTML` 里的 class**(只看 React 节点会漏掉全部表格/工具条类名,这是本轮踩到的验收盲区)。
|
|||
|
|
|
|||
|
|
### 11.5 产物与铺发
|
|||
|
|
|
|||
|
|
- `business-plugins-0.3.4.tgz`(本地 `dsh-local-business-plugins-0.3.4.tgz`,39,098 B;包内 4 条目:`package/{package.json,lib/index.js,lib/client.js,cordis.patch.yml}`,无 `.tgz` / 无 `.bak`)
|
|||
|
|
- ⚠️ 打包前**删掉了 `lib/client.js.bak-*`** —— `.npmignore` **没有**排除 `.bak`,留着会被打进产物
|
|||
|
|
- 铺发:`ssh bt-server 'cd /opt/dshs && node scripts/ensure-biz-plugins.cjs --all --restart'`(服务端脚本 md5 与本机不同,但选版逻辑一致:按 `business-plugins-<ver>.tgz` 前缀取最大版本)
|
|||
|
|
|
|||
|
|
### 11.6 ⚠️ 本轮发现、**未动手**的问题(先报告)
|
|||
|
|
|
|||
|
|
1. **门户 `readAsBase64()` 缺 `await`**(见 §11.3)—— 影响门户三个上传入口,属生产缺陷。修它要改 `web/portal.html`,**不在本次要求范围** ⇒ 未动。
|
|||
|
|
2. **本档案自身严重重复**:`# 82 · R2 管理面就地化` 标题出现 **6 次**,`## 一`–`## 八` 前缀块重复 **6 份**(1937 行里大半是重复内容,疑似历史多会话并行各自追加所致)。**未做去重**(档案只增不改 + 去重需逐块比对确认无独有内容,应单独立项)。
|
|||
|
|
|
|||
|
|
### 11.7 追加(21:2x):**「官方推荐插件」列表拉高**(用户要求)
|
|||
|
|
|
|||
|
|
> 用户原话:「系统设置 插件管理里面官方插件列表 **高度可以增加,距离底部 100PX 就行**」
|
|||
|
|
|
|||
|
|
| 项 | 改前 | 改后 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 官方插件表容器 | `class="pa-wrap" style="max-height:420px"` | `class="pa-wrap pa-plist"` |
|
|||
|
|
| 高度 | 固定 **420px** | **`max(280px, min(calc(92vh - 470px), 580px))`** |
|
|||
|
|
|
|||
|
|
取值依据(写进 CSS 注释,便于复核):弹窗高 = `min(92vh,1040px)`;表**上方**固定消耗 ≈**470px**(弹窗头 + 页签 + 工具条 + 说明 + 信息行),表**下方**还有按钮行 + 结果区 + 内边距 ⇒ 用 `calc(92vh - 470px)` 反推,使**列表底部距弹窗底部约 100px**。
|
|||
|
|
- 下限 **280px**:小屏时防止被压成一条线;
|
|||
|
|
- 上限 **580px**:对应弹窗触顶 `1040px` 时的可用高度(1040 − 470 − 下方 ≈ 90 − 100 ≈ 380…560 区间,取 580 留 20px 余量)。
|
|||
|
|
|
|||
|
|
产物:**`business-plugins-0.3.5.tgz`**(39,544 B,包内 4 条目)。铺发同上 ⇒ admin/guest 均 0.3.5;`sha256 = 1d29683770b4…` **本机 = artifacts = 两实例 `.dsh-stage` 三方一致**;实例内 `lib/client.js:654` 已含 `.pa-plist{…}`。
|
|||
|
|
验收:`verify-platform-admin-section.mjs` 全绿(CSS 断言扩到 `.pa-plist`);`node --check` 通过;**防假产物自检**:源文件 21:21:41 < 产物 21:21:58 ✅。
|
|||
|
|
⚠️ 门户原值 `calc(100vh - 520px)` 是**整页布局**下的取值,弹窗内不适用 —— 别直接照抄。
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 修正(2026-09-14)· 本档存在**严重内部重复**(已体检,原文按 L5 冻结保留)
|
|||
|
|
|
|||
|
|
**实测**(`python3 scripts/docs-dedupe.py "04-调整方案/82-R2管理面就地化-原生平台管理分区.md"`):
|
|||
|
|
|
|||
|
|
| 项 | 数 |
|
|||
|
|
|---|---|
|
|||
|
|
| 文件规模 | **2024 行 / 89.1 KB**(全库最大单篇;约定上限 30 KB) |
|
|||
|
|
| 块(按 `#`/`##`/`###` 切) | 224 个 |
|
|||
|
|
| **重复标题** | **22 个** |
|
|||
|
|
| **冗余块** | **190 个(≈85%)** —— 同一份「§一–§八」重复 **16 次**;`# 82 · …` 与 §九(9.1–9.6)各重复 **8 次** |
|
|||
|
|
| ⚠️ **内容有差异的** | **「八、口径提醒」两个变体**(各 8 次)⇒ **不是纯复制**,去重时必须两份都看 |
|
|||
|
|
|
|||
|
|
**处置(零改写,遵守 L5 冻结)**:
|
|||
|
|
1. **原文一字未改**,仅追加本小节;
|
|||
|
|
2. 生成**去重视图**(保留每组信息最全的一份,其余位置留一行占位注释):
|
|||
|
|
`…/.workbuddy/cache/dedupe-view/04-调整方案__82-R2管理面就地化-原生平台管理分区.md`
|
|||
|
|
—— **89.1 KB → 59.0 KB**(省略 192 块);
|
|||
|
|
3. ⚠️ **视图仍 59 KB > 30 KB 约定** ⇒ **去重只是第一步**,根治要靠**拆分**(把 §九 追加节与本次 R2 主体拆成两篇);此项**待立项**。
|
|||
|
|
4. 阅读建议:**先看视图**;需核对「八、口径提醒」两个变体时再回原文。
|
|||
|
|
|
|||
|
|
> 复跑体检:`python3 scripts/docs-dedupe.py <本档相对路径> --view-out`
|