1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
+ ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
146 KiB
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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
9.6 尚未做
- D / J / Q(T03 遗留)与登录/注册/门户/设置面板的体验审计(用户 18:1x 关注的第三块)。
十、追加(2026-09-13 19:3x–19:5x):从「只读」升级为「就地全量管理」(用户要求)
10.1 用户的三条要求
- dsh 设置里的「用户管理」改名为「用户设置」,且去掉里面的「打开管理平台」入口
- 「平台管理」不要再跳新页面 —— 把所有管理项都放进「系统管理」,每项点开是弹窗
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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
9.6 尚未做
- D / J / Q(T03 遗留)与登录/注册/门户/设置面板的体验审计(用户 18:1x 关注的第三块)。
十、追加(2026-09-13 19:3x–19:5x):从「只读」升级为「就地全量管理」(用户要求)
10.1 用户的三条要求
- dsh 设置里的「用户管理」改名为「用户设置」,且去掉里面的「打开管理平台」入口
- 「平台管理」不要再跳新页面 —— 把所有管理项都放进「系统管理」,每项点开是弹窗
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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
9.6 尚未做
- D / J / Q(T03 遗留)与登录/注册/门户/设置面板的体验审计(用户 18:1x 关注的第三块)。
十、追加(2026-09-13 19:3x–19:5x):从「只读」升级为「就地全量管理」(用户要求)
10.1 用户的三条要求
- dsh 设置里的「用户管理」改名为「用户设置」,且去掉里面的「打开管理平台」入口
- 「平台管理」不要再跳新页面 —— 把所有管理项都放进「系统管理」,每项点开是弹窗
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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 剩余(本次未做,属同期的另一半)
/admin路由族 + 删 3 个跳转桩页(web/desktop.html/plugins.html/skills.html,各 247–265 B,title=跳转中…)—— 档案 81 §四表格口径;⚠️ 删桩页必须同时加 301 到/admin(否则既有书签断)。删后静态页 9 → 6,需同步改scripts/verify-static.mjs的页数断言。- 注入层 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 期间发现的两个平台缺陷(待修)
op-lock不可用:锁根/opt/dsh/state/.op-lock不存在,且scripts/op-lock.sh自身解析bt-server失败 ⇒ 它报「已存在 → 停手」是假警报,无法用于互斥。agent-browserdaemon 起不来(见 §9.2)—— 浏览器验收链路的唯一可用工具受阻。
9.6 尚未做
- D / J / Q(T03 遗留)与登录/注册/门户/设置面板的体验审计(用户 18:1x 关注的第三块)。
十、追加(2026-09-13 19:3x–19:5x):从「只读」升级为「就地全量管理」(用户要求)
10.1 用户的三条要求
- dsh 设置里的「用户管理」改名为「用户设置」,且去掉里面的「打开管理平台」入口
- 「平台管理」不要再跳新页面 —— 把所有管理项都放进「系统管理」,每项点开是弹窗
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 本身仍对所有人注册,普通用户在设置里能看到「系统管理」这一栏(点进去只有一行「仅管理员」)。
正解(不再注册,而非注册后藏内容):
// 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 |
三处机械改写(除此外结构 / 表格列 / 文案逐字保持一致):
document.getElementById(x)→$("x")(局部查询器,避免与 dsh 面板同名 id 撞车);fetch("/api/…")→paReq("/api/…")(跨子域 +credentials:"include");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 ⚠️ 本轮发现、未动手的问题(先报告)
- 门户
readAsBase64()缺await(见 §11.3)—— 影响门户三个上传入口,属生产缺陷。修它要改web/portal.html,不在本次要求范围 ⇒ 未动。 - 本档案自身严重重复:
# 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 冻结):
- 原文一字未改,仅追加本小节;
- 生成去重视图(保留每组信息最全的一份,其余位置留一行占位注释):
…/.workbuddy/cache/dedupe-view/04-调整方案__82-R2管理面就地化-原生平台管理分区.md—— 89.1 KB → 59.0 KB(省略 192 块); - ⚠️ 视图仍 59 KB > 30 KB 约定 ⇒ 去重只是第一步,根治要靠拆分(把 §九 追加节与本次 R2 主体拆成两篇);此项待立项。
- 阅读建议:先看视图;需核对「八、口径提醒」两个变体时再回原文。
复跑体检:
python3 scripts/docs-dedupe.py <本档相对路径> --view-out