dsh-remote-plugin 0.5.7-rc.1 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +1 -0
- package/README.md +1 -0
- package/apk/dsh-remote.apk +0 -0
- package/gateway-stats.cjs +26 -12
- package/package.json +1 -1
- package/public/admin.html +15 -1
- package/public/admin.js +18 -6
- package/public/app.js +461 -42
- package/public/desktop/desktop.css +207 -0
- package/public/desktop/desktop.html +247 -0
- package/public/desktop/desktop.js +917 -0
- package/public/desktop/i18n.js +53 -0
- package/public/index.html +77 -2
- package/public/styles.css +54 -351
- package/public/theme-vars.css +351 -0
- package/public/update.json +3 -3
- package/public/version.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* DSH Remote 桌面端轻量 i18n · 零依赖(与 public/i18n.js 同构) */
|
|
2
|
+
'use strict'
|
|
3
|
+
;(function () {
|
|
4
|
+
const store = {
|
|
5
|
+
get(k) { try { return localStorage.getItem(k) } catch { return null } },
|
|
6
|
+
set(k, v) { try { localStorage.setItem(k, v) } catch {} }
|
|
7
|
+
}
|
|
8
|
+
function detect() {
|
|
9
|
+
const saved = store.get('dshLang')
|
|
10
|
+
if (saved === 'zh' || saved === 'en') return saved
|
|
11
|
+
return (navigator.language || 'zh').toLowerCase().startsWith('zh') ? 'zh' : 'en'
|
|
12
|
+
}
|
|
13
|
+
let dict = null
|
|
14
|
+
let lang = detect()
|
|
15
|
+
|
|
16
|
+
function t(key, vars) {
|
|
17
|
+
const table = (dict && (dict[lang] || dict.zh)) || {}
|
|
18
|
+
let s = table[key]
|
|
19
|
+
if (s == null) s = (dict && dict.zh && dict.zh[key]) != null ? dict.zh[key] : key
|
|
20
|
+
s = String(s)
|
|
21
|
+
if (vars) {
|
|
22
|
+
const keys = new Set(Object.keys(vars))
|
|
23
|
+
s = s.replace(/\{([A-Za-z0-9_]+)\}/g, (m, k) => keys.has(k) ? String(vars[k] ?? '') : '')
|
|
24
|
+
} else {
|
|
25
|
+
s = s.replace(/\{[A-Za-z0-9_]+\}/g, '')
|
|
26
|
+
}
|
|
27
|
+
return s
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function apply(root) {
|
|
31
|
+
root = root || document
|
|
32
|
+
root.querySelectorAll('[data-i18n]').forEach(el => { el.textContent = t(el.getAttribute('data-i18n')) })
|
|
33
|
+
root.querySelectorAll('[data-i18n-title]').forEach(el => { el.title = t(el.getAttribute('data-i18n-title')) })
|
|
34
|
+
root.querySelectorAll('[data-i18n-placeholder]').forEach(el => { el.placeholder = t(el.getAttribute('data-i18n-placeholder')) })
|
|
35
|
+
root.querySelectorAll('[data-i18n-aria]').forEach(el => { el.setAttribute('aria-label', t(el.getAttribute('data-i18n-aria'))) })
|
|
36
|
+
document.documentElement.lang = lang === 'zh' ? 'zh-CN' : 'en'
|
|
37
|
+
return lang
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function setLang(l) {
|
|
41
|
+
if (l !== 'zh' && l !== 'en') return lang
|
|
42
|
+
lang = l
|
|
43
|
+
store.set('dshLang', l)
|
|
44
|
+
apply(document)
|
|
45
|
+
return lang
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
window.I18N = {
|
|
49
|
+
init(strings) { dict = strings || dict; return apply(document) },
|
|
50
|
+
t, setLang, apply,
|
|
51
|
+
get lang() { return lang }
|
|
52
|
+
}
|
|
53
|
+
})()
|
package/public/index.html
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
<meta name="mobile-web-app-capable" content="yes">
|
|
8
8
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
9
9
|
<title>DSH Remote</title>
|
|
10
|
+
<script>/* 统一入口: 桌面浏览器(宽屏且 UA 非移动)访问根地址自动切换到桌面端, 手机/窄窗口继续 App 界面 */ (function(){try{var proto=location.protocol;var ua=navigator.userAgent||'';var mobile=/Android|iPhone|iPad|iPod|Mobile|Windows Phone/i.test(ua);if((proto==='http:'||proto==='https:')&&!mobile&&window.innerWidth>=1024){var p=location.pathname;if(p==='/'||/\/index\.html$/.test(p)){location.replace('desktop/desktop.html'+location.search)}}}catch(e){}})()</script>
|
|
10
11
|
<script>/* 首帧前应用皮肤, 避免闪白/闪黑 */ (function(){try{var t=localStorage.getItem('dshTheme');if(t!=='default'&&t!=='dark'&&t!=='light'&&t!=='neutral'){t=window.matchMedia('(prefers-color-scheme: light)').matches?'light':'default'}document.documentElement.setAttribute('data-theme',t)}catch(e){}})()</script>
|
|
11
12
|
<link rel="manifest" href="manifest.webmanifest">
|
|
12
13
|
<link rel="icon" href="icon.svg" type="image/svg+xml">
|
|
@@ -128,6 +129,15 @@
|
|
|
128
129
|
<div id="jobs-list" class="jobs-list"></div>
|
|
129
130
|
</section>
|
|
130
131
|
|
|
132
|
+
<!-- Token 统计 -->
|
|
133
|
+
<section id="view-stats" class="view hidden">
|
|
134
|
+
<div class="section-head"><span data-i18n="statsPage.title">Token 统计</span><span id="stats-sub" class="muted"></span></div>
|
|
135
|
+
<div class="stats-cards" id="stats-cards"></div>
|
|
136
|
+
<div id="stats-legend" class="stats-legend"></div>
|
|
137
|
+
<div id="stats-chart" class="stats-chart"></div>
|
|
138
|
+
<div id="stats-note" class="stats-note"></div>
|
|
139
|
+
</section>
|
|
140
|
+
|
|
131
141
|
<!-- 设置 -->
|
|
132
142
|
<section id="view-settings" class="view hidden">
|
|
133
143
|
<div class="settings-group">
|
|
@@ -135,6 +145,16 @@
|
|
|
135
145
|
<div><div class="setting-name" data-i18n="settings.servers">服务器地址(可多个)</div><div class="setting-desc" id="server-desc" data-i18n="servers.defaultDesc">默认 = 当前页面地址</div></div>
|
|
136
146
|
<button id="btn-server-speed" class="mini-btn" data-i18n="settings.speedTest">测速</button>
|
|
137
147
|
</div>
|
|
148
|
+
<div class="group-bar">
|
|
149
|
+
<label class="group-bar-label" data-i18n="groups.current">当前组</label>
|
|
150
|
+
<div class="group-select" id="group-select">
|
|
151
|
+
<button id="group-select-btn" class="group-select-btn" type="button" aria-haspopup="listbox">
|
|
152
|
+
<span id="group-select-label">默认</span><span class="caret">▾</span>
|
|
153
|
+
</button>
|
|
154
|
+
<div id="group-select-menu" class="group-select-menu hidden"></div>
|
|
155
|
+
</div>
|
|
156
|
+
<button id="btn-group-add" class="mini-btn" data-i18n="groups.add">+ 组</button>
|
|
157
|
+
</div>
|
|
138
158
|
<div id="server-list" class="server-list"></div>
|
|
139
159
|
<div class="server-add">
|
|
140
160
|
<input id="server-input" type="url" placeholder="http://IP:8787">
|
|
@@ -148,6 +168,10 @@
|
|
|
148
168
|
<div><div class="setting-name" data-i18n="settings.notifyTitle">通知</div><div class="setting-desc" data-i18n="settings.notifyDesc">收到审批/提问时推送</div></div>
|
|
149
169
|
<label class="switch"><input type="checkbox" id="opt-notify"><span class="slider"></span></label>
|
|
150
170
|
</div>
|
|
171
|
+
<div class="setting-row">
|
|
172
|
+
<div><div class="setting-name" data-i18n="settings.peakRemindTitle">峰谷计费提醒</div><div class="setting-desc" data-i18n="settings.peakRemindDesc">每天 9:00 / 12:00 / 14:00 / 18:00 推送峰谷切换(App 内有效)</div></div>
|
|
173
|
+
<label class="switch"><input type="checkbox" id="opt-peak-remind"><span class="slider"></span></label>
|
|
174
|
+
</div>
|
|
151
175
|
<div class="setting-row">
|
|
152
176
|
<div><div class="setting-name" data-i18n="settings.toolsTitle">显示工具调用</div><div class="setting-desc" data-i18n="settings.toolsDesc">关闭后隐藏 🔧/📦 工具调用与结果</div></div>
|
|
153
177
|
<label class="switch"><input type="checkbox" id="opt-tools"><span class="slider"></span></label>
|
|
@@ -189,6 +213,7 @@
|
|
|
189
213
|
<button data-view="view-home" class="nav-btn active"><span class="nav-ico">▤</span><span data-i18n="nav.sessions">会话</span></button>
|
|
190
214
|
<button data-view="view-files" class="nav-btn"><span class="nav-ico">⇅</span><span data-i18n="nav.files">文件</span></button>
|
|
191
215
|
<button data-view="view-activity" class="nav-btn"><span class="nav-ico">◷</span><span data-i18n="nav.pending">待办</span><b id="nav-pending" class="nav-badge hidden"></b></button>
|
|
216
|
+
<button data-view="view-stats" class="nav-btn"><span class="nav-ico">▦</span><span data-i18n="nav.stats">统计</span></button>
|
|
192
217
|
<button data-view="view-settings" class="nav-btn"><span class="nav-ico">⚙</span><span data-i18n="nav.settings">设置</span></button>
|
|
193
218
|
</nav>
|
|
194
219
|
|
|
@@ -257,8 +282,15 @@
|
|
|
257
282
|
zh: {
|
|
258
283
|
'a11y.hostAdmin': '主机管理', 'a11y.refresh': '刷新', 'a11y.more': '更多操作', 'a11y.moreTitle': '指令/权限/模型',
|
|
259
284
|
'conn.on': '已连接', 'conn.off': '未连接', 'conn.reconnecting': '连接中断,正在重连…',
|
|
285
|
+
'conn.titleGroup': '{group} · {url}({ms})',
|
|
260
286
|
'common.refreshing': '刷新中…',
|
|
261
|
-
'nav.sessions': '会话', 'nav.files': '文件', 'nav.pending': '待办', 'nav.settings': '设置',
|
|
287
|
+
'nav.sessions': '会话', 'nav.files': '文件', 'nav.pending': '待办', 'nav.stats': '统计', 'nav.settings': '设置',
|
|
288
|
+
'statsPage.title': 'Token 统计',
|
|
289
|
+
'statsPage.todayTokens': '今日 Token', 'statsPage.todayCost': '今日费用', 'statsPage.peakShare': '高峰占比',
|
|
290
|
+
'statsPage.input': '未缓存输入', 'statsPage.cacheRead': '缓存命中', 'statsPage.cacheWrite': '缓存写入', 'statsPage.output': '输出',
|
|
291
|
+
'statsPage.peak': '高峰', 'statsPage.off': '空闲', 'statsPage.days': '近 {n} 天',
|
|
292
|
+
'statsPage.gatewayDown': '统计需要网关运行', 'statsPage.empty': '暂无统计,产生会话后自动聚合',
|
|
293
|
+
'statsPage.note': '注:本数据仅在使用 DeepSeek 官方 API 时估算;基于 token 计算,与官网账单可能有出入,一切以官网为准。统计自 2026-08-17 定价生效日起。',
|
|
262
294
|
'home.newSession': '+ 新会话', 'home.empty': '暂无会话', 'home.createFailed': '新建会话失败', 'home.created': '会话已创建',
|
|
263
295
|
'sessions.running': '运行中', 'sessions.statRunning': '运行中', 'sessions.statPending': '待处理', 'sessions.statTotal': '会话总数',
|
|
264
296
|
'sessions.queueBadge': '队列 {n}', 'sessions.goalBadge': '目标·{phase}',
|
|
@@ -277,6 +309,18 @@
|
|
|
277
309
|
'servers.currentDesc': '当前: {url}', 'servers.notSet': '未设置服务器', 'servers.defaultDesc': '默认 = 当前页面地址',
|
|
278
310
|
'servers.needAddress': '请输入服务器地址', 'servers.badProtocol': '地址需以 http:// 或 https:// 开头',
|
|
279
311
|
'servers.duplicate': '该地址已在列表中', 'servers.added': '已添加服务器', 'servers.removedActive': '已删除当前服务器,重新测速…',
|
|
312
|
+
'servers.currentDescGroup': '当前:{group} · {url}({ms})',
|
|
313
|
+
'servers.edit': '编辑', 'servers.manualSelected': '已切换至:{url}',
|
|
314
|
+
'servers.promptNote': '服务器备注(可留空):', 'servers.promptEditNote': '编辑备注({url}):',
|
|
315
|
+
'servers.promptEditUrl': '编辑服务器地址:', 'servers.promptEditGroup': '所属组:', 'servers.edited': '服务器已更新',
|
|
316
|
+
'speed.switchedOrigin': '已切换到当前页面(同源)', 'speed.manualUsing': '手动模式:{url}({ms})',
|
|
317
|
+
'groups.current': '当前组', 'groups.add': '+ 组', 'groups.noServer': '组内暂无服务器',
|
|
318
|
+
'groups.speedTest': '测速', 'groups.autoSelect': '自动选择最快', 'groups.delete': '删除组',
|
|
319
|
+
'groups.autoOn': '{group} 已切换为自动选择', 'groups.autoOff': '{group} 已切换为手动选择',
|
|
320
|
+
'groups.switched': '已切换到组:{group}', 'groups.switchHint': '点击切换当前组,双击重命名', 'groups.promptAdd': '新组名:', 'groups.duplicate': '组名已存在',
|
|
321
|
+
'groups.added': '已创建组:{group}', 'groups.promptRename': '重命名组「{group}」:',
|
|
322
|
+
'groups.renamed': '组已重命名', 'groups.cannotDeleteDefault': '默认组不可删除',
|
|
323
|
+
'groups.confirmDelete': '删除组「{group}」?组内服务器将归入默认组。', 'groups.deleted': '组已删除',
|
|
280
324
|
'stream.error': '事件流错误:{msg}',
|
|
281
325
|
'session.loading': '加载中…', 'session.unknown': '未知会话', 'session.running': '运行中', 'session.interrupted': '已中断',
|
|
282
326
|
'session.stop': '停止', 'session.history': '对话', 'session.errorMsg': '会话出错:{msg}',
|
|
@@ -352,6 +396,12 @@
|
|
|
352
396
|
'settings.servers': '服务器地址(可多个)', 'settings.speedTest': '测速', 'settings.add': '添加',
|
|
353
397
|
'settings.scanTitle': '扫码连接', 'settings.scanDesc': '拍照/相册本地解码(无谷歌服务依赖);也可系统相机扫码或手动粘贴', 'settings.scan': '扫码',
|
|
354
398
|
'settings.notifyTitle': '通知', 'settings.notifyDesc': '收到审批/提问时推送',
|
|
399
|
+
'settings.peakRemindTitle': '峰谷计费提醒', 'settings.peakRemindDesc': '每天 9:00 / 12:00 / 14:00 / 18:00 推送峰谷切换(App 内有效)',
|
|
400
|
+
'peakRemind.enterPeak': '已进入高峰计费时段', 'peakRemind.enterOff': '已进入空闲计费时段',
|
|
401
|
+
'peakRemind.peak0912': '高峰 9:00-12:00', 'peakRemind.off1214': '空闲 12:00-14:00',
|
|
402
|
+
'peakRemind.peak1418': '高峰 14:00-18:00', 'peakRemind.off1809': '空闲 18:00-次日 9:00',
|
|
403
|
+
'peakRemind.browserOnly': '峰谷提醒仅在 App 内有效',
|
|
404
|
+
'peakRemind.on': '峰谷提醒已开启', 'peakRemind.off': '峰谷提醒已关闭',
|
|
355
405
|
'settings.toolsTitle': '显示工具调用', 'settings.toolsDesc': '关闭后隐藏 🔧/📦 工具调用与结果',
|
|
356
406
|
'settings.langTitle': '语言 / Language', 'settings.langDesc': '界面语言,跟随系统或手动切换',
|
|
357
407
|
'settings.themeTitle': '皮肤', 'settings.themeDesc': '默认深空 / 落日 / 易北爱乐厅 / 草原孤塔',
|
|
@@ -374,8 +424,15 @@
|
|
|
374
424
|
en: {
|
|
375
425
|
'a11y.hostAdmin': 'Host admin', 'a11y.refresh': 'Refresh', 'a11y.more': 'More actions', 'a11y.moreTitle': 'Commands / Permissions / Models',
|
|
376
426
|
'conn.on': 'Connected', 'conn.off': 'Offline', 'conn.reconnecting': 'Connection lost, reconnecting…',
|
|
427
|
+
'conn.titleGroup': '{group} · {url} ({ms})',
|
|
377
428
|
'common.refreshing': 'Refreshing…',
|
|
378
|
-
'nav.sessions': 'Sessions', 'nav.files': 'Files', 'nav.pending': 'Inbox', 'nav.settings': 'Settings',
|
|
429
|
+
'nav.sessions': 'Sessions', 'nav.files': 'Files', 'nav.pending': 'Inbox', 'nav.stats': 'Stats', 'nav.settings': 'Settings',
|
|
430
|
+
'statsPage.title': 'Token stats',
|
|
431
|
+
'statsPage.todayTokens': 'Tokens today', 'statsPage.todayCost': 'Cost today', 'statsPage.peakShare': 'Peak share',
|
|
432
|
+
'statsPage.input': 'Uncached input', 'statsPage.cacheRead': 'Cache read', 'statsPage.cacheWrite': 'Cache write', 'statsPage.output': 'Output',
|
|
433
|
+
'statsPage.peak': 'Peak', 'statsPage.off': 'Off-peak', 'statsPage.days': 'Last {n} days',
|
|
434
|
+
'statsPage.gatewayDown': 'Stats require the gateway', 'statsPage.empty': 'No stats yet — they aggregate as sessions happen',
|
|
435
|
+
'statsPage.note': 'Note: estimates assume the official DeepSeek API. Token-based calculation may differ from the official bill; always defer to deepseek.com. Stats start from the 2026-08-17 pricing date.',
|
|
379
436
|
'home.newSession': '+ New session', 'home.empty': 'No sessions yet', 'home.createFailed': 'Failed to create session', 'home.created': 'Session created',
|
|
380
437
|
'sessions.running': 'Running', 'sessions.statRunning': 'Running', 'sessions.statPending': 'Pending', 'sessions.statTotal': 'Sessions',
|
|
381
438
|
'sessions.queueBadge': 'Queue {n}', 'sessions.goalBadge': 'Goal·{phase}',
|
|
@@ -394,6 +451,18 @@
|
|
|
394
451
|
'servers.currentDesc': 'Current: {url}', 'servers.notSet': 'No server set', 'servers.defaultDesc': 'Default = current page URL',
|
|
395
452
|
'servers.needAddress': 'Enter a server address', 'servers.badProtocol': 'Address must start with http:// or https://',
|
|
396
453
|
'servers.duplicate': 'This address is already in the list', 'servers.added': 'Server added', 'servers.removedActive': 'Removed active server, re-testing…',
|
|
454
|
+
'servers.currentDescGroup': 'Current: {group} · {url} ({ms})',
|
|
455
|
+
'servers.edit': 'Edit', 'servers.manualSelected': 'Switched to: {url}',
|
|
456
|
+
'servers.promptNote': 'Server note (optional):', 'servers.promptEditNote': 'Edit note ({url}):',
|
|
457
|
+
'servers.promptEditUrl': 'Edit server URL:', 'servers.promptEditGroup': 'Group:', 'servers.edited': 'Server updated',
|
|
458
|
+
'speed.switchedOrigin': 'Switched to current page (same origin)', 'speed.manualUsing': 'Manual mode: {url} ({ms})',
|
|
459
|
+
'groups.current': 'Current group', 'groups.add': '+ Group', 'groups.noServer': 'No servers in this group',
|
|
460
|
+
'groups.speedTest': 'Speed test', 'groups.autoSelect': 'Auto-select fastest', 'groups.delete': 'Delete group',
|
|
461
|
+
'groups.autoOn': '{group} is now auto-select', 'groups.autoOff': '{group} is now manual',
|
|
462
|
+
'groups.switched': 'Switched to group: {group}', 'groups.switchHint': 'Click to switch group, double-click to rename', 'groups.promptAdd': 'New group name:', 'groups.duplicate': 'Group already exists',
|
|
463
|
+
'groups.added': 'Created group: {group}', 'groups.promptRename': 'Rename group "{group}":',
|
|
464
|
+
'groups.renamed': 'Group renamed', 'groups.cannotDeleteDefault': 'The default group cannot be deleted',
|
|
465
|
+
'groups.confirmDelete': 'Delete group "{group}"? Its servers move to the default group.', 'groups.deleted': 'Group deleted',
|
|
397
466
|
'stream.error': 'Event stream error: {msg}',
|
|
398
467
|
'session.loading': 'Loading…', 'session.unknown': 'Unknown session', 'session.running': 'Running', 'session.interrupted': 'Interrupted',
|
|
399
468
|
'session.stop': 'Stop', 'session.history': 'Conversation', 'session.errorMsg': 'Session error: {msg}',
|
|
@@ -469,6 +538,12 @@
|
|
|
469
538
|
'settings.servers': 'Servers (one or more)', 'settings.speedTest': 'Test', 'settings.add': 'Add',
|
|
470
539
|
'settings.scanTitle': 'Scan to pair', 'settings.scanDesc': 'Photo/gallery QR decoding on device (no Google services); system camera or manual paste also work', 'settings.scan': 'Scan',
|
|
471
540
|
'settings.notifyTitle': 'Notifications', 'settings.notifyDesc': 'Push on approvals / questions',
|
|
541
|
+
'settings.peakRemindTitle': 'Peak/off-peak reminders', 'settings.peakRemindDesc': 'Push at 9:00 / 12:00 / 14:00 / 18:00 daily (in-app only)',
|
|
542
|
+
'peakRemind.enterPeak': 'Peak pricing period started', 'peakRemind.enterOff': 'Off-peak pricing period started',
|
|
543
|
+
'peakRemind.peak0912': 'Peak 9:00-12:00', 'peakRemind.off1214': 'Off-peak 12:00-14:00',
|
|
544
|
+
'peakRemind.peak1418': 'Peak 14:00-18:00', 'peakRemind.off1809': 'Off-peak 18:00-9:00 next day',
|
|
545
|
+
'peakRemind.browserOnly': 'Peak reminders only work in the app',
|
|
546
|
+
'peakRemind.on': 'Peak reminders enabled', 'peakRemind.off': 'Peak reminders disabled',
|
|
472
547
|
'settings.toolsTitle': 'Show tool calls', 'settings.toolsDesc': 'Hide 🔧/📦 tool calls and results when off',
|
|
473
548
|
'settings.langTitle': 'Language / 语言', 'settings.langDesc': 'UI language, follows system or switch manually',
|
|
474
549
|
'settings.themeTitle': 'Theme', 'settings.themeDesc': 'Default deep space / Sunset / Elbphilharmonie / Prairie Tower',
|
package/public/styles.css
CHANGED
|
@@ -1,354 +1,8 @@
|
|
|
1
1
|
/* DSH Remote · 移动优先 · 四皮肤(默认深空/深色落日/亮色易北爱乐厅/中性草原孤塔)
|
|
2
|
-
*
|
|
3
|
-
* 红绿色弱友好原则: 状态语义色之外, 品牌色使用蓝/青 + 橙/紫系, 避免红绿配对。 */
|
|
2
|
+
* 规则样式表; 变量定义已抽取到 theme-vars.css(桌面端共享), 保持单一来源。 */
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
:root {
|
|
7
|
-
--dsr-radius: 14px;
|
|
8
|
-
--dsr-safe-top: max(env(safe-area-inset-top, 0px), var(--native-top, 0px));
|
|
9
|
-
--dsr-safe-b: max(env(safe-area-inset-bottom, 0px), var(--native-bottom, 0px));
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/* ============ 深空「默认」: 经典深蓝紫(保留原配色) ============ */
|
|
13
|
-
:root,
|
|
14
|
-
html[data-theme="default"] {
|
|
15
|
-
/* 中性灰阶 0(白) → 9(近黑) */
|
|
16
|
-
--dsr-neutral-0: #FFFFFF;
|
|
17
|
-
--dsr-neutral-1: #F4F6F9;
|
|
18
|
-
--dsr-neutral-2: #E6EAF0;
|
|
19
|
-
--dsr-neutral-3: #C9D1DC;
|
|
20
|
-
--dsr-neutral-4: #A6B0BE;
|
|
21
|
-
--dsr-neutral-5: #828D9E;
|
|
22
|
-
--dsr-neutral-6: #616C7E;
|
|
23
|
-
--dsr-neutral-7: #444E5E;
|
|
24
|
-
--dsr-neutral-8: #2B3442;
|
|
25
|
-
--dsr-neutral-9: #1A212C;
|
|
26
|
-
|
|
27
|
-
--dsr-bg: #0B0E1A;
|
|
28
|
-
--dsr-bg-2: #101528;
|
|
29
|
-
--dsr-panel: #151B33;
|
|
30
|
-
--dsr-panel-2: #1B2340;
|
|
31
|
-
--dsr-line: #263056;
|
|
32
|
-
--dsr-divider: rgba(232, 236, 255, .16);
|
|
33
|
-
--dsr-text: #E8ECFF;
|
|
34
|
-
--dsr-muted: #8B94BD;
|
|
35
|
-
--dsr-text-disabled: rgba(232, 236, 255, .45);
|
|
36
|
-
|
|
37
|
-
--dsr-accent: #5B8CFF;
|
|
38
|
-
--dsr-on-accent: #FFFFFF;
|
|
39
|
-
--dsr-accent-strong: #6FA0FF;
|
|
40
|
-
--dsr-accent-soft: #5B8CFF1F;
|
|
41
|
-
--dsr-accent-line: #5B8CFF66;
|
|
42
|
-
--dsr-accent-2: #B48CFF;
|
|
43
|
-
--dsr-accent-2-strong: #B48CFF;
|
|
44
|
-
--dsr-accent-2-soft: #B48CFF21;
|
|
45
|
-
--dsr-accent-2-line: #B48CFF66;
|
|
46
|
-
--dsr-brand-a: #5B8CFF;
|
|
47
|
-
--dsr-brand-b: #B48CFF;
|
|
48
|
-
|
|
49
|
-
--dsr-success: #4BCF7E;
|
|
50
|
-
--dsr-success-soft: #4BCF7E21;
|
|
51
|
-
--dsr-success-line: #4BCF7E66;
|
|
52
|
-
--dsr-warning: #FF9E64;
|
|
53
|
-
--dsr-warning-soft: #FF9E6421;
|
|
54
|
-
--dsr-warning-line: #FF9E6466;
|
|
55
|
-
--dsr-on-warning: #1A120B;
|
|
56
|
-
--dsr-error: #FF8F6B;
|
|
57
|
-
--dsr-error-soft: #FF8F6B24;
|
|
58
|
-
--dsr-error-line: #FF8F6B66;
|
|
59
|
-
--dsr-info: #7DCFFF;
|
|
60
|
-
--dsr-info-soft: #7DCFFF21;
|
|
61
|
-
--dsr-info-line: #7DCFFF66;
|
|
62
|
-
|
|
63
|
-
--dsr-head-bg: rgba(11, 14, 26, .94);
|
|
64
|
-
--dsr-nav-bg: rgba(16, 21, 40, .94);
|
|
65
|
-
--dsr-nav-muted: #8B94BD;
|
|
66
|
-
--dsr-nav-active: #6FA0FF;
|
|
67
|
-
--dsr-nav-badge-bg: #FF9E64;
|
|
68
|
-
--dsr-nav-badge-text: #1A120B;
|
|
69
|
-
--dsr-composer-bg: rgba(11, 14, 26, .92);
|
|
70
|
-
--dsr-overlay: rgba(5, 7, 14, .66);
|
|
71
|
-
--dsr-code-bg: rgba(0, 0, 0, .28);
|
|
72
|
-
--dsr-shadow: rgba(0, 0, 0, .4);
|
|
73
|
-
--dsr-glow: rgba(91, 140, 255, .8);
|
|
74
|
-
--dsr-head-running-bg: linear-gradient(90deg, rgba(11, 14, 26, .94), rgba(35, 65, 150, .92), rgba(125, 207, 255, .6), rgba(35, 65, 150, .92), rgba(11, 14, 26, .94));
|
|
75
|
-
--dsr-head-running-line: rgba(91, 140, 255, .55);
|
|
76
|
-
--dsr-head-interrupted-bg: linear-gradient(90deg, rgba(11, 14, 26, .94), rgba(90, 26, 12, .92), rgba(255, 158, 100, .55), rgba(90, 26, 12, .92), rgba(11, 14, 26, .94));
|
|
77
|
-
--dsr-head-interrupted-line: rgba(255, 158, 100, .55);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/* ============ 深色「落日」: 深钴蓝底 + 琥珀橙强调 ============ */
|
|
81
|
-
html[data-theme="dark"] {
|
|
82
|
-
/* 中性灰阶 0(白) → 9(近黑) */
|
|
83
|
-
--dsr-neutral-0: #FFFFFF;
|
|
84
|
-
--dsr-neutral-1: #F4F6F9;
|
|
85
|
-
--dsr-neutral-2: #E6EAF0;
|
|
86
|
-
--dsr-neutral-3: #C9D1DC;
|
|
87
|
-
--dsr-neutral-4: #A6B0BE;
|
|
88
|
-
--dsr-neutral-5: #828D9E;
|
|
89
|
-
--dsr-neutral-6: #616C7E;
|
|
90
|
-
--dsr-neutral-7: #444E5E;
|
|
91
|
-
--dsr-neutral-8: #2B3442;
|
|
92
|
-
--dsr-neutral-9: #1A212C;
|
|
93
|
-
|
|
94
|
-
/* 表面与文字 */
|
|
95
|
-
--dsr-bg: #05348B;
|
|
96
|
-
--dsr-bg-2: #0B3E86;
|
|
97
|
-
--dsr-panel: #0D438F;
|
|
98
|
-
--dsr-panel-2: #164E9E;
|
|
99
|
-
--dsr-line: #2E5A8C;
|
|
100
|
-
--dsr-divider: rgba(255, 255, 255, .16);
|
|
101
|
-
--dsr-text: #FFFFFF;
|
|
102
|
-
--dsr-muted: rgba(255, 255, 255, .85);
|
|
103
|
-
--dsr-text-disabled: rgba(255, 255, 255, .48);
|
|
104
|
-
|
|
105
|
-
/* 品牌强调(琥珀橙)与点缀(米色) */
|
|
106
|
-
--dsr-accent: #F9A647;
|
|
107
|
-
--dsr-on-accent: #1A120B;
|
|
108
|
-
--dsr-accent-strong: #F9A647;
|
|
109
|
-
--dsr-accent-soft: #F9A64721;
|
|
110
|
-
--dsr-accent-line: #F9A64766;
|
|
111
|
-
--dsr-accent-2: #EDCFAB;
|
|
112
|
-
--dsr-accent-2-strong: #EDCFAB;
|
|
113
|
-
--dsr-accent-2-soft: #EDCFAB21;
|
|
114
|
-
--dsr-accent-2-line: #EDCFAB66;
|
|
115
|
-
--dsr-brand-a: #F9A647;
|
|
116
|
-
--dsr-brand-b: #EDCFAB;
|
|
117
|
-
|
|
118
|
-
/* 状态色(WCAG 对比度按深钴蓝底校准) */
|
|
119
|
-
--dsr-success: #7EE2A8;
|
|
120
|
-
--dsr-success-soft: #7EE2A821;
|
|
121
|
-
--dsr-success-line: #7EE2A866;
|
|
122
|
-
--dsr-warning: #F9A647;
|
|
123
|
-
--dsr-warning-soft: #F9A64721;
|
|
124
|
-
--dsr-warning-line: #F9A64766;
|
|
125
|
-
--dsr-on-warning: #1A120B;
|
|
126
|
-
--dsr-error: #FFB4A6;
|
|
127
|
-
--dsr-error-soft: #FFB4A624;
|
|
128
|
-
--dsr-error-line: #FFB4A666;
|
|
129
|
-
--dsr-info: #7DCFFF;
|
|
130
|
-
--dsr-info-soft: #7DCFFF21;
|
|
131
|
-
--dsr-info-line: #7DCFFF66;
|
|
132
|
-
|
|
133
|
-
/* 悬浮/遮罩/特殊表面 */
|
|
134
|
-
--dsr-head-bg: rgba(4, 32, 90, .94);
|
|
135
|
-
--dsr-nav-bg: rgba(7, 38, 104, .94);
|
|
136
|
-
--dsr-nav-muted: rgba(255, 255, 255, .85);
|
|
137
|
-
--dsr-nav-active: #F9A647;
|
|
138
|
-
--dsr-nav-badge-bg: #F9A647;
|
|
139
|
-
--dsr-nav-badge-text: #1A120B;
|
|
140
|
-
--dsr-composer-bg: rgba(5, 42, 110, .92);
|
|
141
|
-
--dsr-overlay: rgba(2, 10, 32, .66);
|
|
142
|
-
--dsr-code-bg: rgba(0, 0, 0, .28);
|
|
143
|
-
--dsr-shadow: rgba(0, 0, 0, .4);
|
|
144
|
-
--dsr-glow: rgba(249, 166, 71, .55);
|
|
145
|
-
--dsr-head-running-bg: linear-gradient(90deg, rgba(4, 32, 90, .94), rgba(30, 77, 123, .92), rgba(125, 207, 255, .55), rgba(30, 77, 123, .92), rgba(4, 32, 90, .94));
|
|
146
|
-
--dsr-head-running-line: rgba(249, 166, 71, .55);
|
|
147
|
-
--dsr-head-interrupted-bg: linear-gradient(90deg, rgba(4, 32, 90, .94), rgba(90, 26, 12, .92), rgba(255, 180, 166, .55), rgba(90, 26, 12, .92), rgba(4, 32, 90, .94));
|
|
148
|
-
--dsr-head-interrupted-line: rgba(255, 180, 166, .55);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/* ============ 亮色「易北爱乐厅」: 米白底 + 沙金强调 ============ */
|
|
152
|
-
html[data-theme="light"] {
|
|
153
|
-
--dsr-neutral-0: #FFFFFF;
|
|
154
|
-
--dsr-neutral-1: #FAF9F7;
|
|
155
|
-
--dsr-neutral-2: #F3F1ED;
|
|
156
|
-
--dsr-neutral-3: #E8E5DF;
|
|
157
|
-
--dsr-neutral-4: #D8D4CC;
|
|
158
|
-
--dsr-neutral-5: #B8B3A9;
|
|
159
|
-
--dsr-neutral-6: #8A857C;
|
|
160
|
-
--dsr-neutral-7: #615D56;
|
|
161
|
-
--dsr-neutral-8: #3F3C37;
|
|
162
|
-
--dsr-neutral-9: #2B2B2B;
|
|
163
|
-
|
|
164
|
-
--dsr-bg: #EFEEEC;
|
|
165
|
-
--dsr-bg-2: #E5E1D9;
|
|
166
|
-
--dsr-panel: #FAF8F5;
|
|
167
|
-
--dsr-panel-2: #FFFFFF;
|
|
168
|
-
--dsr-line: #D8D2C6;
|
|
169
|
-
--dsr-divider: rgba(43, 43, 43, .12);
|
|
170
|
-
--dsr-text: #2B2B2B;
|
|
171
|
-
--dsr-muted: #6E6A63;
|
|
172
|
-
--dsr-text-disabled: #A8A39A;
|
|
173
|
-
|
|
174
|
-
/* 沙金(填充/按钮) + 深沙金(小字号文字) + 浅桃粉(点缀) */
|
|
175
|
-
--dsr-accent: #E6BC7B;
|
|
176
|
-
--dsr-on-accent: #2B2B2B;
|
|
177
|
-
--dsr-accent-strong: #7A5A24;
|
|
178
|
-
--dsr-accent-soft: #E6BC7B40;
|
|
179
|
-
--dsr-accent-line: #C89A4E66;
|
|
180
|
-
--dsr-accent-2: #6E5A8C;
|
|
181
|
-
--dsr-accent-2-strong: #6E5A8C;
|
|
182
|
-
--dsr-accent-2-soft: #6E5A8C1F;
|
|
183
|
-
--dsr-accent-2-line: #6E5A8C59;
|
|
184
|
-
--dsr-brand-a: #E6BC7B;
|
|
185
|
-
--dsr-brand-b: #EDD4C2;
|
|
4
|
+
@import 'theme-vars.css';
|
|
186
5
|
|
|
187
|
-
--dsr-success: #237A46;
|
|
188
|
-
--dsr-success-soft: #237A461A;
|
|
189
|
-
--dsr-success-line: #237A4659;
|
|
190
|
-
--dsr-warning: #965A0B;
|
|
191
|
-
--dsr-warning-soft: #B96A0E1F;
|
|
192
|
-
--dsr-warning-line: #B96A0E59;
|
|
193
|
-
--dsr-on-warning: #FFFFFF;
|
|
194
|
-
--dsr-error: #B7423F;
|
|
195
|
-
--dsr-error-soft: #B7423F1F;
|
|
196
|
-
--dsr-error-line: #B7423F59;
|
|
197
|
-
--dsr-info: #2563C0;
|
|
198
|
-
--dsr-info-soft: #2563C01A;
|
|
199
|
-
--dsr-info-line: #2563C059;
|
|
200
|
-
|
|
201
|
-
--dsr-head-bg: rgba(239, 238, 236, .94);
|
|
202
|
-
--dsr-nav-bg: rgba(250, 248, 245, .94);
|
|
203
|
-
--dsr-nav-muted: #6E6A63;
|
|
204
|
-
--dsr-nav-active: #7A5A24;
|
|
205
|
-
--dsr-nav-badge-bg: #965A0B;
|
|
206
|
-
--dsr-nav-badge-text: #FFFFFF;
|
|
207
|
-
--dsr-composer-bg: rgba(250, 248, 245, .92);
|
|
208
|
-
--dsr-overlay: rgba(43, 43, 43, .4);
|
|
209
|
-
--dsr-code-bg: rgba(0, 0, 0, .06);
|
|
210
|
-
--dsr-shadow: rgba(43, 43, 43, .18);
|
|
211
|
-
--dsr-glow: rgba(198, 154, 78, .45);
|
|
212
|
-
--dsr-head-running-bg: linear-gradient(90deg, rgba(239, 238, 236, .94), rgba(230, 188, 123, .45), rgba(255, 255, 255, .65), rgba(230, 188, 123, .45), rgba(239, 238, 236, .94));
|
|
213
|
-
--dsr-head-running-line: rgba(122, 90, 36, .55);
|
|
214
|
-
--dsr-head-interrupted-bg: linear-gradient(90deg, rgba(239, 238, 236, .94), rgba(183, 66, 63, .18), rgba(255, 255, 255, .65), rgba(183, 66, 63, .18), rgba(239, 238, 236, .94));
|
|
215
|
-
--dsr-head-interrupted-line: rgba(183, 66, 63, .55);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/* ============ 中性「草原孤塔」: 鼠尾草底 + 橄榄绿块 + 陶土红点缀(莫兰迪自然系) ============ */
|
|
219
|
-
html[data-theme="neutral"] {
|
|
220
|
-
--dsr-neutral-0: #FFFFFF;
|
|
221
|
-
--dsr-neutral-1: #FAF7EE;
|
|
222
|
-
--dsr-neutral-2: #F1EDDF;
|
|
223
|
-
--dsr-neutral-3: #E6DFC8;
|
|
224
|
-
--dsr-neutral-4: #D5CDB4;
|
|
225
|
-
--dsr-neutral-5: #B8AF91;
|
|
226
|
-
--dsr-neutral-6: #8E866D;
|
|
227
|
-
--dsr-neutral-7: #6B6450;
|
|
228
|
-
--dsr-neutral-8: #454133;
|
|
229
|
-
--dsr-neutral-9: #2B2B2B;
|
|
230
|
-
|
|
231
|
-
--dsr-bg: #DDD4B8;
|
|
232
|
-
--dsr-bg-2: #D2C9AC;
|
|
233
|
-
--dsr-panel: #E6DFC8;
|
|
234
|
-
--dsr-panel-2: #F1EDDF;
|
|
235
|
-
--dsr-line: #B8AF91;
|
|
236
|
-
--dsr-divider: rgba(43, 43, 43, .14);
|
|
237
|
-
--dsr-text: #2B2B2B;
|
|
238
|
-
--dsr-muted: #5E5A45;
|
|
239
|
-
--dsr-text-disabled: #9A937C;
|
|
240
|
-
|
|
241
|
-
/* 橄榄军绿 = 主色(按钮/开关/底部导航块); 陶土砖红 = 强调(徽标/图标/链接) */
|
|
242
|
-
--dsr-accent: #585818;
|
|
243
|
-
--dsr-on-accent: #F5F1E3;
|
|
244
|
-
--dsr-accent-strong: #585818;
|
|
245
|
-
--dsr-accent-soft: #5858181F;
|
|
246
|
-
--dsr-accent-line: #58581866;
|
|
247
|
-
--dsr-accent-2: #832D15;
|
|
248
|
-
--dsr-accent-2-strong: #832D15;
|
|
249
|
-
--dsr-accent-2-soft: #832D151F;
|
|
250
|
-
--dsr-accent-2-line: #832D1566;
|
|
251
|
-
--dsr-brand-a: #585818;
|
|
252
|
-
--dsr-brand-b: #832D15;
|
|
253
|
-
|
|
254
|
-
--dsr-success: #1E5C33;
|
|
255
|
-
--dsr-success-soft: #1E5C331F;
|
|
256
|
-
--dsr-success-line: #1E5C3366;
|
|
257
|
-
--dsr-warning: #8A4B0C;
|
|
258
|
-
--dsr-warning-soft: #8A4B0C1F;
|
|
259
|
-
--dsr-warning-line: #8A4B0C66;
|
|
260
|
-
--dsr-on-warning: #FFFFFF;
|
|
261
|
-
--dsr-error: #8A2A1F;
|
|
262
|
-
--dsr-error-soft: #8A2A1F1F;
|
|
263
|
-
--dsr-error-line: #8A2A1F66;
|
|
264
|
-
--dsr-info: #1F4E7A;
|
|
265
|
-
--dsr-info-soft: #1F4E7A1F;
|
|
266
|
-
--dsr-info-line: #1F4E7A66;
|
|
267
|
-
|
|
268
|
-
--dsr-head-bg: rgba(221, 212, 184, .94);
|
|
269
|
-
--dsr-nav-bg: #585818;
|
|
270
|
-
--dsr-nav-muted: rgba(245, 241, 227, .8);
|
|
271
|
-
--dsr-nav-active: #F5F1E3;
|
|
272
|
-
--dsr-nav-badge-bg: #832D15;
|
|
273
|
-
--dsr-nav-badge-text: #F5F1E3;
|
|
274
|
-
--dsr-composer-bg: rgba(230, 223, 200, .92);
|
|
275
|
-
--dsr-overlay: rgba(43, 43, 43, .4);
|
|
276
|
-
--dsr-code-bg: rgba(0, 0, 0, .07);
|
|
277
|
-
--dsr-shadow: rgba(43, 43, 43, .2);
|
|
278
|
-
--dsr-glow: rgba(88, 88, 24, .5);
|
|
279
|
-
--dsr-head-running-bg: linear-gradient(90deg, rgba(221, 212, 184, .94), rgba(88, 88, 24, .30), rgba(245, 241, 227, .65), rgba(88, 88, 24, .30), rgba(221, 212, 184, .94));
|
|
280
|
-
--dsr-head-running-line: rgba(88, 88, 24, .55);
|
|
281
|
-
--dsr-head-interrupted-bg: linear-gradient(90deg, rgba(221, 212, 184, .94), rgba(131, 45, 21, .20), rgba(245, 241, 227, .65), rgba(131, 45, 21, .20), rgba(221, 212, 184, .94));
|
|
282
|
-
--dsr-head-interrupted-line: rgba(131, 45, 21, .55);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/* 无 JS 或 JS 前: 跟随系统深浅偏好 */
|
|
286
|
-
@media (prefers-color-scheme: light) {
|
|
287
|
-
:root:not([data-theme]) {
|
|
288
|
-
--dsr-neutral-0: #FFFFFF;
|
|
289
|
-
--dsr-neutral-1: #FAF9F7;
|
|
290
|
-
--dsr-neutral-2: #F3F1ED;
|
|
291
|
-
--dsr-neutral-3: #E8E5DF;
|
|
292
|
-
--dsr-neutral-4: #D8D4CC;
|
|
293
|
-
--dsr-neutral-5: #B8B3A9;
|
|
294
|
-
--dsr-neutral-6: #8A857C;
|
|
295
|
-
--dsr-neutral-7: #615D56;
|
|
296
|
-
--dsr-neutral-8: #3F3C37;
|
|
297
|
-
--dsr-neutral-9: #2B2B2B;
|
|
298
|
-
|
|
299
|
-
--dsr-bg: #EFEEEC;
|
|
300
|
-
--dsr-bg-2: #E5E1D9;
|
|
301
|
-
--dsr-panel: #FAF8F5;
|
|
302
|
-
--dsr-panel-2: #FFFFFF;
|
|
303
|
-
--dsr-line: #D8D2C6;
|
|
304
|
-
--dsr-divider: rgba(43, 43, 43, .12);
|
|
305
|
-
--dsr-text: #2B2B2B;
|
|
306
|
-
--dsr-muted: #6E6A63;
|
|
307
|
-
--dsr-text-disabled: #A8A39A;
|
|
308
|
-
|
|
309
|
-
--dsr-accent: #E6BC7B;
|
|
310
|
-
--dsr-on-accent: #2B2B2B;
|
|
311
|
-
--dsr-accent-strong: #7A5A24;
|
|
312
|
-
--dsr-accent-soft: #E6BC7B40;
|
|
313
|
-
--dsr-accent-line: #C89A4E66;
|
|
314
|
-
--dsr-accent-2: #6E5A8C;
|
|
315
|
-
--dsr-accent-2-strong: #6E5A8C;
|
|
316
|
-
--dsr-accent-2-soft: #6E5A8C1F;
|
|
317
|
-
--dsr-accent-2-line: #6E5A8C59;
|
|
318
|
-
--dsr-brand-a: #E6BC7B;
|
|
319
|
-
--dsr-brand-b: #EDD4C2;
|
|
320
|
-
|
|
321
|
-
--dsr-success: #237A46;
|
|
322
|
-
--dsr-success-soft: #237A461A;
|
|
323
|
-
--dsr-success-line: #237A4659;
|
|
324
|
-
--dsr-warning: #965A0B;
|
|
325
|
-
--dsr-warning-soft: #B96A0E1F;
|
|
326
|
-
--dsr-warning-line: #B96A0E59;
|
|
327
|
-
--dsr-on-warning: #FFFFFF;
|
|
328
|
-
--dsr-error: #B7423F;
|
|
329
|
-
--dsr-error-soft: #B7423F1F;
|
|
330
|
-
--dsr-error-line: #B7423F59;
|
|
331
|
-
--dsr-info: #2563C0;
|
|
332
|
-
--dsr-info-soft: #2563C01A;
|
|
333
|
-
--dsr-info-line: #2563C059;
|
|
334
|
-
|
|
335
|
-
--dsr-head-bg: rgba(239, 238, 236, .94);
|
|
336
|
-
--dsr-nav-bg: rgba(250, 248, 245, .94);
|
|
337
|
-
--dsr-nav-muted: #6E6A63;
|
|
338
|
-
--dsr-nav-active: #7A5A24;
|
|
339
|
-
--dsr-nav-badge-bg: #965A0B;
|
|
340
|
-
--dsr-nav-badge-text: #FFFFFF;
|
|
341
|
-
--dsr-composer-bg: rgba(250, 248, 245, .92);
|
|
342
|
-
--dsr-overlay: rgba(43, 43, 43, .4);
|
|
343
|
-
--dsr-code-bg: rgba(0, 0, 0, .06);
|
|
344
|
-
--dsr-shadow: rgba(43, 43, 43, .18);
|
|
345
|
-
--dsr-glow: rgba(198, 154, 78, .45);
|
|
346
|
-
--dsr-head-running-bg: linear-gradient(90deg, rgba(239, 238, 236, .94), rgba(230, 188, 123, .45), rgba(255, 255, 255, .65), rgba(230, 188, 123, .45), rgba(239, 238, 236, .94));
|
|
347
|
-
--dsr-head-running-line: rgba(122, 90, 36, .55);
|
|
348
|
-
--dsr-head-interrupted-bg: linear-gradient(90deg, rgba(239, 238, 236, .94), rgba(183, 66, 63, .18), rgba(255, 255, 255, .65), rgba(183, 66, 63, .18), rgba(239, 238, 236, .94));
|
|
349
|
-
--dsr-head-interrupted-line: rgba(183, 66, 63, .55);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
6
|
|
|
353
7
|
/* ============ 基础 ============ */
|
|
354
8
|
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
|
|
@@ -450,6 +104,32 @@ button {
|
|
|
450
104
|
}
|
|
451
105
|
.section-head.small { margin-top: 6px; }
|
|
452
106
|
|
|
107
|
+
/* ---------- Token 统计(移动端) ---------- */
|
|
108
|
+
.stats-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
|
109
|
+
.scard { background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: var(--dsr-radius); padding: 10px 11px; min-width: 0; }
|
|
110
|
+
.scard.span2 { grid-column: span 2; }
|
|
111
|
+
.scard .v { font-size: 17px; font-weight: 700; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
112
|
+
.scard .k { font-size: 10px; color: var(--dsr-muted); margin-top: 2px; line-height: 1.4; }
|
|
113
|
+
.bucket-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3px 10px; margin-top: 6px; }
|
|
114
|
+
.bucket-grid .b { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; font-size: 10.5px; min-width: 0; }
|
|
115
|
+
.bucket-grid .b .n { color: var(--dsr-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
116
|
+
.bucket-grid .b .t { font-weight: 600; white-space: nowrap; }
|
|
117
|
+
.stats-chart { display: flex; align-items: flex-end; gap: 7px; height: 190px; padding: 12px 12px 10px; margin-top: 10px; background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: var(--dsr-radius); overflow-x: auto; overflow-y: hidden; }
|
|
118
|
+
.stats-legend { display: flex; gap: 12px; font-size: 10px; color: var(--dsr-muted); margin-top: 6px; }
|
|
119
|
+
.stats-legend .lg { display: inline-flex; align-items: center; gap: 4px; }
|
|
120
|
+
.stats-legend .sw { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
|
|
121
|
+
.stats-legend .sw.peak { background: var(--dsr-accent-strong); }
|
|
122
|
+
.stats-legend .sw.off { background: var(--dsr-accent-2); }
|
|
123
|
+
.stats-bar { flex: 1; min-width: 36px; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; }
|
|
124
|
+
.stats-bar .bars { width: 100%; max-width: 42px; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; border-radius: 6px 6px 0 0; overflow: hidden; background: var(--dsr-accent-soft); }
|
|
125
|
+
.stats-bar .seg { width: 100%; }
|
|
126
|
+
.stats-bar .seg.peak { background: var(--dsr-accent-strong); }
|
|
127
|
+
.stats-bar .seg.off { background: var(--dsr-accent-2); }
|
|
128
|
+
.stats-bar .lbl { font-size: 9px; color: var(--dsr-muted); white-space: nowrap; }
|
|
129
|
+
.stats-bar .val { font-size: 9px; color: var(--dsr-text); white-space: nowrap; }
|
|
130
|
+
.stats-note { font-size: 11px; color: var(--dsr-muted); line-height: 1.6; margin-top: 8px; }
|
|
131
|
+
.stats-empty { color: var(--dsr-muted); text-align: center; padding: 18px 0; font-size: 12px; }
|
|
132
|
+
|
|
453
133
|
/* ---------- 会话列表 ---------- */
|
|
454
134
|
.session-list { display: flex; flex-direction: column; gap: 8px; }
|
|
455
135
|
.session-card {
|
|
@@ -755,16 +435,38 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
755
435
|
.setting-desc.expanded { white-space: normal; overflow: visible; text-overflow: clip; word-break: break-word; }
|
|
756
436
|
.about { text-align: center; color: var(--dsr-muted); font-size: 12px; margin-top: 16px; line-height: 1.8; }
|
|
757
437
|
|
|
758
|
-
/* 多服务器列表 */
|
|
438
|
+
/* 多服务器列表(分组) */
|
|
439
|
+
.group-bar { display: flex; align-items: center; gap: 8px; padding: 0 14px 10px; }
|
|
440
|
+
.group-bar-label { font-size: 12px; color: var(--dsr-muted); white-space: nowrap; }
|
|
441
|
+
.group-select { flex: 1; min-width: 0; position: relative; }
|
|
442
|
+
.group-select-btn { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 6px; background: var(--dsr-bg-2); color: var(--dsr-text); border: 1px solid var(--dsr-line); border-radius: 10px; padding: 7px 9px; font: inherit; font-size: 13px; outline: none; cursor: pointer; }
|
|
443
|
+
.group-select-btn .caret { color: var(--dsr-muted); font-size: 10px; transition: transform .15s ease; }
|
|
444
|
+
.group-select-menu { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 30; max-height: 220px; overflow-y: auto; background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.28); padding: 4px; display: flex; flex-direction: column; gap: 2px; }
|
|
445
|
+
.group-option { width: 100%; text-align: left; background: none; border: none; color: var(--dsr-text); font: inherit; font-size: 13px; padding: 8px 10px; border-radius: 8px; }
|
|
446
|
+
.group-option.current { background: var(--dsr-accent-soft); color: var(--dsr-accent-strong); font-weight: 600; }
|
|
447
|
+
.group-option:active { background: var(--dsr-panel-2); }
|
|
759
448
|
.server-list { padding: 0 14px 10px; display: flex; flex-direction: column; gap: 6px; }
|
|
760
449
|
.server-empty { font-size: 12px; color: var(--dsr-muted); }
|
|
450
|
+
.srv-group { border: 1px solid var(--dsr-line); border-radius: 12px; background: var(--dsr-panel); overflow: hidden; }
|
|
451
|
+
.srv-group-head { display: flex; align-items: center; gap: 6px; padding: 7px 9px; }
|
|
452
|
+
.srv-group-name { flex: 1; min-width: 0; text-align: left; background: none; border: none; color: var(--dsr-text); font: inherit; font-size: 13px; font-weight: 600; padding: 2px 0; display: flex; align-items: center; gap: 6px; }
|
|
453
|
+
.srv-group-count { font-size: 10.5px; color: var(--dsr-muted); background: var(--dsr-bg-2); border-radius: 999px; padding: 0 7px; line-height: 16px; }
|
|
454
|
+
.srv-group-speed { flex-shrink: 0; padding: 3px 8px; font-size: 12px; }
|
|
455
|
+
.srv-group-del { flex-shrink: 0; width: 22px; height: 22px; border-radius: 7px; background: var(--dsr-panel); border: 1px solid var(--dsr-line); color: var(--dsr-muted); font-size: 11px; }
|
|
456
|
+
.srv-group-del:active { color: var(--dsr-error); }
|
|
457
|
+
.srv-group-body { display: flex; flex-direction: column; gap: 6px; padding: 0 9px 9px; }
|
|
458
|
+
.switch.small { width: 36px; height: 21px; }
|
|
459
|
+
.switch.small .slider::before { width: 15px; height: 15px; left: 2px; top: 2px; }
|
|
460
|
+
.switch.small input:checked + .slider::before { transform: translateX(15px); }
|
|
761
461
|
.server-row {
|
|
762
462
|
display: flex; align-items: center; gap: 8px;
|
|
763
463
|
background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-radius: 10px;
|
|
764
464
|
padding: 8px 10px;
|
|
765
465
|
}
|
|
766
466
|
.server-row.active { border-color: var(--dsr-info-line); background: var(--dsr-info-soft); }
|
|
767
|
-
.server-
|
|
467
|
+
.server-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
468
|
+
.server-note { font-size: 13px; word-break: break-all; }
|
|
469
|
+
.server-url { flex: 1; min-width: 0; font-size: 11.5px; color: var(--dsr-muted); word-break: break-all; }
|
|
768
470
|
.server-badge {
|
|
769
471
|
flex-shrink: 0; font-size: 11px; padding: 1px 7px; border-radius: 999px;
|
|
770
472
|
background: var(--dsr-accent-soft); color: var(--dsr-accent-strong);
|
|
@@ -772,10 +474,11 @@ body.in-session .main { padding-bottom: 84px; }
|
|
|
772
474
|
}
|
|
773
475
|
.server-badge.good { background: var(--dsr-success-soft); color: var(--dsr-success); border-color: var(--dsr-success-line); }
|
|
774
476
|
.server-badge.bad { background: var(--dsr-warning-soft); color: var(--dsr-warning); border-color: var(--dsr-warning-line); }
|
|
775
|
-
.server-del {
|
|
477
|
+
.server-edit, .server-del {
|
|
776
478
|
flex-shrink: 0; width: 24px; height: 24px; border-radius: 7px;
|
|
777
479
|
background: var(--dsr-panel); border: 1px solid var(--dsr-line); color: var(--dsr-muted); font-size: 12px;
|
|
778
480
|
}
|
|
481
|
+
.server-edit:active { color: var(--dsr-accent-strong); }
|
|
779
482
|
.server-del:active { color: var(--dsr-error); }
|
|
780
483
|
.server-add { display: flex; gap: 8px; padding: 0 14px 13px; }
|
|
781
484
|
.server-add input {
|