dsh-dock 0.13.0 → 0.15.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 +27 -8
- package/client.js +1235 -610
- package/features/animation/view.jsx +2 -2
- package/features/balance/view.js +1 -1
- package/features/games/view.jsx +1 -1
- package/features/mobile/host.js +306 -0
- package/features/mobile/view.js +359 -154
- package/features/mobile-relay/host.js +5 -245
- package/features/mobile-relay/view.jsx +9 -330
- package/features/modelconfig/host.js +195 -1
- package/features/modelconfig/view.js +762 -92
- package/features/notify/view.jsx +2 -2
- package/features/runstate/host.js +10 -0
- package/features/runstate/view.jsx +2 -2
- package/features/tokenlog/view.jsx +44 -14
- package/index.js +15 -1
- package/package.json +9 -3
- package/screenshots/dock-modelconfig-provider-create.png +0 -0
- package/screenshots/dock-modelconfig-provider-edit.png +0 -0
- package/screenshots/dock-modelconfig-providers.png +0 -0
- package/screenshots/dock-modelconfig.png +0 -0
- package/src/client.jsx +1 -1
- package/src/shared.js +6 -3
- package/src/welcome-ack.js +69 -0
package/client.js
CHANGED
|
@@ -2187,7 +2187,7 @@ function initFeatureState(defs) {
|
|
|
2187
2187
|
}
|
|
2188
2188
|
function syncFeatureStateFromHost(defs) {
|
|
2189
2189
|
if (typeof fetch !== "function") return;
|
|
2190
|
-
fetch("
|
|
2190
|
+
fetch("dsh-dock/features").then(async (res) => {
|
|
2191
2191
|
if (!res.ok) return;
|
|
2192
2192
|
const data = await res.json().catch(() => null);
|
|
2193
2193
|
const persisted = data && data.ok && data.data && data.data.persisted;
|
|
@@ -2214,7 +2214,7 @@ function syncFeatureStateFromHost(defs) {
|
|
|
2214
2214
|
}
|
|
2215
2215
|
function pushFeatureEnabledToHost(id, enabled) {
|
|
2216
2216
|
if (typeof fetch !== "function") return;
|
|
2217
|
-
fetch("
|
|
2217
|
+
fetch("dsh-dock/features", {
|
|
2218
2218
|
method: "POST",
|
|
2219
2219
|
headers: { "content-type": "application/json" },
|
|
2220
2220
|
body: JSON.stringify({ id, enabled })
|
|
@@ -2299,8 +2299,16 @@ function subscribePanel(fn) {
|
|
|
2299
2299
|
// features/tokenlog/view.jsx
|
|
2300
2300
|
var import_react2 = __toESM(require("react"), 1);
|
|
2301
2301
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
2302
|
+
var routeGone = false;
|
|
2303
|
+
function isTokenlogRouteGone() {
|
|
2304
|
+
return routeGone;
|
|
2305
|
+
}
|
|
2306
|
+
function routeGoneMessage() {
|
|
2307
|
+
return "\u5BBF\u4E3B\u672A\u542F\u7528\u300C\u7528\u91CF\u8BB0\u5F55\u300D\u8DEF\u7531\uFF08\u6216\u5BBF\u4E3B\u8FDB\u7A0B\u662F\u65E7\u7248\u672C\uFF09\uFF0C\u8BF7\u5728\u529F\u80FD\u575E\u91CC\u542F\u7528\u8BE5\u529F\u80FD\u6216\u91CD\u542F dsh web";
|
|
2308
|
+
}
|
|
2302
2309
|
function rpcCall(method, args) {
|
|
2303
|
-
|
|
2310
|
+
if (routeGone) return Promise.reject(new Error(routeGoneMessage()));
|
|
2311
|
+
return fetch("dsh-dock/tokenlog/" + method, {
|
|
2304
2312
|
method: "POST",
|
|
2305
2313
|
headers: { "content-type": "application/json" },
|
|
2306
2314
|
body: JSON.stringify(args === void 0 ? {} : args)
|
|
@@ -2308,7 +2316,8 @@ function rpcCall(method, args) {
|
|
|
2308
2316
|
const data = await res.json().catch(() => ({}));
|
|
2309
2317
|
if (res.ok && data && data.ok === true) return data.data;
|
|
2310
2318
|
if (res.status === 405 || res.status === 404) {
|
|
2311
|
-
|
|
2319
|
+
routeGone = true;
|
|
2320
|
+
throw new Error(routeGoneMessage());
|
|
2312
2321
|
}
|
|
2313
2322
|
if (data && data.ok === false) throw new Error(data.error && data.error.message || "HTTP " + res.status);
|
|
2314
2323
|
throw new Error("HTTP " + res.status + (data && data.error && data.error.message ? ": " + data.error.message : ""));
|
|
@@ -3670,32 +3679,37 @@ function TokenLogChip(props) {
|
|
|
3670
3679
|
(0, import_react2.useEffect)(() => {
|
|
3671
3680
|
if (!sid) return;
|
|
3672
3681
|
let cancel = false;
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3682
|
+
let timer = null;
|
|
3683
|
+
const load = () => {
|
|
3684
|
+
if (cancel || isTokenlogRouteGone()) return null;
|
|
3685
|
+
return rpcCall("query", { sessionId: sid }).then((d) => {
|
|
3686
|
+
if (!cancel) setSnap({ totals: d && d.totals, rate: d && d.rateUsdCny || 7.2, err: "" });
|
|
3687
|
+
}).catch((e) => {
|
|
3688
|
+
if (!cancel) setSnap((s) => ({ totals: s.totals, rate: s.rate, err: String(e && e.message || e) }));
|
|
3689
|
+
});
|
|
3690
|
+
};
|
|
3678
3691
|
load();
|
|
3679
|
-
|
|
3692
|
+
timer = setInterval(load, 1e4);
|
|
3680
3693
|
return () => {
|
|
3681
3694
|
cancel = true;
|
|
3682
|
-
clearInterval(timer);
|
|
3695
|
+
if (timer) clearInterval(timer);
|
|
3683
3696
|
};
|
|
3684
3697
|
}, [sid]);
|
|
3685
3698
|
if (!sid) return null;
|
|
3686
3699
|
const t = snap.totals;
|
|
3687
|
-
const
|
|
3688
|
-
const
|
|
3700
|
+
const gone = isTokenlogRouteGone();
|
|
3701
|
+
const label = gone ? "\u7528\u91CF\xB7\u672A\u542F\u7528" : snap.err && !t ? snap.err.includes("\u91CD\u542F") || snap.err.includes("\u542F\u7528") ? "\u7528\u91CF\xB7\u672A\u542F\u7528" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 " + fmtCostCny(t.cost, snap.rate) : "") : "\u26C1 \u2026";
|
|
3702
|
+
const title = gone ? routeGoneMessage() + "\n\uFF08\u53EF\u5728\u529F\u80FD\u575E\u91CC\u542F\u7528\u300C\u7528\u91CF\u8BB0\u5F55\u300D\uFF09" : t ? "\u672C\u4F1A\u8BDD " + fmtNum(t.calls) + " \u6B21\u8C03\u7528 \xB7 " + fmtNum(t.totalTokens) + " Token \xB7 " + fmtCostCny(t.cost, snap.rate) + "\uFF08\u4F30\u7B97\uFF09\n\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55" : (snap.err ? snap.err + "\n" : "") + "\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55";
|
|
3689
3703
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
3690
3704
|
"button",
|
|
3691
3705
|
{
|
|
3692
3706
|
type: "button",
|
|
3693
|
-
className: "dockchip" + (snap.err && !t ? " err" : ""),
|
|
3707
|
+
className: "dockchip" + (snap.err && !t && !gone ? " err" : ""),
|
|
3694
3708
|
title,
|
|
3695
3709
|
"aria-label": "\u4F1A\u8BDD\u7528\u91CF",
|
|
3696
3710
|
onClick: () => openPanel("tokenlog", { sessionId: sid, navAt: Date.now() }),
|
|
3697
3711
|
children: [
|
|
3698
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dockchip-dot", style: { background: "var(--dk-warn)" } }),
|
|
3712
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dockchip-dot", style: { background: gone ? "var(--dsw-alias-label-tertiary,#8b95ab)" : "var(--dk-warn)" } }),
|
|
3699
3713
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label })
|
|
3700
3714
|
]
|
|
3701
3715
|
}
|
|
@@ -3731,7 +3745,7 @@ var modelsStore = {
|
|
|
3731
3745
|
load() {
|
|
3732
3746
|
if (this.snap.loading) return;
|
|
3733
3747
|
this.set({ loading: true, error: null });
|
|
3734
|
-
fetch("
|
|
3748
|
+
fetch("dsh-dock/models", { cache: "no-store", signal: AbortSignal.timeout(2e4) }).then((res) => res.ok ? res.json() : Promise.reject(new Error("\u6A21\u578B\u76EE\u5F55\u63A5\u53E3 HTTP " + res.status))).then((data) => this.set({ data, loading: false, error: null })).catch((e) => this.set({ loading: false, error: e && e.message || String(e) }));
|
|
3735
3749
|
}
|
|
3736
3750
|
};
|
|
3737
3751
|
function useModels() {
|
|
@@ -3748,35 +3762,190 @@ var DKM_TAGS = [["video", "\u89C6\u9891"], ["audio", "\u97F3\u9891"], ["document
|
|
|
3748
3762
|
var DKM_PI_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
3749
3763
|
var DKM_DS_LEVELS = ["off", "low", "high", "max"];
|
|
3750
3764
|
var DKM_EFFORT_NAMES = { off: "\u5173\u95ED", minimal: "\u6781\u4F4E", low: "\u4F4E", medium: "\u4E2D", high: "\u9AD8", xhigh: "\u8D85\u9AD8", max: "\u6700\u9AD8" };
|
|
3765
|
+
var DKM_APIS = [
|
|
3766
|
+
["openai-completions", "OpenAI \u517C\u5BB9\uFF08chat/completions\uFF09"],
|
|
3767
|
+
["openai-responses", "OpenAI Responses"],
|
|
3768
|
+
["anthropic-messages", "Anthropic Messages"]
|
|
3769
|
+
];
|
|
3770
|
+
var DKM_ROUTE_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
3771
|
+
function dkmEnvFromRoute(route) {
|
|
3772
|
+
const s = String(route || "").toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
3773
|
+
if (!s) return "";
|
|
3774
|
+
return (/^[0-9]/.test(s) ? "KEY_" + s : s) + "_API_KEY";
|
|
3775
|
+
}
|
|
3776
|
+
var DKM_ALL_INPUT = DKM_MODALITIES.map((x) => x[0]);
|
|
3777
|
+
var DKM_ALL_TAGS = DKM_TAGS.map((x) => x[0]);
|
|
3778
|
+
function dkmToggleIn(list, v) {
|
|
3779
|
+
return list.indexOf(v) >= 0 ? list.filter((x) => x !== v) : list.concat([v]);
|
|
3780
|
+
}
|
|
3781
|
+
function dkmAllInputs(on) {
|
|
3782
|
+
return { input: on ? DKM_ALL_INPUT.slice() : [], tags: on ? DKM_ALL_TAGS.slice() : [] };
|
|
3783
|
+
}
|
|
3784
|
+
function dkmAllLevels(on) {
|
|
3785
|
+
const lv = {};
|
|
3786
|
+
for (const k of DKM_PI_LEVELS) lv[k] = !!on;
|
|
3787
|
+
return { effortsMode: "custom", effortLevels: lv };
|
|
3788
|
+
}
|
|
3789
|
+
function draftFromModel(m) {
|
|
3790
|
+
const levels = {};
|
|
3791
|
+
if (m.efforts === "custom" && m.effortMap && typeof m.effortMap === "object") {
|
|
3792
|
+
for (const lv of DKM_PI_LEVELS) levels[lv] = m.effortMap[lv] !== void 0;
|
|
3793
|
+
}
|
|
3794
|
+
return {
|
|
3795
|
+
id: m.id || "",
|
|
3796
|
+
name: m.name || "",
|
|
3797
|
+
contextWindow: m.contextWindow != null ? String(m.contextWindow) : "",
|
|
3798
|
+
maxTokens: m.maxTokens != null ? String(m.maxTokens) : "",
|
|
3799
|
+
input: m.input && m.input.length ? m.input.slice() : ["text"],
|
|
3800
|
+
tags: (m.tags || []).slice(),
|
|
3801
|
+
effortsMode: m.efforts === "custom" ? "custom" : m.efforts === "off" ? "off" : "inherit",
|
|
3802
|
+
effortLevels: levels,
|
|
3803
|
+
raw: m.raw && typeof m.raw === "object" ? m.raw : null
|
|
3804
|
+
};
|
|
3805
|
+
}
|
|
3806
|
+
function emptyModelDraft() {
|
|
3807
|
+
return { id: "", name: "", contextWindow: "", maxTokens: "", input: ["text"], tags: [], effortsMode: "inherit", effortLevels: {}, raw: null };
|
|
3808
|
+
}
|
|
3809
|
+
function emptyProviderForm() {
|
|
3810
|
+
return {
|
|
3811
|
+
route: "",
|
|
3812
|
+
displayName: "",
|
|
3813
|
+
api: "openai-completions",
|
|
3814
|
+
baseURL: "",
|
|
3815
|
+
apiKeyEnv: "",
|
|
3816
|
+
apiKey: "",
|
|
3817
|
+
defaultInput: ["text"],
|
|
3818
|
+
models: [],
|
|
3819
|
+
extra: {}
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
function providerFormFromProvider(p) {
|
|
3823
|
+
const raw = p.rawProfile && typeof p.rawProfile === "object" && !Array.isArray(p.rawProfile) ? p.rawProfile : {};
|
|
3824
|
+
const extra = Object.assign({}, raw);
|
|
3825
|
+
delete extra.displayName;
|
|
3826
|
+
delete extra.api;
|
|
3827
|
+
delete extra.baseURL;
|
|
3828
|
+
delete extra.apiKeyEnv;
|
|
3829
|
+
delete extra.defaultInput;
|
|
3830
|
+
delete extra.models;
|
|
3831
|
+
const models = draftFromProvider(p).models;
|
|
3832
|
+
return {
|
|
3833
|
+
route: p.route || p.id || "",
|
|
3834
|
+
displayName: typeof raw.displayName === "string" ? raw.displayName : p.displayName || "",
|
|
3835
|
+
api: typeof raw.api === "string" && raw.api ? raw.api : p.api || "openai-completions",
|
|
3836
|
+
baseURL: typeof raw.baseURL === "string" ? raw.baseURL : p.baseURL || "",
|
|
3837
|
+
apiKeyEnv: typeof raw.apiKeyEnv === "string" ? raw.apiKeyEnv : p.apiKeyEnv || "",
|
|
3838
|
+
apiKey: "",
|
|
3839
|
+
defaultInput: Array.isArray(raw.defaultInput) && raw.defaultInput.length ? raw.defaultInput.slice() : Array.isArray(p.defaultInput) && p.defaultInput.length ? p.defaultInput.slice() : ["text"],
|
|
3840
|
+
models: models.length ? models : [emptyModelDraft()],
|
|
3841
|
+
extra
|
|
3842
|
+
};
|
|
3843
|
+
}
|
|
3751
3844
|
function draftFromProvider(p) {
|
|
3752
3845
|
return {
|
|
3753
3846
|
id: p.id,
|
|
3754
3847
|
kind: p.kind,
|
|
3755
3848
|
thinking: p.thinking === "disabled" ? "disabled" : "enabled",
|
|
3756
3849
|
defaultEffort: DKM_DS_LEVELS.indexOf(p.defaultEffort) >= 0 ? p.defaultEffort : "high",
|
|
3757
|
-
models: (p.models || []).map(
|
|
3758
|
-
const levels = {};
|
|
3759
|
-
if (m.efforts === "custom" && m.effortMap && typeof m.effortMap === "object") {
|
|
3760
|
-
for (const lv of DKM_PI_LEVELS) levels[lv] = m.effortMap[lv] !== void 0;
|
|
3761
|
-
}
|
|
3762
|
-
return {
|
|
3763
|
-
id: m.id || "",
|
|
3764
|
-
name: m.name || "",
|
|
3765
|
-
contextWindow: m.contextWindow != null ? String(m.contextWindow) : "",
|
|
3766
|
-
maxTokens: m.maxTokens != null ? String(m.maxTokens) : "",
|
|
3767
|
-
input: m.input && m.input.length ? m.input.slice() : ["text"],
|
|
3768
|
-
tags: (m.tags || []).slice(),
|
|
3769
|
-
effortsMode: m.efforts === "custom" ? "custom" : m.efforts === "off" ? "off" : "inherit",
|
|
3770
|
-
effortLevels: levels,
|
|
3771
|
-
raw: m.raw && typeof m.raw === "object" ? m.raw : null
|
|
3772
|
-
};
|
|
3773
|
-
})
|
|
3850
|
+
models: (p.models || []).map(draftFromModel)
|
|
3774
3851
|
};
|
|
3775
3852
|
}
|
|
3776
|
-
function
|
|
3853
|
+
function ModelRow(props) {
|
|
3854
|
+
const m = props.m, i = props.i, kind = props.kind, onPatch = props.onPatch, onDel = props.onDel;
|
|
3855
|
+
return import_react3.default.createElement(
|
|
3856
|
+
"div",
|
|
3857
|
+
{ key: i, className: "dkm-model" },
|
|
3858
|
+
import_react3.default.createElement(
|
|
3859
|
+
"div",
|
|
3860
|
+
{ className: "dkm-model-head" },
|
|
3861
|
+
import_react3.default.createElement("span", { className: "dkm-model-idx" }, "#" + (i + 1)),
|
|
3862
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-del", onClick: () => onDel(i) }, "\u5220\u9664")
|
|
3863
|
+
),
|
|
3864
|
+
import_react3.default.createElement(
|
|
3865
|
+
"div",
|
|
3866
|
+
{ className: "dkm-grid" },
|
|
3867
|
+
import_react3.default.createElement("input", { className: "dkm-input", placeholder: "\u6A21\u578B id\uFF08\u5FC5\u586B\uFF0C\u5982 deepseek-v4-pro\uFF09", value: m.id, onChange: (e) => onPatch(i, { id: e.target.value }) }),
|
|
3868
|
+
import_react3.default.createElement("input", { className: "dkm-input", placeholder: "\u663E\u793A\u540D\u79F0\uFF08\u53EF\u9009\uFF09", value: m.name, onChange: (e) => onPatch(i, { name: e.target.value }) }),
|
|
3869
|
+
import_react3.default.createElement("input", { className: "dkm-input", placeholder: "\u4E0A\u4E0B\u6587\u7A97\u53E3", inputMode: "numeric", value: m.contextWindow, onChange: (e) => onPatch(i, { contextWindow: e.target.value }) }),
|
|
3870
|
+
import_react3.default.createElement("input", { className: "dkm-input", placeholder: "\u6700\u5927\u8F93\u51FA", inputMode: "numeric", value: m.maxTokens, onChange: (e) => onPatch(i, { maxTokens: e.target.value }) })
|
|
3871
|
+
),
|
|
3872
|
+
import_react3.default.createElement(
|
|
3873
|
+
"div",
|
|
3874
|
+
{ className: "dkm-checks" },
|
|
3875
|
+
import_react3.default.createElement("span", { className: "dkm-label" }, "\u8F93\u5165\u7C7B\u578B\uFF1A"),
|
|
3876
|
+
DKM_MODALITIES.map(([v, label]) => import_react3.default.createElement(
|
|
3877
|
+
"label",
|
|
3878
|
+
{
|
|
3879
|
+
key: v,
|
|
3880
|
+
className: "dkm-check",
|
|
3881
|
+
title: v === "image" ? "\u7531\u4F60\u58F0\u660E\u8BE5\u7AEF\u70B9\u652F\u6301\u56FE\u7247\uFF1A\u4FDD\u5B58\u540E\u539F\u56FE\u76F4\u53D1\uFF0C\u5E76\u53EF\u4F5C\u4E3A\u89C6\u89C9\u6A21\u578B\u5019\u9009\u3002\u7CFB\u7EDF\u4E0D\u4F1A\u66FF\u4F60\u731C\u6D4B\uFF1B\u7AEF\u70B9\u5B9E\u9645\u4E0D\u652F\u6301\u65F6\u53D6\u6D88\u52FE\u9009\u5373\u53EF\u6062\u590D\u8D70\u56FE\u7247\u7406\u89E3\u4EE3\u7406" : null
|
|
3882
|
+
},
|
|
3883
|
+
import_react3.default.createElement("input", {
|
|
3884
|
+
type: "checkbox",
|
|
3885
|
+
checked: m.input.indexOf(v) >= 0,
|
|
3886
|
+
onChange: () => {
|
|
3887
|
+
const next = dkmToggleIn(m.input, v);
|
|
3888
|
+
onPatch(i, { input: next.length > 0 ? next : ["text"] });
|
|
3889
|
+
}
|
|
3890
|
+
}),
|
|
3891
|
+
label
|
|
3892
|
+
)),
|
|
3893
|
+
import_react3.default.createElement("span", { className: "dkm-label dkm-tag", title: "\u6807\u6CE8\u4EC5\u5728\u672C\u9762\u677F\u5C55\u793A\u4E0E\u6301\u4E45\u5316\uFF0C\u4E0D\u53C2\u4E0E\u8BF7\u6C42\u8DEF\u7531\uFF08\u5B98\u65B9 schema \u53EA\u63A5\u53D7\u6587\u672C/\u56FE\u7247\uFF09" }, "\u6807\u6CE8\uFF1A"),
|
|
3894
|
+
DKM_TAGS.map(([v, label]) => import_react3.default.createElement(
|
|
3895
|
+
"label",
|
|
3896
|
+
{ key: v, className: "dkm-check dkm-tag" },
|
|
3897
|
+
import_react3.default.createElement("input", { type: "checkbox", checked: m.tags.indexOf(v) >= 0, onChange: () => onPatch(i, { tags: dkmToggleIn(m.tags, v) }) }),
|
|
3898
|
+
label
|
|
3899
|
+
)),
|
|
3900
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u52FE\u9009\u5168\u90E8\u8F93\u5165\u7C7B\u578B\u4E0E\u6807\u6CE8", onClick: () => onPatch(i, dkmAllInputs(true)) }, "\u5168\u9009"),
|
|
3901
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u53D6\u6D88\u5168\u90E8\u52FE\u9009\uFF08\u8F93\u5165\u7559\u7A7A = \u7EE7\u627F\u76EE\u5F55\u9ED8\u8BA4\uFF09", onClick: () => onPatch(i, dkmAllInputs(false)) }, "\u53D6\u6D88\u5168\u9009")
|
|
3902
|
+
),
|
|
3903
|
+
import_react3.default.createElement(
|
|
3904
|
+
"div",
|
|
3905
|
+
{ className: "dkm-efforts" },
|
|
3906
|
+
import_react3.default.createElement("span", { className: "dkm-label" }, "\u601D\u8003\u5F3A\u5EA6\uFF1A"),
|
|
3907
|
+
kind === "deepseek" ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\u968F Provider \u8BBE\u7F6E\uFF08Off/Low/High/Max\uFF0C\u5168\u6A21\u578B\u5171\u4EAB\uFF09") : import_react3.default.createElement(
|
|
3908
|
+
"span",
|
|
3909
|
+
null,
|
|
3910
|
+
import_react3.default.createElement(
|
|
3911
|
+
"select",
|
|
3912
|
+
{
|
|
3913
|
+
className: "dkm-select",
|
|
3914
|
+
value: m.effortsMode,
|
|
3915
|
+
onChange: (e) => onPatch(i, {
|
|
3916
|
+
effortsMode: e.target.value,
|
|
3917
|
+
effortLevels: e.target.value === "custom" && m.effortsMode !== "custom" ? { off: true, low: true, high: true } : m.effortLevels
|
|
3918
|
+
})
|
|
3919
|
+
},
|
|
3920
|
+
import_react3.default.createElement("option", { value: "inherit" }, "\u8DDF\u968F\u76EE\u5F55\u9ED8\u8BA4"),
|
|
3921
|
+
import_react3.default.createElement("option", { value: "off" }, "\u4E0D\u652F\u6301\u601D\u8003"),
|
|
3922
|
+
import_react3.default.createElement("option", { value: "custom" }, "\u81EA\u5B9A\u4E49\u6863\u4F4D")
|
|
3923
|
+
),
|
|
3924
|
+
m.effortsMode === "custom" ? DKM_PI_LEVELS.map((lv) => import_react3.default.createElement(
|
|
3925
|
+
"label",
|
|
3926
|
+
{ key: lv, className: "dkm-check" },
|
|
3927
|
+
import_react3.default.createElement("input", {
|
|
3928
|
+
type: "checkbox",
|
|
3929
|
+
checked: !!m.effortLevels[lv],
|
|
3930
|
+
onChange: () => {
|
|
3931
|
+
const nl = Object.assign({}, m.effortLevels);
|
|
3932
|
+
nl[lv] = !nl[lv];
|
|
3933
|
+
onPatch(i, { effortLevels: nl });
|
|
3934
|
+
}
|
|
3935
|
+
}),
|
|
3936
|
+
DKM_EFFORT_NAMES[lv] || lv
|
|
3937
|
+
)) : null,
|
|
3938
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u52FE\u9009\u5168\u90E8\u5F3A\u5EA6\u6863\uFF08\u5207\u4E3A\u81EA\u5B9A\u4E49\uFF09", onClick: () => onPatch(i, dkmAllLevels(true)) }, "\u5168\u9009"),
|
|
3939
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u53D6\u6D88\u5168\u90E8\u5F3A\u5EA6\u6863", onClick: () => onPatch(i, dkmAllLevels(false)) }, "\u53D6\u6D88\u5168\u9009")
|
|
3940
|
+
)
|
|
3941
|
+
)
|
|
3942
|
+
);
|
|
3943
|
+
}
|
|
3944
|
+
function ModelsView(props) {
|
|
3777
3945
|
const snap = useModels();
|
|
3778
3946
|
const data = snap.data;
|
|
3779
3947
|
const providers = data && Array.isArray(data.providers) ? data.providers : [];
|
|
3948
|
+
const params = props && props.params;
|
|
3780
3949
|
const [selId, setSelId] = import_react3.default.useState(null);
|
|
3781
3950
|
const [draft, setDraft] = import_react3.default.useState(null);
|
|
3782
3951
|
const [builtKey, setBuiltKey] = import_react3.default.useState(null);
|
|
@@ -3789,6 +3958,8 @@ function ModelsView() {
|
|
|
3789
3958
|
const [vpSaving, setVpSaving] = import_react3.default.useState(false);
|
|
3790
3959
|
const [vpMsg, setVpMsg] = import_react3.default.useState(null);
|
|
3791
3960
|
const [vpDirectExpanded, setVpDirectExpanded] = import_react3.default.useState(false);
|
|
3961
|
+
const [page, setPage] = import_react3.default.useState("settings");
|
|
3962
|
+
const [pageOpenCreate, setPageOpenCreate] = import_react3.default.useState(false);
|
|
3792
3963
|
import_react3.default.useEffect(() => {
|
|
3793
3964
|
modelsStore.load();
|
|
3794
3965
|
}, []);
|
|
@@ -3813,7 +3984,7 @@ function ModelsView() {
|
|
|
3813
3984
|
const saveVp = () => {
|
|
3814
3985
|
if (!vpDraft || vpSaving) return;
|
|
3815
3986
|
setVpSaving(true);
|
|
3816
|
-
fetch("
|
|
3987
|
+
fetch("dsh-dock/models", {
|
|
3817
3988
|
method: "POST",
|
|
3818
3989
|
headers: { "content-type": "application/json" },
|
|
3819
3990
|
body: JSON.stringify({ visionProxy: vpDraft, revisions: data && data.revisions || {} }),
|
|
@@ -3851,6 +4022,13 @@ function ModelsView() {
|
|
|
3851
4022
|
setSelId(id);
|
|
3852
4023
|
setMsg(null);
|
|
3853
4024
|
};
|
|
4025
|
+
import_react3.default.useEffect(() => {
|
|
4026
|
+
if (params && params.page === "providers") setPage("providers");
|
|
4027
|
+
if (params && params.openProviderForm) {
|
|
4028
|
+
setPage("providers");
|
|
4029
|
+
setPageOpenCreate(true);
|
|
4030
|
+
}
|
|
4031
|
+
}, []);
|
|
3854
4032
|
const save = () => {
|
|
3855
4033
|
if (!draft || !cur || !dirty || saving) return;
|
|
3856
4034
|
const models = draft.models.map((m) => ({
|
|
@@ -3870,7 +4048,7 @@ function ModelsView() {
|
|
|
3870
4048
|
payload.defaultEffort = draft.defaultEffort;
|
|
3871
4049
|
}
|
|
3872
4050
|
setSaving(true);
|
|
3873
|
-
fetch("
|
|
4051
|
+
fetch("dsh-dock/models", {
|
|
3874
4052
|
method: "POST",
|
|
3875
4053
|
headers: { "content-type": "application/json" },
|
|
3876
4054
|
body: JSON.stringify(payload),
|
|
@@ -3884,98 +4062,28 @@ function ModelsView() {
|
|
|
3884
4062
|
}
|
|
3885
4063
|
}).catch((e) => setMsg({ ok: false, text: e && e.message || String(e) })).then(() => setSaving(false));
|
|
3886
4064
|
};
|
|
3887
|
-
const modelRow = (m, i) =>
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
)
|
|
3908
|
-
|
|
3909
|
-
"div",
|
|
3910
|
-
{ className: "dkm-checks" },
|
|
3911
|
-
import_react3.default.createElement("span", { className: "dkm-label" }, "\u8F93\u5165\u7C7B\u578B\uFF1A"),
|
|
3912
|
-
DKM_MODALITIES.map(([v, label]) => import_react3.default.createElement(
|
|
3913
|
-
"label",
|
|
3914
|
-
{
|
|
3915
|
-
key: v,
|
|
3916
|
-
className: "dkm-check",
|
|
3917
|
-
title: v === "image" ? "\u7531\u4F60\u58F0\u660E\u8BE5\u7AEF\u70B9\u652F\u6301\u56FE\u7247\uFF1A\u4FDD\u5B58\u540E\u539F\u56FE\u76F4\u53D1\uFF0C\u5E76\u53EF\u4F5C\u4E3A\u89C6\u89C9\u6A21\u578B\u5019\u9009\u3002\u7CFB\u7EDF\u4E0D\u4F1A\u66FF\u4F60\u731C\u6D4B\uFF1B\u7AEF\u70B9\u5B9E\u9645\u4E0D\u652F\u6301\u65F6\u53D6\u6D88\u52FE\u9009\u5373\u53EF\u6062\u590D\u8D70\u56FE\u7247\u7406\u89E3\u4EE3\u7406" : null
|
|
3918
|
-
},
|
|
3919
|
-
import_react3.default.createElement("input", {
|
|
3920
|
-
type: "checkbox",
|
|
3921
|
-
checked: m.input.indexOf(v) >= 0,
|
|
3922
|
-
onChange: () => {
|
|
3923
|
-
const next = toggleIn(m.input, v);
|
|
3924
|
-
patchModel(i, { input: next.length > 0 ? next : ["text"] });
|
|
3925
|
-
}
|
|
3926
|
-
}),
|
|
3927
|
-
label
|
|
3928
|
-
)),
|
|
3929
|
-
import_react3.default.createElement("span", { className: "dkm-label dkm-tag", title: "\u6807\u6CE8\u4EC5\u5728\u672C\u9762\u677F\u5C55\u793A\u4E0E\u6301\u4E45\u5316\uFF0C\u4E0D\u53C2\u4E0E\u8BF7\u6C42\u8DEF\u7531\uFF08\u5B98\u65B9 schema \u53EA\u63A5\u53D7\u6587\u672C/\u56FE\u7247\uFF09" }, "\u6807\u6CE8\uFF1A"),
|
|
3930
|
-
DKM_TAGS.map(([v, label]) => import_react3.default.createElement(
|
|
3931
|
-
"label",
|
|
3932
|
-
{ key: v, className: "dkm-check dkm-tag" },
|
|
3933
|
-
import_react3.default.createElement("input", { type: "checkbox", checked: m.tags.indexOf(v) >= 0, onChange: () => patchModel(i, { tags: toggleIn(m.tags, v) }) }),
|
|
3934
|
-
label
|
|
3935
|
-
)),
|
|
3936
|
-
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u52FE\u9009\u5168\u90E8\u8F93\u5165\u7C7B\u578B\u4E0E\u6807\u6CE8", onClick: () => patchModel(i, allInputs(true)) }, "\u5168\u9009"),
|
|
3937
|
-
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u53D6\u6D88\u5168\u90E8\u52FE\u9009\uFF08\u8F93\u5165\u7559\u7A7A = \u7EE7\u627F\u76EE\u5F55\u9ED8\u8BA4\uFF09", onClick: () => patchModel(i, allInputs(false)) }, "\u53D6\u6D88\u5168\u9009")
|
|
3938
|
-
),
|
|
3939
|
-
import_react3.default.createElement(
|
|
3940
|
-
"div",
|
|
3941
|
-
{ className: "dkm-efforts" },
|
|
3942
|
-
import_react3.default.createElement("span", { className: "dkm-label" }, "\u601D\u8003\u5F3A\u5EA6\uFF1A"),
|
|
3943
|
-
cur.kind === "deepseek" ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\u968F Provider \u8BBE\u7F6E\uFF08Off/Low/High/Max\uFF0C\u5168\u6A21\u578B\u5171\u4EAB\uFF09") : import_react3.default.createElement(
|
|
3944
|
-
"span",
|
|
3945
|
-
null,
|
|
3946
|
-
import_react3.default.createElement(
|
|
3947
|
-
"select",
|
|
3948
|
-
{
|
|
3949
|
-
className: "dkm-select",
|
|
3950
|
-
value: m.effortsMode,
|
|
3951
|
-
onChange: (e) => patchModel(i, {
|
|
3952
|
-
effortsMode: e.target.value,
|
|
3953
|
-
effortLevels: e.target.value === "custom" && m.effortsMode !== "custom" ? { off: true, low: true, high: true } : m.effortLevels
|
|
3954
|
-
})
|
|
3955
|
-
},
|
|
3956
|
-
import_react3.default.createElement("option", { value: "inherit" }, "\u8DDF\u968F\u76EE\u5F55\u9ED8\u8BA4"),
|
|
3957
|
-
import_react3.default.createElement("option", { value: "off" }, "\u4E0D\u652F\u6301\u601D\u8003"),
|
|
3958
|
-
import_react3.default.createElement("option", { value: "custom" }, "\u81EA\u5B9A\u4E49\u6863\u4F4D")
|
|
3959
|
-
),
|
|
3960
|
-
m.effortsMode === "custom" ? DKM_PI_LEVELS.map((lv) => import_react3.default.createElement(
|
|
3961
|
-
"label",
|
|
3962
|
-
{ key: lv, className: "dkm-check" },
|
|
3963
|
-
import_react3.default.createElement("input", {
|
|
3964
|
-
type: "checkbox",
|
|
3965
|
-
checked: !!m.effortLevels[lv],
|
|
3966
|
-
onChange: () => {
|
|
3967
|
-
const nl = Object.assign({}, m.effortLevels);
|
|
3968
|
-
nl[lv] = !nl[lv];
|
|
3969
|
-
patchModel(i, { effortLevels: nl });
|
|
3970
|
-
}
|
|
3971
|
-
}),
|
|
3972
|
-
DKM_EFFORT_NAMES[lv] || lv
|
|
3973
|
-
)) : null,
|
|
3974
|
-
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u52FE\u9009\u5168\u90E8\u5F3A\u5EA6\u6863\uFF08\u5207\u4E3A\u81EA\u5B9A\u4E49\uFF09", onClick: () => patchModel(i, allLevels(true)) }, "\u5168\u9009"),
|
|
3975
|
-
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u4E00\u952E\u53D6\u6D88\u5168\u90E8\u5F3A\u5EA6\u6863", onClick: () => patchModel(i, allLevels(false)) }, "\u53D6\u6D88\u5168\u9009")
|
|
3976
|
-
)
|
|
3977
|
-
)
|
|
3978
|
-
);
|
|
4065
|
+
const modelRow = (m, i) => ModelRow({
|
|
4066
|
+
m,
|
|
4067
|
+
i,
|
|
4068
|
+
kind: cur.kind,
|
|
4069
|
+
onPatch: (j, patch) => patchModel(j, patch),
|
|
4070
|
+
onDel: (j) => patchDraft({ models: draft.models.filter((_, k) => k !== j) })
|
|
4071
|
+
});
|
|
4072
|
+
if (page === "providers") {
|
|
4073
|
+
return import_react3.default.createElement(ProvidersPage, {
|
|
4074
|
+
data,
|
|
4075
|
+
providers,
|
|
4076
|
+
loading: snap.loading,
|
|
4077
|
+
error: snap.error,
|
|
4078
|
+
openCreate: pageOpenCreate,
|
|
4079
|
+
onCreateHandled: () => setPageOpenCreate(false),
|
|
4080
|
+
// 返回主页时顺手重读目录:子页面里增删改过的 Provider 立即反映到模型编辑器
|
|
4081
|
+
onBack: () => {
|
|
4082
|
+
setPage("settings");
|
|
4083
|
+
refreshModels();
|
|
4084
|
+
}
|
|
4085
|
+
});
|
|
4086
|
+
}
|
|
3979
4087
|
const body = [];
|
|
3980
4088
|
if (data) {
|
|
3981
4089
|
body.push(import_react3.default.createElement(
|
|
@@ -4115,6 +4223,44 @@ function ModelsView() {
|
|
|
4115
4223
|
)
|
|
4116
4224
|
));
|
|
4117
4225
|
}
|
|
4226
|
+
if (data) {
|
|
4227
|
+
const custom = providers.filter((p) => p.kind === "pi-ai");
|
|
4228
|
+
const missingKey = custom.filter((p) => p.apiKeyEnv && !p.apiKeyConfigured).length;
|
|
4229
|
+
body.push(import_react3.default.createElement(
|
|
4230
|
+
"div",
|
|
4231
|
+
{ key: "pf-entry", className: "dkp-card" },
|
|
4232
|
+
import_react3.default.createElement(
|
|
4233
|
+
"div",
|
|
4234
|
+
{ className: "dkp-rowhead" },
|
|
4235
|
+
import_react3.default.createElement(
|
|
4236
|
+
"span",
|
|
4237
|
+
{ className: "dkp-identity" },
|
|
4238
|
+
import_react3.default.createElement("span", { className: "dkp-name" }, "\u6A21\u578B\u63D0\u4F9B\u5546"),
|
|
4239
|
+
import_react3.default.createElement("span", { className: "dkp-tag" }, custom.length + " \u4E2A\u81EA\u5B9A\u4E49\u8DEF\u7531"),
|
|
4240
|
+
custom.length > 0 ? import_react3.default.createElement("span", {
|
|
4241
|
+
className: "dkp-dot " + (missingKey > 0 ? "warn" : "ok"),
|
|
4242
|
+
role: "img",
|
|
4243
|
+
title: missingKey > 0 ? "\u6709 " + missingKey + " \u4E2A Provider \u672A\u914D\u7F6E\u5BC6\u94A5" : "\u5BC6\u94A5\u5747\u5DF2\u914D\u7F6E",
|
|
4244
|
+
"aria-label": missingKey > 0 ? "\u6709 Provider \u672A\u914D\u7F6E\u5BC6\u94A5" : "\u5BC6\u94A5\u5747\u5DF2\u914D\u7F6E"
|
|
4245
|
+
}) : null
|
|
4246
|
+
),
|
|
4247
|
+
import_react3.default.createElement(
|
|
4248
|
+
"span",
|
|
4249
|
+
{ className: "dkp-actions" },
|
|
4250
|
+
import_react3.default.createElement("button", {
|
|
4251
|
+
type: "button",
|
|
4252
|
+
className: "dkp-btn ghost sm",
|
|
4253
|
+
onClick: () => setPage("providers")
|
|
4254
|
+
}, "\u7BA1\u7406")
|
|
4255
|
+
)
|
|
4256
|
+
),
|
|
4257
|
+
import_react3.default.createElement(
|
|
4258
|
+
"p",
|
|
4259
|
+
{ className: "dkp-hint" },
|
|
4260
|
+
"\u65B0\u589E / \u7F16\u8F91 / \u5220\u9664\u81EA\u5B9A\u4E49\u6A21\u578B Provider\uFF08OpenAI \u517C\u5BB9\u3001Anthropic \u7B49\uFF09\uFF0C\u5199\u5165\u5B98\u65B9\u914D\u7F6E\u5E76\u70ED\u751F\u6548\uFF1BAPI Key \u5B58\u672C\u673A\u51ED\u636E\u5E93\uFF08\u6587\u4EF6\u4EC5 root \u53EF\u8BFB\uFF09\u3002"
|
|
4261
|
+
)
|
|
4262
|
+
));
|
|
4263
|
+
}
|
|
4118
4264
|
if (data && providers.length === 0) {
|
|
4119
4265
|
body.push(import_react3.default.createElement("div", { key: "empty", className: "dkm-note" }, "\u6CA1\u6709\u53EF\u7F16\u8F91\u7684\u6A21\u578B Provider\uFF08Host \u4FA7\u5C1A\u672A\u914D\u7F6E\uFF09"));
|
|
4120
4266
|
}
|
|
@@ -4133,63 +4279,589 @@ function ModelsView() {
|
|
|
4133
4279
|
if (cur && draft) {
|
|
4134
4280
|
body.push(import_react3.default.createElement(
|
|
4135
4281
|
"div",
|
|
4136
|
-
{ key: "prov", className: "dkm-prov" },
|
|
4282
|
+
{ key: "prov", className: "dkm-prov" },
|
|
4283
|
+
import_react3.default.createElement(
|
|
4284
|
+
"div",
|
|
4285
|
+
{ className: "dkm-prov-head" },
|
|
4286
|
+
import_react3.default.createElement("span", { className: "dkm-name" }, cur.displayName),
|
|
4287
|
+
import_react3.default.createElement("span", { className: "dkm-badge" }, cur.kind === "deepseek" ? "\u5B98\u65B9 DeepSeek" : "\u81EA\u5B9A\u4E49\u8DEF\u7531"),
|
|
4288
|
+
import_react3.default.createElement("span", { className: "dkm-sub" }, [cur.api, cur.baseURL].filter(Boolean).join(" \xB7 "))
|
|
4289
|
+
),
|
|
4290
|
+
cur.kind === "deepseek" ? import_react3.default.createElement(
|
|
4291
|
+
"div",
|
|
4292
|
+
{ className: "dkm-controls" },
|
|
4293
|
+
import_react3.default.createElement("span", { className: "dkm-label" }, "\u601D\u8003\u6A21\u5F0F\uFF1A"),
|
|
4294
|
+
import_react3.default.createElement(
|
|
4295
|
+
"select",
|
|
4296
|
+
{ className: "dkm-select", value: draft.thinking, onChange: (e) => patchDraft({ thinking: e.target.value }) },
|
|
4297
|
+
import_react3.default.createElement("option", { value: "enabled" }, "\u5F00\u542F"),
|
|
4298
|
+
import_react3.default.createElement("option", { value: "disabled" }, "\u5173\u95ED")
|
|
4299
|
+
),
|
|
4300
|
+
import_react3.default.createElement("span", { className: "dkm-label" }, "\u9ED8\u8BA4\u5F3A\u5EA6\uFF1A"),
|
|
4301
|
+
import_react3.default.createElement(
|
|
4302
|
+
"select",
|
|
4303
|
+
{ className: "dkm-select", value: draft.defaultEffort, onChange: (e) => patchDraft({ defaultEffort: e.target.value }) },
|
|
4304
|
+
DKM_DS_LEVELS.map((lv) => import_react3.default.createElement("option", { key: lv, value: lv }, DKM_EFFORT_NAMES[lv] || lv))
|
|
4305
|
+
)
|
|
4306
|
+
) : null,
|
|
4307
|
+
import_react3.default.createElement(
|
|
4308
|
+
"div",
|
|
4309
|
+
{ className: "dkm-toolbar" },
|
|
4310
|
+
import_react3.default.createElement("span", { className: "dkm-toolbar-label" }, "\u6279\u91CF\uFF08\u5168\u90E8\u6A21\u578B\uFF09\uFF1A"),
|
|
4311
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u52FE\u9009\u5168\u90E8\u8F93\u5165\u7C7B\u578B\u4E0E\u6807\u6CE8", onClick: () => bulkModels(() => allInputs(true)) }, "\u8F93\u5165\u5168\u9009"),
|
|
4312
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u53D6\u6D88\u5168\u90E8\u8F93\u5165\u52FE\u9009\uFF08\u7559\u7A7A = \u7EE7\u627F\u76EE\u5F55\u9ED8\u8BA4\uFF09", onClick: () => bulkModels(() => allInputs(false)) }, "\u8F93\u5165\u53D6\u6D88\u5168\u9009"),
|
|
4313
|
+
cur.kind !== "deepseek" ? import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u52FE\u9009\u5168\u90E8\u5F3A\u5EA6\u6863\uFF08\u5207\u4E3A\u81EA\u5B9A\u4E49\uFF09", onClick: () => bulkModels(() => allLevels(true)) }, "\u5F3A\u5EA6\u5168\u9009") : null,
|
|
4314
|
+
cur.kind !== "deepseek" ? import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u53D6\u6D88\u5168\u90E8\u5F3A\u5EA6\u6863", onClick: () => bulkModels(() => allLevels(false)) }, "\u5F3A\u5EA6\u53D6\u6D88\u5168\u9009") : null
|
|
4315
|
+
),
|
|
4316
|
+
import_react3.default.createElement(
|
|
4317
|
+
"div",
|
|
4318
|
+
{ style: { display: "flex", flexDirection: "column", gap: "8px" } },
|
|
4319
|
+
draft.models.map(modelRow),
|
|
4320
|
+
import_react3.default.createElement("button", {
|
|
4321
|
+
type: "button",
|
|
4322
|
+
className: "dkm-add",
|
|
4323
|
+
onClick: () => patchDraft({
|
|
4324
|
+
models: draft.models.concat([{ id: "", name: "", contextWindow: "", maxTokens: "", input: ["text"], tags: [], effortsMode: "inherit", effortLevels: {} }])
|
|
4325
|
+
})
|
|
4326
|
+
}, "+ \u6DFB\u52A0\u6A21\u578B")
|
|
4327
|
+
),
|
|
4328
|
+
import_react3.default.createElement(
|
|
4329
|
+
"div",
|
|
4330
|
+
{ className: "dkm-savebar" },
|
|
4331
|
+
import_react3.default.createElement("span", { className: "dkm-msg" }, dirty ? "\u6709\u672A\u4FDD\u5B58\u7684\u4FEE\u6539" : "\u65E0\u672A\u4FDD\u5B58\u4FEE\u6539"),
|
|
4332
|
+
import_react3.default.createElement("button", { type: "button", className: "dkm-save", disabled: !dirty || saving, onClick: save }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u5199\u56DE\u5B98\u65B9\u914D\u7F6E"),
|
|
4333
|
+
import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: saving || snap.loading, onClick: refreshModels }, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u91CD\u65B0\u62C9\u53D6"),
|
|
4334
|
+
msg ? import_react3.default.createElement("span", { className: "dkm-msg " + (msg.ok ? "ok" : "err") }, msg.text) : null
|
|
4335
|
+
)
|
|
4336
|
+
));
|
|
4337
|
+
}
|
|
4338
|
+
return import_react3.default.createElement("div", { className: "dkm-list" }, body);
|
|
4339
|
+
}
|
|
4340
|
+
function ProviderModelRow(props) {
|
|
4341
|
+
const m = props.m;
|
|
4342
|
+
const i = props.i;
|
|
4343
|
+
const check = (v, list, kind) => import_react3.default.createElement(
|
|
4344
|
+
"label",
|
|
4345
|
+
{ key: v[0], className: "dkp-check" },
|
|
4346
|
+
import_react3.default.createElement("input", {
|
|
4347
|
+
type: "checkbox",
|
|
4348
|
+
checked: list.indexOf(v[0]) >= 0,
|
|
4349
|
+
onChange: () => {
|
|
4350
|
+
const next = dkmToggleIn(list, v[0]);
|
|
4351
|
+
props.onPatch(i, kind === "input" ? { input: next.length > 0 ? next : ["text"] } : { tags: next });
|
|
4352
|
+
}
|
|
4353
|
+
}),
|
|
4354
|
+
v[1]
|
|
4355
|
+
);
|
|
4356
|
+
return import_react3.default.createElement(
|
|
4357
|
+
"div",
|
|
4358
|
+
{ className: "dkp-model-entry" },
|
|
4359
|
+
import_react3.default.createElement(
|
|
4360
|
+
"div",
|
|
4361
|
+
{ className: "dkp-model-row" },
|
|
4362
|
+
import_react3.default.createElement("input", { className: "dkp-input", placeholder: "\u6A21\u578B id\uFF08\u5FC5\u586B\uFF09", value: m.id, onChange: (e) => props.onPatch(i, { id: e.target.value }) }),
|
|
4363
|
+
import_react3.default.createElement("input", { className: "dkp-input", placeholder: "\u663E\u793A\u540D\u79F0\uFF08\u53EF\u9009\uFF09", value: m.name, onChange: (e) => props.onPatch(i, { name: e.target.value }) }),
|
|
4364
|
+
import_react3.default.createElement("input", { className: "dkp-input", placeholder: "\u4E0A\u4E0B\u6587\u7A97\u53E3", inputMode: "numeric", value: m.contextWindow, onChange: (e) => props.onPatch(i, { contextWindow: e.target.value }) }),
|
|
4365
|
+
import_react3.default.createElement("input", { className: "dkp-input", placeholder: "\u6700\u5927\u8F93\u51FA", inputMode: "numeric", value: m.maxTokens, onChange: (e) => props.onPatch(i, { maxTokens: e.target.value }) }),
|
|
4366
|
+
import_react3.default.createElement("button", { type: "button", className: "dkp-iconbtn danger", title: "\u5220\u9664\u8BE5\u6A21\u578B", "aria-label": "\u5220\u9664\u6A21\u578B", onClick: () => props.onDel(i) }, "\u2715")
|
|
4367
|
+
),
|
|
4368
|
+
import_react3.default.createElement(
|
|
4369
|
+
"div",
|
|
4370
|
+
{ className: "dkp-model-opts" },
|
|
4371
|
+
import_react3.default.createElement(
|
|
4372
|
+
"div",
|
|
4373
|
+
{ className: "dkp-checks" },
|
|
4374
|
+
import_react3.default.createElement("span", { className: "dkp-flabel" }, "\u8F93\u5165\u7C7B\u578B\uFF1A"),
|
|
4375
|
+
DKM_MODALITIES.map((v) => check(v, m.input, "input")),
|
|
4376
|
+
import_react3.default.createElement("span", { className: "dkp-flabel dkp-dim", title: "\u6807\u6CE8\u4EC5\u5728\u672C\u9762\u677F\u5C55\u793A\u4E0E\u6301\u4E45\u5316\uFF0C\u4E0D\u53C2\u4E0E\u8BF7\u6C42\u8DEF\u7531\uFF08\u5B98\u65B9 schema \u53EA\u63A5\u53D7\u6587\u672C/\u56FE\u7247\uFF09" }, "\u6807\u6CE8\uFF1A"),
|
|
4377
|
+
DKM_TAGS.map((v) => check(v, m.tags, "tags")),
|
|
4378
|
+
import_react3.default.createElement("button", { type: "button", className: "dkp-mini", title: "\u4E00\u952E\u52FE\u9009\u5168\u90E8\u8F93\u5165\u7C7B\u578B\u4E0E\u6807\u6CE8", onClick: () => props.onPatch(i, dkmAllInputs(true)) }, "\u5168\u9009"),
|
|
4379
|
+
import_react3.default.createElement("button", { type: "button", className: "dkp-mini", title: "\u4E00\u952E\u53D6\u6D88\u5168\u90E8\u52FE\u9009", onClick: () => props.onPatch(i, dkmAllInputs(false)) }, "\u53D6\u6D88\u5168\u9009")
|
|
4380
|
+
),
|
|
4381
|
+
import_react3.default.createElement(
|
|
4382
|
+
"div",
|
|
4383
|
+
{ className: "dkp-checks" },
|
|
4384
|
+
import_react3.default.createElement("span", { className: "dkp-flabel" }, "\u601D\u8003\u5F3A\u5EA6\uFF1A"),
|
|
4385
|
+
import_react3.default.createElement(
|
|
4386
|
+
"select",
|
|
4387
|
+
{
|
|
4388
|
+
className: "dkp-input dkp-select dkp-select-sm",
|
|
4389
|
+
value: m.effortsMode,
|
|
4390
|
+
onChange: (e) => props.onPatch(i, {
|
|
4391
|
+
effortsMode: e.target.value,
|
|
4392
|
+
effortLevels: e.target.value === "custom" && m.effortsMode !== "custom" ? { off: true, low: true, high: true } : m.effortLevels
|
|
4393
|
+
})
|
|
4394
|
+
},
|
|
4395
|
+
import_react3.default.createElement("option", { value: "inherit" }, "\u8DDF\u968F\u76EE\u5F55\u9ED8\u8BA4"),
|
|
4396
|
+
import_react3.default.createElement("option", { value: "off" }, "\u4E0D\u652F\u6301\u601D\u8003"),
|
|
4397
|
+
import_react3.default.createElement("option", { value: "custom" }, "\u81EA\u5B9A\u4E49\u6863\u4F4D")
|
|
4398
|
+
),
|
|
4399
|
+
m.effortsMode === "custom" ? DKM_PI_LEVELS.map((lv) => import_react3.default.createElement(
|
|
4400
|
+
"label",
|
|
4401
|
+
{ key: lv, className: "dkp-check" },
|
|
4402
|
+
import_react3.default.createElement("input", {
|
|
4403
|
+
type: "checkbox",
|
|
4404
|
+
checked: !!m.effortLevels[lv],
|
|
4405
|
+
onChange: () => {
|
|
4406
|
+
const nl = Object.assign({}, m.effortLevels);
|
|
4407
|
+
nl[lv] = !nl[lv];
|
|
4408
|
+
props.onPatch(i, { effortLevels: nl });
|
|
4409
|
+
}
|
|
4410
|
+
}),
|
|
4411
|
+
DKM_EFFORT_NAMES[lv] || lv
|
|
4412
|
+
)) : null,
|
|
4413
|
+
import_react3.default.createElement("button", { type: "button", className: "dkp-mini", title: "\u4E00\u952E\u52FE\u9009\u5168\u90E8\u5F3A\u5EA6\u6863\uFF08\u5207\u4E3A\u81EA\u5B9A\u4E49\uFF09", onClick: () => props.onPatch(i, dkmAllLevels(true)) }, "\u5168\u9009"),
|
|
4414
|
+
import_react3.default.createElement("button", { type: "button", className: "dkp-mini", title: "\u4E00\u952E\u53D6\u6D88\u5168\u90E8\u5F3A\u5EA6\u6863", onClick: () => props.onPatch(i, dkmAllLevels(false)) }, "\u53D6\u6D88\u5168\u9009")
|
|
4415
|
+
)
|
|
4416
|
+
)
|
|
4417
|
+
);
|
|
4418
|
+
}
|
|
4419
|
+
function ProvidersPage(props) {
|
|
4420
|
+
const data = props.data;
|
|
4421
|
+
const providers = props.providers || [];
|
|
4422
|
+
const piProviders = providers.filter((p) => p.kind === "pi-ai");
|
|
4423
|
+
const [pfMode, setPfMode] = import_react3.default.useState(null);
|
|
4424
|
+
const [pfDraft, setPfDraft] = import_react3.default.useState(null);
|
|
4425
|
+
const [pfDirty, setPfDirty] = import_react3.default.useState(false);
|
|
4426
|
+
const [pfSaving, setPfSaving] = import_react3.default.useState(false);
|
|
4427
|
+
const [pfMsg, setPfMsg] = import_react3.default.useState(null);
|
|
4428
|
+
const [pfDelArm, setPfDelArm] = import_react3.default.useState(null);
|
|
4429
|
+
const [pfFetching, setPfFetching] = import_react3.default.useState(false);
|
|
4430
|
+
const [pfFetchedList, setPfFetchedList] = import_react3.default.useState(null);
|
|
4431
|
+
const openPfCreate = () => {
|
|
4432
|
+
setPfMode("create");
|
|
4433
|
+
setPfDraft(emptyProviderForm());
|
|
4434
|
+
setPfDirty(false);
|
|
4435
|
+
setPfMsg(null);
|
|
4436
|
+
setPfDelArm(null);
|
|
4437
|
+
setPfFetchedList(null);
|
|
4438
|
+
};
|
|
4439
|
+
const openPfEdit = (p) => {
|
|
4440
|
+
setPfMode("edit");
|
|
4441
|
+
setPfDraft(providerFormFromProvider(p));
|
|
4442
|
+
setPfDirty(false);
|
|
4443
|
+
setPfMsg(null);
|
|
4444
|
+
setPfDelArm(null);
|
|
4445
|
+
setPfFetchedList(null);
|
|
4446
|
+
};
|
|
4447
|
+
const closePf = () => {
|
|
4448
|
+
setPfMode(null);
|
|
4449
|
+
setPfDraft(null);
|
|
4450
|
+
setPfDirty(false);
|
|
4451
|
+
setPfMsg(null);
|
|
4452
|
+
setPfDelArm(null);
|
|
4453
|
+
setPfFetchedList(null);
|
|
4454
|
+
};
|
|
4455
|
+
const patchPf = (patch) => {
|
|
4456
|
+
setPfDraft(Object.assign({}, pfDraft, patch));
|
|
4457
|
+
setPfDirty(true);
|
|
4458
|
+
setPfMsg(null);
|
|
4459
|
+
};
|
|
4460
|
+
const patchPfModel = (i, patch) => {
|
|
4461
|
+
const models = pfDraft.models.slice();
|
|
4462
|
+
models[i] = Object.assign({}, models[i], patch);
|
|
4463
|
+
patchPf({ models });
|
|
4464
|
+
};
|
|
4465
|
+
const delPfModel = (i) => patchPf({ models: pfDraft.models.filter((_, j) => j !== i) });
|
|
4466
|
+
const addPfModel = () => patchPf({ models: pfDraft.models.concat([emptyModelDraft()]) });
|
|
4467
|
+
const togglePfModel = (id, name, on) => {
|
|
4468
|
+
const base = pfDraft.models.filter((m) => String(m.id || "").trim());
|
|
4469
|
+
if (on) {
|
|
4470
|
+
if (base.some((m) => String(m.id).trim() === id)) return;
|
|
4471
|
+
base.push(Object.assign(emptyModelDraft(), { id, name: name || "", input: pfDraft.defaultInput.slice() }));
|
|
4472
|
+
} else {
|
|
4473
|
+
const i = base.findIndex((m) => String(m.id).trim() === id);
|
|
4474
|
+
if (i >= 0) base.splice(i, 1);
|
|
4475
|
+
}
|
|
4476
|
+
patchPf({ models: base });
|
|
4477
|
+
};
|
|
4478
|
+
const setAllPfModels = (on) => {
|
|
4479
|
+
const base = [];
|
|
4480
|
+
if (on && pfFetchedList) {
|
|
4481
|
+
for (const mm of pfFetchedList) {
|
|
4482
|
+
const id = String(mm && mm.id || "").trim();
|
|
4483
|
+
if (!id) continue;
|
|
4484
|
+
base.push(Object.assign(emptyModelDraft(), { id, name: mm && mm.name || "", input: pfDraft.defaultInput.slice() }));
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
patchPf({ models: base });
|
|
4488
|
+
};
|
|
4489
|
+
const pfSelectedCount = () => pfDraft ? pfDraft.models.filter((m) => String(m.id || "").trim()).length : 0;
|
|
4490
|
+
const pfModelsPayload = () => pfDraft.models.map((m) => ({
|
|
4491
|
+
id: String(m.id || "").trim(),
|
|
4492
|
+
name: String(m.name || "").trim(),
|
|
4493
|
+
contextWindow: m.contextWindow === "" || m.contextWindow == null ? void 0 : Number(m.contextWindow),
|
|
4494
|
+
maxTokens: m.maxTokens === "" || m.maxTokens == null ? void 0 : Number(m.maxTokens),
|
|
4495
|
+
input: m.input,
|
|
4496
|
+
tags: m.tags,
|
|
4497
|
+
effortsMode: m.effortsMode,
|
|
4498
|
+
effortLevels: m.effortLevels,
|
|
4499
|
+
raw: m.raw
|
|
4500
|
+
}));
|
|
4501
|
+
const fetchPfModels = () => {
|
|
4502
|
+
if (!pfDraft || pfFetching) return;
|
|
4503
|
+
setPfFetching(true);
|
|
4504
|
+
setPfMsg(null);
|
|
4505
|
+
fetch("dsh-dock/models", {
|
|
4506
|
+
method: "POST",
|
|
4507
|
+
headers: { "content-type": "application/json" },
|
|
4508
|
+
body: JSON.stringify({
|
|
4509
|
+
action: "listModels",
|
|
4510
|
+
baseURL: pfDraft.baseURL,
|
|
4511
|
+
api: pfDraft.api,
|
|
4512
|
+
apiKeyEnv: pfDraft.apiKeyEnv,
|
|
4513
|
+
apiKey: pfDraft.apiKey
|
|
4514
|
+
}),
|
|
4515
|
+
signal: AbortSignal.timeout(3e4)
|
|
4516
|
+
}).then((res) => res.json().then((b) => ({ status: res.status, body: b })).catch(() => ({ status: res.status, body: {} }))).then((r) => {
|
|
4517
|
+
if (r.status === 200 && r.body && r.body.ok) {
|
|
4518
|
+
setPfFetchedList(Array.isArray(r.body.models) ? r.body.models : []);
|
|
4519
|
+
} else {
|
|
4520
|
+
setPfMsg({ ok: false, text: r.body && r.body.error || "HTTP " + r.status });
|
|
4521
|
+
}
|
|
4522
|
+
}).catch((e) => setPfMsg({ ok: false, text: e && e.message || String(e) })).then(() => setPfFetching(false));
|
|
4523
|
+
};
|
|
4524
|
+
const savePf = () => {
|
|
4525
|
+
if (!pfDraft || pfSaving) return;
|
|
4526
|
+
const route = pfDraft.route.trim();
|
|
4527
|
+
const baseURL = pfDraft.baseURL.trim();
|
|
4528
|
+
const apiKey = pfDraft.apiKey.trim();
|
|
4529
|
+
let apiKeyEnv = pfDraft.apiKeyEnv.trim();
|
|
4530
|
+
if (apiKey && !apiKeyEnv) {
|
|
4531
|
+
apiKeyEnv = dkmEnvFromRoute(route);
|
|
4532
|
+
setPfDraft(Object.assign({}, pfDraft, { apiKeyEnv }));
|
|
4533
|
+
}
|
|
4534
|
+
const models = pfModelsPayload();
|
|
4535
|
+
if (!route) {
|
|
4536
|
+
setPfMsg({ ok: false, text: "\u8DEF\u7531 key \u4E0D\u80FD\u4E3A\u7A7A\uFF08\u5982 modelscope\uFF09" });
|
|
4537
|
+
return;
|
|
4538
|
+
}
|
|
4539
|
+
if (!DKM_ROUTE_KEY_RE.test(route)) {
|
|
4540
|
+
setPfMsg({ ok: false, text: "\u8DEF\u7531 key \u975E\u6CD5\uFF1A\u53EA\u80FD\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u4E0E . _ -\uFF0C\u4E14\u4EE5\u5B57\u6BCD/\u6570\u5B57\u5F00\u5934" });
|
|
4541
|
+
return;
|
|
4542
|
+
}
|
|
4543
|
+
if (!/^https?:\/\//i.test(baseURL)) {
|
|
4544
|
+
setPfMsg({ ok: false, text: "baseURL \u987B\u4EE5 http:// \u6216 https:// \u5F00\u5934" });
|
|
4545
|
+
return;
|
|
4546
|
+
}
|
|
4547
|
+
const ids = models.map((m) => m.id);
|
|
4548
|
+
if (ids.length === 0 || ids.some((x) => !x)) {
|
|
4549
|
+
setPfMsg({ ok: false, text: "\u6BCF\u4E2A\u6A21\u578B\u90FD\u8981\u6709 id\uFF08\u53EF\u70B9\u300C\u83B7\u53D6\u6A21\u578B\u5217\u8868\u300D\u81EA\u52A8\u62C9\u53D6\uFF09" });
|
|
4550
|
+
return;
|
|
4551
|
+
}
|
|
4552
|
+
if (new Set(ids).size !== ids.length) {
|
|
4553
|
+
setPfMsg({ ok: false, text: "\u6A21\u578B id \u6709\u91CD\u590D" });
|
|
4554
|
+
return;
|
|
4555
|
+
}
|
|
4556
|
+
const profile = Object.assign({}, pfDraft.extra || {});
|
|
4557
|
+
const dn = pfDraft.displayName.trim();
|
|
4558
|
+
if (dn) profile.displayName = dn;
|
|
4559
|
+
else delete profile.displayName;
|
|
4560
|
+
profile.api = pfDraft.api;
|
|
4561
|
+
profile.baseURL = baseURL;
|
|
4562
|
+
if (apiKeyEnv) profile.apiKeyEnv = apiKeyEnv;
|
|
4563
|
+
else delete profile.apiKeyEnv;
|
|
4564
|
+
profile.defaultInput = pfDraft.defaultInput;
|
|
4565
|
+
profile.models = models;
|
|
4566
|
+
const payload = {
|
|
4567
|
+
action: pfMode === "create" ? "create" : "update",
|
|
4568
|
+
route,
|
|
4569
|
+
profile,
|
|
4570
|
+
revisions: data && data.revisions || {}
|
|
4571
|
+
};
|
|
4572
|
+
if (apiKey) payload.apiKey = apiKey;
|
|
4573
|
+
setPfSaving(true);
|
|
4574
|
+
setPfMsg(null);
|
|
4575
|
+
fetch("dsh-dock/models", {
|
|
4576
|
+
method: "POST",
|
|
4577
|
+
headers: { "content-type": "application/json" },
|
|
4578
|
+
body: JSON.stringify(payload),
|
|
4579
|
+
signal: AbortSignal.timeout(3e4)
|
|
4580
|
+
}).then((res) => res.json().then((b) => ({ status: res.status, body: b })).catch(() => ({ status: res.status, body: {} }))).then((r) => {
|
|
4581
|
+
if (r.status === 200 && r.body && r.body.ok) {
|
|
4582
|
+
setPfMsg({ ok: true, text: "Provider\u300C" + route + "\u300D\u5DF2" + (pfMode === "create" ? "\u65B0\u589E" : "\u66F4\u65B0") + "\uFF1B\u4F1A\u8BDD\u6A21\u578B\u9009\u62E9\u5668\u5373\u65F6\u53EF\u9009" });
|
|
4583
|
+
setPfMode(null);
|
|
4584
|
+
setPfDraft(null);
|
|
4585
|
+
setPfDirty(false);
|
|
4586
|
+
modelsStore.load();
|
|
4587
|
+
} else {
|
|
4588
|
+
setPfMsg({ ok: false, text: r.body && r.body.error || "HTTP " + r.status });
|
|
4589
|
+
}
|
|
4590
|
+
}).catch((e) => setPfMsg({ ok: false, text: e && e.message || String(e) })).then(() => setPfSaving(false));
|
|
4591
|
+
};
|
|
4592
|
+
const deletePf = (p) => {
|
|
4593
|
+
const route = p.route || p.id;
|
|
4594
|
+
if (pfDelArm !== route) {
|
|
4595
|
+
setPfDelArm(route);
|
|
4596
|
+
setPfMsg(null);
|
|
4597
|
+
return;
|
|
4598
|
+
}
|
|
4599
|
+
setPfDelArm(null);
|
|
4600
|
+
setPfSaving(true);
|
|
4601
|
+
setPfMsg(null);
|
|
4602
|
+
fetch("dsh-dock/models", {
|
|
4603
|
+
method: "POST",
|
|
4604
|
+
headers: { "content-type": "application/json" },
|
|
4605
|
+
body: JSON.stringify({ action: "delete", route, revisions: data && data.revisions || {} }),
|
|
4606
|
+
signal: AbortSignal.timeout(2e4)
|
|
4607
|
+
}).then((res) => res.json().then((b) => ({ status: res.status, body: b })).catch(() => ({ status: res.status, body: {} }))).then((r) => {
|
|
4608
|
+
if (r.status === 200 && r.body && r.body.ok) {
|
|
4609
|
+
setPfMsg({ ok: true, text: "Provider\u300C" + route + "\u300D\u5DF2\u5220\u9664" });
|
|
4610
|
+
if (pfMode === "edit" && pfDraft && pfDraft.route === route) {
|
|
4611
|
+
setPfMode(null);
|
|
4612
|
+
setPfDraft(null);
|
|
4613
|
+
}
|
|
4614
|
+
modelsStore.load();
|
|
4615
|
+
} else {
|
|
4616
|
+
setPfMsg({ ok: false, text: r.body && r.body.error || "HTTP " + r.status });
|
|
4617
|
+
}
|
|
4618
|
+
}).catch((e) => setPfMsg({ ok: false, text: e && e.message || String(e) })).then(() => setPfSaving(false));
|
|
4619
|
+
};
|
|
4620
|
+
const openedRef = import_react3.default.useRef(false);
|
|
4621
|
+
import_react3.default.useEffect(() => {
|
|
4622
|
+
if (props.openCreate && !openedRef.current) {
|
|
4623
|
+
openedRef.current = true;
|
|
4624
|
+
openPfCreate();
|
|
4625
|
+
if (typeof props.onCreateHandled === "function") props.onCreateHandled();
|
|
4626
|
+
}
|
|
4627
|
+
}, []);
|
|
4628
|
+
const input = (p) => import_react3.default.createElement("input", Object.assign({ className: "dkp-input" }, p));
|
|
4629
|
+
const field = (label, node, hint) => import_react3.default.createElement(
|
|
4630
|
+
"div",
|
|
4631
|
+
{ className: "dkp-field", key: label },
|
|
4632
|
+
import_react3.default.createElement("label", { className: "dkp-flabel" }, label),
|
|
4633
|
+
node,
|
|
4634
|
+
hint ? import_react3.default.createElement("p", { className: "dkp-hint" }, hint) : null
|
|
4635
|
+
);
|
|
4636
|
+
const editor = !pfDraft ? null : import_react3.default.createElement(
|
|
4637
|
+
"div",
|
|
4638
|
+
{ className: "dkp-editor" },
|
|
4639
|
+
import_react3.default.createElement(
|
|
4640
|
+
"div",
|
|
4641
|
+
{ className: "dkp-editor-head" },
|
|
4642
|
+
import_react3.default.createElement("span", { className: "dkp-editor-title" }, pfMode === "create" ? "\u65B0\u589E Provider" : "\u7F16\u8F91 Provider"),
|
|
4643
|
+
pfMode === "edit" ? import_react3.default.createElement("span", { className: "dkp-editor-route" }, pfDraft.route) : null
|
|
4644
|
+
),
|
|
4645
|
+
field("\u8DEF\u7531 key", input({
|
|
4646
|
+
value: pfDraft.route,
|
|
4647
|
+
disabled: pfMode === "edit",
|
|
4648
|
+
placeholder: "acme-gateway",
|
|
4649
|
+
onChange: (e) => patchPf({ route: e.target.value })
|
|
4650
|
+
}), pfMode === "edit" ? "\u8DEF\u7531 key \u662F\u914D\u7F6E\u952E\uFF0C\u4FDD\u5B58\u540E\u4E0D\u5EFA\u8BAE\u4FEE\u6539\u3002" : "\u552F\u4E00\u6807\u8BC6\uFF1A\u53EA\u80FD\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u4E0E . _ -\uFF0C\u4E14\u4EE5\u5B57\u6BCD/\u6570\u5B57\u5F00\u5934\u3002"),
|
|
4651
|
+
field("\u663E\u793A\u540D\u79F0", input({
|
|
4652
|
+
value: pfDraft.displayName,
|
|
4653
|
+
placeholder: pfDraft.route || "\u5982 \u9B54\u642D ModelScope",
|
|
4654
|
+
onChange: (e) => patchPf({ displayName: e.target.value })
|
|
4655
|
+
})),
|
|
4656
|
+
field("baseURL", input({
|
|
4657
|
+
value: pfDraft.baseURL,
|
|
4658
|
+
placeholder: pfDraft.api === "anthropic-messages" ? "https://gateway.example" : "https://gateway.example/v1",
|
|
4659
|
+
onChange: (e) => patchPf({ baseURL: e.target.value })
|
|
4660
|
+
}), "OpenAI \u517C\u5BB9\u7AEF\u70B9\u901A\u5E38\u4EE5 /v1 \u7ED3\u5C3E\uFF1BAnthropic Messages \u7531 SDK \u81EA\u884C\u8FFD\u52A0 /v1/messages\u3002"),
|
|
4661
|
+
field("API \u534F\u8BAE", import_react3.default.createElement(
|
|
4662
|
+
"select",
|
|
4663
|
+
{
|
|
4664
|
+
className: "dkp-input dkp-select",
|
|
4665
|
+
value: pfDraft.api,
|
|
4666
|
+
onChange: (e) => patchPf({ api: e.target.value })
|
|
4667
|
+
},
|
|
4668
|
+
DKM_APIS.map(([v, label]) => import_react3.default.createElement("option", { key: v, value: v }, label))
|
|
4669
|
+
)),
|
|
4670
|
+
field("API Key", import_react3.default.createElement("input", {
|
|
4671
|
+
className: "dkp-input",
|
|
4672
|
+
type: "password",
|
|
4673
|
+
autoComplete: "new-password",
|
|
4674
|
+
placeholder: pfMode === "edit" ? "\u7559\u7A7A = \u4E0D\u6539\u52A8\u5DF2\u5B58\u5BC6\u94A5" : "sk-\u2026\uFF08\u4EC5\u672C\u6B21\u5199\u5165\u672C\u673A\u51ED\u636E\u5E93\uFF0C\u4E0D\u56DE\u663E\uFF09",
|
|
4675
|
+
value: pfDraft.apiKey,
|
|
4676
|
+
onChange: (e) => patchPf({ apiKey: e.target.value })
|
|
4677
|
+
})),
|
|
4678
|
+
import_react3.default.createElement(
|
|
4679
|
+
"details",
|
|
4680
|
+
{ className: "dkp-customized" },
|
|
4681
|
+
import_react3.default.createElement("summary", { className: "dkp-summary" }, "\u81EA\u5B9A\u4E49\u8BBE\u7F6E"),
|
|
4137
4682
|
import_react3.default.createElement(
|
|
4138
4683
|
"div",
|
|
4139
|
-
{ className: "
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4684
|
+
{ className: "dkp-custombody" },
|
|
4685
|
+
field("apiKeyEnv", input({
|
|
4686
|
+
value: pfDraft.apiKeyEnv,
|
|
4687
|
+
placeholder: "\u7559\u7A7A = \u6309\u8DEF\u7531 key \u81EA\u52A8\u751F\u6210\uFF08" + (dkmEnvFromRoute(pfDraft.route) || "ROUTE_API_KEY") + "\uFF09",
|
|
4688
|
+
onChange: (e) => patchPf({ apiKeyEnv: e.target.value })
|
|
4689
|
+
}), "\u51ED\u636E\u5E93\u6761\u76EE\u540D\uFF1B\u7559\u7A7A\u65F6\u6309\u8DEF\u7531 key \u63A8\u5BFC\uFF0C\u4E00\u822C\u65E0\u9700\u586B\u5199\u3002"),
|
|
4690
|
+
import_react3.default.createElement(
|
|
4691
|
+
"div",
|
|
4692
|
+
{ className: "dkp-field" },
|
|
4693
|
+
import_react3.default.createElement("span", { className: "dkp-flabel" }, "\u9ED8\u8BA4\u8F93\u5165\u7C7B\u578B"),
|
|
4694
|
+
import_react3.default.createElement(
|
|
4695
|
+
"div",
|
|
4696
|
+
{ className: "dkp-checks" },
|
|
4697
|
+
DKM_MODALITIES.map(([v, label]) => import_react3.default.createElement(
|
|
4698
|
+
"label",
|
|
4699
|
+
{ key: v, className: "dkp-check" },
|
|
4700
|
+
import_react3.default.createElement("input", {
|
|
4701
|
+
type: "checkbox",
|
|
4702
|
+
checked: pfDraft.defaultInput.indexOf(v) >= 0,
|
|
4703
|
+
onChange: () => {
|
|
4704
|
+
const next = dkmToggleIn(pfDraft.defaultInput, v);
|
|
4705
|
+
patchPf({ defaultInput: next.length > 0 ? next : ["text"] });
|
|
4706
|
+
}
|
|
4707
|
+
}),
|
|
4708
|
+
label
|
|
4709
|
+
)),
|
|
4710
|
+
import_react3.default.createElement("span", { className: "dkp-hint" }, "\u6A21\u578B\u672A\u5355\u72EC\u58F0\u660E\u8F93\u5165\u7C7B\u578B\u65F6\u7EE7\u627F\u8FD9\u91CC\u3002")
|
|
4711
|
+
)
|
|
4712
|
+
)
|
|
4713
|
+
)
|
|
4714
|
+
),
|
|
4715
|
+
import_react3.default.createElement(
|
|
4716
|
+
"section",
|
|
4717
|
+
{ className: "dkp-catalog", "aria-label": "\u6A21\u578B" },
|
|
4718
|
+
import_react3.default.createElement(
|
|
4145
4719
|
"div",
|
|
4146
|
-
{ className: "
|
|
4147
|
-
import_react3.default.createElement("span", { className: "dkm-label" }, "\u601D\u8003\u6A21\u5F0F\uFF1A"),
|
|
4720
|
+
{ className: "dkp-catalog-head" },
|
|
4148
4721
|
import_react3.default.createElement(
|
|
4149
|
-
"
|
|
4150
|
-
{ className: "
|
|
4151
|
-
import_react3.default.createElement("
|
|
4152
|
-
import_react3.default.createElement(
|
|
4722
|
+
"div",
|
|
4723
|
+
{ className: "dkp-catalog-titlewrap" },
|
|
4724
|
+
import_react3.default.createElement("span", { className: "dkp-catalog-title" }, "\u6A21\u578B"),
|
|
4725
|
+
import_react3.default.createElement(
|
|
4726
|
+
"span",
|
|
4727
|
+
{ className: "dkp-catalog-meta" },
|
|
4728
|
+
"\u5DF2\u9009 " + pfSelectedCount() + " \u4E2A" + (pfFetchedList ? " / \u4E0A\u6E38\u5171 " + pfFetchedList.length + " \u4E2A" : "")
|
|
4729
|
+
)
|
|
4153
4730
|
),
|
|
4154
|
-
import_react3.default.createElement("span", { className: "dkm-label" }, "\u9ED8\u8BA4\u5F3A\u5EA6\uFF1A"),
|
|
4155
4731
|
import_react3.default.createElement(
|
|
4156
|
-
"
|
|
4157
|
-
{ className: "
|
|
4158
|
-
|
|
4732
|
+
"div",
|
|
4733
|
+
{ className: "dkp-actions" },
|
|
4734
|
+
import_react3.default.createElement("button", {
|
|
4735
|
+
type: "button",
|
|
4736
|
+
className: "dkp-btn ghost sm",
|
|
4737
|
+
disabled: pfFetching || !pfDraft.baseURL,
|
|
4738
|
+
title: "\u8C03\u7528 baseURL/models \u62C9\u53D6\u8BE5\u7AEF\u70B9\u53EF\u7528\u6A21\u578B\uFF0C\u52FE\u9009\u540E\u52A0\u5165\u4E0B\u65B9\u5217\u8868",
|
|
4739
|
+
onClick: fetchPfModels
|
|
4740
|
+
}, pfFetching ? "\u62C9\u53D6\u4E2D\u2026" : "\u83B7\u53D6\u6A21\u578B\u5217\u8868"),
|
|
4741
|
+
pfFetchedList && pfFetchedList.length > 0 ? import_react3.default.createElement("button", { type: "button", className: "dkp-btn ghost sm", title: "\u52FE\u9009\u4E0A\u6E38\u8FD4\u56DE\u7684\u5168\u90E8\u6A21\u578B", onClick: () => setAllPfModels(true) }, "\u5168\u9009") : null,
|
|
4742
|
+
pfFetchedList && pfFetchedList.length > 0 ? import_react3.default.createElement("button", { type: "button", className: "dkp-btn ghost sm", title: "\u6E05\u7A7A\u5DF2\u52FE\u9009\u7684\u6A21\u578B", onClick: () => setAllPfModels(false) }, "\u6E05\u7A7A") : null
|
|
4159
4743
|
)
|
|
4160
|
-
) : null,
|
|
4161
|
-
import_react3.default.createElement(
|
|
4162
|
-
"div",
|
|
4163
|
-
{ className: "dkm-toolbar" },
|
|
4164
|
-
import_react3.default.createElement("span", { className: "dkm-toolbar-label" }, "\u6279\u91CF\uFF08\u5168\u90E8\u6A21\u578B\uFF09\uFF1A"),
|
|
4165
|
-
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u52FE\u9009\u5168\u90E8\u8F93\u5165\u7C7B\u578B\u4E0E\u6807\u6CE8", onClick: () => bulkModels(() => allInputs(true)) }, "\u8F93\u5165\u5168\u9009"),
|
|
4166
|
-
import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u53D6\u6D88\u5168\u90E8\u8F93\u5165\u52FE\u9009\uFF08\u7559\u7A7A = \u7EE7\u627F\u76EE\u5F55\u9ED8\u8BA4\uFF09", onClick: () => bulkModels(() => allInputs(false)) }, "\u8F93\u5165\u53D6\u6D88\u5168\u9009"),
|
|
4167
|
-
cur.kind !== "deepseek" ? import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u52FE\u9009\u5168\u90E8\u5F3A\u5EA6\u6863\uFF08\u5207\u4E3A\u81EA\u5B9A\u4E49\uFF09", onClick: () => bulkModels(() => allLevels(true)) }, "\u5F3A\u5EA6\u5168\u9009") : null,
|
|
4168
|
-
cur.kind !== "deepseek" ? import_react3.default.createElement("button", { type: "button", className: "dkm-mini", title: "\u5168\u90E8\u6A21\u578B\uFF1A\u53D6\u6D88\u5168\u90E8\u5F3A\u5EA6\u6863", onClick: () => bulkModels(() => allLevels(false)) }, "\u5F3A\u5EA6\u53D6\u6D88\u5168\u9009") : null
|
|
4169
4744
|
),
|
|
4170
|
-
import_react3.default.createElement(
|
|
4745
|
+
pfFetchedList ? import_react3.default.createElement(
|
|
4171
4746
|
"div",
|
|
4172
|
-
{
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4747
|
+
{ className: "dkp-picker" },
|
|
4748
|
+
pfFetchedList.length === 0 ? import_react3.default.createElement("div", { className: "dkp-hint" }, "\u4E0A\u6E38\u6CA1\u6709\u8FD4\u56DE\u4EFB\u4F55\u6A21\u578B") : pfFetchedList.map((mm) => {
|
|
4749
|
+
const id = String(mm && mm.id || "").trim();
|
|
4750
|
+
if (!id) return null;
|
|
4751
|
+
const checked = pfDraft.models.some((m) => String(m.id || "").trim() === id);
|
|
4752
|
+
return import_react3.default.createElement(
|
|
4753
|
+
"label",
|
|
4754
|
+
{ key: id },
|
|
4755
|
+
import_react3.default.createElement("input", {
|
|
4756
|
+
type: "checkbox",
|
|
4757
|
+
checked,
|
|
4758
|
+
onChange: () => togglePfModel(id, mm && mm.name || "", !checked)
|
|
4759
|
+
}),
|
|
4760
|
+
import_react3.default.createElement("span", { className: "dkp-picker-id" }, id),
|
|
4761
|
+
mm && mm.name ? import_react3.default.createElement("span", { className: "dkp-picker-name" }, mm.name) : null
|
|
4762
|
+
);
|
|
4763
|
+
})
|
|
4764
|
+
) : null,
|
|
4765
|
+
pfDraft.models.length === 0 ? import_react3.default.createElement("div", { className: "dkp-empty" }, "\u8FD8\u6CA1\u6709\u6A21\u578B\u2014\u2014\u70B9\u300C\u83B7\u53D6\u6A21\u578B\u5217\u8868\u300D\u52FE\u9009\u4E0A\u6E38\u6A21\u578B\uFF0C\u6216\u300C\u6DFB\u52A0\u6A21\u578B\u300D\u624B\u52A8\u586B\u5199\u3002") : import_react3.default.createElement(
|
|
4766
|
+
"div",
|
|
4767
|
+
{ className: "dkp-model-list" },
|
|
4768
|
+
pfDraft.models.map((m, i) => import_react3.default.createElement(ProviderModelRow, { key: i, m, i, onPatch: patchPfModel, onDel: delPfModel }))
|
|
4181
4769
|
),
|
|
4770
|
+
import_react3.default.createElement("button", { type: "button", className: "dkp-addmodel", onClick: addPfModel }, "\uFF0B \u6DFB\u52A0\u6A21\u578B")
|
|
4771
|
+
),
|
|
4772
|
+
pfMsg && !pfMsg.ok ? import_react3.default.createElement("p", { className: "dkp-error" }, pfMsg.text) : null,
|
|
4773
|
+
import_react3.default.createElement(
|
|
4774
|
+
"div",
|
|
4775
|
+
{ className: "dkp-editor-actions" },
|
|
4776
|
+
import_react3.default.createElement("span", { className: "dkp-hint" }, pfDirty ? "\u6709\u672A\u4FDD\u5B58\u7684\u4FEE\u6539" : ""),
|
|
4777
|
+
import_react3.default.createElement("button", { type: "button", className: "dkp-btn ghost", onClick: closePf }, "\u53D6\u6D88"),
|
|
4182
4778
|
import_react3.default.createElement(
|
|
4183
|
-
"
|
|
4184
|
-
{ className: "
|
|
4185
|
-
|
|
4186
|
-
import_react3.default.createElement("button", { type: "button", className: "dkm-save", disabled: !dirty || saving, onClick: save }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u5199\u56DE\u5B98\u65B9\u914D\u7F6E"),
|
|
4187
|
-
import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: saving || snap.loading, onClick: refreshModels }, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u91CD\u65B0\u62C9\u53D6"),
|
|
4188
|
-
msg ? import_react3.default.createElement("span", { className: "dkm-msg " + (msg.ok ? "ok" : "err") }, msg.text) : null
|
|
4779
|
+
"button",
|
|
4780
|
+
{ type: "button", className: "dkp-btn primary", disabled: pfSaving, onClick: savePf },
|
|
4781
|
+
pfSaving ? "\u4FDD\u5B58\u4E2D\u2026" : pfMode === "create" ? "\u65B0\u589E Provider" : "\u4FDD\u5B58\u4FEE\u6539"
|
|
4189
4782
|
)
|
|
4783
|
+
)
|
|
4784
|
+
);
|
|
4785
|
+
const body = [
|
|
4786
|
+
import_react3.default.createElement("button", { key: "back", type: "button", className: "dkp-back", onClick: props.onBack }, "\u2190 \u6A21\u578B\u8BBE\u7F6E"),
|
|
4787
|
+
import_react3.default.createElement("h2", { key: "title", className: "dkp-title" }, "\u6A21\u578B\u63D0\u4F9B\u5546"),
|
|
4788
|
+
import_react3.default.createElement(
|
|
4789
|
+
"p",
|
|
4790
|
+
{ key: "intro", className: "dkp-intro" },
|
|
4791
|
+
"\u65B0\u589E / \u7F16\u8F91 / \u5220\u9664\u81EA\u5B9A\u4E49\u6A21\u578B Provider\uFF08OpenAI \u517C\u5BB9\u3001Anthropic \u7B49\uFF09\uFF0C\u5199\u5165\u5B98\u65B9\u914D\u7F6E\u5E76\u70ED\u751F\u6548\uFF1BAPI Key \u5B58\u672C\u673A\u51ED\u636E\u5E93\uFF08\u6587\u4EF6\u4EC5 root \u53EF\u8BFB\uFF09\u3002\u5185\u7F6E DeepSeek \u5B98\u65B9 Provider \u5728\u672C\u9875\u53EA\u8BFB\uFF0C\u5176\u6A21\u578B\u76EE\u5F55\u8BF7\u56DE\u300C\u6A21\u578B\u8BBE\u7F6E\u300D\u7F16\u8F91\u3002"
|
|
4792
|
+
)
|
|
4793
|
+
];
|
|
4794
|
+
if (props.error) {
|
|
4795
|
+
body.push(import_react3.default.createElement("p", { key: "err", className: "dkp-error" }, "\u6A21\u578B\u76EE\u5F55\u62C9\u53D6\u5931\u8D25\uFF1A" + props.error));
|
|
4796
|
+
}
|
|
4797
|
+
if (pfMsg && !pfDraft) {
|
|
4798
|
+
body.push(import_react3.default.createElement("p", { key: "msg", className: "dkp-msg " + (pfMsg.ok ? "ok" : "err"), role: "status" }, pfMsg.text));
|
|
4799
|
+
}
|
|
4800
|
+
if (!data) {
|
|
4801
|
+
body.push(import_react3.default.createElement("p", { key: "loading", className: "dkp-hint" }, props.loading ? "\u6B63\u5728\u62C9\u53D6\u6A21\u578B\u76EE\u5F55\u2026" : "\u7B49\u5F85\u62C9\u53D6\u6A21\u578B\u76EE\u5F55"));
|
|
4802
|
+
} else if (piProviders.length === 0) {
|
|
4803
|
+
body.push(import_react3.default.createElement("div", { key: "empty", className: "dkp-empty" }, "\u8FD8\u6CA1\u6709\u81EA\u5B9A\u4E49 Provider\u2014\u2014\u70B9\u4E0B\u65B9\u300C\u65B0\u589E Provider\u300D\u6DFB\u52A0\u3002"));
|
|
4804
|
+
} else {
|
|
4805
|
+
body.push(import_react3.default.createElement(
|
|
4806
|
+
"ul",
|
|
4807
|
+
{ key: "rows", className: "dkp-rows" },
|
|
4808
|
+
piProviders.map((p) => {
|
|
4809
|
+
const route = p.route || p.id;
|
|
4810
|
+
const editing = pfMode === "edit" && !!pfDraft && pfDraft.route === route;
|
|
4811
|
+
const keyMissing = !!(p.apiKeyEnv && !p.apiKeyConfigured);
|
|
4812
|
+
return import_react3.default.createElement(
|
|
4813
|
+
"li",
|
|
4814
|
+
{ key: p.id, className: "dkp-card" },
|
|
4815
|
+
import_react3.default.createElement(
|
|
4816
|
+
"div",
|
|
4817
|
+
{ className: "dkp-rowhead" },
|
|
4818
|
+
import_react3.default.createElement(
|
|
4819
|
+
"span",
|
|
4820
|
+
{ className: "dkp-identity" },
|
|
4821
|
+
import_react3.default.createElement("span", { className: "dkp-name" }, p.displayName || route),
|
|
4822
|
+
import_react3.default.createElement("span", { className: "dkp-tag" }, route),
|
|
4823
|
+
import_react3.default.createElement("span", { className: "dkp-tag" }, (p.models ? p.models.length : 0) + " \u6A21\u578B"),
|
|
4824
|
+
import_react3.default.createElement("span", {
|
|
4825
|
+
className: "dkp-dot " + (keyMissing ? "missing" : "ok"),
|
|
4826
|
+
role: "img",
|
|
4827
|
+
title: p.apiKeyEnv ? p.apiKeyConfigured ? p.apiKeyEnv + " \u5DF2\u914D\u7F6E" : p.apiKeyEnv + " \u672A\u914D\u7F6E" : "\u672A\u8BBE apiKeyEnv",
|
|
4828
|
+
"aria-label": p.apiKeyEnv ? p.apiKeyConfigured ? "\u5BC6\u94A5\u5DF2\u914D\u7F6E" : "\u5BC6\u94A5\u672A\u914D\u7F6E" : "\u672A\u8BBE apiKeyEnv"
|
|
4829
|
+
}),
|
|
4830
|
+
p.apiKeyEnv ? import_react3.default.createElement(
|
|
4831
|
+
"span",
|
|
4832
|
+
{ className: "dkp-tag" + (keyMissing ? " warn" : " ok") },
|
|
4833
|
+
p.apiKeyConfigured ? p.apiKeyEnv + " \u5DF2\u914D\u7F6E" : p.apiKeyEnv + " \u672A\u914D\u7F6E"
|
|
4834
|
+
) : null
|
|
4835
|
+
),
|
|
4836
|
+
import_react3.default.createElement(
|
|
4837
|
+
"span",
|
|
4838
|
+
{ className: "dkp-actions" },
|
|
4839
|
+
import_react3.default.createElement("button", {
|
|
4840
|
+
type: "button",
|
|
4841
|
+
className: "dkp-btn ghost sm",
|
|
4842
|
+
"aria-expanded": editing,
|
|
4843
|
+
onClick: () => editing ? closePf() : openPfEdit(p)
|
|
4844
|
+
}, editing ? "\u6536\u8D77" : "\u7F16\u8F91"),
|
|
4845
|
+
import_react3.default.createElement("button", {
|
|
4846
|
+
type: "button",
|
|
4847
|
+
className: "dkp-btn danger sm" + (pfDelArm === route ? " arm" : ""),
|
|
4848
|
+
title: pfDelArm === route ? "\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\u5220\u9664" : "\u5220\u9664\u8BE5 Provider",
|
|
4849
|
+
onClick: () => deletePf(p)
|
|
4850
|
+
}, pfDelArm === route ? "\u786E\u8BA4\u5220\u9664\uFF1F" : "\u5220\u9664")
|
|
4851
|
+
)
|
|
4852
|
+
),
|
|
4853
|
+
import_react3.default.createElement("div", { className: "dkp-sub" }, [p.api, p.baseURL].filter(Boolean).join(" \xB7 ")),
|
|
4854
|
+
editing ? editor : null
|
|
4855
|
+
);
|
|
4856
|
+
})
|
|
4190
4857
|
));
|
|
4191
4858
|
}
|
|
4192
|
-
|
|
4859
|
+
body.push(import_react3.default.createElement(
|
|
4860
|
+
"div",
|
|
4861
|
+
{ key: "add", className: "dkp-addblock" },
|
|
4862
|
+
pfMode === "create" && pfDraft ? import_react3.default.createElement("div", { className: "dkp-card dkp-addcard" }, editor) : import_react3.default.createElement("button", { type: "button", className: "dkp-addbtn", onClick: openPfCreate }, "\uFF0B \u65B0\u589E Provider")
|
|
4863
|
+
));
|
|
4864
|
+
return import_react3.default.createElement("div", { className: "dkp-page" }, body);
|
|
4193
4865
|
}
|
|
4194
4866
|
function ModelsStat() {
|
|
4195
4867
|
const snap = useModels();
|
|
@@ -4205,7 +4877,7 @@ var feature2 = {
|
|
|
4205
4877
|
name: "\u6A21\u578B\u8BBE\u7F6E",
|
|
4206
4878
|
order: 100,
|
|
4207
4879
|
accent: "#22d3ee",
|
|
4208
|
-
description: "\u7F16\u8F91\u5404 Provider \u6A21\u578B\u76EE\u5F55\
|
|
4880
|
+
description: "\u7F16\u8F91\u5404 Provider \u6A21\u578B\u76EE\u5F55\uFF08\u8F93\u5165\u7C7B\u578B/\u601D\u8003\u5F3A\u5EA6\u6863\u4F4D\uFF09\uFF1B\u81EA\u5B9A\u4E49 Provider \u7684\u589E\u5220\u6539\u5728\u300C\u6A21\u578B\u63D0\u4F9B\u5546\u300D\u5B50\u9875\u9762\uFF0C\u5199\u56DE\u5B98\u65B9\u914D\u7F6E\u70ED\u751F\u6548\uFF0C\u4F1A\u8BDD\u6A21\u578B\u9009\u62E9\u5668\u5373\u65F6\u53EF\u9009",
|
|
4209
4881
|
css: [
|
|
4210
4882
|
".dkm-note{color:var(--dsw-alias-label-secondary);font-size:12px;}",
|
|
4211
4883
|
".dkm-warn{color:var(--dk-warn);}",
|
|
@@ -4250,7 +4922,99 @@ var feature2 = {
|
|
|
4250
4922
|
".dkm-mini{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-family:inherit;font-size:11px;flex:none;}",
|
|
4251
4923
|
".dkm-mini:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary);}",
|
|
4252
4924
|
".dkm-toolbar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;border-top:1px dashed var(--dsw-alias-border-l1);padding-top:8px;}",
|
|
4253
|
-
".dkm-toolbar-label{color:var(--dsw-alias-label-tertiary);font-size:11px;flex:none;}"
|
|
4925
|
+
".dkm-toolbar-label{color:var(--dsw-alias-label-tertiary);font-size:11px;flex:none;}",
|
|
4926
|
+
// ---- 模型提供商子页面(dkp- 前缀):对齐官方「模型」设置页的排版与尺寸 ----
|
|
4927
|
+
// 官方用量参考:section 限宽 720、行卡片 .5px 描边 + radius-xl + 12/14 内距、
|
|
4928
|
+
// 输入高 32、按钮高 36(行内小按钮 28)、新增按钮 44 虚线、编辑器 bg-module-platform。
|
|
4929
|
+
".dkp-page{width:100%;max-width:720px;display:flex;flex-direction:column;gap:12px;color:var(--dsw-alias-label-primary);}",
|
|
4930
|
+
".dkp-back{box-sizing:border-box;align-self:flex-start;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:var(--dsw-radius-sm,6px);padding:4px 8px;margin-left:-8px;font-family:inherit;font-size:12px;line-height:18px;}",
|
|
4931
|
+
".dkp-back:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
4932
|
+
".dkp-title{margin:0;font-size:16px;font-weight:500;line-height:24px;}",
|
|
4933
|
+
".dkp-intro{margin:0;color:var(--dsw-alias-label-tertiary);font-size:14px;line-height:22px;}",
|
|
4934
|
+
".dkp-rows{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:8px;}",
|
|
4935
|
+
".dkp-card{box-sizing:border-box;margin:0;border:.5px solid var(--dsw-alias-settings-card-stroke,var(--dsw-alias-border-l2));background:var(--dsw-alias-settings-card-fill,var(--dsw-alias-bg-layer-1));border-radius:var(--dsw-radius-xl,12px);padding:12px 14px;display:flex;flex-direction:column;gap:10px;}",
|
|
4936
|
+
".dkp-rowhead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}",
|
|
4937
|
+
".dkp-identity{display:inline-flex;align-items:center;gap:6px;min-width:0;flex-wrap:wrap;}",
|
|
4938
|
+
".dkp-name{font-size:14px;font-weight:500;line-height:22px;}",
|
|
4939
|
+
".dkp-tag{flex:none;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs,4px);color:var(--dsw-alias-label-secondary);padding:1px 6px;font-size:11px;line-height:16px;}",
|
|
4940
|
+
".dkp-tag.ok{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
|
|
4941
|
+
".dkp-tag.warn{color:var(--dk-warn);border-color:currentColor;}",
|
|
4942
|
+
".dkp-dot{box-sizing:border-box;flex:none;width:8px;height:8px;border-radius:50%;display:inline-block;}",
|
|
4943
|
+
".dkp-dot.ok{background:var(--dsw-alias-state-success-primary);}",
|
|
4944
|
+
".dkp-dot.missing{background:var(--dsw-alias-state-error-primary);}",
|
|
4945
|
+
".dkp-dot.warn{background:var(--dk-warn);}",
|
|
4946
|
+
".dkp-sub{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
4947
|
+
".dkp-hint{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;}",
|
|
4948
|
+
".dkp-dim{color:var(--dsw-alias-label-tertiary);}",
|
|
4949
|
+
".dkp-error{margin:0;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px;}",
|
|
4950
|
+
".dkp-msg{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;}",
|
|
4951
|
+
".dkp-msg.ok{color:var(--dsw-alias-state-success-primary);}",
|
|
4952
|
+
".dkp-msg.err{color:var(--dsw-alias-state-error-primary);}",
|
|
4953
|
+
".dkp-actions{flex:none;margin-left:auto;display:inline-flex;align-items:center;gap:4px;}",
|
|
4954
|
+
".dkp-btn{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:4px;height:36px;padding:0 14px;border:none;border-radius:var(--dsw-radius-md,8px);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;cursor:pointer;}",
|
|
4955
|
+
".dkp-btn.ghost{border:.5px solid var(--dsw-alias-border-l3);}",
|
|
4956
|
+
".dkp-btn.ghost:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
4957
|
+
".dkp-btn.primary{background:var(--dsw-alias-button-primary-fill,var(--dk-accent));color:var(--dsw-alias-label-primary-foreground,#fff);}",
|
|
4958
|
+
".dkp-btn.primary:hover{background:var(--dsw-alias-button-primary-hover,var(--dk-accent));}",
|
|
4959
|
+
".dkp-btn.danger{color:var(--dsw-alias-state-error-primary);}",
|
|
4960
|
+
".dkp-btn.danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(220,38,38,.1));}",
|
|
4961
|
+
".dkp-btn.arm{color:var(--dsw-alias-state-error-primary);border-color:currentColor;}",
|
|
4962
|
+
".dkp-btn.sm{height:28px;padding:0 10px;border-radius:var(--dsw-radius-sm,6px);font-size:12px;line-height:18px;}",
|
|
4963
|
+
".dkp-btn[disabled]{opacity:.4;cursor:default;}",
|
|
4964
|
+
".dkp-editor{border-radius:var(--dsw-radius-lg,10px);background:var(--dsw-alias-bg-module-platform,var(--dsw-alias-bg-layer-1));padding:14px 16px;display:flex;flex-direction:column;gap:14px;}",
|
|
4965
|
+
".dkp-editor-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;}",
|
|
4966
|
+
".dkp-editor-title{font-size:14px;font-weight:500;line-height:22px;}",
|
|
4967
|
+
".dkp-editor-route{color:var(--dsw-alias-label-tertiary);font-family:var(--ds-font-family-code,ui-monospace,monospace);font-size:12px;line-height:18px;}",
|
|
4968
|
+
".dkp-field{display:flex;flex-direction:column;gap:6px;min-width:0;}",
|
|
4969
|
+
".dkp-flabel{display:inline-flex;align-items:center;gap:10px;color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px;}",
|
|
4970
|
+
".dkp-input{box-sizing:border-box;width:100%;height:32px;padding:0 10px;border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-l2));border-radius:var(--dsw-radius-md,8px);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;}",
|
|
4971
|
+
".dkp-input:focus{border-color:var(--dsw-alias-state-business-primary,var(--dk-accent));outline:none;}",
|
|
4972
|
+
".dkp-input::placeholder{color:var(--dsw-alias-label-dimmed,var(--dsw-alias-label-tertiary));}",
|
|
4973
|
+
".dkp-input:disabled{opacity:.6;cursor:default;}",
|
|
4974
|
+
"select.dkp-input{appearance:auto;cursor:pointer;max-width:240px;}",
|
|
4975
|
+
".dkp-select-sm{height:28px;max-width:160px;font-size:12px;line-height:18px;}",
|
|
4976
|
+
".dkp-checks{display:flex;align-items:center;gap:16px;flex-wrap:wrap;min-height:32px;}",
|
|
4977
|
+
".dkp-check{display:inline-flex;align-items:center;gap:6px;cursor:pointer;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;}",
|
|
4978
|
+
".dkp-check input{accent-color:var(--dk-accent);margin:0;}",
|
|
4979
|
+
".dkp-mini{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;background:transparent;color:var(--dsw-alias-label-tertiary);padding:1px 8px;font-family:inherit;font-size:11px;line-height:16px;flex:none;}",
|
|
4980
|
+
".dkp-mini:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary);}",
|
|
4981
|
+
".dkp-customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px;}",
|
|
4982
|
+
".dkp-summary{display:flex;align-items:center;gap:6px;width:fit-content;margin-left:-4px;padding:2px 4px;border-radius:var(--dsw-radius-sm,6px);list-style:none;cursor:pointer;color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px;}",
|
|
4983
|
+
".dkp-summary::-webkit-details-marker{display:none;}",
|
|
4984
|
+
'.dkp-summary::before{content:"";width:5px;height:5px;border-right:1.5px solid;border-bottom:1.5px solid;transform:rotate(-45deg);transition:transform .12s;}',
|
|
4985
|
+
".dkp-customized[open]>.dkp-summary::before{transform:rotate(45deg);}",
|
|
4986
|
+
".dkp-summary:hover{color:var(--dsw-alias-label-primary);}",
|
|
4987
|
+
".dkp-custombody{display:flex;flex-direction:column;gap:12px;padding-top:12px;}",
|
|
4988
|
+
".dkp-catalog{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:12px;display:flex;flex-direction:column;gap:10px;}",
|
|
4989
|
+
".dkp-catalog-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;}",
|
|
4990
|
+
".dkp-catalog-titlewrap{display:flex;flex-direction:column;gap:2px;}",
|
|
4991
|
+
".dkp-catalog-title{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px;}",
|
|
4992
|
+
".dkp-catalog-meta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;}",
|
|
4993
|
+
".dkp-model-list{display:flex;flex-direction:column;gap:8px;}",
|
|
4994
|
+
".dkp-model-entry{border:.5px solid var(--dsw-alias-border-l4,var(--dsw-alias-border-l2));border-radius:var(--dsw-radius-lg,10px);padding:6px;display:flex;flex-direction:column;gap:6px;}",
|
|
4995
|
+
".dkp-model-row{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(0,.7fr) minmax(0,.7fr) auto;gap:6px;align-items:center;}",
|
|
4996
|
+
".dkp-model-row .dkp-input{height:30px;padding:0 8px;font-size:13px;}",
|
|
4997
|
+
".dkp-model-opts{display:flex;flex-direction:column;gap:4px;padding:2px 2px 0;}",
|
|
4998
|
+
".dkp-iconbtn{box-sizing:border-box;width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:var(--dsw-radius-sm,6px);background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:12px;line-height:1;}",
|
|
4999
|
+
".dkp-iconbtn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
5000
|
+
".dkp-iconbtn.danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(220,38,38,.1));color:var(--dsw-alias-state-error-primary);}",
|
|
5001
|
+
".dkp-addmodel{box-sizing:border-box;align-self:flex-start;display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 10px;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm,6px);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;line-height:18px;cursor:pointer;}",
|
|
5002
|
+
".dkp-addmodel:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
5003
|
+
".dkp-picker{max-height:320px;overflow-y:auto;border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md,8px);padding:4px 6px;display:flex;flex-direction:column;gap:2px;}",
|
|
5004
|
+
".dkp-picker label{display:flex;align-items:center;gap:8px;min-width:0;cursor:pointer;padding:6px 8px;border-radius:var(--dsw-radius-md,8px);}",
|
|
5005
|
+
".dkp-picker label:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
5006
|
+
".dkp-picker input{accent-color:var(--dk-accent);margin:0;flex:none;}",
|
|
5007
|
+
".dkp-picker-id{flex:none;font-family:var(--ds-font-family-code,ui-monospace,monospace);font-size:13px;line-height:20px;}",
|
|
5008
|
+
".dkp-picker-name{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
5009
|
+
".dkp-empty{border:1px dashed var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-lg,10px);padding:12px;text-align:center;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;}",
|
|
5010
|
+
".dkp-addblock{display:flex;align-items:stretch;}",
|
|
5011
|
+
".dkp-addbtn{box-sizing:border-box;flex:1 1 auto;min-width:180px;height:44px;display:inline-flex;align-items:center;justify-content:center;gap:6px;border:1px dashed var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-lg,10px);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;cursor:pointer;}",
|
|
5012
|
+
".dkp-addbtn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
5013
|
+
".dkp-addcard{flex:1 1 auto;padding:14px 16px;}",
|
|
5014
|
+
".dkp-addcard .dkp-editor{background:transparent;padding:0;}",
|
|
5015
|
+
".dkp-editor-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;border-top:.5px solid var(--dsw-alias-border-l2);padding-top:12px;}",
|
|
5016
|
+
".dkp-editor-actions .dkp-hint{margin-right:auto;}",
|
|
5017
|
+
"@media (max-width:680px){.dkp-page{max-width:none;gap:14px}.dkp-intro{font-size:13px;line-height:20px}.dkp-model-row{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.dkp-model-row .dkp-iconbtn{justify-self:end}.dkp-editor{padding:12px}.dkp-addcard{padding:12px 14px}.dkp-btn{height:40px}.dkp-btn.sm{height:34px}.dkp-addbtn{height:48px}}"
|
|
4254
5018
|
].join("\n"),
|
|
4255
5019
|
View: ModelsView,
|
|
4256
5020
|
HomeStat: ModelsStat
|
|
@@ -4402,7 +5166,7 @@ var balanceStore = {
|
|
|
4402
5166
|
load() {
|
|
4403
5167
|
if (this.snap.loading) return;
|
|
4404
5168
|
this.set({ loading: true });
|
|
4405
|
-
fetch("
|
|
5169
|
+
fetch("dsh-dock/balance", { signal: AbortSignal.timeout(2e4) }).then((res) => res.ok ? res.json() : Promise.reject(new Error("\u4F59\u989D\u63A5\u53E3 HTTP " + res.status))).then((data) => this.set({ data, loading: false, error: null })).catch((e) => this.set({ loading: false, error: e && e.message || String(e) }));
|
|
4406
5170
|
}
|
|
4407
5171
|
};
|
|
4408
5172
|
function useBalance(ctx) {
|
|
@@ -4725,7 +5489,7 @@ var feature5 = {
|
|
|
4725
5489
|
var import_react8 = require("react");
|
|
4726
5490
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
4727
5491
|
function rpcCall2(method, args) {
|
|
4728
|
-
return fetch("
|
|
5492
|
+
return fetch("dsh-dock/animation/" + method, {
|
|
4729
5493
|
method: "POST",
|
|
4730
5494
|
headers: { "content-type": "application/json" },
|
|
4731
5495
|
body: JSON.stringify(args === void 0 ? {} : args)
|
|
@@ -6402,7 +7166,7 @@ var feature6 = {
|
|
|
6402
7166
|
var import_react9 = require("react");
|
|
6403
7167
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
6404
7168
|
function rpcCall3(method, args) {
|
|
6405
|
-
return fetch("
|
|
7169
|
+
return fetch("dsh-dock/notify/" + method, {
|
|
6406
7170
|
method: "POST",
|
|
6407
7171
|
headers: { "content-type": "application/json" },
|
|
6408
7172
|
body: JSON.stringify(args === void 0 ? {} : args)
|
|
@@ -7166,7 +7930,7 @@ var feature7 = {
|
|
|
7166
7930
|
var import_react10 = require("react");
|
|
7167
7931
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
7168
7932
|
function rpcCall4(method, args) {
|
|
7169
|
-
return fetch("
|
|
7933
|
+
return fetch("dsh-dock/runstate/" + method, {
|
|
7170
7934
|
method: "POST",
|
|
7171
7935
|
headers: { "content-type": "application/json" },
|
|
7172
7936
|
body: JSON.stringify(args === void 0 ? {} : args)
|
|
@@ -10149,7 +10913,7 @@ function initialDash() {
|
|
|
10149
10913
|
}
|
|
10150
10914
|
function useTaskPulse() {
|
|
10151
10915
|
const [status, setStatus] = (0, import_react20.useState)({ loading: true, active: [], error: false });
|
|
10152
|
-
const refresh = (0, import_react20.useCallback)(() => fetch("
|
|
10916
|
+
const refresh = (0, import_react20.useCallback)(() => fetch("dsh-dock/animation/status", {
|
|
10153
10917
|
method: "POST",
|
|
10154
10918
|
headers: { "content-type": "application/json" },
|
|
10155
10919
|
body: "{}"
|
|
@@ -10922,7 +11686,7 @@ var import_react21 = require("react");
|
|
|
10922
11686
|
var import_qrcode = __toESM(require_browser(), 1);
|
|
10923
11687
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
10924
11688
|
function rpc(method, payload) {
|
|
10925
|
-
return fetch("
|
|
11689
|
+
return fetch("dsh-dock/mobile-relay/" + method, {
|
|
10926
11690
|
method: "POST",
|
|
10927
11691
|
headers: { "content-type": "application/json" },
|
|
10928
11692
|
body: JSON.stringify(payload || {})
|
|
@@ -11221,247 +11985,6 @@ function RemoteCard() {
|
|
|
11221
11985
|
function MobileRelayView() {
|
|
11222
11986
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(RemoteCard, {});
|
|
11223
11987
|
}
|
|
11224
|
-
function MobileRelayOverlay() {
|
|
11225
|
-
(0, import_react21.useEffect)(() => {
|
|
11226
|
-
if (typeof window === "undefined" || typeof document === "undefined") return void 0;
|
|
11227
|
-
const host = window.location && window.location.hostname || "";
|
|
11228
|
-
const loopback = host === "127.0.0.1" || host === "localhost" || host === "::1" || host.endsWith(".localhost");
|
|
11229
|
-
if (loopback) return void 0;
|
|
11230
|
-
if (typeof MutationObserver === "undefined") return void 0;
|
|
11231
|
-
let done = false;
|
|
11232
|
-
const tryDismiss = () => {
|
|
11233
|
-
if (done) return;
|
|
11234
|
-
const dialogs = document.querySelectorAll('[role="dialog"]');
|
|
11235
|
-
for (const dialog of dialogs) {
|
|
11236
|
-
const text = dialog.textContent || "";
|
|
11237
|
-
if (!/预览版说明|Preview Notice/.test(text)) continue;
|
|
11238
|
-
const btn = [...dialog.querySelectorAll("button")].find((b) => {
|
|
11239
|
-
const t = (b.textContent || "").trim();
|
|
11240
|
-
return t === "\u7EE7\u7EED" || t === "Continue";
|
|
11241
|
-
});
|
|
11242
|
-
if (btn) {
|
|
11243
|
-
done = true;
|
|
11244
|
-
btn.click();
|
|
11245
|
-
observer.disconnect();
|
|
11246
|
-
}
|
|
11247
|
-
break;
|
|
11248
|
-
}
|
|
11249
|
-
};
|
|
11250
|
-
const observer = new MutationObserver(tryDismiss);
|
|
11251
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
11252
|
-
tryDismiss();
|
|
11253
|
-
const stopTimer = setTimeout(() => observer.disconnect(), 6e4);
|
|
11254
|
-
return () => {
|
|
11255
|
-
clearTimeout(stopTimer);
|
|
11256
|
-
observer.disconnect();
|
|
11257
|
-
};
|
|
11258
|
-
}, []);
|
|
11259
|
-
(0, import_react21.useEffect)(() => {
|
|
11260
|
-
if (typeof window === "undefined" || typeof document === "undefined") return void 0;
|
|
11261
|
-
const mq = window.matchMedia ? window.matchMedia("(max-width:700px)") : null;
|
|
11262
|
-
if (!mq) return void 0;
|
|
11263
|
-
if (window.__dshDockMobileDrawer === "host") return void 0;
|
|
11264
|
-
window.__dshDockMobileDrawer = "client";
|
|
11265
|
-
const narrow = () => mq.matches;
|
|
11266
|
-
const frameEl = () => document.querySelector('[class$="frame"]');
|
|
11267
|
-
const sidebarCollapsed = () => {
|
|
11268
|
-
const f = frameEl();
|
|
11269
|
-
return !!f && f.hasAttribute("data-sidebar-collapsed");
|
|
11270
|
-
};
|
|
11271
|
-
const dialogOpen = () => !!document.querySelector('[role="dialog"][class*="panel"]');
|
|
11272
|
-
const rightOpen = () => !!document.querySelector("[data-sidebar-right-panel][data-sidebar-right-open]");
|
|
11273
|
-
const collapse = () => {
|
|
11274
|
-
const b = document.querySelector('button[aria-label="\u6536\u8D77\u4FA7\u8FB9\u680F"],button[aria-label="Collapse sidebar"]');
|
|
11275
|
-
if (b) b.click();
|
|
11276
|
-
};
|
|
11277
|
-
const expand = () => {
|
|
11278
|
-
const b = document.querySelector('button[aria-label="\u6253\u5F00\u4FA7\u8FB9\u680F"],button[aria-label="Open sidebar"]');
|
|
11279
|
-
if (b) b.click();
|
|
11280
|
-
};
|
|
11281
|
-
const closeDetails = () => {
|
|
11282
|
-
const panel = document.querySelector("[data-sidebar-right-panel][data-sidebar-right-open]");
|
|
11283
|
-
if (!panel) return;
|
|
11284
|
-
const toggle = panel.querySelector("[data-sidebar-right-toggle]");
|
|
11285
|
-
if (toggle) toggle.click();
|
|
11286
|
-
};
|
|
11287
|
-
const scrim = document.createElement("div");
|
|
11288
|
-
scrim.className = "dsh-mobile-scrim";
|
|
11289
|
-
document.body.appendChild(scrim);
|
|
11290
|
-
document.querySelectorAll(".dsh-mobile-tabbar").forEach((el) => el.remove());
|
|
11291
|
-
const tabbar = document.createElement("nav");
|
|
11292
|
-
tabbar.className = "dsh-mobile-tabbar";
|
|
11293
|
-
tabbar.setAttribute("aria-label", "\u5E95\u90E8\u5BFC\u822A");
|
|
11294
|
-
let tasksActive = 0;
|
|
11295
|
-
let tasksWaiting = 0;
|
|
11296
|
-
const tabDefs = [
|
|
11297
|
-
{
|
|
11298
|
-
id: "sessions",
|
|
11299
|
-
label: "\u4F1A\u8BDD",
|
|
11300
|
-
icon: '<svg viewBox="0 0 24 24"><path d="M21 12a8 8 0 0 1-8 8H5l-2 2V12a8 8 0 0 1 8-8h2a8 8 0 0 1 8 8z"/></svg>',
|
|
11301
|
-
act: () => expand()
|
|
11302
|
-
},
|
|
11303
|
-
{
|
|
11304
|
-
id: "dock",
|
|
11305
|
-
label: "\u63D2\u4EF6",
|
|
11306
|
-
icon: '<svg viewBox="0 0 24 24"><rect x="4" y="4" width="7" height="7" rx="1.5"/><rect x="13" y="4" width="7" height="7" rx="1.5"/><rect x="4" y="13" width="7" height="7" rx="1.5"/><rect x="13" y="13" width="7" height="7" rx="1.5"/></svg>',
|
|
11307
|
-
act: () => {
|
|
11308
|
-
openPanel(tasksActive > 0 || tasksWaiting > 0 ? "runstate" : "home");
|
|
11309
|
-
}
|
|
11310
|
-
},
|
|
11311
|
-
{
|
|
11312
|
-
id: "settings",
|
|
11313
|
-
label: "\u8BBE\u7F6E",
|
|
11314
|
-
icon: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3.2"/><path d="M19.4 15a1.7 1.7 0 0 0 .34 1.87l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06A1.7 1.7 0 0 0 15 19.4a1.7 1.7 0 0 0-1 1.55V21a2 2 0 1 1-4 0v-.09A1.7 1.7 0 0 0 9 19.4a1.7 1.7 0 0 0-1.87.34l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.55-1H3a2 2 0 1 1 0-4h.09A1.7 1.7 0 0 0 4.6 9a1.7 1.7 0 0 0-.34-1.87l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.7 1.7 0 0 0 9 4.6a1.7 1.7 0 0 0 1-1.55V3a2 2 0 1 1 4 0v.09a1.7 1.7 0 0 0 1 1.51 1.7 1.7 0 0 0 1.87-.34l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.7 1.7 0 0 0 19.4 9c.23.6.86 1 1.51 1H21a2 2 0 1 1 0 4h-.09a1.7 1.7 0 0 0-1.51 1z"/></svg>',
|
|
11315
|
-
act: () => {
|
|
11316
|
-
const b = [...document.querySelectorAll("button")].find((x) => (x.getAttribute("aria-label") || "") === "\u8BBE\u7F6E" || (x.textContent || "").trim() === "\u8BBE\u7F6E");
|
|
11317
|
-
if (b) b.click();
|
|
11318
|
-
}
|
|
11319
|
-
}
|
|
11320
|
-
];
|
|
11321
|
-
let tasksBadge = null;
|
|
11322
|
-
const tabButtons = tabDefs.map((def) => {
|
|
11323
|
-
const b = document.createElement("button");
|
|
11324
|
-
b.type = "button";
|
|
11325
|
-
b.className = "dsh-mobile-tab";
|
|
11326
|
-
b.dataset.tab = def.id;
|
|
11327
|
-
b.innerHTML = def.icon + "<span>" + def.label + "</span>";
|
|
11328
|
-
b.addEventListener("click", () => def.act());
|
|
11329
|
-
if (def.id === "dock") {
|
|
11330
|
-
tasksBadge = document.createElement("span");
|
|
11331
|
-
tasksBadge.className = "dsh-mobile-tab-badge";
|
|
11332
|
-
tasksBadge.style.display = "none";
|
|
11333
|
-
b.appendChild(tasksBadge);
|
|
11334
|
-
}
|
|
11335
|
-
tabbar.appendChild(b);
|
|
11336
|
-
return b;
|
|
11337
|
-
});
|
|
11338
|
-
document.body.appendChild(tabbar);
|
|
11339
|
-
const syncTabs = () => {
|
|
11340
|
-
const expanded = !sidebarCollapsed();
|
|
11341
|
-
const settingsOpen = dialogOpen();
|
|
11342
|
-
for (const b of tabButtons) {
|
|
11343
|
-
const id = b.dataset.tab;
|
|
11344
|
-
const on = id === "sessions" && expanded || id === "dock" && panelNav.open || id === "settings" && settingsOpen;
|
|
11345
|
-
b.classList.toggle("on", on);
|
|
11346
|
-
}
|
|
11347
|
-
};
|
|
11348
|
-
const unsubPanel = subscribePanel(syncTabs);
|
|
11349
|
-
let runstateGone = false;
|
|
11350
|
-
const pollTasks = () => {
|
|
11351
|
-
if (runstateGone || !tasksBadge || !narrow() || document.visibilityState === "hidden" || !tabbar.isConnected) return;
|
|
11352
|
-
fetch("/dsh-dock/runstate/status", {
|
|
11353
|
-
method: "POST",
|
|
11354
|
-
headers: { "content-type": "application/json" },
|
|
11355
|
-
body: "{}"
|
|
11356
|
-
}).then(async (res) => {
|
|
11357
|
-
if (res.status === 404 || res.status === 405) {
|
|
11358
|
-
runstateGone = true;
|
|
11359
|
-
tasksActive = 0;
|
|
11360
|
-
tasksWaiting = 0;
|
|
11361
|
-
tasksBadge.style.display = "none";
|
|
11362
|
-
return null;
|
|
11363
|
-
}
|
|
11364
|
-
const body = await res.json().catch(() => null);
|
|
11365
|
-
if (!body) return null;
|
|
11366
|
-
const active = body.data && body.data.active || [];
|
|
11367
|
-
const waiting = active.filter((t) => t.approvals && t.approvals.length).length;
|
|
11368
|
-
tasksActive = active.length;
|
|
11369
|
-
tasksWaiting = waiting;
|
|
11370
|
-
if (waiting > 0) {
|
|
11371
|
-
tasksBadge.textContent = String(waiting);
|
|
11372
|
-
tasksBadge.className = "dsh-mobile-tab-badge wait";
|
|
11373
|
-
tasksBadge.style.display = "";
|
|
11374
|
-
} else if (active.length > 0) {
|
|
11375
|
-
tasksBadge.textContent = String(active.length);
|
|
11376
|
-
tasksBadge.className = "dsh-mobile-tab-badge";
|
|
11377
|
-
tasksBadge.style.display = "";
|
|
11378
|
-
} else {
|
|
11379
|
-
tasksBadge.style.display = "none";
|
|
11380
|
-
}
|
|
11381
|
-
}).catch(() => {
|
|
11382
|
-
});
|
|
11383
|
-
};
|
|
11384
|
-
const tasksTimer = setInterval(pollTasks, 3e3);
|
|
11385
|
-
const vv = window.visualViewport || null;
|
|
11386
|
-
const kbdSync = () => {
|
|
11387
|
-
if (!vv) return;
|
|
11388
|
-
const kbd = vv.height > 0 && window.innerHeight - vv.height > 120;
|
|
11389
|
-
document.documentElement.classList.toggle("dsh-dock-kbd", kbd);
|
|
11390
|
-
};
|
|
11391
|
-
const sync = () => {
|
|
11392
|
-
kbdSync();
|
|
11393
|
-
document.querySelectorAll(".dsh-mobile-tabbar").forEach((el) => {
|
|
11394
|
-
if (el !== tabbar) el.remove();
|
|
11395
|
-
});
|
|
11396
|
-
const on = narrow() && !!frameEl() && !dialogOpen();
|
|
11397
|
-
const collapsed = sidebarCollapsed();
|
|
11398
|
-
const right = rightOpen();
|
|
11399
|
-
if (scrim) scrim.style.display = on && !collapsed ? "" : "none";
|
|
11400
|
-
tabbar.style.display = narrow() && !!frameEl() && !panelNav.open && !right ? "" : "none";
|
|
11401
|
-
syncTabs();
|
|
11402
|
-
};
|
|
11403
|
-
sync();
|
|
11404
|
-
pollTasks();
|
|
11405
|
-
const observer = typeof MutationObserver !== "undefined" ? new MutationObserver(sync) : null;
|
|
11406
|
-
if (observer) observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-sidebar-collapsed"], subtree: true });
|
|
11407
|
-
const timer = setInterval(sync, 1500);
|
|
11408
|
-
const onMq = () => sync();
|
|
11409
|
-
if (mq.addEventListener) mq.addEventListener("change", onMq);
|
|
11410
|
-
else if (mq.addListener) mq.addListener(onMq);
|
|
11411
|
-
window.addEventListener("resize", kbdSync);
|
|
11412
|
-
if (vv && vv.addEventListener) vv.addEventListener("resize", kbdSync);
|
|
11413
|
-
const onVisible = () => {
|
|
11414
|
-
if (document.visibilityState === "visible") pollTasks();
|
|
11415
|
-
};
|
|
11416
|
-
document.addEventListener("visibilitychange", onVisible);
|
|
11417
|
-
const onClick = (e) => {
|
|
11418
|
-
if (!narrow()) return;
|
|
11419
|
-
const t = e.target;
|
|
11420
|
-
if (!t || !t.closest) return;
|
|
11421
|
-
if (t.closest(".dsh-mobile-tabbar")) return;
|
|
11422
|
-
const expanded = !!document.querySelector('button[aria-label="\u6536\u8D77\u4FA7\u8FB9\u680F"],button[aria-label="Collapse sidebar"]');
|
|
11423
|
-
const col = document.querySelector('[class*="sidebarCol"]');
|
|
11424
|
-
const inSidebar = col && col.contains(t);
|
|
11425
|
-
if (!expanded && !inSidebar) return;
|
|
11426
|
-
if (inSidebar) {
|
|
11427
|
-
const row = t.closest('[role="treeitem"]');
|
|
11428
|
-
const rowKey = row && row.getAttribute("data-row-key") || "";
|
|
11429
|
-
const sessionRow = rowKey && rowKey.startsWith("session:") || row && !rowKey && !row.querySelector('[role="treeitem"]') && row.closest('[role="tree"]');
|
|
11430
|
-
const fresh = t.closest('[class*="newSession"]');
|
|
11431
|
-
if (sessionRow || fresh) setTimeout(() => {
|
|
11432
|
-
collapse();
|
|
11433
|
-
closeDetails();
|
|
11434
|
-
}, 300);
|
|
11435
|
-
else {
|
|
11436
|
-
setTimeout(() => {
|
|
11437
|
-
if (document.querySelector('[role="dialog"]')) collapse();
|
|
11438
|
-
}, 260);
|
|
11439
|
-
}
|
|
11440
|
-
return;
|
|
11441
|
-
}
|
|
11442
|
-
if (t.closest('[role="dialog"],[class*="dockm"],[class*="dgfab"],[class*="dgwin"],[class*="dgame"],[data-sidebar-right-panel]')) return;
|
|
11443
|
-
collapse();
|
|
11444
|
-
};
|
|
11445
|
-
document.addEventListener("click", onClick, true);
|
|
11446
|
-
return () => {
|
|
11447
|
-
document.removeEventListener("click", onClick, true);
|
|
11448
|
-
if (observer) observer.disconnect();
|
|
11449
|
-
clearInterval(timer);
|
|
11450
|
-
clearInterval(tasksTimer);
|
|
11451
|
-
unsubPanel();
|
|
11452
|
-
if (mq.removeEventListener) mq.removeEventListener("change", onMq);
|
|
11453
|
-
else if (mq.removeListener) mq.removeListener(onMq);
|
|
11454
|
-
window.removeEventListener("resize", kbdSync);
|
|
11455
|
-
if (vv && vv.removeEventListener) vv.removeEventListener("resize", kbdSync);
|
|
11456
|
-
document.removeEventListener("visibilitychange", onVisible);
|
|
11457
|
-
document.documentElement.classList.remove("dsh-dock-kbd");
|
|
11458
|
-
if (scrim) scrim.remove();
|
|
11459
|
-
tabbar.remove();
|
|
11460
|
-
if (window.__dshDockMobileDrawer === "client") delete window.__dshDockMobileDrawer;
|
|
11461
|
-
};
|
|
11462
|
-
}, []);
|
|
11463
|
-
return null;
|
|
11464
|
-
}
|
|
11465
11988
|
function MobileRelayHomeStat() {
|
|
11466
11989
|
const [summary, setSummary] = (0, import_react21.useState)("\u672A\u5F00\u542F\uFF0C\u5F00\u542F\u540E\u53EF\u8FDC\u7A0B\u767B\u5F55");
|
|
11467
11990
|
(0, import_react21.useEffect)(() => {
|
|
@@ -11487,53 +12010,9 @@ var feature10 = {
|
|
|
11487
12010
|
defaultEnabled: false,
|
|
11488
12011
|
css: `
|
|
11489
12012
|
.dmr{--dmr-accent:var(--dk-accent,#2f6fed);--dmr-accent-soft:color-mix(in srgb,var(--dmr-accent) 13%,transparent);display:flex;flex-direction:column;gap:16px;max-width:720px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}.dmr h3,.dmr h4,.dmr p{margin:0}.dmr h3{font-size:17px;line-height:1.25;letter-spacing:-.01em}.dmr h4{font-size:13px}.dmr-hero,.dmr-status-head{display:flex;align-items:flex-start;gap:12px}.dmr-hero>div,.dmr-status-head>div{min-width:0;display:flex;flex-direction:column;gap:4px}.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}.dmr-hero-icon{width:42px;height:42px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:14px;background:var(--dmr-accent-soft);color:var(--dmr-accent);border:1px solid color-mix(in srgb,var(--dmr-accent) 35%,var(--dsw-alias-border-l1))}.dmr-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none}.dmr-steps li{display:flex;gap:9px;padding:11px;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px}.dmr-steps li>span{width:21px;height:21px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:50%;font-size:11px;font-weight:700;color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-steps div{display:flex;flex-direction:column;gap:3px;min-width:0}.dmr-steps strong{font-size:12px}.dmr-steps small{font-size:11px;color:var(--dsw-alias-label-secondary);line-height:1.45}.dmr-field{display:flex;flex-direction:column;gap:6px;font-weight:600}.dmr-field input,.dmr-field select,.dmr-note textarea{box-sizing:border-box;width:100%;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:10px;padding:10px 12px;min-height:44px;font:inherit;outline:none;transition:border-color .18s ease,box-shadow .18s ease}.dmr-field input:focus,.dmr-field select:focus,.dmr-note textarea:focus{border-color:var(--dmr-accent);box-shadow:0 0 0 3px var(--dmr-accent-soft)}.dmr-field small{font-weight:400}.dmr-network-grid{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(150px,.6fr);gap:12px}.dmr-security{padding:12px 13px;border:1px solid color-mix(in srgb,var(--dk-warn) 48%,var(--dsw-alias-border-l1));border-radius:12px;background:color-mix(in srgb,var(--dk-warn) 9%,transparent)}.dmr-security strong{display:block;margin-bottom:4px;color:var(--dk-warn);font-size:12px}.dmr-security p{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.55}.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button{font:inherit;touch-action:manipulation;cursor:pointer;transition:transform .15s ease,background .18s ease,border-color .18s ease,opacity .18s ease}.dmr-primary,.dmr-secondary{min-height:44px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:10px;padding:9px 13px;font-weight:600}.dmr-primary{align-self:flex-start;border:1px solid var(--dmr-accent);background:var(--dmr-accent);color:#fff}.dmr-primary:hover{filter:brightness(1.05)}.dmr-secondary{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.dmr-secondary:hover{border-color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-primary:active,.dmr-secondary:active,.dmr-icon-button:active{transform:scale(.98)}.dmr-primary:disabled,.dmr-secondary:disabled,.dmr-text-button:disabled,.dmr-icon-button:disabled{cursor:not-allowed;opacity:.5}.dmr-message{display:flex;align-items:flex-start;gap:7px;padding:10px 12px;border-radius:10px;font-size:12px}.dmr-message.success{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent)}.dmr-message.error{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}.dmr-status-head{justify-content:space-between}.dmr-eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--dmr-accent)}.dmr-eyebrow i{width:7px;height:7px;border-radius:50%;background:currentColor;box-shadow:0 0 0 4px var(--dmr-accent-soft)}.dmr-icon-button{display:inline-flex;align-items:center;justify-content:center;flex:none;width:44px;height:44px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:transparent;color:var(--dsw-alias-label-secondary)}.dmr-icon-button:hover{color:var(--dsw-alias-state-error-primary);border-color:currentColor}.dmr-share{display:flex;flex-direction:column;gap:9px;padding:13px;border:1px solid color-mix(in srgb,var(--dmr-accent) 32%,var(--dsw-alias-border-l1));border-radius:13px;background:var(--dmr-accent-soft)}.dmr-share-layout{display:grid;grid-template-columns:196px minmax(0,1fr);gap:16px;align-items:center}.dmr-qr-card{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:5px;padding:10px;border-radius:12px;background:#fff;color:#111827;text-align:center}.dmr-qr-card img{display:block;width:176px;height:176px;max-width:100%;object-fit:contain}.dmr-qr-card strong{font-size:12px}.dmr-qr-card small{color:#4b5563;font-size:10px}.dmr-qr-loading{display:grid;place-items:center;width:176px;height:176px;color:#64748b;font-size:12px}.dmr-share-detail{min-width:0;display:flex;flex-direction:column;gap:10px}.dmr-share-detail>div:first-child{display:flex;flex-direction:column;gap:4px}.dmr-link{padding:10px 11px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);font:12px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-all;color:var(--dsw-alias-label-secondary)}.dmr-share-actions{display:flex;gap:8px;flex-wrap:wrap}.dmr-share-actions .dmr-primary{align-self:auto}.dmr-overview{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.dmr-overview-card{display:flex;flex-direction:column;gap:3px;padding:12px;border:1px solid var(--dsw-alias-border-l1);border-radius:12px;background:var(--dsw-alias-bg-layer-1)}.dmr-overview-card>span{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-overview-card strong{font-size:16px;letter-spacing:-.01em}.dmr-section{display:flex;flex-direction:column;gap:9px}.dmr-section-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.dmr-section-head small{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-text-button{border:0;background:transparent;color:var(--dmr-accent);padding:8px;min-height:36px;font-weight:600}.dmr-task-list{display:flex;flex-direction:column;gap:8px}.dmr-task{display:flex;align-items:flex-start;gap:9px;padding:10px 11px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}.dmr-task>div{display:flex;min-width:0;flex:1;flex-direction:column;gap:2px}.dmr-task strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dmr-phase{flex:none;border-radius:999px;padding:3px 8px;font-size:11px;background:var(--dmr-accent-soft);color:var(--dmr-accent)}.dmr-phase.write{color:var(--dsw-alias-state-success-primary)}.dmr-phase.code{color:var(--dk-warn)}.dmr-phase.search{color:#0d9488}.dmr-empty{padding:18px 12px;text-align:center;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-label-secondary);font-size:12px}.dmr-note{display:flex;flex-direction:column;gap:9px;padding-top:2px}.dmr-note blockquote{margin:0;padding:10px 12px;border-left:3px solid var(--dmr-accent);border-radius:0 9px 9px 0;background:var(--dmr-accent-soft);white-space:pre-wrap;font-size:12px}.dmr-note textarea{min-height:88px;resize:vertical;line-height:1.5}.dmr-note .dmr-secondary{align-self:flex-start}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media (max-width:680px){.dmr{gap:14px;font-size:14px}.dmr h3{font-size:18px}.dmr-steps{grid-template-columns:1fr;gap:8px}.dmr-steps li{padding:10px}.dmr-steps small,.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{font-size:12px}.dmr-network-grid{grid-template-columns:1fr;gap:10px}.dmr-field input,.dmr-field select{font-size:16px}.dmr-primary,.dmr-secondary{width:100%;font-size:14px}.dmr-share-layout{grid-template-columns:1fr;gap:12px}.dmr-qr-card{width:min(240px,100%);margin:0 auto}.dmr-qr-card img,.dmr-qr-loading{width:210px;height:210px}.dmr-share-actions{flex-direction:column}.dmr-share-actions .dmr-primary{width:100%}.dmr-overview{gap:8px}.dmr-overview-card{padding:11px}.dmr-status-head{gap:8px}.dmr-link{font-size:11px}.dmr-note textarea{font-size:16px;min-height:104px}.dmr-note .dmr-secondary{align-self:stretch}.dmr-compact .dmr-hero-icon{width:40px;height:40px;border-radius:13px}}@media (prefers-reduced-motion:reduce){.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button,.dmr-field input,.dmr-field select,.dmr-note textarea{transition:none}}.dmr-lan{flex:none;margin-top:6px;padding-top:16px;border-top:1px solid var(--dsw-alias-border-l1)}.dmr-lan-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dmr-lan-title{min-width:0;display:flex;flex-direction:column;gap:4px}.dmr-lan-title p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}.dmr-lan-badge{flex:none;display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:5px 10px;font-size:11px;font-weight:700;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary)}.dmr-lan-badge.on{border-color:color-mix(in srgb,var(--dmr-accent) 45%,transparent);background:var(--dmr-accent-soft);color:var(--dmr-accent)}.dmr-lan-active,.dmr-lan-idle{display:flex;flex-direction:column;gap:12px}.dmr-lan-active .dmr-share-detail small strong{color:var(--dsw-alias-state-error-primary)}.dmr-danger{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,var(--dsw-alias-border-l2));color:var(--dsw-alias-state-error-primary)}.dmr-danger:hover{border-color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}
|
|
11490
|
-
|
|
11491
|
-
* \u7EDF\u4E00\u8D70\u5E95\u90E8 Tab \u680F\u300C\u4F1A\u8BDD\u300D\u9875\u7B7E\uFF0C\u628A\u624B\u60AC\u6D6E\u5728\u5185\u5BB9\u4E0A\u8FD8\u538B\u8FC7\u8F93\u5165\u533A\uFF08\u7528\u6237\u5B9E\u6D4B\uFF09\u3002 */
|
|
11492
|
-
@media (max-width:700px){.dsh-mobile-scrim{position:fixed;inset:0;z-index:75;background:rgba(8,10,14,.45);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);touch-action:none}
|
|
11493
|
-
/* ---- \u4EFF ZCode \u624B\u673A\u7AEF\uFF1A\u5E95\u90E8 Tab \u680F + \u8F93\u5165\u533A\u5438\u9644\u5E95\u90E8 ---- */
|
|
11494
|
-
.dsh-mobile-tabbar{position:fixed;left:0;right:0;bottom:0;z-index:65;display:flex;align-items:stretch;justify-content:space-around;padding:6px 8px calc(8px + env(safe-area-inset-bottom,0px));background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#1c2230) 92%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-top:1px solid var(--dsw-alias-border-l1,rgba(127,139,161,.25));touch-action:manipulation}
|
|
11495
|
-
.dsh-mobile-tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:48px;padding:4px 0;border:0;background:transparent;color:var(--dsw-alias-label-tertiary,#8b95ab);font:600 11px/1.2 inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;border-radius:10px}
|
|
11496
|
-
.dsh-mobile-tab svg{width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
|
|
11497
|
-
.dsh-mobile-tab.on{color:var(--dsw-alias-label-primary,#e6eaf2)}
|
|
11498
|
-
.dsh-mobile-tab.on svg{color:var(--dk-accent,#4d9fff)}
|
|
11499
|
-
.dsh-mobile-tab:active{transform:scale(.94)}
|
|
11500
|
-
/* \u300C\u4EFB\u52A1\u300D\u9875\u7B7E\u89D2\u6807\uFF1A\u8FDB\u884C\u4E2D=\u84DD\uFF08\u6570\u91CF\uFF09\uFF0C\u7B49\u5F85\u786E\u8BA4=\u7EA2\uFF08\u6570\u91CF+\u8109\u51B2\uFF09\u2014\u2014\u63A5\u529B\u573A\u666F\u91CC
|
|
11501
|
-
* \u7B49\u5F85\u786E\u8BA4\u662F\u6700\u9700\u8981\u4EBA\u4ECB\u5165\u7684\u72B6\u6001\uFF0C\u4E00\u773C\u53EF\u89C1\uFF1B\u6570\u636E\u6765\u81EA runstate \u5BBF\u4E3B\u8DEF\u7531\u4F4E\u9891\u8F6E\u8BE2\u3002 */
|
|
11502
|
-
.dsh-mobile-tab{position:relative}
|
|
11503
|
-
.dsh-mobile-tab-badge{position:absolute;top:0;right:calc(50% - 26px);box-sizing:border-box;min-width:16px;height:16px;padding:0 4px;border-radius:9px;display:flex;align-items:center;justify-content:center;background:#4d9fff;color:#fff;font-size:10px;font-weight:700;line-height:1;font-variant-numeric:tabular-nums;box-shadow:0 2px 8px rgba(0,0,0,.35);pointer-events:none}
|
|
11504
|
-
.dsh-mobile-tab-badge.wait{background:#ef4444;animation:dsh-badge-pulse 1.2s ease-in-out infinite}
|
|
11505
|
-
@keyframes dsh-badge-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.18)}}
|
|
11506
|
-
@media (prefers-reduced-motion:reduce){.dsh-mobile-tab-badge.wait{animation:none}}
|
|
11507
|
-
/* \u8F93\u5165\u533A\u5438\u9644\u5230 Tab \u680F\u4E0A\u65B9\uFF1A\u5BBF\u4E3B\u628A\u6B22\u8FCE\u5185\u5BB9 justify-content:center \u5782\u76F4\u5C45\u4E2D\uFF0C
|
|
11508
|
-
* \u624B\u673A\u89C6\u53E3\u4E0B\u8F93\u5165\u5361\u7247\u60AC\u5728\u4E2D\u90E8\u3001\u4E0B\u65B9\u7559\u51FA\u5927\u7247\u7A7A\u767D\u3002\u6539\u7528\u300C\u8F93\u5165\u533A margin-top:auto\u300D
|
|
11509
|
-
* \u8D34\u5E95\uFF0C\u5E76\u7ED9\u6EDA\u52A8\u4F53\u7559\u51FA Tab \u680F\u9AD8\u5EA6\u7684\u5185\u8FB9\u8DDD\uFF0C\u907F\u514D\u5185\u5BB9\u88AB Tab \u680F\u906E\u6321\u3002
|
|
11510
|
-
* \u26A0\uFE0F \u7EDD\u4E0D\u80FD\u7ED9\u6EDA\u52A8\u4F53\u52A0 justify-content:flex-end/center \u8D34\u5E95\uFF1A\u5185\u5BB9\u4F1A\u88AB\u6324\u5230\u6EDA\u52A8\u4F53
|
|
11511
|
-
* \u8D77\u70B9\u4E4B\u5916\uFF0CChrome \u4E0D\u628A\u8D77\u70B9\u65B9\u5411\u6EA2\u51FA\u7B97\u8FDB scrollHeight\uFF08\u624B\u673A\u89C6\u53E3\u5B9E\u6D4B
|
|
11512
|
-
* scrollHeight==clientHeight\u3001maxScroll==0\uFF09\uFF0C\u4F1A\u8BDD\u8BB0\u5F55\u5F7B\u5E95\u6EDA\u4E0D\u52A8\u3001\u9996\u6761\u6D88\u606F\u6C38\u8FDC
|
|
11513
|
-
* \u770B\u4E0D\u5230\u3002\u5BBF\u4E3B\u534A\u90E8\u65E7\u7248\u6CE8\u5165\u91CC\u8FD8\u7559\u7740\u90A3\u6761 flex-end\uFF08\u8981\u91CD\u542F dsh web \u624D\u6D88\u5931\uFF09\uFF0C\u8FD9\u91CC
|
|
11514
|
-
* \u7528\u66F4\u9AD8\u4F18\u5148\u7EA7\u7684\u9009\u62E9\u5668\u663E\u5F0F\u590D\u4F4D\uFF1A\u5237\u65B0\u9875\u9762\u5373\u4FEE\u597D\uFF0C\u4E0D\u5FC5\u7B49\u91CD\u542F\u3002 */
|
|
11515
|
-
[class*="scrollBody"][data-conversation-scroll]{justify-content:flex-start !important;padding-bottom:calc(72px + env(safe-area-inset-bottom,0px)) !important}
|
|
11516
|
-
[class*="scrollBody"]{padding-bottom:calc(72px + env(safe-area-inset-bottom,0px)) !important}
|
|
11517
|
-
[class*="scrollBody"]>[class*="composerSeat"]{margin-top:auto;padding-bottom:6px}
|
|
11518
|
-
/* \u8F93\u5165\u533A\u5DE5\u5177\u884C\u4E0A\u7684 dsh-dock chip\uFF08\u7528\u91CF/\u4F59\u989D\uFF09\uFF1A\u7A84\u5C4F\u4E0B 28cqw \u7684\u5BBD\u5EA6\u4E0A\u9650\u628A\u5B83\u4EEC\u6324\u6210
|
|
11519
|
-
* \u300C\u2026\u300D\u300C\u4F59..\u300D\uFF08\u624B\u673A\u5B9E\u6D4B\uFF09\uFF0C\u65E2\u8BFB\u4E0D\u51FA\u6570\u503C\u53C8\u767D\u5360\u8F93\u5165\u884C\u7A7A\u95F4\u3002\u624B\u673A\u7AEF\u6574\u7EC4\u6536\u8D77\uFF0C\u6570\u503C\u5728
|
|
11520
|
-
* \u5E95\u90E8\u300C\u529F\u80FD\u575E\u300D\u91CC\u770B\uFF08\u7528\u91CF/\u4F59\u989D\u9875\u4FE1\u606F\u66F4\u5168\uFF09\uFF1B\u684C\u9762\u7AEF\u4E0D\u52A8\u3002 */
|
|
11521
|
-
.dockchip-row{display:none}
|
|
11522
|
-
/* \u6536\u8D77\u7684\u4FA7\u680F\u8F68\u9053\uFF08collapsed rail\uFF09\u5728\u7A84\u5C4F\u53EA\u5269 1px \u5360\u4F4D\uFF0C\u4F46\u8F68\u9053\u91CC\u7684\u6309\u94AE
|
|
11523
|
-
* \u4ECD\u4F1A\u6EA2\u51FA\u8D34\u5728\u5DE6\u8FB9\u7F18\uFF08\u529F\u80FD\u575E/\u8FDB\u5316/\u8BBE\u7F6E\u4E09\u679A\u9732\u51FA\u534A\u8FB9\u7684\u5706\u94AE\uFF09\u3002\u9690\u85CF\u6574\u5217\uFF0C
|
|
11524
|
-
* \u8FD9\u4E9B\u5165\u53E3\u5DF2\u7531\u5E95\u90E8 Tab \u680F\u63A5\u7BA1\uFF1B\u5C55\u5F00\u62BD\u5C49\uFF08z 80\uFF09\u4E0D\u53D7\u5F71\u54CD\u3002 */
|
|
11525
|
-
[class*="sidebarCol"]:has([class*="collapsed"]){visibility:hidden}
|
|
11526
|
-
/* \u8F6F\u952E\u76D8\u5F39\u51FA\uFF08visualViewport \u5224\u5B9A\uFF0C\u6302 html.dsh-dock-kbd\uFF09\uFF1ATab \u680F\u6574\u4F53\u8BA9\u4F4D\uFF08\u6253\u5B57\u65F6
|
|
11527
|
-
* \u5B83\u53EA\u4F1A\u6324\u5360\u952E\u76D8\u4E0A\u65B9\u7684\u4E00\u7EBF\u7A7A\u95F4\uFF09\uFF0C\u6EDA\u52A8\u4F53\u7559\u767D\u6536\u7A84\u3002\u9009\u62E9\u5668\u7279\u5F02\u6027\u9AD8\u4E8E\u4E0A\u9762\u7684 72px
|
|
11528
|
-
* \u7559\u767D\u89C4\u5219\uFF0C\u80FD\u538B\u8FC7\u53BB\u3002\u5BBF\u4E3B\u63A5\u7BA1\u671F\u95F4\u7531\u5BBF\u4E3B\u811A\u672C\u540C\u6B65\u7F6E/\u6458\u8FD9\u4E2A\u7C7B\u3002 */
|
|
11529
|
-
html.dsh-dock-kbd .dsh-mobile-tabbar{display:none !important}
|
|
11530
|
-
html.dsh-dock-kbd [class*="scrollBody"]{padding-bottom:12px !important}
|
|
11531
|
-
/* \u529F\u80FD\u575E\u9762\u677F\u5728\u624B\u673A\u7AEF\u62AC\u5230\u539F\u751F\u5F39\u5C42\u4E4B\u4E0A\uFF1A\u4ECE\u4FA7\u680F\u8FDB\u7684\u5B98\u65B9\u63D2\u4EF6\u7BA1\u7406\u9875\u7B49\u539F\u751F\u5F39\u5C42 z \u5E8F\u9AD8\u4E8E
|
|
11532
|
-
* \u9762\u677F\u9ED8\u8BA4\u7684 200\uFF0C\u529F\u80FD\u575E\u5F00\u5728\u4E0B\u9762\u4F1A\u88AB\u76D6\u4F4F\u2014\u2014\u300C\u63D2\u4EF6\u300D\u9875\u7B7E\u70B9\u4E86\u50CF\u6CA1\u53CD\u5E94/\u9732\u51FA\u539F\u9875\u9762\u3002 */
|
|
11533
|
-
[class*="dockm-backdrop"]{z-index:2000 !important}}`,
|
|
12013
|
+
`,
|
|
11534
12014
|
View: MobileRelayView,
|
|
11535
|
-
HomeStat: MobileRelayHomeStat
|
|
11536
|
-
Overlay: MobileRelayOverlay
|
|
12015
|
+
HomeStat: MobileRelayHomeStat
|
|
11537
12016
|
};
|
|
11538
12017
|
|
|
11539
12018
|
// features/mobile/view.js
|
|
@@ -11541,54 +12020,36 @@ var import_react22 = __toESM(require("react"), 1);
|
|
|
11541
12020
|
var import_react23 = require("react");
|
|
11542
12021
|
var MOBILE_QUERY_NARROW = "(max-width: 820px)";
|
|
11543
12022
|
var MOBILE_QUERY_COARSE = "(pointer: coarse) and (hover: none)";
|
|
11544
|
-
var
|
|
11545
|
-
|
|
11546
|
-
|
|
11547
|
-
if (typeof localStorage !== "undefined") {
|
|
11548
|
-
const raw = localStorage.getItem(MOBILE_STORE_KEY);
|
|
11549
|
-
const obj = raw ? JSON.parse(raw) : null;
|
|
11550
|
-
if (obj && typeof obj === "object" && typeof obj.floating === "boolean") mobilePref.floating = obj.floating;
|
|
11551
|
-
}
|
|
11552
|
-
} catch {
|
|
11553
|
-
}
|
|
11554
|
-
var prefListeners = /* @__PURE__ */ new Set();
|
|
11555
|
-
function notifyPref() {
|
|
11556
|
-
for (const fn of prefListeners) {
|
|
11557
|
-
try {
|
|
11558
|
-
fn();
|
|
11559
|
-
} catch {
|
|
11560
|
-
}
|
|
11561
|
-
}
|
|
11562
|
-
}
|
|
11563
|
-
function floatingShown() {
|
|
11564
|
-
return mobilePref.floating !== false;
|
|
11565
|
-
}
|
|
11566
|
-
function setFloatingShown(value) {
|
|
11567
|
-
mobilePref.floating = value !== false;
|
|
12023
|
+
var MOBILE_QUERY_CHROME = "(max-width: 700px)";
|
|
12024
|
+
function mobileActive() {
|
|
12025
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
11568
12026
|
try {
|
|
11569
|
-
|
|
12027
|
+
return window.matchMedia(MOBILE_QUERY_NARROW).matches || window.matchMedia(MOBILE_QUERY_COARSE).matches;
|
|
11570
12028
|
} catch {
|
|
12029
|
+
return false;
|
|
11571
12030
|
}
|
|
11572
|
-
notifyPref();
|
|
11573
12031
|
}
|
|
11574
|
-
function
|
|
11575
|
-
|
|
11576
|
-
return () => {
|
|
11577
|
-
prefListeners.delete(fn);
|
|
12032
|
+
function watchQuery(query, onChange) {
|
|
12033
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
|
|
11578
12034
|
};
|
|
11579
|
-
|
|
11580
|
-
function mobileActive() {
|
|
11581
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
12035
|
+
let mq = null;
|
|
11582
12036
|
try {
|
|
11583
|
-
|
|
12037
|
+
mq = window.matchMedia(query);
|
|
11584
12038
|
} catch {
|
|
11585
|
-
return
|
|
12039
|
+
return () => {
|
|
12040
|
+
};
|
|
11586
12041
|
}
|
|
12042
|
+
const update = () => onChange(mq.matches);
|
|
12043
|
+
update();
|
|
12044
|
+
if (typeof mq.addEventListener === "function") mq.addEventListener("change", update);
|
|
12045
|
+
else if (typeof mq.addListener === "function") mq.addListener(update);
|
|
12046
|
+
return () => {
|
|
12047
|
+
if (typeof mq.removeEventListener === "function") mq.removeEventListener("change", update);
|
|
12048
|
+
else if (typeof mq.removeListener === "function") mq.removeListener(update);
|
|
12049
|
+
};
|
|
11587
12050
|
}
|
|
11588
|
-
function MobileOverlay(
|
|
11589
|
-
const ctx = props && props.ctx;
|
|
12051
|
+
function MobileOverlay() {
|
|
11590
12052
|
const [active, setActive] = (0, import_react23.useState)(() => mobileActive());
|
|
11591
|
-
const [floating, setFloating] = (0, import_react23.useState)(() => floatingShown());
|
|
11592
12053
|
(0, import_react23.useEffect)(() => {
|
|
11593
12054
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
|
|
11594
12055
|
let mqs = [];
|
|
@@ -11628,56 +12089,171 @@ function MobileOverlay(props) {
|
|
|
11628
12089
|
document.body.removeAttribute("data-dk-mobile");
|
|
11629
12090
|
};
|
|
11630
12091
|
}, [active]);
|
|
11631
|
-
(0, import_react23.useEffect)(() =>
|
|
11632
|
-
|
|
11633
|
-
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
12092
|
+
(0, import_react23.useEffect)(() => mobileChrome(), []);
|
|
12093
|
+
return null;
|
|
12094
|
+
}
|
|
12095
|
+
function mobileChrome() {
|
|
12096
|
+
if (typeof window === "undefined" || typeof document === "undefined") return void 0;
|
|
12097
|
+
const mq = window.matchMedia ? window.matchMedia(MOBILE_QUERY_CHROME) : null;
|
|
12098
|
+
if (!mq) return void 0;
|
|
12099
|
+
if (window.__dshDockMobileDrawer === "host") return void 0;
|
|
12100
|
+
window.__dshDockMobileDrawer = "client";
|
|
12101
|
+
const narrow = () => mq.matches;
|
|
12102
|
+
const frameEl = () => document.querySelector('[class$="frame"]');
|
|
12103
|
+
const sidebarCollapsed = () => {
|
|
12104
|
+
const f = frameEl();
|
|
12105
|
+
return !!f && f.hasAttribute("data-sidebar-collapsed");
|
|
12106
|
+
};
|
|
12107
|
+
const dialogOpen = () => !!document.querySelector('[role="dialog"][class*="panel"]');
|
|
12108
|
+
const rightOpen = () => !!document.querySelector("[data-sidebar-right-panel][data-sidebar-right-open]");
|
|
12109
|
+
const collapse = () => {
|
|
12110
|
+
const b = document.querySelector('button[aria-label="\u6536\u8D77\u4FA7\u8FB9\u680F"],button[aria-label="Collapse sidebar"]');
|
|
12111
|
+
if (b) b.click();
|
|
12112
|
+
};
|
|
12113
|
+
const expand = () => {
|
|
12114
|
+
const b = document.querySelector('button[aria-label="\u6253\u5F00\u4FA7\u8FB9\u680F"],button[aria-label="Open sidebar"]');
|
|
12115
|
+
if (b) b.click();
|
|
12116
|
+
};
|
|
12117
|
+
const closeDetails = () => {
|
|
12118
|
+
const panel = document.querySelector("[data-sidebar-right-panel][data-sidebar-right-open]");
|
|
12119
|
+
if (!panel) return;
|
|
12120
|
+
const toggle = panel.querySelector("[data-sidebar-right-toggle]");
|
|
12121
|
+
if (toggle) toggle.click();
|
|
12122
|
+
};
|
|
12123
|
+
const scrim = document.createElement("div");
|
|
12124
|
+
scrim.className = "dsh-mobile-scrim";
|
|
12125
|
+
document.body.appendChild(scrim);
|
|
12126
|
+
document.querySelectorAll(".dsh-mobile-tabbar").forEach((el) => el.remove());
|
|
12127
|
+
const burger = document.createElement("button");
|
|
12128
|
+
burger.type = "button";
|
|
12129
|
+
burger.className = "dsh-mobile-burger";
|
|
12130
|
+
burger.setAttribute("aria-label", "\u6253\u5F00\u4F1A\u8BDD\u5217\u8868");
|
|
12131
|
+
burger.setAttribute("aria-expanded", "false");
|
|
12132
|
+
burger.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7h16"/><path d="M4 12h16"/><path d="M4 17h16"/></svg><span class="dsh-mobile-burger-badge" hidden></span>';
|
|
12133
|
+
burger.addEventListener("click", () => expand());
|
|
12134
|
+
document.body.appendChild(burger);
|
|
12135
|
+
const syncBurger = () => {
|
|
12136
|
+
const expanded = !sidebarCollapsed();
|
|
12137
|
+
burger.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
12138
|
+
burger.classList.toggle("on", expanded);
|
|
12139
|
+
};
|
|
12140
|
+
const badge = burger.querySelector(".dsh-mobile-burger-badge");
|
|
12141
|
+
let runstateGone = false;
|
|
12142
|
+
const pollTasks = () => {
|
|
12143
|
+
if (runstateGone || !badge || !narrow() || document.visibilityState === "hidden" || !burger.isConnected) return;
|
|
12144
|
+
const on = stateOf("runstate").enabled !== false;
|
|
12145
|
+
if (!on && !window.__dshDockRunstate) {
|
|
12146
|
+
badge.hidden = true;
|
|
12147
|
+
return;
|
|
11647
12148
|
}
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
if (
|
|
11654
|
-
|
|
11655
|
-
|
|
11656
|
-
|
|
11657
|
-
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
12149
|
+
fetch("dsh-dock/runstate/status", {
|
|
12150
|
+
method: "POST",
|
|
12151
|
+
headers: { "content-type": "application/json" },
|
|
12152
|
+
body: "{}"
|
|
12153
|
+
}).then(async (res) => {
|
|
12154
|
+
if (res.status === 404 || res.status === 405) {
|
|
12155
|
+
runstateGone = true;
|
|
12156
|
+
badge.hidden = true;
|
|
12157
|
+
return null;
|
|
12158
|
+
}
|
|
12159
|
+
const body = await res.json().catch(() => null);
|
|
12160
|
+
if (!body) return null;
|
|
12161
|
+
const active = body.data && body.data.active || [];
|
|
12162
|
+
const waiting = active.reduce((n, t) => n + (Array.isArray(t.approvals) ? t.approvals.length : 0), 0);
|
|
12163
|
+
if (waiting > 0) {
|
|
12164
|
+
badge.textContent = waiting > 99 ? "99+" : String(waiting);
|
|
12165
|
+
badge.className = "dsh-mobile-burger-badge wait";
|
|
12166
|
+
badge.hidden = false;
|
|
12167
|
+
burger.setAttribute("title", waiting + " \u4E2A\u4EFB\u52A1\u7B49\u5F85\u4F60\u786E\u8BA4");
|
|
12168
|
+
} else if (active.length > 0) {
|
|
12169
|
+
badge.textContent = active.length > 99 ? "99+" : String(active.length);
|
|
12170
|
+
badge.className = "dsh-mobile-burger-badge";
|
|
12171
|
+
badge.hidden = false;
|
|
12172
|
+
burger.setAttribute("title", active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D");
|
|
12173
|
+
} else {
|
|
12174
|
+
badge.hidden = true;
|
|
12175
|
+
burger.removeAttribute("title");
|
|
12176
|
+
}
|
|
12177
|
+
}).catch(() => {
|
|
12178
|
+
});
|
|
12179
|
+
};
|
|
12180
|
+
const tasksTimer = setInterval(pollTasks, 3e3);
|
|
12181
|
+
const onVisible = () => {
|
|
12182
|
+
if (document.visibilityState === "visible") pollTasks();
|
|
12183
|
+
};
|
|
12184
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
12185
|
+
pollTasks();
|
|
12186
|
+
const vv = window.visualViewport || null;
|
|
12187
|
+
const kbdSync = () => {
|
|
12188
|
+
if (!vv) return;
|
|
12189
|
+
const kbd = vv.height > 0 && window.innerHeight - vv.height > 120;
|
|
12190
|
+
document.documentElement.classList.toggle("dsh-dock-kbd", kbd);
|
|
12191
|
+
};
|
|
12192
|
+
const sync = () => {
|
|
12193
|
+
kbdSync();
|
|
12194
|
+
document.querySelectorAll(".dsh-mobile-tabbar").forEach((el) => el.remove());
|
|
12195
|
+
const on = narrow() && !!frameEl() && !dialogOpen();
|
|
12196
|
+
const collapsed = sidebarCollapsed();
|
|
12197
|
+
const right = rightOpen();
|
|
12198
|
+
if (scrim) scrim.style.display = on && !collapsed ? "" : "none";
|
|
12199
|
+
burger.style.display = narrow() && !!frameEl() && !panelNav.open && !right ? "" : "none";
|
|
12200
|
+
syncBurger();
|
|
12201
|
+
};
|
|
12202
|
+
sync();
|
|
12203
|
+
const observer = typeof MutationObserver !== "undefined" ? new MutationObserver(sync) : null;
|
|
12204
|
+
if (observer) observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-sidebar-collapsed"], subtree: true });
|
|
12205
|
+
const timer = setInterval(sync, 1500);
|
|
12206
|
+
const onMq = () => sync();
|
|
12207
|
+
if (mq.addEventListener) mq.addEventListener("change", onMq);
|
|
12208
|
+
else if (mq.addListener) mq.addListener(onMq);
|
|
12209
|
+
window.addEventListener("resize", kbdSync);
|
|
12210
|
+
if (vv && vv.addEventListener) vv.addEventListener("resize", kbdSync);
|
|
12211
|
+
const onClick = (e) => {
|
|
12212
|
+
if (!narrow()) return;
|
|
12213
|
+
const t = e.target;
|
|
12214
|
+
if (!t || !t.closest) return;
|
|
12215
|
+
if (t.closest(".dsh-mobile-burger")) return;
|
|
12216
|
+
const expanded = !!document.querySelector('button[aria-label="\u6536\u8D77\u4FA7\u8FB9\u680F"],button[aria-label="Collapse sidebar"]');
|
|
12217
|
+
const col = document.querySelector('[class*="sidebarCol"]');
|
|
12218
|
+
const inSidebar = col && col.contains(t);
|
|
12219
|
+
if (!expanded && !inSidebar) return;
|
|
12220
|
+
if (inSidebar) {
|
|
12221
|
+
const row = t.closest('[role="treeitem"]');
|
|
12222
|
+
const rowKey = row && row.getAttribute("data-row-key") || "";
|
|
12223
|
+
const sessionRow = rowKey && rowKey.startsWith("session:") || row && !rowKey && !row.querySelector('[role="treeitem"]') && row.closest('[role="tree"]');
|
|
12224
|
+
const fresh = t.closest('[class*="newSession"]');
|
|
12225
|
+
if (sessionRow || fresh) {
|
|
12226
|
+
setTimeout(() => {
|
|
12227
|
+
collapse();
|
|
12228
|
+
closeDetails();
|
|
12229
|
+
}, 300);
|
|
12230
|
+
return;
|
|
12231
|
+
}
|
|
12232
|
+
if (rowKey.startsWith("workspace:")) return;
|
|
12233
|
+
setTimeout(() => {
|
|
12234
|
+
if (document.querySelector('[role="dialog"]')) collapse();
|
|
12235
|
+
}, 260);
|
|
12236
|
+
return;
|
|
11667
12237
|
}
|
|
12238
|
+
if (t.closest('[role="dialog"],[class*="dockm"],[class*="dgfab"],[class*="dgwin"],[class*="dgame"],[data-sidebar-right-panel]')) return;
|
|
12239
|
+
collapse();
|
|
12240
|
+
};
|
|
12241
|
+
document.addEventListener("click", onClick, true);
|
|
12242
|
+
return () => {
|
|
12243
|
+
document.removeEventListener("click", onClick, true);
|
|
12244
|
+
if (observer) observer.disconnect();
|
|
12245
|
+
clearInterval(timer);
|
|
12246
|
+
clearInterval(tasksTimer);
|
|
12247
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
12248
|
+
if (mq.removeEventListener) mq.removeEventListener("change", onMq);
|
|
12249
|
+
else if (mq.removeListener) mq.removeListener(onMq);
|
|
12250
|
+
window.removeEventListener("resize", kbdSync);
|
|
12251
|
+
if (vv && vv.removeEventListener) vv.removeEventListener("resize", kbdSync);
|
|
12252
|
+
document.documentElement.classList.remove("dsh-dock-kbd");
|
|
12253
|
+
if (scrim) scrim.remove();
|
|
12254
|
+
burger.remove();
|
|
12255
|
+
if (window.__dshDockMobileDrawer === "client") delete window.__dshDockMobileDrawer;
|
|
11668
12256
|
};
|
|
11669
|
-
return import_react22.default.createElement("button", {
|
|
11670
|
-
type: "button",
|
|
11671
|
-
className: "dkmob-fab",
|
|
11672
|
-
"aria-label": "\u5F00\u5173\u4FA7\u680F",
|
|
11673
|
-
title: "\u5F00\u5173\u4FA7\u680F",
|
|
11674
|
-
onClick: onToggle
|
|
11675
|
-
}, import_react22.default.createElement(
|
|
11676
|
-
"svg",
|
|
11677
|
-
{ width: 20, height: 20, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
|
|
11678
|
-
import_react22.default.createElement("rect", { x: 1.5, y: 2.5, width: 13, height: 11, rx: 2 }),
|
|
11679
|
-
import_react22.default.createElement("line", { x1: 6, y1: 2.5, x2: 6, y2: 13.5 })
|
|
11680
|
-
));
|
|
11681
12257
|
}
|
|
11682
12258
|
function useViewportSize() {
|
|
11683
12259
|
const [size, setSize] = (0, import_react23.useState)(() => typeof window === "undefined" ? null : { w: window.innerWidth, h: window.innerHeight });
|
|
@@ -11689,31 +12265,38 @@ function useViewportSize() {
|
|
|
11689
12265
|
}, []);
|
|
11690
12266
|
return size;
|
|
11691
12267
|
}
|
|
11692
|
-
function
|
|
12268
|
+
function useMobileState() {
|
|
11693
12269
|
const [active, setActive] = (0, import_react23.useState)(() => mobileActive());
|
|
11694
|
-
const [
|
|
11695
|
-
const
|
|
12270
|
+
const [chrome, setChrome] = (0, import_react23.useState)(() => typeof window === "undefined" || typeof window.matchMedia !== "function" ? false : window.matchMedia(MOBILE_QUERY_CHROME).matches);
|
|
12271
|
+
const [owner, setOwner] = (0, import_react23.useState)(() => typeof window === "undefined" ? null : window.__dshDockMobileDrawer || null);
|
|
11696
12272
|
(0, import_react23.useEffect)(() => {
|
|
11697
|
-
|
|
12273
|
+
const offChrome = watchQuery(MOBILE_QUERY_CHROME, setChrome);
|
|
11698
12274
|
let mqs = [];
|
|
11699
12275
|
try {
|
|
11700
12276
|
mqs = [window.matchMedia(MOBILE_QUERY_NARROW), window.matchMedia(MOBILE_QUERY_COARSE)];
|
|
11701
12277
|
} catch {
|
|
11702
|
-
|
|
12278
|
+
mqs = [];
|
|
11703
12279
|
}
|
|
11704
|
-
const
|
|
11705
|
-
update();
|
|
12280
|
+
const compute = () => setActive(mqs.some((mq) => mq.matches));
|
|
11706
12281
|
for (const mq of mqs) {
|
|
11707
|
-
if (typeof mq.addEventListener === "function") mq.addEventListener("change",
|
|
11708
|
-
else if (typeof mq.addListener === "function") mq.addListener(
|
|
12282
|
+
if (typeof mq.addEventListener === "function") mq.addEventListener("change", compute);
|
|
12283
|
+
else if (typeof mq.addListener === "function") mq.addListener(compute);
|
|
11709
12284
|
}
|
|
12285
|
+
const timer = setInterval(() => setOwner(typeof window === "undefined" ? null : window.__dshDockMobileDrawer || null), 1e3);
|
|
11710
12286
|
return () => {
|
|
12287
|
+
offChrome();
|
|
11711
12288
|
for (const mq of mqs) {
|
|
11712
|
-
if (typeof mq.removeEventListener === "function") mq.removeEventListener("change",
|
|
11713
|
-
else if (typeof mq.removeListener === "function") mq.removeListener(
|
|
12289
|
+
if (typeof mq.removeEventListener === "function") mq.removeEventListener("change", compute);
|
|
12290
|
+
else if (typeof mq.removeListener === "function") mq.removeListener(compute);
|
|
11714
12291
|
}
|
|
12292
|
+
clearInterval(timer);
|
|
11715
12293
|
};
|
|
11716
12294
|
}, []);
|
|
12295
|
+
return { active, chrome, owner };
|
|
12296
|
+
}
|
|
12297
|
+
function MobileView() {
|
|
12298
|
+
const { active, chrome, owner } = useMobileState();
|
|
12299
|
+
const size = useViewportSize();
|
|
11717
12300
|
return import_react22.default.createElement(
|
|
11718
12301
|
"div",
|
|
11719
12302
|
{ className: "dkmob-root" },
|
|
@@ -11732,73 +12315,44 @@ function MobileView() {
|
|
|
11732
12315
|
import_react22.default.createElement(
|
|
11733
12316
|
"div",
|
|
11734
12317
|
{ className: "dkmob-row" },
|
|
11735
|
-
import_react22.default.createElement("span", { className: "dkmob-label" }, "\
|
|
11736
|
-
import_react22.default.createElement("
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
|
|
11740
|
-
"
|
|
11741
|
-
"
|
|
11742
|
-
|
|
11743
|
-
onClick: () => setFloatingShown(!floating)
|
|
11744
|
-
}),
|
|
11745
|
-
import_react22.default.createElement("span", { className: "dkmob-dim" }, "44px \u5706\u94AE\u56FA\u5B9A\u5728\u5DE6\u4E0B\u89D2\uFF0C\u8C03\u7528 dsh \u5B98\u65B9 toggleSidebar \u5F00\u5408\u7A84\u5C4F\u62BD\u5C49\uFF1B\u4E0D\u9700\u8981\u65F6\u53EF\u5728\u6B64\u5173\u95ED\u3002")
|
|
12318
|
+
import_react22.default.createElement("span", { className: "dkmob-label" }, "\u624B\u673A\u7AEF chrome"),
|
|
12319
|
+
import_react22.default.createElement("span", { className: "dkmob-state" + (chrome ? " on" : "") }, chrome ? "\u2264700px\uFF0C\u751F\u6548\u4E2D" : "\u672A\u547D\u4E2D"),
|
|
12320
|
+
import_react22.default.createElement(
|
|
12321
|
+
"span",
|
|
12322
|
+
{ className: "dkmob-dim" },
|
|
12323
|
+
"\u5DE6\u4E0A\u89D2\u6C49\u5821\u83DC\u5355\uFF08\u5C55\u5F00\u5DE6\u4FA7\u4F1A\u8BDD\u62BD\u5C49\uFF09+ \u4FA7\u680F\u62BD\u5C49\u906E\u7F69 + \u8F6F\u952E\u76D8\u8BA9\u4F4D\uFF1B\u5E95\u90E8 Tab \u680F\u5DF2\u6309\u7528\u6237\u8981\u6C42\u79FB\u9664\uFF0C\u63D2\u4EF6/\u8BBE\u7F6E\u7B49\u5165\u53E3\u5728\u62BD\u5C49\u91CC\u3002",
|
|
12324
|
+
owner === "host" ? "\u5F53\u524D\u7531\u5BBF\u4E3B\u6CE8\u5165\u7248\u9A71\u52A8\uFF08\u91CD\u542F dsh web \u540E\u751F\u6548\u7684\u90A3\u5957\uFF09\u3002" : owner === "client" ? "\u5F53\u524D\u7531\u5BA2\u6237\u7AEF\u81EA\u5EFA\u7248\u9A71\u52A8\uFF08\u5237\u65B0\u5373\u751F\u6548\uFF09\u3002" : ""
|
|
12325
|
+
)
|
|
11746
12326
|
),
|
|
11747
12327
|
import_react22.default.createElement(
|
|
11748
12328
|
"div",
|
|
11749
12329
|
{ className: "dkmob-note" },
|
|
11750
12330
|
"\u751F\u6548\u4E2D\u7684\u4F18\u5316\uFF1A\u8F93\u5165\u7C7B\u63A7\u4EF6\u5B57\u53F7\u62C9\u5230 16px\uFF08\u907F\u514D iOS \u805A\u7126\u7F29\u653E\u6574\u9875\uFF09\xB7 \u7EAF\u56FE\u6807\u6309\u94AE\u9762\u79EF\u515C\u5E95 \u226536px \xB7 ",
|
|
11751
|
-
"\u53BB\u6389\u70B9\u6309\u9AD8\u4EAE\u4E0E\u53CC\u51FB\u7F29\u653E\u5224\u5B9A \xB7 \u4EE3\u7801\u5757\u6A2A\u5411\u6EDA\u52A8\u3001\u884C\u5185\u4EE3\u7801\u81EA\u52A8\u6362\u884C \xB7
|
|
12331
|
+
"\u53BB\u6389\u70B9\u6309\u9AD8\u4EAE\u4E0E\u53CC\u51FB\u7F29\u653E\u5224\u5B9A \xB7 \u4EE3\u7801\u5757\u6A2A\u5411\u6EDA\u52A8\u3001\u884C\u5185\u4EE3\u7801\u81EA\u52A8\u6362\u884C \xB7 \u6EDA\u52A8\u4F53 touch-action:pan-y + iOS \u60EF\u6027\u6EDA\u52A8 \xB7 ",
|
|
12332
|
+
"\u8BBE\u7F6E\u5F39\u5C42\u5185\u5BB9\u5217 min-height:0\uFF08\u5426\u5219\u7A84\u5C4F\u5F39\u5C42\u88AB\u5185\u5BB9\u6491\u9AD8\u540E\u6574\u7247\u6ED1\u4E0D\u52A8\uFF09\xB7 viewport meta \u8865 viewport-fit=cover",
|
|
11752
12333
|
"\uFF08standalone \u5168\u5C4F\u65F6\u7ED9\u5706\u89D2/\u5218\u6D77\u7559\u5B89\u5168\u533A\uFF09\u3002\u505C\u7528\u672C\u529F\u80FD\u5373\u5168\u90E8\u8FD8\u539F\u3002"
|
|
11753
12334
|
)
|
|
11754
12335
|
);
|
|
11755
12336
|
}
|
|
11756
12337
|
function MobileStat() {
|
|
11757
|
-
const
|
|
11758
|
-
const [floating, setFloating] = (0, import_react23.useState)(() => floatingShown());
|
|
11759
|
-
(0, import_react23.useEffect)(() => {
|
|
11760
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
|
|
11761
|
-
let mqs = [];
|
|
11762
|
-
try {
|
|
11763
|
-
mqs = [window.matchMedia(MOBILE_QUERY_NARROW), window.matchMedia(MOBILE_QUERY_COARSE)];
|
|
11764
|
-
} catch {
|
|
11765
|
-
return void 0;
|
|
11766
|
-
}
|
|
11767
|
-
const update = () => setActive(mqs.some((mq) => mq.matches));
|
|
11768
|
-
update();
|
|
11769
|
-
for (const mq of mqs) {
|
|
11770
|
-
if (typeof mq.addEventListener === "function") mq.addEventListener("change", update);
|
|
11771
|
-
else if (typeof mq.addListener === "function") mq.addListener(update);
|
|
11772
|
-
}
|
|
11773
|
-
return () => {
|
|
11774
|
-
for (const mq of mqs) {
|
|
11775
|
-
if (typeof mq.removeEventListener === "function") mq.removeEventListener("change", update);
|
|
11776
|
-
else if (typeof mq.removeListener === "function") mq.removeListener(update);
|
|
11777
|
-
}
|
|
11778
|
-
};
|
|
11779
|
-
}, []);
|
|
11780
|
-
(0, import_react23.useEffect)(() => subscribePref(() => setFloating(floatingShown())), []);
|
|
12338
|
+
const { active, chrome } = useMobileState();
|
|
11781
12339
|
if (!active) return import_react22.default.createElement("span", null, "\u5F53\u524D\u89C6\u53E3\u672A\u547D\u4E2D\u624B\u673A\u5F62\u6001\uFF0C\u6837\u5F0F\u672A\u6CE8\u5165");
|
|
11782
|
-
return import_react22.default.createElement("span", null, "\u624B\u673A\u6A21\u5F0F\u751F\u6548\u4E2D \xB7
|
|
12340
|
+
return import_react22.default.createElement("span", null, "\u624B\u673A\u6A21\u5F0F\u751F\u6548\u4E2D \xB7 " + (chrome ? "\u5DE6\u4E0A\u89D2\u6C49\u5821\u83DC\u5355\u5DF2\u63A5\u7BA1\u4F1A\u8BDD\u5165\u53E3" : "chrome \u5E26\u5BBD\u672A\u547D\u4E2D\uFF08\u2264700px \u624D\u542F\u7528\uFF09"));
|
|
11783
12341
|
}
|
|
11784
12342
|
var css6 = [
|
|
11785
|
-
// 浮动侧栏按钮:44px 触控面积(Apple HIG 最低建议),token 取主题变量自动适配亮暗色;
|
|
11786
|
-
// z-index 190 压在功能坞弹层(dockm-backdrop,200)之下,弹层打开时被遮罩盖住不误触。
|
|
11787
|
-
".dkmob-fab{position:fixed;left:calc(env(safe-area-inset-left,0px) + 62px);bottom:calc(env(safe-area-inset-bottom,0px) + 74px);z-index:190;width:44px;height:44px;border-radius:50%;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);display:inline-flex;align-items:center;justify-content:center;padding:0;box-shadow:0 4px 14px rgb(0 0 0 / .22);cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;transition:transform .12s var(--ds-ease-in-out),background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
|
|
11788
|
-
".dkmob-fab:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
11789
|
-
".dkmob-fab:active{transform:scale(.94);}",
|
|
11790
12343
|
// 输入类控件 16px:防 iOS 聚焦自动放大(<16px 的输入框聚焦时 Safari 强制缩放页面)
|
|
11791
12344
|
'body[data-dk-mobile="1"] :is(textarea, input:not([type]), input[type="text"], input[type="search"], input[type="url"], input[type="password"], input[type="number"], input[type="email"], [contenteditable="true"]){font-size:16px !important;}',
|
|
11792
12345
|
// 触控基础:去点按高亮、消双击缩放判定
|
|
11793
12346
|
'body[data-dk-mobile="1"] :is(button, [role="button"]){-webkit-tap-highlight-color:transparent;touch-action:manipulation;}',
|
|
11794
12347
|
// 纯图标按钮面积兜底:实测窄屏下一批 28×28 的工具钮很难点中;36px 是不引起行高剧变的上限。
|
|
11795
|
-
// 只收「唯一子元素是 svg
|
|
11796
|
-
|
|
11797
|
-
'body[data-dk-mobile="1"] button:has(> svg:only-child):not(.dsh-mobile-drawer-btn):not(.dkmob-fab){min-width:36px;min-height:36px;}',
|
|
12348
|
+
// 只收「唯一子元素是 svg」的按钮,避免撑坏带文字的行内控件;排除本模块 chrome 按钮。
|
|
12349
|
+
'body[data-dk-mobile="1"] button:has(> svg:only-child):not(.dsh-mobile-burger){min-width:36px;min-height:36px;}',
|
|
11798
12350
|
// 代码块横向滚动、行内代码换行:窄屏不撑破版面
|
|
11799
12351
|
'body[data-dk-mobile="1"] pre{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;}',
|
|
11800
12352
|
'body[data-dk-mobile="1"] code{overflow-wrap:anywhere;}',
|
|
11801
12353
|
'body[data-dk-mobile="1"] pre code{overflow-wrap:normal;}',
|
|
12354
|
+
// 滚动兜底:所有纵向滚动体可纵向平移 + iOS 惯性滚动(祖先合成层/触控声明不再吃掉触摸滚动)。
|
|
12355
|
+
'body[data-dk-mobile="1"] :is([class*="scrollBody"], [class*="sidebarCol"] [class*="list"], [role="dialog"] [class*="options"], [class*="dockm-content"]){-webkit-overflow-scrolling:touch;overscroll-behavior-y:contain;touch-action:pan-y;}',
|
|
11802
12356
|
// iOS 横竖屏切换时的字号自动膨胀关掉(:has 挂到 html 上;dsh 自身样式已依赖 :has,基线足够)
|
|
11803
12357
|
'html:has(body[data-dk-mobile="1"]){-webkit-text-size-adjust:100%;text-size-adjust:100%;}',
|
|
11804
12358
|
// 功能页自身
|
|
@@ -11808,14 +12362,85 @@ var css6 = [
|
|
|
11808
12362
|
".dkmob-state{flex:none;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 10px;font-size:11px;}",
|
|
11809
12363
|
".dkmob-state.on{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary);}",
|
|
11810
12364
|
".dkmob-dim{color:var(--dsw-alias-label-secondary);font-size:12px;}",
|
|
11811
|
-
".dkmob-note{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.7;border-top:1px solid var(--dsw-alias-border-l1);padding-top:10px;}"
|
|
12365
|
+
".dkmob-note{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.7;border-top:1px solid var(--dsw-alias-border-l1);padding-top:10px;}",
|
|
12366
|
+
// 手机端 chrome:左上角汉堡菜单 + 抽屉遮罩(窄屏 ≤700px;与宿主半部同款)
|
|
12367
|
+
"@media (max-width:700px){",
|
|
12368
|
+
".dsh-mobile-scrim{position:fixed;inset:0;z-index:75;background:rgba(8,10,14,.45);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);touch-action:none}",
|
|
12369
|
+
// 左上角汉堡菜单(三条横线):44×44 触控面积,避让刘海/圆角安全区;z 66 高于正文、
|
|
12370
|
+
// 低于遮罩 75 / 抽屉 80——抽屉展开时被自然盖住。
|
|
12371
|
+
// ⚠️ 视觉上刻意「不贴合卡片」:页面左上角本来就是空的,原生同类控件(右上的侧栏开关)
|
|
12372
|
+
// 是**裸图标**——无底色、无边框、无阴影。早期版本做成白底圆角卡片 + 阴影 + 模糊,
|
|
12373
|
+
// 悬浮在白底页面上像一块贴上去的异物(用户实测反馈「没有贴合边缘,很突兀」)。
|
|
12374
|
+
// 现在与原生同款:透明底、无边框无阴影,只留图标;点按才给极轻的底色反馈。
|
|
12375
|
+
// 视觉重量靠图标本身撑住(22px、1.9px 描边、主文字色),不靠容器。
|
|
12376
|
+
".dsh-mobile-burger{position:fixed;left:env(safe-area-inset-left,0px);top:env(safe-area-inset-top,0px);z-index:66;box-sizing:border-box;width:44px;height:44px;display:flex;align-items:center;justify-content:center;padding:0;border:0;border-radius:0;background:transparent;color:var(--dsw-alias-label-primary,#e6eaf2);cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:manipulation;transition:color .15s var(--ds-ease-in-out,ease)}",
|
|
12377
|
+
".dsh-mobile-burger svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round}",
|
|
12378
|
+
// 展开态:图标换成强调色(与原生「已激活」的语义一致),不引入额外容器。
|
|
12379
|
+
".dsh-mobile-burger.on{color:var(--dk-accent,#4d9fff)}",
|
|
12380
|
+
// 点按反馈走图标本身(用 :active 的底色透出,范围就是 44×44 触控区)。
|
|
12381
|
+
".dsh-mobile-burger:active{background:color-mix(in srgb,currentColor 12%,transparent)}",
|
|
12382
|
+
// 待确认任务角标:锚在按钮右上角的小圆点/数字。刻意做成「贴边小圆点」而不是
|
|
12383
|
+
// 底部 Tab 栏那种带容器的页签角标——汉堡是裸图标,角标再带容器就又突兀了。
|
|
12384
|
+
// 等待确认(要人介入)= 红点 + 脉冲;进行中 = 蓝色数字(弱一级,不抢注意力)。
|
|
12385
|
+
".dsh-mobile-burger-badge{position:absolute;top:4px;right:4px;box-sizing:border-box;min-width:8px;height:8px;padding:0;border-radius:999px;background:#4d9fff;font:700 9px/8px inherit;font-variant-numeric:tabular-nums;text-align:center;color:#fff;pointer-events:none;box-shadow:0 0 0 2px var(--dsw-alias-bg-layer-1,#12151b)}",
|
|
12386
|
+
".dsh-mobile-burger-badge[hidden]{display:none}",
|
|
12387
|
+
".dsh-mobile-burger-badge:not([hidden]){min-width:16px;height:16px;line-height:16px;padding:0 4px}",
|
|
12388
|
+
".dsh-mobile-burger-badge.wait{background:#ef4444;animation:dsh-burger-badge-pulse 1.2s ease-in-out infinite}",
|
|
12389
|
+
"@keyframes dsh-burger-badge-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.18)}}",
|
|
12390
|
+
"@media (prefers-reduced-motion:reduce){.dsh-mobile-burger-badge.wait{animation:none}}",
|
|
12391
|
+
// ⚠️ 「设置页滑不动」的关键兜底(客户端无条件携带 = 刷新即生效,不必等宿主重启):
|
|
12392
|
+
// 窄屏把设置弹层改成纵向堆叠后,内容列若是默认 min-height:auto 就会被内容撑高
|
|
12393
|
+
// (无头 390×844 实测列高 1216px 塞在 844px 视口里)、再被 .panel 的 overflow:hidden
|
|
12394
|
+
// 裁掉——列内滚动容器([class*=options])因此 scrollHeight==clientHeight,手指怎么滑
|
|
12395
|
+
// 都不动。补 min-height:0 后 scrollTop 0 → 425。宿主半部 MOBILE_LAYOUT_CSS 同款;
|
|
12396
|
+
// 两处都写是因为宿主注入要重启 dsh web 才更新,而客户端样式刷新即生效,覆盖窗口期。
|
|
12397
|
+
'[role="dialog"][class*="panel"]>[class*="content"]{min-height:0!important}',
|
|
12398
|
+
// 输入区吸附到视口底部 + 滚动体留白(与宿主半部同款)。
|
|
12399
|
+
// ⚠️ 底部留白只保留 iPhone home indicator 的安全区,不再额外留白。沿革:原 72px 是
|
|
12400
|
+
// 「底部 Tab 栏高度 + 安全区」;Tab 栏移除后先收到 24px,但实测(真实实例 390×844
|
|
12401
|
+
// 像素扫描)输入卡片下方仍有 **51px** 空白带,其中 24px 是这里的滚动体内边距、
|
|
12402
|
+
// 6px 是下面 composerSeat 的内边距——两者都是 Tab 栏时代的遗留,在没有底栏的页面上
|
|
12403
|
+
// 纯属浪费。收窄到「只有安全区」后卡片下沿更贴近视口底,这 30px 直接变成会话区
|
|
12404
|
+
// 可显示的正文(滚动体内边距在 flex 容器里会把 composerSeat 连同消息区一起下移/增高)。
|
|
12405
|
+
// dsh 自带的 ~21px 底部间距(卡片 margin)保留,视觉上仍有呼吸感,不会贴死屏幕边缘。
|
|
12406
|
+
// ⚠️ 绝不能给滚动体加 justify-content:flex-end/center 贴底:内容会被挤到滚动体
|
|
12407
|
+
// 起点之外,Chrome 不把起点方向溢出算进 scrollHeight(手机视口实测
|
|
12408
|
+
// scrollHeight==clientHeight、maxScroll==0),会话记录彻底滚不动、首条消息永远看不到。
|
|
12409
|
+
// 宿主半部旧版注入里还留着那条 flex-end(要重启 dsh web 才消失),这里用更高优先级
|
|
12410
|
+
// 的选择器显式复位:刷新页面即修好,不必等重启。贴底只能用输入区自己的 margin-top:auto。
|
|
12411
|
+
'[class*="scrollBody"][data-conversation-scroll]{justify-content:flex-start !important;padding-bottom:env(safe-area-inset-bottom,0px) !important}',
|
|
12412
|
+
'html:not(.dsh-dock-kbd) [class*="scrollBody"]{padding-bottom:env(safe-area-inset-bottom,0px) !important}',
|
|
12413
|
+
'html.dsh-dock-kbd [class*="scrollBody"]{padding-bottom:env(safe-area-inset-bottom,0px) !important}',
|
|
12414
|
+
'[class*="scrollBody"]>[class*="composerSeat"]{margin-top:auto;padding-bottom:0}',
|
|
12415
|
+
// 输入区工具行上的 dsh-dock chip(用量/余额):窄屏下 28cqw 的宽度上限把它们挤成
|
|
12416
|
+
// 「…」「余..」(手机实测),既读不出数值又白占输入行空间。手机端整组收起,数值在
|
|
12417
|
+
// 功能坞(抽屉里进)看;桌面端不动。
|
|
12418
|
+
".dockchip-row{display:none}",
|
|
12419
|
+
'[class*="sidebarCol"]:has([class*="collapsed"]){visibility:hidden}',
|
|
12420
|
+
// ⚠️ 列级 visibility:hidden 在 dsh 0.2.0 上挡不住:工作区浏览器给自己的
|
|
12421
|
+
// headerActions/sectionLabel 显式声明 visibility:visible(展开/收拢动画用),visibility
|
|
12422
|
+
// 可被后代覆盖,轨道按钮会从隐藏列里「透」出来(实测手机截图左缘游离按钮)。
|
|
12423
|
+
// display:none 不可被后代翻转——但只能打在**轨道根节点**上(类名同时含 root 与
|
|
12424
|
+
// collapsed 两个语义后缀),绝不能打在列上:frame 是「侧栏 0px + 中列 1fr + 右轨 0px」
|
|
12425
|
+
// 的网格,列 display:none 会从网格流里摘掉,中列被自动放置顶进 0px 轨(实测整页空屏)。
|
|
12426
|
+
// 弹层打开时豁免(设置弹层挂在列内部,display:none 会连坐成空气弹层),此时列退回
|
|
12427
|
+
// visibility 机制(由下一条 [role=dialog] 强制可见),窄屏弹层全屏铺满盖住透出的轨道。
|
|
12428
|
+
'[class*="sidebarCol"]:has([class*="collapsed"]):not(:has([role="dialog"])) [class*="root"][class*="collapsed"]{display:none !important}',
|
|
12429
|
+
// 设置/插件管理弹层挂在侧栏列内部:上面隐藏整列会把它连坐隐藏(空气弹层)。
|
|
12430
|
+
// visibility 可被后代覆盖,弹层关闭态整体卸载,所以只在真正打开时命中。
|
|
12431
|
+
'[class*="sidebarCol"]:has([class*="collapsed"]) [role="dialog"]{visibility:visible}',
|
|
12432
|
+
"html.dsh-dock-kbd .dsh-mobile-burger{display:none !important}",
|
|
12433
|
+
// 功能坞面板在手机端抬到原生弹层之上:从抽屉进的官方插件管理页等原生弹层 z 序高于
|
|
12434
|
+
// 面板默认的 200,功能坞开在下面会被盖住。抽屉展开时从侧栏 rail 点功能坞图标进入。
|
|
12435
|
+
'[class*="dockm-backdrop"]{z-index:2000 !important}',
|
|
12436
|
+
"}"
|
|
11812
12437
|
].join("\n");
|
|
11813
12438
|
var feature11 = {
|
|
11814
12439
|
id: "mobile",
|
|
11815
12440
|
name: "\u624B\u673A\u9002\u914D",
|
|
11816
12441
|
order: 170,
|
|
11817
12442
|
accent: "#34d399",
|
|
11818
|
-
description: "\u624B\u673A/\u7A84\u5C4F\u6392\u7248\u4E0E\u89E6\u63A7\u515C\u5E95\
|
|
12443
|
+
description: "\u624B\u673A/\u7A84\u5C4F\u6392\u7248\u4E0E\u89E6\u63A7\u515C\u5E95\uFF1A\u5DE6\u4E0A\u89D2\u6C49\u5821\u83DC\u5355 + \u4FA7\u680F\u62BD\u5C49\u300116px \u8F93\u5165\u9632 iOS \u7F29\u653E\u3001\u56FE\u6807\u6309\u94AE\u89E6\u63A7\u9762\u79EF\u3001\u4EE3\u7801\u5757\u6EDA\u52A8\u3001\u6EDA\u52A8\u515C\u5E95",
|
|
11819
12444
|
defaultEnabled: true,
|
|
11820
12445
|
css: css6,
|
|
11821
12446
|
Overlay: MobileOverlay,
|
|
@@ -11824,7 +12449,7 @@ var feature11 = {
|
|
|
11824
12449
|
};
|
|
11825
12450
|
|
|
11826
12451
|
// src/client.jsx
|
|
11827
|
-
var DOCK_VERSION = "0.
|
|
12452
|
+
var DOCK_VERSION = "0.15.0";
|
|
11828
12453
|
var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6, feature7, feature8, feature9, feature10, feature11];
|
|
11829
12454
|
var PLANNED_FEATURES = [];
|
|
11830
12455
|
var PLANNED_NOTES = {};
|