@wenbin_wb/dsh-bridge 2.2.4 → 2.2.5
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 +70 -6
- package/README.zh-CN.md +70 -6
- package/client/client.js +310 -128
- package/client/index.js +265 -113
- package/docs/qq-usage.md +385 -0
- package/lib/index.js +39 -0
- package/lib/platform/conversation-bridge.js +5 -3
- package/lib/qq/index.js +2 -0
- package/lib/tunnel-client.mjs +0 -3
- package/lib/wechat/node.js +42 -16
- package/package.json +3 -2
package/client/client.js
CHANGED
|
@@ -89,17 +89,17 @@ function semverGt(a, b) {
|
|
|
89
89
|
return av.pre > bv.pre;
|
|
90
90
|
}
|
|
91
91
|
var s = {
|
|
92
|
-
card: { background: "var(--dsw-alias-bg-layer-
|
|
92
|
+
card: { background: "var(--dsw-alias-bg-layer-2,#f9fafb)", border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)", borderRadius: 12, padding: "16px 20px", marginBottom: 16 },
|
|
93
93
|
block: { borderTop: "1px solid var(--dsw-alias-border-l2,#e5e7eb)", marginTop: 12, paddingTop: 12 },
|
|
94
94
|
muted: { color: "var(--dsw-alias-label-tertiary,#8b93a1)", fontSize: 12, lineHeight: 1.5 },
|
|
95
95
|
label: { color: "var(--dsw-alias-label-primary,currentColor)", fontSize: 13, fontWeight: 500 },
|
|
96
96
|
code: { fontFamily: "ui-monospace,Menlo,monospace", fontSize: 12, wordBreak: "break-all", color: "var(--dsw-alias-label-primary,currentColor)" },
|
|
97
97
|
btnPri: { font: "inherit", cursor: "pointer", border: "none", background: "var(--dsw-alias-brand-primary,#4f6ef7)", color: "var(--dsw-alias-label-primary-foreground,#fff)", height: 32, padding: "0 14px", borderRadius: 999, fontSize: 13, fontWeight: 500, display: "inline-flex", alignItems: "center", gap: 4 },
|
|
98
|
-
btnGhost: { font: "inherit", cursor: "pointer", border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", background: "var(--dsw-alias-bg-layer-
|
|
98
|
+
btnGhost: { font: "inherit", cursor: "pointer", border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", background: "var(--dsw-alias-bg-layer-2,#f9fafb)", color: "var(--dsw-alias-label-primary,currentColor)", height: 32, padding: "0 14px", borderRadius: 999, fontSize: 13, display: "inline-flex", alignItems: "center", gap: 4, textDecoration: "none" },
|
|
99
99
|
btnLink: { font: "inherit", cursor: "pointer", border: "none", background: "none", color: "var(--dsw-alias-brand-primary,#4f6ef7)", fontSize: 12, padding: 0, display: "inline-flex", alignItems: "center", gap: 3, textDecoration: "none" },
|
|
100
|
-
qr: { width: 200, height: 200, borderRadius: 10, border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)", margin: "8px 0", display: "block" },
|
|
100
|
+
qr: { width: 200, height: 200, borderRadius: 10, border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)", margin: "8px 0", display: "block", background: "#ffffff", padding: 6, boxSizing: "border-box" },
|
|
101
101
|
tag: { display: "inline-flex", alignItems: "center", padding: "2px 8px", borderRadius: 999, fontSize: 12, fontWeight: 500 },
|
|
102
|
-
input: { width: "100%", font: "inherit", fontSize: 13, padding: "7px 10px", borderRadius: 8, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", background: "var(--dsw-alias-bg-layer-
|
|
102
|
+
input: { width: "100%", font: "inherit", fontSize: 13, padding: "7px 10px", borderRadius: 8, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", background: "var(--dsw-alias-bg-layer-2,#f9fafb)", color: "var(--dsw-alias-label-primary,currentColor)", outline: "none", boxSizing: "border-box" },
|
|
103
103
|
warn: { background: "var(--dsw-alias-state-warn-bg,#fffbeb)", border: "1px solid var(--dsw-alias-state-warn-border,#fde68a)", borderRadius: 8, padding: "10px 14px", fontSize: 12, color: "var(--dsw-alias-state-warn-primary,#92400e)", lineHeight: 1.6 },
|
|
104
104
|
tip: { background: "var(--dsw-alias-bg-layer-2,#f9fafb)", borderRadius: 8, padding: "10px 14px", fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)", lineHeight: 1.6 }
|
|
105
105
|
};
|
|
@@ -129,14 +129,38 @@ function useCopy() {
|
|
|
129
129
|
}, []);
|
|
130
130
|
return [copied, copy];
|
|
131
131
|
}
|
|
132
|
-
function StatusTag({ running }) {
|
|
132
|
+
function StatusTag({ running, status }) {
|
|
133
|
+
let bg = "var(--dsw-alias-bg-layer-2,#f3f4f6)";
|
|
134
|
+
let color = "var(--dsw-alias-label-secondary,#6b7280)";
|
|
135
|
+
let text = running ? "\u8FD0\u884C\u4E2D" : "\u672A\u542F\u52A8";
|
|
136
|
+
if (status === "connected") {
|
|
137
|
+
bg = "var(--dsw-alias-state-success-bg,#ecfdf5)";
|
|
138
|
+
color = "var(--dsw-alias-state-success-primary,#059669)";
|
|
139
|
+
text = "\u5DF2\u8FDE\u63A5";
|
|
140
|
+
} else if (status === "starting") {
|
|
141
|
+
bg = "var(--dsw-alias-state-info-bg,#eff6ff)";
|
|
142
|
+
color = "var(--dsw-alias-state-info-primary,#3b82f6)";
|
|
143
|
+
text = "\u8FDE\u63A5\u4E2D\u2026";
|
|
144
|
+
} else if (status === "reconnecting") {
|
|
145
|
+
bg = "var(--dsw-alias-state-warn-bg,#fffbeb)";
|
|
146
|
+
color = "var(--dsw-alias-state-warn-primary,#d97706)";
|
|
147
|
+
text = "\u91CD\u8FDE\u4E2D\u2026";
|
|
148
|
+
} else if (status === "paused") {
|
|
149
|
+
bg = "var(--dsw-alias-state-warn-bg,#fffbeb)";
|
|
150
|
+
color = "var(--dsw-alias-state-warn-primary,#d97706)";
|
|
151
|
+
text = "\u6682\u505C\u4E2D";
|
|
152
|
+
} else if (status === "error") {
|
|
153
|
+
bg = "var(--dsw-alias-state-error-bg,#fef2f2)";
|
|
154
|
+
color = "var(--dsw-alias-state-error-primary,#dc2626)";
|
|
155
|
+
text = "\u5F02\u5E38";
|
|
156
|
+
} else if (running) {
|
|
157
|
+
bg = "var(--dsw-alias-state-success-bg,#ecfdf5)";
|
|
158
|
+
color = "var(--dsw-alias-state-success-primary,#059669)";
|
|
159
|
+
text = "\u8FD0\u884C\u4E2D";
|
|
160
|
+
}
|
|
133
161
|
return React.createElement("span", {
|
|
134
|
-
style: {
|
|
135
|
-
|
|
136
|
-
background: running ? "var(--dsw-alias-state-success-bg,#ecfdf5)" : "var(--dsw-alias-bg-layer-2,#f3f4f6)",
|
|
137
|
-
color: running ? "var(--dsw-alias-state-success-primary,#059669)" : "var(--dsw-alias-label-secondary,#6b7280)"
|
|
138
|
-
}
|
|
139
|
-
}, running ? "\u8FD0\u884C\u4E2D" : "\u672A\u542F\u52A8");
|
|
162
|
+
style: { ...s.tag, background: bg, color }
|
|
163
|
+
}, text);
|
|
140
164
|
}
|
|
141
165
|
function QrBlock({ url, qr, onReset }) {
|
|
142
166
|
const [copied, setCopied] = React.useState(false);
|
|
@@ -220,6 +244,7 @@ var CustomTunnelConfigForm = React.memo(function CustomTunnelConfigForm2({ serve
|
|
|
220
244
|
const [serverUrl, setServerUrl] = React.useState(initUrl ?? "");
|
|
221
245
|
const [accessToken, setAccessToken] = React.useState(initToken ?? "");
|
|
222
246
|
const [saving, setSaving] = React.useState(false);
|
|
247
|
+
const [saveSuccess, setSaveSuccess] = React.useState(false);
|
|
223
248
|
const syncedRef = React.useRef(false);
|
|
224
249
|
React.useEffect(() => {
|
|
225
250
|
if (!syncedRef.current && (initUrl || initToken)) {
|
|
@@ -231,14 +256,23 @@ var CustomTunnelConfigForm = React.memo(function CustomTunnelConfigForm2({ serve
|
|
|
231
256
|
const dirty = serverUrl !== (initUrl ?? "") || accessToken !== (initToken ?? "");
|
|
232
257
|
const handleSave = React.useCallback(async () => {
|
|
233
258
|
setSaving(true);
|
|
259
|
+
setSaveSuccess(false);
|
|
234
260
|
try {
|
|
235
261
|
await onSave(serverUrl, accessToken);
|
|
262
|
+
setSaveSuccess(true);
|
|
263
|
+
setTimeout(() => setSaveSuccess(false), 2500);
|
|
236
264
|
} finally {
|
|
237
265
|
setSaving(false);
|
|
238
266
|
}
|
|
239
267
|
}, [onSave, serverUrl, accessToken]);
|
|
240
|
-
const handleUrlChange = React.useCallback((e) =>
|
|
241
|
-
|
|
268
|
+
const handleUrlChange = React.useCallback((e) => {
|
|
269
|
+
setServerUrl(e.target.value);
|
|
270
|
+
setSaveSuccess(false);
|
|
271
|
+
}, []);
|
|
272
|
+
const handleTokenChange = React.useCallback((e) => {
|
|
273
|
+
setAccessToken(e.target.value);
|
|
274
|
+
setSaveSuccess(false);
|
|
275
|
+
}, []);
|
|
242
276
|
return React.createElement(
|
|
243
277
|
"div",
|
|
244
278
|
{ style: s.block },
|
|
@@ -251,6 +285,9 @@ var CustomTunnelConfigForm = React.memo(function CustomTunnelConfigForm2({ serve
|
|
|
251
285
|
placeholder: "WebSocket \u5730\u5740\uFF0C\u4F8B\u5982 wss://tunnel.example.com/connect",
|
|
252
286
|
value: serverUrl,
|
|
253
287
|
onChange: handleUrlChange,
|
|
288
|
+
onKeyDown: (e) => {
|
|
289
|
+
if (e.key === "Enter" && dirty && !saving) handleSave();
|
|
290
|
+
},
|
|
254
291
|
disabled: saving
|
|
255
292
|
}),
|
|
256
293
|
React.createElement("input", {
|
|
@@ -259,13 +296,21 @@ var CustomTunnelConfigForm = React.memo(function CustomTunnelConfigForm2({ serve
|
|
|
259
296
|
placeholder: "\u8BBF\u95EE\u4EE4\u724C\uFF08Access Token\uFF09",
|
|
260
297
|
value: accessToken,
|
|
261
298
|
onChange: handleTokenChange,
|
|
299
|
+
onKeyDown: (e) => {
|
|
300
|
+
if (e.key === "Enter" && dirty && !saving) handleSave();
|
|
301
|
+
},
|
|
262
302
|
disabled: saving
|
|
263
303
|
}),
|
|
264
304
|
React.createElement("button", {
|
|
265
|
-
style: {
|
|
266
|
-
|
|
305
|
+
style: {
|
|
306
|
+
...s.btnPri,
|
|
307
|
+
alignSelf: "flex-start",
|
|
308
|
+
opacity: !dirty || saving ? saveSuccess ? 1 : 0.5 : 1,
|
|
309
|
+
background: saveSuccess ? "var(--dsw-alias-state-success-primary,#059669)" : void 0
|
|
310
|
+
},
|
|
311
|
+
disabled: !dirty && !saveSuccess || saving,
|
|
267
312
|
onClick: handleSave
|
|
268
|
-
}, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u914D\u7F6E")
|
|
313
|
+
}, saving ? "\u4FDD\u5B58\u4E2D\u2026" : saveSuccess ? "\u2713 \u5DF2\u4FDD\u5B58" : "\u4FDD\u5B58\u914D\u7F6E")
|
|
269
314
|
)
|
|
270
315
|
);
|
|
271
316
|
});
|
|
@@ -381,6 +426,16 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
381
426
|
await act(BRIDGE_ENDPOINTS.platformSetAllowFrom, { allowFrom: list });
|
|
382
427
|
}, [act, platform?.allowFrom]);
|
|
383
428
|
const handleNewId = React.useCallback((e) => setNewId(e.target.value), []);
|
|
429
|
+
const [showSecret, setShowSecret] = React.useState(false);
|
|
430
|
+
const resetDefaults = React.useCallback(() => {
|
|
431
|
+
setCfgDraft((d) => ({
|
|
432
|
+
...d,
|
|
433
|
+
digestIntervalSec: "300",
|
|
434
|
+
approvalTimeoutSec: "600",
|
|
435
|
+
maxMessageChars: "2000",
|
|
436
|
+
sendChunkDelayMs: "1500"
|
|
437
|
+
}));
|
|
438
|
+
}, []);
|
|
384
439
|
const saveConfig = React.useCallback(async () => {
|
|
385
440
|
if (!cfgDraft) return;
|
|
386
441
|
const payload = {
|
|
@@ -420,9 +475,9 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
420
475
|
React.createElement("div", { style: s.label }, platformName),
|
|
421
476
|
React.createElement("div", { style: { ...s.muted, marginTop: 2 } }, platformDesc)
|
|
422
477
|
),
|
|
423
|
-
React.createElement(StatusTag, { running: connected })
|
|
478
|
+
React.createElement(StatusTag, { status: platform?.status, running: connected })
|
|
424
479
|
),
|
|
425
|
-
// 快捷入口:使用说明 /
|
|
480
|
+
// 快捷入口:使用说明 / 开放平台 / 命令速查
|
|
426
481
|
React.createElement(
|
|
427
482
|
"div",
|
|
428
483
|
{ style: { display: "flex", gap: 8, marginTop: 10, flexWrap: "wrap", alignItems: "center" } },
|
|
@@ -431,7 +486,19 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
431
486
|
target: "_blank",
|
|
432
487
|
rel: "noopener noreferrer",
|
|
433
488
|
style: s.btnGhost
|
|
434
|
-
}, "\u{1F4D6} \u4F7F\u7528\u8BF4\u660E"),
|
|
489
|
+
}, "\u{1F4D6} \u5FAE\u4FE1\u4F7F\u7528\u8BF4\u660E"),
|
|
490
|
+
platformId === "qq" && React.createElement("a", {
|
|
491
|
+
href: "https://github.com/wenbin-wb/dsh-bridge/blob/main/docs/qq-usage.md",
|
|
492
|
+
target: "_blank",
|
|
493
|
+
rel: "noopener noreferrer",
|
|
494
|
+
style: s.btnGhost
|
|
495
|
+
}, "\u{1F4D6} QQ \u4F7F\u7528\u8BF4\u660E"),
|
|
496
|
+
platformId === "qq" && React.createElement("a", {
|
|
497
|
+
href: "https://bot.q.qq.com/wiki/develop/api-v2/",
|
|
498
|
+
target: "_blank",
|
|
499
|
+
rel: "noopener noreferrer",
|
|
500
|
+
style: s.btnGhost
|
|
501
|
+
}, "\u{1F310} QQ \u5F00\u653E\u5E73\u53F0"),
|
|
435
502
|
React.createElement("button", {
|
|
436
503
|
style: s.btnGhost,
|
|
437
504
|
onClick: () => setShowHelp((v) => !v)
|
|
@@ -441,32 +508,89 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
441
508
|
showHelp && React.createElement(
|
|
442
509
|
"div",
|
|
443
510
|
{ style: { ...s.block, fontSize: 12, lineHeight: 1.8, fontFamily: "monospace" } },
|
|
444
|
-
React.createElement("div", null, "/new <\u63D0\u793A\u8BCD> \u2014 \u65B0\u5EFA\u4F1A\u8BDD\uFF08\u5F53\u524D\u5DE5\u4F5C\u533A\uFF09"),
|
|
445
|
-
React.createElement("div", null, "/new <\u63D0\u793A\u8BCD> @N \u2014 \u5728\u6307\u5B9A\u5DE5\u4F5C\u533A\u65B0\u5EFA"),
|
|
446
|
-
React.createElement("div", null, "/sessions \u2014 \u6309\u5DE5\u4F5C\u533A\u5206\u7EC4\
|
|
447
|
-
React.createElement("div", null, "/use N \u2014 \u5207\u6362\u5230\u4F1A\u8BDD N"),
|
|
448
|
-
React.createElement("div", null, "/workspaces \u2014 \u5217\u51FA\u5DE5\u4F5C\u533A"),
|
|
449
|
-
React.createElement("div", null, "/
|
|
450
|
-
React.createElement("div", null, "/
|
|
451
|
-
React.createElement("div", null, "/
|
|
452
|
-
React.createElement("div", null, "/
|
|
511
|
+
React.createElement("div", null, "/new <\u63D0\u793A\u8BCD> \u2014 \u65B0\u5EFA\u4F1A\u8BDD\u5E76\u5F00\u59CB\uFF08\u5F53\u524D\u5DE5\u4F5C\u533A\uFF09"),
|
|
512
|
+
React.createElement("div", null, "/new <\u63D0\u793A\u8BCD> @N \u2014 \u5728\u6307\u5B9A\u5DE5\u4F5C\u533A\u65B0\u5EFA\u4F1A\u8BDD"),
|
|
513
|
+
React.createElement("div", null, "/sessions\uFF08\u6216 /list\uFF09\u2014 \u5217\u51FA\u4F1A\u8BDD\uFF08\u6309\u5DE5\u4F5C\u533A\u5206\u7EC4\uFF0C\u5E26\u6807\u9898\uFF09"),
|
|
514
|
+
React.createElement("div", null, "/use N\uFF08\u6216 /resume N\uFF09\u2014 \u5207\u6362\u5230\u4F1A\u8BDD N"),
|
|
515
|
+
React.createElement("div", null, "/workspaces \u2014 \u5217\u51FA\u6240\u6709\u53EF\u7528\u5DE5\u4F5C\u533A"),
|
|
516
|
+
React.createElement("div", null, "/end \u2014 \u7ED3\u675F\u5F53\u524D\u4F1A\u8BDD\uFF08\u56DE\u5230\u65E0\u6D3B\u52A8\u4F1A\u8BDD\u72B6\u6001\uFF09"),
|
|
517
|
+
React.createElement("div", null, "/stop \u2014 \u505C\u6B62\u5F53\u524D\u4EFB\u52A1"),
|
|
518
|
+
React.createElement("div", null, "/status \u2014 \u67E5\u770B Agent \u72B6\u6001\u4E0E\u4F1A\u8BDD\u6458\u8981"),
|
|
519
|
+
React.createElement("div", null, "/yes \u6216 /no\uFF08\u6216 1/2\uFF09\u2014 \u56DE\u5E94\u6743\u9650\u5BA1\u6279\u8BF7\u6C42"),
|
|
520
|
+
React.createElement("div", null, "/help \u2014 \u663E\u793A\u5B8C\u6574\u547D\u4EE4\u5E2E\u52A9")
|
|
453
521
|
),
|
|
454
522
|
err && React.createElement("div", { style: { ...s.warn, marginTop: 10 } }, err),
|
|
455
|
-
//
|
|
523
|
+
// 已配置:结构化状态看板 + 白名单
|
|
456
524
|
platform?.configured && React.createElement(
|
|
457
525
|
"div",
|
|
458
526
|
{ style: s.block },
|
|
527
|
+
// 结构化状态卡片看板
|
|
459
528
|
React.createElement(
|
|
460
529
|
"div",
|
|
461
|
-
{
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
530
|
+
{
|
|
531
|
+
style: {
|
|
532
|
+
display: "grid",
|
|
533
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(140px, 1fr))",
|
|
534
|
+
gap: 8,
|
|
535
|
+
marginBottom: 12
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
React.createElement(
|
|
539
|
+
"div",
|
|
540
|
+
{
|
|
541
|
+
style: {
|
|
542
|
+
background: "var(--dsw-alias-bg-layer-1,#fff)",
|
|
543
|
+
border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)",
|
|
544
|
+
borderRadius: 8,
|
|
545
|
+
padding: "8px 12px"
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
React.createElement("div", { style: { ...s.muted, fontSize: 11 } }, "\u8FDE\u63A5\u72B6\u6001"),
|
|
549
|
+
React.createElement(
|
|
550
|
+
"div",
|
|
551
|
+
{ style: { ...s.label, fontSize: 13, marginTop: 2, display: "flex", alignItems: "center", gap: 6 } },
|
|
552
|
+
React.createElement("span", {
|
|
553
|
+
style: {
|
|
554
|
+
width: 6,
|
|
555
|
+
height: 6,
|
|
556
|
+
borderRadius: "50%",
|
|
557
|
+
background: connected ? "var(--dsw-alias-state-success-primary,#10b981)" : "var(--dsw-alias-label-tertiary,#9ca3af)"
|
|
558
|
+
}
|
|
559
|
+
}),
|
|
560
|
+
statusLabel
|
|
561
|
+
)
|
|
562
|
+
),
|
|
563
|
+
platform.accountId && React.createElement(
|
|
564
|
+
"div",
|
|
565
|
+
{
|
|
566
|
+
style: {
|
|
567
|
+
background: "var(--dsw-alias-bg-layer-1,#fff)",
|
|
568
|
+
border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)",
|
|
569
|
+
borderRadius: 8,
|
|
570
|
+
padding: "8px 12px"
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
React.createElement("div", { style: { ...s.muted, fontSize: 11 } }, "\u767B\u5F55\u8D26\u53F7"),
|
|
574
|
+
React.createElement("div", { style: { ...s.code, fontSize: 12, marginTop: 2, fontWeight: 500 } }, platform.accountId)
|
|
575
|
+
),
|
|
576
|
+
platform.sessionId && React.createElement(
|
|
577
|
+
"div",
|
|
578
|
+
{
|
|
579
|
+
style: {
|
|
580
|
+
background: "var(--dsw-alias-bg-layer-1,#fff)",
|
|
581
|
+
border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)",
|
|
582
|
+
borderRadius: 8,
|
|
583
|
+
padding: "8px 12px"
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
React.createElement("div", { style: { ...s.muted, fontSize: 11 } }, "\u6D3B\u52A8\u4F1A\u8BDD"),
|
|
587
|
+
React.createElement("div", { style: { ...s.code, fontSize: 12, marginTop: 2 } }, platform.sessionId)
|
|
588
|
+
)
|
|
465
589
|
),
|
|
466
590
|
React.createElement(
|
|
467
591
|
"div",
|
|
468
592
|
{ style: { ...s.muted, fontSize: 12, marginTop: 8, lineHeight: 1.6 } },
|
|
469
|
-
|
|
593
|
+
`\u767D\u540D\u5355 (\u5DF2\u6388\u6743 ${platform.allowFrom?.length || 0} \u4E2A\u8D26\u53F7/\u7FA4):`
|
|
470
594
|
),
|
|
471
595
|
React.createElement(
|
|
472
596
|
"div",
|
|
@@ -493,9 +617,12 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
493
617
|
{ style: { display: "flex", gap: 8, marginTop: 8, alignItems: "center" } },
|
|
494
618
|
React.createElement("input", {
|
|
495
619
|
style: { ...s.input, flex: 1 },
|
|
496
|
-
placeholder: platformId === "wechat" ? "\u6DFB\u52A0\u5141\u8BB8\u7684\u5FAE\u4FE1 ID\uFF08\u5982 xxx@im.wechat\uFF09" : "\u6DFB\u52A0\u5141\u8BB8\u7684\u7528\u6237 ID",
|
|
620
|
+
placeholder: platformId === "wechat" ? "\u6DFB\u52A0\u5141\u8BB8\u7684\u5FAE\u4FE1 ID\uFF08\u5982 xxx@im.wechat\uFF09\uFF0C\u6309 Enter \u6DFB\u52A0" : "\u6DFB\u52A0\u5141\u8BB8\u7684\u7528\u6237/\u7FA4 ID\uFF0C\u6309 Enter \u6DFB\u52A0",
|
|
497
621
|
value: newId,
|
|
498
|
-
onChange: handleNewId
|
|
622
|
+
onChange: handleNewId,
|
|
623
|
+
onKeyDown: (e) => {
|
|
624
|
+
if (e.key === "Enter" && newId.trim() && !busy) addAllow();
|
|
625
|
+
}
|
|
499
626
|
}),
|
|
500
627
|
React.createElement("button", {
|
|
501
628
|
style: { ...s.btnGhost, whiteSpace: "nowrap", opacity: newId.trim() && !busy ? 1 : 0.5 },
|
|
@@ -543,19 +670,36 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
543
670
|
style: { ...s.input, width: "100%" },
|
|
544
671
|
placeholder: "\u8BF7\u8F93\u5165 AppID",
|
|
545
672
|
value: cfgDraft?.appId ?? "",
|
|
546
|
-
onChange: (e) => setCfgDraft((d) => ({ ...d, appId: e.target.value }))
|
|
673
|
+
onChange: (e) => setCfgDraft((d) => ({ ...d, appId: e.target.value })),
|
|
674
|
+
onKeyDown: (e) => {
|
|
675
|
+
if (e.key === "Enter" && cfgDraft?.appId?.trim() && cfgDraft?.clientSecret?.trim() && !busy) saveConfig();
|
|
676
|
+
}
|
|
547
677
|
})
|
|
548
678
|
),
|
|
549
679
|
React.createElement(
|
|
550
680
|
"div",
|
|
551
681
|
null,
|
|
552
682
|
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "ClientSecret \u2014 QQ \u5F00\u653E\u5E73\u53F0\u673A\u5668\u4EBA\u5BC6\u94A5"),
|
|
553
|
-
React.createElement(
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
683
|
+
React.createElement(
|
|
684
|
+
"div",
|
|
685
|
+
{ style: { display: "flex", gap: 6, alignItems: "center" } },
|
|
686
|
+
React.createElement("input", {
|
|
687
|
+
style: { ...s.input, flex: 1 },
|
|
688
|
+
type: showSecret ? "text" : "password",
|
|
689
|
+
placeholder: "\u8BF7\u8F93\u5165 ClientSecret",
|
|
690
|
+
value: cfgDraft?.clientSecret ?? "",
|
|
691
|
+
onChange: (e) => setCfgDraft((d) => ({ ...d, clientSecret: e.target.value })),
|
|
692
|
+
onKeyDown: (e) => {
|
|
693
|
+
if (e.key === "Enter" && cfgDraft?.appId?.trim() && cfgDraft?.clientSecret?.trim() && !busy) saveConfig();
|
|
694
|
+
}
|
|
695
|
+
}),
|
|
696
|
+
React.createElement("button", {
|
|
697
|
+
style: { ...s.btnGhost, height: 32, padding: "0 10px", fontSize: 13, flexShrink: 0 },
|
|
698
|
+
onClick: () => setShowSecret((v) => !v),
|
|
699
|
+
type: "button",
|
|
700
|
+
title: showSecret ? "\u9690\u85CF\u5BC6\u94A5" : "\u663E\u793A\u660E\u6587"
|
|
701
|
+
}, showSecret ? "\u{1F648} \u9690\u85CF" : "\u{1F441}\uFE0F \u663E\u793A")
|
|
702
|
+
)
|
|
559
703
|
),
|
|
560
704
|
React.createElement(
|
|
561
705
|
"div",
|
|
@@ -588,7 +732,7 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
588
732
|
login.phase === "error" && React.createElement("div", { style: { ...s.muted, fontSize: 12 } }, login.error ?? "\u767B\u5F55\u5931\u8D25")
|
|
589
733
|
)
|
|
590
734
|
),
|
|
591
|
-
//
|
|
735
|
+
// 高级设置(紧凑 2x2 网格 + 恢复默认值)
|
|
592
736
|
cfgDraft && React.createElement(
|
|
593
737
|
"div",
|
|
594
738
|
{ style: s.block },
|
|
@@ -599,72 +743,83 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
599
743
|
showAdvanced && React.createElement(
|
|
600
744
|
"div",
|
|
601
745
|
{ style: { display: "flex", flexDirection: "column", gap: 10 } },
|
|
602
|
-
//
|
|
746
|
+
// 2x2 参数网格
|
|
603
747
|
React.createElement(
|
|
604
748
|
"div",
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
749
|
+
{
|
|
750
|
+
style: {
|
|
751
|
+
display: "grid",
|
|
752
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
|
|
753
|
+
gap: 10
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
// 心跳间隔
|
|
757
|
+
React.createElement(
|
|
758
|
+
"div",
|
|
759
|
+
null,
|
|
760
|
+
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "\u5FC3\u8DF3\u8FDB\u5EA6\u95F4\u9694 (\u79D2)"),
|
|
761
|
+
React.createElement("input", {
|
|
762
|
+
style: { ...s.input, width: "100%" },
|
|
763
|
+
type: "number",
|
|
764
|
+
min: 30,
|
|
765
|
+
max: 3600,
|
|
766
|
+
value: cfgDraft.digestIntervalSec,
|
|
767
|
+
onChange: (e) => setCfgDraft((d) => ({ ...d, digestIntervalSec: e.target.value }))
|
|
768
|
+
})
|
|
769
|
+
),
|
|
770
|
+
// 审批超时
|
|
771
|
+
React.createElement(
|
|
772
|
+
"div",
|
|
773
|
+
null,
|
|
774
|
+
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "\u5BA1\u6279\u8D85\u65F6\u81EA\u52A8\u62D2\u7EDD (\u79D2)"),
|
|
775
|
+
React.createElement("input", {
|
|
776
|
+
style: { ...s.input, width: "100%" },
|
|
777
|
+
type: "number",
|
|
778
|
+
min: 30,
|
|
779
|
+
max: 86400,
|
|
780
|
+
value: cfgDraft.approvalTimeoutSec,
|
|
781
|
+
onChange: (e) => setCfgDraft((d) => ({ ...d, approvalTimeoutSec: e.target.value }))
|
|
782
|
+
})
|
|
783
|
+
),
|
|
784
|
+
// 每气泡字数
|
|
785
|
+
React.createElement(
|
|
786
|
+
"div",
|
|
787
|
+
null,
|
|
788
|
+
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "\u5355\u6761\u6700\u5927\u5B57\u6570\u9650\u5236 (\u5B57)"),
|
|
789
|
+
React.createElement("input", {
|
|
790
|
+
style: { ...s.input, width: "100%" },
|
|
791
|
+
type: "number",
|
|
792
|
+
min: 100,
|
|
793
|
+
max: 1e4,
|
|
794
|
+
value: cfgDraft.maxMessageChars,
|
|
795
|
+
onChange: (e) => setCfgDraft((d) => ({ ...d, maxMessageChars: e.target.value }))
|
|
796
|
+
})
|
|
797
|
+
),
|
|
798
|
+
// 分块延迟
|
|
799
|
+
React.createElement(
|
|
800
|
+
"div",
|
|
801
|
+
null,
|
|
802
|
+
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "\u5206\u5757\u53D1\u9001\u5EF6\u8FDF (\u6BEB\u79D2)"),
|
|
803
|
+
React.createElement("input", {
|
|
804
|
+
style: { ...s.input, width: "100%" },
|
|
805
|
+
type: "number",
|
|
806
|
+
min: 0,
|
|
807
|
+
max: 1e4,
|
|
808
|
+
value: cfgDraft.sendChunkDelayMs,
|
|
809
|
+
onChange: (e) => setCfgDraft((d) => ({ ...d, sendChunkDelayMs: e.target.value }))
|
|
810
|
+
})
|
|
811
|
+
)
|
|
657
812
|
),
|
|
658
813
|
// QQ 平台凭证
|
|
659
814
|
platformId === "qq" && React.createElement(
|
|
660
815
|
"div",
|
|
661
|
-
{ style: { display: "flex", flexDirection: "column", gap: 10 } },
|
|
816
|
+
{ style: { display: "flex", flexDirection: "column", gap: 10, marginTop: 4 } },
|
|
662
817
|
React.createElement(
|
|
663
818
|
"div",
|
|
664
819
|
null,
|
|
665
820
|
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "AppID \u2014 QQ \u5F00\u653E\u5E73\u53F0\u673A\u5668\u4EBA\u5E94\u7528 ID"),
|
|
666
821
|
React.createElement("input", {
|
|
667
|
-
style: { ...s.input, width:
|
|
822
|
+
style: { ...s.input, width: "100%" },
|
|
668
823
|
placeholder: "\u8BF7\u8F93\u5165 AppID",
|
|
669
824
|
value: cfgDraft.appId,
|
|
670
825
|
onChange: (e) => setCfgDraft((d) => ({ ...d, appId: e.target.value }))
|
|
@@ -673,20 +828,40 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
673
828
|
React.createElement(
|
|
674
829
|
"div",
|
|
675
830
|
null,
|
|
676
|
-
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "ClientSecret \u2014 QQ \u5F00\u653E\u5E73\u53F0\u673A\u5668\u4EBA\u5BC6\u94A5"),
|
|
677
|
-
React.createElement(
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
831
|
+
React.createElement("div", { style: { ...s.muted, marginBottom: 4 } }, "ClientSecret \u2014 QQ \u5F00\u653E\u5E73\u53F0\u673A\u5668\u4EBA\u5BC6\u94A5\uFF08\u7559\u7A7A\u5219\u4FDD\u6301\u5DF2\u4FDD\u5B58\u5BC6\u94A5\uFF09"),
|
|
832
|
+
React.createElement(
|
|
833
|
+
"div",
|
|
834
|
+
{ style: { display: "flex", gap: 6, alignItems: "center" } },
|
|
835
|
+
React.createElement("input", {
|
|
836
|
+
style: { ...s.input, flex: 1 },
|
|
837
|
+
type: showSecret ? "text" : "password",
|
|
838
|
+
placeholder: "\u7559\u7A7A\u4FDD\u6301\u5DF2\u4FDD\u5B58\u5BC6\u94A5",
|
|
839
|
+
value: cfgDraft.clientSecret,
|
|
840
|
+
onChange: (e) => setCfgDraft((d) => ({ ...d, clientSecret: e.target.value }))
|
|
841
|
+
}),
|
|
842
|
+
React.createElement("button", {
|
|
843
|
+
style: { ...s.btnGhost, height: 32, padding: "0 10px", fontSize: 13, flexShrink: 0 },
|
|
844
|
+
onClick: () => setShowSecret((v) => !v),
|
|
845
|
+
type: "button",
|
|
846
|
+
title: showSecret ? "\u9690\u85CF\u5BC6\u94A5" : "\u663E\u793A\u660E\u6587"
|
|
847
|
+
}, showSecret ? "\u{1F648} \u9690\u85CF" : "\u{1F441}\uFE0F \u663E\u793A")
|
|
848
|
+
)
|
|
683
849
|
)
|
|
684
850
|
),
|
|
685
|
-
React.createElement(
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
851
|
+
React.createElement(
|
|
852
|
+
"div",
|
|
853
|
+
{ style: { display: "flex", gap: 8, alignItems: "center", marginTop: 4 } },
|
|
854
|
+
React.createElement("button", {
|
|
855
|
+
style: { ...s.btnPri, opacity: cfgDirty && !busy ? 1 : 0.5 },
|
|
856
|
+
disabled: !cfgDirty || busy,
|
|
857
|
+
onClick: saveConfig
|
|
858
|
+
}, busy ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u8BBE\u7F6E"),
|
|
859
|
+
React.createElement("button", {
|
|
860
|
+
style: { ...s.btnGhost, height: 32, fontSize: 12 },
|
|
861
|
+
onClick: resetDefaults,
|
|
862
|
+
title: "\u6062\u590D\u63A8\u8350\u9ED8\u8BA4\u914D\u7F6E"
|
|
863
|
+
}, "\u21BA \u6062\u590D\u63A8\u8350\u9ED8\u8BA4")
|
|
864
|
+
)
|
|
690
865
|
)
|
|
691
866
|
),
|
|
692
867
|
React.createElement(
|
|
@@ -832,9 +1007,9 @@ function VersionBanner({ rpcCall }) {
|
|
|
832
1007
|
);
|
|
833
1008
|
}
|
|
834
1009
|
var TABS = [
|
|
835
|
-
{ id: "lan", label: "\u5C40\u57DF\u7F51" },
|
|
836
|
-
{ id: "tunnel", label: "\u516C\u7F51\u96A7\u9053" },
|
|
837
|
-
{ id: "im", label: "IM \u673A\u5668\u4EBA" }
|
|
1010
|
+
{ id: "lan", label: "\u5C40\u57DF\u7F51", icon: "\u{1F4F6}" },
|
|
1011
|
+
{ id: "tunnel", label: "\u516C\u7F51\u96A7\u9053", icon: "\u{1F310}" },
|
|
1012
|
+
{ id: "im", label: "IM \u673A\u5668\u4EBA", icon: "\u{1F916}" }
|
|
838
1013
|
];
|
|
839
1014
|
function TabBar({ active, onChange, dots }) {
|
|
840
1015
|
return React.createElement(
|
|
@@ -842,12 +1017,12 @@ function TabBar({ active, onChange, dots }) {
|
|
|
842
1017
|
{
|
|
843
1018
|
style: {
|
|
844
1019
|
display: "flex",
|
|
845
|
-
gap:
|
|
1020
|
+
gap: 4,
|
|
846
1021
|
marginBottom: 20,
|
|
847
1022
|
borderBottom: "1px solid var(--dsw-alias-border-l2,#e5e7eb)"
|
|
848
1023
|
}
|
|
849
1024
|
},
|
|
850
|
-
TABS.map(({ id, label }) => {
|
|
1025
|
+
TABS.map(({ id, label, icon }) => {
|
|
851
1026
|
const isActive = active === id;
|
|
852
1027
|
const hasDot = dots?.[id];
|
|
853
1028
|
return React.createElement(
|
|
@@ -873,6 +1048,7 @@ function TabBar({ active, onChange, dots }) {
|
|
|
873
1048
|
whiteSpace: "nowrap"
|
|
874
1049
|
}
|
|
875
1050
|
},
|
|
1051
|
+
React.createElement("span", { style: { fontSize: 14 } }, icon),
|
|
876
1052
|
label,
|
|
877
1053
|
hasDot && React.createElement("span", {
|
|
878
1054
|
style: {
|
|
@@ -1011,9 +1187,9 @@ function BridgePanel({ rpcCall }) {
|
|
|
1011
1187
|
);
|
|
1012
1188
|
} else if (activeTab === "im") {
|
|
1013
1189
|
const IM_PLATFORMS = [
|
|
1014
|
-
{ id: "wechat", label: "\u5FAE\u4FE1", desc: "
|
|
1015
|
-
{ id: "qq", label: "QQ",
|
|
1016
|
-
{ id: "feishu", label: "\u98DE\u4E66", desc: "\u5B98\u65B9\u4E8B\u4EF6\u56DE\u8C03 API" }
|
|
1190
|
+
{ id: "wechat", label: "\u5FAE\u4FE1", icon: "\u{1F4AC}", desc: "ClawBot \u626B\u7801\u76F4\u8FDE \xB7 \u65E0\u9700\u516C\u7F51" },
|
|
1191
|
+
{ id: "qq", label: "QQ", icon: "\u{1F427}", desc: "\u5B98\u65B9\u673A\u5668\u4EBA \xB7 \u79C1\u804A/\u7FA4\u804A/\u6309\u94AE" },
|
|
1192
|
+
{ id: "feishu", label: "\u98DE\u4E66", icon: "\u{1F54A}\uFE0F", desc: "\u5B98\u65B9\u4E8B\u4EF6\u56DE\u8C03 API" }
|
|
1017
1193
|
];
|
|
1018
1194
|
tabContent = React.createElement(
|
|
1019
1195
|
"div",
|
|
@@ -1024,7 +1200,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
1024
1200
|
{
|
|
1025
1201
|
style: { display: "flex", gap: 10, marginBottom: 16, flexWrap: "wrap" }
|
|
1026
1202
|
},
|
|
1027
|
-
IM_PLATFORMS.map(({ id, label, desc }) => {
|
|
1203
|
+
IM_PLATFORMS.map(({ id, label, icon, desc }) => {
|
|
1028
1204
|
const platformData = platforms?.[id];
|
|
1029
1205
|
const available = !!platformData;
|
|
1030
1206
|
const active = platformData?.status === "connected" || platformData?.status === "starting" || platformData?.status === "reconnecting";
|
|
@@ -1033,21 +1209,27 @@ function BridgePanel({ rpcCall }) {
|
|
|
1033
1209
|
{
|
|
1034
1210
|
key: id,
|
|
1035
1211
|
style: {
|
|
1036
|
-
flex: "1 1
|
|
1037
|
-
border: `1px solid ${selectedPlatform === id ? "var(--dsw-alias-
|
|
1212
|
+
flex: "1 1 150px",
|
|
1213
|
+
border: `1px solid ${selectedPlatform === id ? "var(--dsw-alias-brand-primary,#4f6ef7)" : active ? "var(--dsw-alias-state-success-primary,#10b981)" : "var(--dsw-alias-border-l2,#e5e7eb)"}`,
|
|
1038
1214
|
borderRadius: 10,
|
|
1039
1215
|
padding: "12px 14px",
|
|
1040
|
-
opacity: available ? 1 : 0.
|
|
1216
|
+
opacity: available ? 1 : 0.5,
|
|
1041
1217
|
cursor: available ? "pointer" : "not-allowed",
|
|
1042
|
-
background: selectedPlatform === id ? "var(--dsw-alias-state-info-bg,#eff6ff)" : active ? "var(--dsw-alias-state-success-bg,#ecfdf5)" :
|
|
1218
|
+
background: selectedPlatform === id ? "var(--dsw-alias-state-info-bg,#eff6ff)" : active ? "var(--dsw-alias-state-success-bg,#ecfdf5)" : "var(--dsw-alias-bg-layer-2,#f9fafb)",
|
|
1219
|
+
boxShadow: selectedPlatform === id ? "0 0 0 1px var(--dsw-alias-brand-primary,#4f6ef7)" : "none",
|
|
1043
1220
|
transition: "all 0.15s ease"
|
|
1044
1221
|
},
|
|
1045
1222
|
onClick: available ? () => setSelectedPlatform(id) : void 0
|
|
1046
1223
|
},
|
|
1047
1224
|
React.createElement(
|
|
1048
1225
|
"div",
|
|
1049
|
-
{ style: { ...s.label, fontSize: 13, display: "flex", alignItems: "center",
|
|
1050
|
-
|
|
1226
|
+
{ style: { ...s.label, fontSize: 13, display: "flex", alignItems: "center", justifyContent: "space-between" } },
|
|
1227
|
+
React.createElement(
|
|
1228
|
+
"span",
|
|
1229
|
+
{ style: { display: "flex", alignItems: "center", gap: 6 } },
|
|
1230
|
+
React.createElement("span", { style: { fontSize: 14 } }, icon),
|
|
1231
|
+
label
|
|
1232
|
+
),
|
|
1051
1233
|
active && React.createElement("span", {
|
|
1052
1234
|
style: { width: 6, height: 6, borderRadius: "50%", background: "var(--dsw-alias-state-success-primary,#10b981)", flexShrink: 0 }
|
|
1053
1235
|
}),
|
|
@@ -1058,7 +1240,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
1058
1240
|
style: { fontSize: 11, color: "var(--dsw-alias-label-tertiary,#9ca3af)", fontWeight: 400 }
|
|
1059
1241
|
}, "\u5373\u5C06\u652F\u6301")
|
|
1060
1242
|
),
|
|
1061
|
-
React.createElement("div", { style: { ...s.muted, marginTop:
|
|
1243
|
+
React.createElement("div", { style: { ...s.muted, marginTop: 4, fontSize: 11 } }, desc)
|
|
1062
1244
|
);
|
|
1063
1245
|
})
|
|
1064
1246
|
),
|
|
@@ -1076,7 +1258,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
1076
1258
|
}
|
|
1077
1259
|
return React.createElement(
|
|
1078
1260
|
"div",
|
|
1079
|
-
{ style: { maxWidth:
|
|
1261
|
+
{ style: { maxWidth: 620 } },
|
|
1080
1262
|
err && React.createElement("div", {
|
|
1081
1263
|
style: { ...s.card, background: "var(--dsw-alias-state-error-bg,#fef2f2)", color: "var(--dsw-alias-state-error-primary,#dc2626)", fontSize: 13, marginBottom: 16 }
|
|
1082
1264
|
}, err),
|