Files
dsh_shenxian/dsh-server-docs/07-实例UI分区登记表.md
T
admin 3efd68517f chore: 并入已删除会话的在途成果(防丢失;原会话已删,未做功能验收)
**背景**:这些改动原属本工作区另外几个会话(T01/T02 等),**那些会话已被用户删除** ⇒
工作树里的成果处于"无主"状态,一次错误 checkout / 覆盖即**永久丢失** ⇒ 代入库保全。
口径遵循本项目**先例**(`39a1f2e` / `b617cdb`:**别人的活,代入库并在提交信息里注明**)。

**内容**:档案 101「能力管理」改名 + 页内 tab 分页|档案 102 语言切换搬入「用户设置」|
`07-实例UI分区登记表.md`|`scripts/find-ui*.mjs`(UI 元素定位工具)|`poc/portal-entry/`(0.5.3)|
`src/web/locale-pref.ts` + `home-files.ts`(语言偏好持久化)|`test/locale-pref.test.mjs`|
`package.json`|`BRIEF.md` / `INDEX.md` / `docs-manifest.json` / `03-路线图与待办.md` / 档案 100 增量。

**已做最小健全性检查**(⚠️ **未跑完整构建 / 单测** —— 那是原会话的验收职责,本次只求"不丢"):
- JSON 合法:`package.json` / `poc/business-plugins/package.json` / `docs-manifest.json` ✓
- 4 个 TS 文件 `{}`/`()` 配平 ✓;新增文件均非空 ✓
- 规模:13 文件改动 +340/−210,新增 12 条

**未 push**(按 §4 提交边界:用户说"提交",未说"推送")。
2026-09-15 21:17:12 +08:00

85 lines
6.7 KiB
Markdown
Raw 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.
# 07 · 实例 UI 分区登记表(settings.section 谁提供、源码在哪、能不能改)
- 日期:2026-09-15
- 触发:用户问「**为什么查代码要这么久 是不是反应 代码结构有问题或者没有 工程结构的索引文件**」——
当时为了搞清「设置面板里的『用户设置』是谁渲染的」,我在 6 个官方包 + 3 个自研包里逐个 grep,
绕了 ~30 次工具调用。**根因见 §三**(其中两条是真结构缺口)。
- 状态:✅ 表格为**现行值**;改动分区时**同步改本表**(与 `INDEX.md` 一样属于"要维护的入口")
> **本表只回答四个问题**:这个分区**id** 是什么 → **谁提供** → **源码在哪** → **我能不能改**。
> 单查某功能的实现细节仍去 `04-调整方案/`。
---
## 一、实例「设置」面板的分区总表(现行)
> **本表由 `node scripts/find-ui.mjs --md` 生成**(扫的是**活着的 profile + 官方包**,不是仓里快照)。
> ⛔ **改分区 ⇒ 同一次改动里刷新本表**。下表的 label 是从代码里**解码**出来的(含 `\uXXXX` 转义形态)。
| order | id | label | 提供者 | 来源 | 源码 / 可改性 |
|---|---|---|---|---|---|
| 0 | `general` | 通用设置 | `@deepseek-ai/dsh-client-ui-settings-general` | 官方 | 官方包,⛔ **不可改**(R2);**官方语言切换就在这一页**(`settings.general.item`) |
| 10 | `models` | (官方 locale 键) | `@deepseek-ai/dsh-client-ui-settings-models` | 官方 | ⛔ 不可改;⚠️ **被角色补丁禁用**(本环境打开必报错,档案 87) |
| 15 | `plugins` | (官方 locale 键) | `@deepseek-ai/dsh-client-ui-settings-plugins` | 官方 | ⛔ 不可改;⚠️ 角色补丁禁用 |
| 20 | `agent-presets` | (内部无 label) | `@deepseek-ai/dsh-client-ui-agent-preset` | 官方 | ⛔ 不可改 |
| 100 | `model-settings` | 模型设置 | `business-plugins` | **自研** | 仓 `poc/business-plugins/lib/client.js` ✅ **可改** |
| 101 | `business-plugins` | **能力管理** | `business-plugins` | **自研** | 同上 ✅ 可改(原「功能管理」,档案 101 改名 + tab 分页) |
| 102 | `platform-admin` | 系统管理 | `business-plugins` | **自研** | 同上 ✅ 可改(**仅 admin**) |
| 103 | `user-settings` | **用户设置** | `portal-entry` | **自研** | 仓 `poc/portal-entry/lib/client.js` ✅ 可改(账号 / **界面语言** / 退出登录) |
> 附注:官方包的 label 走各自的 locale 词典(表里显示 `t("…")` 即"未在包内解析到"),
> 而**官方那 4 个我们本来也不该改**,所以不再深挖;真要读文案去该包 `README.zh.md`。
> `preferences`(偏好设置,自研)已于 2026-09-15 **撤除**(档案 102)。
## 二、定位一个 UI 分区的**最快路径**(照这个顺序,别再绕)
1. **先看"活着的实例里装了什么"**,而不是先翻官方包:
```bash
P=/var/lib/dshs/users/<uid>/home/profiles/web
ls $P/node_modules/@dsh-local/ # 自研 bundle
grep -l "settings.section" $P/node_modules/@dsh-local/*/lib/client.js # 谁注册了分区
```
⛔ 我当时的错:先去 `/usr/local/...` 官方树里找、再去 0.1.2 备份里找、又怀疑第三方插件 —— 最后才查 profile。
2. **官方包的根**(不是 profile):
`/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/`
3. **搜中文 UI 文案必须同时搜两种形态**:
```bash
grep -rn "用户设置" . # UTF-8 字面量
grep -rn 'u7528u6237u8bbeu7f6e' . # \u 转义形态 ← portal-entry 就是这种,只搜上一条永远 0 命中
```
(可用 `python3 -c 'print(open("f").read().encode("unicode_escape").decode())'` 反推转义形态。)
4. **别被副本误导**(三处都有同名不同版本的旧拷贝):
- `dsh-server-docs/04-调整方案/poc/*` = **历史快照**(如 portal-entry 停在 0.5.1);
- profile 的 `node_modules/.pnpm/` 里堆着 `@dsh-local+business-plugins@…0.2.3/0.3.4/0.3.8/0.3.11` 等历史 tgz;
- `/opt/dsh/backups/` 下有升级前的整套官方包(如 `dsh-0.1.2-rc.1`)。
⇒ **判"现行"只认两处**:仓内 `poc/<name>/` + profile 里 `node_modules/@dsh-local/<name>/`。
---
## 三、为什么会绕这么久(诊断结论)
| # | 原因 | 性质 | 已做的处置 |
|---|---|---|---|
| 1 | 标签用 **`\uXXXX` 转义**存(`"\u7528\u6237\u8bbe\u7f6e"`),按 UTF-8 搜永远 0 命中 | **代码侧小缺陷**(可维护性) | 记入本表 §二 第 3 条;⛔ 新增文案**建议直接写中文**(官方 bundle 亦混用,但可 grep 的优先) |
| 2 | **源码没入仓**:`portal-entry` 不在 `poc/` 里,线上只有 tgz ⇒ 只能从产物反推 | **真结构缺口** | ✅ 已把 0.5.3 源码补进 `poc/portal-entry/`;**约定:产物只从仓内源码构建** |
| 3 | **没有"哪个包提供哪个 UI"的索引**,id/order/label 散在 9 个包里 | **真结构缺口** | ✅ 本文件(`07-实例UI分区登记表.md`) |
| 4 | 集群切换后"实例侧实测"变难(新用户落 `w-106`、47→106 无 SSH 路由) | 环境复杂度 | 见 `PLAYBOOK §9.1`;新用户落点见 `03-路线图` |
---
## 四、维护约定
- **改任何分区(增/删/改名/调 order)⇒ 同一次改动里更新本表**;⛔ 不要只改代码。
- 新增自研 bundle 时,**源码必须落在仓内 `poc/<name>/`**,并在本表登记。
- 本表**不写版本号**(会漂)—— 版本去 `poc/<name>/package.json` 与 `/opt/dsh/artifacts/` 看。
## 五、长效机制(2026-09-15 建,针对 §三 的三条根因)
| 根因 | 机制 | 怎么用 |
|---|---|---|
| 找不齐「谁提供哪个 UI 分区」 | **`node scripts/find-ui.mjs [关键词] [--md] [--grep]`** —— 扫活 profile + 官方包,一次给全:id / order / label(**含转义解码**)/ 提供者 / 源码路径 / **能不能改** | 改任何实例 UI 前**先跑它**(本来要 30 次 grep 的事 → 1 条命令) |
| 中文文案搜不到(`\uXXXX` 转义) | 由 `find-ui.mjs` 内建(**两种形态都搜**);`PLAYBOOK §9.2` 也记了反推转义的方法 | 手写 grep 时记得两种形态都试 |
| 自研 bundle 源码不在仓里 | **约定:`poc/<name>/` 是唯一源码位置,产物只从仓内源码构建**;`portal-entry` 已补入 | 发现某自研包不在 `poc/` ⇒ 先从部署产物取出入仓,再改 |
| 改完忘了同步断言 / 文档 | `npm run verify`(含 `verify-my-skills` / `verify-portal-entry` 的结构断言)+ **本表** | 每次改动收尾跑一次 |
| 打包把上一版 tgz 打进去(0.2.5 / 0.5.4 两次同坑) | 各包 `.npmignore` 排除 `*.tgz` + `verify-portal-entry.mjs` 里的机械断言 | 已有防线,新包照抄 |