dsh-wkgeo-ops 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +185 -3
- package/client/client.js +2128 -0
- package/cordis.patch.yml +3 -0
- package/lib/index.js +2505 -0
- package/lib/wizard.js +701 -0
- package/package.json +39 -4
- package/skill/README.md +39 -0
- package/skill/wkgeo-site-content/SKILL.md +148 -0
- package/skill/wkgeo-site-content/site-manifest.example.json +62 -0
- package/skills/wkgeo-site-build/SKILL.md +30 -0
package/README.md
CHANGED
|
@@ -1,3 +1,185 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# dsh-wkgeo-ops · DSH 插件「网站运营」
|
|
2
|
+
|
|
3
|
+
把本机 `wkgeo` CLI(`F:\cloudbase\cli\wkgeo.mjs`)的站点运营能力接进 DeepSeek Harness:
|
|
4
|
+
**agent 7 个工具** + **左侧栏「网站运营」入口(点开是中央面板)** + **右侧边栏「网站运营」面板(含三步建站向导)**。不新增任何 npm 依赖,只用 Node 内置模块。
|
|
5
|
+
|
|
6
|
+
- key / 包名 / cordis 插件名:`dsh-wkgeo-ops`
|
|
7
|
+
- 版本:0.1.0 v4(private,不发布到 npm)
|
|
8
|
+
- 宿主:DSH Web 客户端(`dsh.client.platform = "web"`)+ cordis 服务端插件
|
|
9
|
+
- v2 口径(老板 2026-10-30):**三步向导**(①站点名 ②语言 ③内容来源)+ **模板 / 网址 / 文件 三选或多选**
|
|
10
|
+
- v4 口径(老板 2026-10-30):「初始化先选**站点根目录** → **站点卡片**一个一个显示(能点进去)→ 详情里有**本地文件夹**」;不再用一张表铺列表
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. 目录结构
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
integrations/dsh-wkgeo-ops/
|
|
18
|
+
├─ package.json # manifest:main / dsh.bundle.patch / dsh.client / exports / peerDeps
|
|
19
|
+
├─ cordis.patch.yml # 装载层:- insert: id/name = dsh-wkgeo-ops
|
|
20
|
+
├─ lib/
|
|
21
|
+
│ ├─ wizard.js # 纯函数:三步向导状态机 + 来源归一 + 能力探测 + 命令构造 + 建站闸门
|
|
22
|
+
│ └─ index.js # 服务端 cordis 插件:7 个工具 + 6 条路由 + 执行层(可单测)
|
|
23
|
+
├─ client/
|
|
24
|
+
│ └─ client.js # Web 客户端:左侧栏入口 + 面板(初始化/卡片网格/详情/向导/日志 五态)
|
|
25
|
+
└─ README.md # 本文件
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 2. 三步向导(面板主流程)
|
|
29
|
+
|
|
30
|
+
| 步 | 内容 | 规则 |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| ① | **站点名** | 必填,≤60 字;回车即下一步 |
|
|
33
|
+
| ② | **语言** | 默认**中文**(`zh-CN`),可选**英文**(`en`) |
|
|
34
|
+
| ③ | **内容来源:模板 / 网址 / 文件** | 三个入口**同时摆出来**,复选框式**可单选可多选**;勾谁展开谁的输入 |
|
|
35
|
+
|
|
36
|
+
入口位置(老板口径):
|
|
37
|
+
|
|
38
|
+
- **没有站点时**:空态第一行就是整宽主按钮「**+ 创建网站(第一个)**」。
|
|
39
|
+
- **有站点时**:列表最末尾固定一行虚线「**+ 创建新网站(最后一个)**」,顶部也有「+ 创建网站」小按钮。
|
|
40
|
+
|
|
41
|
+
第三步的三种来源:
|
|
42
|
+
|
|
43
|
+
| 来源 | 角色 | 勾选后展开的输入 |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| 模板 | **设计骨架** | 模板中心下拉(默认模板 + `WKGEO_TEMPLATE_KEYS` 配置的名字)+ 手填模板名/uuid |
|
|
46
|
+
| 网址 | **结构与内容来源** | 老站 URL(`http(s)://…`) |
|
|
47
|
+
| 文件 | **结构与内容来源** | 本地目录(逐个 `*.html`)或 zip 路径 |
|
|
48
|
+
|
|
49
|
+
**合并语义**(UI 文案与文档同一份 `MERGE_SEMANTICS`,非装饰):
|
|
50
|
+
|
|
51
|
+
1. 模板 = 设计骨架;网址 / 文件 = 结构与内容来源。
|
|
52
|
+
2. 只选网址或文件 → 先用它生成模板(`template init`),再建站。
|
|
53
|
+
3. 模板 + 网址/文件 → 模板做骨架,内容按栏目灌入。
|
|
54
|
+
4. **做不到的组合必须明确标「未填充」**(`unfilled[]` + 面板黄色提示),**不许静默忽略**。
|
|
55
|
+
|
|
56
|
+
深层链接(截图 / 复现用):`?wizard=1&step=3&name=…&lang=zh-CN&sources=template,url&templateKey=…&url=…`。
|
|
57
|
+
|
|
58
|
+
## 3. 工具清单(agent 侧,7 个)
|
|
59
|
+
|
|
60
|
+
| 工具 | 参数 | 底层命令 | 返回要点 |
|
|
61
|
+
| --- | --- | --- | --- |
|
|
62
|
+
| `wkgeo_sites_list` | 无 | `sites list --json` | `{ ok, count, sites[] }`,每站 `id/name/status/shortHost/shortUrl/domain/domainVerification/provisionState/relation/cmsOnly` |
|
|
63
|
+
| `wkgeo_site_status` | `site`* | `sites get <id> --json` | `{ ok, site }`:状态、短域、域名验证(含 `verifiedAt`)、证书、备案、开通状态 |
|
|
64
|
+
| `wkgeo_site_preview` | `site`*、`path` | `preview <path> --site <id> --json` | `{ ok, url, siteId, path }` → `https://wkgeo.com/cms/preview/<站点ID>/about/` |
|
|
65
|
+
| `wkgeo_publish` | `site`*、`confirm`*、`wait` | `publish --site <id> --confirm [--no-wait] --json` | 缺 `confirm:true` **不执行**,回 `{executed:false,needsConfirm:true,reason,risk}` |
|
|
66
|
+
| `wkgeo_site_create` | `name`*、`lang`、`source`、`templateKey`、`url`、`dir`、`zipPath`、`confirm`* | 计划式执行:`sites create` →(`lang save`)→(`templates save`×N)→(`import --apply`) | 缺 `confirm:true` 只回 `{executed:false,needsConfirm:true,plan[],risk}`;有 confirm 才逐步执行,回 `{ok,siteId,steps[],unfilled[],gaps[],warnings[]}` |
|
|
67
|
+
| `wkgeo_template_from_url` | `url`*、`out`、`site`、`confirm` | `template init --from-url <url> [--out <dir>] --json`(长任务 300s) | CLI 没这个子命令时 → `{supported:false,executed:false,gap,command,fallback}`,**0 次 CLI 调用**,不假装成功 |
|
|
68
|
+
| `wkgeo_template_from_dir` | `dir`、`zipPath`、`out`、`site`、`confirm` | `template init --from-dir <dir> [--out <dir>] --json`(300s);没有该子命令时降级 `templates save` | 只给 zip → `{supported:false,gap:{code:'ZIP_UNSUPPORTED'}}`;无 `site`/`confirm` → `needsConfirm:true` + 将执行的命令清单 |
|
|
69
|
+
|
|
70
|
+
`*` = 必填。实现细节:
|
|
71
|
+
|
|
72
|
+
- **`parameters` 必须是 raw JSON Schema**(`{ type:'object', properties, required }`),由 `paramsSchema(properties, required)` 统一生成,`required` 恒输出;传「属性名 → 属性 schema」的映射会被模型 API 判 `schema must be a JSON Schema of 'type': "object", got 'type: null'`(`INVALID_REQUEST`,整轮被打回)。回归脚本:`verify/tool-schema.mjs`(用 DSH 随包的 ajv 编译 7 个 schema,期望 `RESULT: ALL PASS`、exit 0)。
|
|
73
|
+
- 一律 `spawn(node, [cli, ...args])`(`shell:false`、`windowsHide:true`);**普通命令硬超时 30s**,**长任务(模板生成 / 建站 / 导入)300s**(`LONG_TIMEOUT_MS`),超时 `SIGKILL` 回 `code:"TIMEOUT"`;stdout 上限 4MB。
|
|
74
|
+
- 只解析 CLI 的 JSON 信封;失败只回 `error.code/message/hint`,**不打印任何 token、不落日志**。
|
|
75
|
+
- node 解析顺序:`WKGEO_NODE_BIN` → `process.execPath`(仅当是 `node.exe`)→ `node`;CLI 路径可用 `WKGEO_CLI` 覆盖,默认 `F:\cloudbase\cli\wkgeo.mjs`。
|
|
76
|
+
- **能力探测**(10 分钟缓存):读 `template init --help` / `sites create --help` / `import --help` 文本,判断 `--from-url`、`--from-dir`、`--lang`、`--url` 是否真的存在;**探测不到就不硬塞参数**,改走降级路径并在返回里标 `capabilities`。
|
|
77
|
+
- 模板中心下拉的选项来自 `WKGEO_TEMPLATE_KEYS`(逗号分隔的内置模板名/uuid)+ 一个「默认模板(不指定)」+ 手填框;CLI 没有「列模板」的命令,缺口见 §7。
|
|
78
|
+
|
|
79
|
+
## 4. 面板(Web 客户端侧)
|
|
80
|
+
|
|
81
|
+
- **左侧栏入口(v3)**:`sidebar.panellist`(`id: wkgeo-ops`、`order: 30`、图标 `OpsIcon`)+ `main`(`key: wkgeo-ops`,渲染同一个 `PanelBody`)。两条的 id/key 必须相同:①只注册就有点不开、②只注册就先没图标;**装插件本身不会自动往左栏加菜单,这两条必须自己写**。停用插件时若该面板正激活,先 `layout.selectPanel(null)` 把界面交还对话。
|
|
82
|
+
- 注册 `sidebarRightTabs`(`id: wkgeo-ops`、`priority: fallback`)+ `sidebar.right.pane.tab` / `.title` 两个 slot,与 `dsh-bili-panel` 范式一致;右栏页签与左栏入口渲染的是**同一个** `PanelBody`。
|
|
83
|
+
- **五态(v4)**:
|
|
84
|
+
1. **初始化**(本机还没设站点根目录时):一张居中卡片「第一步:先选站点根目录」——手输绝对路径,或点「选择根目录」进目录浏览器一层层点。**强制第一步、不能跳过**:根目录没设就只显示这张卡,不给卡片列表(唯一例外是服务端 config 接口不可用 `cfgDown`,那时退回列表并在顶栏提示「接口不可用」)。
|
|
85
|
+
2. **卡片网格**:一个站一张卡(站名 + 状态 pill + 主机链接 + 类型/验证/短码 tags + 底部「📁 本地文件夹」行),末尾虚线「+ 新建站点」卡;整张卡可点。
|
|
86
|
+
3. **详情**:点卡进去 → 返回按钮 + 站点信息 7 行 + 本地文件夹面板(绝对路径 / 相对根目录 / HTML 文件清单 / 换文件夹 / 重新扫描 / 打开站点)。
|
|
87
|
+
4. **向导**(三步,见 §2)、5. **执行日志**。
|
|
88
|
+
- **目录选择器是固定浮层弹窗(v4.1)**:`position: fixed` 全屏遮罩 + 720px 白卡(`role="dialog"`、`aria-modal`),点遮罩即取消;顶部手输路径 + `↑ 上一级` + `→` 跳转,中间子目录列表、底部「取消 / 用这个目录」。**不要改回普通区块**:面板容器高度有限,内联区块会被挤成 0 高(老板 2026-10-30 报「点了没弹出选择器」,根因见下一条)。
|
|
89
|
+
- **真 React 两个坑(v4.1 修)**:① 目录取数的 `useEffect` **必须带依赖数组 `[path]`**——无依赖写法每轮渲染都重跑,React 先执行上一轮清理把 `alive` 置 false,首个 fetch 响应被丢弃且守卫拦住重试,表现就是永远停在「读取目录中…」(自写的轻量垫片不复现,真 React 必现);② 受控输入框用 `onChange`,不要用 `onInput`(真 React 里等价只读)。
|
|
90
|
+
- **页签 guide 的 title / description 必须是函数(v4.2 修,事故级)**:`sidebarRightTabs.register({ guide: [{ title: '站点状态' }] })` 这种**字符串写法**会让 DSH 在渲染右栏 guide 时抛 `TypeError: entry.title is not a function`;它发生在右栏同一个 React 树里 → **整个右侧栏被卸载成一片空白**(连 DSH 自带的「开始」页签内容也没了),左侧栏 / 中央面板不受影响。正确写法 `title: () => '…'`(dsh-image-gen 即如此),本仓库再用 `asLabel()` 兜底。回归:`node integrations/dsh-wkgeo-ops/verify/panel-registration.mjs` → `RESULT: ALL PASS`。
|
|
91
|
+
- **v5(2026-10-30):面板根节点自己撑满宽度** —— `STYLE.wrap` 必须带 `width:'100%'; minWidth:0; flex:'1 1 auto'`,顶栏 `STYLE.bar` 带 `flexWrap:'wrap'`、标题/计数 `whiteSpace:'nowrap'`;否则在右栏(flex 项、宽度窄)里整块会收缩成一竖条。
|
|
92
|
+
- **v5:右栏与中央共用同一个入口组件 `OpsPanel`**(apply 内定义:`h(PanelBoundary, null, h(PanelBody, ctx))`),两处槽位都直接传这个组件(和 `dsh-bili-panel` 同形),**不要再套 PaneShell 之类的额外外壳**;面板标题后有一个 `v5` 小标记,用来确认客户端加载的是哪一版。
|
|
93
|
+
|
|
94
|
+
- 取数路由(服务端自注册、与 DSH GUI 同源):
|
|
95
|
+
- `GET /wkgeo-ops/sites`(`?refresh=1` 强刷,默认 15s 缓存)
|
|
96
|
+
- `GET /wkgeo-ops/templates` → `{ok, choices[], manual, note, gap, mergeSemantics[]}`
|
|
97
|
+
- `POST /wkgeo-ops/site-create` → `application/x-ndjson` 逐步流(先 `{type:'plan'}` 再 `{type:'step'}`…最后 `{type:'done'}`);**缺 `confirm:true` 一律 200 + `needsConfirm:true`,不执行**;非 POST → 405。
|
|
98
|
+
- **`GET|POST /wkgeo-ops/config`**(v4):读/写本机站点根目录。GET → `{ok, rootDir, exists}`;POST `{rootDir}` 保存(相对路径 400 `ROOT_NOT_ABSOLUTE`、不存在 400 `ROOT_MISSING`、不是目录 400 `ROOT_NOT_DIR`);`{rootDir:''}` 清空。
|
|
99
|
+
- **`GET /wkgeo-ops/browse?path=`**(v4):目录选择器数据源,回 `{ok, path, parent, dirs[], files[], htmlCount, insideRoot}`。**设了根目录后只允许浏览根目录之内**(越界 403 `OUTSIDE_ROOT`);没设根目录时可从家目录/盘符起随便翻。
|
|
100
|
+
- **`GET|POST|DELETE /wkgeo-ops/site-folder`**(v4):站点 ↔ 本地文件夹映射。GET 无参回全部 `folders{}`、`?site=<id>` 回单站(含 `rel`/`exists`/`htmlCount`/`files[]`,未绑定 `bound:false`);POST `{siteId, dir}` 绑定(要求已有根目录 `ROOT_UNSET`、绝对路径 `DIR_NOT_ABSOLUTE`、在根目录内 `OUTSIDE_ROOT`、目录真实存在 `DIR_MISSING`/`DIR_NOT_DIR`);DELETE `?site=<id>` 解绑。
|
|
101
|
+
- **存储位置**:`<DSH_PROFILE_DIR 或 ~/.dsh>/wkgeo-ops/config.json`,形状 `{ rootDir, folders: { [siteId]: dir }, updatedAt }`。**只存本机**,不上传、不写进站点、不进 CLI。
|
|
102
|
+
- 样式只用 `--dsw-alias-*` CSS 变量,不引外部资源、不引 CSS 文件。
|
|
103
|
+
- 拿不到 `webServer` 服务时只跳过路由(面板顶栏提示「接口不可用」并退回列表),**7 个工具照常可用**。
|
|
104
|
+
|
|
105
|
+
## 5. 安装(老板侧)
|
|
106
|
+
|
|
107
|
+
前置:`wkgeo` CLI 已登录(`node F:\cloudbase\cli\wkgeo.mjs login`),DSH 已在运行。
|
|
108
|
+
|
|
109
|
+
**A. 拷贝插件(必做)**
|
|
110
|
+
|
|
111
|
+
```powershell
|
|
112
|
+
Copy-Item -Recurse -Force 'F:\cloudbase\integrations\dsh-wkgeo-ops' "$env:USERPROFILE\.dsh\plugins-src\dsh-wkgeo-ops"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**B. 让 DSH 装载它(二选一)**
|
|
116
|
+
|
|
117
|
+
1. **有插件安装 UI**(DSH 设置里的插件页,「从本地目录安装」):选到 `%USERPROFILE%\.dsh\plugins-src\dsh-wkgeo-ops`,装上后重启 DSH。
|
|
118
|
+
2. **手动挂 profile**(只需两处,**不用**改 `cordis.patch.yml`):
|
|
119
|
+
- `%USERPROFILE%\.dsh\profiles\desktop\package.json` 的 `dependencies` 加
|
|
120
|
+
`"dsh-wkgeo-ops": "file:C:/Users/Administrator/.dsh/plugins-src/dsh-wkgeo-ops"`
|
|
121
|
+
- 同文件 `dsh.profile.bundles` 数组加一项 `dsh-wkgeo-ops`
|
|
122
|
+
- 重启 DSH。
|
|
123
|
+
|
|
124
|
+
> `cordis.patch.yml` 里**不需要**再写 `- id: dsh-wkgeo-ops`:`dsh.profile.bundles` 里的包是按 bundle 层挂载的,包内自带的 `cordis.patch.yml` 会自动应用(本机 profile 的 patch 文件里就没有该条目,插件照样正常加载)。
|
|
125
|
+
|
|
126
|
+
**C. 验证(装完应同时出现两处入口 + 7 个工具)**
|
|
127
|
+
|
|
128
|
+
| 位置 | 现象 |
|
|
129
|
+
|---|---|
|
|
130
|
+
| **左侧栏** | 第 5 个图标(显示器+双卡片,`order: 30`,排在「工作台」后面);点它 → 中央区渲染「网站运营」面板 |
|
|
131
|
+
| 右侧栏 | 「网站运营」页签(与左栏入口并存,两条路都能进) |
|
|
132
|
+
| 对话 | agent 调 `wkgeo_sites_list` 返回站点数组 |
|
|
133
|
+
|
|
134
|
+
左栏入口是插件自己注册的(`client/client.js` 的 `sidebar.panellist` + `main` 两个槽位、共用 id `wkgeo-ops`),**装插件本身不会自动往左栏塞菜单**——所以看到图标就说明这版代码已生效;只看到右侧栏页签则说明装的是旧版(左栏入口是 2026-10-30 加的)。
|
|
135
|
+
|
|
136
|
+
**D. 别人(另一台机器 / 另一个 profile)首次安装的差异**
|
|
137
|
+
|
|
138
|
+
- 左栏 / 右栏入口与工具都随包走,**换机器一样出现**;`client` 侧不依赖本机路径。
|
|
139
|
+
- ⚠️ **唯一本机相关的东西是 wkgeo CLI 路径**:`lib/index.js` 的 `DEFAULT_CLI_PATH` 默认 `F:\cloudbase\cli\wkgeo.mjs`。别人机器上 CLI 调不通时,设环境变量 `WKGEO_CLI=<其仓库>/cli/wkgeo.mjs`(`WKGEO_NODE_BIN` 可指定 node)后重启 DSH 即可——左栏图标仍然在,只是面板取数会报 `SPAWN_FAILED`。
|
|
140
|
+
- 插件中心卡片**没有图标和本地化描述**(包内暂无 `locale/` 与 `icon` 导出),不影响功能。
|
|
141
|
+
- 已发布公共 npm:`npm i dsh-wkgeo-ops` / 插件中心填 `dsh-wkgeo-ops`(v0.2.0 起可装);本仓库目录安装仍可拷目录 / `file:` 依赖。
|
|
142
|
+
|
|
143
|
+
## 6. 自测
|
|
144
|
+
|
|
145
|
+
```powershell
|
|
146
|
+
node --check integrations\dsh-wkgeo-ops\lib\index.js # exit 0
|
|
147
|
+
node --check integrations\dsh-wkgeo-ops\lib\wizard.js # exit 0
|
|
148
|
+
node --check integrations\dsh-wkgeo-ops\client\client.js # exit 0
|
|
149
|
+
node .tmp-build\t159\smoke.mjs # SMOKE OK — 40 checks passed / exit 0
|
|
150
|
+
node .tmp-build\t161\api-test.mjs # 23/23 PASS · RESULT: ALL PASS / exit 0(v4 三条新路由)
|
|
151
|
+
node .tmp-build\t161\shoot.mjs # SHOTS=5 / exit 0(v4 五张截图)
|
|
152
|
+
node .tmp-build\t162\repro.mjs # 真 React 18 全流程:init → 浮层选根目录 → 卡片 → 详情 → 绑定文件夹,打印 CLICK_*/AFTER_* 文本、ERRS=[]
|
|
153
|
+
node integrations/dsh-wkgeo-ops/verify/panel-registration.mjs # 页签/面板注册静态断言(guide 必须函数、左栏两条、错误边界)· RESULT: ALL PASS
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
smoke 的 40 项断言分组(v2 起的回归基线):①三文件 `node --check` ②manifest + exports + peerDeps ③`cordis.patch.yml` ④v1/v2 纯函数导出 ⑤列表/详情/预览解析 ⑥publish 闸门(缺 confirm 0 次 CLI)⑦**七个工具齐 + `name/confirm` 必填内联** ⑧**建站闸门:缺 confirm → `needsConfirm:true` + 0 次 CLI** ⑨**四种来源组合的命令序列**(模板 / 网址 / 文件 / 模板+网址,含 from-url 先于 create)⑩**三步向导状态机**(不能跳步 / 语言默认中文 / 多选至少一项 / 三步走完)⑪zip 与 from-url 缺口 ⑫三条面板路由 ⑬文件扫描 ⑭客户端 `__internal` 纯函数与深链还原。
|
|
157
|
+
|
|
158
|
+
`t161/api-test.mjs`(v4)用临时 store 文件起本地 HTTP 服务,断言:config 初始空 / 相对路径 `ROOT_NOT_ABSOLUTE` / 不存在 `ROOT_MISSING` / 保存落盘;browse 默认落根目录且 `insideRoot` / 越界 403 `OUTSIDE_ROOT`;folder 绑定 `rel`/`htmlCount`/`index.html` 排最前 / `?site=` 单站 / 全量映射 / 未绑定 / 越界 403 / `DIR_MISSING` / `DIR_NOT_ABSOLUTE` / DELETE 解绑;`isPathInside`/`relToRoot` 四个纯函数。
|
|
159
|
+
|
|
160
|
+
面板渲染证据(不装进真 DSH,用本地静态服务 + Chrome headless 截真实 `client.js`):
|
|
161
|
+
|
|
162
|
+
```powershell
|
|
163
|
+
node .tmp-build\t161\preview.mjs # 打印 PANEL_URL / BROWSE_URL / CARDS_URL / DETAIL_URL / REAL_URL
|
|
164
|
+
node .tmp-build\t161\shoot.mjs # 自动起服务 + Chrome headless(CDP) 1440×900 截五张
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
- 初始化(先选站点根目录):`.tmp-build\t161\shot-init.png`
|
|
168
|
+
- 目录选择器(一层层点):`.tmp-build\t161\shot-browse.png`
|
|
169
|
+
- 卡片网格(状态 pill / tags / 本地文件夹行 / +新建卡):`.tmp-build\t161\shot-cards.png`
|
|
170
|
+
- 站点详情(站点信息 + 本地文件夹清单):`.tmp-build\t161\shot-detail.png`
|
|
171
|
+
- 真实 CLI 的 23 个站点渲染成卡片:`.tmp-build\t161\shot-real.png`
|
|
172
|
+
|
|
173
|
+
`t162/repro.mjs` 是**真 React 18**(unpkg UMD,存在 `.tmp-build\t162\vendor`)的端到端复现:自起 http 服务发真实 `client.js` + mock 五条路由,Chrome headless 里按文字点按钮、取 innerText、收集 `window.onerror`,跑完打印 `AFTER_USE_TEXT`(=卡片)`AFTER_CARD_TEXT`(=详情)`BOUND_TEXT`(=已绑定文件夹)与 `ERRS3=[]`;产物 `after.png`(浮层)/`after-use.png`/`after-card.png`/`after-bind-modal.png`/`after-bound.png`。**改面板交互后先跑这个**,轻量垫片(t161/t159)复现不了 effect 时序类 bug。
|
|
174
|
+
|
|
175
|
+
## 7. 已知限制 / 未验证项(如实记录)
|
|
176
|
+
|
|
177
|
+
1. **CLI 没有 `template init`**:`wkgeo template init --from-url/--from-dir`(task-42)**尚未合入** `cli/`,`template init` 现报 `usage` 错误。所以「网址/文件 → 生成模板」这一步现在**只能降级**:网址 → `import --url … --apply`(灌内容,骨架仍是默认模板,返回 `unfilled:[{kind:'template'}]`);文件 → 逐个 `templates save`。CLI 支持后会自动切换(能力探测),插件代码不用改。
|
|
178
|
+
2. **`sites create` 没有 `--lang`**:真实 CLI 会报「不认识的参数:--lang」。所以英文站走「建站后 `lang save --code en --name 英文 --site <id> --confirm`」;默认中文不额外调用。探测到 CLI 将来支持 `--lang` 会自动加。
|
|
179
|
+
3. **zip 不支持**:Node 内置无解压、CLI 也无 `templates import --zip`;插件明确回 `ZIP_UNSUPPORTED`,不假装成功。
|
|
180
|
+
4. **模板中心列表拿不到**:CLI 没有列内置模板的命令(`templates list` 列的是**某站点自己的 html**)。下拉只能给「默认模板 + `WKGEO_TEMPLATE_KEYS` + 手填」;`--template` 真正匹配的是 DB `public.cms_template`(`source='builtin'`)的 **name 或 id**。
|
|
181
|
+
5. **`import` 需运维权限**:它走 service_role 直连库(本机 `tencent/cloudbase/import-site.mjs`),客户/AI 账号不该用;插件只用它做「网址来源」的降级,且会同时标未填充项。
|
|
182
|
+
6. **已装进真实 DSH**(`%USERPROFILE%\.dsh\plugins-src\dsh-wkgeo-ops`,profile 里是 `file:` 依赖 → pnpm **link**,别删/挪该目录):左栏「网站运营」入口已实测出现在运行中的 GUI 里。但 **服务端 `lib/index.js` 的改动必须重启 DSH 才生效**(路由在 `apply()` 里注册,进程内模块已缓存):v4 的三条新路由在未重启的实例上会 404,面板顶栏会提示「接口不可用」。`client/client.js` 的改动可以热重载、不用重启。
|
|
183
|
+
7. **`wkgeo_publish` / `wkgeo_site_create` 未在真实环境执行过**(破坏性写操作,只做注入假 CLI 的链路测试)。
|
|
184
|
+
8. 面板截图里的列表用**真实 23 个站点**(`shot-real.png`),不是造的数据;卡片网格/详情/初始化三张用固定的 5 个假站点。
|
|
185
|
+
9. **站点 ↔ 本地文件夹是本机私有映射**:wkgeo 站点模型里没有「本地目录」字段,映射只存在 `<DSH_PROFILE_DIR>/wkgeo-ops/config.json`(根目录只能设一个、文件夹必须在根目录之内)。换机器 / 换 profile 要重新设根目录并重绑;不会随站点同步。
|