Files
dsh_shenxian/dsh-server-docs/04-调整方案/143-MCN工作台入口失效与语言切换显示修复.md
admin e6207aa691
build / build-and-scan (push) Waiting to run
chore(仓库对齐): 文档库结构治理 + IM/插件线落地
文档库:目录改为编号制(01-规范/02-架构设计/03-数据库/04-调整方案/
05-交接单/06-ops/07-scripts/08-skills/09-archive),顶层散文件归入 01-规范/;
INDEX.md 与 docs-manifest.json 重刷(档案 146 篇);旧目录名引用全量对齐。

IM 线:src/im/**(SDK / hub / store / presence / ws / gateway-token)、
src/web/routes/im.ts、src/db/plugin-data/**、src/supervisor/plugin-assembly.ts
及对应 test/**。

插件线:poc/{im-agent-bridge,im-connection-gateway,im-conversation-tabs,
business-plugins-im,carbon-mcp-probe}、src/web/routes/{sessions,overlay-device}.ts、
src/net/relay/{device-grant,instance-credential}.ts。

仓库卫生:清出 40 个历史误入库 / 已改名文件(34 个交接单归档 + 6 个旧结构,
本地均有副本);dsh-server-docs/.gitignore 补 tmp/;交接单不入库(政策)。
2026-09-24 07:25:16 +08:00

102 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 143 · MCN工作台入口"点了没反应" + 用户设置里切语言"没反应"
- 日期:2026-09-20
- 触发:用户「admin账号dsh会话 点击左侧 MCN工作台入口 没有反应,找到原因修复后把MCN任务会话入口的位置改到MCN工作台 header区域(用图标即可)」+「设置选项中 用户设置里面切换 语言还是不起做用」
- 对象:`dsh-plugin-mcn-suite` **0.3.10 → 0.3.11**(客户端源 = `dsh-plugin-mcn/lib/client.js`)· `@dsh-local/portal-entry` **0.5.5 → 0.5.6**
- 状态:✅ 已落地,**真机浏览器实测通过**(admin 实例,47)
> **TL;DR**|两条都是 **dsh 0.1.5-rc.1 与插件里写死的老契约不一致**,不是用户操作问题:
> ① 对话区槽位名从 `conversation` 改成 **`main.conversation`** ⇒ 插件 `querySelector('[data-slot="conversation"]')`
> 实测**恒为 null** ⇒ 工作台面板**根本不挂载**(面板宿主 `pageHost` 一直 null,portal 不渲染)="点了没反应"。
> ② `ctx.locale.getLocale()` 由"返回 id 字符串"变成**返回快照对象** `{active,locales,revision}` ⇒
> `String(obj).split("-")[0]` 恒为 `"[object Object]"` ⇒ 受控 `<select>` 匹配不上任何 option,
> 浏览器只显示**第一项(English)** ⇒ 选「中文」时界面看着毫无变化(其实**本来就是中文**,是显示错)。
> 同时按用户要求把「MCN任务会话」入口**从左侧栏独立一行搬进工作台 header(图标按钮)**。
---
## 一、取证(先证后改,全部为实测)
| # | 结论 | 证据 |
|---|---|---|
| 1 | 线上插件客户端代码 = 本地源码(**不是**改不生效) | 实例内 `dsh-plugin-mcn-suite/lib/client.js` md5 = 本地 `dsh-plugin-mcn/lib/client.js` 拼装产物 md5(`f1a3cf7c…`) |
| 2 | 实例跑的是 **dsh 0.1.5-rc.1**(插件按 0.1.2-rc.1 写) | `/usr/local/bin/dsh --version` = `0.1.5-rc.1` |
| 3 | **槽位名已改名** | 浏览器实测 `document.querySelector('[data-slot="conversation"]')` = **null**;页面上 29 个 `data-slot` 里是 **`main.conversation`**(父 `main`、祖父 `.centerCol`,两者都是 `display:contents` 透明容器,与旧结构**同形**) |
| 4 | 语言取值形态已变 | 官方 `dsh-client-locale/lib/client.js`:`getLocale()` **`return this.snapshot`**(=`{active,locales,revision}`) |
| 5 | 语言下拉"显示错"可复现 | 用户设置里 select 的 DOM `value="en"/selectedIndex=0`,而 `document.documentElement.lang` = **`zh-CN`**(即界面本来就是中文) |
> 取证手段:`mksess.cjs`(admin 临时会话)+ `agent-browser`(`set headers` 无效 ⇒ 改用 `eval document.cookie='sid=…; domain=.ai1net.com'` 注入)+ `eval` 探针。**用完删会话**(`user_agent='poc-curl2'`)。
---
## 二、改动
### 2.1 `dsh-plugin-mcn-suite` 0.3.10 → 0.3.11
源改在 `dsh-plugin-mcn/lib/client.js`(**该包是整合包的源**,构建脚本按序拼接;整合产物 `dsh-plugin-mcn-suite/lib/client.js` 由脚本重生成,勿手改):
1. **槽位自适应**:新增 `CONVERSATION_SLOT_SELECTORS = ['[data-slot="main.conversation"]', '[data-slot="conversation"]']`
+ `findConversationSlot()`,`conversation` 的取值改为调用它(两个名字都认 ⇒ 跨 dsh 版本都能挂载)。
2. **配套 CSS** 同步:`.mcnNav_split>[data-slot='conversation']` 与 `…>div{…}` 两条规则各补 `,….mcnNav_split>[data-slot='main.conversation']…`。
3. **入口搬家**:删除侧栏独立入口组件 `AiSessionsTrigger` 与其注册(`id: mcn-sessions, order: 61`);
`McnPage` 新增 `openAiSessions()`(`setEntryParams(null); setView("ai-sessions")`)并在 **header**(面包屑右侧工具条)
增加图标按钮(新增 `V1_ICON_INNER.chat` = Lucide `messages-square`),面包屑补 `ai-sessions` → 「MCN任务会话」。
### 2.2 `@dsh-local/portal-entry` 0.5.5 → 0.5.6
`currentLocale()` 兼容两种形态(**对象取 `.active`**,并兜底 `getSnapshot().active`;字符串形态照旧)。`pickLocale` / `setLocale` 不动。
### 2.3 构建链上顺带修掉的两处**负向回归**(同轮,属"随手一构建就会把已删功能装回去")
| # | 问题 | 处置 |
|---|---|---|
| A | `build-mcn-suite.cjs` 的 `CLIENT_SOURCES` / `HOST_SYNC` **仍列着 `dsh-plugin-mcn-schedule`**,而 v0.3.10 已按用户指令摘除计划任务(`HOST_PARTS` 只剩 mcn+voxemw,线上产物 `lib/host/` 无 `schedule`)⇒ **一构建就把「计划任务」装回去** | 两处同步删掉该条目(与 `lib/index.js` 的 `HOST_PARTS` 对齐) |
| B | `dsh-plugin-mcn/lib/client.js` 里 v0.3.10 的「更多功能 → 自动任务」摘除编辑**丢了**(线上产物是注释、源文件里还是死链按钮 `openEntry("entry:mcn-schedule")`) | 源文件补回同一处编辑(改成说明注释) |
| C | `pack` 未排除 tgz ⇒ 历史散落在 suite 根的 `dsh-plugin-mcn-suite-0.3.10.tgz`(1.9 MB)会被打进新包 | `--exclude=*.tgz` + 若命中即抛错;历史 tgz 移到 `dist/` |
> A/B/C 都是为了满足**「新产物 = 线上产物 + 本次修复」**这一可核验性质:重打包后与线上 0.3.10 的 `diff` = **9 个 hunk / 51 行**,全部是本次改动。
---
## 三、验收
| # | 口径 | 结果 |
|---|---|---|
| A | 语法 / 构建 | ✅ 两个源文件 `node --check` 通过;`build-mcn-suite.cjs client` 自检全绿(load=1 / collect=5 / `exports.default`=0) |
| B | 产物核验 | ✅ `dist/dsh-plugin-mcn-suite-0.3.11.tgz`(436 条目 / 1.90 MB / md5 `0b84b3bc…`);顶层只有 `package/`,无 `.bak`/`node_modules`/`tgz`;`portal-entry-0.5.6.tgz`(4 文件,两个半边都在) |
| C | 与线上旧产物的差异面 | ✅ 仅 9 hunk / 51 行,全部为本次改动(见 §二 2.3 注) |
| D | 投放 | ✅ admin:`pnpm add` 实装 **0.3.11**(bundles=7 含本包)· `portal-entry` 实装 **0.5.6**;旧产物归档 `business-plugins/.bak/dsh-plugin-mcn-suite-0.3.10.tgz` |
| E | **浏览器实测(三段式)** | ✅ ① 点「MCN工作台」⇒ `hash=#/mcn`、`[data-mcn-split]` 与 `[data-mcn-panel]` 均出现、面板正文为「MCN 工作台 / 热点数据 / 账号列表 / AI写脚本 / 脚本诊断」;② 点 header 的「MCN任务会话」图标 ⇒ 面包屑「MCN 工作台 / MCN任务会话」、页标题与计数正常;③ 左侧栏**已无**独立「MCN任务会话」行;④ 语言:初始 `select=zh`(**修前是 en**,界面却是中文)、选 English ⇒ `lang=en` 且整站变英文、选 中文 ⇒ `lang=zh-CN` 且回中文;⑤ 持久化:`<home>/settings.yaml` 出现 `locale: preference: zh` |
| F | 平台侧校验 | ✅ `scripts/verify-portal-entry.mjs` **全绿(28 条)**(本轮把「快照对象取 `.active`」补成断言,防回退) |
| G | 收尾 | ✅ 测试会话已删(PG `sessions where user_agent='poc-curl2'` = 0);服务器 `/tmp` 暂存件已清 |
---
## 四、边界 / 未覆盖
1. ✅ **guest(实例在 w-106)已补齐(2026-09-20 09:1x–09:3x,同一会话内追加)**:106 上 `@dsh-local/portal-entry`
已从 **0.5.5 → 0.5.6**(`pnpm add` 成功、`dsh.profile.bundles` 含本包、包内 `client.js` 命中 `v = v.active`),
实例停过后由平台按需拉起;**浏览器实测**:初始态 `document.documentElement.lang` = `zh-CN` 且下拉 = `zh`(**修前恒显示 en**),
切 English ⇒ `lang=en` + 下拉 `en`(一致)⇒ 修复在 guest 同样生效。
⚠️ `dsh-plugin-mcn-suite` 在 106 上**仍未安装** —— 它本来只有 admin 装(MCN 工作台是 admin 的自研插件),不是遗漏。
手段 = 新脚本 **`scripts/install-plugin-for-user.cjs`**(见档案 144 §二:把"给某个用户装某个 tgz"收敛成**机器无关的原子动作**)。
2. `dsh` 版本契约(槽位名 / locale API)属**跨版本耦合点**:这次是"改名"型破坏,插件侧已做成双名兼容;
若 0.1.6 再改名,`CONVERSATION_SLOT_SELECTORS` 是唯一落点(一处集中维护)。
---
## 五、可复用结论(跨会话)
- 🔴 **「点了没反应」先查宿主契约**:MCN 工作台靠 `document.querySelector('[data-slot="…"]')` 找宿主 ⇒ **槽位名是外部契约**,
dsh 升级后**必须**用浏览器确认名字(本次 `conversation` → `main.conversation`)。判据:`[data-mcn-panel]` 是否出现。
- 🔴 **官方 locale 是"两形态"API**:`getLocale()` 在 0.1.5-rc.1 返回**快照对象**;凡读当前语言必须取 `.active`。
表现具有欺骗性:**下拉显示 English 但界面是中文** ⇒ 别按"界面语言对不对"判断,要看 `document.documentElement.lang` + select 的 `value`。
- 🔴 **重打包前先做"产物差异面"核验**:把新产物与**线上在跑的那份**做 `diff`,确认差异只含本次改动 ——
本次正是靠它抓到 A/B/C 三处"一构建就负向回归"(计划任务复活 / 死链菜单项 / 历史 tgz 打进包)。
- 🔧 **浏览器实测的可行姿势**:`mksess.cjs` 造 admin 会话 → `agent-browser`:`set headers` 注 Cookie **不生效**,
改用 `open https://ai1net.com/login.html` + `eval document.cookie='sid=…; domain=.ai1net.com; path=/'` → 再 `open` 实例子域。
另注:`agent-browser` 在本机**前台会被沙箱杀(SIGTERM)**,用 `run_in_background` 起一次(守护进程常驻)后,后续命令加
`> 文件 2>&1`(**不走管道**)即可前台跑。
- 🔧 **手动跑平台脚本要带运行环境**:`/etc/dshs.env` + `dshs.service.d/*.conf` 的 `Environment=`(否则 `DSH_PLATFORM_DIR` 缺省,
`artifactDir()` 会落到 `/root/.dshs/platform/artifacts`)。脚本模板见 `.workbuddy/tmp/run-with-platform-env.sh`。