@linxin666/dsh-remote-web-ui 0.1.13 → 0.1.15
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.i18n.yaml +2 -2
- package/README.md +5 -2
- package/README.zh.md +1 -1
- package/lib/client.js +30 -17
- package/lib/client.js.map +1 -1
- package/lib/index.js +177 -34
- package/lib/mobile.js +44 -25
- package/lib/mobile.js.map +1 -1
- package/lib/types/client/PluginSettingsCard.d.ts +26 -11
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PluginSettingsCard.js +27 -7
- package/lib/types/client/locales.js +2 -2
- package/lib/types/client/settings-form.d.ts +14 -5
- package/lib/types/client/settings-form.d.ts.map +1 -1
- package/lib/types/client/settings-form.js +38 -10
- package/lib/types/mobile/mux.d.ts +13 -4
- package/lib/types/mobile/mux.d.ts.map +1 -1
- package/lib/types/mobile/mux.js +50 -30
- package/lib/types/mobile/mux.test.js +75 -6
- package/lib/types/mobile-api.d.ts +2 -0
- package/lib/types/mobile-api.d.ts.map +1 -1
- package/lib/types/mobile-api.js +4 -1
- package/lib/types/routes.d.ts +17 -0
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +49 -10
- package/lib/types/update.d.ts +5 -1
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +122 -26
- package/package.json +1 -1
- package/src/client/PluginSettingsCard.tsx +83 -17
- package/src/client/locales.ts +2 -2
- package/src/client/settings-card.module.css +6 -0
- package/src/client/settings-form.ts +41 -9
- package/src/mobile/mux.test.ts +84 -6
- package/src/mobile/mux.ts +46 -25
- package/src/mobile-api.ts +6 -1
- package/src/routes.ts +51 -10
- package/src/update.ts +116 -26
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# node scripts/verify-docs.mjs --write <dir>
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 97f5f6b000e12fd89ad8723fd25306075a10df06
|
|
6
|
+
README.zh.md: 30c7d55a4f31e914091318c3205d23f3b9979f60
|
package/README.md
CHANGED
|
@@ -39,8 +39,11 @@ actions, and the update panel that probes and runs the update.
|
|
|
39
39
|
phone icon) opens the update panel, which probes the npm registry for the
|
|
40
40
|
installed `@linxin666/dsh-*` family releases. When a newer release exists
|
|
41
41
|
the panel runs the update automatically (`pnpm update` inside the owning
|
|
42
|
-
dsh profile;
|
|
43
|
-
|
|
42
|
+
dsh profile; when pnpm is missing it falls back to `corepack pnpm` and
|
|
43
|
+
then `npx --yes pnpm`, and on Windows the command runs through `cmd.exe`
|
|
44
|
+
so npm-installed `.cmd` shims resolve; the loopback-only
|
|
45
|
+
`/api/update/status` + `/api/update/run` endpoints drive it) and asks for
|
|
46
|
+
a dsh web restart to pick it up. Local
|
|
44
47
|
link installs (development mode) are detected and report the npm state
|
|
45
48
|
without updating.
|
|
46
49
|
|
package/README.zh.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- **手机侧**:扫码将手机与一次性、限时令牌绑定,并落地到 **`/m` 独立移动端界面**——一款专为小屏设计的轻客户端(见[截图](#截图)),而不是把桌面 UI 塞进手机。链接携带 `workspace` 参数,手机落地到桌面正在查看的同一工作区。
|
|
14
14
|
- **安全**:一个有效的一次性令牌(刷新会使旧链接失效;已接受的令牌不可复用;令牌会过期)。停止会撤销每一台已配对设备与当前令牌——已配对设备在下一次请求时被切断。当插件 `requirePairingForLan` 门开启(默认)时,每个非 loopback 的 `/api` 请求必须携带有效的已配对设备 cookie,因此二维码是进入暴露在局域网上的 dsh web 的唯一途径。
|
|
15
15
|
- **实时状态**:桌面面板经 SSE 流实时镜像配对状态(等待 → 已连接 → 已断开)。
|
|
16
|
-
- **远程更新**:侧边栏底部的下载触发按钮(手机图标左侧)打开更新面板,它探测 npm registry 上已安装的 `@linxin666/dsh-*` 全家桶版本。当存在较新版本时,面板自动执行更新(在所属 dsh profile 内 `pnpm update
|
|
16
|
+
- **远程更新**:侧边栏底部的下载触发按钮(手机图标左侧)打开更新面板,它探测 npm registry 上已安装的 `@linxin666/dsh-*` 全家桶版本。当存在较新版本时,面板自动执行更新(在所属 dsh profile 内 `pnpm update`;pnpm 缺失时依次回退 `corepack pnpm`、`npx --yes pnpm`,Windows 上经 `cmd.exe` 执行以解析 npm 安装的 `.cmd` shim;由仅 loopback 的 `/api/update/status` + `/api/update/run` 端点驱动)并请求重启 dsh web 以生效。本地 link 安装(开发模式)会被探测到,只报告 npm 状态而不更新。
|
|
17
17
|
|
|
18
18
|
## 截图
|
|
19
19
|
|
package/lib/client.js
CHANGED
|
@@ -2217,7 +2217,7 @@ window.__ModuleLoader__.load({
|
|
|
2217
2217
|
}
|
|
2218
2218
|
//#endregion
|
|
2219
2219
|
//#region \0dsh-css:packages/dsh-remote-web-ui/src/client/settings-card.module.css.mjs
|
|
2220
|
-
const css = ".Kwoi6G_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.Kwoi6G_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.Kwoi6G_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Kwoi6G_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Kwoi6G_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Kwoi6G_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Kwoi6G_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Kwoi6G_chevronOpen{transform:rotate(180deg)}.Kwoi6G_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.Kwoi6G_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.Kwoi6G_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.Kwoi6G_discard,.Kwoi6G_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Kwoi6G_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Kwoi6G_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Kwoi6G_discard:disabled,.Kwoi6G_save:disabled{opacity:.4;cursor:default}.Kwoi6G_discard:focus-visible,.Kwoi6G_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Kwoi6G_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.Kwoi6G_field+.Kwoi6G_field{border-top:1px solid var(--dsw-alias-border-l2)}.Kwoi6G_head{align-items:center;gap:8px;display:flex}.Kwoi6G_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.Kwoi6G_badges{align-items:center;gap:8px;display:inline-flex}.Kwoi6G_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.Kwoi6G_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.Kwoi6G_reset:disabled{cursor:default}.Kwoi6G_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.Kwoi6G_input,.Kwoi6G_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_input:focus-visible,.Kwoi6G_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.Kwoi6G_input:disabled,.Kwoi6G_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.Kwoi6G_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.Kwoi6G_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.Kwoi6G_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.Kwoi6G_card,.Kwoi6G_header,.Kwoi6G_chevron,.Kwoi6G_chevronOpen,.Kwoi6G_discard,.Kwoi6G_save{transition:none}}";
|
|
2220
|
+
const css = ".Kwoi6G_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.Kwoi6G_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.Kwoi6G_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Kwoi6G_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Kwoi6G_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Kwoi6G_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Kwoi6G_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Kwoi6G_chevronOpen{transform:rotate(180deg)}.Kwoi6G_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.Kwoi6G_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.Kwoi6G_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.Kwoi6G_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.Kwoi6G_discard,.Kwoi6G_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Kwoi6G_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Kwoi6G_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.Kwoi6G_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Kwoi6G_discard:disabled,.Kwoi6G_save:disabled{opacity:.4;cursor:default}.Kwoi6G_discard:focus-visible,.Kwoi6G_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Kwoi6G_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.Kwoi6G_field+.Kwoi6G_field{border-top:1px solid var(--dsw-alias-border-l2)}.Kwoi6G_head{align-items:center;gap:8px;display:flex}.Kwoi6G_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.Kwoi6G_badges{align-items:center;gap:8px;display:inline-flex}.Kwoi6G_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Kwoi6G_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.Kwoi6G_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.Kwoi6G_reset:disabled{cursor:default}.Kwoi6G_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.Kwoi6G_input,.Kwoi6G_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_input:focus-visible,.Kwoi6G_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.Kwoi6G_input:disabled,.Kwoi6G_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.Kwoi6G_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Kwoi6G_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.Kwoi6G_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.Kwoi6G_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.Kwoi6G_card,.Kwoi6G_header,.Kwoi6G_chevron,.Kwoi6G_chevronOpen,.Kwoi6G_discard,.Kwoi6G_save{transition:none}}";
|
|
2221
2221
|
const tagId = "@linxin666/dsh-remote-web-ui/settings-card.module.css";
|
|
2222
2222
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2223
2223
|
const tag = document.createElement("style");
|
|
@@ -2258,12 +2258,12 @@ window.__ModuleLoader__.load({
|
|
|
2258
2258
|
//#endregion
|
|
2259
2259
|
//#region src/client/PluginSettingsCard.tsx
|
|
2260
2260
|
/**
|
|
2261
|
-
*
|
|
2262
|
-
* plugin and what its settings govern, the controls inside, and the save
|
|
2263
|
-
* writes them. Renders nothing while the namespace is unavailable — a
|
|
2261
|
+
* Family-shared chrome for plugin settings cards: a disclosure header naming
|
|
2262
|
+
* the plugin and what its settings govern, the controls inside, and the save
|
|
2263
|
+
* that writes them. Renders nothing while the namespace is unavailable — a
|
|
2264
2264
|
* deployment that does not compose the owning plugin should show no trace of
|
|
2265
|
-
* it.
|
|
2266
|
-
*
|
|
2265
|
+
* it. Inlined into each consumer's client bundle; mirrors the official
|
|
2266
|
+
* ui-plugin-config PluginCard in a self-contained slice.
|
|
2267
2267
|
*/
|
|
2268
2268
|
/**
|
|
2269
2269
|
* Render one plugin settings card.
|
|
@@ -2275,6 +2275,7 @@ window.__ModuleLoader__.load({
|
|
|
2275
2275
|
const { state } = props;
|
|
2276
2276
|
if (!state.available) return null;
|
|
2277
2277
|
const title = props.t(props.titleKey);
|
|
2278
|
+
const description = props.t(props.descriptionKey);
|
|
2278
2279
|
const blocked = !state.dirty || state.invalid || state.saving;
|
|
2279
2280
|
const cardClass = open ? `${settings_card_module_css_default.cardOpen} ${settings_card_module_css_default.card}` : settings_card_module_css_default.card;
|
|
2280
2281
|
if (!state.exposed) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
@@ -2291,10 +2292,12 @@ window.__ModuleLoader__.load({
|
|
|
2291
2292
|
className: settings_card_module_css_default.headText,
|
|
2292
2293
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2293
2294
|
className: settings_card_module_css_default.name,
|
|
2295
|
+
title,
|
|
2294
2296
|
children: title
|
|
2295
2297
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2296
2298
|
className: settings_card_module_css_default.description,
|
|
2297
|
-
|
|
2299
|
+
title: description,
|
|
2300
|
+
children: description
|
|
2298
2301
|
})]
|
|
2299
2302
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2300
2303
|
width: "14",
|
|
@@ -2332,14 +2335,17 @@ window.__ModuleLoader__.load({
|
|
|
2332
2335
|
className: settings_card_module_css_default.headText,
|
|
2333
2336
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2334
2337
|
className: settings_card_module_css_default.name,
|
|
2338
|
+
title,
|
|
2335
2339
|
children: title
|
|
2336
2340
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2337
2341
|
className: settings_card_module_css_default.description,
|
|
2338
|
-
|
|
2342
|
+
title: description,
|
|
2343
|
+
children: description
|
|
2339
2344
|
})]
|
|
2340
2345
|
}),
|
|
2341
2346
|
state.dirty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2342
2347
|
className: settings_card_module_css_default.pending,
|
|
2348
|
+
title: props.t("settings.unsaved"),
|
|
2343
2349
|
children: props.t("settings.unsaved")
|
|
2344
2350
|
}) : null,
|
|
2345
2351
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
@@ -2494,8 +2500,9 @@ window.__ModuleLoader__.load({
|
|
|
2494
2500
|
}
|
|
2495
2501
|
//#endregion
|
|
2496
2502
|
//#region src/client/settings-form.ts
|
|
2497
|
-
/** A whole-number field. An empty draft clears the field; any other draft that is not a finite number blocks the save. */
|
|
2498
|
-
function numberField(field) {
|
|
2503
|
+
/** A whole- or decimal-number field. An empty draft clears the field; any other draft that is not a finite number within the constraints blocks the save. */
|
|
2504
|
+
function numberField(field, constraints = {}) {
|
|
2505
|
+
const { integer = false, min } = constraints;
|
|
2499
2506
|
return {
|
|
2500
2507
|
field,
|
|
2501
2508
|
format: (value) => typeof value === "number" ? String(value) : "",
|
|
@@ -2503,10 +2510,13 @@ window.__ModuleLoader__.load({
|
|
|
2503
2510
|
const trimmed = text.trim();
|
|
2504
2511
|
if (trimmed === "") return { kind: "clear" };
|
|
2505
2512
|
const parsed = Number(trimmed);
|
|
2506
|
-
|
|
2513
|
+
if (!Number.isFinite(parsed)) return void 0;
|
|
2514
|
+
if (integer && !Number.isInteger(parsed)) return void 0;
|
|
2515
|
+
if (min !== void 0 && parsed < min) return void 0;
|
|
2516
|
+
return {
|
|
2507
2517
|
kind: "set",
|
|
2508
2518
|
value: parsed
|
|
2509
|
-
}
|
|
2519
|
+
};
|
|
2510
2520
|
}
|
|
2511
2521
|
};
|
|
2512
2522
|
}
|
|
@@ -2530,11 +2540,13 @@ window.__ModuleLoader__.load({
|
|
|
2530
2540
|
field,
|
|
2531
2541
|
format: (value) => typeof value === "boolean" ? String(value) : "",
|
|
2532
2542
|
parse: (text) => {
|
|
2533
|
-
|
|
2543
|
+
const trimmed = text.trim();
|
|
2544
|
+
if (trimmed === "") return { kind: "clear" };
|
|
2545
|
+
if (trimmed === "true") return {
|
|
2534
2546
|
kind: "set",
|
|
2535
2547
|
value: true
|
|
2536
2548
|
};
|
|
2537
|
-
if (
|
|
2549
|
+
if (trimmed === "false") return {
|
|
2538
2550
|
kind: "set",
|
|
2539
2551
|
value: false
|
|
2540
2552
|
};
|
|
@@ -2636,12 +2648,13 @@ window.__ModuleLoader__.load({
|
|
|
2636
2648
|
const plan = this.plan();
|
|
2637
2649
|
const writes = plan.flatMap((item) => item.run === void 0 ? [] : [item.run]);
|
|
2638
2650
|
if (plan.length === 0 || this.saving || writes.length !== plan.length) return;
|
|
2651
|
+
const fields = new Set(plan.map((item) => item.field));
|
|
2639
2652
|
this.saving = true;
|
|
2640
2653
|
this.failed = false;
|
|
2641
2654
|
this.publish();
|
|
2642
2655
|
let landed = true;
|
|
2643
2656
|
for (const write of writes) landed = await write() && landed;
|
|
2644
|
-
if (landed) this.staged.
|
|
2657
|
+
if (landed) for (const field of fields) this.staged.delete(field);
|
|
2645
2658
|
this.saving = false;
|
|
2646
2659
|
this.failed = !landed;
|
|
2647
2660
|
this.publish();
|
|
@@ -3022,7 +3035,7 @@ window.__ModuleLoader__.load({
|
|
|
3022
3035
|
"update.packages": "组件版本",
|
|
3023
3036
|
"update.retry": "重新检查",
|
|
3024
3037
|
"update.close": "关闭更新面板",
|
|
3025
|
-
"update.error.pnpmMissing": "未找到 pnpm
|
|
3038
|
+
"update.error.pnpmMissing": "未找到 pnpm,已尝试 pnpm / corepack / npx 仍不可用。请安装 pnpm 后重启应用(Windows: npm install -g pnpm 或 corepack enable;macOS: brew install pnpm 或 corepack enable)。",
|
|
3026
3039
|
"update.error.timeout": "更新超时,已终止安装进程,请重试。",
|
|
3027
3040
|
"update.error.notFound": "未找到 dsh-web-ui 聚合包安装,无法更新。",
|
|
3028
3041
|
"update.error.link": "当前为本地开发模式(链接安装),无法自动更新。",
|
|
@@ -3124,7 +3137,7 @@ window.__ModuleLoader__.load({
|
|
|
3124
3137
|
"update.packages": "Component versions",
|
|
3125
3138
|
"update.retry": "Check again",
|
|
3126
3139
|
"update.close": "Close update panel",
|
|
3127
|
-
"update.error.pnpmMissing": "pnpm was not found. Install
|
|
3140
|
+
"update.error.pnpmMissing": "pnpm was not found (tried pnpm / corepack / npx). Install pnpm and restart the app (Windows: npm install -g pnpm or corepack enable; macOS: brew install pnpm or corepack enable).",
|
|
3128
3141
|
"update.error.timeout": "The update timed out and the install process was killed; try again.",
|
|
3129
3142
|
"update.error.notFound": "The dsh-web-ui aggregate package is not installed; nothing to update.",
|
|
3130
3143
|
"update.error.link": "Local development mode (link install) — automatic update is unavailable.",
|