dsh-remote-plugin 0.6.16 → 0.6.18
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/apk/dsh-remote.apk +0 -0
- package/gateway-stats.cjs +3 -2
- package/gateway.cjs +87 -8
- package/index.mjs +21 -3
- package/package.json +1 -1
- package/public/admin.html +11 -6
- package/public/admin.js +88 -14
- package/public/app.js +430 -86
- package/public/desktop/desktop.css +5 -0
- package/public/desktop/desktop.html +20 -15
- package/public/desktop/desktop.js +281 -52
- package/public/index.html +58 -19
- package/public/styles.css +87 -19
- package/public/update.json +12 -12
- package/public/version.json +1 -1
package/public/index.html
CHANGED
|
@@ -229,12 +229,47 @@
|
|
|
229
229
|
</section>
|
|
230
230
|
|
|
231
231
|
<!-- Token 统计 -->
|
|
232
|
-
<section id="view-stats" class="view hidden">
|
|
233
|
-
<
|
|
232
|
+
<section id="view-stats" class="view hidden stats-view" aria-labelledby="stats-page-title">
|
|
233
|
+
<header class="stats-page-head">
|
|
234
|
+
<div class="stats-page-copy">
|
|
235
|
+
<div class="stats-eyebrow" data-i18n="statsPage.eyebrow">USAGE OVERVIEW</div>
|
|
236
|
+
<h1 id="stats-page-title" data-i18n="statsPage.title">Token 统计</h1>
|
|
237
|
+
<p class="stats-page-subtitle" data-i18n="statsPage.subtitle">按日查看 Token 用量与费用估算</p>
|
|
238
|
+
</div>
|
|
239
|
+
<div class="stats-date-wrap">
|
|
240
|
+
<span class="stats-date-label" data-i18n="statsPage.latest">最新日期</span>
|
|
241
|
+
<span id="stats-sub" class="stats-date">—</span>
|
|
242
|
+
</div>
|
|
243
|
+
</header>
|
|
244
|
+
<div class="stats-toolbar">
|
|
245
|
+
<span class="stats-toolbar-label" data-i18n="statsPage.chartMetric">图表指标</span>
|
|
246
|
+
<div id="stats-mode-picker" class="stats-mode-picker" role="group" data-i18n-aria="statsPage.chartMetric">
|
|
247
|
+
<button type="button" class="stats-mode-btn active" data-stats-mode="token" aria-pressed="true" data-i18n="statsPage.modeTokens">Token 数</button>
|
|
248
|
+
<button type="button" class="stats-mode-btn" data-stats-mode="cost" aria-pressed="false" data-i18n="statsPage.modeCost">费用(官方)</button>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
234
251
|
<div class="stats-cards" id="stats-cards"></div>
|
|
235
|
-
<
|
|
236
|
-
|
|
237
|
-
|
|
252
|
+
<section class="stats-panel" data-stats-panel="cost" aria-labelledby="stats-cost-title">
|
|
253
|
+
<div class="stats-panel-head">
|
|
254
|
+
<div>
|
|
255
|
+
<div class="stats-panel-kicker" data-i18n="statsPage.costKicker">ESTIMATED COST</div>
|
|
256
|
+
<h2 id="stats-cost-title" class="stats-panel-title" data-i18n="statsPage.costTrend">费用趋势</h2>
|
|
257
|
+
</div>
|
|
258
|
+
<div id="stats-legend" class="stats-legend"></div>
|
|
259
|
+
</div>
|
|
260
|
+
<div id="stats-chart" class="stats-chart" role="list" aria-live="polite" data-i18n-aria="statsPage.costChartLabel"></div>
|
|
261
|
+
</section>
|
|
262
|
+
<section class="stats-panel" data-stats-panel="token" aria-labelledby="stats-token-title">
|
|
263
|
+
<div class="stats-panel-head">
|
|
264
|
+
<div>
|
|
265
|
+
<div class="stats-panel-kicker" data-i18n="statsPage.tokenKicker">TOKEN VOLUME</div>
|
|
266
|
+
<h2 id="stats-token-title" class="stats-panel-title" data-i18n="statsPage.tokenTrend">Token 量趋势</h2>
|
|
267
|
+
</div>
|
|
268
|
+
<div id="stats-token-legend" class="stats-legend"></div>
|
|
269
|
+
</div>
|
|
270
|
+
<div id="stats-token-chart" class="stats-chart" role="list" aria-live="polite" data-i18n-aria="statsPage.tokenChartLabel"></div>
|
|
271
|
+
</section>
|
|
272
|
+
<p id="stats-note" class="stats-note"></p>
|
|
238
273
|
</section>
|
|
239
274
|
|
|
240
275
|
<!-- 设置 -->
|
|
@@ -877,12 +912,14 @@
|
|
|
877
912
|
'overview.action.openSession': '打开最近会话', 'overview.action.newSession': '新建会话', 'overview.action.attention': '处理待办', 'overview.action.connect': '去设置连接', 'overview.action.refresh': '重新检查连接',
|
|
878
913
|
'overview.communityEyebrow': 'COMMUNITY BOARD', 'overview.communityTitle': '公告与投票', 'overview.communityHistory': '历史公告', 'overview.communityEmpty': '暂无未读公告',
|
|
879
914
|
'overview.communityPoll': '投票', 'overview.communityNotice': '公告', 'overview.communityNew': '新', 'overview.communityVote': '参与投票', 'overview.communityView': '查看公告', 'overview.communityVoted': '已参与',
|
|
880
|
-
'statsPage.title': 'Token 统计',
|
|
881
|
-
'statsPage.
|
|
915
|
+
'statsPage.eyebrow': '使用概览', 'statsPage.title': 'Token 统计', 'statsPage.subtitle': '按日查看 Token 用量与费用估算', 'statsPage.latest': '最新日期', 'statsPage.chartMetric': '图表指标', 'statsPage.modeTokens': 'Token 数', 'statsPage.modeCost': '费用(官方)',
|
|
916
|
+
'statsPage.costKicker': 'ESTIMATED COST', 'statsPage.tokenKicker': 'TOKEN VOLUME', 'statsPage.costChartLabel': '近 7 天费用趋势', 'statsPage.tokenChartLabel': '近 7 天 Token 用量趋势',
|
|
917
|
+
'statsPage.today': '今日', 'statsPage.tokenUnit': 'Tokens', 'statsPage.breakdown': '今日用量构成', 'statsPage.estimated': '估算费用', 'statsPage.peakShareLabel': '高峰费用占比 {n}%',
|
|
918
|
+
'statsPage.todayTokens': '今日 Token', 'statsPage.todayCost': '今日费用', 'statsPage.peakShare': '高峰占比', 'statsPage.costTrend': '费用趋势', 'statsPage.tokenTrend': 'Token 量趋势', 'statsPage.tokenTotal': 'Token 总量',
|
|
882
919
|
'statsPage.input': '未缓存输入', 'statsPage.cacheRead': '缓存命中', 'statsPage.cacheWrite': '缓存写入', 'statsPage.output': '输出',
|
|
883
920
|
'statsPage.peak': '高峰', 'statsPage.off': '空闲', 'statsPage.days': '近 {n} 天',
|
|
884
921
|
'statsPage.gatewayDown': '统计需要网关运行', 'statsPage.empty': '暂无统计,产生会话后自动聚合',
|
|
885
|
-
'statsPage.note': '
|
|
922
|
+
'statsPage.note': '注:Token 量按 DSH usage 事件记录,第三方 provider 需提供 usage 才能计入;费用仅对已知 DeepSeek 模型估算,与官网账单可能有出入,一切以官网为准。统计自 2026-08-17 定价生效日起。',
|
|
886
923
|
'home.newSession': '+ 新会话', 'home.newWorkspace': '+ 工作区', 'home.empty': '暂无会话', 'home.createFailed': '新建会话失败', 'home.created': '会话已创建',
|
|
887
924
|
'wb.unbound': '未绑定工作台', 'wb.bound': '绑定 {title}', 'wb.noProjects': '暂无项目', 'wb.noSessions': '暂无会话', 'wb.newSession': '新会话', 'wb.orderSaved': '顺序已保存到当前设备', 'wb.flatHidden': '工作台会话已收起({n} 个)', 'wb.archivedHidden': '------隐藏已归档会话------', 'wb.archivedShown': '------显示已归档会话------',
|
|
888
925
|
'workspace.createTitle': '新建工作区', 'workspace.createDesc': '将在当前文件目录下创建文件夹,并自动打开新会话。', 'workspace.parent': '父目录', 'workspace.namePlaceholder': '例如:my-project', 'workspace.cancel': '取消', 'workspace.create': '创建并打开', 'workspace.nameRequired': '请输入工作区名称', 'workspace.exists': '该目录已存在', 'workspace.invalidName': '名称不能包含路径分隔符', 'workspace.createFailed': '创建工作区失败:{msg}', 'workspace.created': '工作区已创建', 'workspace.createdNoSession': '工作区已创建,但新会话未能打开',
|
|
@@ -903,13 +940,13 @@
|
|
|
903
940
|
'speed.switched': '已切换到最快服务器:{url}({ms}ms)', 'speed.alreadyBest': '当前已是最快:{url}({ms}ms)',
|
|
904
941
|
'speed.allDown': '全部服务器不可达',
|
|
905
942
|
'servers.empty': '未添加备用服务器 · 默认使用当前页面地址', 'servers.untested': '未测速',
|
|
906
|
-
'servers.current': ' · 当前', 'servers.unreachable': '不可达', 'servers.delete': '删除服务器',
|
|
943
|
+
'servers.current': ' · 当前', 'servers.unreachable': '不可达', 'servers.delete': '删除服务器', 'servers.tokenSet': '令牌已配置', 'servers.tokenMissing': '未配置令牌',
|
|
907
944
|
'servers.currentDesc': '当前: {url}', 'servers.notSet': '未设置服务器', 'servers.defaultDesc': '默认 = 当前页面地址',
|
|
908
945
|
'servers.needAddress': '请输入服务器地址', 'servers.badProtocol': '地址需以 http:// 或 https:// 开头',
|
|
909
|
-
'servers.duplicate': '
|
|
946
|
+
'servers.duplicate': '相同地址和令牌已在列表中', 'servers.added': '已添加服务器', 'servers.removedActive': '已删除当前服务器,重新测速…',
|
|
910
947
|
'servers.currentDescGroup': '当前:{group} · {url}({ms})',
|
|
911
948
|
'servers.edit': '编辑', 'servers.manualSelected': '已切换至:{url}',
|
|
912
|
-
'servers.promptNote': '服务器备注(可留空):', 'servers.promptEditNote': '编辑备注({url}):',
|
|
949
|
+
'servers.promptNote': '服务器备注(可留空):', 'servers.promptEditNote': '编辑备注({url}):', 'servers.promptEditToken': '编辑服务器令牌(留空保持不变):',
|
|
913
950
|
'servers.promptEditUrl': '编辑服务器地址:', 'servers.promptEditGroup': '所属组:', 'servers.edited': '服务器已更新',
|
|
914
951
|
'speed.switchedOrigin': '已切换到当前页面(同源)', 'speed.manualUsing': '手动模式:{url}({ms})',
|
|
915
952
|
'groups.current': '当前组', 'groups.add': '+ 组', 'groups.noServer': '组内暂无服务器',
|
|
@@ -1004,7 +1041,7 @@
|
|
|
1004
1041
|
'settings.groupGeneral': '通用', 'settings.groupGeneralDesc': '显示工具调用、预设提示词',
|
|
1005
1042
|
'settings.groupModel': '模型', 'settings.groupModelDesc': '提供方、API 密钥和模型目录',
|
|
1006
1043
|
'settings.groupTests': '功能测试', 'settings.groupTestsDesc': '验证 Android 和 DSH 原生能力',
|
|
1007
|
-
'settings.groupServers': '服务器', 'settings.groupServersDesc': '
|
|
1044
|
+
'settings.groupServers': '服务器', 'settings.groupServersDesc': '服务器地址、令牌与扫码连接',
|
|
1008
1045
|
'settings.groupNotify': '通知', 'settings.groupNotifyDesc': '通知、提醒、后台轮询',
|
|
1009
1046
|
'settings.groupTheme': '皮肤', 'settings.groupThemeDesc': '配色主题',
|
|
1010
1047
|
'settings.groupAbout': '关于', 'settings.groupAboutDesc': 'DSH 状态、检查更新',
|
|
@@ -1104,12 +1141,14 @@
|
|
|
1104
1141
|
'overview.action.openSession': 'Open recent session', 'overview.action.newSession': 'New session', 'overview.action.attention': 'Review pending', 'overview.action.connect': 'Set up connection', 'overview.action.refresh': 'Check connection',
|
|
1105
1142
|
'overview.communityEyebrow': 'COMMUNITY BOARD', 'overview.communityTitle': 'Announcements & polls', 'overview.communityHistory': 'History', 'overview.communityEmpty': 'No unread announcements',
|
|
1106
1143
|
'overview.communityPoll': 'Poll', 'overview.communityNotice': 'Notice', 'overview.communityNew': 'New', 'overview.communityVote': 'Vote now', 'overview.communityView': 'View notice', 'overview.communityVoted': 'Voted',
|
|
1107
|
-
'statsPage.title': 'Token stats',
|
|
1108
|
-
'statsPage.
|
|
1144
|
+
'statsPage.eyebrow': 'USAGE OVERVIEW', 'statsPage.title': 'Token stats', 'statsPage.subtitle': 'Daily token volume and estimated costs', 'statsPage.latest': 'Latest date', 'statsPage.chartMetric': 'Chart metric', 'statsPage.modeTokens': 'Token count', 'statsPage.modeCost': 'Cost (official)',
|
|
1145
|
+
'statsPage.costKicker': 'ESTIMATED COST', 'statsPage.tokenKicker': 'TOKEN VOLUME', 'statsPage.costChartLabel': 'Cost trend for the last 7 days', 'statsPage.tokenChartLabel': 'Token volume trend for the last 7 days',
|
|
1146
|
+
'statsPage.today': 'Today', 'statsPage.tokenUnit': 'Tokens', 'statsPage.breakdown': 'Today’s usage breakdown', 'statsPage.estimated': 'Estimated cost', 'statsPage.peakShareLabel': 'Peak cost share {n}%',
|
|
1147
|
+
'statsPage.todayTokens': 'Tokens today', 'statsPage.todayCost': 'Cost today', 'statsPage.peakShare': 'Peak share', 'statsPage.costTrend': 'Cost trend', 'statsPage.tokenTrend': 'Token volume trend', 'statsPage.tokenTotal': 'Total tokens',
|
|
1109
1148
|
'statsPage.input': 'Uncached input', 'statsPage.cacheRead': 'Cache read', 'statsPage.cacheWrite': 'Cache write', 'statsPage.output': 'Output',
|
|
1110
1149
|
'statsPage.peak': 'Peak', 'statsPage.off': 'Off-peak', 'statsPage.days': 'Last {n} days',
|
|
1111
1150
|
'statsPage.gatewayDown': 'Stats require the gateway', 'statsPage.empty': 'No stats yet — they aggregate as sessions happen',
|
|
1112
|
-
'statsPage.note': 'Note:
|
|
1151
|
+
'statsPage.note': 'Note: token volume uses DSH usage events; a third-party provider must expose usage to be counted. Costs are estimates for known DeepSeek models and may differ from the official bill; always defer to deepseek.com. Stats start from the 2026-08-17 pricing date.',
|
|
1113
1152
|
'home.newSession': '+ New session', 'home.newWorkspace': '+ Workspace', 'home.empty': 'No sessions yet', 'home.createFailed': 'Failed to create session', 'home.created': 'Session created',
|
|
1114
1153
|
'wb.unbound': 'No workbench bound', 'wb.bound': 'Bound {title}', 'wb.noProjects': 'No projects', 'wb.noSessions': 'No sessions', 'wb.newSession': 'New session', 'wb.orderSaved': 'Order saved on this device', 'wb.flatHidden': 'Workbench sessions folded ({n})', 'wb.archivedHidden': '------ Hide archived ------', 'wb.archivedShown': '------ Show archived ------',
|
|
1115
1154
|
'workspace.createTitle': 'New workspace', 'workspace.createDesc': 'Create a folder in the current file directory and open a new session there.', 'workspace.parent': 'Parent folder', 'workspace.namePlaceholder': 'For example: my-project', 'workspace.cancel': 'Cancel', 'workspace.create': 'Create & open', 'workspace.nameRequired': 'Enter a workspace name', 'workspace.exists': 'That folder already exists', 'workspace.invalidName': 'The name cannot contain path separators', 'workspace.createFailed': 'Could not create workspace: {msg}', 'workspace.created': 'Workspace created', 'workspace.createdNoSession': 'Workspace created, but the new session could not be opened',
|
|
@@ -1130,13 +1169,13 @@
|
|
|
1130
1169
|
'speed.switched': 'Switched to fastest server: {url} ({ms}ms)', 'speed.alreadyBest': 'Already on fastest: {url} ({ms}ms)',
|
|
1131
1170
|
'speed.allDown': 'All servers unreachable',
|
|
1132
1171
|
'servers.empty': 'No backup servers · using the current page URL', 'servers.untested': 'Untested',
|
|
1133
|
-
'servers.current': ' · current', 'servers.unreachable': 'Unreachable', 'servers.delete': 'Remove server',
|
|
1172
|
+
'servers.current': ' · current', 'servers.unreachable': 'Unreachable', 'servers.delete': 'Remove server', 'servers.tokenSet': 'Token set', 'servers.tokenMissing': 'No token',
|
|
1134
1173
|
'servers.currentDesc': 'Current: {url}', 'servers.notSet': 'No server set', 'servers.defaultDesc': 'Default = current page URL',
|
|
1135
1174
|
'servers.needAddress': 'Enter a server address', 'servers.badProtocol': 'Address must start with http:// or https://',
|
|
1136
|
-
'servers.duplicate': '
|
|
1175
|
+
'servers.duplicate': 'The same address and token is already in the list', 'servers.added': 'Server added', 'servers.removedActive': 'Removed active server, re-testing…',
|
|
1137
1176
|
'servers.currentDescGroup': 'Current: {group} · {url} ({ms})',
|
|
1138
1177
|
'servers.edit': 'Edit', 'servers.manualSelected': 'Switched to: {url}',
|
|
1139
|
-
'servers.promptNote': 'Server note (optional):', 'servers.promptEditNote': 'Edit note ({url}):',
|
|
1178
|
+
'servers.promptNote': 'Server note (optional):', 'servers.promptEditNote': 'Edit note ({url}):', 'servers.promptEditToken': 'Edit server token (blank keeps the current token):',
|
|
1140
1179
|
'servers.promptEditUrl': 'Edit server URL:', 'servers.promptEditGroup': 'Group:', 'servers.edited': 'Server updated',
|
|
1141
1180
|
'speed.switchedOrigin': 'Switched to current page (same origin)', 'speed.manualUsing': 'Manual mode: {url} ({ms})',
|
|
1142
1181
|
'groups.current': 'Current group', 'groups.add': '+ Group', 'groups.noServer': 'No servers in this group',
|
|
@@ -1231,7 +1270,7 @@
|
|
|
1231
1270
|
'settings.groupGeneral': 'General', 'settings.groupGeneralDesc': 'Tool calls, prompt presets',
|
|
1232
1271
|
'settings.groupModel': 'Models', 'settings.groupModelDesc': 'Providers, API keys, and model catalogs',
|
|
1233
1272
|
'settings.groupTests': 'Feature tests', 'settings.groupTestsDesc': 'Check Android and DSH native capabilities',
|
|
1234
|
-
'settings.groupServers': 'Servers', 'settings.groupServersDesc': 'Server address, scan to pair',
|
|
1273
|
+
'settings.groupServers': 'Servers', 'settings.groupServersDesc': 'Server address, token, and scan to pair',
|
|
1235
1274
|
'settings.groupNotify': 'Notifications', 'settings.groupNotifyDesc': 'Notifications, reminders, background polling',
|
|
1236
1275
|
'settings.groupTheme': 'Theme', 'settings.groupThemeDesc': 'Color themes',
|
|
1237
1276
|
'settings.groupAbout': 'About', 'settings.groupAboutDesc': 'DSH status, updates',
|
package/public/styles.css
CHANGED
|
@@ -166,30 +166,97 @@ a.mini-btn { text-decoration: none; display: inline-flex; align-items: center; }
|
|
|
166
166
|
.workspace-path-block { display: grid; gap: 6px; margin-top: 2px; color: var(--dsr-muted); font-size: 12px; }
|
|
167
167
|
|
|
168
168
|
/* ---------- Token 统计(移动端) ---------- */
|
|
169
|
-
.stats-
|
|
170
|
-
.
|
|
171
|
-
.
|
|
172
|
-
.
|
|
173
|
-
.
|
|
174
|
-
.
|
|
175
|
-
.
|
|
176
|
-
.
|
|
177
|
-
.
|
|
178
|
-
.stats-
|
|
179
|
-
.stats-
|
|
180
|
-
.stats-
|
|
181
|
-
.stats-
|
|
169
|
+
.stats-view { padding-bottom: 16px; }
|
|
170
|
+
.stats-page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 4px 2px 17px; }
|
|
171
|
+
.stats-page-copy { min-width: 0; }
|
|
172
|
+
.stats-eyebrow, .stats-panel-kicker { color: var(--dsr-accent-strong); font-size: 10px; font-weight: 800; letter-spacing: .14em; line-height: 1.2; }
|
|
173
|
+
.stats-page-head h1 { margin: 4px 0 4px; font-size: 26px; line-height: 1.15; letter-spacing: -.04em; text-wrap: balance; }
|
|
174
|
+
.stats-page-subtitle { margin: 0; color: var(--dsr-muted); font-size: 12px; line-height: 1.5; }
|
|
175
|
+
.stats-date-wrap { display: grid; gap: 2px; flex: 0 0 auto; justify-items: end; padding: 7px 10px; background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 12px; }
|
|
176
|
+
.stats-date-label { color: var(--dsr-muted); font-size: 10px; white-space: nowrap; }
|
|
177
|
+
.stats-date { color: var(--dsr-text); font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
178
|
+
.stats-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 2px 12px; }
|
|
179
|
+
.stats-toolbar-label { color: var(--dsr-muted); font-size: 11px; font-weight: 650; }
|
|
180
|
+
.stats-mode-picker { display: inline-grid; grid-template-columns: 1fr 1fr; gap: 3px; padding: 3px; background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 11px; }
|
|
181
|
+
.stats-mode-btn { min-height: 30px; padding: 5px 10px; border: 1px solid transparent; border-radius: 8px; color: var(--dsr-muted); font-size: 11px; font-weight: 650; white-space: nowrap; }
|
|
182
|
+
.stats-mode-btn.active { color: var(--dsr-text); background: var(--dsr-accent-soft); border-color: var(--dsr-accent-line); box-shadow: 0 2px 8px var(--dsr-shadow); }
|
|
183
|
+
.stats-mode-btn:active { background: var(--dsr-panel-2); }
|
|
184
|
+
.stats-mode-btn:focus-visible { position: relative; z-index: 1; }
|
|
185
|
+
.stats-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
|
|
186
|
+
.scard { position: relative; min-width: 0; overflow: hidden; padding: 14px; background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 18px; box-shadow: 0 8px 24px var(--dsr-shadow); }
|
|
187
|
+
.scard::before { content: ''; position: absolute; inset: 0 0 auto; height: 2px; background: var(--dsr-line); }
|
|
188
|
+
.scard-primary { grid-column: 1 / -1; background: linear-gradient(140deg, var(--dsr-panel), var(--dsr-accent-soft)); }
|
|
189
|
+
.scard-primary::before { background: linear-gradient(90deg, var(--dsr-accent), var(--dsr-accent-2)); }
|
|
190
|
+
.scard-cost::before { background: var(--dsr-accent-2); }
|
|
191
|
+
.scard-share::before { background: var(--dsr-info); }
|
|
192
|
+
.scard-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
|
|
193
|
+
.scard-label { display: inline-flex; align-items: center; gap: 7px; min-width: 0; color: var(--dsr-muted); font-size: 11px; font-weight: 700; }
|
|
194
|
+
.scard-label > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
195
|
+
.scard-icon { display: grid; place-items: center; width: 22px; height: 22px; flex: 0 0 auto; border-radius: 7px; color: var(--dsr-accent-strong); background: var(--dsr-accent-soft); font-size: 14px; font-weight: 800; }
|
|
196
|
+
.scard-icon.cost { color: var(--dsr-accent-2); background: var(--dsr-accent-2-soft); font-size: 12px; }
|
|
197
|
+
.scard-icon.share { color: var(--dsr-info); background: var(--dsr-info-soft); font-size: 12px; }
|
|
198
|
+
.scard-badge { max-width: 48%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsr-muted); font-size: 10px; font-variant-numeric: tabular-nums; }
|
|
199
|
+
.scard-value { margin-top: 11px; color: var(--dsr-text); font-size: 26px; font-weight: 800; line-height: 1.05; letter-spacing: -.035em; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
200
|
+
.scard-primary .scard-value { font-size: clamp(32px, 9vw, 42px); }
|
|
201
|
+
.scard-unit { margin-left: 6px; color: var(--dsr-muted); font-size: 11px; font-weight: 600; letter-spacing: 0; }
|
|
202
|
+
.scard-helper { margin-top: 7px; color: var(--dsr-muted); font-size: 10px; line-height: 1.4; }
|
|
203
|
+
.bucket-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin-top: 14px; padding-top: 11px; border-top: 1px solid var(--dsr-line); }
|
|
204
|
+
.bucket-grid .b { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto; gap: 2px 5px; min-width: 0; }
|
|
205
|
+
.bucket-dot { width: 6px; height: 6px; margin-top: 3px; border-radius: 50%; background: var(--dsr-accent); }
|
|
206
|
+
.bucket-dot.input { background: var(--dsr-accent-strong); }
|
|
207
|
+
.bucket-dot.cache-read { background: var(--dsr-info); }
|
|
208
|
+
.bucket-dot.cache-write { background: var(--dsr-accent-2); }
|
|
209
|
+
.bucket-dot.output { background: var(--dsr-warning); }
|
|
210
|
+
.bucket-grid .n { min-width: 0; overflow: hidden; color: var(--dsr-muted); font-size: 10px; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
|
|
211
|
+
.bucket-grid .t { grid-column: 2; min-width: 0; overflow: hidden; color: var(--dsr-text); font-size: 12px; line-height: 1.2; font-weight: 700; font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; }
|
|
212
|
+
.stats-split { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; margin-top: 14px; }
|
|
213
|
+
.stats-split-item { display: grid; gap: 5px; min-width: 0; padding: 8px; background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-radius: 10px; }
|
|
214
|
+
.stats-split-item span { display: flex; align-items: center; gap: 5px; min-width: 0; color: var(--dsr-muted); font-size: 10px; white-space: nowrap; }
|
|
215
|
+
.stats-split-item strong { overflow: hidden; color: var(--dsr-text); font-size: 12px; font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; }
|
|
216
|
+
.split-dot { width: 6px; height: 6px; flex: 0 0 auto; border-radius: 50%; background: var(--dsr-accent-strong); }
|
|
217
|
+
.split-dot.off { background: var(--dsr-accent-2); }
|
|
218
|
+
.share-layout { display: flex; align-items: center; gap: 10px; margin-top: 13px; }
|
|
219
|
+
.share-ring { position: relative; display: grid; place-items: center; width: 68px; height: 68px; flex: 0 0 auto; border-radius: 50%; background: conic-gradient(var(--dsr-info) var(--share), var(--dsr-bg-2) 0); }
|
|
220
|
+
.share-ring::after { content: ''; position: absolute; inset: 6px; border-radius: 50%; background: var(--dsr-panel); }
|
|
221
|
+
.share-ring span { position: relative; z-index: 1; color: var(--dsr-text); font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; }
|
|
222
|
+
.share-copy { display: grid; gap: 2px; min-width: 0; }
|
|
223
|
+
.share-copy strong { font-size: 13px; }
|
|
224
|
+
.share-copy span, .share-copy small { color: var(--dsr-muted); font-size: 10px; line-height: 1.35; }
|
|
225
|
+
.share-copy small { font-variant-numeric: tabular-nums; }
|
|
226
|
+
.stats-panel { margin-top: 14px; padding: 14px; background: var(--dsr-panel); border: 1px solid var(--dsr-line); border-radius: 18px; box-shadow: 0 8px 24px var(--dsr-shadow); }
|
|
227
|
+
.stats-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; min-width: 0; margin-bottom: 12px; }
|
|
228
|
+
.stats-panel-title { margin: 3px 0 0; font-size: 16px; line-height: 1.2; letter-spacing: -.02em; }
|
|
229
|
+
.stats-legend { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 9px; min-width: 0; margin-top: 1px; color: var(--dsr-muted); font-size: 10px; }
|
|
230
|
+
.stats-legend .lg { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
|
|
231
|
+
.stats-legend .sw { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
|
|
182
232
|
.stats-legend .sw.peak { background: var(--dsr-accent-strong); }
|
|
183
233
|
.stats-legend .sw.off { background: var(--dsr-accent-2); }
|
|
184
|
-
.stats-
|
|
185
|
-
.stats-
|
|
234
|
+
.stats-legend .sw.token { background: var(--dsr-accent); }
|
|
235
|
+
.stats-chart { display: flex; align-items: flex-end; gap: 7px; height: 190px; padding: 21px 2px 20px; overflow-x: auto; overflow-y: hidden; background-image: linear-gradient(to top, var(--dsr-line) 1px, transparent 1px); background-size: 100% 25%; border-radius: 10px; }
|
|
236
|
+
.stats-bar { display: flex; flex: 1 0 30px; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; height: 100%; min-width: 30px; }
|
|
237
|
+
.stats-bar .bars { display: flex; width: 100%; max-width: 40px; height: 100%; flex-direction: column; justify-content: flex-end; overflow: hidden; border-radius: 7px 7px 3px 3px; background: var(--dsr-accent-soft); box-shadow: 0 4px 12px var(--dsr-shadow); }
|
|
186
238
|
.stats-bar .seg { width: 100%; }
|
|
187
239
|
.stats-bar .seg.peak { background: var(--dsr-accent-strong); }
|
|
188
240
|
.stats-bar .seg.off { background: var(--dsr-accent-2); }
|
|
189
|
-
.stats-bar .
|
|
190
|
-
.stats-bar .
|
|
191
|
-
.stats-
|
|
192
|
-
.stats-empty { color: var(--dsr-muted); text-align: center;
|
|
241
|
+
.stats-bar .bars.token { background: linear-gradient(180deg, var(--dsr-accent-strong), var(--dsr-accent)); }
|
|
242
|
+
.stats-bar .lbl { color: var(--dsr-muted); font-size: 9px; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
243
|
+
.stats-bar .val { min-height: 12px; color: var(--dsr-text); font-size: 9px; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
244
|
+
.stats-empty { display: grid; flex: 1; place-items: center; min-height: 145px; color: var(--dsr-muted); text-align: center; font-size: 12px; }
|
|
245
|
+
.stats-note { margin: 14px 2px 0; padding: 10px 12px; color: var(--dsr-muted); background: var(--dsr-info-soft); border-left: 3px solid var(--dsr-info); border-radius: 0 10px 10px 0; font-size: 11px; line-height: 1.6; }
|
|
246
|
+
|
|
247
|
+
@media (max-width: 380px) {
|
|
248
|
+
.stats-page-head { gap: 8px; }
|
|
249
|
+
.stats-page-head h1 { font-size: 23px; }
|
|
250
|
+
.stats-date-wrap { padding: 6px 8px; }
|
|
251
|
+
.stats-toolbar { align-items: flex-start; flex-direction: column; gap: 6px; }
|
|
252
|
+
.stats-mode-picker { width: 100%; }
|
|
253
|
+
.stats-mode-btn { width: 100%; }
|
|
254
|
+
.scard { padding: 12px; }
|
|
255
|
+
.bucket-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
256
|
+
.stats-panel { padding: 12px; }
|
|
257
|
+
.stats-panel-head { display: block; }
|
|
258
|
+
.stats-legend { justify-content: flex-start; margin-top: 8px; }
|
|
259
|
+
}
|
|
193
260
|
|
|
194
261
|
/* ---------- 会话列表 ---------- */
|
|
195
262
|
.session-list { display: flex; flex-direction: column; gap: 8px; }
|
|
@@ -848,6 +915,7 @@ button.overview-attention-item, button.overview-session-item { cursor:pointer; }
|
|
|
848
915
|
.server-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
849
916
|
.server-note { font-size: 13px; word-break: break-all; }
|
|
850
917
|
.server-url { flex: 1; min-width: 0; font-size: 11.5px; color: var(--dsr-muted); word-break: break-all; }
|
|
918
|
+
.server-token-badge { color: var(--dsr-muted); font-size: 10px; }
|
|
851
919
|
.server-badge {
|
|
852
920
|
flex-shrink: 0; font-size: 11px; padding: 1px 7px; border-radius: 999px;
|
|
853
921
|
background: var(--dsr-accent-soft); color: var(--dsr-accent-strong);
|
package/public/update.json
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.6.
|
|
2
|
+
"version": "0.6.18",
|
|
3
3
|
"apkUrl": "dsh-remote.apk",
|
|
4
|
-
"sha256": "
|
|
5
|
-
"releasedAt": "2026-08-
|
|
6
|
-
"notes": "0.6.
|
|
4
|
+
"sha256": "f55ce7284c8f32308fb605bbec3fb432dc73521bb5486c40b48353343e9b63c4",
|
|
5
|
+
"releasedAt": "2026-08-29T06:47:44.726Z",
|
|
6
|
+
"notes": "0.6.18:新增独立 Token 量趋势统计并保留原有费用趋势;服务器连接身份改为地址加令牌,支持同地址不同令牌并兼容旧配置;投票在网关不可达时尝试直连公网收集器托底(需收集器允许 App/Web CORS);修复 Windows 下 gateway-stats 调用 zstd 时弹出终端窗口的问题,并补充回归测试;同步完善相关模块文档。",
|
|
7
7
|
"history": [
|
|
8
|
+
{
|
|
9
|
+
"version": "0.6.18",
|
|
10
|
+
"notes": "0.6.18:新增独立 Token 量趋势统计并保留原有费用趋势;服务器连接身份改为地址加令牌,支持同地址不同令牌并兼容旧配置;投票在网关不可达时尝试直连公网收集器托底(需收集器允许 App/Web CORS);修复 Windows 下 gateway-stats 调用 zstd 时弹出终端窗口的问题,并补充回归测试;同步完善相关模块文档。"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.6.17",
|
|
14
|
+
"notes": "0.6.17:修复 host.describe 初次失败后总览误报 DSH 上游离线并增加恢复重试;识别 Docker、无 systemd 和插件内嵌等外部生命周期环境,隐藏不可用的 DSH 启停并给出明确提示;兼容 Caddy Basic Auth,避免管理 API 覆盖 Authorization 导致登录循环;支持通过环境变量或管理页手动补充 Docker 宿主、局域网和 Tailscale 地址并写入配对二维码;完整适配 Windows 盘符、UNC、多文件根和跨主机文件路径清理,并新增 Windows 原生 CI 安全门禁。"
|
|
15
|
+
},
|
|
8
16
|
{
|
|
9
17
|
"version": "0.6.16",
|
|
10
18
|
"notes": "0.6.16:Windows 端 DSH 服务启动/重启接入 Windows Service(实验性功能),启动后继续检查 DSH HTTP 与 mux/host 实时通道;空对话退出时清理 App 本地残留;网关控制台主机 IP 改为可逐项启用的地址表,关闭地址不再进入配对二维码、诊断和防火墙建议;Android 设置新增模型配置、自定义模型思考深度档位和小米/系统 ASR 功能测试,支持复制设备、权限、partial/final、session 重建和错误诊断日志。"
|
|
@@ -36,14 +44,6 @@
|
|
|
36
44
|
{
|
|
37
45
|
"version": "0.6.9",
|
|
38
46
|
"notes": "0.6.9 正式版:全面优化网络连接稳定性,重构网关实时链路与连接管理;修复 downlink-only 心跳断联、网关重启风暴和 WebSocket 状态竞态;新增 VPN 友好 Ping/Pong、集中 mux/host collector、短时 WebSocket ticket、CORS 收紧与统计旁路优化。"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"version": "0.6.8",
|
|
42
|
-
"notes": "0.6.8 正式版:重构手机端、桌面端和插件管理界面;新增工作台、图片附件、历史公告和全屏输入;修复会话布局、系统提示裁切、主题图标对比度与全屏输入高度问题。"
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"version": "0.6.7",
|
|
46
|
-
"notes": "修复手机端左滑归档松手后按钮不固定;新增云端公告弹窗,支持按 App 版本和有效期定向发布;新增工作台绑定与项目级会话;新增手机端左滑归档和二次确认;新增手机回车行为设置;新增归档会话折叠和 /permission 参数选择。"
|
|
47
47
|
}
|
|
48
48
|
]
|
|
49
49
|
}
|
package/public/version.json
CHANGED