dsh-dock 0.4.1 → 0.6.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 +98 -11
- package/client.js +2124 -243
- package/features/animation/host.js +642 -0
- package/features/animation/view.jsx +1631 -0
- package/features/balance/view.js +66 -41
- package/features/modelconfig/view.js +62 -18
- package/features/theme/view.js +35 -10
- package/features/tokenlog/view.jsx +3 -1
- package/features/visionproxy/host.js +24 -10
- package/index.js +5 -9
- package/package.json +2 -2
- package/screenshots/dock-animation.png +0 -0
- package/screenshots/dock-robot.png +0 -0
- package/src/client.jsx +130 -62
- package/src/host-core.js +31 -1
- package/src/shared.js +24 -3
package/client.js
CHANGED
|
@@ -41,7 +41,7 @@ __export(client_exports, {
|
|
|
41
41
|
inject: () => inject
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(client_exports);
|
|
44
|
-
var
|
|
44
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
45
45
|
|
|
46
46
|
// src/shared.js
|
|
47
47
|
var import_react = __toESM(require("react"), 1);
|
|
@@ -70,9 +70,29 @@ var stateListeners = /* @__PURE__ */ new Set();
|
|
|
70
70
|
function notifyState() {
|
|
71
71
|
for (const fn of stateListeners) fn();
|
|
72
72
|
}
|
|
73
|
+
var FEATURE_STORE_KEY = "dsh-dock/features/v1";
|
|
74
|
+
var featurePersist = { map: {} };
|
|
75
|
+
try {
|
|
76
|
+
if (typeof localStorage !== "undefined") {
|
|
77
|
+
const raw = localStorage.getItem(FEATURE_STORE_KEY);
|
|
78
|
+
const obj = raw ? JSON.parse(raw) : null;
|
|
79
|
+
if (obj && typeof obj === "object") featurePersist.map = obj;
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
function persistFeatureEnabled() {
|
|
84
|
+
try {
|
|
85
|
+
if (typeof localStorage !== "undefined") localStorage.setItem(FEATURE_STORE_KEY, JSON.stringify(featurePersist.map));
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
}
|
|
73
89
|
function initFeatureState(defs) {
|
|
74
90
|
for (const f of defs) {
|
|
75
|
-
if (
|
|
91
|
+
if (featureState.has(f.id)) continue;
|
|
92
|
+
let enabled = !f.planned && f.defaultEnabled !== false;
|
|
93
|
+
const saved = featurePersist.map[f.id];
|
|
94
|
+
if (typeof saved === "boolean") enabled = saved;
|
|
95
|
+
featureState.set(f.id, { enabled, error: null });
|
|
76
96
|
}
|
|
77
97
|
}
|
|
78
98
|
function stateOf(id) {
|
|
@@ -86,6 +106,8 @@ function stateOf(id) {
|
|
|
86
106
|
function toggleFeature(id) {
|
|
87
107
|
const st = stateOf(id);
|
|
88
108
|
st.enabled = !st.enabled;
|
|
109
|
+
featurePersist.map[id] = st.enabled;
|
|
110
|
+
persistFeatureEnabled();
|
|
89
111
|
notifyState();
|
|
90
112
|
}
|
|
91
113
|
function subscribeFeatureState(fn) {
|
|
@@ -700,7 +722,7 @@ function TokenLogChip(props) {
|
|
|
700
722
|
}, [sid]);
|
|
701
723
|
if (!sid) return null;
|
|
702
724
|
const t = snap.totals;
|
|
703
|
-
const label = snap.err && !t ? snap.err.includes("\u91CD\u542F") ? "\u7528\u91CF\xB7\u9700\u91CD\u542F\u5BBF\u4E3B" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 " +
|
|
725
|
+
const label = snap.err && !t ? snap.err.includes("\u91CD\u542F") ? "\u7528\u91CF\xB7\u9700\u91CD\u542F\u5BBF\u4E3B" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 $" + t.cost.toFixed(2) : "") : "\u26C1 \u2026";
|
|
704
726
|
const title = t ? "\u672C\u4F1A\u8BDD " + fmtNum(t.calls) + " \u6B21\u8C03\u7528 \xB7 " + fmtNum(t.totalTokens) + " Token \xB7 " + fmtCost(t.cost) + "\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";
|
|
705
727
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
706
728
|
"button",
|
|
@@ -746,8 +768,8 @@ var modelsStore = {
|
|
|
746
768
|
},
|
|
747
769
|
load() {
|
|
748
770
|
if (this.snap.loading) return;
|
|
749
|
-
this.set({ loading: true });
|
|
750
|
-
fetch("/dsh-dock/models", { 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) }));
|
|
771
|
+
this.set({ loading: true, error: null });
|
|
772
|
+
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) }));
|
|
751
773
|
}
|
|
752
774
|
};
|
|
753
775
|
function useModels() {
|
|
@@ -804,6 +826,14 @@ function ModelsView() {
|
|
|
804
826
|
const [vpDirty, setVpDirty] = import_react3.default.useState(false);
|
|
805
827
|
const [vpSaving, setVpSaving] = import_react3.default.useState(false);
|
|
806
828
|
const [vpMsg, setVpMsg] = import_react3.default.useState(null);
|
|
829
|
+
const [vpDirectExpanded, setVpDirectExpanded] = import_react3.default.useState(false);
|
|
830
|
+
import_react3.default.useEffect(() => {
|
|
831
|
+
modelsStore.load();
|
|
832
|
+
}, []);
|
|
833
|
+
const refreshModels = () => {
|
|
834
|
+
setBuiltKey(null);
|
|
835
|
+
modelsStore.load();
|
|
836
|
+
};
|
|
807
837
|
const cur = providers.length > 0 ? providers.find((p) => p.id === selId) || providers[0] : null;
|
|
808
838
|
const wantKey = cur ? cur.id + ":" + String(data && data.generatedAt || 0) : null;
|
|
809
839
|
if (cur && builtKey !== wantKey) {
|
|
@@ -922,7 +952,7 @@ function ModelsView() {
|
|
|
922
952
|
{
|
|
923
953
|
key: v,
|
|
924
954
|
className: "dkm-check",
|
|
925
|
-
title: v === "image" ? "\
|
|
955
|
+
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
|
|
926
956
|
},
|
|
927
957
|
import_react3.default.createElement("input", {
|
|
928
958
|
type: "checkbox",
|
|
@@ -985,6 +1015,14 @@ function ModelsView() {
|
|
|
985
1015
|
)
|
|
986
1016
|
);
|
|
987
1017
|
const body = [];
|
|
1018
|
+
if (data) {
|
|
1019
|
+
body.push(import_react3.default.createElement(
|
|
1020
|
+
"div",
|
|
1021
|
+
{ key: "refresh", className: "dkm-topbar" },
|
|
1022
|
+
import_react3.default.createElement("span", { className: "dkm-sub" }, "\u5DF2\u8F7D\u5165 " + providers.length + " \u4E2A Provider\uFF1B\u5728 DSH \u539F\u751F\u6A21\u578B\u8BBE\u7F6E\u4E2D\u65B0\u589E\u540E\uFF0C\u8FD4\u56DE\u672C\u9875\u4F1A\u81EA\u52A8\u66F4\u65B0"),
|
|
1023
|
+
import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: snap.loading || saving, onClick: refreshModels }, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0\u6A21\u578B\u76EE\u5F55")
|
|
1024
|
+
));
|
|
1025
|
+
}
|
|
988
1026
|
if (snap.error) {
|
|
989
1027
|
body.push(import_react3.default.createElement(
|
|
990
1028
|
"div",
|
|
@@ -1003,13 +1041,23 @@ function ModelsView() {
|
|
|
1003
1041
|
));
|
|
1004
1042
|
}
|
|
1005
1043
|
if (data && data.visionProxy !== void 0 && vpDraft) {
|
|
1006
|
-
const
|
|
1044
|
+
const runtimeImage = (m) => Array.isArray(m.runtimeInput) && m.runtimeInput.indexOf("image") >= 0;
|
|
1045
|
+
const declaredImage = (m) => Array.isArray(m.input) && m.input.indexOf("image") >= 0;
|
|
1007
1046
|
const vpDirect = [];
|
|
1008
1047
|
const vpProxied = [];
|
|
1009
1048
|
for (const p of providers) {
|
|
1010
1049
|
for (const m of p.models || []) {
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1050
|
+
const declared = declaredImage(m);
|
|
1051
|
+
const runtime = runtimeImage(m);
|
|
1052
|
+
const source = declared ? "\u4F60\u5DF2\u6807\u8BB0\u56FE\u7247" : runtime ? "\u8FD0\u884C\u65F6\u8BC6\u522B" : "\u672A\u6807\u8BB0\u56FE\u7247";
|
|
1053
|
+
const item = {
|
|
1054
|
+
key: p.id + "/" + m.id,
|
|
1055
|
+
label: (p.displayName || p.id) + " / " + (m.name || m.id) + "\uFF08" + source + "\uFF09",
|
|
1056
|
+
model: m.name || m.id,
|
|
1057
|
+
source,
|
|
1058
|
+
declared
|
|
1059
|
+
};
|
|
1060
|
+
(declared || runtime ? vpDirect : vpProxied).push(item);
|
|
1013
1061
|
}
|
|
1014
1062
|
}
|
|
1015
1063
|
const vpCandidates = vpDirect.slice();
|
|
@@ -1025,6 +1073,11 @@ function ModelsView() {
|
|
|
1025
1073
|
import_react3.default.createElement("span", { className: "dkm-badge" }, vpDraft.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
|
|
1026
1074
|
import_react3.default.createElement("span", { className: "dkm-sub" }, "\u7EAF\u6587\u672C\u6A21\u578B\u6536\u5230\u56FE\u7247\u65F6\u81EA\u52A8\u8C03\u7528\u6240\u9009\u89C6\u89C9\u6A21\u578B\u8BC6\u522B\uFF0C\u8BC6\u522B\u6587\u672C\u66FF\u6362\u56FE\u7247\uFF1B\u591A\u6A21\u6001\u6A21\u578B\u539F\u6837\u81EA\u8BC6\u522B")
|
|
1027
1075
|
),
|
|
1076
|
+
import_react3.default.createElement(
|
|
1077
|
+
"div",
|
|
1078
|
+
{ className: "dkm-note dkm-warn" },
|
|
1079
|
+
"\u26A0 \u672C\u529F\u80FD\u4F1A\u8C03\u7528\u89C6\u89C9\u6A21\u578B\u8BC6\u522B\u56FE\u7247\uFF0C\u6D88\u8017 token\uFF08\u6BCF\u6B21\u8BC6\u56FE\u6309\u89C6\u89C9\u6A21\u578B\u8BA1\u8D39\uFF09\u3002\u9ED8\u8BA4\u5173\u95ED\uFF1B\u4E0D\u5F00\u542F\u5219\u63D2\u4EF6\u5176\u4F59\u529F\u80FD\u5747\u4E0D\u6D88\u8017\u4EFB\u4F55 token\u3002"
|
|
1080
|
+
),
|
|
1028
1081
|
import_react3.default.createElement(
|
|
1029
1082
|
"div",
|
|
1030
1083
|
{ className: "dkm-checks" },
|
|
@@ -1059,23 +1112,37 @@ function ModelsView() {
|
|
|
1059
1112
|
!vpKnown && vpDraft.provider ? import_react3.default.createElement("option", { value: vpKey }, vpDraft.provider + " / " + vpDraft.model + "\uFF08\u5F53\u524D\uFF09") : null,
|
|
1060
1113
|
vpCandidates.map((c) => import_react3.default.createElement("option", { key: c.key, value: c.key }, c.label))
|
|
1061
1114
|
),
|
|
1062
|
-
vpCandidates.length === 0 ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\
|
|
1115
|
+
vpCandidates.length === 0 ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\u8FD8\u6CA1\u6709\u6807\u8BB0\u56FE\u7247\u80FD\u529B\u7684\u6A21\u578B\u2014\u2014\u5728\u4E0B\u65B9\u7ED9\u4F60\u786E\u8BA4\u652F\u6301\u56FE\u7247\u7684\u6A21\u578B\u52FE\u9009\u300C\u56FE\u7247\u300D\u5E76\u4FDD\u5B58") : null
|
|
1063
1116
|
),
|
|
1064
1117
|
import_react3.default.createElement(
|
|
1065
1118
|
"div",
|
|
1066
1119
|
{ className: "dkm-sub" },
|
|
1067
|
-
"\
|
|
1120
|
+
"\u4EE5\u4F60\u5728\u4E0B\u65B9\u52FE\u9009\u7684\u300C\u56FE\u7247\u300D\u4E3A\u51C6\uFF1B\u8FD0\u884C\u65F6\u8BC6\u522B\u53EA\u662F\u8F85\u52A9\u63D0\u793A\u3002\u5B83\u4E0D\u4EE3\u8868\u5DF2\u8054\u7F51\u5B9E\u6D4B\u53EF\u8C03\u7528\uFF0C\u5B9E\u9645\u53EF\u7528\u6027\u4ECD\u53D6\u51B3\u4E8E Provider \u51ED\u636E\u3001\u989D\u5EA6\u4E0E\u4E0A\u6E38\u670D\u52A1\u3002\u82E5\u7AEF\u70B9\u5B9E\u9645\u4E0D\u8BA4\u56FE\uFF0C\u53D6\u6D88\u8BE5\u6A21\u578B\u7684\u300C\u56FE\u7247\u300D\u52FE\u9009\u5373\u53EF\u6062\u590D\u8D70\u56FE\u7247\u7406\u89E3\u4EE3\u7406\u3002"
|
|
1068
1121
|
),
|
|
1069
1122
|
vpDirect.length > 0 ? import_react3.default.createElement(
|
|
1070
1123
|
"div",
|
|
1071
|
-
{ className: "dkm-
|
|
1072
|
-
import_react3.default.createElement(
|
|
1073
|
-
|
|
1124
|
+
{ className: "dkm-capabilities" },
|
|
1125
|
+
import_react3.default.createElement(
|
|
1126
|
+
"div",
|
|
1127
|
+
{ className: "dkm-checks" },
|
|
1128
|
+
import_react3.default.createElement("span", { className: "dkm-label" }, "\u539F\u56FE\u76F4\u53D1\u5019\u9009\uFF08\u4F60\u7684\u6807\u8BB0\u4F18\u5148\uFF0C" + vpDirect.length + "\uFF09\uFF1A"),
|
|
1129
|
+
import_react3.default.createElement("button", {
|
|
1130
|
+
type: "button",
|
|
1131
|
+
className: "dkm-mini",
|
|
1132
|
+
"aria-expanded": vpDirectExpanded,
|
|
1133
|
+
onClick: () => setVpDirectExpanded(!vpDirectExpanded)
|
|
1134
|
+
}, vpDirectExpanded ? "\u6536\u8D77\u5217\u8868" : "\u5C55\u5F00\u5217\u8868")
|
|
1135
|
+
),
|
|
1136
|
+
vpDirectExpanded ? import_react3.default.createElement(
|
|
1137
|
+
"div",
|
|
1138
|
+
{ className: "dkm-checks dkm-capability-list" },
|
|
1139
|
+
vpDirect.map((c) => import_react3.default.createElement("span", { key: c.key, className: "dkm-chip", title: c.key + " \xB7 " + c.source }, c.model))
|
|
1140
|
+
) : null
|
|
1074
1141
|
) : null,
|
|
1075
1142
|
vpProxied.length > 0 ? import_react3.default.createElement(
|
|
1076
1143
|
"div",
|
|
1077
1144
|
{ className: "dkm-checks" },
|
|
1078
|
-
import_react3.default.createElement("span", { className: "dkm-label" }, "\u8D70\u89C6\u89C9\u4EE3\u7406\uFF08\
|
|
1145
|
+
import_react3.default.createElement("span", { className: "dkm-label" }, "\u8D70\u89C6\u89C9\u4EE3\u7406\uFF08\u672A\u6807\u8BB0\u56FE\u7247\uFF0C" + vpProxied.length + "\uFF09\uFF1A"),
|
|
1079
1146
|
import_react3.default.createElement("span", { className: "dkm-sub" }, vpProxied.map((c) => c.model).join("\u3001"))
|
|
1080
1147
|
) : null,
|
|
1081
1148
|
import_react3.default.createElement(
|
|
@@ -1155,10 +1222,7 @@ function ModelsView() {
|
|
|
1155
1222
|
{ className: "dkm-savebar" },
|
|
1156
1223
|
import_react3.default.createElement("span", { className: "dkm-msg" }, dirty ? "\u6709\u672A\u4FDD\u5B58\u7684\u4FEE\u6539" : "\u65E0\u672A\u4FDD\u5B58\u4FEE\u6539"),
|
|
1157
1224
|
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"),
|
|
1158
|
-
import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: saving, onClick:
|
|
1159
|
-
setBuiltKey(null);
|
|
1160
|
-
modelsStore.load();
|
|
1161
|
-
} }, "\u91CD\u65B0\u62C9\u53D6"),
|
|
1225
|
+
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"),
|
|
1162
1226
|
msg ? import_react3.default.createElement("span", { className: "dkm-msg " + (msg.ok ? "ok" : "err") }, msg.text) : null
|
|
1163
1227
|
)
|
|
1164
1228
|
));
|
|
@@ -1182,6 +1246,7 @@ var feature2 = {
|
|
|
1182
1246
|
description: "\u7F16\u8F91\u5404 Provider \u6A21\u578B\u76EE\u5F55\uFF1A\u8F93\u5165\u7C7B\u578B\uFF08\u6587\u672C/\u56FE\u7247 + \u6807\u6CE8\uFF09\u4E0E\u601D\u8003\u5F3A\u5EA6\u6863\u4F4D\uFF1B\u5199\u56DE\u5B98\u65B9\u914D\u7F6E\u70ED\u751F\u6548\uFF0C\u4F1A\u8BDD\u6A21\u578B\u9009\u62E9\u5668\u5373\u65F6\u53EF\u9009",
|
|
1183
1247
|
css: [
|
|
1184
1248
|
".dkm-note{color:var(--dsw-alias-label-secondary);font-size:12px;}",
|
|
1249
|
+
".dkm-warn{color:var(--dsw-alias-state-warning-primary);}",
|
|
1185
1250
|
".dkm-error{color:var(--dsw-alias-state-error-primary);font-size:12px;}",
|
|
1186
1251
|
".dkm-chips{display:flex;flex-wrap:wrap;gap:6px;}",
|
|
1187
1252
|
".dkm-chip{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);border-radius:999px;padding:3px 12px;font-family:inherit;font-size:12px;}",
|
|
@@ -1216,6 +1281,9 @@ var feature2 = {
|
|
|
1216
1281
|
".dkm-msg.ok{color:var(--dsw-alias-state-success-primary);}",
|
|
1217
1282
|
".dkm-msg.err{color:var(--dsw-alias-state-error-primary);}",
|
|
1218
1283
|
".dkm-list{display:flex;flex-direction:column;gap:8px;}",
|
|
1284
|
+
".dkm-topbar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}",
|
|
1285
|
+
".dkm-capabilities{display:flex;flex-direction:column;gap:6px;}",
|
|
1286
|
+
".dkm-capability-list{max-height:168px;overflow:auto;padding:2px 0 2px 2px;}",
|
|
1219
1287
|
".dkm-ro{color:var(--dsw-alias-label-secondary);font-size:12px;}",
|
|
1220
1288
|
".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;}",
|
|
1221
1289
|
".dkm-mini:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary);}",
|
|
@@ -1258,40 +1326,64 @@ var feature3 = {
|
|
|
1258
1326
|
|
|
1259
1327
|
// features/theme/view.js
|
|
1260
1328
|
var import_react5 = __toESM(require("react"), 1);
|
|
1261
|
-
|
|
1329
|
+
var import_react6 = require("react");
|
|
1330
|
+
var PREFERENCE_LABELS = { light: "\u4EAE\u8272", dark: "\u6697\u8272", system: "\u8DDF\u968F\u7CFB\u7EDF" };
|
|
1331
|
+
var THEME_LABELS = { light: "\u4EAE\u8272", dark: "\u6697\u8272" };
|
|
1332
|
+
function readThemeInfo(ctx) {
|
|
1262
1333
|
const theme = ctx && ctx.get ? ctx.get("theme") : void 0;
|
|
1263
|
-
if (theme
|
|
1334
|
+
if (!theme || typeof theme.getTheme !== "function") return { err: "theme \u670D\u52A1\u4E0D\u53EF\u7528" };
|
|
1264
1335
|
let snap = null;
|
|
1265
1336
|
try {
|
|
1266
1337
|
snap = theme.getTheme();
|
|
1267
1338
|
} catch (err) {
|
|
1268
1339
|
return { err: "\u8BFB\u53D6\u5931\u8D25\uFF1A" + String(err && err.message || err) };
|
|
1269
1340
|
}
|
|
1270
|
-
const
|
|
1341
|
+
const preference = snap && typeof snap.preference === "string" ? snap.preference : "";
|
|
1342
|
+
const activeId = snap && snap.active && typeof snap.active.id === "string" ? snap.active.id : "";
|
|
1343
|
+
const label = (PREFERENCE_LABELS[preference] || preference || "\u672A\u77E5") + (activeId && activeId !== preference && THEME_LABELS[activeId] ? "\uFF08\u5B9E\u9645" + THEME_LABELS[activeId] + "\uFF09" : "");
|
|
1271
1344
|
return { label };
|
|
1272
1345
|
}
|
|
1346
|
+
function useThemeInfo(ctx) {
|
|
1347
|
+
const [info, setInfo] = (0, import_react6.useState)(() => readThemeInfo(ctx));
|
|
1348
|
+
(0, import_react6.useEffect)(() => {
|
|
1349
|
+
let off = null;
|
|
1350
|
+
try {
|
|
1351
|
+
if (ctx && typeof ctx.on === "function") {
|
|
1352
|
+
off = ctx.on("theme/change", () => setInfo(readThemeInfo(ctx)));
|
|
1353
|
+
}
|
|
1354
|
+
} catch {
|
|
1355
|
+
}
|
|
1356
|
+
return () => {
|
|
1357
|
+
try {
|
|
1358
|
+
if (typeof off === "function") off();
|
|
1359
|
+
} catch {
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
}, [ctx]);
|
|
1363
|
+
return info;
|
|
1364
|
+
}
|
|
1273
1365
|
function ThemeView(props) {
|
|
1274
|
-
const r =
|
|
1366
|
+
const r = useThemeInfo(props && props.ctx);
|
|
1275
1367
|
if (r.err) return import_react5.default.createElement("div", null, r.err);
|
|
1276
1368
|
return import_react5.default.createElement("div", null, "\u5F53\u524D\u4E3B\u9898\uFF1A" + r.label);
|
|
1277
1369
|
}
|
|
1278
1370
|
function ThemeStat(props) {
|
|
1279
|
-
const r =
|
|
1371
|
+
const r = useThemeInfo(props && props.ctx);
|
|
1280
1372
|
if (r.err) return import_react5.default.createElement("span", null, r.err);
|
|
1281
|
-
return import_react5.default.createElement("span", null, "\
|
|
1373
|
+
return import_react5.default.createElement("span", null, "\u4E3B\u9898\uFF1A" + r.label);
|
|
1282
1374
|
}
|
|
1283
1375
|
var feature4 = {
|
|
1284
1376
|
id: "theme",
|
|
1285
1377
|
name: "\u4E3B\u9898\u4FE1\u606F",
|
|
1286
1378
|
order: 150,
|
|
1287
1379
|
accent: "#a78bfa",
|
|
1288
|
-
description: "\
|
|
1380
|
+
description: "\u8BFB\u53D6\u5F53\u524D\u4E3B\u9898\u5FEB\u7167\uFF1A\u504F\u597D\u4E0E\u5B9E\u9645\u751F\u6548\u4E3B\u9898\uFF08\u7EAF Client\uFF0C\u4E3B\u9898\u5207\u6362\u5B9E\u65F6\u5237\u65B0\uFF09",
|
|
1289
1381
|
View: ThemeView,
|
|
1290
1382
|
HomeStat: ThemeStat
|
|
1291
1383
|
};
|
|
1292
1384
|
|
|
1293
1385
|
// features/balance/view.js
|
|
1294
|
-
var
|
|
1386
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
1295
1387
|
var ACCENT_PALETTE = ["#4d9fff", "#34d399", "#fbbf24", "#a78bfa", "#f472b6", "#38bdf8", "#fb923c", "#4ade80", "#e879f9", "#22d3ee"];
|
|
1296
1388
|
var CURATED_ACCENTS = {
|
|
1297
1389
|
"deepseek-official": "#4d9fff",
|
|
@@ -1302,7 +1394,6 @@ var CURATED_ACCENTS = {
|
|
|
1302
1394
|
anthropic: "#d97757",
|
|
1303
1395
|
"google-gemini": "#4285f4"
|
|
1304
1396
|
};
|
|
1305
|
-
var C_TOTAL = "#34d399";
|
|
1306
1397
|
var C_GRANTED = "#22d3ee";
|
|
1307
1398
|
var C_TOPUP = "#fbbf24";
|
|
1308
1399
|
var C_ERR = "#f87171";
|
|
@@ -1334,8 +1425,8 @@ var balanceStore = {
|
|
|
1334
1425
|
}
|
|
1335
1426
|
};
|
|
1336
1427
|
function useBalance(ctx) {
|
|
1337
|
-
const [snap, setSnap] =
|
|
1338
|
-
|
|
1428
|
+
const [snap, setSnap] = import_react7.default.useState(balanceStore.snap);
|
|
1429
|
+
import_react7.default.useEffect(() => {
|
|
1339
1430
|
const off = balanceStore.subscribe(() => setSnap(balanceStore.snap));
|
|
1340
1431
|
if (!balanceStore.snap.data && !balanceStore.snap.loading) balanceStore.load();
|
|
1341
1432
|
const disposer = ctx && typeof ctx.interval === "function" ? ctx.interval(() => balanceStore.load(), 5 * 60 * 1e3) : null;
|
|
@@ -1349,7 +1440,7 @@ function useBalance(ctx) {
|
|
|
1349
1440
|
function BalanceView(props) {
|
|
1350
1441
|
const snap = useBalance(props && props.ctx);
|
|
1351
1442
|
const load = () => balanceStore.load();
|
|
1352
|
-
|
|
1443
|
+
import_react7.default.useEffect(() => {
|
|
1353
1444
|
const pid = props && props.params && props.params.provider;
|
|
1354
1445
|
if (!pid || typeof document === "undefined") return;
|
|
1355
1446
|
const t = setTimeout(() => {
|
|
@@ -1372,16 +1463,18 @@ function BalanceView(props) {
|
|
|
1372
1463
|
const def = data && data.default ? data.default.provider : null;
|
|
1373
1464
|
const body = [];
|
|
1374
1465
|
if (snap.error) {
|
|
1375
|
-
body.push(
|
|
1466
|
+
body.push(import_react7.default.createElement("div", { key: "err", className: "dkb-note dkb-error" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF1A" + snap.error));
|
|
1376
1467
|
} else if (!data) {
|
|
1377
|
-
body.push(
|
|
1468
|
+
body.push(import_react7.default.createElement("div", { key: "loading", className: "dkb-note" }, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u8FD8\u6CA1\u6709\u6570\u636E\uFF0C\u70B9\u51FB\u4E0B\u65B9\u5237\u65B0"));
|
|
1378
1469
|
} else if (providers.length === 0) {
|
|
1379
|
-
body.push(
|
|
1470
|
+
body.push(import_react7.default.createElement("div", { key: "empty", className: "dkb-note" }, "\u6CA1\u6709\u627E\u5230\u5DF2\u914D\u7F6E\u7684\u6A21\u578B Provider"));
|
|
1380
1471
|
} else {
|
|
1381
|
-
|
|
1472
|
+
const rank = (p) => p.balance && p.balance.status === "ok" ? 0 : p.balance && p.balance.status === "login-required" ? 1 : 2;
|
|
1473
|
+
const sorted = providers.slice().sort((a, b) => rank(a) - rank(b));
|
|
1474
|
+
body.push(import_react7.default.createElement(
|
|
1382
1475
|
"div",
|
|
1383
1476
|
{ key: "rows", className: "dkb-rows" },
|
|
1384
|
-
|
|
1477
|
+
sorted.map((p) => {
|
|
1385
1478
|
const accent = accentOf(p.id);
|
|
1386
1479
|
const b = p.balance;
|
|
1387
1480
|
let badge = ["\u672A\u77E5", ""];
|
|
@@ -1392,66 +1485,92 @@ function BalanceView(props) {
|
|
|
1392
1485
|
else if (b.status === "login-required") badge = ["\u9700\u767B\u5F55", "warn"];
|
|
1393
1486
|
else badge = ["\u67E5\u8BE2\u5931\u8D25", "err"];
|
|
1394
1487
|
}
|
|
1395
|
-
const sub = ["ID: " + p.id, p.api ? "api: " + p.api : null, p.baseURL ? p.baseURL : null].filter(Boolean).join(" \xB7 ");
|
|
1396
|
-
const cells = [];
|
|
1397
1488
|
let balBody = null;
|
|
1398
1489
|
if (b && b.status === "ok" && b.kind === "quota") {
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
import_react6.default.createElement("span", { className: "dkb-part" }, "\u5DF2\u7528 " + fmt(b.used) + " / \u603B " + fmt(b.limit)),
|
|
1405
|
-
b.resetTime ? import_react6.default.createElement("span", { className: "dkb-part" }, "\u91CD\u7F6E " + String(b.resetTime).slice(0, 16)) : null
|
|
1406
|
-
));
|
|
1407
|
-
(Array.isArray(b.dims) ? b.dims : []).forEach((d, i) => {
|
|
1408
|
-
cells.push(import_react6.default.createElement(
|
|
1490
|
+
const dims = Array.isArray(b.dims) ? b.dims : [];
|
|
1491
|
+
balBody = import_react7.default.createElement(
|
|
1492
|
+
import_react7.default.Fragment,
|
|
1493
|
+
null,
|
|
1494
|
+
import_react7.default.createElement(
|
|
1409
1495
|
"div",
|
|
1410
|
-
{
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1496
|
+
{ className: "dkb-main" },
|
|
1497
|
+
import_react7.default.createElement("span", { className: "dkb-main-label" }, "\u5269\u4F59\u989D\u5EA6"),
|
|
1498
|
+
import_react7.default.createElement("span", { className: "dkb-main-value" }, fmt(b.remaining) + (b.unit ? " " + b.unit : "")),
|
|
1499
|
+
import_react7.default.createElement(
|
|
1500
|
+
"span",
|
|
1501
|
+
{ className: "dkb-main-part" },
|
|
1502
|
+
"\u5DF2\u7528 " + fmt(b.used) + " / \u603B " + fmt(b.limit),
|
|
1503
|
+
b.resetTime ? import_react7.default.createElement("span", null, " \xB7 \u91CD\u7F6E " + String(b.resetTime).slice(0, 10)) : null
|
|
1504
|
+
)
|
|
1505
|
+
),
|
|
1506
|
+
dims.map((d, i) => import_react7.default.createElement(
|
|
1507
|
+
"div",
|
|
1508
|
+
{ key: "d" + i, className: "dkb-dim" },
|
|
1509
|
+
import_react7.default.createElement("span", { className: "dkb-dim-label" }, d.window === "weekly" ? "\u5468\u989D\u5EA6" : "\u5C0F\u65F6\u989D\u5EA6"),
|
|
1510
|
+
import_react7.default.createElement(
|
|
1511
|
+
"span",
|
|
1512
|
+
{ className: "dkb-dim-bar" },
|
|
1513
|
+
import_react7.default.createElement("span", { className: "dkb-dim-fill", style: { width: (d.limit > 0 ? Math.min(100, Math.round(d.remaining / d.limit * 100)) : 0) + "%" } })
|
|
1514
|
+
),
|
|
1515
|
+
import_react7.default.createElement("span", { className: "dkb-dim-text" }, "\u5269 " + fmt(d.remaining) + " / " + fmt(d.limit))
|
|
1516
|
+
))
|
|
1517
|
+
);
|
|
1417
1518
|
} else if (b && b.status === "ok") {
|
|
1418
1519
|
const infos = Array.isArray(b.infos) ? b.infos : [];
|
|
1419
|
-
|
|
1520
|
+
balBody = import_react7.default.createElement(
|
|
1420
1521
|
"div",
|
|
1421
|
-
{
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1522
|
+
{ className: "dkb-mains" },
|
|
1523
|
+
infos.map((i, idx) => import_react7.default.createElement(
|
|
1524
|
+
"div",
|
|
1525
|
+
{ key: idx, className: "dkb-main" },
|
|
1526
|
+
import_react7.default.createElement("span", { className: "dkb-main-label", style: { color: accent } }, i.currency),
|
|
1527
|
+
import_react7.default.createElement("span", { className: "dkb-main-value" }, fmt(i.totalBalance)),
|
|
1528
|
+
import_react7.default.createElement(
|
|
1529
|
+
"span",
|
|
1530
|
+
{ className: "dkb-main-parts" },
|
|
1531
|
+
i.grantedBalance != null ? import_react7.default.createElement("span", { className: "dkb-main-part", style: { color: C_GRANTED } }, "\u8D60\u9001 " + fmt(i.grantedBalance)) : null,
|
|
1532
|
+
i.toppedUpBalance != null ? import_react7.default.createElement("span", { className: "dkb-main-part", style: { color: C_TOPUP } }, "\u5145\u503C " + fmt(i.toppedUpBalance)) : null
|
|
1533
|
+
)
|
|
1534
|
+
))
|
|
1535
|
+
);
|
|
1427
1536
|
} else if (b && b.status === "login-required" && b.consoleUrl) {
|
|
1428
|
-
balBody =
|
|
1537
|
+
balBody = import_react7.default.createElement(
|
|
1429
1538
|
"div",
|
|
1430
|
-
{ className: "dkb-
|
|
1431
|
-
|
|
1539
|
+
{ className: "dkb-main" },
|
|
1540
|
+
import_react7.default.createElement("a", { href: b.consoleUrl, target: "_blank", rel: "noreferrer", className: "dkb-link", style: { color: accent } }, "\u53BB\u63A7\u5236\u53F0\u67E5\u770B\u4F59\u989D \u2192")
|
|
1432
1541
|
);
|
|
1433
1542
|
} else {
|
|
1434
|
-
balBody =
|
|
1543
|
+
balBody = b && b.message ? import_react7.default.createElement("div", { className: "dkb-note" }, b.message) : import_react7.default.createElement("div", { className: "dkb-note" }, "\u8BE5 Provider \u6CA1\u6709\u5DF2\u77E5\u7684\u4F59\u989D\u67E5\u8BE2\u63A5\u53E3");
|
|
1435
1544
|
}
|
|
1436
|
-
|
|
1437
|
-
return
|
|
1545
|
+
const sub = ["ID " + p.id, p.api, p.baseURL ? p.baseURL.replace(/^https?:\/\//, "") : null].filter(Boolean).join(" \xB7 ");
|
|
1546
|
+
return import_react7.default.createElement(
|
|
1438
1547
|
"div",
|
|
1439
1548
|
{ key: p.id, className: "dkb-row", "data-dock-provider": p.id },
|
|
1440
|
-
|
|
1549
|
+
import_react7.default.createElement(
|
|
1441
1550
|
"div",
|
|
1442
1551
|
{ className: "dkb-row-head" },
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
def === p.id ?
|
|
1446
|
-
|
|
1552
|
+
import_react7.default.createElement("span", { className: "dkb-dot", style: { background: accent } }),
|
|
1553
|
+
import_react7.default.createElement("span", { className: "dkb-name", style: { color: accent } }, p.displayName),
|
|
1554
|
+
def === p.id ? import_react7.default.createElement("span", { className: "dkb-default" }, "\u9ED8\u8BA4") : null,
|
|
1555
|
+
import_react7.default.createElement("span", { className: "dkb-badge" + (badge[1] ? " " + badge[1] : ""), style: badge[1] === "err" ? { color: C_ERR, borderColor: C_ERR } : null }, badge[0]),
|
|
1556
|
+
// 模型数折叠提示(点开展开 chips)
|
|
1557
|
+
p.models && p.models.length > 0 ? import_react7.default.createElement("button", {
|
|
1558
|
+
type: "button",
|
|
1559
|
+
className: "dkb-models-toggle",
|
|
1560
|
+
title: p.models.join(", "),
|
|
1561
|
+
onClick: (e) => {
|
|
1562
|
+
const row = e.currentTarget.closest(".dkb-row");
|
|
1563
|
+
if (row) row.classList.toggle("dkb-models-open");
|
|
1564
|
+
}
|
|
1565
|
+
}, p.models.length + " \u4E2A\u6A21\u578B \u25BE") : null
|
|
1447
1566
|
),
|
|
1448
|
-
sub ?
|
|
1449
|
-
p.apiKeyEnv ?
|
|
1450
|
-
p.models && p.models.length > 0 ?
|
|
1567
|
+
sub ? import_react7.default.createElement("div", { className: "dkb-sub" }, sub) : null,
|
|
1568
|
+
p.apiKeyEnv ? import_react7.default.createElement("div", { className: "dkb-sub" }, "\u5BC6\u94A5: " + p.apiKeyEnv + (p.credentialConfigured ? " \u2713" : " \u2717")) : null,
|
|
1569
|
+
p.models && p.models.length > 0 ? import_react7.default.createElement(
|
|
1451
1570
|
"div",
|
|
1452
1571
|
{ className: "dkb-chips" },
|
|
1453
|
-
p.models.slice(0, 8).map((m) =>
|
|
1454
|
-
p.models.length > 8 ?
|
|
1572
|
+
p.models.slice(0, 8).map((m) => import_react7.default.createElement("span", { key: m, className: "dkb-chip", style: { border: "1px solid " + accent, color: accent, background: accent + "1a" } }, m)),
|
|
1573
|
+
p.models.length > 8 ? import_react7.default.createElement("span", { key: "more", className: "dkb-chip" }, "+" + (p.models.length - 8)) : null
|
|
1455
1574
|
) : null,
|
|
1456
1575
|
balBody
|
|
1457
1576
|
);
|
|
@@ -1459,20 +1578,20 @@ function BalanceView(props) {
|
|
|
1459
1578
|
));
|
|
1460
1579
|
}
|
|
1461
1580
|
const now = new Date(data && data.generatedAt ? data.generatedAt : Date.now());
|
|
1462
|
-
return
|
|
1581
|
+
return import_react7.default.createElement(
|
|
1463
1582
|
"div",
|
|
1464
1583
|
{ className: "dkb-rows" },
|
|
1465
|
-
|
|
1584
|
+
import_react7.default.createElement(
|
|
1466
1585
|
"div",
|
|
1467
1586
|
{ className: "dkb-note" },
|
|
1468
|
-
data && !snap.error && providers.length > 0 ? okCount + "/" + providers.length + " \u4E2A Provider \u53EF\u67E5\u4F59\u989D" : "\u6A21\u578B\u4F59\u989D \xB7 Host \u534A\u90E8\u5B9E\u65F6\u62C9\u53D6"
|
|
1587
|
+
data && !snap.error && providers.length > 0 ? okCount + "/" + providers.length + " \u4E2A Provider \u53EF\u67E5\u4F59\u989D\uFF08\u53EF\u67E5\u7684\u6392\u524D\u9762\uFF09" : "\u6A21\u578B\u4F59\u989D \xB7 Host \u534A\u90E8\u5B9E\u65F6\u62C9\u53D6"
|
|
1469
1588
|
),
|
|
1470
1589
|
body,
|
|
1471
|
-
|
|
1590
|
+
import_react7.default.createElement(
|
|
1472
1591
|
"div",
|
|
1473
1592
|
{ className: "dkb-foot" },
|
|
1474
|
-
|
|
1475
|
-
|
|
1593
|
+
import_react7.default.createElement("span", null, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u66F4\u65B0\u4E8E " + now.toLocaleTimeString()),
|
|
1594
|
+
import_react7.default.createElement("button", { type: "button", className: "dkb-refresh", onClick: load }, "\u5237\u65B0")
|
|
1476
1595
|
)
|
|
1477
1596
|
);
|
|
1478
1597
|
}
|
|
@@ -1480,14 +1599,14 @@ function BalanceStat(props) {
|
|
|
1480
1599
|
const snap = useBalance(props && props.ctx);
|
|
1481
1600
|
const data = snap.data;
|
|
1482
1601
|
const providers = data && Array.isArray(data.providers) ? data.providers : [];
|
|
1483
|
-
if (snap.error) return
|
|
1484
|
-
if (!data) return
|
|
1602
|
+
if (snap.error) return import_react7.default.createElement("span", { className: "dockm-err" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF08\u70B9\u51FB\u8FDB\u5165\u67E5\u770B\u8BE6\u60C5\uFF09");
|
|
1603
|
+
if (!data) return import_react7.default.createElement("span", null, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u7B49\u5F85\u62C9\u53D6\u4F59\u989D");
|
|
1485
1604
|
const ok = providers.filter((p) => p.balance && p.balance.status === "ok").length;
|
|
1486
|
-
return
|
|
1605
|
+
return import_react7.default.createElement("span", null, providers.length + " \u4E2A Provider \xB7 " + ok + " \u4E2A\u53EF\u67E5\u4F59\u989D");
|
|
1487
1606
|
}
|
|
1488
1607
|
function useCurrentProvider(ctx, sessionId) {
|
|
1489
|
-
const [cur, setCur] =
|
|
1490
|
-
|
|
1608
|
+
const [cur, setCur] = import_react7.default.useState(null);
|
|
1609
|
+
import_react7.default.useEffect(() => {
|
|
1491
1610
|
let alive = true, off = null;
|
|
1492
1611
|
try {
|
|
1493
1612
|
const models = ctx && ctx.get ? ctx.get("modelDirectories") : void 0;
|
|
@@ -1549,7 +1668,7 @@ function BalanceChip(props) {
|
|
|
1549
1668
|
const text = snap.error ? "\u4F59\u989D\xB7\u5931\u8D25" : !data ? snap.loading ? "\u4F59\u989D \u2026" : "\u4F59\u989D \u2014" : cur ? chipBalanceText(cur) : "\u4F59\u989D \u2014";
|
|
1550
1669
|
const selModel = sel && (sel.model || sel.selected && sel.selected.model) || null;
|
|
1551
1670
|
const title = cur ? (cur.displayName || cur.id) + (selModel ? " \xB7 \u5F53\u524D\u6A21\u578B " + selModel : "") + " \xB7 \u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u4F59\u989D\u8BE6\u60C5" : "\u70B9\u51FB\u6253\u5F00\u529F\u80FD\u575E \xB7 \u6A21\u578B\u4F59\u989D";
|
|
1552
|
-
return
|
|
1671
|
+
return import_react7.default.createElement(
|
|
1553
1672
|
"button",
|
|
1554
1673
|
{
|
|
1555
1674
|
type: "button",
|
|
@@ -1558,8 +1677,8 @@ function BalanceChip(props) {
|
|
|
1558
1677
|
"aria-label": "\u6A21\u578B\u4F59\u989D",
|
|
1559
1678
|
onClick: () => openPanel("balance", def ? { provider: def } : null)
|
|
1560
1679
|
},
|
|
1561
|
-
|
|
1562
|
-
|
|
1680
|
+
import_react7.default.createElement("span", { className: "dockchip-dot", style: { background: accent } }),
|
|
1681
|
+
import_react7.default.createElement("span", null, text)
|
|
1563
1682
|
);
|
|
1564
1683
|
}
|
|
1565
1684
|
var feature5 = {
|
|
@@ -1571,8 +1690,9 @@ var feature5 = {
|
|
|
1571
1690
|
css: [
|
|
1572
1691
|
".dkb-note{color:var(--dsw-alias-label-secondary);font-size:12px;}",
|
|
1573
1692
|
".dkb-error{color:var(--dsw-alias-state-error-primary);}",
|
|
1574
|
-
".dkb-rows{display:flex;flex-direction:column;gap:
|
|
1575
|
-
|
|
1693
|
+
".dkb-rows{display:flex;flex-direction:column;gap:10px;}",
|
|
1694
|
+
// Provider 卡片:行距收窄、留白分层
|
|
1695
|
+
".dkb-row{border:1px solid var(--dsw-alias-border-l1);border-radius:10px;padding:10px 14px 12px;display:flex;flex-direction:column;gap:6px;}",
|
|
1576
1696
|
".dkb-row-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}",
|
|
1577
1697
|
".dkb-dot{width:8px;height:8px;border-radius:50%;flex:none;}",
|
|
1578
1698
|
".dkb-name{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary);}",
|
|
@@ -1581,13 +1701,28 @@ var feature5 = {
|
|
|
1581
1701
|
".dkb-badge.ok{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
|
|
1582
1702
|
".dkb-badge.warn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor;}",
|
|
1583
1703
|
".dkb-badge.err{color:var(--dsw-alias-state-error-primary);border-color:currentColor;}",
|
|
1704
|
+
// 模型数折叠开关(点行头右侧"N 个模型 ▾"展开/收起 chips)
|
|
1705
|
+
".dkb-models-toggle{margin-left:auto;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);font-family:inherit;font-size:11px;padding:1px 6px;border-radius:6px;white-space:nowrap;}",
|
|
1706
|
+
".dkb-models-toggle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
1707
|
+
".dkb-row:not(.dkb-models-open) .dkb-chips{display:none;}",
|
|
1708
|
+
'.dkb-row.dkb-models-open .dkb-models-toggle::after{content:"";}',
|
|
1709
|
+
// 连接信息弱化单行(省略 URL 协议头、超出省略号)
|
|
1584
1710
|
".dkb-sub{color:var(--dsw-alias-label-tertiary);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
1585
|
-
".dkb-chips{display:flex;flex-wrap:wrap;gap:4px;}",
|
|
1711
|
+
".dkb-chips{display:flex;flex-wrap:wrap;gap:4px;padding:2px 0 4px;}",
|
|
1586
1712
|
".dkb-chip{font-size:10px;border-radius:6px;padding:1px 6px;}",
|
|
1587
|
-
|
|
1588
|
-
".dkb-
|
|
1589
|
-
".dkb-
|
|
1590
|
-
".dkb-
|
|
1713
|
+
// 余额主数字卡(大号数字 + 小字辅助信息;多币种横排多卡)
|
|
1714
|
+
".dkb-mains{display:flex;gap:12px;flex-wrap:wrap;}",
|
|
1715
|
+
".dkb-main{display:flex;flex-direction:column;gap:2px;padding:8px 12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:150px;}",
|
|
1716
|
+
".dkb-main-label{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
1717
|
+
".dkb-main-value{font-size:20px;font-weight:700;color:var(--dsw-alias-state-success-primary);font-variant-numeric:tabular-nums;line-height:1.2;}",
|
|
1718
|
+
".dkb-main-parts{display:flex;gap:10px;flex-wrap:wrap;}",
|
|
1719
|
+
".dkb-main-part{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
1720
|
+
// 配额维度条(周/小时额度:进度条 + 剩余/总量)
|
|
1721
|
+
".dkb-dim{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--dsw-alias-label-secondary);}",
|
|
1722
|
+
".dkb-dim-label{flex:none;min-width:44px;color:var(--dsw-alias-label-tertiary);}",
|
|
1723
|
+
".dkb-dim-bar{flex:1;max-width:220px;height:5px;border-radius:3px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);overflow:hidden;}",
|
|
1724
|
+
".dkb-dim-fill{display:block;height:100%;border-radius:3px;background:linear-gradient(90deg,var(--dsw-alias-state-success-primary),color-mix(in srgb,var(--dsw-alias-state-success-primary) 60%,#fff));}",
|
|
1725
|
+
".dkb-dim-text{flex:none;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;}",
|
|
1591
1726
|
".dkb-link{font-size:12px;text-decoration:none;}",
|
|
1592
1727
|
".dkb-link:hover{text-decoration:underline;}",
|
|
1593
1728
|
".dkb-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;color:var(--dsw-alias-label-tertiary);font-size:12px;}",
|
|
@@ -1602,15 +1737,1678 @@ var feature5 = {
|
|
|
1602
1737
|
Chip: BalanceChip
|
|
1603
1738
|
};
|
|
1604
1739
|
|
|
1605
|
-
//
|
|
1606
|
-
var
|
|
1607
|
-
var
|
|
1608
|
-
|
|
1609
|
-
|
|
1740
|
+
// features/animation/view.jsx
|
|
1741
|
+
var import_react8 = require("react");
|
|
1742
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1743
|
+
function rpcCall2(method, args) {
|
|
1744
|
+
return fetch("/dsh-dock/animation/" + method, {
|
|
1745
|
+
method: "POST",
|
|
1746
|
+
headers: { "content-type": "application/json" },
|
|
1747
|
+
body: JSON.stringify(args === void 0 ? {} : args)
|
|
1748
|
+
}).then(async (res) => {
|
|
1749
|
+
const data = await res.json().catch(() => ({}));
|
|
1750
|
+
if (res.ok && data && data.ok === true) return data.data;
|
|
1751
|
+
if (res.status === 405 || res.status === 404) {
|
|
1752
|
+
throw new Error("\u5BBF\u4E3B\u8FDB\u7A0B\u662F\u65E7\u7248\u672C\uFF08\u6CA1\u6709\u4EFB\u52A1\u52A8\u753B\u8DEF\u7531\uFF09\uFF0C\u91CD\u542F dsh web \u540E\u91CD\u8BD5");
|
|
1753
|
+
}
|
|
1754
|
+
if (data && data.ok === false) throw new Error(data.error && data.error.message || "HTTP " + res.status);
|
|
1755
|
+
throw new Error("HTTP " + res.status + (data && data.error && data.error.message ? ": " + data.error.message : ""));
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
var EFFECT_MODES = [
|
|
1759
|
+
{ id: "flow", name: "\u6D41\u5149\u7EC6\u7EBF", desc: "\u9876\u90E8\u7EC6\u7EBF\u6D41\u5149\u5F80\u8FD4\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\u52A0\u5FEB" },
|
|
1760
|
+
{ id: "breathe", name: "\u547C\u5438\u5149\u70B9", desc: "\u9192\u76EE\u547C\u5438\u5149\u70B9\u5E26\u6269\u6563\u5149\u6655\uFF1A\u989C\u8272\u968F\u4EFB\u52A1\u9636\u6BB5\uFF08\u601D\u8003\u84DD/\u8F93\u51FA\u7EFF/\u4EE3\u7801\u6A59/\u67E5\u8D44\u6599\u9752\uFF09\uFF0C\u547C\u5438\u968F\u541E\u5410\u52A0\u5FEB" },
|
|
1761
|
+
{ id: "ring", name: "\u8F68\u9053\u5149\u73AF", desc: "\u7EC6\u73AF\u7ED5\u5706\u70B9\u65CB\u8F6C\uFF0C\u8F6C\u901F\u968F\u4EFB\u52A1\u901F\u5EA6" },
|
|
1762
|
+
{ id: "orbit", name: "\u73AF\u5C4F\u5DE1\u822A", desc: "\u4E00\u9897\u5149\u70B9\u6CBF\u5C4F\u5E55\u8FB9\u7F18\u5DE1\u822A\u6574\u5708\uFF0C\u9192\u76EE\u4E0D\u906E\u6321" },
|
|
1763
|
+
{ id: "robot", name: "\u684C\u9762\u4F19\u4F34", desc: "\u771F\u4EBA\u5316\u53CC\u5DE5\u4F4D\uFF1A\u67E5\u8D44\u6599\u770B\u5DE6\u5C4F\u3001\u5199\u5165/\u6539\u4EE3\u7801\u79FB\u5230\u53F3\u5C4F\uFF1B\u5EA7\u6905\u548C\u8F6C\u5934\u968F\u5B9E\u65F6\u4EFB\u52A1\u8282\u594F\u52A0\u901F" },
|
|
1764
|
+
{ id: "matrix", name: "\u4EE3\u7801\u96E8", desc: "\u5B57\u7B26\u6CBF\u5C4F\u5E55\u7F13\u843D\u5982\u6570\u636E\u6D41\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\uFF0C\u514B\u5236\u7684\u4F4E\u900F\u660E\u5EA6" },
|
|
1765
|
+
{ id: "stars", name: "\u661F\u91CE", desc: "\u7EC6\u788E\u661F\u70B9\u7F13\u6162\u98D8\u79FB\u95EA\u70C1\uFF0C\u5B89\u9759\u8010\u770B\u7684\u80CC\u666F\u6C1B\u56F4" },
|
|
1766
|
+
{ id: "aurora", name: "\u6781\u5149", desc: "\u5C4F\u5E55\u9876\u90E8\u67D4\u5149\u5E26\u7F13\u6162\u547C\u5438\u6D41\u52A8\uFF0C\u50CF\u6781\u5149\u62C2\u8FC7" }
|
|
1610
1767
|
];
|
|
1611
|
-
var
|
|
1612
|
-
|
|
1768
|
+
var PHASE_LABELS = { think: "\u601D\u8003\u4E2D", write: "\u8F93\u51FA\u4E2D", code: "\u7F16\u5199\u4EE3\u7801", search: "\u67E5\u8D44\u6599" };
|
|
1769
|
+
function phaseLabel(p) {
|
|
1770
|
+
return PHASE_LABELS[p] || "\u5DE5\u4F5C\u4E2D";
|
|
1771
|
+
}
|
|
1772
|
+
var PHASE_COLORS = { think: "#60a5fa", write: "#34d399", code: "#fbbf24", search: "#2dd4bf" };
|
|
1773
|
+
function phaseColor(p) {
|
|
1774
|
+
return PHASE_COLORS[p] || "#4d9fff";
|
|
1775
|
+
}
|
|
1776
|
+
var END_LABELS = {
|
|
1777
|
+
completed: { label: "\u5B8C\u6210", cls: "ok" },
|
|
1778
|
+
error: { label: "\u51FA\u9519", cls: "err" },
|
|
1779
|
+
aborted: { label: "\u5DF2\u4E2D\u6B62", cls: "warn" },
|
|
1780
|
+
blocked: { label: "\u53D7\u963B", cls: "warn" },
|
|
1781
|
+
"max-tokens": { label: "\u8FBE\u8F93\u51FA\u4E0A\u9650", cls: "warn" },
|
|
1782
|
+
interrupted: { label: "\u4E2D\u65AD", cls: "warn" }
|
|
1613
1783
|
};
|
|
1784
|
+
function endInfo(reason) {
|
|
1785
|
+
return END_LABELS[reason] || END_LABELS.completed;
|
|
1786
|
+
}
|
|
1787
|
+
function isSuccessReason(reason) {
|
|
1788
|
+
return !reason || reason === "completed";
|
|
1789
|
+
}
|
|
1790
|
+
function fmtNum2(n) {
|
|
1791
|
+
return (Number(n) || 0).toLocaleString("en-US");
|
|
1792
|
+
}
|
|
1793
|
+
function fmtCompact2(n) {
|
|
1794
|
+
n = Number(n) || 0;
|
|
1795
|
+
if (n >= 1e6) return (n / 1e6).toFixed(2) + "M";
|
|
1796
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "K";
|
|
1797
|
+
return String(Math.round(n));
|
|
1798
|
+
}
|
|
1799
|
+
function fmtDur(ms) {
|
|
1800
|
+
const s = Math.max(0, Math.round((ms || 0) / 1e3));
|
|
1801
|
+
const h = Math.floor(s / 3600), m = Math.floor(s % 3600 / 60), sec = s % 60;
|
|
1802
|
+
if (h > 0) return h + "\u5C0F\u65F6" + m + "\u5206" + sec + "\u79D2";
|
|
1803
|
+
if (m > 0) return m + "\u5206" + sec + "\u79D2";
|
|
1804
|
+
return sec + "\u79D2";
|
|
1805
|
+
}
|
|
1806
|
+
function fmtClock(ms) {
|
|
1807
|
+
const s = Math.max(0, Math.floor((ms || 0) / 1e3));
|
|
1808
|
+
const h = Math.floor(s / 3600), m = Math.floor(s % 3600 / 60), sec = s % 60;
|
|
1809
|
+
const p = (x) => String(x).padStart(2, "0");
|
|
1810
|
+
return h > 0 ? h + ":" + p(m) + ":" + p(sec) : p(m) + ":" + p(sec);
|
|
1811
|
+
}
|
|
1812
|
+
function fmtTime2(ts) {
|
|
1813
|
+
if (!ts) return "";
|
|
1814
|
+
const d = new Date(ts);
|
|
1815
|
+
const p = (x) => String(x).padStart(2, "0");
|
|
1816
|
+
return p(d.getHours()) + ":" + p(d.getMinutes()) + ":" + p(d.getSeconds());
|
|
1817
|
+
}
|
|
1818
|
+
function truncate(str, max) {
|
|
1819
|
+
if (!str) return "";
|
|
1820
|
+
return String(str).length > max ? String(str).slice(0, max) + "\u2026" : str;
|
|
1821
|
+
}
|
|
1822
|
+
var animationStore = {
|
|
1823
|
+
snap: { status: null, loading: false, error: null },
|
|
1824
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
1825
|
+
subscribe(fn) {
|
|
1826
|
+
this.listeners.add(fn);
|
|
1827
|
+
return () => {
|
|
1828
|
+
this.listeners.delete(fn);
|
|
1829
|
+
};
|
|
1830
|
+
},
|
|
1831
|
+
emit() {
|
|
1832
|
+
for (const fn of this.listeners) fn();
|
|
1833
|
+
},
|
|
1834
|
+
applyConfig(cfg) {
|
|
1835
|
+
if (this.snap.status) {
|
|
1836
|
+
this.snap = Object.assign({}, this.snap, { status: Object.assign({}, this.snap.status, { config: cfg }) });
|
|
1837
|
+
this.emit();
|
|
1838
|
+
}
|
|
1839
|
+
},
|
|
1840
|
+
refresh() {
|
|
1841
|
+
if (this.snap.loading) return Promise.resolve();
|
|
1842
|
+
this.snap = Object.assign({}, this.snap, { loading: true });
|
|
1843
|
+
this.emit();
|
|
1844
|
+
return rpcCall2("status").then((data) => {
|
|
1845
|
+
this.snap = { status: data, loading: false, error: null };
|
|
1846
|
+
this.emit();
|
|
1847
|
+
}).catch((e) => {
|
|
1848
|
+
this.snap = Object.assign({}, this.snap, { loading: false, error: e && e.message || String(e) });
|
|
1849
|
+
this.emit();
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
};
|
|
1853
|
+
function useAnimation() {
|
|
1854
|
+
const [snap, setSnap] = (0, import_react8.useState)(animationStore.snap);
|
|
1855
|
+
(0, import_react8.useEffect)(() => animationStore.subscribe(() => setSnap(animationStore.snap)), []);
|
|
1856
|
+
return snap;
|
|
1857
|
+
}
|
|
1858
|
+
function useTicker(ctx, active) {
|
|
1859
|
+
const [, bump] = (0, import_react8.useState)(0);
|
|
1860
|
+
(0, import_react8.useEffect)(() => {
|
|
1861
|
+
if (!active) return;
|
|
1862
|
+
if (ctx && typeof ctx.interval === "function") return ctx.interval(bump, 1e3);
|
|
1863
|
+
const t = setInterval(bump, 1e3);
|
|
1864
|
+
return () => clearInterval(t);
|
|
1865
|
+
}, [active]);
|
|
1866
|
+
}
|
|
1867
|
+
function Box3(props) {
|
|
1868
|
+
const w = props.w, h = props.h, d = props.d;
|
|
1869
|
+
const faces = [
|
|
1870
|
+
[w, h, "translate(-50%,-50%) translateZ(" + d / 2 + "px)"],
|
|
1871
|
+
[w, h, "translate(-50%,-50%) rotateY(180deg) translateZ(" + d / 2 + "px)"],
|
|
1872
|
+
[d, h, "translate(-50%,-50%) rotateY(90deg) translateZ(" + w / 2 + "px)"],
|
|
1873
|
+
[d, h, "translate(-50%,-50%) rotateY(-90deg) translateZ(" + w / 2 + "px)"],
|
|
1874
|
+
[w, d, "translate(-50%,-50%) rotateX(90deg) translateZ(" + h / 2 + "px)"],
|
|
1875
|
+
[w, d, "translate(-50%,-50%) rotateX(-90deg) translateZ(" + h / 2 + "px)"]
|
|
1876
|
+
];
|
|
1877
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1878
|
+
"span",
|
|
1879
|
+
{
|
|
1880
|
+
className: "dk3-box " + (props.cls || ""),
|
|
1881
|
+
style: Object.assign(
|
|
1882
|
+
{ width: w, height: h, left: props.x - w / 2, top: props.y - h / 2 },
|
|
1883
|
+
props.z ? { transform: "translateZ(" + props.z + "px)" } : null,
|
|
1884
|
+
props.style
|
|
1885
|
+
),
|
|
1886
|
+
children: [
|
|
1887
|
+
faces.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-face", style: { width: f[0], height: f[1], transform: f[2] } }, i)),
|
|
1888
|
+
props.children
|
|
1889
|
+
]
|
|
1890
|
+
}
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1893
|
+
function Monitor3(props) {
|
|
1894
|
+
const w = props.w, h = props.h;
|
|
1895
|
+
const searchScreen = props.mode === "search";
|
|
1896
|
+
const lines = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
|
|
1897
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1898
|
+
"span",
|
|
1899
|
+
{
|
|
1900
|
+
className: "dk3-mon3 " + (props.cls || ""),
|
|
1901
|
+
style: { left: props.x - w / 2, top: props.y - h / 2, width: w, height: h, transform: "translateZ(" + (props.z || -3) + "px) rotateY(" + (props.ry || 0) + "deg)" },
|
|
1902
|
+
children: [
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w, h, d: 5, cls: "dk3-frame", x: w / 2, y: h / 2 }),
|
|
1904
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-screen", style: { width: w - 4, height: h - 4, transform: "translate(-50%,-50%) translateZ(3.1px)" }, children: searchScreen ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-search-ui", children: [
|
|
1905
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-search-box", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", {}) }),
|
|
1906
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-search-results", children: lines.slice(0, 6).map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}, i)) })
|
|
1907
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-code", children: [
|
|
1908
|
+
lines.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}, i)),
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-cur" })
|
|
1910
|
+
] }) })
|
|
1911
|
+
]
|
|
1912
|
+
}
|
|
1913
|
+
);
|
|
1914
|
+
}
|
|
1915
|
+
function RobotScene(props) {
|
|
1916
|
+
const phase = props && props.phase ? props.phase : "code";
|
|
1917
|
+
const tasks = Array.isArray(props && props.tasks) ? props.tasks : null;
|
|
1918
|
+
const n = tasks ? Math.max(1, Math.min(3, tasks.length)) : 1;
|
|
1919
|
+
const station = phase === "search" ? "left" : phase === "write" || phase === "code" ? "right" : "center";
|
|
1920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-bot-scene", "data-phase": phase, "data-station": station, "data-tasks": tasks ? String(n) : void 0, "aria-hidden": "true", children: [
|
|
1921
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-world", children: [
|
|
1922
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 134, h: 7, d: 38, cls: "dk3-desk", x: 145, y: 76 }),
|
|
1923
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 24, d: 30, cls: "dk3-metal dk3-leg", x: 84, y: 89 }),
|
|
1924
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 24, d: 30, cls: "dk3-metal dk3-leg", x: 206, y: 89 }),
|
|
1925
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 34, h: 24, x: 140, y: 59, ry: 20, cls: "left", mode: "search" }),
|
|
1926
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 42, h: 30, x: 180, y: 57, ry: -16, cls: "right" }),
|
|
1927
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 28, h: 18, x: 160, y: 31, ry: 0, cls: "top" }),
|
|
1928
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 130, y: 71, z: 14 }),
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 2.5, d: 6, cls: "dk3-metal dk3-mouse3", x: 141, y: 71, z: 14 }),
|
|
1930
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 5, d: 4, cls: "dk3-mug", x: 154, y: 69, z: 14 }),
|
|
1931
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 170, y: 71, z: 14 }),
|
|
1932
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 2.5, d: 6, cls: "dk3-metal dk3-mouse3", x: 181, y: 71, z: 14 }),
|
|
1933
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-person", children: [
|
|
1934
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 20, d: 20, cls: "dk3-chairback", x: 2, y: 47 }),
|
|
1935
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 18, h: 4, d: 20, cls: "dk3-chairseat", x: 12, y: 59 }),
|
|
1936
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 9, d: 3, cls: "dk3-metal", x: 12, y: 66 }),
|
|
1937
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 13, h: 2, d: 13, cls: "dk3-metal", x: 12, y: 71 }),
|
|
1938
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 3, d: 3, cls: "dk3-wheel", x: 6, y: 74 }),
|
|
1939
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 3, d: 3, cls: "dk3-wheel", x: 18, y: 74 }),
|
|
1940
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 5, d: 9, cls: "dk3-pants", x: 20, y: 54 }),
|
|
1941
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 10, d: 4, cls: "dk3-pants", x: 26, y: 62 }),
|
|
1942
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 6, h: 3, d: 5, cls: "dk3-shoe", x: 28, y: 70 }),
|
|
1943
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-upper3", children: [
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 18, h: 5, d: 12, cls: "dk3-hood dk3-shoulders3", x: 13, y: 30 }),
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 15, h: 14, d: 11, cls: "dk3-hood dk3-torso dk3-chest3", x: 12, y: 38 }),
|
|
1946
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 7, d: 10, cls: "dk3-hood dk3-torso dk3-waist3", x: 12, y: 47 }),
|
|
1947
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 8, d: 9, cls: "dk3-hood dk3-hoodbump", x: 5, y: 32 }),
|
|
1948
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 7, d: 5, cls: "dk3-skin dk3-neck3", x: 14, y: 24 }),
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 8, h: 3, d: 8, cls: "dk3-collar3", x: 14, y: 28 }),
|
|
1950
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-head3", children: [
|
|
1951
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box3, { w: 12, h: 11, d: 11, cls: "dk3-skin dk3-cranium", x: 8, y: 8, children: [
|
|
1952
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-brows", style: { width: 9, height: 4, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(5.8px)" }, children: [
|
|
1953
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1954
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1955
|
+
] }),
|
|
1956
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-eyes", style: { width: 9, height: 6, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(5.7px)" }, children: [
|
|
1957
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1958
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1959
|
+
] }),
|
|
1960
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-nose", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.1px)" } })
|
|
1961
|
+
] }),
|
|
1962
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 9, h: 7, d: 9, cls: "dk3-skin dk3-jaw3", x: 8.5, y: 14, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-mouth", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(4.7px)" } }) }),
|
|
1963
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 5, d: 12, cls: "dk3-hair dk3-hair-crown", x: 8, y: 3.5 }),
|
|
1964
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 8, d: 11, cls: "dk3-hair dk3-hair-back", x: 3, y: 7.5 }),
|
|
1965
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fringe3", children: [
|
|
1966
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1967
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1968
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1969
|
+
] }),
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-ear" })
|
|
1971
|
+
] }),
|
|
1972
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-near", children: [
|
|
1973
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
|
|
1974
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
|
|
1975
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 10, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 5.5, y: 2 }),
|
|
1976
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-wrist3", children: [
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 2, y: 2 }),
|
|
1978
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fingers3", children: [
|
|
1979
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1980
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1981
|
+
] })
|
|
1982
|
+
] })
|
|
1983
|
+
] })
|
|
1984
|
+
] }),
|
|
1985
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-far", children: [
|
|
1986
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
|
|
1987
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
|
|
1988
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 10, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 5.5, y: 2 }),
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-wrist3", children: [
|
|
1990
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 2, y: 2 }),
|
|
1991
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fingers3", children: [
|
|
1992
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1993
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1994
|
+
] })
|
|
1995
|
+
] })
|
|
1996
|
+
] })
|
|
1997
|
+
] })
|
|
1998
|
+
] })
|
|
1999
|
+
] })
|
|
2000
|
+
] }),
|
|
2001
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-bubble", children: [
|
|
2002
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2003
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2004
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2005
|
+
] })
|
|
2006
|
+
] });
|
|
2007
|
+
}
|
|
2008
|
+
var SOUND_LIBRARY = {
|
|
2009
|
+
chime: { name: "\u6E05\u8106\u53CC\u97F3", notes: { done: [[659.25, 0, 0.14], [880, 0.13, 0.24]], err: [[220, 0, 0.16], [164.81, 0.15, 0.3]] } },
|
|
2010
|
+
ding: { name: "\u53EE", notes: { done: [[987.77, 0, 0.35]], err: [[246.94, 0, 0.4]] } },
|
|
2011
|
+
coin: { name: "\u91D1\u5E01", notes: { done: [[988, 0, 0.08], [1319, 0.08, 0.35], [988, 0, 0.08, "square"], [1319, 0.08, 0.3, "square"]], err: [[196, 0, 0.12], [147, 0.11, 0.35]] } },
|
|
2012
|
+
bell: { name: "\u949F\u58F0", notes: { done: [[523.25, 0, 0.5], [659.25, 0.02, 0.45], [783.99, 0.04, 0.4]], err: [[174.61, 0, 0.5], [130.81, 0.05, 0.5]] } },
|
|
2013
|
+
pulse: { name: "\u8109\u51B2", notes: { done: [[440, 0, 0.09], [440, 0.14, 0.09], [440, 0.28, 0.16]], err: [[174.61, 0, 0.1], [174.61, 0.14, 0.1], [174.61, 0.28, 0.18]] } },
|
|
2014
|
+
arp: { name: "\u7436\u97F3", notes: { done: [[523.25, 0, 0.12], [659.25, 0.09, 0.12], [783.99, 0.18, 0.12], [1046.5, 0.27, 0.3]], err: [[392, 0, 0.12], [329.63, 0.1, 0.12], [261.63, 0.2, 0.12], [196, 0.3, 0.32]] } }
|
|
2015
|
+
};
|
|
2016
|
+
var soundCtx = null;
|
|
2017
|
+
function playTone(seq) {
|
|
2018
|
+
try {
|
|
2019
|
+
if (typeof window === "undefined" || !window.AudioContext && !window.webkitAudioContext) return;
|
|
2020
|
+
const AC = window.AudioContext || window.webkitAudioContext;
|
|
2021
|
+
if (!soundCtx) soundCtx = new AC();
|
|
2022
|
+
if (soundCtx.state === "suspended") {
|
|
2023
|
+
soundCtx.resume().catch(() => {
|
|
2024
|
+
});
|
|
2025
|
+
}
|
|
2026
|
+
const t0 = soundCtx.currentTime;
|
|
2027
|
+
for (const [f, at, dur, wave] of seq) {
|
|
2028
|
+
const osc = soundCtx.createOscillator();
|
|
2029
|
+
const gain = soundCtx.createGain();
|
|
2030
|
+
osc.type = wave || "sine";
|
|
2031
|
+
osc.frequency.value = f;
|
|
2032
|
+
gain.gain.setValueAtTime(0, t0 + at);
|
|
2033
|
+
gain.gain.linearRampToValueAtTime(0.18, t0 + at + 0.015);
|
|
2034
|
+
gain.gain.exponentialRampToValueAtTime(1e-4, t0 + at + dur);
|
|
2035
|
+
osc.connect(gain).connect(soundCtx.destination);
|
|
2036
|
+
osc.start(t0 + at);
|
|
2037
|
+
osc.stop(t0 + at + dur + 0.05);
|
|
2038
|
+
}
|
|
2039
|
+
} catch {
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
function playDoneSound(success, effect) {
|
|
2043
|
+
const lib = SOUND_LIBRARY[effect] || SOUND_LIBRARY.chime;
|
|
2044
|
+
playTone(success ? lib.notes.done : lib.notes.err);
|
|
2045
|
+
}
|
|
2046
|
+
function previewSound(effect) {
|
|
2047
|
+
const lib = SOUND_LIBRARY[effect] || SOUND_LIBRARY.chime;
|
|
2048
|
+
playTone(lib.notes.done);
|
|
2049
|
+
const delayed = lib.notes.err.map(([f, at, dur, wave]) => [f, at + 0.55, dur, wave]);
|
|
2050
|
+
playTone(delayed);
|
|
2051
|
+
}
|
|
2052
|
+
function Toast(props) {
|
|
2053
|
+
const t = props.t;
|
|
2054
|
+
const [closing, setClosing] = (0, import_react8.useState)(false);
|
|
2055
|
+
const close = (0, import_react8.useCallback)(() => {
|
|
2056
|
+
if (!closing) setClosing(true);
|
|
2057
|
+
}, [closing]);
|
|
2058
|
+
(0, import_react8.useEffect)(() => {
|
|
2059
|
+
if (!t.stayMs) return;
|
|
2060
|
+
const timer = setTimeout(close, t.stayMs);
|
|
2061
|
+
return () => clearTimeout(timer);
|
|
2062
|
+
}, []);
|
|
2063
|
+
(0, import_react8.useEffect)(() => {
|
|
2064
|
+
if (!closing) return;
|
|
2065
|
+
const timer = setTimeout(() => props.onClose(t.id), 240);
|
|
2066
|
+
return () => clearTimeout(timer);
|
|
2067
|
+
}, [closing]);
|
|
2068
|
+
const markColor = t.kind === "success" ? "var(--dsw-alias-state-success-primary,#34d399)" : t.kind === "error" ? "var(--dsw-alias-state-error-primary,#f87171)" : "var(--dsw-alias-state-warning-primary,#fbbf24)";
|
|
2069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-toast" + (closing ? " out" : ""), children: [
|
|
2070
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-toast-head", children: [
|
|
2071
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-toast-mark", style: { background: markColor } }),
|
|
2072
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-toast-title", title: t.title, children: t.title }),
|
|
2073
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-toast-close", "aria-label": "\u5173\u95ED", onClick: close, children: "\u2715" })
|
|
2074
|
+
] }),
|
|
2075
|
+
t.body ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-toast-body", children: t.body }) : null
|
|
2076
|
+
] });
|
|
2077
|
+
}
|
|
2078
|
+
function makeBits(n, fn) {
|
|
2079
|
+
const arr = [];
|
|
2080
|
+
for (let i = 0; i < n; i++) arr.push(fn(i));
|
|
2081
|
+
return arr;
|
|
2082
|
+
}
|
|
2083
|
+
function BurstLayer(props) {
|
|
2084
|
+
const bursts = props.bursts || [];
|
|
2085
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-fxwrap", "aria-hidden": "true", children: bursts.map((b) => {
|
|
2086
|
+
if (b.type === "plane") {
|
|
2087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-plane", style: { left: b.x, top: b.y }, children: "\u27A4" }, b.id);
|
|
2088
|
+
}
|
|
2089
|
+
if (b.type === "spark") {
|
|
2090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-spark", style: { left: b.x, top: b.y }, children: b.bits.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { style: { "--dx": p.dx + "px", "--dy": p.dy + "px", background: p.c, boxShadow: "0 0 6px " + p.c } }, i)) }, b.id);
|
|
2091
|
+
}
|
|
2092
|
+
if (b.type === "streak") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-streak" }, b.id);
|
|
2093
|
+
if (b.type === "flash") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-flash" }, b.id);
|
|
2094
|
+
if (b.type === "surge") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-surge" }, b.id);
|
|
2095
|
+
if (b.type === "confetti") {
|
|
2096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-confetti", children: b.bits.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { style: { left: p.l + "%", "--dx": p.dx + "px", "--r": p.r + "deg", background: p.c, boxShadow: "0 0 4px " + p.c, animationDelay: p.d + "s" } }, i)) }, b.id);
|
|
2097
|
+
}
|
|
2098
|
+
return null;
|
|
2099
|
+
}) });
|
|
2100
|
+
}
|
|
2101
|
+
var MATRIX_CHARS = "01</>;{}=+*#";
|
|
2102
|
+
function AmbientLayer(props) {
|
|
2103
|
+
const mode = props.mode;
|
|
2104
|
+
const speed = props.speed;
|
|
2105
|
+
const matrix = (0, import_react8.useMemo)(() => makeBits(34, () => ({
|
|
2106
|
+
l: Math.random() * 100,
|
|
2107
|
+
d: 4 + Math.random() * 6,
|
|
2108
|
+
delay: -Math.random() * 8,
|
|
2109
|
+
o: 0.28 + Math.random() * 0.34,
|
|
2110
|
+
s: 11 + Math.round(Math.random() * 4),
|
|
2111
|
+
c: MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)]
|
|
2112
|
+
})), []);
|
|
2113
|
+
const stars = (0, import_react8.useMemo)(() => makeBits(80, () => ({
|
|
2114
|
+
l: Math.random() * 100,
|
|
2115
|
+
t: Math.random() * 100,
|
|
2116
|
+
sz: 1.5 + Math.random() * 2,
|
|
2117
|
+
d: 2 + Math.random() * 4,
|
|
2118
|
+
delay: -Math.random() * 6,
|
|
2119
|
+
dx: (Math.random() - 0.5) * 40,
|
|
2120
|
+
dy: (Math.random() - 0.5) * 24
|
|
2121
|
+
})), []);
|
|
2122
|
+
if (mode === "matrix") {
|
|
2123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-amb dkan-matrix", style: { "--dkan-speed": speed }, "aria-hidden": "true", children: matrix.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { left: p.l + "%", animationDuration: "calc(" + p.d + "s / var(--dkan-speed,1))", animationDelay: p.delay + "s", opacity: p.o, fontSize: p.s }, children: p.c }, i)) });
|
|
2124
|
+
}
|
|
2125
|
+
if (mode === "stars") {
|
|
2126
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-amb dkan-stars", style: { "--dkan-speed": speed }, "aria-hidden": "true", children: [
|
|
2127
|
+
stars.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-star", style: { left: p.l + "%", top: p.t + "%", width: p.sz, height: p.sz, animationDuration: "calc(" + p.d + "s / var(--dkan-speed,1))", animationDelay: p.delay + "s", "--dx": p.dx + "px", "--dy": p.dy + "px" } }, i)),
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-moon" }),
|
|
2129
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-meteor", style: { top: "12%", left: "72%", animationDelay: "0s" } }),
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-meteor", style: { top: "28%", left: "88%", animationDelay: "2.8s" } }),
|
|
2131
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-meteor", style: { top: "6%", left: "42%", animationDelay: "5.6s" } })
|
|
2132
|
+
] });
|
|
2133
|
+
}
|
|
2134
|
+
if (mode === "aurora") {
|
|
2135
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-amb dkan-aurora", style: { "--dkan-speed": speed }, "aria-hidden": "true", children: [
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2137
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2138
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2139
|
+
] });
|
|
2140
|
+
}
|
|
2141
|
+
return null;
|
|
2142
|
+
}
|
|
2143
|
+
function AnimationOverlay(props) {
|
|
2144
|
+
const ctx = props && props.ctx;
|
|
2145
|
+
const snap = useAnimation();
|
|
2146
|
+
const [toasts, setToasts] = (0, import_react8.useState)([]);
|
|
2147
|
+
const [flourish, setFlourish] = (0, import_react8.useState)(null);
|
|
2148
|
+
const [bursts, setBursts] = (0, import_react8.useState)([]);
|
|
2149
|
+
const prevActiveRef = (0, import_react8.useRef)(null);
|
|
2150
|
+
const burstIdRef = (0, import_react8.useRef)(0);
|
|
2151
|
+
const pushBurst = (0, import_react8.useCallback)((type, x, y, bits) => {
|
|
2152
|
+
const id = ++burstIdRef.current;
|
|
2153
|
+
setBursts((prev) => prev.concat([{ id, type, x, y, bits }]).slice(-6));
|
|
2154
|
+
setTimeout(() => setBursts((prev) => prev.filter((b) => b.id !== id)), 2600);
|
|
2155
|
+
}, []);
|
|
2156
|
+
(0, import_react8.useEffect)(() => {
|
|
2157
|
+
if (typeof document === "undefined") return;
|
|
2158
|
+
const onClick = (e) => {
|
|
2159
|
+
const t = e.target;
|
|
2160
|
+
if (!t || !t.closest) return;
|
|
2161
|
+
const sendBtn = t.closest('button[aria-label="Send message"], button[aria-label*="\u53D1\u9001"]');
|
|
2162
|
+
const newSession = t.closest('button[aria-label*="New session"], button[aria-label*="\u65B0\u4F1A\u8BDD"], button[aria-label*="New Session"]');
|
|
2163
|
+
const workspace = t.closest('button[aria-label*="Choose workspace"], button[aria-label*="\u5DE5\u4F5C\u76EE\u5F55"], button[aria-label*="workspace"]');
|
|
2164
|
+
const sessionItem = t.closest('[role="treeitem"]');
|
|
2165
|
+
if (sendBtn) {
|
|
2166
|
+
pushBurst("plane", e.clientX, e.clientY);
|
|
2167
|
+
} else if (newSession) {
|
|
2168
|
+
pushBurst("spark", e.clientX, e.clientY, makeBits(10, () => ({
|
|
2169
|
+
dx: (Math.random() - 0.5) * 70,
|
|
2170
|
+
dy: (Math.random() - 0.5) * 70,
|
|
2171
|
+
c: ["#4d9fff", "#34d399", "#fbbf24", "#f472b6"][Math.floor(Math.random() * 4)]
|
|
2172
|
+
})));
|
|
2173
|
+
} else if (workspace) {
|
|
2174
|
+
pushBurst("flash");
|
|
2175
|
+
} else if (sessionItem) {
|
|
2176
|
+
pushBurst("streak");
|
|
2177
|
+
}
|
|
2178
|
+
};
|
|
2179
|
+
document.addEventListener("click", onClick, true);
|
|
2180
|
+
return () => document.removeEventListener("click", onClick, true);
|
|
2181
|
+
}, [pushBurst]);
|
|
2182
|
+
const taskCountRef = (0, import_react8.useRef)(0);
|
|
2183
|
+
(0, import_react8.useEffect)(() => {
|
|
2184
|
+
const st2 = snap.status;
|
|
2185
|
+
if (!st2 || !st2.active) return;
|
|
2186
|
+
const n = st2.active.length;
|
|
2187
|
+
if (n > taskCountRef.current) pushBurst("surge");
|
|
2188
|
+
taskCountRef.current = n;
|
|
2189
|
+
}, [snap.status, pushBurst]);
|
|
2190
|
+
(0, import_react8.useEffect)(() => {
|
|
2191
|
+
let stopped = false;
|
|
2192
|
+
let timer = null;
|
|
2193
|
+
const loop = async () => {
|
|
2194
|
+
await animationStore.refresh();
|
|
2195
|
+
if (stopped) return;
|
|
2196
|
+
const s = animationStore.snap;
|
|
2197
|
+
timer = setTimeout(loop, s.error ? 15e3 : s.status && s.status.active && s.status.active.length > 0 ? 850 : 6e3);
|
|
2198
|
+
};
|
|
2199
|
+
loop();
|
|
2200
|
+
const onVisible = () => {
|
|
2201
|
+
if (!stopped && typeof document !== "undefined" && document.visibilityState === "visible") animationStore.refresh();
|
|
2202
|
+
};
|
|
2203
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
2204
|
+
return () => {
|
|
2205
|
+
stopped = true;
|
|
2206
|
+
if (timer) clearTimeout(timer);
|
|
2207
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
2208
|
+
};
|
|
2209
|
+
}, []);
|
|
2210
|
+
(0, import_react8.useEffect)(() => {
|
|
2211
|
+
const st2 = snap.status;
|
|
2212
|
+
if (!st2 || !st2.active) return;
|
|
2213
|
+
const prev = prevActiveRef.current;
|
|
2214
|
+
if (prev) {
|
|
2215
|
+
const currIds = new Set(st2.active.map((x) => x.sessionId));
|
|
2216
|
+
for (const task of prev) {
|
|
2217
|
+
if (currIds.has(task.sessionId)) continue;
|
|
2218
|
+
const record = (st2.recent || []).find((r) => r.sessionId === task.sessionId) || null;
|
|
2219
|
+
handleTaskEnd(task, record, st2.config || {});
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
prevActiveRef.current = st2.active.slice();
|
|
2223
|
+
}, [snap.status]);
|
|
2224
|
+
const handleTaskEnd = (task, record, cfg2) => {
|
|
2225
|
+
const reason = record && record.endReason || "";
|
|
2226
|
+
const success = isSuccessReason(reason);
|
|
2227
|
+
const info = endInfo(reason);
|
|
2228
|
+
if (cfg2.animationEnabled) {
|
|
2229
|
+
setFlourish({ key: Date.now(), err: !success });
|
|
2230
|
+
if (success) {
|
|
2231
|
+
pushBurst("confetti", 0, 0, makeBits(18, (i) => ({
|
|
2232
|
+
l: 4 + i / 18 * 92 + Math.random() * 3,
|
|
2233
|
+
dx: (Math.random() - 0.5) * 60,
|
|
2234
|
+
r: Math.random() * 720 - 360,
|
|
2235
|
+
d: Math.random() * 0.35,
|
|
2236
|
+
c: ["#4d9fff", "#34d399", "#fbbf24", "#f472b6", "#a78bfa"][i % 5]
|
|
2237
|
+
})));
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
if (!cfg2.notifyEnabled) return;
|
|
2241
|
+
const wanted = success ? cfg2.notifyOnComplete : cfg2.notifyOnError;
|
|
2242
|
+
if (!wanted) return;
|
|
2243
|
+
const models = record && record.models && record.models.length ? record.models.join(", ") : task.models && task.models.length ? task.models.join(", ") : "\u672A\u77E5\u6A21\u578B";
|
|
2244
|
+
const provider = record && record.provider || task.provider || "";
|
|
2245
|
+
const startTs = record && record.startTime || task.startTime;
|
|
2246
|
+
const endTs = record && record.endTime || Date.now();
|
|
2247
|
+
const lines = [
|
|
2248
|
+
"\u4EFB\u52A1\uFF1A" + (record && record.title || task.title || "(\u65E0\u6807\u9898)"),
|
|
2249
|
+
"\u6A21\u578B\uFF1A" + models + (provider ? "\uFF08" + provider + "\uFF09" : ""),
|
|
2250
|
+
"\u8017\u65F6\uFF1A" + fmtDur(record && record.duration || endTs - startTs) + "\uFF08" + fmtTime2(startTs) + " \u2192 " + fmtTime2(endTs) + "\uFF09",
|
|
2251
|
+
"\u56DE\u5408 " + (record && record.turns || task.turns || 0) + " \xB7 \u6B65\u9AA4 " + (record && record.steps || task.steps || 0) + (record && record.toolCalls || task.toolCalls ? " \xB7 \u5DE5\u5177 " + (record && record.toolCalls || task.toolCalls) + " \u6B21" : ""),
|
|
2252
|
+
"Token\uFF1A\u8F93\u5165 " + fmtNum2(record && record.inputTokens || task.inputTokens) + " / \u8F93\u51FA " + fmtNum2(record && record.outputTokens || task.outputTokens)
|
|
2253
|
+
];
|
|
2254
|
+
if (record && record.lastText) lines.push("\u6458\u8981\uFF1A" + truncate(record.lastText, 140));
|
|
2255
|
+
if (!success && record && record.errorMessage) lines.push("\u9519\u8BEF\uFF1A" + truncate(record.errorMessage, 120));
|
|
2256
|
+
const title = success ? "\u4EFB\u52A1\u5B8C\u6210" : "\u4EFB\u52A1" + info.label;
|
|
2257
|
+
const toast = {
|
|
2258
|
+
id: Date.now() + Math.random(),
|
|
2259
|
+
kind: success ? "success" : info.cls === "err" ? "error" : "warn",
|
|
2260
|
+
title,
|
|
2261
|
+
body: lines.join("\n"),
|
|
2262
|
+
stayMs: typeof cfg2.notifyStayMs === "number" ? cfg2.notifyStayMs : 8e3
|
|
2263
|
+
};
|
|
2264
|
+
setToasts((prev) => prev.concat([toast]).slice(-4));
|
|
2265
|
+
if (cfg2.soundNotify !== false) playDoneSound(success, cfg2.soundEffect);
|
|
2266
|
+
if (cfg2.systemNotify && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
|
|
2267
|
+
try {
|
|
2268
|
+
new Notification("dsh " + title, {
|
|
2269
|
+
body: (record && record.title || task.title || "(\u65E0\u6807\u9898)") + " \xB7 " + fmtDur(record && record.duration || endTs - startTs),
|
|
2270
|
+
tag: "dsh-dock-animation-" + task.sessionId
|
|
2271
|
+
});
|
|
2272
|
+
} catch {
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
};
|
|
2276
|
+
const st = snap.status;
|
|
2277
|
+
const cfg = st && st.config;
|
|
2278
|
+
const active = st && st.active ? st.active : [];
|
|
2279
|
+
const animOn = !!(cfg && cfg.animationEnabled && active.length > 0);
|
|
2280
|
+
const mode = cfg && cfg.effectMode ? cfg.effectMode : "flow";
|
|
2281
|
+
const phase = active.length > 0 ? active.reduce((best, x) => !best || (x.phaseAt || 0) > (best.phaseAt || 0) ? x : best, null).phase : "think";
|
|
2282
|
+
useTicker(ctx, animOn);
|
|
2283
|
+
const now = Date.now();
|
|
2284
|
+
const elapsed = active.length > 0 ? fmtClock(now - Math.min(...active.map((x) => x.startTime || now))) : "";
|
|
2285
|
+
const [panelOpen, setPanelOpen2] = (0, import_react8.useState)(false);
|
|
2286
|
+
(0, import_react8.useEffect)(() => {
|
|
2287
|
+
setPanelOpen2(panelNav.open);
|
|
2288
|
+
return subscribePanel(() => setPanelOpen2(panelNav.open));
|
|
2289
|
+
}, []);
|
|
2290
|
+
const [speed, setSpeed] = (0, import_react8.useState)(1);
|
|
2291
|
+
const speedRef = (0, import_react8.useRef)({ ticks: -1, at: 0 });
|
|
2292
|
+
(0, import_react8.useEffect)(() => {
|
|
2293
|
+
if (!st || active.length === 0) {
|
|
2294
|
+
speedRef.current = { ticks: -1, at: 0 };
|
|
2295
|
+
setSpeed(1);
|
|
2296
|
+
return;
|
|
2297
|
+
}
|
|
2298
|
+
const ticks = active.reduce((a, x) => a + (x.motionTicks || 0), 0);
|
|
2299
|
+
const t = Date.now();
|
|
2300
|
+
const prev = speedRef.current;
|
|
2301
|
+
if (prev.ticks < 0 || t - prev.at < 300) {
|
|
2302
|
+
speedRef.current = { ticks, at: t };
|
|
2303
|
+
return;
|
|
2304
|
+
}
|
|
2305
|
+
const rate = Math.max(0, (ticks - prev.ticks) / ((t - prev.at) / 1e3));
|
|
2306
|
+
const phaseBoost = phase === "write" || phase === "code" ? 0.28 : phase === "search" ? 0.18 : 0;
|
|
2307
|
+
const next = Math.max(0.9, Math.min(4, Number((0.9 + rate / 14 + phaseBoost).toFixed(2))));
|
|
2308
|
+
setSpeed((current) => Math.abs(current - next) < 0.03 ? current : next);
|
|
2309
|
+
speedRef.current = { ticks, at: t };
|
|
2310
|
+
}, [snap.status]);
|
|
2311
|
+
const ambientOn = animOn && !panelOpen;
|
|
2312
|
+
const robotScaleFromConfig = Math.max(0.85, Math.min(2.2, Number(cfg && cfg.robotScale) || 1.35));
|
|
2313
|
+
const speedStyle = { "--dkan-speed": Number(speed).toFixed(2) };
|
|
2314
|
+
const saveRobotScale = (0, import_react8.useCallback)((robotScale) => {
|
|
2315
|
+
rpcCall2("config", { robotScale }).then((d) => animationStore.applyConfig(d && d.config)).catch(() => {
|
|
2316
|
+
});
|
|
2317
|
+
}, []);
|
|
2318
|
+
const [botPos, setBotPos] = (0, import_react8.useState)(null);
|
|
2319
|
+
const botPosRef = (0, import_react8.useRef)(null);
|
|
2320
|
+
const botDragRef = (0, import_react8.useRef)(null);
|
|
2321
|
+
const botResizeRef = (0, import_react8.useRef)(null);
|
|
2322
|
+
const [botScaleDraft, setBotScaleDraft] = (0, import_react8.useState)(null);
|
|
2323
|
+
const botClickBlockRef = (0, import_react8.useRef)(false);
|
|
2324
|
+
(0, import_react8.useEffect)(() => {
|
|
2325
|
+
try {
|
|
2326
|
+
if (typeof localStorage === "undefined") return;
|
|
2327
|
+
const raw = localStorage.getItem("dsh-dock/anim/robot-pos/v1");
|
|
2328
|
+
const p = raw ? JSON.parse(raw) : null;
|
|
2329
|
+
if (p && typeof p.x === "number" && typeof p.y === "number" && typeof window !== "undefined") {
|
|
2330
|
+
const card = document.querySelector(".dkan-botcard");
|
|
2331
|
+
const w = card ? card.offsetWidth : 200, h = card ? card.offsetHeight : 160;
|
|
2332
|
+
const x = Math.min(Math.max(8, p.x), Math.max(8, window.innerWidth - w - 8));
|
|
2333
|
+
const y = Math.min(Math.max(8, p.y), Math.max(8, window.innerHeight - h - 8));
|
|
2334
|
+
botPosRef.current = { x, y };
|
|
2335
|
+
setBotPos({ x, y });
|
|
2336
|
+
}
|
|
2337
|
+
} catch {
|
|
2338
|
+
}
|
|
2339
|
+
}, []);
|
|
2340
|
+
const onBotPointerDown = (e) => {
|
|
2341
|
+
if (e.button !== 0) return;
|
|
2342
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
2343
|
+
botDragRef.current = { sx: e.clientX, sy: e.clientY, ox: r.left, oy: r.top, moved: false };
|
|
2344
|
+
try {
|
|
2345
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2346
|
+
} catch {
|
|
2347
|
+
}
|
|
2348
|
+
};
|
|
2349
|
+
const onBotPointerMove = (e) => {
|
|
2350
|
+
const d = botDragRef.current;
|
|
2351
|
+
if (!d || typeof window === "undefined") return;
|
|
2352
|
+
const dx = e.clientX - d.sx, dy = e.clientY - d.sy;
|
|
2353
|
+
if (!d.moved && Math.hypot(dx, dy) < 4) return;
|
|
2354
|
+
d.moved = true;
|
|
2355
|
+
const el = e.currentTarget;
|
|
2356
|
+
const w = el.offsetWidth || 200, h = el.offsetHeight || 160;
|
|
2357
|
+
const x = Math.min(Math.max(8, d.ox + dx), window.innerWidth - w - 8);
|
|
2358
|
+
const y = Math.min(Math.max(8, d.oy + dy), window.innerHeight - h - 8);
|
|
2359
|
+
botPosRef.current = { x, y };
|
|
2360
|
+
setBotPos({ x, y });
|
|
2361
|
+
};
|
|
2362
|
+
const onBotPointerUp = () => {
|
|
2363
|
+
const d = botDragRef.current;
|
|
2364
|
+
botDragRef.current = null;
|
|
2365
|
+
if (d && d.moved) {
|
|
2366
|
+
try {
|
|
2367
|
+
if (typeof localStorage !== "undefined") localStorage.setItem("dsh-dock/anim/robot-pos/v1", JSON.stringify(botPosRef.current));
|
|
2368
|
+
} catch {
|
|
2369
|
+
}
|
|
2370
|
+
botClickBlockRef.current = true;
|
|
2371
|
+
setTimeout(() => {
|
|
2372
|
+
botClickBlockRef.current = false;
|
|
2373
|
+
}, 0);
|
|
2374
|
+
}
|
|
2375
|
+
};
|
|
2376
|
+
const onBotResizePointerDown = (e) => {
|
|
2377
|
+
if (e.button !== 0) return;
|
|
2378
|
+
e.preventDefault();
|
|
2379
|
+
e.stopPropagation();
|
|
2380
|
+
botResizeRef.current = { sx: e.clientX, sy: e.clientY, scale: botScaleDraft == null ? robotScaleFromConfig : botScaleDraft };
|
|
2381
|
+
try {
|
|
2382
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2383
|
+
} catch {
|
|
2384
|
+
}
|
|
2385
|
+
};
|
|
2386
|
+
const onBotResizePointerMove = (e) => {
|
|
2387
|
+
const d = botResizeRef.current;
|
|
2388
|
+
if (!d) return;
|
|
2389
|
+
e.preventDefault();
|
|
2390
|
+
e.stopPropagation();
|
|
2391
|
+
const delta = (e.clientX - d.sx + (e.clientY - d.sy)) / 2;
|
|
2392
|
+
const next = Math.max(0.85, Math.min(2.2, Math.round((d.scale + delta / 220) * 100) / 100));
|
|
2393
|
+
setBotScaleDraft(next);
|
|
2394
|
+
if (botPosRef.current && typeof window !== "undefined") {
|
|
2395
|
+
const w = 220 * next + 24, h = 132 * next + 46;
|
|
2396
|
+
const x = Math.min(Math.max(8, botPosRef.current.x), Math.max(8, window.innerWidth - w - 8));
|
|
2397
|
+
const y = Math.min(Math.max(8, botPosRef.current.y), Math.max(8, window.innerHeight - h - 8));
|
|
2398
|
+
botPosRef.current = { x, y };
|
|
2399
|
+
setBotPos({ x, y });
|
|
2400
|
+
}
|
|
2401
|
+
};
|
|
2402
|
+
const onBotResizePointerUp = (e) => {
|
|
2403
|
+
if (!botResizeRef.current) return;
|
|
2404
|
+
e.preventDefault();
|
|
2405
|
+
e.stopPropagation();
|
|
2406
|
+
const next = botScaleDraft == null ? robotScaleFromConfig : botScaleDraft;
|
|
2407
|
+
botResizeRef.current = null;
|
|
2408
|
+
saveRobotScale(next);
|
|
2409
|
+
try {
|
|
2410
|
+
if (botPosRef.current && typeof localStorage !== "undefined") localStorage.setItem("dsh-dock/anim/robot-pos/v1", JSON.stringify(botPosRef.current));
|
|
2411
|
+
} catch {
|
|
2412
|
+
}
|
|
2413
|
+
setBotScaleDraft(null);
|
|
2414
|
+
};
|
|
2415
|
+
const onBotClick = () => {
|
|
2416
|
+
if (botClickBlockRef.current) return;
|
|
2417
|
+
openPanel("animation");
|
|
2418
|
+
};
|
|
2419
|
+
const displayRobotScale = botScaleDraft == null ? robotScaleFromConfig : botScaleDraft;
|
|
2420
|
+
const botCardStyle = botPos ? Object.assign({}, speedStyle, { "--dkan-bot-scale": displayRobotScale, left: botPos.x, top: botPos.y, right: "auto", bottom: "auto" }) : Object.assign({}, speedStyle, { "--dkan-bot-scale": displayRobotScale });
|
|
2421
|
+
if (!st) return null;
|
|
2422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2423
|
+
ambientOn && mode === "flow" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-line", style: speedStyle, "aria-hidden": "true" }) : null,
|
|
2424
|
+
ambientOn && (mode === "matrix" || mode === "stars" || mode === "aurora") ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AmbientLayer, { mode, speed: Number(speed).toFixed(2) }) : null,
|
|
2425
|
+
ambientOn && mode === "orbit" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-orbit", style: speedStyle, "aria-hidden": "true" }) : null,
|
|
2426
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BurstLayer, { bursts }),
|
|
2427
|
+
ambientOn && mode === "robot" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2428
|
+
"div",
|
|
2429
|
+
{
|
|
2430
|
+
className: "dkan-botcard",
|
|
2431
|
+
role: "button",
|
|
2432
|
+
tabIndex: 0,
|
|
2433
|
+
style: botCardStyle,
|
|
2434
|
+
title: active.length + " \u4E2A\u4EFB\u52A1 \xB7 " + phaseLabel(phase) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875 \xB7 \u53EF\u62D6\u52A8\u5230\u4EFB\u610F\u4F4D\u7F6E",
|
|
2435
|
+
onPointerDown: onBotPointerDown,
|
|
2436
|
+
onPointerMove: onBotPointerMove,
|
|
2437
|
+
onPointerUp: onBotPointerUp,
|
|
2438
|
+
onPointerCancel: onBotPointerUp,
|
|
2439
|
+
onClick: onBotClick,
|
|
2440
|
+
onKeyDown: (e) => {
|
|
2441
|
+
if (e.target === e.currentTarget && (e.key === "Enter" || e.key === " ")) {
|
|
2442
|
+
e.preventDefault();
|
|
2443
|
+
onBotClick();
|
|
2444
|
+
}
|
|
2445
|
+
},
|
|
2446
|
+
children: [
|
|
2447
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase, tasks: active }),
|
|
2448
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-bot-cap", children: [
|
|
2449
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
|
|
2450
|
+
" \u4E2A\u4EFB\u52A1",
|
|
2451
|
+
elapsed ? " \xB7 " + elapsed : "",
|
|
2452
|
+
" \xB7 ",
|
|
2453
|
+
phaseLabel(phase)
|
|
2454
|
+
] }),
|
|
2455
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2456
|
+
"button",
|
|
2457
|
+
{
|
|
2458
|
+
type: "button",
|
|
2459
|
+
className: "dkan-bot-resize",
|
|
2460
|
+
"aria-label": "\u8C03\u6574\u684C\u9762\u4F19\u4F34\u5927\u5C0F",
|
|
2461
|
+
title: "\u62D6\u52A8\u8C03\u6574\u684C\u9762\u4F19\u4F34\u5927\u5C0F",
|
|
2462
|
+
onPointerDown: onBotResizePointerDown,
|
|
2463
|
+
onPointerMove: onBotResizePointerMove,
|
|
2464
|
+
onPointerUp: onBotResizePointerUp,
|
|
2465
|
+
onPointerCancel: onBotResizePointerUp,
|
|
2466
|
+
onClick: (e) => e.stopPropagation(),
|
|
2467
|
+
onKeyDown: (e) => {
|
|
2468
|
+
if (e.key !== "ArrowUp" && e.key !== "ArrowRight" && e.key !== "ArrowDown" && e.key !== "ArrowLeft") return;
|
|
2469
|
+
e.preventDefault();
|
|
2470
|
+
e.stopPropagation();
|
|
2471
|
+
const d = e.key === "ArrowUp" || e.key === "ArrowRight" ? 0.05 : -0.05;
|
|
2472
|
+
saveRobotScale(Math.max(0.85, Math.min(2.2, Math.round((displayRobotScale + d) * 100) / 100)));
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
)
|
|
2476
|
+
]
|
|
2477
|
+
}
|
|
2478
|
+
) : null,
|
|
2479
|
+
ambientOn && mode !== "robot" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2480
|
+
"button",
|
|
2481
|
+
{
|
|
2482
|
+
type: "button",
|
|
2483
|
+
className: "dkan-badge" + (mode === "breathe" ? " dkan-badge-breathe" : ""),
|
|
2484
|
+
style: Object.assign({}, speedStyle, { "--dkan-phase": phaseColor(phase) }),
|
|
2485
|
+
title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 " + phaseLabel(phase) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
|
|
2486
|
+
onClick: () => openPanel("animation"),
|
|
2487
|
+
children: [
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap", children: [
|
|
2489
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
|
|
2490
|
+
mode === "breathe" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-halo" }) : null,
|
|
2491
|
+
mode === "ring" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-ring" }) : null
|
|
2492
|
+
] }),
|
|
2493
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-badge-txt", children: [
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
|
|
2495
|
+
" \u4E2A\u4EFB\u52A1",
|
|
2496
|
+
elapsed ? " \xB7 " + elapsed : "",
|
|
2497
|
+
" \xB7 ",
|
|
2498
|
+
phaseLabel(phase)
|
|
2499
|
+
] })
|
|
2500
|
+
]
|
|
2501
|
+
}
|
|
2502
|
+
) : null,
|
|
2503
|
+
flourish ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2504
|
+
"div",
|
|
2505
|
+
{
|
|
2506
|
+
className: "dkan-done" + (flourish.err ? " err" : ""),
|
|
2507
|
+
onAnimationEnd: () => setFlourish(null),
|
|
2508
|
+
"aria-hidden": "true"
|
|
2509
|
+
},
|
|
2510
|
+
flourish.key
|
|
2511
|
+
) : null,
|
|
2512
|
+
toasts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-toasts", children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Toast, { t, onClose: (id) => setToasts((prev) => prev.filter((x) => x.id !== id)) }, t.id)) }) : null
|
|
2513
|
+
] });
|
|
2514
|
+
}
|
|
2515
|
+
function ModePreview({ id }) {
|
|
2516
|
+
if (id === "flow") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev-flow" }) });
|
|
2517
|
+
if (id === "ring") {
|
|
2518
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap", children: [
|
|
2519
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
|
|
2520
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-ring" })
|
|
2521
|
+
] }) });
|
|
2522
|
+
}
|
|
2523
|
+
if (id === "orbit") {
|
|
2524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev dkan-prev-box", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev-orbit" }) });
|
|
2525
|
+
}
|
|
2526
|
+
if (id === "matrix") {
|
|
2527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-prev dkan-prev-matrix", children: [
|
|
2528
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2529
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2530
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2531
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2532
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2533
|
+
] });
|
|
2534
|
+
}
|
|
2535
|
+
if (id === "stars") {
|
|
2536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-prev dkan-prev-stars", children: [
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2538
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2539
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2540
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2542
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2543
|
+
] });
|
|
2544
|
+
}
|
|
2545
|
+
if (id === "aurora") {
|
|
2546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-prev dkan-prev-aurora", children: [
|
|
2547
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2548
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2549
|
+
] });
|
|
2550
|
+
}
|
|
2551
|
+
if (id === "robot") {
|
|
2552
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev dkan-prev-bot", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase: "code" }) });
|
|
2553
|
+
}
|
|
2554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap dkan-breathe", children: [
|
|
2555
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
|
|
2556
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-halo" })
|
|
2557
|
+
] }) });
|
|
2558
|
+
}
|
|
2559
|
+
function TaskRow(props) {
|
|
2560
|
+
const t = props.t;
|
|
2561
|
+
const info = endInfo(t.endReason);
|
|
2562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task", children: [
|
|
2563
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task-head", children: [
|
|
2564
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-task-title", title: t.title, children: t.title || "(\u65E0\u6807\u9898)" }),
|
|
2565
|
+
props.done ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag " + info.cls, children: info.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag on", children: phaseLabel(t.phase) })
|
|
2566
|
+
] }),
|
|
2567
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task-meta", children: [
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: (t.models && t.models.length ? t.models.join(", ") : "\u672A\u77E5") + (t.provider ? "\uFF08" + t.provider + "\uFF09" : "") }),
|
|
2569
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: props.done ? fmtDur(t.duration) : fmtClock(t.elapsed) }),
|
|
2570
|
+
"turns" in t ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u56DE\u5408 " + (t.turns || 0) + " \xB7 \u6B65\u9AA4 " + (t.steps || 0) + (t.toolCalls ? " \xB7 \u5DE5\u5177 " + t.toolCalls : "") }) : null,
|
|
2571
|
+
t.totalTokens ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u21A7" + fmtCompact2(t.inputTokens) + " \u21A5" + fmtCompact2(t.outputTokens) }) : null,
|
|
2572
|
+
props.done && t.endTime ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: fmtTime2(t.endTime) }) : null
|
|
2573
|
+
] }),
|
|
2574
|
+
props.done && t.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-task-err", children: truncate(t.errorMessage, 120) }) : null
|
|
2575
|
+
] });
|
|
2576
|
+
}
|
|
2577
|
+
function AnimationView(props) {
|
|
2578
|
+
const ctx = props && props.ctx;
|
|
2579
|
+
const snap = useAnimation(ctx);
|
|
2580
|
+
const [cfg, setCfg] = (0, import_react8.useState)(null);
|
|
2581
|
+
const [saveErr, setSaveErr] = (0, import_react8.useState)("");
|
|
2582
|
+
const [testing, setTesting] = (0, import_react8.useState)(false);
|
|
2583
|
+
const [testState, setTestState] = (0, import_react8.useState)(null);
|
|
2584
|
+
const [feishuTestState, setFeishuTestState] = (0, import_react8.useState)(null);
|
|
2585
|
+
const [feishuTesting, setFeishuTesting] = (0, import_react8.useState)(false);
|
|
2586
|
+
const cfgRef = (0, import_react8.useRef)(null);
|
|
2587
|
+
const pendingSavesRef = (0, import_react8.useRef)(0);
|
|
2588
|
+
const editingWebhookRef = (0, import_react8.useRef)(false);
|
|
2589
|
+
const editingFeishuRef = (0, import_react8.useRef)(false);
|
|
2590
|
+
(0, import_react8.useEffect)(() => {
|
|
2591
|
+
const c = snap.status && snap.status.config;
|
|
2592
|
+
if (!c) return;
|
|
2593
|
+
if (pendingSavesRef.current > 0 || editingWebhookRef.current || editingFeishuRef.current) return;
|
|
2594
|
+
if (c !== cfgRef.current) {
|
|
2595
|
+
cfgRef.current = c;
|
|
2596
|
+
setCfg(Object.assign({}, c));
|
|
2597
|
+
}
|
|
2598
|
+
}, [snap.status]);
|
|
2599
|
+
(0, import_react8.useEffect)(() => {
|
|
2600
|
+
if (!animationStore.snap.status) animationStore.refresh();
|
|
2601
|
+
}, []);
|
|
2602
|
+
const patch = (p) => {
|
|
2603
|
+
setSaveErr("");
|
|
2604
|
+
setCfg(Object.assign({}, cfg, p));
|
|
2605
|
+
pendingSavesRef.current++;
|
|
2606
|
+
return rpcCall2("config", p).then((d) => {
|
|
2607
|
+
pendingSavesRef.current--;
|
|
2608
|
+
animationStore.applyConfig(d && d.config);
|
|
2609
|
+
}).catch((e) => {
|
|
2610
|
+
pendingSavesRef.current--;
|
|
2611
|
+
setSaveErr("\u4FDD\u5B58\u5931\u8D25\uFF1A" + (e && e.message || String(e)));
|
|
2612
|
+
});
|
|
2613
|
+
};
|
|
2614
|
+
const saveWebhook = async () => {
|
|
2615
|
+
if (!editingWebhookRef.current) return;
|
|
2616
|
+
const hook = String(cfg.dingtalkWebhook || "").trim();
|
|
2617
|
+
await patch({ dingtalkWebhook: hook });
|
|
2618
|
+
editingWebhookRef.current = false;
|
|
2619
|
+
const c = animationStore.snap.status && animationStore.snap.status.config;
|
|
2620
|
+
if (c && c !== cfgRef.current) {
|
|
2621
|
+
cfgRef.current = c;
|
|
2622
|
+
setCfg(Object.assign({}, c));
|
|
2623
|
+
}
|
|
2624
|
+
};
|
|
2625
|
+
const saveFeishuWebhook = async () => {
|
|
2626
|
+
if (!editingFeishuRef.current) return;
|
|
2627
|
+
const hook = String(cfg.feishuWebhook || "").trim();
|
|
2628
|
+
await patch({ feishuWebhook: hook });
|
|
2629
|
+
editingFeishuRef.current = false;
|
|
2630
|
+
const c = animationStore.snap.status && animationStore.snap.status.config;
|
|
2631
|
+
if (c && c !== cfgRef.current) {
|
|
2632
|
+
cfgRef.current = c;
|
|
2633
|
+
setCfg(Object.assign({}, c));
|
|
2634
|
+
}
|
|
2635
|
+
};
|
|
2636
|
+
const runDingtalkTest = async () => {
|
|
2637
|
+
setTesting(true);
|
|
2638
|
+
setTestState(null);
|
|
2639
|
+
try {
|
|
2640
|
+
if (editingWebhookRef.current) {
|
|
2641
|
+
const hook = String(cfg.dingtalkWebhook || "").trim();
|
|
2642
|
+
if (!hook) throw new Error("\u8BF7\u5148\u586B\u5199 Webhook \u5730\u5740");
|
|
2643
|
+
const d = await rpcCall2("config", { dingtalkWebhook: hook });
|
|
2644
|
+
animationStore.applyConfig(d && d.config);
|
|
2645
|
+
editingWebhookRef.current = false;
|
|
2646
|
+
cfgRef.current = d && d.config || cfgRef.current;
|
|
2647
|
+
setCfg(Object.assign({}, cfg, { dingtalkWebhook: hook }));
|
|
2648
|
+
}
|
|
2649
|
+
const r = await rpcCall2("test");
|
|
2650
|
+
setTestState(r && r.sent ? { ok: true, msg: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u53BB\u7FA4\u91CC\u770B\u770B" } : { ok: false, msg: r && r.error || "\u53D1\u9001\u5931\u8D25" });
|
|
2651
|
+
} catch (e) {
|
|
2652
|
+
setTestState({ ok: false, msg: e && e.message || String(e) });
|
|
2653
|
+
} finally {
|
|
2654
|
+
setTesting(false);
|
|
2655
|
+
}
|
|
2656
|
+
};
|
|
2657
|
+
const runFeishuTest = async () => {
|
|
2658
|
+
setFeishuTesting(true);
|
|
2659
|
+
setFeishuTestState(null);
|
|
2660
|
+
try {
|
|
2661
|
+
if (editingFeishuRef.current) {
|
|
2662
|
+
const hook = String(cfg.feishuWebhook || "").trim();
|
|
2663
|
+
if (!hook) throw new Error("\u8BF7\u5148\u586B\u5199 Webhook \u5730\u5740");
|
|
2664
|
+
const d = await rpcCall2("config", { feishuWebhook: hook });
|
|
2665
|
+
animationStore.applyConfig(d && d.config);
|
|
2666
|
+
editingFeishuRef.current = false;
|
|
2667
|
+
cfgRef.current = d && d.config || cfgRef.current;
|
|
2668
|
+
setCfg(Object.assign({}, cfg, { feishuWebhook: hook }));
|
|
2669
|
+
}
|
|
2670
|
+
const r = await rpcCall2("test", { target: "feishu" });
|
|
2671
|
+
setFeishuTestState(r && r.sent ? { ok: true, msg: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u53BB\u7FA4\u91CC\u770B\u770B" } : { ok: false, msg: r && r.error || "\u53D1\u9001\u5931\u8D25" });
|
|
2672
|
+
} catch (e) {
|
|
2673
|
+
setFeishuTestState({ ok: false, msg: e && e.message || String(e) });
|
|
2674
|
+
} finally {
|
|
2675
|
+
setFeishuTesting(false);
|
|
2676
|
+
}
|
|
2677
|
+
};
|
|
2678
|
+
const enableSystemNotify = async (next) => {
|
|
2679
|
+
if (next && typeof Notification !== "undefined" && Notification.permission !== "granted") {
|
|
2680
|
+
try {
|
|
2681
|
+
const perm = await Notification.requestPermission();
|
|
2682
|
+
if (perm !== "granted") {
|
|
2683
|
+
setSaveErr("\u6D4F\u89C8\u5668\u672A\u6388\u6743\u7CFB\u7EDF\u901A\u77E5\uFF08\u53EF\u5728\u5730\u5740\u680F\u6743\u9650\u8BBE\u7F6E\u91CC\u91CD\u65B0\u5141\u8BB8\uFF09");
|
|
2684
|
+
return;
|
|
2685
|
+
}
|
|
2686
|
+
} catch {
|
|
2687
|
+
setSaveErr("\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u7CFB\u7EDF\u901A\u77E5");
|
|
2688
|
+
return;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
patch({ systemNotify: next });
|
|
2692
|
+
};
|
|
2693
|
+
const st = snap.status;
|
|
2694
|
+
const active = st && st.active ? st.active : [];
|
|
2695
|
+
const recent = st && st.recent ? st.recent.slice(0, 6) : [];
|
|
2696
|
+
const permNote = typeof Notification === "undefined" ? "\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u7CFB\u7EDF\u901A\u77E5" : Notification.permission === "granted" ? "\u5DF2\u6388\u6743 \xB7 \u4EC5\u9875\u9762\u540E\u53F0\u65F6\u63A8\u9001" : Notification.permission === "denied" ? "\u5DF2\u88AB\u6D4F\u89C8\u5668\u62D2\u7EDD\uFF08\u9700\u5728\u6D4F\u89C8\u5668\u6743\u9650\u8BBE\u7F6E\u91CC\u91CD\u65B0\u5141\u8BB8\uFF09" : "\u672A\u6388\u6743 \xB7 \u5F00\u542F\u65F6\u4F1A\u8BF7\u6C42\u6388\u6743\uFF0C\u4EC5\u9875\u9762\u540E\u53F0\u65F6\u63A8\u9001";
|
|
2697
|
+
const rows = [];
|
|
2698
|
+
if (!cfg) {
|
|
2699
|
+
rows.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: snap.error ? "\u72B6\u6001\u4E0D\u53EF\u7528\uFF1A" + snap.error : snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4EFB\u52A1\u72B6\u6001\u2026" : "\u7B49\u5F85\u4EFB\u52A1\u72B6\u6001" }, "load"));
|
|
2700
|
+
} else {
|
|
2701
|
+
rows.push(
|
|
2702
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2703
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2704
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u8FD0\u884C\u52A8\u753B" }),
|
|
2705
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4EFB\u52A1\u8FDB\u884C\u4E2D\u624D\u51FA\u73B0\uFF1B\u514B\u5236\u7684\u52A8\u6548\uFF0C\u6697/\u4EAE\u8272\u81EA\u9002\u5E94" }),
|
|
2706
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
|
|
2707
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.animationEnabled ? " on" : ""), children: cfg.animationEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
|
|
2708
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2709
|
+
"button",
|
|
2710
|
+
{
|
|
2711
|
+
type: "button",
|
|
2712
|
+
className: "dock-sw" + (cfg.animationEnabled ? " on" : ""),
|
|
2713
|
+
role: "switch",
|
|
2714
|
+
"aria-checked": cfg.animationEnabled,
|
|
2715
|
+
"aria-label": "\u5F00\u5173\u8FD0\u884C\u52A8\u753B",
|
|
2716
|
+
title: cfg.animationEnabled ? "\u5173\u95ED\u8FD0\u884C\u52A8\u753B" : "\u5F00\u542F\u8FD0\u884C\u52A8\u753B",
|
|
2717
|
+
onClick: () => patch({ animationEnabled: !cfg.animationEnabled })
|
|
2718
|
+
}
|
|
2719
|
+
)
|
|
2720
|
+
] })
|
|
2721
|
+
] }),
|
|
2722
|
+
cfg.animationEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2723
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-modes", children: EFFECT_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2724
|
+
"button",
|
|
2725
|
+
{
|
|
2726
|
+
type: "button",
|
|
2727
|
+
className: "dkan-mode" + (cfg.effectMode === m.id ? " on" : ""),
|
|
2728
|
+
onClick: () => patch({ effectMode: m.id }),
|
|
2729
|
+
children: [
|
|
2730
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-mode-name", children: m.name }),
|
|
2731
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ModePreview, { id: m.id }),
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-mode-desc", children: m.desc })
|
|
2733
|
+
]
|
|
2734
|
+
},
|
|
2735
|
+
m.id
|
|
2736
|
+
)) }),
|
|
2737
|
+
cfg.effectMode === "robot" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-robot-controls", children: [
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-robot-controls-head", children: [
|
|
2739
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u684C\u9762\u4F19\u4F34\u5927\u5C0F" }),
|
|
2740
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
|
|
2741
|
+
Math.round((Number(cfg.robotScale) || 1.35) * 100),
|
|
2742
|
+
"%"
|
|
2743
|
+
] })
|
|
2744
|
+
] }),
|
|
2745
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-robot-size-options", role: "group", "aria-label": "\u684C\u9762\u4F19\u4F34\u5927\u5C0F\u9884\u8BBE", children: [[1, "\u7D27\u51D1"], [1.35, "\u9ED8\u8BA4"], [1.7, "\u52A0\u5927"], [2.1, "\u7279\u5927"]].map(([scale, label]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2746
|
+
"button",
|
|
2747
|
+
{
|
|
2748
|
+
type: "button",
|
|
2749
|
+
className: Math.abs((Number(cfg.robotScale) || 1.35) - scale) < 0.03 ? "on" : "",
|
|
2750
|
+
onClick: () => patch({ robotScale: scale }),
|
|
2751
|
+
children: label
|
|
2752
|
+
},
|
|
2753
|
+
scale
|
|
2754
|
+
)) }),
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-robot-slider-row", children: [
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2757
|
+
"input",
|
|
2758
|
+
{
|
|
2759
|
+
type: "range",
|
|
2760
|
+
min: "0.85",
|
|
2761
|
+
max: "2.2",
|
|
2762
|
+
step: "0.05",
|
|
2763
|
+
value: Number(cfg.robotScale) || 1.35,
|
|
2764
|
+
"aria-label": "\u684C\u9762\u4F19\u4F34\u5927\u5C0F\u767E\u5206\u6BD4",
|
|
2765
|
+
onChange: (e) => patch({ robotScale: Number(e.target.value) })
|
|
2766
|
+
}
|
|
2767
|
+
),
|
|
2768
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u6D6E\u5C42\u53F3\u4E0B\u89D2\u4E5F\u53EF\u76F4\u63A5\u62D6\u52A8\u7F29\u653E\uFF0C\u5927\u5C0F\u4F1A\u81EA\u52A8\u4FDD\u5B58\u3002" })
|
|
2769
|
+
] })
|
|
2770
|
+
] }) : null
|
|
2771
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u52A8\u753B\u5DF2\u5173\u95ED\u2014\u2014\u53EA\u4FDD\u7559\u901A\u77E5\uFF08\u6216\u5168\u90E8\u5173\u95ED\uFF09\u65F6\uFF0C\u9875\u9762\u4E0D\u4F1A\u6709\u4EFB\u4F55\u52A8\u6548\u3002" })
|
|
2772
|
+
] }, "anim"),
|
|
2773
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2775
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u5B8C\u6210\u901A\u77E5" }),
|
|
2776
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4E0E\u52A8\u753B\u4E92\u4E0D\u4F9D\u8D56\uFF0C\u53EF\u5355\u72EC\u5F00\u542F" }),
|
|
2777
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
|
|
2778
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.notifyEnabled ? " on" : ""), children: cfg.notifyEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2780
|
+
"button",
|
|
2781
|
+
{
|
|
2782
|
+
type: "button",
|
|
2783
|
+
className: "dock-sw" + (cfg.notifyEnabled ? " on" : ""),
|
|
2784
|
+
role: "switch",
|
|
2785
|
+
"aria-checked": cfg.notifyEnabled,
|
|
2786
|
+
"aria-label": "\u5F00\u5173\u5B8C\u6210\u901A\u77E5",
|
|
2787
|
+
title: cfg.notifyEnabled ? "\u5173\u95ED\u5B8C\u6210\u901A\u77E5" : "\u5F00\u542F\u5B8C\u6210\u901A\u77E5",
|
|
2788
|
+
onClick: () => patch({ notifyEnabled: !cfg.notifyEnabled })
|
|
2789
|
+
}
|
|
2790
|
+
)
|
|
2791
|
+
] })
|
|
2792
|
+
] }),
|
|
2793
|
+
cfg.notifyEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-rows-narrow", children: [
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u5B8C\u6210\u901A\u77E5" }),
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2797
|
+
"button",
|
|
2798
|
+
{
|
|
2799
|
+
type: "button",
|
|
2800
|
+
className: "dkm-miniswitch" + (cfg.notifyOnComplete ? " on" : ""),
|
|
2801
|
+
onClick: () => patch({ notifyOnComplete: !cfg.notifyOnComplete }),
|
|
2802
|
+
children: cfg.notifyOnComplete ? "\u5F00" : "\u5173"
|
|
2803
|
+
}
|
|
2804
|
+
),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u4EFB\u52A1\u6B63\u5E38\u5B8C\u6210\u65F6\u901A\u77E5" })
|
|
2806
|
+
] }),
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2808
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u5F02\u5E38\u901A\u77E5" }),
|
|
2809
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2810
|
+
"button",
|
|
2811
|
+
{
|
|
2812
|
+
type: "button",
|
|
2813
|
+
className: "dkm-miniswitch" + (cfg.notifyOnError ? " on" : ""),
|
|
2814
|
+
onClick: () => patch({ notifyOnError: !cfg.notifyOnError }),
|
|
2815
|
+
children: cfg.notifyOnError ? "\u5F00" : "\u5173"
|
|
2816
|
+
}
|
|
2817
|
+
),
|
|
2818
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u51FA\u9519 / \u4E2D\u6B62 / \u8FBE\u8F93\u51FA\u4E0A\u9650\u65F6\u901A\u77E5" })
|
|
2819
|
+
] }),
|
|
2820
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u505C\u7559\u65F6\u957F" }),
|
|
2822
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2823
|
+
"select",
|
|
2824
|
+
{
|
|
2825
|
+
className: "dkan-select",
|
|
2826
|
+
value: String(cfg.notifyStayMs),
|
|
2827
|
+
onChange: (e) => patch({ notifyStayMs: Number(e.target.value) }),
|
|
2828
|
+
children: [
|
|
2829
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "4000", children: "4 \u79D2" }),
|
|
2830
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "8000", children: "8 \u79D2" }),
|
|
2831
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "15000", children: "15 \u79D2" }),
|
|
2832
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "30000", children: "30 \u79D2" }),
|
|
2833
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "0", children: "\u5E38\u9A7B\uFF08\u624B\u52A8\u5173\u95ED\uFF09" })
|
|
2834
|
+
]
|
|
2835
|
+
}
|
|
2836
|
+
)
|
|
2837
|
+
] }),
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2839
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u7CFB\u7EDF\u901A\u77E5" }),
|
|
2840
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2841
|
+
"button",
|
|
2842
|
+
{
|
|
2843
|
+
type: "button",
|
|
2844
|
+
className: "dkm-miniswitch" + (cfg.systemNotify ? " on" : ""),
|
|
2845
|
+
onClick: () => enableSystemNotify(!cfg.systemNotify),
|
|
2846
|
+
children: cfg.systemNotify ? "\u5F00" : "\u5173"
|
|
2847
|
+
}
|
|
2848
|
+
),
|
|
2849
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: permNote })
|
|
2850
|
+
] }),
|
|
2851
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2852
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u63D0\u793A\u97F3" }),
|
|
2853
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2854
|
+
"button",
|
|
2855
|
+
{
|
|
2856
|
+
type: "button",
|
|
2857
|
+
className: "dkm-miniswitch" + (cfg.soundNotify !== false ? " on" : ""),
|
|
2858
|
+
onClick: () => patch({ soundNotify: cfg.soundNotify === false }),
|
|
2859
|
+
children: cfg.soundNotify !== false ? "\u5F00" : "\u5173"
|
|
2860
|
+
}
|
|
2861
|
+
),
|
|
2862
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u65F6\u64AD\u653E\uFF08\u8BD5\u542C\u4E3A\u5148\u64AD\u5B8C\u6210\u97F3\u3001\u540E\u64AD\u5F02\u5E38\u97F3\uFF09" })
|
|
2863
|
+
] }),
|
|
2864
|
+
cfg.soundNotify !== false ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-sounds", children: Object.keys(SOUND_LIBRARY).map((key) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2865
|
+
"button",
|
|
2866
|
+
{
|
|
2867
|
+
type: "button",
|
|
2868
|
+
className: "dkan-sound" + (cfg.soundEffect === key ? " on" : ""),
|
|
2869
|
+
onClick: () => patch({ soundEffect: key }),
|
|
2870
|
+
children: [
|
|
2871
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sound-name", children: [
|
|
2872
|
+
SOUND_LIBRARY[key].name,
|
|
2873
|
+
cfg.soundEffect === key ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sound-cur", children: "\u2713" }) : null
|
|
2874
|
+
] }),
|
|
2875
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2876
|
+
"span",
|
|
2877
|
+
{
|
|
2878
|
+
className: "dkan-sound-play",
|
|
2879
|
+
role: "button",
|
|
2880
|
+
tabIndex: 0,
|
|
2881
|
+
title: "\u8BD5\u542C " + SOUND_LIBRARY[key].name,
|
|
2882
|
+
onClick: (e) => {
|
|
2883
|
+
e.stopPropagation();
|
|
2884
|
+
previewSound(key);
|
|
2885
|
+
},
|
|
2886
|
+
onKeyDown: (e) => {
|
|
2887
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2888
|
+
e.preventDefault();
|
|
2889
|
+
e.stopPropagation();
|
|
2890
|
+
previewSound(key);
|
|
2891
|
+
}
|
|
2892
|
+
},
|
|
2893
|
+
children: "\u25B6"
|
|
2894
|
+
}
|
|
2895
|
+
)
|
|
2896
|
+
]
|
|
2897
|
+
},
|
|
2898
|
+
key
|
|
2899
|
+
)) }) : null
|
|
2900
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u901A\u77E5\u5DF2\u5173\u95ED\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u65F6\u65E2\u4E0D\u5F39\u5361\u7247\u4E5F\u4E0D\u63A8\u7CFB\u7EDF\u901A\u77E5\u3002" })
|
|
2901
|
+
] }, "notify"),
|
|
2902
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2903
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2904
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u9489\u9489\u63A8\u9001" }),
|
|
2905
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u9489\u9489\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF1B\u4E8B\u4EF6\u8DDF\u968F\u4E0A\u65B9\u5B8C\u6210/\u5F02\u5E38\u5F00\u5173\uFF09" }),
|
|
2906
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
|
|
2907
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.dingtalkEnabled ? " on" : ""), children: cfg.dingtalkEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2909
|
+
"button",
|
|
2910
|
+
{
|
|
2911
|
+
type: "button",
|
|
2912
|
+
className: "dock-sw" + (cfg.dingtalkEnabled ? " on" : ""),
|
|
2913
|
+
role: "switch",
|
|
2914
|
+
"aria-checked": cfg.dingtalkEnabled,
|
|
2915
|
+
"aria-label": "\u5F00\u5173\u9489\u9489\u63A8\u9001",
|
|
2916
|
+
title: cfg.dingtalkEnabled ? "\u5173\u95ED\u9489\u9489\u63A8\u9001" : "\u5F00\u542F\u9489\u9489\u63A8\u9001",
|
|
2917
|
+
onClick: () => patch({ dingtalkEnabled: !cfg.dingtalkEnabled })
|
|
2918
|
+
}
|
|
2919
|
+
)
|
|
2920
|
+
] })
|
|
2921
|
+
] }),
|
|
2922
|
+
cfg.dingtalkEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-rows-narrow", children: [
|
|
2923
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row dkan-row-webhook", children: [
|
|
2924
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "Webhook" }),
|
|
2925
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2926
|
+
"input",
|
|
2927
|
+
{
|
|
2928
|
+
type: "text",
|
|
2929
|
+
className: "dkan-input",
|
|
2930
|
+
spellCheck: false,
|
|
2931
|
+
value: cfg.dingtalkWebhook || "",
|
|
2932
|
+
placeholder: "https://oapi.dingtalk.com/robot/send?access_token=\u2026",
|
|
2933
|
+
onChange: (e) => {
|
|
2934
|
+
editingWebhookRef.current = true;
|
|
2935
|
+
setCfg(Object.assign({}, cfg, { dingtalkWebhook: e.target.value }));
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
),
|
|
2939
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2940
|
+
"button",
|
|
2941
|
+
{
|
|
2942
|
+
type: "button",
|
|
2943
|
+
className: "dkan-btn",
|
|
2944
|
+
disabled: !editingWebhookRef.current,
|
|
2945
|
+
onClick: saveWebhook,
|
|
2946
|
+
children: editingWebhookRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
|
|
2947
|
+
}
|
|
2948
|
+
)
|
|
2949
|
+
] }),
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
|
|
2952
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-btn", disabled: testing, onClick: runDingtalkTest, children: testing ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
|
|
2953
|
+
testState ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-row-sub" + (testState.ok ? " dkan-ok" : " dkan-err"), children: [
|
|
2954
|
+
testState.ok ? "\u2713 " : "\u2717 ",
|
|
2955
|
+
testState.msg
|
|
2956
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
|
|
2957
|
+
] }),
|
|
2958
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u9489\u9489\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u667A\u80FD\u7FA4\u52A9\u624B \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\uFF08Webhook\uFF09\uFF0C \u5B89\u5168\u8BBE\u7F6E\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
|
|
2959
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u9489\u9489\u3002" })
|
|
2960
|
+
] }, "dingtalk"),
|
|
2961
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2962
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2963
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u98DE\u4E66\u63A8\u9001" }),
|
|
2964
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u98DE\u4E66\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF1B\u4E8B\u4EF6\u8DDF\u968F\u4E0A\u65B9\u5B8C\u6210/\u5F02\u5E38\u5F00\u5173\uFF09" }),
|
|
2965
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
|
|
2966
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.feishuEnabled ? " on" : ""), children: cfg.feishuEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2968
|
+
"button",
|
|
2969
|
+
{
|
|
2970
|
+
type: "button",
|
|
2971
|
+
className: "dock-sw" + (cfg.feishuEnabled ? " on" : ""),
|
|
2972
|
+
role: "switch",
|
|
2973
|
+
"aria-checked": cfg.feishuEnabled,
|
|
2974
|
+
"aria-label": "\u5F00\u5173\u98DE\u4E66\u63A8\u9001",
|
|
2975
|
+
title: cfg.feishuEnabled ? "\u5173\u95ED\u98DE\u4E66\u63A8\u9001" : "\u5F00\u542F\u98DE\u4E66\u63A8\u9001",
|
|
2976
|
+
onClick: () => patch({ feishuEnabled: !cfg.feishuEnabled })
|
|
2977
|
+
}
|
|
2978
|
+
)
|
|
2979
|
+
] })
|
|
2980
|
+
] }),
|
|
2981
|
+
cfg.feishuEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-rows-narrow", children: [
|
|
2982
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row dkan-row-webhook", children: [
|
|
2983
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "Webhook" }),
|
|
2984
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2985
|
+
"input",
|
|
2986
|
+
{
|
|
2987
|
+
type: "text",
|
|
2988
|
+
className: "dkan-input",
|
|
2989
|
+
spellCheck: false,
|
|
2990
|
+
value: cfg.feishuWebhook || "",
|
|
2991
|
+
placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/\u2026",
|
|
2992
|
+
onChange: (e) => {
|
|
2993
|
+
editingFeishuRef.current = true;
|
|
2994
|
+
setCfg(Object.assign({}, cfg, { feishuWebhook: e.target.value }));
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
),
|
|
2998
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2999
|
+
"button",
|
|
3000
|
+
{
|
|
3001
|
+
type: "button",
|
|
3002
|
+
className: "dkan-btn",
|
|
3003
|
+
disabled: !editingFeishuRef.current,
|
|
3004
|
+
onClick: saveFeishuWebhook,
|
|
3005
|
+
children: editingFeishuRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
|
|
3006
|
+
}
|
|
3007
|
+
)
|
|
3008
|
+
] }),
|
|
3009
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
3010
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
|
|
3011
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-btn", disabled: feishuTesting, onClick: runFeishuTest, children: feishuTesting ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
|
|
3012
|
+
feishuTestState ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-row-sub" + (feishuTestState.ok ? " dkan-ok" : " dkan-err"), children: [
|
|
3013
|
+
feishuTestState.ok ? "\u2713 " : "\u2717 ",
|
|
3014
|
+
feishuTestState.msg
|
|
3015
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
|
|
3016
|
+
] }),
|
|
3017
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u98DE\u4E66\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u7FA4\u673A\u5668\u4EBA \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\u673A\u5668\u4EBA\uFF08\u83B7\u53D6 Webhook \u5730\u5740\uFF09\uFF1B \u5B89\u5168\u8BBE\u7F6E\u5982\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
|
|
3018
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u98DE\u4E66\u3002" })
|
|
3019
|
+
] }, "feishu")
|
|
3020
|
+
);
|
|
3021
|
+
}
|
|
3022
|
+
if (saveErr) rows.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note dkan-err", children: saveErr }, "err"));
|
|
3023
|
+
rows.push(
|
|
3024
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
3025
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
3026
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u8FD0\u884C\u72B6\u6001" }),
|
|
3027
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: snap.error ? "\u72B6\u6001\u62C9\u53D6\u5931\u8D25\uFF1A" + snap.error : active.length > 0 ? active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D" : recent.length > 0 ? "\u7A7A\u95F2 \xB7 \u663E\u793A\u6700\u8FD1\u5B8C\u6210" : "\u7A7A\u95F2 \xB7 \u6682\u65E0\u4EFB\u52A1\u8BB0\u5F55" }),
|
|
3028
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-refresh", onClick: () => animationStore.refresh(), children: snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0" })
|
|
3029
|
+
] }),
|
|
3030
|
+
active.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-tasks", children: active.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TaskRow, { t }, t.sessionId)) }) : null,
|
|
3031
|
+
active.length === 0 && recent.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u53D1\u8D77\u65B0\u4F1A\u8BDD\u4EFB\u52A1\u540E\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u8FDB\u884C\u4E2D\u4E0E\u6700\u8FD1\u5B8C\u6210\u7684\u4EFB\u52A1\uFF1B\u52A8\u753B\u4E0E\u901A\u77E5\u540C\u65F6\u5728\u9875\u9762\u751F\u6548\u3002" }) : null,
|
|
3032
|
+
recent.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-tasks dkan-tasks-done", children: recent.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TaskRow, { t, done: true }, t.sessionId + ":" + t.endTime)) }) : null
|
|
3033
|
+
] }, "state")
|
|
3034
|
+
);
|
|
3035
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-root", children: rows });
|
|
3036
|
+
}
|
|
3037
|
+
function AnimationStat(props) {
|
|
3038
|
+
const snap = useAnimation(props && props.ctx);
|
|
3039
|
+
const st = snap.status;
|
|
3040
|
+
if (snap.error) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-err", children: "\u4EFB\u52A1\u72B6\u6001\u4E0D\u53EF\u7528\uFF08\u5BBF\u4E3B\u9700\u91CD\u542F\u52A0\u8F7D\u52A8\u753B\u8DEF\u7531\uFF09" });
|
|
3041
|
+
if (!st) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u7B49\u5F85\u4EFB\u52A1\u72B6\u6001\u2026" });
|
|
3042
|
+
if (st.active && st.active.length > 0) {
|
|
3043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: st.active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 " + fmtDur(Math.max(...st.active.map((x) => x.elapsed || 0))) });
|
|
3044
|
+
}
|
|
3045
|
+
const last = st.recent && st.recent[0];
|
|
3046
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: last ? "\u7A7A\u95F2 \xB7 \u6700\u8FD1\u5B8C\u6210 " + truncate(last.title, 24) : "\u7A7A\u95F2 \xB7 \u6682\u65E0\u4EFB\u52A1\u8BB0\u5F55" });
|
|
3047
|
+
}
|
|
3048
|
+
var css2 = [
|
|
3049
|
+
// 顶部流光细线(3px,比首版更醒目)
|
|
3050
|
+
".dkan-line{position:fixed;top:0;left:0;right:0;height:3px;z-index:9990;pointer-events:none;background:color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 30%,transparent);}",
|
|
3051
|
+
'.dkan-line::after{content:"";position:absolute;top:0;bottom:0;left:-42%;width:42%;background:linear-gradient(90deg,transparent,var(--dsw-alias-accent,#4d9fff) 60%,#fff);box-shadow:0 0 10px 1px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 70%,transparent);animation:dkan-flow calc(1.9s / var(--dkan-speed,1)) linear infinite;}',
|
|
3052
|
+
"@keyframes dkan-flow{to{left:100%}}",
|
|
3053
|
+
// 完成瞬间的一次性流光(成功绿 / 异常红),动画结束自动清场
|
|
3054
|
+
".dkan-done{position:fixed;top:0;left:0;right:0;height:3px;z-index:9991;pointer-events:none;background:linear-gradient(90deg,transparent,var(--dsw-alias-state-success-primary,#34d399) 50%,#fff);background-size:50% 100%;background-repeat:no-repeat;animation:dkan-done 1.1s var(--ds-ease-in-out) forwards;}",
|
|
3055
|
+
".dkan-done.err{background-image:linear-gradient(90deg,transparent,var(--dsw-alias-state-error-primary,#f87171) 50%,#fff);}",
|
|
3056
|
+
"@keyframes dkan-done{0%{background-position:-60% 0;opacity:0}25%{opacity:1}100%{background-position:160% 0;opacity:0}}",
|
|
3057
|
+
// 环屏巡航:光点沿屏幕边缘转一整圈
|
|
3058
|
+
".dkan-orbit{position:fixed;top:0;left:0;width:12px;height:12px;z-index:9990;pointer-events:none;border-radius:50%;background:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 14px 4px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 60%,transparent),0 0 30px 8px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 25%,transparent);animation:dkan-orbit calc(14s / var(--dkan-speed,1)) linear infinite;}",
|
|
3059
|
+
"@keyframes dkan-orbit{0%{top:0;left:0}25%{top:0;left:calc(100vw - 12px)}50%{top:calc(100vh - 12px);left:calc(100vw - 12px)}75%{top:calc(100vh - 12px);left:0}100%{top:0;left:0}}",
|
|
3060
|
+
// ===== 氛围动效 =====
|
|
3061
|
+
".dkan-amb{position:fixed;inset:0;z-index:9989;pointer-events:none;overflow:hidden;}",
|
|
3062
|
+
// pointer-events 不继承:全屏装饰层的子粒子(星点/流星/极光/火花/彩带)必须各自透明于点击
|
|
3063
|
+
".dkan-amb *,.dkan-fxwrap *{pointer-events:none;}",
|
|
3064
|
+
// 代码雨:字符列缓落(提亮加大,速度随吞吐)
|
|
3065
|
+
".dkan-matrix span{position:absolute;top:-12%;writing-mode:vertical-rl;font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-accent,#4d9fff);text-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 60%,transparent);animation:dkan-fall linear infinite;will-change:transform;}",
|
|
3066
|
+
"@keyframes dkan-fall{to{transform:translateY(125vh)}}",
|
|
3067
|
+
// 星野:星点缓慢飘移 + 闪烁(加亮加发光)+ 月亮 + 流星
|
|
3068
|
+
".dkan-stars .dkan-star{position:absolute;border-radius:50%;background:#cfe3ff;box-shadow:0 0 4px 1px color-mix(in srgb,#8ab6ff 55%,transparent);animation:dkan-star ease-in-out infinite alternate;}",
|
|
3069
|
+
"@keyframes dkan-star{0%{opacity:.3;transform:translate(0,0)}50%{opacity:1}100%{opacity:.45;transform:translate(var(--dx),var(--dy))}}",
|
|
3070
|
+
// 月亮:右上弯月(radial-gradient 咬出月牙,透明区不遮挡背景;外圈柔光晕)
|
|
3071
|
+
".dkan-moon{position:absolute;top:9%;right:10%;width:36px;height:36px;border-radius:50%;background:radial-gradient(circle at 66% 34%,transparent 0 44%,#fdf6d8 46%,#e8d9a0 78%,#d8c78a);box-shadow:0 0 18px 4px color-mix(in srgb,#fdf6d8 35%,transparent),0 0 44px 12px color-mix(in srgb,#fdf6d8 15%,transparent);}",
|
|
3072
|
+
// 流星:斜向划过的光带(亮头 + 渐隐尾),周期出现
|
|
3073
|
+
".dkan-meteor{position:absolute;width:110px;height:2px;border-radius:2px;background:linear-gradient(90deg,#fff,color-mix(in srgb,#8ab6ff 60%,transparent) 40%,transparent);transform:rotate(35deg);transform-origin:left center;opacity:0;animation:dkan-meteor 8.4s linear infinite;}",
|
|
3074
|
+
'.dkan-meteor::before{content:"";position:absolute;left:-2px;top:-2px;width:6px;height:6px;border-radius:50%;background:#fff;box-shadow:0 0 8px 2px color-mix(in srgb,#cfe3ff 70%,transparent);}',
|
|
3075
|
+
"@keyframes dkan-meteor{0%{opacity:0;transform:rotate(35deg) translateX(0)}3%{opacity:1}10%{opacity:0;transform:rotate(35deg) translateX(46vh)}100%{opacity:0;transform:rotate(35deg) translateX(46vh)}}",
|
|
3076
|
+
// 极光:顶部柔光带呼吸流动(加浓)
|
|
3077
|
+
".dkan-aurora i{position:absolute;top:-40%;left:-20%;width:70%;height:80%;border-radius:50%;filter:blur(50px);opacity:.32;animation:dkan-aurora ease-in-out infinite alternate;}",
|
|
3078
|
+
".dkan-aurora i:nth-child(1){background:#4d9fff;}",
|
|
3079
|
+
".dkan-aurora i:nth-child(2){background:#34d399;left:20%;animation-delay:-2s;}",
|
|
3080
|
+
".dkan-aurora i:nth-child(3){background:#a78bfa;left:55%;animation-delay:-4s;}",
|
|
3081
|
+
"@keyframes dkan-aurora{0%{transform:translateX(-8%) scaleY(1)}100%{transform:translateX(10%) scaleY(1.3)}}",
|
|
3082
|
+
// ===== 交互反馈层 =====
|
|
3083
|
+
".dkan-fxwrap{position:fixed;inset:0;z-index:9992;pointer-events:none;overflow:hidden;}",
|
|
3084
|
+
".dkan-fx{position:absolute;}",
|
|
3085
|
+
// 纸飞机:从点击处向右上飞出淡出(加大加亮)
|
|
3086
|
+
".dkan-fx-plane{color:var(--dsw-alias-accent,#4d9fff);font-size:24px;text-shadow:0 0 8px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 70%,transparent);animation:dkan-plane 1.2s var(--ds-ease-in-out) forwards;}",
|
|
3087
|
+
"@keyframes dkan-plane{0%{opacity:0;transform:translate(0,0) rotate(-20deg) scale(.6)}15%{opacity:1;transform:translate(20px,-14px) rotate(-20deg) scale(1.1)}100%{opacity:0;transform:translate(240px,-160px) rotate(-20deg) scale(1)}}",
|
|
3088
|
+
// 火花:粒子四散(加大加多散得更开)
|
|
3089
|
+
".dkan-fx-spark i{position:absolute;width:7px;height:7px;border-radius:50%;box-shadow:0 0 6px currentColor;animation:dkan-spark .9s var(--ds-ease-in-out) forwards;}",
|
|
3090
|
+
"@keyframes dkan-spark{0%{opacity:1;transform:translate(0,0) scale(1)}100%{opacity:0;transform:translate(var(--dx),var(--dy)) scale(.4)}}",
|
|
3091
|
+
// 流光:横向扫过(切会话,加高加亮)
|
|
3092
|
+
".dkan-fx-streak{top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,transparent,var(--dsw-alias-accent,#4d9fff) 50%,#fff);background-size:45% 100%;background-repeat:no-repeat;box-shadow:0 0 12px 2px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 50%,transparent);animation:dkan-streak 1s var(--ds-ease-in-out) forwards;}",
|
|
3093
|
+
"@keyframes dkan-streak{0%{background-position:-50% 0;opacity:0}20%{opacity:1}100%{background-position:150% 0;opacity:0}}",
|
|
3094
|
+
// 微光:全屏柔光一闪(切工作目录,加浓)
|
|
3095
|
+
".dkan-fx-flash{inset:0;background:radial-gradient(ellipse at center,color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 26%,transparent),transparent 75%);animation:dkan-flash .8s var(--ds-ease-in-out) forwards;}",
|
|
3096
|
+
"@keyframes dkan-flash{0%{opacity:0}30%{opacity:1}100%{opacity:0}}",
|
|
3097
|
+
// 光涌:底部向上涌起(任务开始,加高加浓)
|
|
3098
|
+
".dkan-fx-surge{left:0;right:0;bottom:0;height:42%;background:linear-gradient(0deg,color-mix(in srgb,var(--dsw-alias-state-success-primary,#34d399) 38%,transparent),transparent);animation:dkan-surge 1.2s var(--ds-ease-in-out) forwards;}",
|
|
3099
|
+
"@keyframes dkan-surge{0%{opacity:0;transform:translateY(45%)}30%{opacity:1}100%{opacity:0;transform:translateY(-35%)}}",
|
|
3100
|
+
// 彩带:顶部飘落(任务完成庆祝,加大加多)
|
|
3101
|
+
".dkan-fx-confetti{inset:0;}",
|
|
3102
|
+
".dkan-fx-confetti i{position:absolute;top:-14px;width:8px;height:13px;border-radius:2px;box-shadow:0 0 4px currentColor;animation:dkan-confetti 2s var(--ds-ease-in-out) forwards;}",
|
|
3103
|
+
"@keyframes dkan-confetti{0%{opacity:1;transform:translateY(0) rotate(0)}100%{opacity:0;transform:translateY(75vh) translateX(var(--dx)) rotate(var(--r))}}",
|
|
3104
|
+
// 右下角状态徽标(玻璃拟态,可点击);抬到 dsh 输入卡上方避免重叠错位
|
|
3105
|
+
".dkan-badge{position:fixed;right:20px;bottom:calc(var(--dsh-composer-height,152px) + 20px);z-index:9990;display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border-radius:999px;cursor:pointer;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 78%,transparent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 6px 24px rgb(0 0 0 / .16);color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;line-height:18px;pointer-events:auto;animation:dkan-rise .3s var(--ds-ease-in-out);transition:color .15s var(--ds-ease-in-out);}",
|
|
3106
|
+
".dkan-badge:hover{color:var(--dsw-alias-label-primary);}",
|
|
3107
|
+
".dkan-badge .n{color:var(--dsw-alias-label-primary);font-weight:600;}",
|
|
3108
|
+
"@keyframes dkan-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}",
|
|
3109
|
+
// 徽标圆点与两种动效(呼吸 / 轨道环)
|
|
3110
|
+
".dkan-dotwrap{position:relative;width:20px;height:20px;flex:none;display:inline-flex;align-items:center;justify-content:center;}",
|
|
3111
|
+
".dkan-dot{width:12px;height:12px;border-radius:50%;background:var(--dkan-phase,var(--dsw-alias-accent,#4d9fff));box-shadow:0 0 10px color-mix(in srgb,var(--dkan-phase,var(--dsw-alias-accent,#4d9fff)) 70%,transparent);transition:background .4s var(--ds-ease-in-out),box-shadow .4s var(--ds-ease-in-out);}",
|
|
3112
|
+
".dkan-breathe .dkan-dot{animation:dkan-breathe calc(2.2s / var(--dkan-speed,1)) ease-in-out infinite;}",
|
|
3113
|
+
"@keyframes dkan-breathe{0%,100%{transform:scale(1);opacity:.5}50%{transform:scale(1.7);opacity:1}}",
|
|
3114
|
+
// 呼吸光晕:向外扩散的波纹环,与圆点同频(颜色随阶段)
|
|
3115
|
+
".dkan-halo{position:absolute;inset:0;border-radius:50%;border:2px solid var(--dkan-phase,var(--dsw-alias-accent,#4d9fff));animation:dkan-halo calc(2.2s / var(--dkan-speed,1)) ease-out infinite;}",
|
|
3116
|
+
"@keyframes dkan-halo{0%{transform:scale(.5);opacity:.9}70%{transform:scale(1.5);opacity:.25}100%{transform:scale(1.7);opacity:0}}",
|
|
3117
|
+
// breathe 模式徽标更醒目:阶段色描边 + 呼吸辉光
|
|
3118
|
+
".dkan-badge-breathe{border-color:color-mix(in srgb,var(--dkan-phase,#4d9fff) 55%,transparent);animation:dkan-rise .3s var(--ds-ease-in-out),dkan-badge-breathe calc(2.2s / var(--dkan-speed,1)) ease-in-out infinite;}",
|
|
3119
|
+
"@keyframes dkan-badge-breathe{0%,100%{box-shadow:0 0 6px color-mix(in srgb,var(--dkan-phase,#4d9fff) 22%,transparent),0 6px 24px rgb(0 0 0 / .16)}50%{box-shadow:0 0 18px color-mix(in srgb,var(--dkan-phase,#4d9fff) 55%,transparent),0 6px 24px rgb(0 0 0 / .16)}}",
|
|
3120
|
+
".dkan-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,transparent 0 68%,var(--dsw-alias-accent,#4d9fff) 92%,#fff);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));animation:dkan-spin calc(2.2s / var(--dkan-speed,1)) linear infinite;opacity:.9;}",
|
|
3121
|
+
"@keyframes dkan-spin{to{transform:rotate(360deg)}}",
|
|
3122
|
+
// 通知卡片栈(右上角)
|
|
3123
|
+
".dkan-toasts{position:fixed;top:16px;right:16px;z-index:9995;display:flex;flex-direction:column;gap:8px;width:min(380px,calc(100vw - 32px));}",
|
|
3124
|
+
".dkan-toast{border-radius:12px;padding:12px 14px;pointer-events:auto;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 88%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--dsw-alias-border-l1);box-shadow:0 10px 36px rgb(0 0 0 / .22);animation:dkan-toast-in .32s var(--ds-ease-in-out);}",
|
|
3125
|
+
".dkan-toast.out{animation:dkan-toast-out .24s var(--ds-ease-in-out) forwards;}",
|
|
3126
|
+
"@keyframes dkan-toast-in{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}",
|
|
3127
|
+
"@keyframes dkan-toast-out{to{opacity:0;transform:translateX(10px)}}",
|
|
3128
|
+
".dkan-toast-head{display:flex;align-items:center;gap:8px;margin-bottom:4px;}",
|
|
3129
|
+
".dkan-toast-mark{width:8px;height:8px;border-radius:50%;flex:none;}",
|
|
3130
|
+
".dkan-toast-title{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
3131
|
+
".dkan-toast-close{cursor:pointer;flex:none;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:6px;width:22px;height:22px;font-size:11px;line-height:1;display:inline-flex;align-items:center;justify-content:center;font-family:inherit;}",
|
|
3132
|
+
".dkan-toast-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
3133
|
+
".dkan-toast-body{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.7;white-space:pre-line;word-break:break-word;}",
|
|
3134
|
+
// 面板页布局
|
|
3135
|
+
".dkan-root{display:flex;flex-direction:column;gap:10px;}",
|
|
3136
|
+
".dkan-note{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;}",
|
|
3137
|
+
".dkan-err{color:var(--dsw-alias-state-error-primary);}",
|
|
3138
|
+
".dkan-sec{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:8px;}",
|
|
3139
|
+
".dkan-sec-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}",
|
|
3140
|
+
".dkan-sec-title{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary);flex:none;}",
|
|
3141
|
+
".dkan-sec-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);flex:1;min-width:120px;}",
|
|
3142
|
+
".dkan-sec-sw{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:8px;}",
|
|
3143
|
+
".dkan-sec-swlabel{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;}",
|
|
3144
|
+
".dkan-sec-swlabel.on{color:var(--dsw-alias-state-success-primary);}",
|
|
3145
|
+
".dkan-refresh{cursor:pointer;flex:none;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:2px 10px;font-family:inherit;font-size:12px;}",
|
|
3146
|
+
".dkan-refresh:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3147
|
+
// 模式选择卡(带缩微预览)
|
|
3148
|
+
".dkan-modes{display:flex;gap:8px;flex-wrap:wrap;}",
|
|
3149
|
+
".dkan-mode{flex:1;min-width:150px;display:flex;flex-direction:column;gap:6px;padding:10px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-2);cursor:pointer;font-family:inherit;text-align:left;transition:border-color .15s var(--ds-ease-in-out);}",
|
|
3150
|
+
".dkan-mode:hover{border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3151
|
+
".dkan-mode.on{border-color:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 0 1px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 40%,transparent);}",
|
|
3152
|
+
".dkan-mode-name{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:6px;}",
|
|
3153
|
+
'.dkan-mode.on .dkan-mode-name::after{content:"\u2713";color:var(--dsw-alias-accent,#4d9fff);}',
|
|
3154
|
+
".dkan-mode-desc{font-size:11px;color:var(--dsw-alias-label-tertiary);line-height:1.5;}",
|
|
3155
|
+
".dkan-robot-controls{display:flex;flex-direction:column;gap:8px;padding:9px 10px;border:1px solid color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 28%,var(--dsw-alias-border-l1));border-radius:9px;background:color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 5%,var(--dsw-alias-bg-layer-2));}",
|
|
3156
|
+
".dkan-robot-controls-head{display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--dsw-alias-label-primary);}",
|
|
3157
|
+
".dkan-robot-controls-head strong{font-variant-numeric:tabular-nums;color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3158
|
+
".dkan-robot-size-options{display:flex;gap:6px;flex-wrap:wrap;}",
|
|
3159
|
+
".dkan-robot-size-options button{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:3px 10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font:inherit;font-size:11px;}",
|
|
3160
|
+
".dkan-robot-size-options button:hover,.dkan-robot-size-options button.on{border-color:var(--dsw-alias-accent,#4d9fff);color:var(--dsw-alias-label-primary);}",
|
|
3161
|
+
".dkan-robot-slider-row{display:flex;align-items:center;gap:9px;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
3162
|
+
".dkan-robot-slider-row input{accent-color:var(--dsw-alias-accent,#4d9fff);width:min(240px,100%);}",
|
|
3163
|
+
".dkan-prev{height:30px;border-radius:6px;background:var(--dsw-alias-bg-layer-1);position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;}",
|
|
3164
|
+
".dkan-prev-flow{position:absolute;top:0;left:0;right:0;height:3px;background:color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 30%,transparent);}",
|
|
3165
|
+
'.dkan-prev-flow::after{content:"";position:absolute;top:0;bottom:0;left:-40%;width:40%;background:linear-gradient(90deg,transparent,var(--dsw-alias-accent,#4d9fff));animation:dkan-flow 1.9s linear infinite;}',
|
|
3166
|
+
".dkan-prev-box{--dkan-speed:1;}",
|
|
3167
|
+
".dkan-prev-orbit{position:absolute;top:3px;left:3px;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 7px 2px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 55%,transparent);animation:dkan-prev-orbit 3s linear infinite;}",
|
|
3168
|
+
"@keyframes dkan-prev-orbit{0%{top:3px;left:3px}25%{top:3px;left:calc(100% - 10px)}50%{top:calc(100% - 10px);left:calc(100% - 10px)}75%{top:calc(100% - 10px);left:3px}100%{top:3px;left:3px}}",
|
|
3169
|
+
// 预览:代码雨(字符列下落)
|
|
3170
|
+
".dkan-prev-matrix i{position:absolute;top:-100%;writing-mode:vertical-rl;font-size:8px;font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-accent,#4d9fff);opacity:.5;animation:dkan-prev-fall 2.2s linear infinite;}",
|
|
3171
|
+
".dkan-prev-matrix i:nth-child(1){left:12%;}",
|
|
3172
|
+
".dkan-prev-matrix i:nth-child(2){left:32%;animation-delay:-.6s;}",
|
|
3173
|
+
".dkan-prev-matrix i:nth-child(3){left:52%;animation-delay:-1.2s;}",
|
|
3174
|
+
".dkan-prev-matrix i:nth-child(4){left:72%;animation-delay:-.3s;}",
|
|
3175
|
+
".dkan-prev-matrix i:nth-child(5){left:88%;animation-delay:-1.6s;}",
|
|
3176
|
+
'.dkan-prev-matrix i::after{content:"01</>";}',
|
|
3177
|
+
"@keyframes dkan-prev-fall{to{transform:translateY(300%)}}",
|
|
3178
|
+
// 预览:星野(星点闪烁)
|
|
3179
|
+
".dkan-prev-stars i{position:absolute;width:2px;height:2px;border-radius:50%;background:var(--dsw-alias-label-secondary);animation:dkan-prev-star 1.6s ease-in-out infinite alternate;}",
|
|
3180
|
+
".dkan-prev-stars i:nth-child(1){left:15%;top:25%;}",
|
|
3181
|
+
".dkan-prev-stars i:nth-child(2){left:40%;top:60%;animation-delay:-.4s;}",
|
|
3182
|
+
".dkan-prev-stars i:nth-child(3){left:60%;top:30%;animation-delay:-.8s;}",
|
|
3183
|
+
".dkan-prev-stars i:nth-child(4){left:80%;top:55%;animation-delay:-1.2s;}",
|
|
3184
|
+
".dkan-prev-stars i:nth-child(5){left:28%;top:70%;animation-delay:-.6s;}",
|
|
3185
|
+
".dkan-prev-stars i:nth-child(6){left:70%;top:75%;animation-delay:-1s;}",
|
|
3186
|
+
"@keyframes dkan-prev-star{0%{opacity:.2}100%{opacity:.9}}",
|
|
3187
|
+
// 预览:极光(柔光带呼吸)
|
|
3188
|
+
".dkan-prev-aurora i{position:absolute;top:-30%;width:60%;height:120%;border-radius:50%;filter:blur(8px);opacity:.35;animation:dkan-prev-aurora 2.4s ease-in-out infinite alternate;}",
|
|
3189
|
+
".dkan-prev-aurora i:nth-child(1){left:5%;background:#4d9fff;}",
|
|
3190
|
+
".dkan-prev-aurora i:nth-child(2){left:45%;background:#34d399;animation-delay:-1.2s;}",
|
|
3191
|
+
"@keyframes dkan-prev-aurora{0%{transform:translateX(-10%)}100%{transform:translateX(15%)}}",
|
|
3192
|
+
".dkan-prev-bot{height:92px;justify-content:center;}",
|
|
3193
|
+
".dkan-prev-bot .dkan-bot-scene{--dkan-bot-scale:1;transform:scale(.56);transform-origin:center;}",
|
|
3194
|
+
// ===== 桌面伙伴:具象人物 + 紧凑双工位(尺寸可调,整卡可拖拽) =====
|
|
3195
|
+
// 卡片:玻璃拟态;默认停泊右下(dsh 输入卡上方),拖动后位置持久化、可放屏幕任意处
|
|
3196
|
+
".dkan-botcard{--dkan-bot-scale:1.35;position:fixed;right:20px;bottom:calc(var(--dsh-composer-height,152px) + 20px);z-index:9990;display:flex;flex-direction:column;gap:6px;padding:10px 12px;border-radius:16px;cursor:grab;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 86%,transparent);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 12px 36px rgb(0 0 0 / .22);color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;pointer-events:auto;touch-action:none;user-select:none;animation:dkan-rise .3s var(--ds-ease-in-out);}",
|
|
3197
|
+
".dkan-botcard:hover,.dkan-botcard:focus-visible{border-color:var(--dsw-alias-accent,#4d9fff);outline:none;}",
|
|
3198
|
+
".dkan-botcard.dkan-dragging{cursor:grabbing;animation:none;}",
|
|
3199
|
+
".dkan-botcard .n{color:var(--dsw-alias-label-primary);font-weight:600;}",
|
|
3200
|
+
".dkan-bot-cap{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:18px;}",
|
|
3201
|
+
".dkan-bot-resize{position:absolute;right:7px;bottom:7px;width:15px;height:15px;padding:0;border:0;border-radius:4px;background:linear-gradient(135deg,transparent 0 42%,var(--dsw-alias-label-tertiary) 44% 51%,transparent 53% 62%,var(--dsw-alias-label-tertiary) 64% 71%,transparent 73%);cursor:nwse-resize;touch-action:none;opacity:.72;}",
|
|
3202
|
+
".dkan-bot-resize:hover,.dkan-bot-resize:focus-visible{opacity:1;outline:1px solid var(--dsw-alias-accent,#4d9fff);outline-offset:1px;}",
|
|
3203
|
+
// ===== 3D 场景(CSS 长方体拼装:世界层统一 3/4 视角——俯视 + 侧身面向镜头) =====
|
|
3204
|
+
".dkan-bot-scene{position:relative;width:calc(220px * var(--dkan-bot-scale,1));height:calc(132px * var(--dkan-bot-scale,1));perspective:calc(620px * var(--dkan-bot-scale,1));perspective-origin:55% 18%;--dk3-side:#7c8ba0;--dk3-side-hi:#a9b8ca;--dk3-side-dk:#4c5870;--dk3-screen:#0d1526;--dkan-code-a:#4ade80;--dkan-code-b:#60a5fa;--dkan-code-c:#fbbf24;}",
|
|
3205
|
+
".dk3-world{position:absolute;left:0;top:0;width:220px;height:132px;transform-style:preserve-3d;transform-origin:top left;transform:scale(var(--dkan-bot-scale,1)) rotateX(-15deg) rotateY(-30deg);}",
|
|
3206
|
+
".dk3-box{position:absolute;transform-style:preserve-3d;}",
|
|
3207
|
+
".dk3-face{position:absolute;left:50%;top:50%;display:block;background:var(--dk3-side);backface-visibility:hidden;border-radius:1px;}",
|
|
3208
|
+
// 金属件着色:顶面亮、底面暗,正/侧面中调(3D 光感)
|
|
3209
|
+
".dk3-metal .dk3-face{background:linear-gradient(180deg,#93a5ba,#71809a);}",
|
|
3210
|
+
".dk3-metal .dk3-face:nth-child(5){background:linear-gradient(180deg,var(--dk3-side-hi),#9dadc2);}",
|
|
3211
|
+
".dk3-metal .dk3-face:nth-child(6){background:var(--dk3-side-dk);}",
|
|
3212
|
+
// 书桌与桌腿
|
|
3213
|
+
".dk3-desk .dk3-face{background:linear-gradient(180deg,#9db0c6,#7f92aa);}",
|
|
3214
|
+
".dk3-desk .dk3-face:nth-child(5){background:#c3d2e2;}",
|
|
3215
|
+
// 显示器(薄盒 + 贴在前面的屏幕;组内扇形微转,整组后撤出桌沿)
|
|
3216
|
+
".dk3-mon3{position:absolute;transform-style:preserve-3d;}",
|
|
3217
|
+
".dk3-frame .dk3-face{background:#3a465b;}",
|
|
3218
|
+
".dk3-frame .dk3-face:nth-child(5){background:#55647d;}",
|
|
3219
|
+
".dk3-screen{position:absolute;left:50%;top:50%;background:var(--dk3-screen);border-radius:2px;overflow:hidden;transition:opacity .4s var(--ds-ease-in-out),box-shadow .4s var(--ds-ease-in-out);}",
|
|
3220
|
+
// 屏幕内容:代码块整体向上滚动(10 行=5 行×2 循环,滚半程无缝接回)+ 闪烁光标,速度随 --dkan-speed
|
|
3221
|
+
".dk3-code{position:absolute;left:0;top:0;right:0;display:block;animation:dk3-scroll calc(5s / var(--dkan-speed,1)) linear infinite;}",
|
|
3222
|
+
".dk3-code i{display:block;height:2px;border-radius:1px;margin:2px 3px 0;background:var(--dkan-code-b);opacity:.55;}",
|
|
3223
|
+
".dk3-code i:nth-child(5n+1){width:58%;background:var(--dkan-code-a);}",
|
|
3224
|
+
".dk3-code i:nth-child(5n+2){width:82%;}",
|
|
3225
|
+
".dk3-code i:nth-child(5n+3){width:46%;background:var(--dkan-code-c);}",
|
|
3226
|
+
".dk3-code i:nth-child(5n+4){width:72%;}",
|
|
3227
|
+
".dk3-code i:nth-child(5n){width:54%;background:var(--dkan-code-a);}",
|
|
3228
|
+
".dk3-cur{position:absolute;left:3px;bottom:2px;width:4px;height:2px;background:var(--dkan-code-b);animation:dkan-blink3 1s steps(1) infinite;}",
|
|
3229
|
+
// 左屏检索视图:搜索框、放大镜与结果条,和右侧代码编辑器明确区分
|
|
3230
|
+
".dk3-search-ui{position:absolute;inset:3px;display:block;overflow:hidden;}",
|
|
3231
|
+
".dk3-search-box{display:block;height:5px;margin:0 1px 3px;border:1px solid color-mix(in srgb,var(--dkan-code-a) 72%,#d7fff4);border-radius:2px;box-sizing:border-box;}",
|
|
3232
|
+
".dk3-search-box b{display:block;width:2px;height:2px;margin:1px 0 0 2px;border:1px solid var(--dkan-code-a);border-radius:50%;position:relative;}",
|
|
3233
|
+
".dk3-search-box b:after{content:'';position:absolute;width:2px;height:1px;background:var(--dkan-code-a);right:-2px;bottom:-1px;transform:rotate(45deg);transform-origin:left center;}",
|
|
3234
|
+
".dk3-search-results{display:block;animation:dk3-search-scroll calc(2.1s / var(--dkan-speed,1)) linear infinite;}",
|
|
3235
|
+
".dk3-search-results i{display:block;height:2px;margin:2px 1px 0;border-radius:1px;background:var(--dkan-code-a);opacity:.72;}",
|
|
3236
|
+
".dk3-search-results i:nth-child(2n){width:74%;background:var(--dkan-code-b);}",
|
|
3237
|
+
".dk3-search-results i:nth-child(3n){width:48%;background:var(--dkan-code-c);}",
|
|
3238
|
+
"@keyframes dk3-search-scroll{to{transform:translateY(-5px)}}",
|
|
3239
|
+
"@keyframes dk3-scroll{to{transform:translateY(-50%)}}",
|
|
3240
|
+
// 人物与椅子始终正对桌面:工位切换只横移,不再旋转整个人和座椅。
|
|
3241
|
+
".dk3-person{--dk3-seat-x:22px;position:absolute;left:98px;top:14px;width:44px;height:61px;transform-style:preserve-3d;transform:translateZ(30px) translateX(var(--dk3-seat-x));transition:transform max(.18s,calc(.38s / var(--dkan-speed,1))) cubic-bezier(.23,1,.32,1);will-change:transform;}",
|
|
3242
|
+
".dkan-bot-scene[data-station=left] .dk3-person{--dk3-seat-x:0px;}",
|
|
3243
|
+
".dkan-bot-scene[data-station=center] .dk3-person{--dk3-seat-x:22px;}",
|
|
3244
|
+
".dkan-bot-scene[data-station=right] .dk3-person{--dk3-seat-x:44px;}",
|
|
3245
|
+
// 上身以髋部为旋转原点;只做前后倾,始终朝向桌面。
|
|
3246
|
+
".dk3-upper3{position:absolute;inset:0;transform-style:preserve-3d;transform-origin:12px 52px;transform:translateZ(0);transition:transform .24s cubic-bezier(.77,0,.175,1);will-change:transform;}",
|
|
3247
|
+
// 动漫人物配色:皮肤/头发/卫衣/裤子
|
|
3248
|
+
".dk3-skin .dk3-face{background:linear-gradient(180deg,#ffd9b8,#f3b98d);}",
|
|
3249
|
+
".dk3-skin .dk3-face:nth-child(5){background:#ffe3c9;}",
|
|
3250
|
+
".dk3-hair .dk3-face{background:linear-gradient(180deg,#5b4632,#3f3021);}",
|
|
3251
|
+
".dk3-hair .dk3-face:nth-child(5){background:#6b543c;}",
|
|
3252
|
+
".dk3-hood .dk3-face{background:linear-gradient(180deg,#7c8ba0,#5b6a80);}",
|
|
3253
|
+
".dk3-hood .dk3-face:nth-child(5){background:#93a5ba;}",
|
|
3254
|
+
".dk3-pants .dk3-face{background:linear-gradient(180deg,#3d4a5c,#2c3646);}",
|
|
3255
|
+
".dk3-pants .dk3-face:nth-child(5){background:#4a5a70;}",
|
|
3256
|
+
// 人物细节:收窄下颌、连续肩颈、短侧渐层发型
|
|
3257
|
+
".dk3-cranium .dk3-face{border-radius:42% 46% 38% 36%;}",
|
|
3258
|
+
".dk3-jaw3 .dk3-face{border-radius:30% 30% 48% 48%;}",
|
|
3259
|
+
".dk3-neck3 .dk3-face{border-radius:2px;}",
|
|
3260
|
+
".dk3-collar3 .dk3-face{background:linear-gradient(180deg,#516176,#374459);border-radius:3px;}",
|
|
3261
|
+
".dk3-shoulders3 .dk3-face{border-radius:4px;}",
|
|
3262
|
+
".dk3-chest3 .dk3-face{border-radius:4px;}",
|
|
3263
|
+
".dk3-waist3 .dk3-face{border-radius:3px;}",
|
|
3264
|
+
".dk3-hair .dk3-face{border-radius:2px;}",
|
|
3265
|
+
".dk3-hair-crown .dk3-face{border-radius:48% 42% 28% 30%;}",
|
|
3266
|
+
".dk3-hair-back .dk3-face{background:linear-gradient(180deg,#493727,#2f241b);border-radius:46% 24% 38% 44%;}",
|
|
3267
|
+
".dk3-shoe .dk3-face{background:#20262f;border-radius:2px;}",
|
|
3268
|
+
".dk3-mug .dk3-face{background:#c2703d;border-radius:1px;}",
|
|
3269
|
+
".dk3-mug .dk3-face:nth-child(5){background:#e08a52;}",
|
|
3270
|
+
".dk3-mouth{position:absolute;left:50%;top:64%;width:3.5px;height:1px;border-radius:2px;background:#a9635c;}",
|
|
3271
|
+
// 椅子
|
|
3272
|
+
".dk3-chairback .dk3-face{background:linear-gradient(180deg,#3f4c60,#2c3648);}",
|
|
3273
|
+
".dk3-chairseat .dk3-face{background:#33415a;}",
|
|
3274
|
+
// 头组与颈部中心均为 x=14;只让头部观察左右屏,身体和椅子不转向。
|
|
3275
|
+
".dk3-head3{--dk3-head-turn:rotateY(0deg);position:absolute;left:6px;top:3px;width:17px;height:21px;transform-style:preserve-3d;transform-origin:8px 18px;transform:var(--dk3-head-turn);transition:transform max(.18s,calc(.22s / var(--dkan-speed,1))) cubic-bezier(.23,1,.32,1);will-change:transform;}",
|
|
3276
|
+
".dkan-bot-scene[data-station=left] .dk3-head3{--dk3-head-turn:rotateY(-18deg);}",
|
|
3277
|
+
".dkan-bot-scene[data-station=center] .dk3-head3{--dk3-head-turn:rotateY(0deg);}",
|
|
3278
|
+
".dkan-bot-scene[data-station=right] .dk3-head3{--dk3-head-turn:rotateY(14deg);}",
|
|
3279
|
+
".dk3-brows{position:absolute;left:50%;top:29%;display:flex;gap:2.5px;align-items:center;justify-content:center;}",
|
|
3280
|
+
".dk3-brows i{width:3.5px;height:1px;border-radius:2px;background:#3a2a21;transform:rotate(-7deg);}",
|
|
3281
|
+
".dk3-brows i+ i{transform:rotate(7deg);}",
|
|
3282
|
+
".dk3-eyes{position:absolute;left:50%;top:51%;display:flex;gap:2.5px;align-items:center;justify-content:center;}",
|
|
3283
|
+
".dk3-eyes i{width:3.5px;height:2.5px;border-radius:50%;background:radial-gradient(circle at 62% 30%,#fff 0 .5px,#263141 .8px 1.7px,#111827 1.9px);animation:dkan-blink3 4.8s infinite;}",
|
|
3284
|
+
".dk3-nose{position:absolute;left:50%;top:66%;width:2px;height:3px;border-radius:60% 40% 55% 45%;background:linear-gradient(90deg,#e7a67e,#c77f67);}",
|
|
3285
|
+
".dk3-ear{position:absolute;left:1px;top:10px;width:3px;height:5px;border-radius:52% 44% 48% 52%;background:linear-gradient(90deg,#edaa82,#ffd2ad);transform:translateZ(2px);}",
|
|
3286
|
+
".dk3-fringe3{position:absolute;left:13px;top:4px;width:5px;height:7px;transform-style:preserve-3d;transform:rotateY(90deg) translateZ(5.8px);}",
|
|
3287
|
+
".dk3-fringe3 i{position:absolute;top:0;width:2px;height:6px;border-radius:70% 25% 60% 30%;background:linear-gradient(180deg,#6b5239,#392b20);transform-origin:top center;}",
|
|
3288
|
+
".dk3-fringe3 i:nth-child(1){left:0;transform:rotate(-18deg);height:5px;}",
|
|
3289
|
+
".dk3-fringe3 i:nth-child(2){left:1.8px;transform:rotate(-6deg);height:6px;}",
|
|
3290
|
+
".dk3-fringe3 i:nth-child(3){left:3.5px;transform:rotate(12deg);height:4px;}",
|
|
3291
|
+
"@keyframes dkan-blink3{0%,91%,100%{transform:scaleY(1)}94%{transform:scaleY(.15)}}",
|
|
3292
|
+
// 手臂按肩→肘→腕分段,旋转原点位于真实关节连接处。
|
|
3293
|
+
".dk3-arm3{position:absolute;left:20px;top:30px;width:16px;height:16px;transform-style:preserve-3d;transform-origin:2px 2px;will-change:transform;}",
|
|
3294
|
+
".dk3-elbow{position:absolute;left:0;top:10px;width:15px;height:5px;transform-style:preserve-3d;transform-origin:1px 2px;will-change:transform;}",
|
|
3295
|
+
".dk3-wrist3{position:absolute;left:9.5px;top:0;width:6px;height:5px;transform-style:preserve-3d;transform-origin:1px 2px;will-change:transform;}",
|
|
3296
|
+
".dk3-fingers3{position:absolute;left:3px;top:1px;width:4px;height:3px;transform:translateZ(2px);}",
|
|
3297
|
+
".dk3-fingers3 i{position:absolute;left:0;width:4px;height:.8px;border-radius:2px;background:#f2b58d;}",
|
|
3298
|
+
".dk3-fingers3 i+ i{top:1.4px;width:3.5px;}",
|
|
3299
|
+
".dk3-far{transform:translateZ(-7px);filter:brightness(.72);}",
|
|
3300
|
+
// 思考泡泡(贴镜头 2D 层,think 阶段显示)
|
|
3301
|
+
".dkan-bubble{position:absolute;left:80px;top:4px;display:none;gap:3px;padding:4px 6px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);box-shadow:0 2px 6px rgb(0 0 0 / .15);z-index:3;}",
|
|
3302
|
+
".dkan-bubble i{width:4px;height:4px;border-radius:50%;background:var(--dsw-alias-label-tertiary);animation:dkan-bubdot 1.2s ease-in-out infinite;}",
|
|
3303
|
+
".dkan-bubble i:nth-child(2){animation-delay:.2s;}",
|
|
3304
|
+
".dkan-bubble i:nth-child(3){animation-delay:.4s;}",
|
|
3305
|
+
"@keyframes dkan-bubdot{0%,100%{opacity:.25;transform:translateY(0)}50%{opacity:1;transform:translateY(-2px)}}",
|
|
3306
|
+
// ===== 多任务工位(data-tasks=活跃任务数,上限 3) =====
|
|
3307
|
+
// 椅子滚轮
|
|
3308
|
+
".dk3-wheel .dk3-face{background:#1c232e;border-radius:50%;}",
|
|
3309
|
+
// 有活跃任务时,未轮到的侧工位稍暗;多任务则两个工位均保持可见。
|
|
3310
|
+
".dkan-bot-scene[data-tasks] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks] .dk3-mon3.right .dk3-screen{opacity:.3;}",
|
|
3311
|
+
// 2 个及以上任务:左右工位同时点亮(各自带辉光、代码滚动加速)。
|
|
3312
|
+
'.dkan-bot-scene[data-tasks="2"] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks="2"] .dk3-mon3.right .dk3-screen,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 8px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 42%,transparent);}',
|
|
3313
|
+
'.dkan-bot-scene[data-tasks="2"] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-tasks="2"] .dk3-mon3.right .dk3-code,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.right .dk3-code{animation-duration:calc(2.6s / var(--dkan-speed,1));}',
|
|
3314
|
+
// 座椅移动期间滚轮跟随任务节奏转动;思考中停下,避免无意义的常驻运动。
|
|
3315
|
+
".dkan-bot-scene[data-station=left] .dk3-wheel,.dkan-bot-scene[data-station=right] .dk3-wheel{animation:dkan-wheel calc(.46s / var(--dkan-speed,1)) linear infinite;transform-origin:center;}",
|
|
3316
|
+
"@keyframes dkan-wheel{to{transform:rotateZ(360deg)}}",
|
|
3317
|
+
// ===== 阶段驱动(data-phase 四态,host 由 chunk 流实时同步) =====
|
|
3318
|
+
// think:上身轻靠、近侧手托下巴、远侧手留在桌面;动作有停顿而不是机械往返。
|
|
3319
|
+
".dkan-bot-scene[data-phase=think] .dk3-screen{opacity:.32;}",
|
|
3320
|
+
".dkan-bot-scene[data-phase=think] .dkan-bubble{display:inline-flex;}",
|
|
3321
|
+
".dkan-bot-scene[data-phase=think] .dk3-upper3{animation:dkan-think-upper max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3322
|
+
".dkan-bot-scene[data-phase=think] .dk3-head3{animation:dkan-think-head max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3323
|
+
".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-near{animation:dkan-think-near max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3324
|
+
".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-far{transform:translateZ(-7px) rotateZ(3deg);}",
|
|
3325
|
+
".dkan-bot-scene[data-phase=think] .dk3-near .dk3-elbow{transform:rotateZ(-28deg) translateY(-1px);}",
|
|
3326
|
+
".dkan-bot-scene[data-phase=think] .dk3-near .dk3-wrist3{transform:rotateZ(-18deg) translateY(-1px);}",
|
|
3327
|
+
"@keyframes dkan-think-upper{0%,44%{transform:rotateZ(-1deg) translateY(0)}62%,100%{transform:rotateZ(-1.8deg) translateY(-.5px)}}",
|
|
3328
|
+
"@keyframes dkan-think-head{0%,44%{transform:var(--dk3-head-turn) rotateZ(-3deg)}62%,100%{transform:var(--dk3-head-turn) rotateZ(-6deg) translateY(-.5px)}}",
|
|
3329
|
+
"@keyframes dkan-think-near{0%,44%{transform:rotateZ(-31deg) translate(-8px,-14.5px)}62%,100%{transform:rotateZ(-34deg) translate(-8.5px,-15px)}}",
|
|
3330
|
+
// write/code:身体仍面向桌面,仅轻微前倾;主要由手腕和手指敲击。
|
|
3331
|
+
".dkan-bot-scene[data-phase=write] .dk3-mon3.right .dk3-screen,.dkan-bot-scene[data-phase=code] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 11px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 52%,transparent);}",
|
|
3332
|
+
".dkan-bot-scene[data-phase=write] .dk3-mon3.right .dk3-code,.dkan-bot-scene[data-phase=code] .dk3-mon3.right .dk3-code{animation-duration:calc(1.35s / var(--dkan-speed,1));}",
|
|
3333
|
+
".dkan-bot-scene[data-phase=write] .dk3-upper3,.dkan-bot-scene[data-phase=code] .dk3-upper3{animation:dkan-code-upper max(1.2s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3334
|
+
".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-near,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-near{transform:rotateZ(3deg);}",
|
|
3335
|
+
".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far{transform:translateZ(-7px) rotateZ(1deg);}",
|
|
3336
|
+
".dkan-bot-scene[data-phase=write] .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-elbow{animation:dkan-type-elbow max(.28s,calc(.58s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3337
|
+
".dkan-bot-scene[data-phase=write] .dk3-wrist3,.dkan-bot-scene[data-phase=code] .dk3-wrist3{animation:dkan-type-wrist max(.18s,calc(.29s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3338
|
+
".dkan-bot-scene[data-phase=write] .dk3-far .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-far .dk3-elbow{animation-delay:-.09s;animation-duration:max(.3s,calc(.63s / var(--dkan-speed,1)));}",
|
|
3339
|
+
".dkan-bot-scene[data-phase=write] .dk3-far .dk3-wrist3,.dkan-bot-scene[data-phase=code] .dk3-far .dk3-wrist3{animation-delay:-.09s;animation-duration:max(.2s,calc(.33s / var(--dkan-speed,1)));}",
|
|
3340
|
+
".dkan-bot-scene[data-phase=write] .dk3-head3,.dkan-bot-scene[data-phase=code] .dk3-head3{animation:dkan-output-head max(1.2s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3341
|
+
"@keyframes dkan-code-upper{0%,38%{transform:rotateZ(2deg) translate(1px,0)}62%,100%{transform:rotateZ(3deg) translate(1px,1px)}}",
|
|
3342
|
+
"@keyframes dkan-type-elbow{0%,38%{transform:rotateZ(-4deg)}62%,100%{transform:rotateZ(5deg) translateY(1px)}}",
|
|
3343
|
+
"@keyframes dkan-type-wrist{0%,34%{transform:rotateZ(-2deg) translateY(0)}62%,100%{transform:rotateZ(3deg) translateY(1.5px)}}",
|
|
3344
|
+
"@keyframes dkan-output-head{0%,46%,100%{transform:var(--dk3-head-turn) rotateZ(3deg)}58%{transform:var(--dk3-head-turn) rotateZ(5deg) translateY(1px)}}",
|
|
3345
|
+
// search:身体正对桌面,头看左屏,近侧手腕小幅操作鼠标。
|
|
3346
|
+
".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-screen{opacity:1;box-shadow:0 0 10px color-mix(in srgb,var(--dkan-code-a,#4ade80) 52%,transparent);}",
|
|
3347
|
+
".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-search-results{animation-duration:calc(1.05s / var(--dkan-speed,1));}",
|
|
3348
|
+
".dkan-bot-scene[data-phase=search] .dk3-upper3{transform:rotateZ(2deg) translateY(1px);}",
|
|
3349
|
+
".dkan-bot-scene[data-phase=search] .dk3-head3{animation:dkan-search-head max(.72s,calc(1.15s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3350
|
+
".dkan-bot-scene[data-phase=search] .dk3-near .dk3-wrist3{animation:dkan-search-wrist max(.45s,calc(.72s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
|
|
3351
|
+
".dkan-bot-scene[data-phase=search] .dk3-far{transform:translateZ(-7px) rotateZ(2deg);}",
|
|
3352
|
+
"@keyframes dkan-search-head{0%,28%{transform:var(--dk3-head-turn) rotateZ(1deg)}48%,68%{transform:var(--dk3-head-turn) rotateZ(6deg) translate(1px,1px)}88%,100%{transform:var(--dk3-head-turn) rotateZ(2deg)}}",
|
|
3353
|
+
"@keyframes dkan-search-wrist{0%,34%{transform:translateX(-1px)}62%,100%{transform:translateX(1.5px)}}",
|
|
3354
|
+
// 减少动态时停止空间位移,保留屏幕亮暗与思考状态的淡入反馈。
|
|
3355
|
+
"@media (prefers-reduced-motion:reduce){.dk3-person,.dk3-upper3,.dk3-head3,.dk3-arm3,.dk3-elbow,.dk3-wrist3,.dk3-wheel,.dk3-code,.dk3-search-results{animation:none!important;transition:none!important}.dk3-screen,.dkan-bubble{transition:opacity .2s cubic-bezier(.23,1,.32,1)!important}}",
|
|
3356
|
+
// 通知子选项行
|
|
3357
|
+
".dkan-rows-narrow{display:flex;flex-direction:column;gap:6px;}",
|
|
3358
|
+
".dkan-row{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary);flex-wrap:wrap;}",
|
|
3359
|
+
".dkan-row-label{flex:none;min-width:60px;color:var(--dsw-alias-label-primary);}",
|
|
3360
|
+
".dkan-row-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
3361
|
+
".dkm-miniswitch{cursor:pointer;flex:none;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 12px;font-family:inherit;font-size:11px;line-height:18px;}",
|
|
3362
|
+
".dkm-miniswitch.on{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
|
|
3363
|
+
".dkan-select{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:3px 8px;font-size:12px;font-family:inherit;}",
|
|
3364
|
+
// 音效选择卡(名称 + 播放键;选中态描边)
|
|
3365
|
+
".dkan-sounds{display:flex;gap:6px;flex-wrap:wrap;}",
|
|
3366
|
+
".dkan-sound{flex:1;min-width:104px;display:flex;align-items:center;justify-content:space-between;gap:6px;padding:6px 10px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-2);cursor:pointer;font-family:inherit;transition:border-color .15s var(--ds-ease-in-out);}",
|
|
3367
|
+
".dkan-sound:hover{border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3368
|
+
".dkan-sound.on{border-color:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 0 1px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 40%,transparent);}",
|
|
3369
|
+
".dkan-sound-name{font-size:12px;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:5px;}",
|
|
3370
|
+
".dkan-sound-cur{color:var(--dsw-alias-accent,#4d9fff);font-size:11px;}",
|
|
3371
|
+
".dkan-sound-play{flex:none;cursor:pointer;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:1;border-radius:50%;width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--dsw-alias-border-l2);}",
|
|
3372
|
+
".dkan-sound-play:hover{color:var(--dsw-alias-label-primary);border-color:currentColor;}",
|
|
3373
|
+
".dkan-input{flex:1;min-width:220px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:4px 8px;font-size:12px;font-family:inherit;}",
|
|
3374
|
+
".dkan-input:focus{outline:none;border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3375
|
+
".dkan-row-webhook{flex-wrap:nowrap;}",
|
|
3376
|
+
".dkan-row-webhook .dkan-input{min-width:0;}",
|
|
3377
|
+
".dkan-btn{cursor:pointer;flex:none;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:4px 12px;font-family:inherit;font-size:12px;}",
|
|
3378
|
+
".dkan-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3379
|
+
".dkan-btn[disabled]{opacity:.5;cursor:default;}",
|
|
3380
|
+
".dkan-ok{color:var(--dsw-alias-state-success-primary);}",
|
|
3381
|
+
// 任务列表
|
|
3382
|
+
".dkan-tasks{display:flex;flex-direction:column;gap:6px;}",
|
|
3383
|
+
".dkan-tasks-done{border-top:1px dashed var(--dsw-alias-border-l2);padding-top:6px;}",
|
|
3384
|
+
".dkan-task{border:1px solid var(--dsw-alias-border-l1);border-radius:8px;padding:6px 10px;display:flex;flex-direction:column;gap:3px;}",
|
|
3385
|
+
".dkan-task-head{display:flex;align-items:center;gap:8px;min-width:0;}",
|
|
3386
|
+
".dkan-task-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
3387
|
+
".dkan-task-meta{display:flex;gap:10px;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
3388
|
+
".dkan-task-err{font-size:11px;color:var(--dsw-alias-state-error-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
3389
|
+
".dkan-tag{flex:none;font-size:10px;border-radius:999px;padding:0 8px;color:var(--dsw-alias-label-tertiary);border:1px solid var(--dsw-alias-border-l2);}",
|
|
3390
|
+
".dkan-tag.on{color:var(--dsw-alias-accent,#4d9fff);border-color:currentColor;}",
|
|
3391
|
+
".dkan-tag.ok{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
|
|
3392
|
+
".dkan-tag.err{color:var(--dsw-alias-state-error-primary);border-color:currentColor;}",
|
|
3393
|
+
".dkan-tag.warn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor;}"
|
|
3394
|
+
].join("\n");
|
|
3395
|
+
var feature6 = {
|
|
3396
|
+
id: "animation",
|
|
3397
|
+
name: "\u4EFB\u52A1\u52A8\u753B",
|
|
3398
|
+
order: 130,
|
|
3399
|
+
accent: "#f472b6",
|
|
3400
|
+
description: "\u4EFB\u52A1\u8FD0\u884C\u52A8\u753B\uFF08\u6D41\u5149\u7EC6\u7EBF/\u547C\u5438\u5149\u70B9/\u8F68\u9053\u5149\u73AF\uFF09\u4E0E\u5B8C\u6210\u901A\u77E5\uFF0C\u4E24\u7EC4\u5F00\u5173\u72EC\u7ACB\u3001\u914D\u7F6E\u6301\u4E45\u5316",
|
|
3401
|
+
css: css2,
|
|
3402
|
+
View: AnimationView,
|
|
3403
|
+
HomeStat: AnimationStat,
|
|
3404
|
+
Overlay: AnimationOverlay
|
|
3405
|
+
};
|
|
3406
|
+
|
|
3407
|
+
// src/client.jsx
|
|
3408
|
+
var DOCK_VERSION = "0.5.0";
|
|
3409
|
+
var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6];
|
|
3410
|
+
var PLANNED_FEATURES = [];
|
|
3411
|
+
var PLANNED_NOTES = {};
|
|
1614
3412
|
var externalDefs = [];
|
|
1615
3413
|
var externalListeners = /* @__PURE__ */ new Set();
|
|
1616
3414
|
function notifyExternal() {
|
|
@@ -1633,6 +3431,7 @@ var dockBridge = {
|
|
|
1633
3431
|
css: typeof def.css === "string" ? def.css : "",
|
|
1634
3432
|
View: def.View,
|
|
1635
3433
|
HomeStat: typeof def.HomeStat === "function" ? def.HomeStat : null,
|
|
3434
|
+
Overlay: typeof def.Overlay === "function" ? def.Overlay : null,
|
|
1636
3435
|
external: true,
|
|
1637
3436
|
package: typeof def.package === "string" ? def.package : ""
|
|
1638
3437
|
};
|
|
@@ -1671,9 +3470,13 @@ var SHELL_CSS = [
|
|
|
1671
3470
|
".dock-badge{flex:none;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:3px 10px;font-size:12px;}",
|
|
1672
3471
|
".dock-body{border-top:1px solid var(--dsw-alias-border-l1);padding-top:8px;color:var(--dsw-alias-label-secondary);display:flex;flex-direction:column;gap:4px;}",
|
|
1673
3472
|
// 侧栏入口按钮(docke2- 前缀)+ 功能坞弹出面板(dockm- 前缀,仿 dsh 设置的居中模态:遮罩 + 对话框,左导航 + 右内容)
|
|
1674
|
-
|
|
1675
|
-
|
|
3473
|
+
// 侧栏入口按钮(docke2- 前缀):与 dsh 设置按钮(.VOzbGW_trigger)几何逐条对齐——
|
|
3474
|
+
// 宽栏同为整宽左对齐行按钮(高 42、margin 4/-2、padding 0 10px 0 8px、圆角 12),窄栏同为 36 圆钮居中,
|
|
3475
|
+
// 使两按钮上下成列、左右边缘完全对齐(此前右对齐/叠放都会错位)。
|
|
3476
|
+
".docke2-btn{box-sizing:border-box;cursor:pointer;display:flex;align-items:center;gap:8px;border:none;background:transparent;color:var(--dsw-alias-label-primary);border-radius:12px;width:calc(100% + 4px);height:42px;margin:4px -2px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
|
|
3477
|
+
".docke2-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
1676
3478
|
".docke2-btn.docke2-on{color:var(--dsw-alias-accent,#4d9fff);background:var(--dsw-alias-accent-soft,color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 12%,transparent));}",
|
|
3479
|
+
".docke2-btn.docke2-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;border-radius:50%;justify-content:center;gap:0;}",
|
|
1677
3480
|
".docke2-label{white-space:nowrap;overflow:hidden;}",
|
|
1678
3481
|
".dockm-backdrop{position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--dsw-alias-bg-layer-1) 55%,transparent);backdrop-filter:blur(4px);pointer-events:auto;animation:dockm-fade .15s var(--ds-ease-in-out);}",
|
|
1679
3482
|
"@keyframes dockm-fade{from{opacity:0}to{opacity:1}}",
|
|
@@ -1717,16 +3520,36 @@ var SHELL_CSS = [
|
|
|
1717
3520
|
".dockh-card:hover,.dockh-card:focus-visible{border-color:var(--dsw-alias-accent,#4d9fff);outline:none;}",
|
|
1718
3521
|
".dockh-head{display:flex;align-items:center;gap:8px;}",
|
|
1719
3522
|
".dockh-name{font-weight:600;flex:none;}",
|
|
1720
|
-
".dockh-badge{
|
|
1721
|
-
|
|
1722
|
-
".dockh-
|
|
3523
|
+
".dockh-badge{flex:none;font-size:11px;border-radius:999px;padding:0 8px;color:var(--dsw-alias-label-tertiary);border:1px solid var(--dsw-alias-border-l2);}",
|
|
3524
|
+
// 状态标识(非交互:圆点+文字,与可点的开关一眼区分)
|
|
3525
|
+
".dockh-status{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;}",
|
|
3526
|
+
".dockh-sdot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--dsw-alias-state-success-primary,#34d399);box-shadow:0 0 4px color-mix(in srgb,var(--dsw-alias-state-success-primary,#34d399) 55%,transparent);}",
|
|
3527
|
+
".dockh-status.off .dockh-sdot{background:transparent;border:1.5px solid var(--dsw-alias-label-tertiary);box-shadow:none;opacity:.75;}",
|
|
3528
|
+
".dockh-status.plan .dockh-sdot{background:transparent;border:1.5px dashed var(--dsw-alias-label-tertiary);box-shadow:none;}",
|
|
3529
|
+
// iOS 风滑动开关(首页卡片 / 弹层页脚 / 设置页共用的启停控件)
|
|
3530
|
+
".dock-sw{flex:none;position:relative;width:34px;height:19px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;padding:0;transition:background .18s var(--ds-ease-in-out),border-color .18s var(--ds-ease-in-out);}",
|
|
3531
|
+
'.dock-sw::after{content:"";position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgb(0 0 0 / .35);transition:transform .18s var(--ds-ease-in-out);}',
|
|
3532
|
+
".dock-sw:hover{border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3533
|
+
".dock-sw.on{background:var(--dsw-alias-state-success-primary,#34d399);border-color:transparent;}",
|
|
3534
|
+
".dock-sw.on::after{transform:translateX(15px);}",
|
|
3535
|
+
// 弹层页脚:文字标签 + 开关 成组
|
|
3536
|
+
".dockm-foot-sw{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:8px;}",
|
|
3537
|
+
".dockm-foot-swlabel{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
3538
|
+
".dockm-foot-swlabel.on{color:var(--dsw-alias-state-success-primary);}",
|
|
1723
3539
|
".dockh-desc{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;}",
|
|
1724
3540
|
".dockh-stat{color:var(--dsw-alias-label-tertiary);font-size:12px;border-top:1px solid var(--dsw-alias-border-l1);padding-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
1725
3541
|
".dockh-foot{display:flex;align-items:center;gap:8px;}",
|
|
1726
3542
|
".dockh-go{color:var(--dsw-alias-label-tertiary);font-size:11px;}",
|
|
1727
3543
|
// 会话输入区工具行 chips(dockchip- 前缀):余额/用量随身小控件,挂在模型选择器左侧
|
|
1728
|
-
|
|
1729
|
-
|
|
3544
|
+
// 溢出兼容(两层防护,缺一不可):
|
|
3545
|
+
// 1) 宽度上限:宿主 .row 是 flex-wrap:wrap 且换行优先于收缩,chips 一长 tools 整行变宽,
|
|
3546
|
+
// 右侧模型选择器/发送键被挤到第二行(左右错位)。宿主 .row 带 container-type:inline-size,
|
|
3547
|
+
// 用容器单位 cqw 让上限随输入卡宽度自适应(窄卡少占、宽卡多占);不支持 cqw 的老内核退回固定 280px。
|
|
3548
|
+
// 2) 截断:超限部分用省略号截断(完整数值在 title 悬浮提示里),防 chips 凸出输入卡圆角(悬空)。
|
|
3549
|
+
".dockchip-row{display:inline-flex;align-items:center;gap:4px;min-width:0;flex:0 1 auto;overflow:hidden;max-width:280px;}",
|
|
3550
|
+
"@supports (width:1cqw){.dockchip-row{max-width:min(280px,36cqw);}}",
|
|
3551
|
+
".dockchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:2px 8px;font-family:inherit;font-size:11px;line-height:18px;white-space:nowrap;min-width:0;overflow:hidden;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
|
|
3552
|
+
".dockchip > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}",
|
|
1730
3553
|
".dockchip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
1731
3554
|
".dockchip .dockchip-dot{width:6px;height:6px;border-radius:50%;flex:none;}",
|
|
1732
3555
|
".dockchip.err{color:var(--dsw-alias-state-error-primary);}"
|
|
@@ -1756,8 +3579,8 @@ function ensureCss() {
|
|
|
1756
3579
|
}
|
|
1757
3580
|
}
|
|
1758
3581
|
function useExternalVersion() {
|
|
1759
|
-
const [, bump] =
|
|
1760
|
-
|
|
3582
|
+
const [, bump] = import_react9.default.useReducer((n) => n + 1, 0);
|
|
3583
|
+
import_react9.default.useEffect(() => {
|
|
1761
3584
|
externalListeners.add(bump);
|
|
1762
3585
|
return () => {
|
|
1763
3586
|
externalListeners.delete(bump);
|
|
@@ -1765,42 +3588,42 @@ function useExternalVersion() {
|
|
|
1765
3588
|
}, []);
|
|
1766
3589
|
}
|
|
1767
3590
|
var lastGeom = { x: null, y: null, w: null, h: null };
|
|
1768
|
-
function DockIcon() {
|
|
1769
|
-
|
|
3591
|
+
function DockIcon(props) {
|
|
3592
|
+
const size = props && props.size || 16;
|
|
3593
|
+
return import_react9.default.createElement(
|
|
1770
3594
|
"svg",
|
|
1771
|
-
{ width:
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
3595
|
+
{ width: size, height: size, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
|
|
3596
|
+
import_react9.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
|
|
3597
|
+
import_react9.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
|
|
3598
|
+
import_react9.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
|
|
3599
|
+
import_react9.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
|
|
1776
3600
|
);
|
|
1777
3601
|
}
|
|
1778
3602
|
function DockEntry(props) {
|
|
1779
3603
|
const wide = !!props.wide;
|
|
1780
|
-
const [open, setOpen] =
|
|
1781
|
-
|
|
1782
|
-
return
|
|
3604
|
+
const [open, setOpen] = import_react9.default.useState(panelNav.open);
|
|
3605
|
+
import_react9.default.useEffect(() => subscribePanel(() => setOpen(panelNav.open)), []);
|
|
3606
|
+
return import_react9.default.createElement("button", {
|
|
1783
3607
|
type: "button",
|
|
1784
|
-
className: "docke2-btn" + (open ? " docke2-on" : ""),
|
|
1785
|
-
style: wide ? { marginLeft: "auto", transform: "translateY(46px)", zIndex: 1, height: 42, lineHeight: "42px", padding: "0 12px" } : { transform: "translateY(44px)", zIndex: 1, width: 36, height: 36, justifyContent: "center", padding: 0 },
|
|
3608
|
+
className: "docke2-btn" + (open ? " docke2-on" : "") + (wide ? "" : " docke2-rail"),
|
|
1786
3609
|
title: "\u529F\u80FD\u575E",
|
|
1787
3610
|
"aria-label": "\u529F\u80FD\u575E",
|
|
1788
3611
|
"aria-expanded": open,
|
|
1789
3612
|
onClick: () => setPanelOpen(!open)
|
|
1790
|
-
},
|
|
3613
|
+
}, import_react9.default.createElement(DockIcon, { size: wide ? 16 : 18 }), wide ? import_react9.default.createElement("span", { className: "docke2-label" }, "\u529F\u80FD\u575E") : null);
|
|
1791
3614
|
}
|
|
1792
3615
|
function DockModal() {
|
|
1793
|
-
const [nav, setNav] =
|
|
1794
|
-
|
|
3616
|
+
const [nav, setNav] = import_react9.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
|
|
3617
|
+
import_react9.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
|
|
1795
3618
|
const open = nav.open || typeof document === "undefined";
|
|
1796
3619
|
const active = nav.active;
|
|
1797
3620
|
const setActive = navigatePanel;
|
|
1798
3621
|
const navParams = nav.params;
|
|
1799
|
-
const [, force] =
|
|
3622
|
+
const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
|
|
1800
3623
|
useExternalVersion();
|
|
1801
|
-
const [win, setWin] =
|
|
1802
|
-
const dlgRef =
|
|
1803
|
-
|
|
3624
|
+
const [win, setWin] = import_react9.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
|
|
3625
|
+
const dlgRef = import_react9.default.useRef(null);
|
|
3626
|
+
import_react9.default.useEffect(() => {
|
|
1804
3627
|
if (lastGeom.w) setWin({ mode: "normal", x: lastGeom.x, y: lastGeom.y, w: lastGeom.w, h: lastGeom.h });
|
|
1805
3628
|
}, []);
|
|
1806
3629
|
function beginDrag(e, type) {
|
|
@@ -1838,13 +3661,13 @@ function DockModal() {
|
|
|
1838
3661
|
const mod = isHome ? null : MODULES.find((m) => m.id === active) || MODULES[0];
|
|
1839
3662
|
const st = mod ? stateOf(mod.id) : null;
|
|
1840
3663
|
const View = mod ? mod.View : null;
|
|
1841
|
-
const viewNode = mod && View ?
|
|
3664
|
+
const viewNode = mod && View ? import_react9.default.createElement(
|
|
1842
3665
|
"div",
|
|
1843
3666
|
{ className: "dockm-view" },
|
|
1844
|
-
|
|
1845
|
-
mod.external ? FeatureBoundary :
|
|
3667
|
+
import_react9.default.createElement(
|
|
3668
|
+
mod.external ? FeatureBoundary : import_react9.default.Fragment,
|
|
1846
3669
|
null,
|
|
1847
|
-
|
|
3670
|
+
import_react9.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
|
|
1848
3671
|
)
|
|
1849
3672
|
) : null;
|
|
1850
3673
|
const enabledCount = MODULES.filter((m) => {
|
|
@@ -1858,10 +3681,10 @@ function DockModal() {
|
|
|
1858
3681
|
width: win.w != null ? win.w : void 0,
|
|
1859
3682
|
height: win.mode === "min" ? "auto" : win.h != null ? win.h : void 0
|
|
1860
3683
|
} : null;
|
|
1861
|
-
return
|
|
3684
|
+
return import_react9.default.createElement(
|
|
1862
3685
|
"div",
|
|
1863
3686
|
{ className: "dockm-backdrop", onClick: () => setPanelOpen(false) },
|
|
1864
|
-
|
|
3687
|
+
import_react9.default.createElement(
|
|
1865
3688
|
"div",
|
|
1866
3689
|
{
|
|
1867
3690
|
className: "dockm-dialog" + (win.mode === "max" ? " dockm-max" : "") + (win.mode === "min" ? " dockm-min" : ""),
|
|
@@ -1869,41 +3692,41 @@ function DockModal() {
|
|
|
1869
3692
|
ref: dlgRef,
|
|
1870
3693
|
onClick: (e) => e.stopPropagation()
|
|
1871
3694
|
},
|
|
1872
|
-
|
|
3695
|
+
import_react9.default.createElement(
|
|
1873
3696
|
"div",
|
|
1874
3697
|
{
|
|
1875
3698
|
className: "dockm-head",
|
|
1876
3699
|
onPointerDown: (e) => beginDrag(e, "move"),
|
|
1877
3700
|
onDoubleClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
|
|
1878
3701
|
},
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
3702
|
+
import_react9.default.createElement(DockIcon, null),
|
|
3703
|
+
import_react9.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
|
|
3704
|
+
import_react9.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
|
|
3705
|
+
import_react9.default.createElement(
|
|
1883
3706
|
"span",
|
|
1884
3707
|
{ className: "dockm-ctrls" },
|
|
1885
|
-
|
|
3708
|
+
import_react9.default.createElement("button", {
|
|
1886
3709
|
type: "button",
|
|
1887
3710
|
className: "dockm-win",
|
|
1888
3711
|
title: win.mode === "min" ? "\u8FD8\u539F" : "\u6700\u5C0F\u5316",
|
|
1889
3712
|
onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "min" ? "normal" : "min" }))
|
|
1890
3713
|
}, "\u2581"),
|
|
1891
|
-
|
|
3714
|
+
import_react9.default.createElement("button", {
|
|
1892
3715
|
type: "button",
|
|
1893
3716
|
className: "dockm-win",
|
|
1894
3717
|
title: win.mode === "max" ? "\u8FD8\u539F" : "\u6700\u5927\u5316",
|
|
1895
3718
|
onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
|
|
1896
3719
|
}, win.mode === "max" ? "\u2750" : "\u25A2"),
|
|
1897
|
-
|
|
3720
|
+
import_react9.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
|
|
1898
3721
|
)
|
|
1899
3722
|
),
|
|
1900
|
-
|
|
3723
|
+
import_react9.default.createElement(
|
|
1901
3724
|
"div",
|
|
1902
3725
|
{ className: "dockm-body" },
|
|
1903
|
-
|
|
3726
|
+
import_react9.default.createElement(
|
|
1904
3727
|
"nav",
|
|
1905
3728
|
{ className: "dockm-nav", "aria-label": "\u529F\u80FD\u6A21\u5757" },
|
|
1906
|
-
|
|
3729
|
+
import_react9.default.createElement(
|
|
1907
3730
|
"button",
|
|
1908
3731
|
{
|
|
1909
3732
|
type: "button",
|
|
@@ -1911,10 +3734,10 @@ function DockModal() {
|
|
|
1911
3734
|
className: "dockm-nav-item" + (isHome ? " on" : ""),
|
|
1912
3735
|
onClick: () => setActive("home")
|
|
1913
3736
|
},
|
|
1914
|
-
|
|
1915
|
-
|
|
3737
|
+
import_react9.default.createElement("span", { className: "dockm-navhome" }, import_react9.default.createElement(DockIcon, null)),
|
|
3738
|
+
import_react9.default.createElement("span", null, "\u9996\u9875")
|
|
1916
3739
|
),
|
|
1917
|
-
MODULES.map((m) =>
|
|
3740
|
+
MODULES.map((m) => import_react9.default.createElement(
|
|
1918
3741
|
"button",
|
|
1919
3742
|
{
|
|
1920
3743
|
type: "button",
|
|
@@ -1922,81 +3745,98 @@ function DockModal() {
|
|
|
1922
3745
|
className: "dockm-nav-item" + (m.id === active ? " on" : ""),
|
|
1923
3746
|
onClick: () => setActive(m.id)
|
|
1924
3747
|
},
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
m.planned ?
|
|
1928
|
-
m.external ?
|
|
3748
|
+
import_react9.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
|
|
3749
|
+
import_react9.default.createElement("span", null, m.name),
|
|
3750
|
+
m.planned ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
|
|
3751
|
+
m.external ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
|
|
1929
3752
|
))
|
|
1930
3753
|
),
|
|
1931
|
-
|
|
3754
|
+
import_react9.default.createElement(
|
|
1932
3755
|
"div",
|
|
1933
3756
|
{ className: "dockm-content" },
|
|
1934
|
-
|
|
3757
|
+
import_react9.default.createElement(
|
|
1935
3758
|
"div",
|
|
1936
3759
|
{ className: "dockm-content-head" },
|
|
1937
|
-
|
|
3760
|
+
import_react9.default.createElement(
|
|
1938
3761
|
"div",
|
|
1939
3762
|
{ className: "dockm-name" },
|
|
1940
|
-
isHome ?
|
|
3763
|
+
isHome ? import_react9.default.createElement("span", { className: "dockm-navhome" }, import_react9.default.createElement(DockIcon, null)) : import_react9.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
|
|
1941
3764
|
isHome ? "\u9996\u9875" : mod.name,
|
|
1942
|
-
!isHome && mod.planned ?
|
|
1943
|
-
!isHome && mod.external ?
|
|
3765
|
+
!isHome && mod.planned ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
|
|
3766
|
+
!isHome && mod.external ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
|
|
1944
3767
|
),
|
|
1945
|
-
|
|
3768
|
+
import_react9.default.createElement(
|
|
1946
3769
|
"div",
|
|
1947
3770
|
{ className: "dockm-desc" },
|
|
1948
3771
|
isHome ? "\u6240\u6709\u5B50\u529F\u80FD\u603B\u63FD\uFF1A\u8FD0\u884C\u72B6\u6001\u3001\u6982\u8981\u4E0E\u5FEB\u6377\u5F00\u5173\uFF0C\u70B9\u51FB\u5361\u7247\u8FDB\u5165\u5BF9\u5E94\u529F\u80FD\u9875\u3002" : mod.description
|
|
1949
3772
|
)
|
|
1950
3773
|
),
|
|
1951
|
-
isHome ?
|
|
1952
|
-
|
|
3774
|
+
isHome ? import_react9.default.createElement("div", { className: "dockm-view" }, import_react9.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react9.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react9.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react9.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
|
|
3775
|
+
import_react9.default.createElement(
|
|
1953
3776
|
"div",
|
|
1954
3777
|
{ className: "dockm-foot" },
|
|
1955
|
-
|
|
1956
|
-
!isHome && mod && !mod.planned && st ?
|
|
1957
|
-
|
|
1958
|
-
className: "dockm-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
}
|
|
1972
|
-
|
|
3778
|
+
import_react9.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
|
|
3779
|
+
!isHome && mod && !mod.planned && st ? import_react9.default.createElement(
|
|
3780
|
+
"span",
|
|
3781
|
+
{ className: "dockm-foot-sw" },
|
|
3782
|
+
import_react9.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
|
|
3783
|
+
import_react9.default.createElement("button", {
|
|
3784
|
+
type: "button",
|
|
3785
|
+
className: "dock-sw" + (st.enabled ? " on" : ""),
|
|
3786
|
+
role: "switch",
|
|
3787
|
+
"aria-checked": !!st.enabled,
|
|
3788
|
+
"aria-label": (st.enabled ? "\u505C\u7528" : "\u542F\u7528") + mod.name,
|
|
3789
|
+
title: st.enabled ? "\u505C\u7528\u300C" + mod.name + "\u300D" : "\u542F\u7528\u300C" + mod.name + "\u300D",
|
|
3790
|
+
onClick: () => {
|
|
3791
|
+
toggleFeature(mod.id);
|
|
3792
|
+
force();
|
|
3793
|
+
}
|
|
3794
|
+
})
|
|
3795
|
+
) : null,
|
|
3796
|
+
!isHome && mod && typeof mod.Chip === "function" ? import_react9.default.createElement(
|
|
3797
|
+
"span",
|
|
3798
|
+
{ className: "dockm-foot-sw" },
|
|
3799
|
+
import_react9.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
|
|
3800
|
+
import_react9.default.createElement("button", {
|
|
3801
|
+
type: "button",
|
|
3802
|
+
className: "dock-sw" + (chipShown(mod.id) ? " on" : ""),
|
|
3803
|
+
role: "switch",
|
|
3804
|
+
"aria-checked": chipShown(mod.id),
|
|
3805
|
+
"aria-label": (chipShown(mod.id) ? "\u9690\u85CF" : "\u663E\u793A") + mod.name + "\u7684\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6",
|
|
3806
|
+
title: "\u63A7\u5236\u4F1A\u8BDD\u8F93\u5165\u533A\uFF08\u6A21\u578B\u9009\u62E9\u5668\u5DE6\u4FA7\uFF09\u662F\u5426\u663E\u793A\u672C\u529F\u80FD\u7684\u968F\u8EAB\u5C0F\u63A7\u4EF6",
|
|
3807
|
+
onClick: () => {
|
|
3808
|
+
setChipShown(mod.id, !chipShown(mod.id));
|
|
3809
|
+
force();
|
|
3810
|
+
}
|
|
3811
|
+
})
|
|
3812
|
+
) : null
|
|
1973
3813
|
)
|
|
1974
3814
|
)
|
|
1975
3815
|
),
|
|
1976
|
-
win.mode === "normal" ?
|
|
3816
|
+
win.mode === "normal" ? import_react9.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
|
|
1977
3817
|
)
|
|
1978
3818
|
);
|
|
1979
3819
|
}
|
|
1980
3820
|
function HomeView(props) {
|
|
1981
3821
|
const ctx = props && props.ctx;
|
|
1982
|
-
const [, force] =
|
|
3822
|
+
const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
|
|
1983
3823
|
useExternalVersion();
|
|
1984
3824
|
const open = (id) => {
|
|
1985
3825
|
if (props && typeof props.onOpen === "function") props.onOpen(id);
|
|
1986
3826
|
};
|
|
1987
|
-
return
|
|
3827
|
+
return import_react9.default.createElement(
|
|
1988
3828
|
"div",
|
|
1989
3829
|
{ className: "dockh-grid" },
|
|
1990
3830
|
allModules().map((m) => {
|
|
1991
3831
|
const st = stateOf(m.id);
|
|
1992
3832
|
const enabled = !!(st && st.enabled);
|
|
1993
3833
|
const Stat = m.HomeStat;
|
|
1994
|
-
const statNode = m.planned ?
|
|
1995
|
-
m.external ? FeatureBoundary :
|
|
3834
|
+
const statNode = m.planned ? import_react9.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react9.default.createElement(
|
|
3835
|
+
m.external ? FeatureBoundary : import_react9.default.Fragment,
|
|
1996
3836
|
null,
|
|
1997
|
-
|
|
1998
|
-
) :
|
|
1999
|
-
return
|
|
3837
|
+
import_react9.default.createElement(Stat, { ctx })
|
|
3838
|
+
) : import_react9.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
|
|
3839
|
+
return import_react9.default.createElement(
|
|
2000
3840
|
"div",
|
|
2001
3841
|
{
|
|
2002
3842
|
key: m.id,
|
|
@@ -2011,34 +3851,41 @@ function HomeView(props) {
|
|
|
2011
3851
|
}
|
|
2012
3852
|
}
|
|
2013
3853
|
},
|
|
2014
|
-
|
|
3854
|
+
import_react9.default.createElement(
|
|
2015
3855
|
"div",
|
|
2016
3856
|
{ className: "dockh-head" },
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
m.external ?
|
|
2020
|
-
|
|
3857
|
+
import_react9.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
|
|
3858
|
+
import_react9.default.createElement("span", { className: "dockh-name" }, m.name),
|
|
3859
|
+
m.external ? import_react9.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
|
|
3860
|
+
// 状态标识:圆点 + 文字(纯展示,与开关视觉区分)
|
|
3861
|
+
import_react9.default.createElement(
|
|
2021
3862
|
"span",
|
|
2022
|
-
{ className: "dockh-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
import_react7.default.createElement(
|
|
2029
|
-
"div",
|
|
2030
|
-
{ className: "dockh-foot" },
|
|
2031
|
-
import_react7.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192"),
|
|
2032
|
-
m.planned ? null : import_react7.default.createElement("button", {
|
|
3863
|
+
{ className: "dockh-status" + (m.planned ? " plan" : enabled ? "" : " off") },
|
|
3864
|
+
import_react9.default.createElement("span", { className: "dockh-sdot" }),
|
|
3865
|
+
import_react9.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
|
|
3866
|
+
),
|
|
3867
|
+
// 启停开关(规划中的功能不显示)
|
|
3868
|
+
m.planned ? null : import_react9.default.createElement("button", {
|
|
2033
3869
|
type: "button",
|
|
2034
|
-
className: "
|
|
3870
|
+
className: "dock-sw" + (enabled ? " on" : ""),
|
|
3871
|
+
role: "switch",
|
|
3872
|
+
"aria-checked": enabled,
|
|
3873
|
+
"aria-label": (enabled ? "\u505C\u7528" : "\u542F\u7528") + m.name,
|
|
3874
|
+
title: enabled ? "\u505C\u7528\u300C" + m.name + "\u300D" : "\u542F\u7528\u300C" + m.name + "\u300D",
|
|
2035
3875
|
onClick: (e) => {
|
|
2036
3876
|
e.stopPropagation();
|
|
2037
3877
|
toggleFeature(m.id);
|
|
2038
3878
|
if (props && typeof props.onToggle === "function") props.onToggle();
|
|
2039
3879
|
force();
|
|
2040
3880
|
}
|
|
2041
|
-
}
|
|
3881
|
+
})
|
|
3882
|
+
),
|
|
3883
|
+
import_react9.default.createElement("div", { className: "dockh-desc" }, m.description),
|
|
3884
|
+
import_react9.default.createElement("div", { className: "dockh-stat" }, statNode),
|
|
3885
|
+
import_react9.default.createElement(
|
|
3886
|
+
"div",
|
|
3887
|
+
{ className: "dockh-foot" },
|
|
3888
|
+
import_react9.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
|
|
2042
3889
|
)
|
|
2043
3890
|
);
|
|
2044
3891
|
})
|
|
@@ -2046,16 +3893,16 @@ function HomeView(props) {
|
|
|
2046
3893
|
}
|
|
2047
3894
|
function DockPanel() {
|
|
2048
3895
|
const ctx = ctxRef.current;
|
|
2049
|
-
const [, force] =
|
|
3896
|
+
const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
|
|
2050
3897
|
useExternalVersion();
|
|
2051
3898
|
const toggle = (id) => {
|
|
2052
3899
|
toggleFeature(id);
|
|
2053
3900
|
force();
|
|
2054
3901
|
};
|
|
2055
|
-
return
|
|
3902
|
+
return import_react9.default.createElement(
|
|
2056
3903
|
"div",
|
|
2057
3904
|
{ className: "dock-root" },
|
|
2058
|
-
|
|
3905
|
+
import_react9.default.createElement(
|
|
2059
3906
|
"div",
|
|
2060
3907
|
{ className: "dock-intro" },
|
|
2061
3908
|
"\u529F\u80FD\u575E\uFF08dsh-dock\uFF09\xB7 \u6240\u6709\u5C0F\u529F\u80FD\u96C6\u4E2D\u5728\u8FD9\u4E00\u4E2A\u9762\u677F\u91CC\u7BA1\u7406\u3002v0.4.0 \u8D77\u6BCF\u4E2A\u529F\u80FD\u662F\u72EC\u7ACB\u6A21\u5757\uFF08features/<id>/\uFF09\uFF0C",
|
|
@@ -2064,50 +3911,64 @@ function DockPanel() {
|
|
|
2064
3911
|
allModules().map((f) => {
|
|
2065
3912
|
const st = stateOf(f.id);
|
|
2066
3913
|
const View = f.View;
|
|
2067
|
-
const viewNode = !f.planned && st.enabled && View ?
|
|
3914
|
+
const viewNode = !f.planned && st.enabled && View ? import_react9.default.createElement(
|
|
2068
3915
|
"div",
|
|
2069
3916
|
{ className: "dock-body" },
|
|
2070
|
-
|
|
2071
|
-
f.external ? FeatureBoundary :
|
|
3917
|
+
import_react9.default.createElement(
|
|
3918
|
+
f.external ? FeatureBoundary : import_react9.default.Fragment,
|
|
2072
3919
|
null,
|
|
2073
|
-
|
|
3920
|
+
import_react9.default.createElement(View, { ctx, feature: f })
|
|
2074
3921
|
)
|
|
2075
3922
|
) : null;
|
|
2076
|
-
return
|
|
3923
|
+
return import_react9.default.createElement(
|
|
2077
3924
|
"div",
|
|
2078
3925
|
{ className: "dock-card", key: f.id },
|
|
2079
|
-
|
|
3926
|
+
import_react9.default.createElement(
|
|
2080
3927
|
"div",
|
|
2081
3928
|
{ className: "dock-card-head" },
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
f.planned ?
|
|
2086
|
-
|
|
3929
|
+
import_react9.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
|
|
3930
|
+
import_react9.default.createElement("span", { className: "dock-name" }, f.name),
|
|
3931
|
+
import_react9.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
|
|
3932
|
+
f.planned ? import_react9.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react9.default.createElement("button", {
|
|
3933
|
+
type: "button",
|
|
3934
|
+
className: "dock-sw" + (st.enabled ? " on" : ""),
|
|
3935
|
+
role: "switch",
|
|
3936
|
+
"aria-checked": st.enabled,
|
|
3937
|
+
"aria-label": (st.enabled ? "\u505C\u7528" : "\u542F\u7528") + f.name,
|
|
3938
|
+
title: st.enabled ? "\u505C\u7528\u300C" + f.name + "\u300D" : "\u542F\u7528\u300C" + f.name + "\u300D",
|
|
2087
3939
|
onClick: () => toggle(f.id)
|
|
2088
|
-
}
|
|
2089
|
-
!f.planned && typeof f.Chip === "function" ?
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
3940
|
+
}),
|
|
3941
|
+
!f.planned && typeof f.Chip === "function" ? import_react9.default.createElement(
|
|
3942
|
+
"span",
|
|
3943
|
+
{ className: "dockm-foot-sw" },
|
|
3944
|
+
import_react9.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
|
|
3945
|
+
import_react9.default.createElement("button", {
|
|
3946
|
+
type: "button",
|
|
3947
|
+
className: "dock-sw" + (chipShown(f.id) ? " on" : ""),
|
|
3948
|
+
role: "switch",
|
|
3949
|
+
"aria-checked": chipShown(f.id),
|
|
3950
|
+
"aria-label": (chipShown(f.id) ? "\u9690\u85CF" : "\u663E\u793A") + f.name + "\u7684\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6",
|
|
3951
|
+
title: "\u63A7\u5236\u4F1A\u8BDD\u8F93\u5165\u533A\uFF08\u6A21\u578B\u9009\u62E9\u5668\u5DE6\u4FA7\uFF09\u662F\u5426\u663E\u793A\u672C\u529F\u80FD\u7684\u968F\u8EAB\u5C0F\u63A7\u4EF6",
|
|
3952
|
+
onClick: () => {
|
|
3953
|
+
setChipShown(f.id, !chipShown(f.id));
|
|
3954
|
+
force();
|
|
3955
|
+
}
|
|
3956
|
+
})
|
|
3957
|
+
) : null
|
|
2097
3958
|
),
|
|
2098
|
-
f.planned ?
|
|
3959
|
+
f.planned ? import_react9.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react9.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
|
|
2099
3960
|
viewNode
|
|
2100
3961
|
);
|
|
2101
3962
|
})
|
|
2102
3963
|
);
|
|
2103
3964
|
}
|
|
2104
3965
|
function DockChips(props) {
|
|
2105
|
-
const [, force] =
|
|
2106
|
-
|
|
3966
|
+
const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
|
|
3967
|
+
import_react9.default.useEffect(() => subscribeFeatureState(() => force()), []);
|
|
2107
3968
|
const items = [];
|
|
2108
3969
|
for (const f of allModules()) {
|
|
2109
3970
|
if (f.planned || !stateOf(f.id).enabled || !chipShown(f.id) || typeof f.Chip !== "function") continue;
|
|
2110
|
-
items.push(
|
|
3971
|
+
items.push(import_react9.default.createElement(f.Chip, {
|
|
2111
3972
|
key: f.id,
|
|
2112
3973
|
ctx: props.ctx,
|
|
2113
3974
|
feature: f,
|
|
@@ -2117,7 +3978,23 @@ function DockChips(props) {
|
|
|
2117
3978
|
}));
|
|
2118
3979
|
}
|
|
2119
3980
|
if (items.length === 0) return null;
|
|
2120
|
-
return
|
|
3981
|
+
return import_react9.default.createElement("div", { className: "dockchip-row" }, items);
|
|
3982
|
+
}
|
|
3983
|
+
function FeatureOverlays() {
|
|
3984
|
+
const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
|
|
3985
|
+
useExternalVersion();
|
|
3986
|
+
import_react9.default.useEffect(() => subscribeFeatureState(() => force()), []);
|
|
3987
|
+
const items = [];
|
|
3988
|
+
for (const f of allModules()) {
|
|
3989
|
+
if (f.planned || !stateOf(f.id).enabled || typeof f.Overlay !== "function") continue;
|
|
3990
|
+
items.push(import_react9.default.createElement(
|
|
3991
|
+
FeatureBoundary,
|
|
3992
|
+
{ key: f.id },
|
|
3993
|
+
import_react9.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
|
|
3994
|
+
));
|
|
3995
|
+
}
|
|
3996
|
+
if (items.length === 0) return null;
|
|
3997
|
+
return import_react9.default.createElement(import_react9.default.Fragment, null, items);
|
|
2121
3998
|
}
|
|
2122
3999
|
var ctxRef = { current: null };
|
|
2123
4000
|
function apply(ctx) {
|
|
@@ -2128,19 +4005,23 @@ function apply(ctx) {
|
|
|
2128
4005
|
if (slots === void 0) return;
|
|
2129
4006
|
slots.inject("sidebar.footer.action", () => slots.register(
|
|
2130
4007
|
{ name: "sidebar.footer.action", id: "dsh-dock", order: 1, label: "\u529F\u80FD\u575E" },
|
|
2131
|
-
(props) =>
|
|
4008
|
+
(props) => import_react9.default.createElement(DockEntry, props)
|
|
2132
4009
|
));
|
|
2133
4010
|
slots.inject("shell.overlay", () => slots.register(
|
|
2134
4011
|
{ name: "shell.overlay", id: "dsh-dock-panel", order: 21, label: "\u529F\u80FD\u575E\u9762\u677F" },
|
|
2135
|
-
() =>
|
|
4012
|
+
() => import_react9.default.createElement(DockModal, null)
|
|
4013
|
+
));
|
|
4014
|
+
slots.inject("shell.overlay", () => slots.register(
|
|
4015
|
+
{ name: "shell.overlay", id: "dsh-dock-feature-overlays", order: 22, label: "\u529F\u80FD\u575E\u5168\u5C40\u6D6E\u5C42" },
|
|
4016
|
+
() => import_react9.default.createElement(FeatureOverlays, null)
|
|
2136
4017
|
));
|
|
2137
4018
|
slots.inject("settings.section", () => slots.register(
|
|
2138
4019
|
{ name: "settings.section", id: "dsh-dock", order: 90, label: "\u529F\u80FD\u575E" },
|
|
2139
|
-
() =>
|
|
4020
|
+
() => import_react9.default.createElement(DockPanel, null)
|
|
2140
4021
|
));
|
|
2141
4022
|
slots.inject("conversation.input.left", () => slots.register(
|
|
2142
4023
|
{ name: "conversation.input.left", id: "dsh-dock-chips", order: 10, label: "\u529F\u80FD\u575E" },
|
|
2143
|
-
(zone) =>
|
|
4024
|
+
(zone) => import_react9.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
|
|
2144
4025
|
));
|
|
2145
4026
|
}
|
|
2146
4027
|
var inject = ["timer"];
|