@wenbin_wb/dsh-bridge 2.2.5 → 2.2.7

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/client/client.js CHANGED
@@ -42,6 +42,7 @@ var BRIDGE_ENDPOINTS = {
42
42
  resetCloudflared: "resetCloudflared",
43
43
  saveCustomTunnelConfig: "saveCustomTunnelConfig",
44
44
  checkVersion: "checkVersion",
45
+ upgradePlugin: "upgradePlugin",
45
46
  // 平台管理器(多 IM 平台统一接口)
46
47
  listPlatforms: "listPlatforms",
47
48
  platformLogin: "platformLogin",
@@ -103,6 +104,59 @@ var s = {
103
104
  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
105
  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
106
  };
107
+ var Icons = {
108
+ wechat: (props) => React.createElement(
109
+ "svg",
110
+ { viewBox: "0 0 24 24", width: 18, height: 18, fill: "currentColor", ...props },
111
+ React.createElement("path", { d: "M8.5 2C4.36 2 1 4.91 1 8.5c0 2.01 1.05 3.81 2.69 4.97l-.69 2.06 2.45-1.22c.94.43 1.98.69 3.05.69.21 0 .42-.01.62-.03-.23-.62-.37-1.28-.37-1.97 0-3.59 3.36-6.5 7.5-6.5.21 0 .41.01.62.03C15.87 4.54 12.44 2 8.5 2zM6 6.5a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5zm5 0a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5zm7.5 3.5c-3.59 0-6.5 2.46-6.5 5.5 0 1.66.86 3.14 2.21 4.1l-.56 1.69 2.01-1c.78.36 1.64.57 2.54.57 3.59 0 6.5-2.46 6.5-5.5s-2.91-5.5-6.5-5.5zm-2 4a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z" })
112
+ ),
113
+ qq: (props) => React.createElement(
114
+ "svg",
115
+ { viewBox: "0 0 24 24", width: 18, height: 18, fill: "currentColor", ...props },
116
+ React.createElement("path", { d: "M12 2C7.58 2 4 5.37 4 9.53c0 1.95.78 3.73 2.07 5.07-.37 1.15-.99 2.19-1.8 3.08-.18.2-.04.52.23.52 2.22 0 3.99-1.07 4.9-1.86.8.25 1.66.39 2.6.39 4.42 0 8-3.37 8-7.53S16.42 2 12 2zm-3 8a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5zm6 0a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5z" })
117
+ ),
118
+ feishu: (props) => React.createElement(
119
+ "svg",
120
+ { viewBox: "0 0 24 24", width: 18, height: 18, fill: "currentColor", ...props },
121
+ React.createElement("path", { d: "M12 2.5L3.5 11.2l6.8 1.8 2.2 6.5 1.8-4.7 5.2-1.4L12 2.5zm-.8 11.1l-4.1-1.1 6.5-6.6-4.2 8.3 1.8-.6z" })
122
+ ),
123
+ telegram: (props) => React.createElement(
124
+ "svg",
125
+ { viewBox: "0 0 24 24", width: 18, height: 18, fill: "currentColor", ...props },
126
+ React.createElement("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69a.2.2 0 0 0-.05-.18c-.06-.05-.14-.03-.21-.02-.09.02-1.49.95-4.22 2.79-.4.27-.76.41-1.08.4-.36-.01-1.04-.2-1.55-.37-.63-.2-1.12-.31-1.08-.66.02-.18.27-.36.74-.55 2.92-1.27 4.86-2.11 5.83-2.51 2.78-1.16 3.35-1.36 3.73-1.36.08 0 .27.02.39.12.1.08.13.19.14.27-.01.06.01.24 0 .38z" })
127
+ ),
128
+ lan: (props) => React.createElement(
129
+ "svg",
130
+ { viewBox: "0 0 24 24", width: 16, height: 16, fill: "currentColor", ...props },
131
+ React.createElement("path", { d: "M12 3c-4.97 0-9 4.03-9 9 0 2.12.74 4.07 1.97 5.61L4.29 19.3a1 1 0 0 0 1.41 1.41l1.7-1.7C9.02 19.64 10.46 20 12 20c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 15c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z" })
132
+ ),
133
+ tunnel: (props) => React.createElement(
134
+ "svg",
135
+ { viewBox: "0 0 24 24", width: 16, height: 16, fill: "currentColor", ...props },
136
+ React.createElement("path", { d: "M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4 0-2.05 1.53-3.76 3.56-3.97l1.07-.11.5-.95C8.08 7.14 9.94 6 12 6c2.62 0 4.88 1.86 5.39 4.43l.3 1.5 1.53.11c1.56.1 2.78 1.41 2.78 2.96 0 1.65-1.35 3-3 3z" })
137
+ ),
138
+ bot: (props) => React.createElement(
139
+ "svg",
140
+ { viewBox: "0 0 24 24", width: 16, height: 16, fill: "currentColor", ...props },
141
+ React.createElement("path", { d: "M20 9V7c0-1.1-.9-2-2-2h-3c0-1.66-1.34-3-3-3S9 3.34 9 5H6c-1.1 0-2 .9-2 2v2c-1.66 0-3 1.34-3 3s1.34 3 3 3v4c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-4c1.66 0 3-1.34 3-3s-1.34-3-3-3zm-2 10H6V7h12v12zm-9-6c-.83 0-1.5-.67-1.5-1.5S8.17 10 9 10s1.5.67 1.5 1.5S9.83 13 9 13zm6 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" })
142
+ ),
143
+ github: (props) => React.createElement(
144
+ "svg",
145
+ { viewBox: "0 0 24 24", width: 13, height: 13, fill: "currentColor", ...props },
146
+ React.createElement("path", { d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.53 1.032 1.53 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" })
147
+ ),
148
+ refresh: (props) => React.createElement(
149
+ "svg",
150
+ { viewBox: "0 0 24 24", width: 12, height: 12, fill: "none", stroke: "currentColor", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", ...props },
151
+ React.createElement("path", { d: "M23 4v6h-6M1 20v-6h6" }),
152
+ React.createElement("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })
153
+ ),
154
+ check: (props) => React.createElement(
155
+ "svg",
156
+ { viewBox: "0 0 24 24", width: 12, height: 12, fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", ...props },
157
+ React.createElement("polyline", { points: "20 6 9 17 4 12" })
158
+ )
159
+ };
106
160
  function useCopy() {
107
161
  const [copied, setCopied] = React.useState(false);
108
162
  const copy = React.useCallback((text) => {
@@ -472,7 +526,15 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
472
526
  React.createElement(
473
527
  "div",
474
528
  null,
475
- React.createElement("div", { style: s.label }, platformName),
529
+ React.createElement(
530
+ "div",
531
+ { style: { ...s.label, display: "flex", alignItems: "center", gap: 7 } },
532
+ platformId === "wechat" && React.createElement(Icons.wechat, { style: { color: "#07C160", width: 20, height: 20 } }),
533
+ platformId === "qq" && React.createElement(Icons.qq, { style: { color: "#12B7F5", width: 20, height: 20 } }),
534
+ platformId === "feishu" && React.createElement(Icons.feishu, { style: { color: "#00D6B9", width: 20, height: 20 } }),
535
+ platformId === "telegram" && React.createElement(Icons.telegram, { style: { color: "#24A1DE", width: 20, height: 20 } }),
536
+ platformName
537
+ ),
476
538
  React.createElement("div", { style: { ...s.muted, marginTop: 2 } }, platformDesc)
477
539
  ),
478
540
  React.createElement(StatusTag, { status: platform?.status, running: connected })
@@ -887,7 +949,11 @@ function UpgradeCommandRow({ cmd }) {
887
949
  color: "var(--dsw-alias-label-secondary,#6b7280)",
888
950
  flex: 1,
889
951
  minWidth: 0,
890
- wordBreak: "break-all"
952
+ wordBreak: "break-all",
953
+ background: "var(--dsw-alias-bg-layer-1,#ffffff)",
954
+ padding: "4px 8px",
955
+ borderRadius: 6,
956
+ border: "1px solid var(--dsw-alias-border-l2,#e5e7eb)"
891
957
  }
892
958
  }, cmd),
893
959
  React.createElement("button", {
@@ -900,6 +966,9 @@ function UpgradeCommandRow({ cmd }) {
900
966
  function VersionBanner({ rpcCall }) {
901
967
  const [info, setInfo] = React.useState(null);
902
968
  const [loading, setLoading] = React.useState(false);
969
+ const [upgrading, setUpgrading] = React.useState(false);
970
+ const [upgradeResult, setUpgradeResult] = React.useState(null);
971
+ const [showManual, setShowManual] = React.useState(false);
903
972
  const check = React.useCallback(async () => {
904
973
  setLoading(true);
905
974
  try {
@@ -913,6 +982,27 @@ function VersionBanner({ rpcCall }) {
913
982
  check();
914
983
  }, [check]);
915
984
  const hasUpdate = info?.latest && info?.current && !info.error && semverGt(info.latest, info.current);
985
+ const isLatest = info?.latest && info?.current && !info.error && !semverGt(info.latest, info.current);
986
+ const handleUpgrade = React.useCallback(async () => {
987
+ if (!info?.latest || upgrading) return;
988
+ setUpgrading(true);
989
+ setUpgradeResult(null);
990
+ try {
991
+ const r = await rpcCall(BRIDGE_ENDPOINTS.upgradePlugin, { version: info.latest });
992
+ if (r?.ok && r.value?.ok) {
993
+ setUpgradeResult({ ok: true, message: `\u5DF2\u6210\u529F\u5347\u7EA7\u5230 v${info.latest}\uFF01\u8BF7\u91CD\u542F DSH \u670D\u52A1\u4F7F\u65B0\u7248\u672C\u751F\u6548\u3002` });
994
+ setTimeout(() => check(), 3e3);
995
+ } else {
996
+ setUpgradeResult({ ok: false, message: r?.value?.error || r?.error?.message || "\u5347\u7EA7\u5931\u8D25" });
997
+ setShowManual(true);
998
+ }
999
+ } catch (e) {
1000
+ setUpgradeResult({ ok: false, message: e.message || "\u5347\u7EA7\u8BF7\u6C42\u5931\u8D25" });
1001
+ setShowManual(true);
1002
+ } finally {
1003
+ setUpgrading(false);
1004
+ }
1005
+ }, [info?.latest, upgrading, rpcCall, check]);
916
1006
  const links = React.createElement(
917
1007
  "div",
918
1008
  { style: { display: "flex", gap: 12, alignItems: "center", flexWrap: "wrap" } },
@@ -921,95 +1011,174 @@ function VersionBanner({ rpcCall }) {
921
1011
  target: "_blank",
922
1012
  rel: "noreferrer",
923
1013
  style: s.btnLink
924
- }, "\u2B50 GitHub"),
1014
+ }, React.createElement(Icons.github), "GitHub"),
925
1015
  React.createElement("a", {
926
1016
  href: RELEASES_URL,
927
1017
  target: "_blank",
928
1018
  rel: "noreferrer",
929
1019
  style: s.btnLink
930
- }, "\u{1F4CB} \u66F4\u65B0\u65E5\u5FD7"),
1020
+ }, "\u66F4\u65B0\u65E5\u5FD7"),
931
1021
  React.createElement("a", {
932
1022
  href: ISSUES_URL,
933
1023
  target: "_blank",
934
1024
  rel: "noreferrer",
935
1025
  style: s.btnLink
936
- }, "\u{1F41B} \u53CD\u9988 Bug")
1026
+ }, "\u53CD\u9988 Issue")
937
1027
  );
938
- if (hasUpdate) {
939
- const cmds = upgradeCommands(info.latest);
940
- return React.createElement(
1028
+ return React.createElement(
1029
+ "div",
1030
+ { style: { marginBottom: 16 } },
1031
+ // 顶部状态行:版本徽标 + 刷新按钮 + 链接组
1032
+ React.createElement(
941
1033
  "div",
942
- { style: { marginBottom: 16 } },
1034
+ {
1035
+ style: {
1036
+ display: "flex",
1037
+ alignItems: "center",
1038
+ justifyContent: "space-between",
1039
+ flexWrap: "wrap",
1040
+ gap: 8
1041
+ }
1042
+ },
943
1043
  React.createElement(
944
1044
  "div",
945
- {
946
- style: {
947
- ...s.card,
948
- background: "var(--dsw-alias-state-info-bg,#eff6ff)",
949
- border: "1px solid var(--dsw-alias-state-info-border,#bfdbfe)",
950
- padding: "12px 16px",
951
- marginBottom: 8
952
- }
953
- },
1045
+ { style: { display: "flex", alignItems: "center", gap: 8 } },
1046
+ // 版本状态徽标
1047
+ React.createElement(
1048
+ "span",
1049
+ {
1050
+ style: {
1051
+ ...s.tag,
1052
+ background: hasUpdate ? "var(--dsw-alias-state-info-bg,#eff6ff)" : isLatest ? "var(--dsw-alias-state-success-bg,#ecfdf5)" : "var(--dsw-alias-bg-layer-2,#f3f4f6)",
1053
+ color: hasUpdate ? "var(--dsw-alias-state-info-primary,#2563eb)" : isLatest ? "var(--dsw-alias-state-success-primary,#059669)" : "var(--dsw-alias-label-secondary,#6b7280)",
1054
+ padding: "3px 10px",
1055
+ fontSize: 12,
1056
+ fontWeight: 500,
1057
+ display: "inline-flex",
1058
+ alignItems: "center",
1059
+ gap: 5
1060
+ }
1061
+ },
1062
+ loading ? React.createElement("span", {
1063
+ style: { display: "inline-flex", alignItems: "center" }
1064
+ }, React.createElement(Icons.refresh)) : isLatest ? React.createElement(Icons.check) : null,
1065
+ info ? `v${info.current}` : "\u7248\u672C\u68C0\u67E5\u4E2D\u2026",
1066
+ isLatest && React.createElement("span", { style: { opacity: 0.85, fontSize: 11, fontWeight: 400 } }, "\xB7 \u5DF2\u662F\u6700\u65B0"),
1067
+ hasUpdate && React.createElement("span", { style: { fontWeight: 600, fontSize: 11 } }, `\u2794 v${info.latest}`),
1068
+ info?.error && React.createElement("span", { style: { color: "var(--dsw-alias-state-warn-primary,#d97706)", fontSize: 11 } }, "(\u7F51\u7EDC\u8D85\u65F6)")
1069
+ ),
1070
+ // 刷新检查按钮
1071
+ React.createElement(
1072
+ "button",
1073
+ {
1074
+ style: {
1075
+ ...s.btnGhost,
1076
+ height: 24,
1077
+ padding: "0 8px",
1078
+ fontSize: 11,
1079
+ opacity: loading ? 0.5 : 1,
1080
+ gap: 4
1081
+ },
1082
+ onClick: check,
1083
+ disabled: loading || upgrading,
1084
+ title: "\u91CD\u65B0\u68C0\u67E5 npm \u7EBF\u4E0A\u7248\u672C"
1085
+ },
1086
+ React.createElement(Icons.refresh),
1087
+ loading ? "\u68C0\u67E5\u4E2D\u2026" : "\u68C0\u67E5\u66F4\u65B0"
1088
+ )
1089
+ ),
1090
+ links
1091
+ ),
1092
+ // 发现新版本高亮卡片(支持一键直接升级)
1093
+ hasUpdate && React.createElement(
1094
+ "div",
1095
+ {
1096
+ style: {
1097
+ ...s.card,
1098
+ background: "var(--dsw-alias-state-info-bg,#eff6ff)",
1099
+ border: "1px solid var(--dsw-alias-state-info-border,#bfdbfe)",
1100
+ padding: "14px 16px",
1101
+ marginTop: 10,
1102
+ marginBottom: 0
1103
+ }
1104
+ },
1105
+ React.createElement(
1106
+ "div",
1107
+ { style: { display: "flex", alignItems: "flex-start", gap: 12 } },
1108
+ React.createElement("span", { style: { fontSize: 22 } }, "\u{1F680}"),
954
1109
  React.createElement(
955
1110
  "div",
956
- { style: { display: "flex", alignItems: "center", gap: 12 } },
957
- React.createElement("span", { style: { fontSize: 20 } }, "\u{1F389}"),
1111
+ { style: { flex: 1, minWidth: 0 } },
958
1112
  React.createElement(
959
1113
  "div",
960
- { style: { flex: 1, minWidth: 0 } },
1114
+ { style: { display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 8, marginBottom: 8 } },
961
1115
  React.createElement("div", {
962
1116
  style: {
963
1117
  fontSize: 13,
964
1118
  fontWeight: 600,
965
- color: "var(--dsw-alias-state-info-primary,#1e40af)",
966
- marginBottom: 8
1119
+ color: "var(--dsw-alias-state-info-primary,#1e40af)"
967
1120
  }
968
1121
  }, `\u53D1\u73B0\u65B0\u7248\u672C v${info.latest}\uFF08\u5F53\u524D v${info.current}\uFF09`),
969
- // 升级命令:dsh plugin 与 npx 两种,均带复制按钮
970
1122
  React.createElement(
971
- "div",
972
- { style: { display: "flex", flexDirection: "column", gap: 6 } },
973
- cmds.map(({ id, cmd }) => React.createElement(UpgradeCommandRow, { key: id, cmd }))
1123
+ "button",
1124
+ {
1125
+ style: {
1126
+ ...s.btnPri,
1127
+ height: 28,
1128
+ fontSize: 12,
1129
+ padding: "0 14px",
1130
+ background: upgradeResult?.ok ? "var(--dsw-alias-state-success-primary,#059669)" : "var(--dsw-alias-brand-primary,#4f6ef7)",
1131
+ opacity: upgrading ? 0.6 : 1
1132
+ },
1133
+ onClick: handleUpgrade,
1134
+ disabled: upgrading || upgradeResult?.ok
1135
+ },
1136
+ upgrading ? React.createElement(
1137
+ "span",
1138
+ { style: { display: "inline-flex", alignItems: "center", gap: 6 } },
1139
+ React.createElement("span", { style: { animation: "spin 1s linear infinite", display: "inline-flex" } }, React.createElement(Icons.refresh)),
1140
+ "\u6B63\u5728\u81EA\u52A8\u5347\u7EA7\u2026"
1141
+ ) : upgradeResult?.ok ? "\u2713 \u5DF2\u5B8C\u6210\u5347\u7EA7" : `\u4E00\u952E\u5347\u7EA7\u5230 v${info.latest}`
974
1142
  )
975
1143
  ),
976
- React.createElement("button", {
1144
+ upgradeResult && React.createElement("div", {
977
1145
  style: {
978
- ...s.btnGhost,
979
- height: 30,
980
- padding: "0 12px",
1146
+ background: upgradeResult.ok ? "var(--dsw-alias-state-success-bg,#ecfdf5)" : "var(--dsw-alias-state-error-bg,#fef2f2)",
1147
+ border: `1px solid ${upgradeResult.ok ? "var(--dsw-alias-state-success-border,#a7f3d0)" : "var(--dsw-alias-state-error-border,#fecaca)"}`,
1148
+ color: upgradeResult.ok ? "var(--dsw-alias-state-success-primary,#065f46)" : "var(--dsw-alias-state-error-primary,#991b1b)",
1149
+ padding: "8px 12px",
1150
+ borderRadius: 6,
981
1151
  fontSize: 12,
982
- opacity: loading ? 0.5 : 1,
983
- flexShrink: 0
1152
+ marginBottom: 8,
1153
+ lineHeight: 1.5
1154
+ }
1155
+ }, upgradeResult.message),
1156
+ React.createElement(
1157
+ "div",
1158
+ { style: { marginTop: 4 } },
1159
+ React.createElement("button", {
1160
+ style: { ...s.btnLink, fontSize: 11, color: "var(--dsw-alias-label-secondary,#6b7280)" },
1161
+ onClick: () => setShowManual((v) => !v)
1162
+ }, showManual ? "\u25B4 \u6298\u53E0\u624B\u52A8\u547D\u4EE4\u884C" : "\u25BE \u67E5\u770B\u624B\u52A8\u5347\u7EA7\u547D\u4EE4 (\u5982\u9700)")
1163
+ ),
1164
+ showManual && React.createElement(
1165
+ "div",
1166
+ {
1167
+ style: { display: "flex", flexDirection: "column", gap: 6, marginTop: 8 }
984
1168
  },
985
- onClick: check,
986
- disabled: loading
987
- }, loading ? "\u2026" : "\u5237\u65B0")
1169
+ upgradeCommands(info.latest).map(
1170
+ ({ id, cmd }) => React.createElement(UpgradeCommandRow, { key: id, cmd })
1171
+ )
1172
+ )
988
1173
  )
989
- ),
990
- links
991
- );
992
- }
993
- return React.createElement(
994
- "div",
995
- { style: { marginBottom: 14, display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 8 } },
996
- React.createElement(
997
- "div",
998
- { style: { ...s.muted, display: "flex", alignItems: "center", gap: 8 } },
999
- loading && !info ? React.createElement("span", null, "\u68C0\u67E5\u66F4\u65B0\u4E2D\u2026") : info ? React.createElement("span", null, `v${info.current}${info.latest && !info.error ? " \xB7 \u5DF2\u662F\u6700\u65B0" : info.error ? " \xB7 \u68C0\u67E5\u5931\u8D25" : ""}`) : null,
1000
- info && React.createElement("button", {
1001
- style: { ...s.btnGhost, height: 22, padding: "0 8px", fontSize: 11, opacity: loading ? 0.5 : 1 },
1002
- onClick: check,
1003
- disabled: loading
1004
- }, loading ? "\u2026" : "\u91CD\u65B0\u68C0\u67E5")
1005
- ),
1006
- links
1174
+ )
1175
+ )
1007
1176
  );
1008
1177
  }
1009
1178
  var TABS = [
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}" }
1179
+ { id: "lan", label: "\u5C40\u57DF\u7F51", icon: Icons.lan },
1180
+ { id: "tunnel", label: "\u516C\u7F51\u96A7\u9053", icon: Icons.tunnel },
1181
+ { id: "im", label: "IM \u673A\u5668\u4EBA", icon: Icons.bot }
1013
1182
  ];
1014
1183
  function TabBar({ active, onChange, dots }) {
1015
1184
  return React.createElement(
@@ -1022,7 +1191,7 @@ function TabBar({ active, onChange, dots }) {
1022
1191
  borderBottom: "1px solid var(--dsw-alias-border-l2,#e5e7eb)"
1023
1192
  }
1024
1193
  },
1025
- TABS.map(({ id, label, icon }) => {
1194
+ TABS.map(({ id, label, icon: TabIcon }) => {
1026
1195
  const isActive = active === id;
1027
1196
  const hasDot = dots?.[id];
1028
1197
  return React.createElement(
@@ -1043,12 +1212,19 @@ function TabBar({ active, onChange, dots }) {
1043
1212
  marginBottom: -1,
1044
1213
  display: "inline-flex",
1045
1214
  alignItems: "center",
1046
- gap: 6,
1215
+ gap: 7,
1047
1216
  transition: "color .15s, border-color .15s",
1048
1217
  whiteSpace: "nowrap"
1049
1218
  }
1050
1219
  },
1051
- React.createElement("span", { style: { fontSize: 14 } }, icon),
1220
+ TabIcon && React.createElement(TabIcon, {
1221
+ style: {
1222
+ color: isActive ? "var(--dsw-alias-brand-primary,#4f6ef7)" : "var(--dsw-alias-label-tertiary,#9ca3af)",
1223
+ width: 16,
1224
+ height: 16,
1225
+ flexShrink: 0
1226
+ }
1227
+ }),
1052
1228
  label,
1053
1229
  hasDot && React.createElement("span", {
1054
1230
  style: {
@@ -1187,9 +1363,10 @@ function BridgePanel({ rpcCall }) {
1187
1363
  );
1188
1364
  } else if (activeTab === "im") {
1189
1365
  const IM_PLATFORMS = [
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" }
1366
+ { id: "wechat", label: "\u5FAE\u4FE1", icon: Icons.wechat, brandColor: "#07C160", desc: "ClawBot \u626B\u7801\u76F4\u8FDE \xB7 \u65E0\u9700\u516C\u7F51" },
1367
+ { id: "qq", label: "QQ", icon: Icons.qq, brandColor: "#12B7F5", desc: "\u5B98\u65B9\u673A\u5668\u4EBA \xB7 \u79C1\u804A/\u7FA4\u804A/\u6309\u94AE" },
1368
+ { id: "feishu", label: "\u98DE\u4E66", icon: Icons.feishu, brandColor: "#00D6B9", desc: "\u5B98\u65B9\u4E8B\u4EF6\u56DE\u8C03 API" },
1369
+ { id: "telegram", label: "Telegram", icon: Icons.telegram, brandColor: "#24A1DE", desc: "\u5B98\u65B9 Bot API" }
1193
1370
  ];
1194
1371
  tabContent = React.createElement(
1195
1372
  "div",
@@ -1200,7 +1377,7 @@ function BridgePanel({ rpcCall }) {
1200
1377
  {
1201
1378
  style: { display: "flex", gap: 10, marginBottom: 16, flexWrap: "wrap" }
1202
1379
  },
1203
- IM_PLATFORMS.map(({ id, label, icon, desc }) => {
1380
+ IM_PLATFORMS.map(({ id, label, icon: IconComponent, brandColor, desc }) => {
1204
1381
  const platformData = platforms?.[id];
1205
1382
  const available = !!platformData;
1206
1383
  const active = platformData?.status === "connected" || platformData?.status === "starting" || platformData?.status === "reconnecting";
@@ -1209,7 +1386,7 @@ function BridgePanel({ rpcCall }) {
1209
1386
  {
1210
1387
  key: id,
1211
1388
  style: {
1212
- flex: "1 1 150px",
1389
+ flex: "1 1 135px",
1213
1390
  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)"}`,
1214
1391
  borderRadius: 10,
1215
1392
  padding: "12px 14px",
@@ -1226,8 +1403,8 @@ function BridgePanel({ rpcCall }) {
1226
1403
  { style: { ...s.label, fontSize: 13, display: "flex", alignItems: "center", justifyContent: "space-between" } },
1227
1404
  React.createElement(
1228
1405
  "span",
1229
- { style: { display: "flex", alignItems: "center", gap: 6 } },
1230
- React.createElement("span", { style: { fontSize: 14 } }, icon),
1406
+ { style: { display: "flex", alignItems: "center", gap: 7 } },
1407
+ IconComponent && React.createElement(IconComponent, { style: { color: brandColor, width: 18, height: 18, flexShrink: 0 } }),
1231
1408
  label
1232
1409
  ),
1233
1410
  active && React.createElement("span", {