@wenbin_wb/dsh-bridge 2.10.4 → 2.10.6
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/CHANGELOG.md +26 -0
- package/README.en.md +410 -410
- package/README.md +432 -432
- package/client/client.js +368 -66
- package/client/index.js +320 -66
- package/docs/CODE_REVIEW.md +220 -0
- package/docs/telegram-usage.md +1 -1
- package/lib/auth/manager.js +5 -4
- package/lib/bridge-rpc.js +19 -0
- package/lib/cloudflared-manager.mjs +513 -361
- package/lib/compat.js +129 -129
- package/lib/feishu/index.js +225 -225
- package/lib/feishu/node.js +439 -439
- package/lib/index.js +43 -8
- package/lib/platform/base.js +147 -147
- package/lib/platform/commands.js +221 -221
- package/lib/platform/conversation-bridge.js +821 -821
- package/lib/platform/dsh-storage.js +117 -117
- package/lib/platform/index.js +10 -10
- package/lib/platform/message-split.js +229 -229
- package/lib/platform/session-catalog.js +372 -372
- package/lib/platform/stream-slices.js +21 -21
- package/lib/qq/index.js +312 -312
- package/lib/telegram/index.js +216 -216
- package/lib/telegram/node.js +322 -322
- package/lib/wechat/gateway.js +986 -986
- package/lib/wechat/index.js +244 -244
- package/lib/wechat/media.js +285 -285
- package/lib/wechat/node.js +352 -352
- package/package.json +2 -2
- package/docs/fix-plan-202608.md +0 -108
- package/docs/fix-tunnel-sse-and-session-list.md +0 -134
- package/docs/platform-abstraction-design.md +0 -473
- package/docs/wechat-bot-plan.md +0 -294
package/client/client.js
CHANGED
|
@@ -1222,14 +1222,14 @@ function StatusTag({ running, status }) {
|
|
|
1222
1222
|
bg = "var(--dsw-alias-state-success-bg,#ecfdf5)";
|
|
1223
1223
|
color = "var(--dsw-alias-state-success-primary,#059669)";
|
|
1224
1224
|
text = "\u5DF2\u8FDE\u63A5";
|
|
1225
|
-
} else if (status === "starting") {
|
|
1225
|
+
} else if (status === "starting" || status === "connecting" || status === "downloading") {
|
|
1226
1226
|
bg = "var(--dsw-alias-state-info-bg,#eff6ff)";
|
|
1227
1227
|
color = "var(--dsw-alias-state-info-primary,#3b82f6)";
|
|
1228
|
-
text = "\u8FDE\u63A5\u4E2D\u2026";
|
|
1228
|
+
text = status === "downloading" ? "\u4E0B\u8F7D\u4E2D\u2026" : "\u8FDE\u63A5\u4E2D\u2026";
|
|
1229
1229
|
} else if (status === "reconnecting") {
|
|
1230
1230
|
bg = "var(--dsw-alias-state-warn-bg,#fffbeb)";
|
|
1231
1231
|
color = "var(--dsw-alias-state-warn-primary,#d97706)";
|
|
1232
|
-
text = "\u91CD\u8FDE\u4E2D\u2026";
|
|
1232
|
+
text = "\u81EA\u52A8\u91CD\u8FDE\u4E2D\u2026";
|
|
1233
1233
|
} else if (status === "paused") {
|
|
1234
1234
|
bg = "var(--dsw-alias-state-warn-bg,#fffbeb)";
|
|
1235
1235
|
color = "var(--dsw-alias-state-warn-primary,#d97706)";
|
|
@@ -1445,6 +1445,185 @@ var CustomTunnelGuide = React.memo(function CustomTunnelGuide2() {
|
|
|
1445
1445
|
}, "\u67E5\u770B\u81EA\u5EFA\u96A7\u9053\u670D\u52A1\u5668\u642D\u5EFA\u6559\u7A0B")
|
|
1446
1446
|
);
|
|
1447
1447
|
});
|
|
1448
|
+
var TunnelEntryCard = React.memo(function TunnelEntryCard2({
|
|
1449
|
+
entry,
|
|
1450
|
+
onCopy,
|
|
1451
|
+
copied,
|
|
1452
|
+
autoStart,
|
|
1453
|
+
onToggleAutoStart,
|
|
1454
|
+
onStart,
|
|
1455
|
+
onStop,
|
|
1456
|
+
onReset
|
|
1457
|
+
}) {
|
|
1458
|
+
const [showQr, setShowQr] = React.useState(false);
|
|
1459
|
+
const hasUrl = Boolean(entry && entry.url);
|
|
1460
|
+
const active = Boolean(entry && entry.running);
|
|
1461
|
+
return React.createElement(
|
|
1462
|
+
"div",
|
|
1463
|
+
{
|
|
1464
|
+
style: {
|
|
1465
|
+
...s.card,
|
|
1466
|
+
borderColor: active ? "var(--dsw-alias-state-success-border,#a7f3d0)" : void 0,
|
|
1467
|
+
background: active ? "linear-gradient(180deg, var(--dsw-alias-bg-layer-2,#f9fafb), var(--dsw-alias-bg-layer-1,#ffffff))" : void 0
|
|
1468
|
+
}
|
|
1469
|
+
},
|
|
1470
|
+
React.createElement(
|
|
1471
|
+
"div",
|
|
1472
|
+
{ style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 10 } },
|
|
1473
|
+
React.createElement(
|
|
1474
|
+
"div",
|
|
1475
|
+
{ style: { flex: "1 1 auto", minWidth: 0 } },
|
|
1476
|
+
React.createElement(
|
|
1477
|
+
"div",
|
|
1478
|
+
{ style: { display: "flex", alignItems: "center", gap: 8 } },
|
|
1479
|
+
React.createElement("span", { style: { fontSize: 16 } }, "\u{1F310}"),
|
|
1480
|
+
React.createElement("div", { style: s.label }, "\u516C\u7F51\u8BBF\u95EE\u5165\u53E3")
|
|
1481
|
+
),
|
|
1482
|
+
React.createElement(
|
|
1483
|
+
"div",
|
|
1484
|
+
{ style: { ...s.muted, marginTop: 4 } },
|
|
1485
|
+
entry ? entry.title + " \xB7 " + entry.desc : "\u5C1A\u672A\u914D\u7F6E\u4EFB\u4F55\u516C\u7F51\u96A7\u9053\uFF0C\u53EF\u5728\u4E0B\u65B9\u5F00\u542F Cloudflare \u96A7\u9053\u6216\u914D\u7F6E\u81EA\u5EFA\u96A7\u9053"
|
|
1486
|
+
)
|
|
1487
|
+
),
|
|
1488
|
+
React.createElement(StatusTag, {
|
|
1489
|
+
running: active,
|
|
1490
|
+
status: entry && entry.phase && entry.phase !== "ready" ? entry.phase : void 0
|
|
1491
|
+
})
|
|
1492
|
+
),
|
|
1493
|
+
React.createElement(
|
|
1494
|
+
"div",
|
|
1495
|
+
{ style: { ...s.block, display: "flex", flexDirection: "column", gap: 10 } },
|
|
1496
|
+
// 有地址:大号 URL + 复制
|
|
1497
|
+
hasUrl && React.createElement(
|
|
1498
|
+
"div",
|
|
1499
|
+
{
|
|
1500
|
+
style: {
|
|
1501
|
+
padding: "10px 12px",
|
|
1502
|
+
background: "var(--dsw-alias-bg-layer-1,#ffffff)",
|
|
1503
|
+
border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)",
|
|
1504
|
+
borderRadius: 10,
|
|
1505
|
+
display: "flex",
|
|
1506
|
+
alignItems: "center",
|
|
1507
|
+
gap: 10
|
|
1508
|
+
}
|
|
1509
|
+
},
|
|
1510
|
+
React.createElement("code", {
|
|
1511
|
+
style: { ...s.code, flex: "1 1 auto", fontSize: 13.5, wordBreak: "break-all", lineHeight: 1.5 }
|
|
1512
|
+
}, entry.url),
|
|
1513
|
+
React.createElement("button", {
|
|
1514
|
+
style: { ...s.btnGhost, flexShrink: 0, height: 28, padding: "0 12px", fontSize: 12 },
|
|
1515
|
+
onClick: () => onCopy && onCopy(entry.url)
|
|
1516
|
+
}, copied ? "\u2713 \u5DF2\u590D\u5236" : "\u590D\u5236")
|
|
1517
|
+
),
|
|
1518
|
+
// 状态细节(重连/错误/连接中)——无 URL 时格外重要,让用户知道隧道在自愈而非消失
|
|
1519
|
+
entry && entry.stateDetail && React.createElement("div", {
|
|
1520
|
+
style: {
|
|
1521
|
+
fontSize: 12,
|
|
1522
|
+
lineHeight: 1.5,
|
|
1523
|
+
color: entry.phase === "error" ? "var(--dsw-alias-state-error-primary,#dc2626)" : entry.phase === "reconnecting" ? "var(--dsw-alias-state-warn-primary,#d97706)" : "var(--dsw-alias-label-secondary,#6b7280)"
|
|
1524
|
+
}
|
|
1525
|
+
}, entry.stateDetail),
|
|
1526
|
+
// 操作行:running → 关闭/停止重连(+ 重置);!running → 开启
|
|
1527
|
+
active && onStop && React.createElement(
|
|
1528
|
+
"div",
|
|
1529
|
+
{ style: { display: "flex", gap: 8, flexWrap: "wrap" } },
|
|
1530
|
+
React.createElement("button", {
|
|
1531
|
+
style: s.btnGhost,
|
|
1532
|
+
onClick: onStop
|
|
1533
|
+
}, entry && entry.phase === "reconnecting" ? "\u505C\u6B62\u91CD\u8FDE" : "\u5173\u95ED"),
|
|
1534
|
+
onReset && React.createElement("button", {
|
|
1535
|
+
style: { ...s.btnGhost, height: 28, padding: "0 12px", fontSize: 12 },
|
|
1536
|
+
onClick: onReset,
|
|
1537
|
+
title: "\u5173\u95ED\u5E76\u91CD\u65B0\u5F00\u542F\uFF0C\u66F4\u6362\u4E34\u65F6\u5730\u5740"
|
|
1538
|
+
}, "\u{1F504} \u91CD\u7F6E\u94FE\u63A5")
|
|
1539
|
+
),
|
|
1540
|
+
// running 但无 onStop 的入口(如外部登记):只给重置/二维码辅助,无开关
|
|
1541
|
+
active && !onStop && onReset && React.createElement(
|
|
1542
|
+
"div",
|
|
1543
|
+
{ style: { display: "flex", gap: 8, flexWrap: "wrap" } },
|
|
1544
|
+
React.createElement("button", {
|
|
1545
|
+
style: { ...s.btnGhost, height: 28, padding: "0 12px", fontSize: 12 },
|
|
1546
|
+
onClick: onReset,
|
|
1547
|
+
title: "\u5173\u95ED\u5E76\u91CD\u65B0\u5F00\u542F\uFF0C\u66F4\u6362\u4E34\u65F6\u5730\u5740"
|
|
1548
|
+
}, "\u{1F504} \u91CD\u7F6E\u94FE\u63A5")
|
|
1549
|
+
),
|
|
1550
|
+
// 未运行:引导开启(连接中/下载中禁用)
|
|
1551
|
+
!active && onStart && React.createElement("button", {
|
|
1552
|
+
style: {
|
|
1553
|
+
...s.btnPri,
|
|
1554
|
+
alignSelf: "flex-start",
|
|
1555
|
+
opacity: entry && entry.configured === false ? 0.4 : 1,
|
|
1556
|
+
background: entry && entry.phase === "connecting" ? "var(--dsw-alias-state-info-primary,#3b82f6)" : void 0
|
|
1557
|
+
},
|
|
1558
|
+
onClick: onStart,
|
|
1559
|
+
disabled: Boolean(entry && entry.configured === false || entry && (entry.phase === "connecting" || entry.phase === "downloading")),
|
|
1560
|
+
title: entry && entry.configured === false ? "\u8BF7\u5148\u5728\u300C\u96A7\u9053\u914D\u7F6E\u300D\u4E2D\u4FDD\u5B58\u670D\u52A1\u5668\u914D\u7F6E" : ""
|
|
1561
|
+
}, entry && entry.phase === "connecting" ? "\u8FDE\u63A5\u4E2D\u2026" : entry && entry.phase === "downloading" ? "\u4E0B\u8F7D\u4E2D\u2026" : "\u5F00\u542F\u516C\u7F51\u96A7\u9053"),
|
|
1562
|
+
// 二维码辅助按钮:有地址未运行时也可查看(外部登记等)
|
|
1563
|
+
hasUrl && entry.qr && React.createElement(
|
|
1564
|
+
"div",
|
|
1565
|
+
{ style: { display: "flex", gap: 8, flexWrap: "wrap" } },
|
|
1566
|
+
React.createElement("button", {
|
|
1567
|
+
style: { ...s.btnGhost, height: 28, padding: "0 12px", fontSize: 12 },
|
|
1568
|
+
onClick: () => setShowQr((v) => !v)
|
|
1569
|
+
}, showQr ? "\u9690\u85CF\u4E8C\u7EF4\u7801" : "\u663E\u793A\u4E8C\u7EF4\u7801")
|
|
1570
|
+
),
|
|
1571
|
+
showQr && hasUrl && entry.qr && React.createElement(
|
|
1572
|
+
"div",
|
|
1573
|
+
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 6 } },
|
|
1574
|
+
React.createElement("img", { src: entry.qr, alt: "QR", style: { ...s.qr, margin: 0 } }),
|
|
1575
|
+
React.createElement("div", { style: { ...s.muted, fontSize: 11 } }, "\u8BF7\u5728\u79C1\u5BC6\u73AF\u5883\u4E0B\u626B\u7801\u4F7F\u7528")
|
|
1576
|
+
)
|
|
1577
|
+
),
|
|
1578
|
+
onToggleAutoStart && React.createElement(
|
|
1579
|
+
"label",
|
|
1580
|
+
{
|
|
1581
|
+
style: {
|
|
1582
|
+
display: "flex",
|
|
1583
|
+
alignItems: "center",
|
|
1584
|
+
gap: 6,
|
|
1585
|
+
marginTop: 12,
|
|
1586
|
+
paddingTop: 10,
|
|
1587
|
+
borderTop: "1px solid var(--dsw-alias-border-l2,#e5e7eb)",
|
|
1588
|
+
fontSize: 12,
|
|
1589
|
+
color: "var(--dsw-alias-label-secondary,#6b7280)",
|
|
1590
|
+
cursor: "pointer",
|
|
1591
|
+
userSelect: "none"
|
|
1592
|
+
},
|
|
1593
|
+
title: "DSH \u542F\u52A8\u65F6\u81EA\u52A8\u6062\u590D\u8BE5\u96A7\u9053\u7684\u8FD0\u884C\u72B6\u6001"
|
|
1594
|
+
},
|
|
1595
|
+
React.createElement("input", {
|
|
1596
|
+
type: "checkbox",
|
|
1597
|
+
checked: Boolean(autoStart),
|
|
1598
|
+
onChange: (e) => onToggleAutoStart(e.target.checked)
|
|
1599
|
+
}),
|
|
1600
|
+
React.createElement("span", null, "\u968F DSH \u542F\u52A8\u81EA\u52A8\u5F00\u542F")
|
|
1601
|
+
)
|
|
1602
|
+
);
|
|
1603
|
+
});
|
|
1604
|
+
var TunnelConfigGroup = React.memo(function TunnelConfigGroup2({ children }) {
|
|
1605
|
+
const [open, setOpen] = React.useState(false);
|
|
1606
|
+
return React.createElement(
|
|
1607
|
+
"div",
|
|
1608
|
+
{ style: s.card },
|
|
1609
|
+
React.createElement(
|
|
1610
|
+
"div",
|
|
1611
|
+
{
|
|
1612
|
+
style: { display: "flex", alignItems: "center", justifyContent: "space-between", cursor: "pointer", userSelect: "none", gap: 8 },
|
|
1613
|
+
onClick: () => setOpen((v) => !v)
|
|
1614
|
+
},
|
|
1615
|
+
React.createElement(
|
|
1616
|
+
"div",
|
|
1617
|
+
{ style: { display: "flex", alignItems: "center", gap: 8 } },
|
|
1618
|
+
React.createElement("span", { style: { fontSize: 14 } }, "\u2699\uFE0F"),
|
|
1619
|
+
React.createElement("div", { style: s.label }, "\u96A7\u9053\u914D\u7F6E"),
|
|
1620
|
+
React.createElement("span", { style: { ...s.muted, fontSize: 11 } }, "Token \xB7 \u56FA\u5B9A\u57DF\u540D \xB7 \u81EA\u5EFA\u670D\u52A1\u5668 \xB7 \u5916\u90E8\u767B\u8BB0")
|
|
1621
|
+
),
|
|
1622
|
+
React.createElement("span", { style: { fontSize: 12, color: "var(--dsw-alias-label-tertiary,#9ca3af)", flexShrink: 0 } }, open ? "\u6536\u8D77 \u25B4" : "\u5C55\u5F00 \u25BE")
|
|
1623
|
+
),
|
|
1624
|
+
open && React.createElement("div", { style: { marginTop: 4 } }, children)
|
|
1625
|
+
);
|
|
1626
|
+
});
|
|
1448
1627
|
var CustomTunnelConfigForm = React.memo(function CustomTunnelConfigForm2({ serverUrl: initUrl, accessToken: initToken, onSave }) {
|
|
1449
1628
|
const [serverUrl, setServerUrl] = React.useState(initUrl ?? "");
|
|
1450
1629
|
const [accessToken, setAccessToken] = React.useState(initToken ?? "");
|
|
@@ -1561,7 +1740,7 @@ var TunnelCard = React.memo(function TunnelCard2({
|
|
|
1561
1740
|
React.createElement(
|
|
1562
1741
|
"div",
|
|
1563
1742
|
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 6 } },
|
|
1564
|
-
React.createElement(StatusTag, { running }),
|
|
1743
|
+
React.createElement(StatusTag, { running, status: phase === "ready" ? void 0 : phase }),
|
|
1565
1744
|
onToggleAutoStart && React.createElement(
|
|
1566
1745
|
"label",
|
|
1567
1746
|
{
|
|
@@ -1590,7 +1769,7 @@ var TunnelCard = React.memo(function TunnelCard2({
|
|
|
1590
1769
|
style: {
|
|
1591
1770
|
...s.block,
|
|
1592
1771
|
fontSize: 12,
|
|
1593
|
-
color: phase === "error" ? "var(--dsw-alias-state-error-primary,#dc2626)" : "var(--dsw-alias-label-secondary,#6b7280)"
|
|
1772
|
+
color: phase === "error" ? "var(--dsw-alias-state-error-primary,#dc2626)" : phase === "reconnecting" ? "var(--dsw-alias-state-warn-primary,#d97706)" : "var(--dsw-alias-label-secondary,#6b7280)"
|
|
1594
1773
|
}
|
|
1595
1774
|
}, state?.detail ?? phase),
|
|
1596
1775
|
url && React.createElement(QrBlock, { url, qr, onReset, auth, onNavigateSecurity }),
|
|
@@ -1605,7 +1784,10 @@ var TunnelCard = React.memo(function TunnelCard2({
|
|
|
1605
1784
|
disabled: configured === false || phase === "connecting" || phase === "downloading",
|
|
1606
1785
|
title: configured === false ? "\u8BF7\u5148\u4FDD\u5B58\u670D\u52A1\u5668\u914D\u7F6E" : ""
|
|
1607
1786
|
}, phase === "connecting" ? "\u8FDE\u63A5\u4E2D\u2026" : phase === "downloading" ? "\u4E0B\u8F7D\u4E2D\u2026" : "\u5F00\u542F"),
|
|
1608
|
-
running && onStop && React.createElement("button", {
|
|
1787
|
+
running && onStop && React.createElement("button", {
|
|
1788
|
+
style: s.btnGhost,
|
|
1789
|
+
onClick: onStop
|
|
1790
|
+
}, phase === "reconnecting" ? "\u505C\u6B62\u91CD\u8FDE" : "\u5173\u95ED")
|
|
1609
1791
|
)
|
|
1610
1792
|
);
|
|
1611
1793
|
});
|
|
@@ -1820,6 +2002,11 @@ var AccessAuthCard = React.memo(function AccessAuthCard2({ auth, rpcCall, onUpda
|
|
|
1820
2002
|
const next = !enabled;
|
|
1821
2003
|
const noPasswordYet = !auth?.hasPassword && !auth?.hasAdminPassword;
|
|
1822
2004
|
if (next && noPasswordYet && mode !== "token_only") {
|
|
2005
|
+
if (mode === "password_only") {
|
|
2006
|
+
window.alert("\u300C\u4EC5\u5BC6\u7801 / PIN \u7801\u767B\u5F55\u300D\u6A21\u5F0F\u5FC5\u987B\u5148\u8BBE\u7F6E\u8BBF\u95EE\u5BC6\u7801\u624D\u80FD\u5F00\u542F\u5B89\u5168\u9632\u62A4\u3002\n\n\u8BF7\u5148\u5728\u4E0B\u65B9\u300C\u8BBE\u7F6E\u5916\u90E8\u8BBF\u5BA2\u8BBF\u95EE\u5BC6\u7801 / PIN \u7801\u300D\u8F93\u5165\u5BC6\u7801\u5E76\u70B9\u51FB\u300C\u4FDD\u5B58\u8BBF\u95EE\u5BC6\u7801\u300D\uFF0C\u7136\u540E\u518D\u5F00\u542F\u3002");
|
|
2007
|
+
setTopMsg({ ok: false, text: "\u8BF7\u5148\u8BBE\u7F6E\u8BBF\u5BA2\u8BBF\u95EE\u5BC6\u7801\uFF0C\u518D\u5F00\u542F\u5B89\u5168\u9632\u62A4" });
|
|
2008
|
+
return;
|
|
2009
|
+
}
|
|
1823
2010
|
const go = window.confirm(
|
|
1824
2011
|
'\u26A0\uFE0F \u60A8\u5C1A\u672A\u8BBE\u7F6E\u4EFB\u4F55\u8BBF\u95EE\u5BC6\u7801\u6216\u7BA1\u7406\u5BC6\u7801\u3002\n\n\u5F00\u542F\u5B89\u5168\u9632\u62A4\u540E\uFF0C\u4EFB\u4F55\u77E5\u9053\u5C40\u57DF\u7F51 IP / \u96A7\u9053\u5730\u5740\u7684\u8BBF\u5BA2\u4ECD\u53EF\u76F4\u63A5\u8FDB\u5165\uFF08\u5F53\u524D\u76F8\u5F53\u4E8E"\u514D\u5BC6\u5F00\u653E"\u72B6\u6001\uFF09\u3002\n\n\u662F\u5426\u4ECD\u8981\u5F00\u542F\uFF1F\u5EFA\u8BAE\u5148\u5173\u95ED\uFF0C\u5728\u4E0B\u65B9\u300C\u8BBE\u7F6E\u5916\u90E8\u8BBF\u5BA2\u8BBF\u95EE\u5BC6\u7801\u300D\u5904\u8BBE\u7F6E\u5BC6\u7801\u540E\u518D\u5F00\u542F\u3002'
|
|
1825
2012
|
);
|
|
@@ -1851,6 +2038,11 @@ var AccessAuthCard = React.memo(function AccessAuthCard2({ auth, rpcCall, onUpda
|
|
|
1851
2038
|
}
|
|
1852
2039
|
};
|
|
1853
2040
|
const handleChangeMode = async (m) => {
|
|
2041
|
+
if (m === "password_only" && !auth?.hasPassword && !auth?.hasAdminPassword) {
|
|
2042
|
+
window.alert("\u300C\u4EC5\u5BC6\u7801 / PIN \u7801\u767B\u5F55\u300D\u9700\u8981\u5148\u8BBE\u7F6E\u8BBF\u95EE\u5BC6\u7801\u3002\n\n\u8BF7\u5728\u4E0B\u65B9\u300C\u8BBE\u7F6E\u5916\u90E8\u8BBF\u5BA2\u8BBF\u95EE\u5BC6\u7801 / PIN \u7801\u300D\u5904\u8F93\u5165\u5BC6\u7801\u5E76\u70B9\u51FB\u300C\u4FDD\u5B58\u8BBF\u95EE\u5BC6\u7801\u300D\uFF0C\u7136\u540E\u518D\u5207\u6362\u5230\u6B64\u6A21\u5F0F\u6216\u5F00\u542F\u5B89\u5168\u9632\u62A4\u3002");
|
|
2043
|
+
setTopMsg({ ok: false, text: "\u8BF7\u5148\u5728\u4E0B\u65B9\u8BBE\u7F6E\u8BBF\u5BA2\u8BBF\u95EE\u5BC6\u7801\uFF0C\u518D\u5207\u6362\u4E3A\u300C\u4EC5\u5BC6\u7801\u767B\u5F55\u300D\u6A21\u5F0F" });
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
1854
2046
|
const prev = mode;
|
|
1855
2047
|
setMode(m);
|
|
1856
2048
|
try {
|
|
@@ -2064,7 +2256,10 @@ var AccessAuthCard = React.memo(function AccessAuthCard2({ auth, rpcCall, onUpda
|
|
|
2064
2256
|
// =========================================================================
|
|
2065
2257
|
// ---- 第一道防线:外部访问门禁(控制谁能进入 Web 界面使用 AI) ----
|
|
2066
2258
|
// =========================================================================
|
|
2067
|
-
|
|
2259
|
+
// 第一道防线卡片:已开启防护,或【尚未设置任何密码】时始终显示——
|
|
2260
|
+
// 未设密码时必须给出密码输入框,否则用户开启防护(尤其 password_only)后
|
|
2261
|
+
// 会因无密码被锁在登录墙外且找不到设密码入口(自我锁死,v2.10.5 修复)。
|
|
2262
|
+
(enabled || !auth?.hasPassword) && React.createElement(
|
|
2068
2263
|
"div",
|
|
2069
2264
|
{ style: s.card },
|
|
2070
2265
|
React.createElement(
|
|
@@ -3863,6 +4058,18 @@ function BridgePanel({ rpcCall }) {
|
|
|
3863
4058
|
const [activeTab, setActiveTab] = React.useState("lan");
|
|
3864
4059
|
const [platforms, setPlatforms] = React.useState(null);
|
|
3865
4060
|
const [selectedPlatform, setSelectedPlatform] = React.useState("wechat");
|
|
4061
|
+
const [copiedUrl, setCopiedUrl] = React.useState("");
|
|
4062
|
+
const copyEntryUrl = React.useCallback((url) => {
|
|
4063
|
+
const done = () => {
|
|
4064
|
+
setCopiedUrl(url);
|
|
4065
|
+
setTimeout(() => setCopiedUrl(""), 2e3);
|
|
4066
|
+
};
|
|
4067
|
+
if (navigator.clipboard?.writeText) {
|
|
4068
|
+
navigator.clipboard.writeText(url).then(done).catch(() => done());
|
|
4069
|
+
} else {
|
|
4070
|
+
done();
|
|
4071
|
+
}
|
|
4072
|
+
}, []);
|
|
3866
4073
|
const isLocalhost = typeof window === "undefined" || (!window.location.hostname || window.location.hostname === "127.0.0.1" || window.location.hostname === "localhost" || window.location.hostname === "::1" || window.location.hostname === "" || window.location.protocol === "file:" || window.location.protocol === "vscode-webview:" || window.location.protocol === "app:" || window.location.hostname.endsWith(".local"));
|
|
3867
4074
|
const [adminUnlocked, setAdminUnlocked] = React.useState(false);
|
|
3868
4075
|
const [unlockPassword, setUnlockPassword] = React.useState("");
|
|
@@ -4085,62 +4292,122 @@ function BridgePanel({ rpcCall }) {
|
|
|
4085
4292
|
);
|
|
4086
4293
|
} else if (activeTab === "tunnel") {
|
|
4087
4294
|
const ext = status?.externalTunnel;
|
|
4295
|
+
const cf = status?.cloudflared;
|
|
4296
|
+
const cfDesc = cf?.tokenConfigured ? "\u56FA\u5B9A\u57DF\u540D\u6A21\u5F0F" : "\u514D\u767B\u5F55\u4E34\u65F6\u57DF\u540D";
|
|
4297
|
+
const entries = [
|
|
4298
|
+
ct && ct.running && {
|
|
4299
|
+
key: "custom",
|
|
4300
|
+
title: "\u81EA\u5EFA\u96A7\u9053",
|
|
4301
|
+
desc: "VPS \u81EA\u5EFA \xB7 \u56FA\u5B9A\u5730\u5740",
|
|
4302
|
+
url: ct.url || null,
|
|
4303
|
+
qr: ct.qr,
|
|
4304
|
+
running: true,
|
|
4305
|
+
phase: ct.state && ct.state.phase,
|
|
4306
|
+
stateDetail: ct.state && ct.state.detail,
|
|
4307
|
+
autoStart: ct.autoStart,
|
|
4308
|
+
onToggleAutoStart: onToggleCustomAutoStart,
|
|
4309
|
+
onStart: onStartCustom,
|
|
4310
|
+
onStop: onStopCustom
|
|
4311
|
+
},
|
|
4312
|
+
cf && cf.running && {
|
|
4313
|
+
key: "cloudflared",
|
|
4314
|
+
title: "Cloudflare \u96A7\u9053",
|
|
4315
|
+
desc: cfDesc,
|
|
4316
|
+
url: cf.url || null,
|
|
4317
|
+
qr: cf.qr,
|
|
4318
|
+
running: true,
|
|
4319
|
+
phase: cf.state && cf.state.phase,
|
|
4320
|
+
stateDetail: cf.state && cf.state.detail,
|
|
4321
|
+
autoStart: cf.autoStart,
|
|
4322
|
+
onToggleAutoStart: onToggleCloudflaredAutoStart,
|
|
4323
|
+
onStart: onStartCloudflared,
|
|
4324
|
+
onStop: onStopCloudflared,
|
|
4325
|
+
onReset: onResetCloudflared
|
|
4326
|
+
},
|
|
4327
|
+
ext && ext.configured && ext.url && {
|
|
4328
|
+
key: "external",
|
|
4329
|
+
title: "\u5916\u90E8\u5DF2\u90E8\u7F72\u96A7\u9053",
|
|
4330
|
+
desc: "\u81EA\u884C\u90E8\u7F72\u767B\u8BB0",
|
|
4331
|
+
url: ext.url,
|
|
4332
|
+
qr: ext.qr,
|
|
4333
|
+
running: true
|
|
4334
|
+
}
|
|
4335
|
+
].filter(Boolean);
|
|
4336
|
+
const primary = entries[0] || null;
|
|
4337
|
+
const otherCount = primary ? entries.length - 1 : entries.length;
|
|
4088
4338
|
tabContent = React.createElement(
|
|
4089
4339
|
React.Fragment,
|
|
4090
4340
|
null,
|
|
4091
|
-
React.createElement(
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
state: status?.cloudflared?.state
|
|
4101
|
-
},
|
|
4102
|
-
autoStart: status?.cloudflared?.autoStart,
|
|
4103
|
-
onToggleAutoStart: onToggleCloudflaredAutoStart,
|
|
4104
|
-
auth: status?.auth,
|
|
4105
|
-
onNavigateSecurity: navSecurity,
|
|
4106
|
-
onStart: onStartCloudflared,
|
|
4107
|
-
onStop: onStopCloudflared,
|
|
4108
|
-
onReset: status?.cloudflared?.running ? onResetCloudflared : null
|
|
4109
|
-
},
|
|
4110
|
-
React.createElement(CloudflareConfigForm, {
|
|
4111
|
-
token: status?.cloudflared?.token ?? "",
|
|
4112
|
-
hostname: status?.cloudflared?.hostname ?? "",
|
|
4113
|
-
onSave: saveCloudflaredConfig
|
|
4114
|
-
})
|
|
4115
|
-
),
|
|
4116
|
-
React.createElement(ExternalTunnelCard, {
|
|
4117
|
-
ext,
|
|
4118
|
-
onSave: saveExternalTunnel
|
|
4341
|
+
React.createElement(TunnelEntryCard, {
|
|
4342
|
+
entry: primary,
|
|
4343
|
+
onCopy: copyEntryUrl,
|
|
4344
|
+
copied: Boolean(copiedUrl && primary && copiedUrl === primary.url),
|
|
4345
|
+
autoStart: primary ? primary.autoStart : void 0,
|
|
4346
|
+
onToggleAutoStart: primary ? primary.onToggleAutoStart : void 0,
|
|
4347
|
+
onStart: primary ? primary.onStart : cf ? onStartCloudflared : null,
|
|
4348
|
+
onStop: primary ? primary.onStop : void 0,
|
|
4349
|
+
onReset: primary ? primary.onReset : void 0
|
|
4119
4350
|
}),
|
|
4351
|
+
otherCount > 0 && React.createElement("div", {
|
|
4352
|
+
style: { ...s.muted, fontSize: 11, marginBottom: 8, textAlign: "center" }
|
|
4353
|
+
}, "\u53E6\u6709 " + otherCount + " \u4E2A\u96A7\u9053\u5165\u53E3\u5728\u8FD0\u884C\uFF0C\u53EF\u5728\u4E0B\u65B9\u300C\u96A7\u9053\u914D\u7F6E\u300D\u4E2D\u67E5\u770B\u4E0E\u7BA1\u7406"),
|
|
4120
4354
|
React.createElement(
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4355
|
+
TunnelConfigGroup,
|
|
4356
|
+
null,
|
|
4357
|
+
React.createElement(
|
|
4358
|
+
TunnelCard,
|
|
4359
|
+
{
|
|
4360
|
+
title: "Cloudflare \u96A7\u9053",
|
|
4361
|
+
desc: cf && cf.tokenConfigured ? "\u56FA\u5B9A\u57DF\u540D\u6A21\u5F0F\uFF08Token \u8FD0\u884C \xB7 \u91CD\u542F URL \u4FDD\u6301\u4E0D\u53D8\uFF09" : "\u4E00\u952E\u83B7\u53D6\u516C\u7F51\u5730\u5740\uFF08\u514D\u767B\u5F55\u4E34\u65F6\u968F\u673A\u57DF\u540D\uFF09",
|
|
4362
|
+
data: {
|
|
4363
|
+
running: cf && cf.running,
|
|
4364
|
+
url: cf && cf.url,
|
|
4365
|
+
qr: cf && cf.qr,
|
|
4366
|
+
state: cf && cf.state
|
|
4367
|
+
},
|
|
4368
|
+
autoStart: cf && cf.autoStart,
|
|
4369
|
+
onToggleAutoStart: onToggleCloudflaredAutoStart,
|
|
4370
|
+
auth: status && status.auth,
|
|
4371
|
+
onNavigateSecurity: navSecurity,
|
|
4372
|
+
onStart: onStartCloudflared,
|
|
4373
|
+
onStop: onStopCloudflared,
|
|
4374
|
+
onReset: cf && cf.running ? onResetCloudflared : null
|
|
4131
4375
|
},
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4376
|
+
React.createElement(CloudflareConfigForm, {
|
|
4377
|
+
token: cf && cf.token || "",
|
|
4378
|
+
hostname: cf && cf.hostname || "",
|
|
4379
|
+
onSave: saveCloudflaredConfig
|
|
4380
|
+
})
|
|
4381
|
+
),
|
|
4382
|
+
React.createElement(
|
|
4383
|
+
TunnelCard,
|
|
4384
|
+
{
|
|
4385
|
+
title: "\u81EA\u5EFA\u96A7\u9053",
|
|
4386
|
+
desc: "\u8FDE\u63A5\u81EA\u5DF1\u90E8\u7F72\u7684\u96A7\u9053\u670D\u52A1\u5668\uFF0C\u83B7\u5F97\u56FA\u5B9A\u57DF\u540D",
|
|
4387
|
+
data: {
|
|
4388
|
+
configured: ct && ct.configured,
|
|
4389
|
+
running: ct && ct.running,
|
|
4390
|
+
url: ct && ct.url,
|
|
4391
|
+
qr: ct && ct.qr,
|
|
4392
|
+
state: ct && ct.state
|
|
4393
|
+
},
|
|
4394
|
+
autoStart: ct && ct.autoStart,
|
|
4395
|
+
onToggleAutoStart: onToggleCustomAutoStart,
|
|
4396
|
+
auth: status && status.auth,
|
|
4397
|
+
onNavigateSecurity: navSecurity,
|
|
4398
|
+
onStart: onStartCustom,
|
|
4399
|
+
onStop: onStopCustom
|
|
4400
|
+
},
|
|
4401
|
+
React.createElement(CustomTunnelGuide),
|
|
4402
|
+
React.createElement(CustomTunnelConfigForm, {
|
|
4403
|
+
serverUrl: ct && ct.serverUrl || "",
|
|
4404
|
+
accessToken: ct && ct.accessToken || "",
|
|
4405
|
+
onSave: saveConfig
|
|
4406
|
+
})
|
|
4407
|
+
),
|
|
4408
|
+
React.createElement(ExternalTunnelCard, {
|
|
4409
|
+
ext,
|
|
4410
|
+
onSave: saveExternalTunnel
|
|
4144
4411
|
})
|
|
4145
4412
|
)
|
|
4146
4413
|
);
|
|
@@ -4236,6 +4503,9 @@ function BridgePanel({ rpcCall }) {
|
|
|
4236
4503
|
const auth = status?.auth;
|
|
4237
4504
|
const policy = auth?.adminPolicy ?? "password_unlock";
|
|
4238
4505
|
const hasAnyPassword = !!(auth?.hasPassword || auth?.hasAdminPassword);
|
|
4506
|
+
const unlockUsesAdmin = !!auth?.hasAdminPassword;
|
|
4507
|
+
const unlockPwdKind = unlockUsesAdmin ? "\u7BA1\u7406\u5BC6\u7801" : "\u8BBF\u95EE\u5BC6\u7801";
|
|
4508
|
+
const unlockPwdHint = unlockUsesAdmin ? "\u8BF7\u8F93\u5165\u540E\u53F0\u7BA1\u7406\u5BC6\u7801\u89E3\u9501\u7BA1\u7406\u6743\u9650\u3002" : "\u5F53\u524D\u672A\u8BBE\u7F6E\u72EC\u7ACB\u7BA1\u7406\u5BC6\u7801\uFF0C\u8F93\u5165\u60A8\u7684\u8BBF\u95EE\u5BC6\u7801\u5373\u53EF\u89E3\u9501\u3002";
|
|
4239
4509
|
const isLocked = !isLocalhost && auth?.adminProtection !== false && policy !== "open" && !adminUnlocked && (policy === "local_only" || hasAnyPassword);
|
|
4240
4510
|
if (isLocked) {
|
|
4241
4511
|
return React.createElement(
|
|
@@ -4293,10 +4563,42 @@ function BridgePanel({ rpcCall }) {
|
|
|
4293
4563
|
{ style: { textAlign: "center", marginBottom: 20 } },
|
|
4294
4564
|
React.createElement("div", { style: { fontSize: 40, marginBottom: 10 } }, "\u{1F512}"),
|
|
4295
4565
|
React.createElement("div", { style: { ...s.label, fontSize: 16, fontWeight: 600 } }, "\u7BA1\u7406\u63A7\u5236\u53F0\u5DF2\u9501\u5B9A"),
|
|
4566
|
+
// 醒目提示该输入哪种密码
|
|
4567
|
+
React.createElement(
|
|
4568
|
+
"div",
|
|
4569
|
+
{ style: { marginTop: 10, display: "flex", justifyContent: "center" } },
|
|
4570
|
+
unlockUsesAdmin ? React.createElement("span", {
|
|
4571
|
+
style: {
|
|
4572
|
+
display: "inline-flex",
|
|
4573
|
+
alignItems: "center",
|
|
4574
|
+
gap: 5,
|
|
4575
|
+
padding: "4px 12px",
|
|
4576
|
+
borderRadius: 999,
|
|
4577
|
+
fontSize: 12,
|
|
4578
|
+
fontWeight: 600,
|
|
4579
|
+
background: "var(--dsw-alias-state-info-bg,#eff6ff)",
|
|
4580
|
+
color: "var(--dsw-alias-state-info-primary,#2563eb)",
|
|
4581
|
+
border: "1px solid var(--dsw-alias-state-info-border,#bfdbfe)"
|
|
4582
|
+
}
|
|
4583
|
+
}, "\u{1F511} \u4F7F\u7528\u7BA1\u7406\u5BC6\u7801\u89E3\u9501") : React.createElement("span", {
|
|
4584
|
+
style: {
|
|
4585
|
+
display: "inline-flex",
|
|
4586
|
+
alignItems: "center",
|
|
4587
|
+
gap: 5,
|
|
4588
|
+
padding: "4px 12px",
|
|
4589
|
+
borderRadius: 999,
|
|
4590
|
+
fontSize: 12,
|
|
4591
|
+
fontWeight: 600,
|
|
4592
|
+
background: "var(--dsw-alias-state-success-bg,#ecfdf5)",
|
|
4593
|
+
color: "var(--dsw-alias-state-success-primary,#059669)",
|
|
4594
|
+
border: "1px solid var(--dsw-alias-state-success-border,#a7f3d0)"
|
|
4595
|
+
}
|
|
4596
|
+
}, "\u{1F510} \u4F7F\u7528\u8BBF\u95EE\u5BC6\u7801\u89E3\u9501")
|
|
4597
|
+
),
|
|
4296
4598
|
React.createElement(
|
|
4297
4599
|
"div",
|
|
4298
|
-
{ style: { ...s.muted, fontSize: 12, marginTop:
|
|
4299
|
-
"\u5F53\u524D\u8BBE\u5907\u4E3A\u8FDC\u7A0B\u8BBF\u95EE\u3002\u4E3A\u4FDD\u62A4\u60A8\u7684\u7F51\u7EDC\u4E0E\u5E73\u53F0\u914D\u7F6E\u5B89\u5168\uFF0C
|
|
4600
|
+
{ style: { ...s.muted, fontSize: 12, marginTop: 10, lineHeight: 1.6 } },
|
|
4601
|
+
"\u5F53\u524D\u8BBE\u5907\u4E3A\u8FDC\u7A0B\u8BBF\u95EE\u3002\u4E3A\u4FDD\u62A4\u60A8\u7684\u7F51\u7EDC\u4E0E\u5E73\u53F0\u914D\u7F6E\u5B89\u5168\uFF0C" + unlockPwdHint
|
|
4300
4602
|
)
|
|
4301
4603
|
),
|
|
4302
4604
|
React.createElement(
|
|
@@ -4308,7 +4610,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
4308
4610
|
React.createElement("input", {
|
|
4309
4611
|
type: "password",
|
|
4310
4612
|
style: s.input,
|
|
4311
|
-
placeholder: "\u8F93\u5165
|
|
4613
|
+
placeholder: "\u8F93\u5165" + unlockPwdKind,
|
|
4312
4614
|
value: unlockPassword,
|
|
4313
4615
|
onChange: (e) => setUnlockPassword(e.target.value),
|
|
4314
4616
|
autoFocus: true
|
|
@@ -4329,7 +4631,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
4329
4631
|
type: "button",
|
|
4330
4632
|
style: { ...s.btnLink, fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)" },
|
|
4331
4633
|
onClick: () => setShowForgotGuide((v) => !v)
|
|
4332
|
-
}, "\u2753 \u5FD8\u8BB0\
|
|
4634
|
+
}, "\u2753 \u5FD8\u8BB0" + unlockPwdKind + "\uFF1F")
|
|
4333
4635
|
),
|
|
4334
4636
|
showForgotGuide && React.createElement(
|
|
4335
4637
|
"div",
|
|
@@ -4346,8 +4648,8 @@ function BridgePanel({ rpcCall }) {
|
|
|
4346
4648
|
textAlign: "left"
|
|
4347
4649
|
}
|
|
4348
4650
|
},
|
|
4349
|
-
React.createElement("div", { style: { fontWeight: 600, color: "var(--dsw-alias-label-primary,currentColor)", marginBottom: 4 } }, "\u{1F6DF} \u627E\u56DE\u4E0E\u91CD\u7F6E\
|
|
4350
|
-
React.createElement("div", null, "1. ", React.createElement("strong", null, "\u7535\u8111\u672C\u673A\u76F4\u8FDE\u4FEE\u6539"), "\uFF1A\u76F4\u63A5\u5728\u8FD0\u884C\u672C\u7A0B\u5E8F\u7684\u7535\u8111\u672C\u673A\u6253\u5F00\u672C\u63A7\u5236\u53F0\uFF08127.0.0.1 \u4EAB\u6709\u7269\u7406\u514D\u9501\u7279\u6743\uFF09\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539\
|
|
4651
|
+
React.createElement("div", { style: { fontWeight: 600, color: "var(--dsw-alias-label-primary,currentColor)", marginBottom: 4 } }, "\u{1F6DF} \u627E\u56DE\u4E0E\u91CD\u7F6E" + unlockPwdKind + "\u6307\u5F15\uFF1A"),
|
|
4652
|
+
React.createElement("div", null, "1. ", React.createElement("strong", null, "\u7535\u8111\u672C\u673A\u76F4\u8FDE\u4FEE\u6539"), "\uFF1A\u76F4\u63A5\u5728\u8FD0\u884C\u672C\u7A0B\u5E8F\u7684\u7535\u8111\u672C\u673A\u6253\u5F00\u672C\u63A7\u5236\u53F0\uFF08127.0.0.1 \u4EAB\u6709\u7269\u7406\u514D\u9501\u7279\u6743\uFF09\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539\u6216\u6E05\u9664\u5BC6\u7801\u3002"),
|
|
4351
4653
|
React.createElement("div", { style: { marginTop: 4 } }, "2. ", React.createElement("strong", null, "\u670D\u52A1\u5668 / \u65E0\u5934\u73AF\u5883"), "\uFF1A\u6551\u6025\u91CD\u7F6E\u6B65\u9AA4\u53C2\u89C1 GitHub README \u7684\u300C\u4E09\u91CD\u5BB9\u707E\u4FDD\u547D\u4F53\u7CFB\u300D\u7AE0\u8282\u3002")
|
|
4352
4654
|
)
|
|
4353
4655
|
)
|
|
@@ -4382,7 +4684,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
4382
4684
|
setUnlockErr(err);
|
|
4383
4685
|
setShowUnlockModal(true);
|
|
4384
4686
|
}
|
|
4385
|
-
}, "\u{1F511} \u7ACB\u5373\u8F93\u5165\
|
|
4687
|
+
}, "\u{1F511} \u7ACB\u5373\u8F93\u5165" + unlockPwdKind + "\u89E3\u9501")
|
|
4386
4688
|
),
|
|
4387
4689
|
// 管理员解锁状态提示条
|
|
4388
4690
|
!isLocalhost && adminUnlocked && React.createElement(
|
|
@@ -4490,7 +4792,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
4490
4792
|
React.createElement(
|
|
4491
4793
|
"div",
|
|
4492
4794
|
{ style: { fontSize: 13, color: "var(--dsw-alias-label-secondary,#4b5563)", marginBottom: 16, lineHeight: 1.5 } },
|
|
4493
|
-
"\u5F53\u524D\u64CD\u4F5C\u9700\u8981\u540E\u53F0\u7BA1\u7406\u5458\u6743\u9650\u3002\u4E3A\u4FDD\u62A4\u60A8\u7684\u7F51\u7EDC\u914D\u7F6E\u4E0E\u673A\u5668\u4EBA\u5E73\u53F0\u5B89\u5168\uFF0C\u8BF7\u8F93\u5165\u7BA1\u7406\u5BC6\u7801\u89E3\u9501\uFF1A"
|
|
4795
|
+
unlockUsesAdmin ? "\u5F53\u524D\u64CD\u4F5C\u9700\u8981\u540E\u53F0\u7BA1\u7406\u5458\u6743\u9650\u3002\u4E3A\u4FDD\u62A4\u60A8\u7684\u7F51\u7EDC\u914D\u7F6E\u4E0E\u673A\u5668\u4EBA\u5E73\u53F0\u5B89\u5168\uFF0C\u8BF7\u8F93\u5165\u7BA1\u7406\u5BC6\u7801\u89E3\u9501\uFF1A" : "\u5F53\u524D\u64CD\u4F5C\u9700\u8981\u540E\u53F0\u7BA1\u7406\u6743\u9650\u3002\u672A\u8BBE\u7F6E\u72EC\u7ACB\u7BA1\u7406\u5BC6\u7801\uFF0C\u8F93\u5165\u60A8\u7684\u8BBF\u95EE\u5BC6\u7801\u5373\u53EF\u89E3\u9501\uFF1A"
|
|
4494
4796
|
),
|
|
4495
4797
|
React.createElement(
|
|
4496
4798
|
"form",
|
|
@@ -4501,7 +4803,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
4501
4803
|
React.createElement("input", {
|
|
4502
4804
|
type: "password",
|
|
4503
4805
|
style: s.input,
|
|
4504
|
-
placeholder: "\
|
|
4806
|
+
placeholder: "\u8F93\u5165" + unlockPwdKind,
|
|
4505
4807
|
value: unlockPassword,
|
|
4506
4808
|
onChange: (e) => setUnlockPassword(e.target.value),
|
|
4507
4809
|
autoFocus: true
|