@wenbin_wb/dsh-bridge 2.8.7 → 2.9.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/CHANGELOG.md +295 -250
- package/README.en.md +408 -572
- package/README.md +430 -570
- package/client/client.js +3844 -3764
- package/client/index.js +140 -876
- package/client/mobile-styles.js +802 -0
- package/docs/fix-plan-202608.md +108 -0
- package/lib/auth/login-template.js +381 -381
- package/lib/auth/manager.js +531 -469
- package/lib/bridge-rpc.js +436 -511
- package/lib/cloudflared-manager.mjs +361 -345
- package/lib/compat.js +129 -0
- package/lib/feishu/index.js +225 -222
- package/lib/feishu/node.js +433 -409
- package/lib/index.js +1765 -1804
- package/lib/platform/base.js +147 -156
- package/lib/platform/commands.js +221 -0
- package/lib/platform/conversation-bridge.js +816 -1570
- package/lib/platform/dsh-storage.js +117 -0
- package/lib/platform/index.js +10 -10
- package/lib/platform/message-split.js +191 -0
- package/lib/platform/session-catalog.js +372 -0
- package/lib/platform/stream-slices.js +21 -0
- package/lib/qq/index.js +312 -309
- package/lib/qq/node.js +532 -533
- package/lib/telegram/index.js +215 -212
- package/lib/telegram/node.js +348 -350
- package/lib/tunnel-client.mjs +39 -15
- package/lib/wechat/gateway.js +973 -960
- package/lib/wechat/index.js +244 -241
- package/lib/wechat/media.js +285 -281
- package/lib/wechat/node.js +352 -350
- package/package.json +106 -102
package/client/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MOBILE_STYLES_CSS } from './mobile-styles.js'
|
|
1
2
|
// dsh-bridge 客户端插件:设置页「远程访问」面板
|
|
2
3
|
|
|
3
4
|
// 兼容非 HTTPS 环境(如手机局域网 HTTP 访问):为非安全上下文补齐 crypto.randomUUID
|
|
@@ -111,6 +112,7 @@ const s = {
|
|
|
111
112
|
tag: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: '3px 10px', borderRadius: 999, fontSize: 12, fontWeight: 500, whiteSpace: 'nowrap', flexShrink: 0, minWidth: 'max-content', lineHeight: 1.4 },
|
|
112
113
|
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' },
|
|
113
114
|
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 },
|
|
115
|
+
err: { background: 'var(--dsw-alias-state-error-bg,#fef2f2)', border: '1px solid var(--dsw-alias-state-error-border,#fecaca)', borderRadius: 8, padding: '10px 14px', fontSize: 12, color: 'var(--dsw-alias-state-error-primary,#991b1b)', lineHeight: 1.6 },
|
|
114
116
|
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 },
|
|
115
117
|
};
|
|
116
118
|
|
|
@@ -557,7 +559,11 @@ const CloudflareConfigForm = React.memo(function CloudflareConfigForm({ token, h
|
|
|
557
559
|
setSaving(true);
|
|
558
560
|
setMsg(null);
|
|
559
561
|
try {
|
|
560
|
-
|
|
562
|
+
// 只回传被修改的字段:掩码 '******' 与未变更的 token 都不上传,服务端保留现值
|
|
563
|
+
const patch = {};
|
|
564
|
+
if (hostnameVal !== (hostname || '')) patch.hostname = hostnameVal;
|
|
565
|
+
if (tokenVal !== (token || '')) patch.token = tokenVal;
|
|
566
|
+
if (Object.keys(patch).length > 0) await onSave(patch);
|
|
561
567
|
setMsg({ ok: true, text: '✓ 固定域名配置已保存' });
|
|
562
568
|
} catch (err) {
|
|
563
569
|
setMsg({ ok: false, text: err.message || '保存失败' });
|
|
@@ -1059,7 +1065,7 @@ const AccessAuthCard = React.memo(function AccessAuthCard({ auth, rpcCall, onUpd
|
|
|
1059
1065
|
|
|
1060
1066
|
// ---- 通用 IM 平台卡片 ----
|
|
1061
1067
|
|
|
1062
|
-
function PlatformCard({ platformId, platformName, platformDesc, rpcCall
|
|
1068
|
+
function PlatformCard({ platformId, platformName, platformDesc, rpcCall }) {
|
|
1063
1069
|
const [platform, setPlatform] = React.useState(null);
|
|
1064
1070
|
const [err, setErr] = React.useState(null);
|
|
1065
1071
|
const [busy, setBusy] = React.useState(false);
|
|
@@ -1075,6 +1081,7 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
1075
1081
|
approvalTimeoutSec: String(platform.config.approvalTimeoutSec ?? 600),
|
|
1076
1082
|
maxMessageChars: String((platform.config.maxMessageChars >= 500 ? platform.config.maxMessageChars : null) ?? (platformId === 'telegram' ? 4096 : 2000)),
|
|
1077
1083
|
sendChunkDelayMs: String(platform.config.sendChunkDelayMs ?? 1500),
|
|
1084
|
+
groupAutoApprove: Boolean(platform.config.groupAutoApprove),
|
|
1078
1085
|
appId: platform.config.appId ?? '',
|
|
1079
1086
|
// Secret 不由后端回传;空值表示沿用已保存密钥
|
|
1080
1087
|
clientSecret: '',
|
|
@@ -1086,12 +1093,6 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
1086
1093
|
}
|
|
1087
1094
|
}, [platform?.config, platformId]);
|
|
1088
1095
|
|
|
1089
|
-
// 向上传递连接状态(供平台列表卡片绿点使用)
|
|
1090
|
-
React.useEffect(() => {
|
|
1091
|
-
const connected = platform?.status === 'connected' || platform?.status === 'starting' || platform?.status === 'reconnecting';
|
|
1092
|
-
onStatusChange?.(connected);
|
|
1093
|
-
}, [platform?.status, onStatusChange]);
|
|
1094
|
-
|
|
1095
1096
|
const loadInFlightRef = React.useRef(false);
|
|
1096
1097
|
const seqRef = React.useRef(0);
|
|
1097
1098
|
const load = React.useCallback(async (quiet = false) => {
|
|
@@ -1139,6 +1140,12 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
1139
1140
|
|
|
1140
1141
|
const onLogin = React.useCallback(() => act(BRIDGE_ENDPOINTS.platformLogin, {}), [act]);
|
|
1141
1142
|
const onStop = React.useCallback(() => act(BRIDGE_ENDPOINTS.platformStop, {}), [act]);
|
|
1143
|
+
// 断开后重连:凭证仍在(configured)时直接用已存凭证重启网关,无需重新扫码;
|
|
1144
|
+
// 只有解绑后(无凭证)才走扫码/绑定流程
|
|
1145
|
+
const onReconnect = React.useCallback(() => {
|
|
1146
|
+
if (platform?.configured) return act(BRIDGE_ENDPOINTS.platformStart, {});
|
|
1147
|
+
return act(BRIDGE_ENDPOINTS.platformLogin, {});
|
|
1148
|
+
}, [act, platform?.configured]);
|
|
1142
1149
|
|
|
1143
1150
|
// 白名单管理
|
|
1144
1151
|
const [newId, setNewId] = React.useState('');
|
|
@@ -1183,11 +1190,16 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
1183
1190
|
// 高级设置保存
|
|
1184
1191
|
const saveConfig = React.useCallback(async () => {
|
|
1185
1192
|
if (!cfgDraft) return;
|
|
1193
|
+
// 非法数字输入回落到当前配置值/默认值,避免 NaN 发到服务端且使 cfgDirty 永真
|
|
1194
|
+
const num = (v, fallback) => {
|
|
1195
|
+
const n = Number(v);
|
|
1196
|
+
return Number.isFinite(n) ? n : fallback;
|
|
1197
|
+
};
|
|
1186
1198
|
const payload = {
|
|
1187
|
-
digestIntervalSec:
|
|
1188
|
-
approvalTimeoutSec:
|
|
1189
|
-
maxMessageChars:
|
|
1190
|
-
sendChunkDelayMs:
|
|
1199
|
+
digestIntervalSec: num(cfgDraft.digestIntervalSec, platform?.config?.digestIntervalSec ?? 300),
|
|
1200
|
+
approvalTimeoutSec: num(cfgDraft.approvalTimeoutSec, platform?.config?.approvalTimeoutSec ?? 600),
|
|
1201
|
+
maxMessageChars: num(cfgDraft.maxMessageChars, platform?.config?.maxMessageChars ?? 2000),
|
|
1202
|
+
sendChunkDelayMs: num(cfgDraft.sendChunkDelayMs, platform?.config?.sendChunkDelayMs ?? 1500),
|
|
1191
1203
|
};
|
|
1192
1204
|
// QQ / 飞书 / Telegram 平台额外携带凭证
|
|
1193
1205
|
if (platformId === 'qq') {
|
|
@@ -1401,9 +1413,9 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
1401
1413
|
),
|
|
1402
1414
|
React.createElement('div', { style: { display: 'flex', gap: 8, marginTop: 10, flexWrap: 'wrap', alignItems: 'center' } },
|
|
1403
1415
|
platform.status !== 'connected' && platform.status !== 'starting' &&
|
|
1404
|
-
React.createElement('button', { style: s.btnPri, onClick:
|
|
1416
|
+
React.createElement('button', { style: s.btnPri, onClick: onReconnect, disabled: busy, title: platform?.configured ? '使用已保存的凭证直接恢复连接,无需重新扫码' : '首次使用需扫码绑定' }, platform?.configured ? '重新连接' : '连接'),
|
|
1405
1417
|
(platform.status === 'connected' || platform.status === 'starting') &&
|
|
1406
|
-
React.createElement('button', { style: s.btnGhost, onClick: onStop, disabled: busy }, '断开'),
|
|
1418
|
+
React.createElement('button', { style: s.btnGhost, onClick: onStop, disabled: busy, title: '停止接收消息;凭证保留,可随时"重新连接"恢复' }, '断开'),
|
|
1407
1419
|
React.createElement('button', {
|
|
1408
1420
|
style: { ...s.btnGhost, color: 'var(--dsw-alias-state-error-primary,#dc2626)', borderColor: 'var(--dsw-alias-state-error-primary,#dc2626)', opacity: busy ? 0.5 : 1 },
|
|
1409
1421
|
disabled: busy,
|
|
@@ -1411,6 +1423,23 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
|
|
|
1411
1423
|
title: '清除登录凭证,下次需重新配置',
|
|
1412
1424
|
}, '解绑账号'),
|
|
1413
1425
|
),
|
|
1426
|
+
// 群聊自动授权开关(仅支持群聊的平台):关闭时新群首次 @机器人 不会自动加白
|
|
1427
|
+
platformId !== 'wechat' && React.createElement('label', {
|
|
1428
|
+
style: { display: 'flex', alignItems: 'center', gap: 6, marginTop: 10, fontSize: 12, cursor: 'pointer', width: 'fit-content', color: 'var(--dsw-alias-label-secondary,#6b7280)' },
|
|
1429
|
+
title: '开启后,白名单之外的新群首次 @机器人 即自动授权入白名单;关闭(默认)时新群必须先在此手动添加',
|
|
1430
|
+
},
|
|
1431
|
+
React.createElement('input', {
|
|
1432
|
+
type: 'checkbox',
|
|
1433
|
+
checked: Boolean(cfgDraft?.groupAutoApprove),
|
|
1434
|
+
disabled: busy,
|
|
1435
|
+
onChange: (e) => {
|
|
1436
|
+
const checked = e.target.checked;
|
|
1437
|
+
setCfgDraft(d => ({ ...(d ?? {}), groupAutoApprove: checked }));
|
|
1438
|
+
act(BRIDGE_ENDPOINTS.platformSetConfig, { groupAutoApprove: checked });
|
|
1439
|
+
},
|
|
1440
|
+
}),
|
|
1441
|
+
React.createElement('span', null, '群聊自动授权(新群首次 @机器人 自动加入白名单,默认关闭)'),
|
|
1442
|
+
),
|
|
1414
1443
|
// 飞书 / Telegram 扫码直达对话引导卡片
|
|
1415
1444
|
(platformId === 'feishu' || platformId === 'telegram') && platform.botQr && React.createElement('div', {
|
|
1416
1445
|
style: {
|
|
@@ -1846,41 +1875,71 @@ function BackupRestoreWidget({ rpcCall, onUpdate }) {
|
|
|
1846
1875
|
}
|
|
1847
1876
|
|
|
1848
1877
|
// 运维 Tab 内的手动重启 DSH 服务小卡片
|
|
1849
|
-
|
|
1878
|
+
// 重启 + 健康轮询公共逻辑:定时器保存在 ref 中,组件卸载即清理。
|
|
1879
|
+
// 修复点:原先两处复制粘贴的 setInterval 不随组件卸载清理,用户切走 Tab 后
|
|
1880
|
+
// 轮询仍会继续运行,并在服务恢复时无条件执行 window.location.reload()。
|
|
1881
|
+
function useDshRestart({ rpcCall, maxAttempts = 30, texts = {} } = {}) {
|
|
1882
|
+
const T = {
|
|
1883
|
+
restarting: '正在向 DSH 服务发送重启指令…',
|
|
1884
|
+
reconnecting: 'DSH 服务正在重启中,正在自动重新连接…',
|
|
1885
|
+
success: '🎉 重启成功!已重新建立连接,正在刷新页面…',
|
|
1886
|
+
timeout: '重连等待超时,请手动刷新页面。',
|
|
1887
|
+
...texts,
|
|
1888
|
+
};
|
|
1850
1889
|
const [restarting, setRestarting] = React.useState(false);
|
|
1851
1890
|
const [status, setStatus] = React.useState(null);
|
|
1891
|
+
const pollRef = React.useRef(null);
|
|
1892
|
+
const reloadRef = React.useRef(null);
|
|
1852
1893
|
|
|
1853
|
-
|
|
1894
|
+
React.useEffect(() => () => {
|
|
1895
|
+
if (pollRef.current) clearInterval(pollRef.current);
|
|
1896
|
+
if (reloadRef.current) clearTimeout(reloadRef.current);
|
|
1897
|
+
}, []);
|
|
1898
|
+
|
|
1899
|
+
const startRestart = React.useCallback(async () => {
|
|
1854
1900
|
setRestarting(true);
|
|
1855
|
-
setStatus({ phase: 'restarting', text:
|
|
1901
|
+
setStatus({ phase: 'restarting', text: T.restarting });
|
|
1856
1902
|
try {
|
|
1857
1903
|
await rpcCall(BRIDGE_ENDPOINTS.restartDsh, {});
|
|
1858
|
-
} catch {
|
|
1904
|
+
} catch {
|
|
1905
|
+
// 服务可能瞬间关闭导致连接断开,忽略
|
|
1906
|
+
}
|
|
1859
1907
|
|
|
1860
|
-
setStatus({ phase: 'reconnecting', text:
|
|
1908
|
+
setStatus({ phase: 'reconnecting', text: T.reconnecting });
|
|
1861
1909
|
await new Promise(r => setTimeout(r, 2000));
|
|
1862
1910
|
|
|
1863
1911
|
let attempts = 0;
|
|
1864
|
-
|
|
1865
|
-
const pollHealth = setInterval(async () => {
|
|
1912
|
+
pollRef.current = setInterval(async () => {
|
|
1866
1913
|
attempts++;
|
|
1867
1914
|
try {
|
|
1868
1915
|
const r = await rpcCall(BRIDGE_ENDPOINTS.checkVersion, {});
|
|
1869
1916
|
if (r?.ok) {
|
|
1870
|
-
clearInterval(
|
|
1871
|
-
|
|
1872
|
-
|
|
1917
|
+
clearInterval(pollRef.current);
|
|
1918
|
+
pollRef.current = null;
|
|
1919
|
+
setStatus({ phase: 'success', text: T.success });
|
|
1920
|
+
reloadRef.current = setTimeout(() => { window.location.reload(); }, 1000);
|
|
1873
1921
|
return;
|
|
1874
1922
|
}
|
|
1875
|
-
} catch {
|
|
1923
|
+
} catch {
|
|
1924
|
+
// 仍在启动中,继续等待
|
|
1925
|
+
}
|
|
1876
1926
|
|
|
1877
1927
|
if (attempts >= maxAttempts) {
|
|
1878
|
-
clearInterval(
|
|
1879
|
-
|
|
1928
|
+
clearInterval(pollRef.current);
|
|
1929
|
+
pollRef.current = null;
|
|
1930
|
+
setStatus({ phase: 'timeout', text: T.timeout });
|
|
1880
1931
|
setRestarting(false);
|
|
1881
1932
|
}
|
|
1882
1933
|
}, 1000);
|
|
1883
|
-
};
|
|
1934
|
+
}, [rpcCall, maxAttempts]);
|
|
1935
|
+
|
|
1936
|
+
const resetStatus = React.useCallback(() => setStatus(null), []);
|
|
1937
|
+
|
|
1938
|
+
return { restarting, status, startRestart, resetStatus };
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
function RestartDshCard({ rpcCall }) {
|
|
1942
|
+
const { restarting, status, startRestart: handleRestart } = useDshRestart({ rpcCall });
|
|
1884
1943
|
|
|
1885
1944
|
return React.createElement('div', { style: { ...s.card, marginBottom: 16 } },
|
|
1886
1945
|
React.createElement('div', { style: { marginBottom: 10 } },
|
|
@@ -1954,8 +2013,6 @@ function RemoteWorkspaceCard({ rpcCall }) {
|
|
|
1954
2013
|
onClick: () => {
|
|
1955
2014
|
if (typeof window.__dshOpenRemoteWorkspaceModal === 'function') {
|
|
1956
2015
|
window.__dshOpenRemoteWorkspaceModal();
|
|
1957
|
-
} else if (typeof showRemoteWorkspaceDialog === 'function') {
|
|
1958
|
-
showRemoteWorkspaceDialog(rpcCall, () => load());
|
|
1959
2016
|
}
|
|
1960
2017
|
},
|
|
1961
2018
|
}, '+ 远程添加工作区'),
|
|
@@ -1987,6 +2044,20 @@ function RemoteWorkspaceCard({ rpcCall }) {
|
|
|
1987
2044
|
);
|
|
1988
2045
|
}
|
|
1989
2046
|
|
|
2047
|
+
// 手动升级命令行:展示命令 + 一键复制
|
|
2048
|
+
function UpgradeCommandRow({ cmd }) {
|
|
2049
|
+
const [copied, copy] = useCopy();
|
|
2050
|
+
return React.createElement('div', { style: { display: 'flex', gap: 6, alignItems: 'center' } },
|
|
2051
|
+
React.createElement('code', {
|
|
2052
|
+
style: { ...s.code, flex: '1 1 auto', fontSize: 12, lineHeight: 1.5, wordBreak: 'break-all' },
|
|
2053
|
+
}, cmd),
|
|
2054
|
+
React.createElement('button', {
|
|
2055
|
+
style: { ...s.btnGhost, height: 26, padding: '0 10px', fontSize: 11, flex: '0 0 auto' },
|
|
2056
|
+
onClick: () => copy(cmd),
|
|
2057
|
+
}, copied ? '✓ 已复制' : '复制'),
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
|
|
1990
2061
|
// 版本检查 + 一键升级 + GitHub/反馈入口
|
|
1991
2062
|
function VersionBanner({ rpcCall }) {
|
|
1992
2063
|
const [info, setInfo] = React.useState(null);
|
|
@@ -1994,15 +2065,22 @@ function VersionBanner({ rpcCall }) {
|
|
|
1994
2065
|
const [upgrading, setUpgrading] = React.useState(false);
|
|
1995
2066
|
const [upgradeResult, setUpgradeResult] = React.useState(null);
|
|
1996
2067
|
const [showManual, setShowManual] = React.useState(false);
|
|
1997
|
-
const [restarting, setRestarting] = React.useState(false);
|
|
1998
|
-
const [restartStatus, setRestartStatus] = React.useState(null);
|
|
1999
2068
|
const [dismissRestart, setDismissRestart] = React.useState(false);
|
|
2069
|
+
const { restarting, status: restartStatus, startRestart: handleRestart, resetStatus: resetRestartStatus } = useDshRestart({
|
|
2070
|
+
rpcCall,
|
|
2071
|
+
texts: {
|
|
2072
|
+
restarting: '正在调度 DSH 服务重启…',
|
|
2073
|
+
success: '🎉 重启成功!已自动加载最新版本。正在刷新页面…',
|
|
2074
|
+
},
|
|
2075
|
+
});
|
|
2000
2076
|
|
|
2001
2077
|
const check = React.useCallback(async () => {
|
|
2002
2078
|
setLoading(true);
|
|
2003
2079
|
try {
|
|
2004
2080
|
const r = await rpcCall(BRIDGE_ENDPOINTS.checkVersion, {});
|
|
2005
2081
|
if (r?.ok) setInfo(r.value);
|
|
2082
|
+
} catch {
|
|
2083
|
+
// 版本检查失败:保留现有 info,不打断面板
|
|
2006
2084
|
} finally {
|
|
2007
2085
|
setLoading(false);
|
|
2008
2086
|
}
|
|
@@ -2018,7 +2096,7 @@ function VersionBanner({ rpcCall }) {
|
|
|
2018
2096
|
setUpgrading(true);
|
|
2019
2097
|
setUpgradeResult(null);
|
|
2020
2098
|
setDismissRestart(false);
|
|
2021
|
-
|
|
2099
|
+
resetRestartStatus();
|
|
2022
2100
|
try {
|
|
2023
2101
|
const r = await rpcCall(BRIDGE_ENDPOINTS.upgradePlugin, { version: info.latest });
|
|
2024
2102
|
if (r?.ok && r.value?.ok) {
|
|
@@ -2035,46 +2113,6 @@ function VersionBanner({ rpcCall }) {
|
|
|
2035
2113
|
}
|
|
2036
2114
|
}, [info?.latest, upgrading, rpcCall]);
|
|
2037
2115
|
|
|
2038
|
-
const handleRestart = React.useCallback(async () => {
|
|
2039
|
-
setRestarting(true);
|
|
2040
|
-
setRestartStatus({ phase: 'restarting', text: '正在调度 DSH 服务重启…' });
|
|
2041
|
-
try {
|
|
2042
|
-
await rpcCall(BRIDGE_ENDPOINTS.restartDsh, {});
|
|
2043
|
-
} catch {
|
|
2044
|
-
// 忽略 RPC 错误(因为服务可能瞬间关闭导致网络连接断开)
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
setRestartStatus({ phase: 'reconnecting', text: 'DSH 服务正在重启中,正在自动重新连接…' });
|
|
2048
|
-
|
|
2049
|
-
// 等待 2 秒后开始健康检查轮询
|
|
2050
|
-
await new Promise(r => setTimeout(r, 2000));
|
|
2051
|
-
|
|
2052
|
-
let attempts = 0;
|
|
2053
|
-
const maxAttempts = 30; // 最多探测 30 次(约 30 秒)
|
|
2054
|
-
const pollHealth = setInterval(async () => {
|
|
2055
|
-
attempts++;
|
|
2056
|
-
try {
|
|
2057
|
-
const r = await rpcCall(BRIDGE_ENDPOINTS.checkVersion, {});
|
|
2058
|
-
if (r?.ok) {
|
|
2059
|
-
clearInterval(pollHealth);
|
|
2060
|
-
setRestartStatus({ phase: 'success', text: '🎉 重启成功!已自动加载最新版本。正在刷新页面…' });
|
|
2061
|
-
setTimeout(() => {
|
|
2062
|
-
window.location.reload();
|
|
2063
|
-
}, 1000);
|
|
2064
|
-
return;
|
|
2065
|
-
}
|
|
2066
|
-
} catch {
|
|
2067
|
-
// 仍在启动中,继续等待
|
|
2068
|
-
}
|
|
2069
|
-
|
|
2070
|
-
if (attempts >= maxAttempts) {
|
|
2071
|
-
clearInterval(pollHealth);
|
|
2072
|
-
setRestartStatus({ phase: 'timeout', text: '重连等待超时,请手动刷新页面。' });
|
|
2073
|
-
setRestarting(false);
|
|
2074
|
-
}
|
|
2075
|
-
}, 1000);
|
|
2076
|
-
}, [rpcCall]);
|
|
2077
|
-
|
|
2078
2116
|
const links = React.createElement('div', { style: { display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' } },
|
|
2079
2117
|
React.createElement('a', {
|
|
2080
2118
|
href: GITHUB_URL, target: '_blank', rel: 'noreferrer', style: s.btnLink,
|
|
@@ -2408,7 +2446,6 @@ function BridgePanel({ rpcCall }) {
|
|
|
2408
2446
|
// 本机物理访问自动静默获取 adminToken,免输密码直通管理(支持 3080 原生端口与 3082 代理端口)
|
|
2409
2447
|
const fetchLoopbackToken = React.useCallback(async () => {
|
|
2410
2448
|
if (!isLocalhost) return null;
|
|
2411
|
-
const currentPort = typeof window !== 'undefined' ? (window.location.port || (window.location.protocol === 'https:' ? '443' : '80')) : '3082';
|
|
2412
2449
|
const proxyPort = status?.proxy?.port || 3082;
|
|
2413
2450
|
const candidateUrls = [
|
|
2414
2451
|
'/__dsh_bridge__/loopback-token',
|
|
@@ -2441,6 +2478,9 @@ function BridgePanel({ rpcCall }) {
|
|
|
2441
2478
|
}
|
|
2442
2479
|
}, [isLocalhost, adminUnlocked, fetchLoopbackToken]);
|
|
2443
2480
|
|
|
2481
|
+
// 被管理员鉴权拦截的操作在此暂存:解锁成功后自动续办,用户无需再点一次
|
|
2482
|
+
const pendingRetryRef = React.useRef(null);
|
|
2483
|
+
|
|
2444
2484
|
const authRpcCall = React.useCallback(async (endpoint, payload = {}, signal) => {
|
|
2445
2485
|
let token = adminToken || getGlobalAdminToken();
|
|
2446
2486
|
if (isLocalhost && !token) {
|
|
@@ -2455,6 +2495,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
2455
2495
|
if (res?.ok === false) {
|
|
2456
2496
|
const msg = res?.error?.message || '';
|
|
2457
2497
|
if (msg.includes('管理员权限') || msg.includes('管理密码解锁')) {
|
|
2498
|
+
pendingRetryRef.current = { endpoint, payload: enriched };
|
|
2458
2499
|
setUnlockErr(msg);
|
|
2459
2500
|
setShowUnlockModal(true);
|
|
2460
2501
|
}
|
|
@@ -2546,6 +2587,28 @@ function BridgePanel({ rpcCall }) {
|
|
|
2546
2587
|
return () => clearInterval(t);
|
|
2547
2588
|
}, [load]);
|
|
2548
2589
|
|
|
2590
|
+
// 解锁成功后自动续办被拦截的操作:用户不再需要重新点击一次
|
|
2591
|
+
React.useEffect(() => {
|
|
2592
|
+
if (!adminUnlocked) return;
|
|
2593
|
+
const pending = pendingRetryRef.current;
|
|
2594
|
+
if (!pending) return;
|
|
2595
|
+
pendingRetryRef.current = null;
|
|
2596
|
+
const token = adminToken || getGlobalAdminToken();
|
|
2597
|
+
(async () => {
|
|
2598
|
+
try {
|
|
2599
|
+
const r = await rpcCall(pending.endpoint, { ...pending.payload, adminToken: token });
|
|
2600
|
+
if (r?.ok) {
|
|
2601
|
+
if (r.value) setStatus(r.value);
|
|
2602
|
+
setErr(null);
|
|
2603
|
+
} else {
|
|
2604
|
+
setErr(r?.error?.message || '刚才的操作重试失败,请手动重试');
|
|
2605
|
+
}
|
|
2606
|
+
} catch (e) {
|
|
2607
|
+
setErr(e.message || '刚才的操作重试失败,请手动重试');
|
|
2608
|
+
}
|
|
2609
|
+
})();
|
|
2610
|
+
}, [adminUnlocked, adminToken, rpcCall]);
|
|
2611
|
+
|
|
2549
2612
|
const act = React.useCallback(async (endpoint, payload) => {
|
|
2550
2613
|
try {
|
|
2551
2614
|
const r = await authRpcCall(endpoint, payload ?? {});
|
|
@@ -2745,7 +2808,6 @@ function BridgePanel({ rpcCall }) {
|
|
|
2745
2808
|
platformName: IM_PLATFORMS.find(p => p.id === selectedPlatform)?.label ?? selectedPlatform,
|
|
2746
2809
|
platformDesc: IM_PLATFORMS.find(p => p.id === selectedPlatform)?.desc ?? '',
|
|
2747
2810
|
rpcCall: authRpcCall,
|
|
2748
|
-
onStatusChange: () => {}, // 状态变化已由 listPlatforms 轮询处理,不需要回调
|
|
2749
2811
|
}),
|
|
2750
2812
|
);
|
|
2751
2813
|
}
|
|
@@ -2782,7 +2844,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
2782
2844
|
},
|
|
2783
2845
|
React.createElement('div', { style: { fontWeight: 600, color: 'var(--dsw-alias-label-primary,currentColor)', marginBottom: 4 } }, '🛟 救急解除锁定指引:'),
|
|
2784
2846
|
React.createElement('div', null, '1. ', React.createElement('strong', null, '电脑本机直连修改'), ':直接在运行本程序的电脑本机打开本控制台(127.0.0.1 享有物理免锁特权),可随时修改策略或清除密码。'),
|
|
2785
|
-
React.createElement('div', { style: { marginTop: 4 } }, '2. ', React.createElement('strong', null, '
|
|
2847
|
+
React.createElement('div', { style: { marginTop: 4 } }, '2. ', React.createElement('strong', null, '服务器 / 无头环境'), ':救急重置步骤参见 GitHub README 的「三重容灾保命体系」章节。'),
|
|
2786
2848
|
),
|
|
2787
2849
|
)
|
|
2788
2850
|
) : (
|
|
@@ -2833,7 +2895,7 @@ function BridgePanel({ rpcCall }) {
|
|
|
2833
2895
|
},
|
|
2834
2896
|
React.createElement('div', { style: { fontWeight: 600, color: 'var(--dsw-alias-label-primary,currentColor)', marginBottom: 4 } }, '🛟 找回与重置密码指引:'),
|
|
2835
2897
|
React.createElement('div', null, '1. ', React.createElement('strong', null, '电脑本机直连修改'), ':直接在运行本程序的电脑本机打开本控制台(127.0.0.1 享有物理免锁特权),可随时修改管理密码。'),
|
|
2836
|
-
React.createElement('div', { style: { marginTop: 4 } }, '2. ', React.createElement('strong', null, '
|
|
2898
|
+
React.createElement('div', { style: { marginTop: 4 } }, '2. ', React.createElement('strong', null, '服务器 / 无头环境'), ':救急重置步骤参见 GitHub README 的「三重容灾保命体系」章节。'),
|
|
2837
2899
|
),
|
|
2838
2900
|
)
|
|
2839
2901
|
)
|
|
@@ -2980,805 +3042,7 @@ function injectMobileStyles() {
|
|
|
2980
3042
|
|
|
2981
3043
|
const style = document.createElement('style');
|
|
2982
3044
|
style.id = 'dsh-bridge-mobile-styles';
|
|
2983
|
-
style.textContent =
|
|
2984
|
-
/* DSH Bridge 隐藏 Tab 栏原生滚动条并保持平滑滑动 */
|
|
2985
|
-
.dsh-tabbar-container {
|
|
2986
|
-
scrollbar-width: none !important;
|
|
2987
|
-
-ms-overflow-style: none !important;
|
|
2988
|
-
}
|
|
2989
|
-
.dsh-tabbar-container::-webkit-scrollbar {
|
|
2990
|
-
display: none !important;
|
|
2991
|
-
width: 0 !important;
|
|
2992
|
-
height: 0 !important;
|
|
2993
|
-
}
|
|
2994
|
-
|
|
2995
|
-
/* DSH Bridge 移动端自适应与触控交互增强样式 */
|
|
2996
|
-
:root {
|
|
2997
|
-
--dsh-mobile-header-h: 52px;
|
|
2998
|
-
--dsh-mobile-safe-top: env(safe-area-inset-top, 0px);
|
|
2999
|
-
--dsh-mobile-safe-bottom: env(safe-area-inset-bottom, 0px);
|
|
3000
|
-
}
|
|
3001
|
-
|
|
3002
|
-
@media (max-width: 768px) {
|
|
3003
|
-
/* 1. 主框架为 Header 腾出顶部空间 */
|
|
3004
|
-
div[class*="_frame"] {
|
|
3005
|
-
display: flex !important;
|
|
3006
|
-
flex-direction: column !important;
|
|
3007
|
-
width: 100vw !important;
|
|
3008
|
-
height: 100dvh !important;
|
|
3009
|
-
margin: 0 !important;
|
|
3010
|
-
padding-top: var(--dsh-mobile-header-h) !important;
|
|
3011
|
-
position: relative !important;
|
|
3012
|
-
grid-template-columns: 1fr !important;
|
|
3013
|
-
overflow: hidden !important;
|
|
3014
|
-
box-sizing: border-box !important;
|
|
3015
|
-
}
|
|
3016
|
-
|
|
3017
|
-
/* 2. 顶部原生导航条:100% 还原 DeepSeek App (左侧双横线,右侧(+),中间留白,无多余设置按钮) */
|
|
3018
|
-
.dsh-mobile-app-header {
|
|
3019
|
-
position: fixed !important;
|
|
3020
|
-
top: 0 !important;
|
|
3021
|
-
left: 0 !important;
|
|
3022
|
-
right: 0 !important;
|
|
3023
|
-
height: var(--dsh-mobile-header-h) !important;
|
|
3024
|
-
padding-top: var(--dsh-mobile-safe-top) !important;
|
|
3025
|
-
background: transparent !important;
|
|
3026
|
-
display: flex !important;
|
|
3027
|
-
align-items: center !important;
|
|
3028
|
-
justify-content: space-between !important;
|
|
3029
|
-
padding-left: 16px !important;
|
|
3030
|
-
padding-right: 16px !important;
|
|
3031
|
-
z-index: 9998 !important;
|
|
3032
|
-
box-sizing: border-box !important;
|
|
3033
|
-
user-select: none !important;
|
|
3034
|
-
pointer-events: none !important;
|
|
3035
|
-
}
|
|
3036
|
-
|
|
3037
|
-
/* 左侧双横线按钮 (DeepSeek App 原生图标) */
|
|
3038
|
-
.dsh-header-menu-btn {
|
|
3039
|
-
width: 40px;
|
|
3040
|
-
height: 40px;
|
|
3041
|
-
border-radius: 50%;
|
|
3042
|
-
border: none;
|
|
3043
|
-
background: transparent;
|
|
3044
|
-
color: var(--dsw-alias-label-primary, #111827);
|
|
3045
|
-
display: inline-flex;
|
|
3046
|
-
align-items: center;
|
|
3047
|
-
justify-content: flex-start;
|
|
3048
|
-
cursor: pointer;
|
|
3049
|
-
padding: 0;
|
|
3050
|
-
transition: opacity 0.15s;
|
|
3051
|
-
pointer-events: auto !important;
|
|
3052
|
-
}
|
|
3053
|
-
.dsh-header-menu-btn:active {
|
|
3054
|
-
opacity: 0.6;
|
|
3055
|
-
}
|
|
3056
|
-
|
|
3057
|
-
/* 右侧 (+) 新建会话按钮 (DeepSeek App 原生图标) */
|
|
3058
|
-
.dsh-header-new-btn {
|
|
3059
|
-
width: 40px;
|
|
3060
|
-
height: 40px;
|
|
3061
|
-
border-radius: 50%;
|
|
3062
|
-
border: none;
|
|
3063
|
-
background: transparent;
|
|
3064
|
-
color: var(--dsw-alias-label-primary, #111827);
|
|
3065
|
-
display: inline-flex;
|
|
3066
|
-
align-items: center;
|
|
3067
|
-
justify-content: flex-end;
|
|
3068
|
-
cursor: pointer;
|
|
3069
|
-
padding: 0;
|
|
3070
|
-
transition: opacity 0.15s;
|
|
3071
|
-
pointer-events: auto !important;
|
|
3072
|
-
}
|
|
3073
|
-
.dsh-header-new-btn:active {
|
|
3074
|
-
opacity: 0.6;
|
|
3075
|
-
}
|
|
3076
|
-
|
|
3077
|
-
/* 中间动态会话标题 (单行居中打点截断,100% 还原原生 App 导航体验) */
|
|
3078
|
-
.dsh-mobile-header-title {
|
|
3079
|
-
flex: 1 1 auto !important;
|
|
3080
|
-
min-width: 0 !important;
|
|
3081
|
-
text-align: center !important;
|
|
3082
|
-
font-size: 15px !important;
|
|
3083
|
-
font-weight: 600 !important;
|
|
3084
|
-
color: var(--dsw-alias-label-primary, #111827) !important;
|
|
3085
|
-
overflow: hidden !important;
|
|
3086
|
-
text-overflow: ellipsis !important;
|
|
3087
|
-
white-space: nowrap !important;
|
|
3088
|
-
padding: 0 10px !important;
|
|
3089
|
-
user-select: none !important;
|
|
3090
|
-
pointer-events: none !important;
|
|
3091
|
-
letter-spacing: -0.2px !important;
|
|
3092
|
-
}
|
|
3093
|
-
|
|
3094
|
-
/* 3. 中间主内容区与输入框 */
|
|
3095
|
-
div[class*="_centerCol"] {
|
|
3096
|
-
flex: 1 1 100% !important;
|
|
3097
|
-
width: 100% !important;
|
|
3098
|
-
min-width: 0 !important;
|
|
3099
|
-
max-width: 100% !important;
|
|
3100
|
-
display: flex !important;
|
|
3101
|
-
height: 100% !important;
|
|
3102
|
-
}
|
|
3103
|
-
|
|
3104
|
-
div[class*="_detailsCol"],
|
|
3105
|
-
div[class*="toggleCluster"],
|
|
3106
|
-
div[class*="W-zNGW_toggleCluster"] {
|
|
3107
|
-
display: none !important;
|
|
3108
|
-
}
|
|
3109
|
-
|
|
3110
|
-
/* 3.0 工作区 Workbench / 任务管理 / 多 Tab 栏移动端自适应适配 */
|
|
3111
|
-
body:not(.dsh-workbench-open) div[class*="nArs4W_panel"],
|
|
3112
|
-
body:not(.dsh-workbench-open) div[class*="workbench_panel"],
|
|
3113
|
-
body:not(.dsh-workbench-open) div[class*="workbenchPanel"],
|
|
3114
|
-
div[class*="nArs4W_panel"][class*="panelHidden"],
|
|
3115
|
-
div[class*="workbench_panel"][class*="panelHidden"],
|
|
3116
|
-
div[class*="workbenchPanel"][class*="panelHidden"],
|
|
3117
|
-
div[class*="panelHidden"] {
|
|
3118
|
-
display: none !important;
|
|
3119
|
-
visibility: hidden !important;
|
|
3120
|
-
pointer-events: none !important;
|
|
3121
|
-
width: 0 !important;
|
|
3122
|
-
height: 0 !important;
|
|
3123
|
-
max-height: 0 !important;
|
|
3124
|
-
z-index: -1 !important;
|
|
3125
|
-
opacity: 0 !important;
|
|
3126
|
-
transform: translateX(105%) !important;
|
|
3127
|
-
}
|
|
3128
|
-
|
|
3129
|
-
body.dsh-workbench-open div[class*="nArs4W_panel"]:not([class*="panelHidden"]),
|
|
3130
|
-
body.dsh-workbench-open div[class*="workbench_panel"]:not([class*="panelHidden"]),
|
|
3131
|
-
body.dsh-workbench-open div[class*="workbenchPanel"]:not([class*="panelHidden"]) {
|
|
3132
|
-
display: flex !important;
|
|
3133
|
-
visibility: visible !important;
|
|
3134
|
-
pointer-events: auto !important;
|
|
3135
|
-
top: var(--dsh-mobile-header-h, 52px) !important;
|
|
3136
|
-
height: calc(100dvh - var(--dsh-mobile-header-h, 52px)) !important;
|
|
3137
|
-
max-height: calc(100dvh - var(--dsh-mobile-header-h, 52px)) !important;
|
|
3138
|
-
z-index: 50 !important;
|
|
3139
|
-
box-sizing: border-box !important;
|
|
3140
|
-
background: var(--dsw-alias-bg-layer-1, #ffffff) !important;
|
|
3141
|
-
transform: none !important;
|
|
3142
|
-
opacity: 1 !important;
|
|
3143
|
-
}
|
|
3144
|
-
|
|
3145
|
-
/* Tab 栏:横向滑动手势 + 干净的底部边框,杜绝与顶部移动端 Header 重叠 */
|
|
3146
|
-
div[class*="nArs4W_tabBar"],
|
|
3147
|
-
div[class*="workbench_tabBar"],
|
|
3148
|
-
div[class*="tabBar"] {
|
|
3149
|
-
min-height: 40px !important;
|
|
3150
|
-
height: 40px !important;
|
|
3151
|
-
background: var(--dsw-alias-bg-layer-1, #ffffff) !important;
|
|
3152
|
-
border-bottom: 1px solid rgba(0, 0, 0, 0.08) !important;
|
|
3153
|
-
display: flex !important;
|
|
3154
|
-
align-items: center !important;
|
|
3155
|
-
justify-content: space-between !important;
|
|
3156
|
-
padding: 0 8px !important;
|
|
3157
|
-
gap: 6px !important;
|
|
3158
|
-
overflow: visible !important;
|
|
3159
|
-
box-sizing: border-box !important;
|
|
3160
|
-
}
|
|
3161
|
-
|
|
3162
|
-
div[class*="nArs4W_tabList"],
|
|
3163
|
-
div[class*="tabList"] {
|
|
3164
|
-
display: flex !important;
|
|
3165
|
-
align-items: center !important;
|
|
3166
|
-
gap: 6px !important;
|
|
3167
|
-
flex: 1 1 auto !important;
|
|
3168
|
-
min-width: 0 !important;
|
|
3169
|
-
overflow-x: auto !important;
|
|
3170
|
-
scrollbar-width: none !important;
|
|
3171
|
-
-webkit-overflow-scrolling: touch !important;
|
|
3172
|
-
}
|
|
3173
|
-
div[class*="nArs4W_tabList"]::-webkit-scrollbar,
|
|
3174
|
-
div[class*="tabList"]::-webkit-scrollbar {
|
|
3175
|
-
display: none !important;
|
|
3176
|
-
}
|
|
3177
|
-
|
|
3178
|
-
/* 单个 Tab 胶囊化,文字超长自动打点,防止 Tab 互相挤压 */
|
|
3179
|
-
div[class*="nArs4W_tab"],
|
|
3180
|
-
div[class*="workbench_tab"] {
|
|
3181
|
-
flex: 0 0 auto !important;
|
|
3182
|
-
max-width: 170px !important;
|
|
3183
|
-
min-width: 70px !important;
|
|
3184
|
-
height: 30px !important;
|
|
3185
|
-
padding: 0 8px 0 10px !important;
|
|
3186
|
-
border-radius: 6px !important;
|
|
3187
|
-
font-size: 12.5px !important;
|
|
3188
|
-
display: inline-flex !important;
|
|
3189
|
-
align-items: center !important;
|
|
3190
|
-
justify-content: space-between !important;
|
|
3191
|
-
gap: 6px !important;
|
|
3192
|
-
background: var(--dsw-alias-bg-layer-2, #f3f4f6) !important;
|
|
3193
|
-
color: var(--dsw-alias-label-secondary, #6b7280) !important;
|
|
3194
|
-
cursor: pointer !important;
|
|
3195
|
-
user-select: none !important;
|
|
3196
|
-
box-sizing: border-box !important;
|
|
3197
|
-
}
|
|
3198
|
-
|
|
3199
|
-
div[class*="nArs4W_tabActive"],
|
|
3200
|
-
div[class*="workbench_tabActive"] {
|
|
3201
|
-
background: var(--dsw-alias-bg-layer-1, #ffffff) !important;
|
|
3202
|
-
color: var(--dsw-alias-label-primary, #111827) !important;
|
|
3203
|
-
font-weight: 600 !important;
|
|
3204
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) !important;
|
|
3205
|
-
}
|
|
3206
|
-
|
|
3207
|
-
span[class*="nArs4W_tabTitle"],
|
|
3208
|
-
span[class*="tabTitle"] {
|
|
3209
|
-
overflow: hidden !important;
|
|
3210
|
-
text-overflow: ellipsis !important;
|
|
3211
|
-
white-space: nowrap !important;
|
|
3212
|
-
flex: 1 1 auto !important;
|
|
3213
|
-
}
|
|
3214
|
-
|
|
3215
|
-
button[class*="nArs4W_tabClose"],
|
|
3216
|
-
button[class*="tabClose"] {
|
|
3217
|
-
width: 18px !important;
|
|
3218
|
-
height: 18px !important;
|
|
3219
|
-
border-radius: 50% !important;
|
|
3220
|
-
display: inline-flex !important;
|
|
3221
|
-
align-items: center !important;
|
|
3222
|
-
justify-content: center !important;
|
|
3223
|
-
flex-shrink: 0 !important;
|
|
3224
|
-
opacity: 0.6 !important;
|
|
3225
|
-
padding: 0 !important;
|
|
3226
|
-
}
|
|
3227
|
-
|
|
3228
|
-
button[class*="nArs4W_tabBarPlus"],
|
|
3229
|
-
button[class*="tabBarPlus"] {
|
|
3230
|
-
width: 28px !important;
|
|
3231
|
-
height: 28px !important;
|
|
3232
|
-
border-radius: 50% !important;
|
|
3233
|
-
display: inline-flex !important;
|
|
3234
|
-
align-items: center !important;
|
|
3235
|
-
justify-content: center !important;
|
|
3236
|
-
flex-shrink: 0 !important;
|
|
3237
|
-
}
|
|
3238
|
-
|
|
3239
|
-
/* 移动端面板右上角“返回对话 / ✕ 收起”按钮:常驻右侧,醒目且易触达 */
|
|
3240
|
-
.dsh-mobile-panel-close-btn {
|
|
3241
|
-
margin-left: 8px !important;
|
|
3242
|
-
flex: 0 0 auto !important;
|
|
3243
|
-
height: 28px !important;
|
|
3244
|
-
padding: 0 10px !important;
|
|
3245
|
-
border-radius: 14px !important;
|
|
3246
|
-
font-size: 12px !important;
|
|
3247
|
-
font-weight: 600 !important;
|
|
3248
|
-
background: #2563eb !important;
|
|
3249
|
-
color: #ffffff !important;
|
|
3250
|
-
border: none !important;
|
|
3251
|
-
display: inline-flex !important;
|
|
3252
|
-
align-items: center !important;
|
|
3253
|
-
justify-content: center !important;
|
|
3254
|
-
gap: 4px !important;
|
|
3255
|
-
cursor: pointer !important;
|
|
3256
|
-
user-select: none !important;
|
|
3257
|
-
box-shadow: 0 2px 6px rgba(37, 99, 235, 0.28) !important;
|
|
3258
|
-
white-space: nowrap !important;
|
|
3259
|
-
transition: transform 0.1s, opacity 0.15s !important;
|
|
3260
|
-
z-index: 10 !important;
|
|
3261
|
-
}
|
|
3262
|
-
.dsh-mobile-panel-close-btn:active {
|
|
3263
|
-
transform: scale(0.95) !important;
|
|
3264
|
-
opacity: 0.85 !important;
|
|
3265
|
-
}
|
|
3266
|
-
|
|
3267
|
-
/* 3.1 会话对话头部顶栏:移动端防挤压与空间释放优化(严格排除 .dsh-mobile-app-header) */
|
|
3268
|
-
div[class*="_centerCol"] header,
|
|
3269
|
-
header[class*="wSkVaW_header"] {
|
|
3270
|
-
padding: 4px 16px 2px 16px !important;
|
|
3271
|
-
position: relative !important;
|
|
3272
|
-
overflow: visible !important;
|
|
3273
|
-
}
|
|
3274
|
-
|
|
3275
|
-
div[class*="wSkVaW_titleRow"],
|
|
3276
|
-
div[class*="titleRow"] {
|
|
3277
|
-
display: flex !important;
|
|
3278
|
-
flex-direction: row !important;
|
|
3279
|
-
align-items: center !important;
|
|
3280
|
-
justify-content: space-between !important;
|
|
3281
|
-
gap: 8px !important;
|
|
3282
|
-
min-height: 32px !important;
|
|
3283
|
-
width: 100% !important;
|
|
3284
|
-
box-sizing: border-box !important;
|
|
3285
|
-
}
|
|
3286
|
-
|
|
3287
|
-
/* 移动端将原有嵌入在内容区的长面包屑标题隐藏(已统一提升至顶部导航栏正中),彻底释放第二行空间 */
|
|
3288
|
-
nav[class*="wSkVaW_crumbs"],
|
|
3289
|
-
nav[class*="crumbs"],
|
|
3290
|
-
div[class*="wSkVaW_crumbs"],
|
|
3291
|
-
div[class*="crumbs"],
|
|
3292
|
-
[class*="wSkVaW_crumbs"] {
|
|
3293
|
-
display: none !important;
|
|
3294
|
-
}
|
|
3295
|
-
|
|
3296
|
-
/* 子代理/智能体模式胶囊 (Actions):紧凑圆角胶囊 */
|
|
3297
|
-
div[class*="wSkVaW_headerActions"],
|
|
3298
|
-
div[class*="headerActions"] {
|
|
3299
|
-
flex: 0 0 auto !important;
|
|
3300
|
-
display: inline-flex !important;
|
|
3301
|
-
align-items: center !important;
|
|
3302
|
-
gap: 4px !important;
|
|
3303
|
-
margin-left: 0 !important;
|
|
3304
|
-
}
|
|
3305
|
-
|
|
3306
|
-
button[class*="h8S2Va_trigger"],
|
|
3307
|
-
button[class*="subagent"] {
|
|
3308
|
-
min-height: 26px !important;
|
|
3309
|
-
height: 26px !important;
|
|
3310
|
-
padding: 2px 8px !important;
|
|
3311
|
-
font-size: 11.5px !important;
|
|
3312
|
-
line-height: 16px !important;
|
|
3313
|
-
border-radius: 13px !important;
|
|
3314
|
-
background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.04)) !important;
|
|
3315
|
-
white-space: nowrap !important;
|
|
3316
|
-
flex-shrink: 0 !important;
|
|
3317
|
-
}
|
|
3318
|
-
|
|
3319
|
-
/* Session Log 导出下载按钮 (Utilities):在移动端极简为 28px 圆形纯图标按钮,隐藏长文本,极大释放顶部空间 */
|
|
3320
|
-
div[class*="wSkVaW_headerUtilities"],
|
|
3321
|
-
div[class*="headerUtilities"] {
|
|
3322
|
-
flex: 0 0 auto !important;
|
|
3323
|
-
margin-left: 4px !important;
|
|
3324
|
-
display: inline-flex !important;
|
|
3325
|
-
align-items: center !important;
|
|
3326
|
-
}
|
|
3327
|
-
|
|
3328
|
-
button[class*="nL4_yW_sessionLogButton"],
|
|
3329
|
-
button[class*="sessionLogButton"] {
|
|
3330
|
-
min-width: 28px !important;
|
|
3331
|
-
width: 28px !important;
|
|
3332
|
-
height: 28px !important;
|
|
3333
|
-
padding: 0 !important;
|
|
3334
|
-
border-radius: 50% !important;
|
|
3335
|
-
display: inline-flex !important;
|
|
3336
|
-
align-items: center !important;
|
|
3337
|
-
justify-content: center !important;
|
|
3338
|
-
flex-shrink: 0 !important;
|
|
3339
|
-
border: 1px solid var(--dsw-alias-border-l2, rgba(0, 0, 0, 0.1)) !important;
|
|
3340
|
-
background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.03)) !important;
|
|
3341
|
-
color: var(--dsw-alias-label-secondary, #6b7280) !important;
|
|
3342
|
-
margin-left: 0 !important;
|
|
3343
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03) !important;
|
|
3344
|
-
}
|
|
3345
|
-
|
|
3346
|
-
button[class*="nL4_yW_sessionLogButton"]:hover:not(:disabled),
|
|
3347
|
-
button[class*="sessionLogButton"]:hover:not(:disabled) {
|
|
3348
|
-
background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.06)) !important;
|
|
3349
|
-
color: var(--dsw-alias-label-primary, #111827) !important;
|
|
3350
|
-
}
|
|
3351
|
-
|
|
3352
|
-
button[class*="nL4_yW_sessionLogButton"] span,
|
|
3353
|
-
button[class*="sessionLogButton"] span {
|
|
3354
|
-
display: none !important;
|
|
3355
|
-
}
|
|
3356
|
-
|
|
3357
|
-
button[class*="nL4_yW_sessionLogButton"] svg,
|
|
3358
|
-
button[class*="sessionLogButton"] svg {
|
|
3359
|
-
width: 13px !important;
|
|
3360
|
-
height: 13px !important;
|
|
3361
|
-
margin: 0 !important;
|
|
3362
|
-
}
|
|
3363
|
-
|
|
3364
|
-
/* 子代理展开菜单在移动端右对齐与宽度自适应 */
|
|
3365
|
-
div[class*="h8S2Va_menu"] {
|
|
3366
|
-
max-width: calc(100vw - 32px) !important;
|
|
3367
|
-
left: auto !important;
|
|
3368
|
-
right: 0 !important;
|
|
3369
|
-
}
|
|
3370
|
-
|
|
3371
|
-
/* 输入框底座:DeepSeek App 居中及底部固定 */
|
|
3372
|
-
div[class*="wSkVaW_scrollBody"] {
|
|
3373
|
-
padding-bottom: max(16px, env(safe-area-inset-bottom)) !important;
|
|
3374
|
-
}
|
|
3375
|
-
|
|
3376
|
-
/* 输入卡片:DeepSeek App 圆角大胶囊造型 */
|
|
3377
|
-
div[class*="uV2eYG_card"] {
|
|
3378
|
-
border-radius: 26px !important;
|
|
3379
|
-
padding: 14px 16px 12px !important;
|
|
3380
|
-
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05) !important;
|
|
3381
|
-
border: 1px solid rgba(0, 0, 0, 0.07) !important;
|
|
3382
|
-
background: var(--dsw-alias-bg-layer-2, #f4f4f7) !important;
|
|
3383
|
-
}
|
|
3384
|
-
|
|
3385
|
-
/* 输入框底部工具栏:弹性自适应,彻底杜绝权限选择器(Full access)与模型选择器重叠碰撞 */
|
|
3386
|
-
div[class*="uV2eYG_row"] {
|
|
3387
|
-
display: flex !important;
|
|
3388
|
-
align-items: center !important;
|
|
3389
|
-
justify-content: space-between !important;
|
|
3390
|
-
gap: 6px !important;
|
|
3391
|
-
width: 100% !important;
|
|
3392
|
-
padding: 2px 2px 4px !important;
|
|
3393
|
-
box-sizing: border-box !important;
|
|
3394
|
-
}
|
|
3395
|
-
|
|
3396
|
-
div[class*="uV2eYG_tools"] {
|
|
3397
|
-
display: flex !important;
|
|
3398
|
-
align-items: center !important;
|
|
3399
|
-
gap: 6px !important;
|
|
3400
|
-
flex: 0 0 auto !important;
|
|
3401
|
-
min-width: 0 !important;
|
|
3402
|
-
}
|
|
3403
|
-
|
|
3404
|
-
div[class*="uV2eYG_modes"] {
|
|
3405
|
-
display: flex !important;
|
|
3406
|
-
align-items: center !important;
|
|
3407
|
-
gap: 4px !important;
|
|
3408
|
-
flex: 0 0 auto !important;
|
|
3409
|
-
min-width: 0 !important;
|
|
3410
|
-
}
|
|
3411
|
-
|
|
3412
|
-
button[class*="Sh0Q9G_trigger"] {
|
|
3413
|
-
flex: 0 0 auto !important;
|
|
3414
|
-
min-width: 0 !important;
|
|
3415
|
-
}
|
|
3416
|
-
|
|
3417
|
-
div[class*="uV2eYG_trailing"] {
|
|
3418
|
-
display: flex !important;
|
|
3419
|
-
align-items: center !important;
|
|
3420
|
-
justify-content: flex-end !important;
|
|
3421
|
-
gap: 6px !important;
|
|
3422
|
-
flex: 1 1 auto !important;
|
|
3423
|
-
min-width: 0 !important;
|
|
3424
|
-
}
|
|
3425
|
-
|
|
3426
|
-
div[class*="_7KE1Ra_root"] {
|
|
3427
|
-
flex: 0 1 auto !important;
|
|
3428
|
-
min-width: 0 !important;
|
|
3429
|
-
max-width: 180px !important;
|
|
3430
|
-
}
|
|
3431
|
-
|
|
3432
|
-
button[class*="_7KE1Ra_trigger"] {
|
|
3433
|
-
max-width: 100% !important;
|
|
3434
|
-
min-width: 0 !important;
|
|
3435
|
-
flex: 1 1 auto !important;
|
|
3436
|
-
padding: 0 4px 0 6px !important;
|
|
3437
|
-
}
|
|
3438
|
-
|
|
3439
|
-
span[class*="_7KE1Ra_triggerLabel"] {
|
|
3440
|
-
overflow: hidden !important;
|
|
3441
|
-
text-overflow: ellipsis !important;
|
|
3442
|
-
white-space: nowrap !important;
|
|
3443
|
-
min-width: 0 !important;
|
|
3444
|
-
}
|
|
3445
|
-
|
|
3446
|
-
/* 4. 原生侧边栏抽屉化 (Drawer) */
|
|
3447
|
-
div[class*="_sidebarCol"] {
|
|
3448
|
-
position: fixed !important;
|
|
3449
|
-
left: 0 !important;
|
|
3450
|
-
top: 0 !important;
|
|
3451
|
-
bottom: 0 !important;
|
|
3452
|
-
height: 100dvh !important;
|
|
3453
|
-
width: 290px !important;
|
|
3454
|
-
max-width: 82vw !important;
|
|
3455
|
-
z-index: 10000 !important;
|
|
3456
|
-
background: var(--dsw-alias-bg-layer-1, #ffffff) !important;
|
|
3457
|
-
transform: translateX(-105%);
|
|
3458
|
-
transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
|
3459
|
-
overflow-y: auto !important;
|
|
3460
|
-
border-right: 1px solid rgba(0, 0, 0, 0.06) !important;
|
|
3461
|
-
pointer-events: auto !important;
|
|
3462
|
-
}
|
|
3463
|
-
body.dsh-drawer-open div[class*="_sidebarCol"] {
|
|
3464
|
-
transform: translateX(0) !important;
|
|
3465
|
-
box-shadow: 4px 0 28px rgba(0, 0, 0, 0.25) !important;
|
|
3466
|
-
pointer-events: auto !important;
|
|
3467
|
-
}
|
|
3468
|
-
|
|
3469
|
-
/* 抽屉内部:强制 100% 宽度,无论内部状态如何均正常展开并展示 DSH 自带的顶部收起侧边栏图标 */
|
|
3470
|
-
body.dsh-drawer-open div[class*="hHd-Xa_root"] {
|
|
3471
|
-
width: 100% !important;
|
|
3472
|
-
max-width: 100% !important;
|
|
3473
|
-
min-width: 100% !important;
|
|
3474
|
-
display: flex !important;
|
|
3475
|
-
flex-direction: column !important;
|
|
3476
|
-
}
|
|
3477
|
-
body.dsh-drawer-open div[class*="hHd-Xa_collapsed"] div[class*="hHd-Xa_regionArea"],
|
|
3478
|
-
body.dsh-drawer-open div[class*="hHd-Xa_collapsed"] button[class*="hHd-Xa_newSession"],
|
|
3479
|
-
body.dsh-drawer-open div[class*="hHd-Xa_collapsed"] div[class*="qDHVXG_root"] {
|
|
3480
|
-
display: flex !important;
|
|
3481
|
-
visibility: visible !important;
|
|
3482
|
-
}
|
|
3483
|
-
div[class*="hHd-Xa_logoRow"] {
|
|
3484
|
-
display: flex !important;
|
|
3485
|
-
align-items: center !important;
|
|
3486
|
-
justify-content: space-between !important;
|
|
3487
|
-
width: 100% !important;
|
|
3488
|
-
padding: 10px 14px 6px 14px !important;
|
|
3489
|
-
box-sizing: border-box !important;
|
|
3490
|
-
}
|
|
3491
|
-
div[class*="hHd-Xa_logoRow"] button[class*="hHd-Xa_toggle"] {
|
|
3492
|
-
display: inline-flex !important;
|
|
3493
|
-
align-items: center !important;
|
|
3494
|
-
justify-content: center !important;
|
|
3495
|
-
width: 32px !important;
|
|
3496
|
-
height: 32px !important;
|
|
3497
|
-
border-radius: 8px !important;
|
|
3498
|
-
color: var(--dsw-alias-label-secondary, #6b7280) !important;
|
|
3499
|
-
background: transparent !important;
|
|
3500
|
-
border: none !important;
|
|
3501
|
-
cursor: pointer !important;
|
|
3502
|
-
margin-left: auto !important;
|
|
3503
|
-
transition: background 0.15s, color 0.15s !important;
|
|
3504
|
-
}
|
|
3505
|
-
div[class*="hHd-Xa_logoRow"] button[class*="hHd-Xa_toggle"]:active {
|
|
3506
|
-
background: var(--dsw-alias-bg-layer-2, rgba(0, 0, 0, 0.06)) !important;
|
|
3507
|
-
color: var(--dsw-alias-label-primary, #111827) !important;
|
|
3508
|
-
}
|
|
3509
|
-
|
|
3510
|
-
/* 设置弹窗打开时解除抽屉隐藏限制 */
|
|
3511
|
-
div[class*="_sidebarCol"]:has(div[class*="VOzbGW_overlay"]) {
|
|
3512
|
-
transform: none !important;
|
|
3513
|
-
width: 100vw !important;
|
|
3514
|
-
max-width: 100vw !important;
|
|
3515
|
-
background: transparent !important;
|
|
3516
|
-
box-shadow: none !important;
|
|
3517
|
-
pointer-events: none !important;
|
|
3518
|
-
}
|
|
3519
|
-
|
|
3520
|
-
/* 5. 半透明背景遮罩 */
|
|
3521
|
-
.dsh-mobile-backdrop {
|
|
3522
|
-
position: fixed;
|
|
3523
|
-
inset: 0;
|
|
3524
|
-
background: rgba(0, 0, 0, 0.4);
|
|
3525
|
-
z-index: 9999;
|
|
3526
|
-
display: none !important;
|
|
3527
|
-
}
|
|
3528
|
-
body.dsh-drawer-open .dsh-mobile-backdrop {
|
|
3529
|
-
display: block !important;
|
|
3530
|
-
pointer-events: auto !important;
|
|
3531
|
-
}
|
|
3532
|
-
|
|
3533
|
-
/* 6. 设置中心全自适应适配 */
|
|
3534
|
-
div[class*="VOzbGW_overlay"] {
|
|
3535
|
-
position: fixed !important;
|
|
3536
|
-
inset: 0 !important;
|
|
3537
|
-
width: 100vw !important;
|
|
3538
|
-
height: 100dvh !important;
|
|
3539
|
-
display: flex !important;
|
|
3540
|
-
align-items: center !important;
|
|
3541
|
-
justify-content: center !important;
|
|
3542
|
-
background: rgba(0, 0, 0, 0.45) !important;
|
|
3543
|
-
backdrop-filter: blur(4px) !important;
|
|
3544
|
-
-webkit-backdrop-filter: blur(4px) !important;
|
|
3545
|
-
z-index: 10002 !important;
|
|
3546
|
-
padding: 10px !important;
|
|
3547
|
-
box-sizing: border-box !important;
|
|
3548
|
-
pointer-events: auto !important;
|
|
3549
|
-
}
|
|
3550
|
-
div[class*="VOzbGW_panel"] {
|
|
3551
|
-
width: 100% !important;
|
|
3552
|
-
max-width: 100% !important;
|
|
3553
|
-
height: 92dvh !important;
|
|
3554
|
-
max-height: 92dvh !important;
|
|
3555
|
-
display: flex !important;
|
|
3556
|
-
flex-direction: row !important;
|
|
3557
|
-
border-radius: 18px !important;
|
|
3558
|
-
overflow: hidden !important;
|
|
3559
|
-
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.25) !important;
|
|
3560
|
-
background: var(--dsw-alias-bg-layer-1, #ffffff) !important;
|
|
3561
|
-
}
|
|
3562
|
-
nav[class*="VOzbGW_nav"] {
|
|
3563
|
-
width: 78px !important;
|
|
3564
|
-
min-width: 78px !important;
|
|
3565
|
-
max-width: 78px !important;
|
|
3566
|
-
padding: 10px 4px !important;
|
|
3567
|
-
box-sizing: border-box !important;
|
|
3568
|
-
border-right: 1px solid var(--dsw-alias-border-l2, #e5e7eb) !important;
|
|
3569
|
-
display: flex !important;
|
|
3570
|
-
flex-direction: column !important;
|
|
3571
|
-
gap: 6px !important;
|
|
3572
|
-
overflow-y: auto !important;
|
|
3573
|
-
}
|
|
3574
|
-
nav[class*="VOzbGW_nav"] button[class*="VOzbGW_navCell"],
|
|
3575
|
-
button[class*="VOzbGW_navCell"] {
|
|
3576
|
-
padding: 8px 2px !important;
|
|
3577
|
-
display: flex !important;
|
|
3578
|
-
flex-direction: column !important;
|
|
3579
|
-
align-items: center !important;
|
|
3580
|
-
justify-content: center !important;
|
|
3581
|
-
text-align: center !important;
|
|
3582
|
-
height: auto !important;
|
|
3583
|
-
min-height: 48px !important;
|
|
3584
|
-
gap: 4px !important;
|
|
3585
|
-
border-radius: 10px !important;
|
|
3586
|
-
}
|
|
3587
|
-
span[class*="VOzbGW_navLabel"] {
|
|
3588
|
-
font-size: 10.5px !important;
|
|
3589
|
-
line-height: 1.2 !important;
|
|
3590
|
-
white-space: normal !important;
|
|
3591
|
-
word-break: break-all !important;
|
|
3592
|
-
text-align: center !important;
|
|
3593
|
-
}
|
|
3594
|
-
div[class*="VOzbGW_content"] {
|
|
3595
|
-
flex: 1 1 auto !important;
|
|
3596
|
-
min-width: 0 !important;
|
|
3597
|
-
width: calc(100% - 78px) !important;
|
|
3598
|
-
max-width: calc(100% - 78px) !important;
|
|
3599
|
-
display: flex !important;
|
|
3600
|
-
flex-direction: column !important;
|
|
3601
|
-
overflow: hidden !important;
|
|
3602
|
-
}
|
|
3603
|
-
div[class*="VOzbGW_options"] {
|
|
3604
|
-
flex: 1 1 auto !important;
|
|
3605
|
-
width: 100% !important;
|
|
3606
|
-
max-width: 100% !important;
|
|
3607
|
-
box-sizing: border-box !important;
|
|
3608
|
-
padding: 0 14px 20px !important;
|
|
3609
|
-
overflow-x: hidden !important;
|
|
3610
|
-
overflow-y: auto !important;
|
|
3611
|
-
-webkit-overflow-scrolling: touch !important;
|
|
3612
|
-
}
|
|
3613
|
-
|
|
3614
|
-
/* 设置中心选项行手机自适应(垂直流式,防文字单字折行) */
|
|
3615
|
-
div[class*="VOzbGW_options"] div[class*="_row"] {
|
|
3616
|
-
display: flex !important;
|
|
3617
|
-
flex-direction: column !important;
|
|
3618
|
-
align-items: stretch !important;
|
|
3619
|
-
gap: 8px !important;
|
|
3620
|
-
width: 100% !important;
|
|
3621
|
-
padding: 12px 0 !important;
|
|
3622
|
-
box-sizing: border-box !important;
|
|
3623
|
-
}
|
|
3624
|
-
div[class*="VOzbGW_options"] div[class*="_rowText"] {
|
|
3625
|
-
width: 100% !important;
|
|
3626
|
-
max-width: 100% !important;
|
|
3627
|
-
}
|
|
3628
|
-
div[class*="VOzbGW_options"] button[class*="_selector"],
|
|
3629
|
-
div[class*="VOzbGW_options"] select,
|
|
3630
|
-
div[class*="VOzbGW_options"] input {
|
|
3631
|
-
width: 100% !important;
|
|
3632
|
-
max-width: 100% !important;
|
|
3633
|
-
box-sizing: border-box !important;
|
|
3634
|
-
}
|
|
3635
|
-
|
|
3636
|
-
/* 7. 代码块、表格与徽标自适应 */
|
|
3637
|
-
pre, code, pre > code, table {
|
|
3638
|
-
max-width: 100% !important;
|
|
3639
|
-
overflow-x: auto !important;
|
|
3640
|
-
-webkit-overflow-scrolling: touch !important;
|
|
3641
|
-
font-size: 12.5px !important;
|
|
3642
|
-
}
|
|
3643
|
-
|
|
3644
|
-
/* 状态徽标与药丸按钮永不折字 */
|
|
3645
|
-
span[style*="border-radius: 999"],
|
|
3646
|
-
span[style*="border-radius:999"] {
|
|
3647
|
-
white-space: nowrap !important;
|
|
3648
|
-
flex-shrink: 0 !important;
|
|
3649
|
-
min-width: max-content !important;
|
|
3650
|
-
}
|
|
3651
|
-
|
|
3652
|
-
/* 二维码与图片移动端弹性缩放 */
|
|
3653
|
-
img[alt="QR"], img[src^="data:image"] {
|
|
3654
|
-
max-width: 100% !important;
|
|
3655
|
-
box-sizing: border-box !important;
|
|
3656
|
-
}
|
|
3657
|
-
|
|
3658
|
-
/* 8. 确保所有 Popover 弹出菜单、操作气泡、下拉框位于抽屉之上且支持触控交互 */
|
|
3659
|
-
div[class*="_portal"],
|
|
3660
|
-
div[class*="portal"],
|
|
3661
|
-
div[class*="popup"],
|
|
3662
|
-
div[class*="dropdown"],
|
|
3663
|
-
div[class*="menu"],
|
|
3664
|
-
div[role="menu"],
|
|
3665
|
-
div[role="dialog"] {
|
|
3666
|
-
z-index: 10005 !important;
|
|
3667
|
-
pointer-events: auto !important;
|
|
3668
|
-
}
|
|
3669
|
-
|
|
3670
|
-
/* 9. 移动端侧边栏:会话与工作区三点操作按钮始终清晰可见且易于点击 */
|
|
3671
|
-
div[class*="sessionRow"] span[class*="rowActions"],
|
|
3672
|
-
div[class*="sessionRow"] button[class*="iconButton"],
|
|
3673
|
-
div[class*="treeBody"] button[class*="iconButton"] {
|
|
3674
|
-
opacity: 0.8 !important;
|
|
3675
|
-
display: inline-flex !important;
|
|
3676
|
-
visibility: visible !important;
|
|
3677
|
-
pointer-events: auto !important;
|
|
3678
|
-
}
|
|
3679
|
-
div[class*="sessionRow"]:active {
|
|
3680
|
-
background: var(--dsw-alias-bg-layer-2, #f3f4f6) !important;
|
|
3681
|
-
}
|
|
3682
|
-
|
|
3683
|
-
/* 全局 overlayLayer 绝不被染黑 */
|
|
3684
|
-
div[class*="overlayLayer"],
|
|
3685
|
-
div[class*="uV2eYG_overlayAnchor"] {
|
|
3686
|
-
background: transparent !important;
|
|
3687
|
-
pointer-events: none !important;
|
|
3688
|
-
}
|
|
3689
|
-
div[class*="overlayLayer"] > * {
|
|
3690
|
-
pointer-events: auto !important;
|
|
3691
|
-
}
|
|
3692
|
-
}
|
|
3693
|
-
|
|
3694
|
-
/* 远程工作区选择弹窗移动端/桌面端自适应样式 */
|
|
3695
|
-
#dsh-remote-workspace-modal {
|
|
3696
|
-
position: fixed !important;
|
|
3697
|
-
inset: 0 !important;
|
|
3698
|
-
z-index: 100000 !important;
|
|
3699
|
-
background: rgba(0, 0, 0, 0.65) !important;
|
|
3700
|
-
backdrop-filter: blur(5px) !important;
|
|
3701
|
-
display: flex !important;
|
|
3702
|
-
align-items: center !important;
|
|
3703
|
-
justify-content: center !important;
|
|
3704
|
-
padding: 16px !important;
|
|
3705
|
-
box-sizing: border-box !important;
|
|
3706
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
3707
|
-
color: var(--dsw-alias-label-primary, #111827) !important;
|
|
3708
|
-
}
|
|
3709
|
-
|
|
3710
|
-
.dsh-ws-dialog-card {
|
|
3711
|
-
background: var(--dsw-alias-bg-layer-1, #ffffff) !important;
|
|
3712
|
-
border: 1px solid var(--dsw-alias-border-l1, #e5e7eb) !important;
|
|
3713
|
-
border-radius: 16px !important;
|
|
3714
|
-
width: 100% !important;
|
|
3715
|
-
max-width: 620px !important;
|
|
3716
|
-
max-height: 88vh !important;
|
|
3717
|
-
display: flex !important;
|
|
3718
|
-
flex-direction: column !important;
|
|
3719
|
-
box-shadow: 0 25px 35px -5px rgba(0,0,0,0.3), 0 12px 16px -5px rgba(0,0,0,0.2) !important;
|
|
3720
|
-
overflow: hidden !important;
|
|
3721
|
-
animation: dshModalFadeIn 0.2s ease-out !important;
|
|
3722
|
-
}
|
|
3723
|
-
|
|
3724
|
-
.dsh-ws-chips-scroll {
|
|
3725
|
-
display: flex !important;
|
|
3726
|
-
align-items: center !important;
|
|
3727
|
-
gap: 6px !important;
|
|
3728
|
-
overflow-x: auto !important;
|
|
3729
|
-
white-space: nowrap !important;
|
|
3730
|
-
scrollbar-width: none !important;
|
|
3731
|
-
-ms-overflow-style: none !important;
|
|
3732
|
-
-webkit-overflow-scrolling: touch !important;
|
|
3733
|
-
padding: 2px 0 !important;
|
|
3734
|
-
}
|
|
3735
|
-
.dsh-ws-chips-scroll::-webkit-scrollbar {
|
|
3736
|
-
display: none !important;
|
|
3737
|
-
}
|
|
3738
|
-
|
|
3739
|
-
@media (max-width: 640px) {
|
|
3740
|
-
#dsh-remote-workspace-modal {
|
|
3741
|
-
align-items: flex-end !important;
|
|
3742
|
-
padding: 0 !important;
|
|
3743
|
-
}
|
|
3744
|
-
|
|
3745
|
-
.dsh-ws-dialog-card {
|
|
3746
|
-
max-height: 92dvh !important;
|
|
3747
|
-
height: 92dvh !important;
|
|
3748
|
-
border-bottom-left-radius: 0 !important;
|
|
3749
|
-
border-bottom-right-radius: 0 !important;
|
|
3750
|
-
border-left: none !important;
|
|
3751
|
-
border-right: none !important;
|
|
3752
|
-
border-bottom: none !important;
|
|
3753
|
-
max-width: 100vw !important;
|
|
3754
|
-
width: 100vw !important;
|
|
3755
|
-
margin: 0 !important;
|
|
3756
|
-
animation: dshBottomSheetUp 0.25s cubic-bezier(0.16, 1, 0.3, 1) !important;
|
|
3757
|
-
}
|
|
3758
|
-
|
|
3759
|
-
.dsh-ws-drag-handle {
|
|
3760
|
-
display: block !important;
|
|
3761
|
-
}
|
|
3762
|
-
}
|
|
3763
|
-
|
|
3764
|
-
@keyframes dshModalFadeIn {
|
|
3765
|
-
from { opacity: 0; transform: scale(0.96); }
|
|
3766
|
-
to { opacity: 1; transform: scale(1); }
|
|
3767
|
-
}
|
|
3768
|
-
|
|
3769
|
-
@keyframes dshBottomSheetUp {
|
|
3770
|
-
from { transform: translateY(100%); }
|
|
3771
|
-
to { transform: translateY(0); }
|
|
3772
|
-
}
|
|
3773
|
-
|
|
3774
|
-
@media (min-width: 769px) {
|
|
3775
|
-
.dsh-mobile-app-header,
|
|
3776
|
-
.dsh-mobile-backdrop,
|
|
3777
|
-
.dsh-mobile-panel-close-btn {
|
|
3778
|
-
display: none !important;
|
|
3779
|
-
}
|
|
3780
|
-
}
|
|
3781
|
-
`;
|
|
3045
|
+
style.textContent = MOBILE_STYLES_CSS;
|
|
3782
3046
|
document.head.appendChild(style);
|
|
3783
3047
|
}
|
|
3784
3048
|
|