dsh-remote-plugin 0.6.7 → 0.6.9

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.
@@ -1,12 +1,17 @@
1
1
  /* DSH Remote 桌面端专用样式 · 零依赖 · 只引用 --dsr-* 皮肤变量 */
2
- html, body { height: 100%; margin: 0; overflow: hidden; overscroll-behavior: none; background: var(--dsr-bg); color: var(--dsr-text); }
2
+ html, body {
3
+ height: 100%; margin: 0; overflow: hidden; overscroll-behavior: none;
4
+ background: var(--dsr-bg); color: var(--dsr-text);
5
+ font-family: system-ui, -apple-system, "PingFang SC", "Noto Sans CJK SC", sans-serif;
6
+ font-size: 14px; line-height: 1.5; text-rendering: optimizeLegibility;
7
+ }
3
8
  .hidden { display: none !important; }
4
9
  .ds-app { position: fixed; inset: 0; display: flex; overflow: hidden; }
5
- .ds-sidebar { width: 280px; flex: none; display: flex; flex-direction: column; border-right: 1px solid var(--dsr-line); background: var(--dsr-panel); overflow: hidden; }
6
- .ds-brand { display: flex; align-items: center; gap: 8px; padding: 14px 14px 10px; font-weight: 700; font-size: 15px; }
10
+ .ds-sidebar { width: 280px; flex: none; display: flex; flex-direction: column; border-right: 1px solid var(--dsr-line); background: linear-gradient(180deg, var(--dsr-panel), var(--dsr-bg)); box-shadow: 12px 0 34px var(--dsr-shadow); overflow: hidden; }
11
+ .ds-brand { display: flex; align-items: center; gap: 8px; padding: 17px 18px 12px; font-weight: 750; font-size: 15px; letter-spacing: .1px; }
7
12
  .ds-logo { color: var(--dsr-accent-strong); }
8
13
  .ds-brand-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
9
- .ds-gh { color: var(--dsr-muted); display: inline-flex; }
14
+ .ds-gh { color: var(--dsr-accent-2); display: inline-flex; }
10
15
  .ds-gh svg { width: 17px; height: 17px; fill: currentColor; }
11
16
  .ds-new-session { padding: 0 12px 8px; }
12
17
  .ds-btn { display: inline-flex; align-items: center; gap: 6px; background: var(--dsr-bg-2); color: var(--dsr-text); border: 1px solid var(--dsr-line); border-radius: 9px; padding: 6px 11px; font: inherit; font-size: 12.5px; cursor: pointer; white-space: nowrap; }
@@ -14,7 +19,7 @@ html, body { height: 100%; margin: 0; overflow: hidden; overscroll-behavior: non
14
19
  .ds-btn:hover { filter: brightness(1.06); }
15
20
  .ds-btn:active { filter: brightness(.96); }
16
21
  a.ds-btn { text-decoration: none; }
17
- .ds-new-session .ds-btn { width: 100%; justify-content: center; }
22
+ .ds-new-session .ds-btn { width: 100%; justify-content: center; min-height: 38px; border-radius: 12px; background: linear-gradient(135deg, var(--dsr-accent-soft), transparent); }
18
23
  .ds-section-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; min-width: 0; padding-right: 10px; }
19
24
  .ds-section-label { min-width: 0; flex: 1; font-size: 11px; color: var(--dsr-muted); letter-spacing: .8px; padding: 10px 14px 6px; font-weight: 700; }
20
25
  .ds-session-sort {
@@ -23,7 +28,7 @@ a.ds-btn { text-decoration: none; }
23
28
  font: inherit; font-size: 10.5px; outline: none;
24
29
  }
25
30
  .ds-session-sort:focus { border-color: var(--dsr-accent-line); color: var(--dsr-text); }
26
- .ds-session-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 8px; display: flex; flex-direction: column; gap: 3px; }
31
+ .ds-session-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 2px 8px 10px; display: flex; flex-direction: column; gap: 5px; }
27
32
  .ds-session-group {
28
33
  display: flex; align-items: center; gap: 6px; flex: 0 0 auto; min-width: 0; min-height: 28px;
29
34
  box-sizing: border-box; padding: 8px 10px 4px; border-bottom: 1px solid var(--dsr-line);
@@ -31,9 +36,9 @@ a.ds-btn { text-decoration: none; }
31
36
  }
32
37
  .ds-session-group-icon { flex: 0 0 auto; color: var(--dsr-accent-2); font-size: 11px; }
33
38
  .ds-session-group-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
34
- .ds-session-item { width: 100%; flex: 0 0 auto; text-align: left; border: none; background: transparent; color: var(--dsr-text); font: inherit; font-size: 13px; padding: 8px 9px; border-radius: 9px; cursor: pointer; display: flex; flex-direction: column; gap: 3px; }
35
- .ds-session-item:hover { background: var(--dsr-bg-2); }
36
- .ds-session-item.current { background: var(--dsr-accent-soft); color: var(--dsr-accent-strong); }
39
+ .ds-session-item { width: 100%; flex: 0 0 auto; text-align: left; border: 1px solid transparent; background: transparent; color: var(--dsr-text); font: inherit; font-size: 13px; padding: 9px 10px; border-radius: 11px; cursor: pointer; display: flex; flex-direction: column; gap: 3px; transition: transform .18s ease, background .18s ease, border-color .18s ease; }
40
+ .ds-session-item:hover { background: linear-gradient(90deg, var(--dsr-bg-2), transparent); border-color: var(--dsr-line); transform: translateX(2px); }
41
+ .ds-session-item.current { background: linear-gradient(90deg, var(--dsr-accent-soft), transparent); border-color: var(--dsr-accent-line); color: var(--dsr-accent-strong); }
37
42
  .ds-session-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
38
43
  .ds-session-workspace { min-width: 0; color: var(--dsr-muted); font-size: 10.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
39
44
  .ds-session-list.workspace-sorted .ds-session-workspace { display: none; }
@@ -43,10 +48,13 @@ a.ds-btn { text-decoration: none; }
43
48
  .ds-session-dot.running { background: var(--dsr-warning); }
44
49
  .ds-sidebar-foot { border-top: 1px solid var(--dsr-line); padding: 8px; display: flex; flex-direction: column; gap: 3px; max-height: 58vh; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--dsr-line) transparent; }
45
50
  .ds-sidebar-foot > * { flex-shrink: 0; }
46
- .ds-nav-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; border: none; background: transparent; color: var(--dsr-text); font: inherit; font-size: 13px; padding: 9px 10px; border-radius: 9px; cursor: pointer; }
47
- .ds-nav-item:hover { background: var(--dsr-bg-2); }
48
- .ds-nav-item.active { background: var(--dsr-accent-soft); color: var(--dsr-accent-strong); }
49
- .ds-nav-ico { width: 18px; text-align: center; }
51
+ .ds-nav-item { position: relative; display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; border: none; background: transparent; color: var(--dsr-text); font: inherit; font-size: 13px; padding: 9px 10px; border-radius: 10px; cursor: pointer; transition: background .18s ease, color .18s ease, transform .18s ease; }
52
+ .ds-nav-item:hover { background: linear-gradient(90deg, var(--dsr-bg-2), transparent); transform: translateX(2px); }
53
+ .ds-nav-item.active { background: linear-gradient(90deg, var(--dsr-accent-soft), transparent); color: var(--dsr-accent-strong); }
54
+ .ds-nav-item.active::before { content: ''; width: 3px; height: 18px; position: absolute; left: 2px; border-radius: 999px; background: var(--dsr-accent); box-shadow: 0 0 12px var(--dsr-glow); }
55
+ .ds-nav-ico { width: 18px; height: 18px; display: grid; place-items: center; text-align: center; color: var(--dsr-accent-2); }
56
+ .ds-nav-ico svg { width: 17px; height: 17px; display: block; }
57
+ .ds-nav-item.active .ds-nav-ico { color: var(--dsr-accent-strong); }
50
58
 
51
59
  /* 侧边栏底部常驻反馈入口 */
52
60
  .ds-feedback { position: relative; margin-top: 4px; }
@@ -56,7 +64,7 @@ a.ds-btn { text-decoration: none; }
56
64
  font: inherit; font-size: 13px; padding: 9px 10px; border-radius: 9px; cursor: pointer;
57
65
  }
58
66
  .ds-feedback-btn:hover { background: var(--dsr-bg-2); }
59
- .ds-feedback-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
67
+ .ds-feedback-btn svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--dsr-info); }
60
68
  .ds-feedback-menu {
61
69
  position: absolute; bottom: calc(100% + 8px); left: 0; right: 0; z-index: 45;
62
70
  background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-radius: 14px;
@@ -70,7 +78,7 @@ a.ds-btn { text-decoration: none; }
70
78
  padding: 7px 8px; border-radius: 10px; border: none; background: transparent; color: var(--dsr-text);
71
79
  font: inherit; text-align: left; cursor: pointer; text-decoration: none;
72
80
  }
73
- .ds-feedback-item:hover, .ds-feedback-item:focus-visible { background: var(--dsr-bg); outline: none; }
81
+ .ds-feedback-item:hover, .ds-feedback-item:focus-visible { background: var(--dsr-bg); }
74
82
  .ds-feedback-ico {
75
83
  width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0;
76
84
  display: grid; place-items: center; background: var(--dsr-panel); border: 1px solid var(--dsr-line); color: var(--dsr-accent-strong);
@@ -138,10 +146,13 @@ a.ds-btn { text-decoration: none; }
138
146
  .ds-fb-textarea:focus, .ds-fb-input:focus { border-color: var(--dsr-accent-line); }
139
147
  .ds-fb-input { min-height: 42px; }
140
148
 
141
- .ds-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
142
- .ds-topbar { height: 52px; flex: none; display: flex; align-items: center; gap: 10px; padding: 0 14px; border-bottom: 1px solid var(--dsr-line); background: var(--dsr-panel); }
143
- .ds-icon-btn { width: 32px; height: 32px; border-radius: 9px; border: 1px solid var(--dsr-line); background: var(--dsr-bg-2); color: var(--dsr-text); cursor: pointer; font-size: 15px; display: inline-flex; align-items: center; justify-content: center; }
149
+ .ds-main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: radial-gradient(900px 560px at 96% -18%, var(--dsr-accent-soft), transparent 64%), linear-gradient(180deg, var(--dsr-bg), var(--dsr-bg-2)); }
150
+ .ds-topbar { height: 58px; flex: none; display: flex; align-items: center; gap: 10px; padding: 0 20px; border-bottom: 1px solid var(--dsr-divider); background: linear-gradient(180deg, var(--dsr-head-bg), transparent); backdrop-filter: blur(16px); }
151
+ .ds-icon-btn { width: 32px; height: 32px; border-radius: 9px; border: 1px solid var(--dsr-line); background: var(--dsr-bg-2); color: var(--dsr-accent-strong); cursor: pointer; font-size: 15px; display: inline-flex; align-items: center; justify-content: center; }
152
+ .ds-icon-btn svg { width: 17px; height: 17px; display: block; }
144
153
  .ds-icon-btn:hover { filter: brightness(1.06); }
154
+ #btn-donate { color: var(--dsr-accent-2); }
155
+ #btn-stats-top { color: var(--dsr-info); }
145
156
  #btn-mobile-nav { display: none; }
146
157
  .ds-title { flex: 1; min-width: 0; font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
147
158
  .ds-top-right { display: flex; align-items: center; gap: 10px; }
@@ -151,9 +162,75 @@ a.ds-btn { text-decoration: none; }
151
162
  .ds-server { font-size: 12px; color: var(--dsr-muted); max-width: 320px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
152
163
 
153
164
  .ds-content { flex: 1; min-height: 0; display: flex; }
154
- .ds-view { flex: 1; min-width: 0; display: flex; flex-direction: column; padding: 14px 16px; overflow: hidden; }
165
+ .ds-view { flex: 1; min-width: 0; display: flex; flex-direction: column; padding: 20px 26px 32px; overflow: hidden; }
155
166
  .ds-view.hidden { display: none; }
156
167
  .ds-view { animation: dsFade .15s ease; }
168
+
169
+ /* ---------- 系统总览 · A 方案 ---------- */
170
+ #view-overview { overflow-y:auto; background:radial-gradient(circle at 86% 4%,var(--dsr-accent-soft),transparent 32%),var(--dsr-bg); }
171
+ #view-overview > .ds-overview-head,
172
+ #view-overview > .ds-overview-grid,
173
+ #view-overview > .ds-overview-runtime-head,
174
+ #view-overview > .ds-overview-metrics,
175
+ #view-overview > .ds-overview-session-list { width:min(100%, 1500px); margin-left:auto; margin-right:auto; }
176
+ .ds-overview-head { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; margin-top:4px; margin-bottom:18px; }
177
+ .ds-overview-eyebrow { color:var(--dsr-accent-strong); font-size:10px; font-weight:800; letter-spacing:2px; line-height:1.3; }
178
+ .ds-overview-title { margin:4px 0 3px; font-size:26px; line-height:1.2; letter-spacing:-.5px; }
179
+ .ds-overview-subtitle { margin:0; color:var(--dsr-muted); font-size:12px; }
180
+ .ds-overview-refresh { flex:none; }
181
+ .ds-overview-grid { display:grid; grid-template-columns:minmax(0,1.28fr) minmax(300px,.72fr); gap:14px; align-items:start; }
182
+ .ds-overview-pulse-card, .ds-overview-side { min-width:0; border:1px solid var(--dsr-line); border-radius:20px; background:linear-gradient(145deg, var(--dsr-panel), var(--dsr-bg-2)); box-shadow:0 18px 44px var(--dsr-shadow); backdrop-filter:blur(18px); }
183
+ .ds-overview-pulse-card { position:relative; overflow:hidden; display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:center; gap:14px; padding:18px 20px; }
184
+ .ds-overview-pulse-card::after { content:""; position:absolute; width:190px; height:190px; right:-80px; top:-95px; border-radius:50%; background:var(--dsr-accent-soft); filter:blur(5px); pointer-events:none; }
185
+ .ds-overview-pulse-copy { min-width:0; align-self:start; }
186
+ .ds-overview-status { margin-top:8px; font-size:24px; font-weight:780; letter-spacing:-.4px; }
187
+ .ds-overview-status-desc { margin-top:5px; color:var(--dsr-muted); font-size:11px; }
188
+ .ds-overview-primary-action { display:inline-flex; align-items:center; justify-content:center; min-height:36px; margin-top:15px; padding:7px 14px; border:1px solid var(--dsr-accent-strong); border-radius:10px; background:var(--dsr-accent-strong); color:var(--dsr-on-accent); font:inherit; font-size:12px; font-weight:750; cursor:pointer; transition:transform .18s ease, filter .18s ease; }
189
+ .ds-overview-primary-action:hover, .ds-overview-primary-action:focus-visible { filter:brightness(1.08); transform:translateY(-1px); }
190
+ .ds-overview-pulse-card.status-degraded { border-color:var(--dsr-warning-line); }
191
+ .ds-overview-pulse-card.status-degraded .ds-overview-primary-action { border-color:var(--dsr-warning); background:var(--dsr-warning); color:var(--dsr-on-warning); }
192
+ .ds-overview-pulse-card.status-offline { border-color:var(--dsr-error-line); }
193
+ .ds-overview-pulse-card.status-offline .ds-overview-primary-action { border-color:var(--dsr-error); background:var(--dsr-error); color:var(--dsr-neutral-9); }
194
+ .ds-system-pulse-ring { position:relative; z-index:1; width:116px; height:116px; padding:9px; border-radius:50%; background:conic-gradient(var(--dsr-accent) 0 var(--pulse-pct),var(--dsr-line) var(--pulse-pct) 100%); box-shadow:0 0 22px var(--dsr-glow); }
195
+ .ds-system-pulse-ring::before { content:""; position:absolute; inset:7px; border:1px solid var(--dsr-accent-line); border-radius:50%; opacity:.75; }
196
+ .ds-system-pulse-core { position:relative; display:flex; flex-direction:column; align-items:center; justify-content:center; width:100%; height:100%; border-radius:50%; background:var(--dsr-bg-2); color:var(--dsr-muted); }
197
+ .ds-system-pulse-core strong { max-width:100%; color:var(--dsr-text); font-size:17px; line-height:1.05; letter-spacing:.2px; text-align:center; white-space:nowrap; }
198
+ .ds-system-pulse-core span { max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; margin-top:5px; font-size:9px; text-align:center; }
199
+ .ds-overview-links { grid-column:1 / -1; display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:8px; padding-top:10px; border-top:1px solid var(--dsr-line); }
200
+ .ds-overview-link { min-width:0; display:grid; grid-template-columns:auto 1fr; align-items:center; gap:5px 8px; color:var(--dsr-muted); font-size:11px; }
201
+ .ds-overview-link i { width:7px; height:7px; border-radius:50%; background:var(--dsr-muted); box-shadow:0 0 0 4px var(--dsr-line); }
202
+ .ds-overview-link b { grid-column:2; color:var(--dsr-text); font-size:11px; font-weight:650; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
203
+ .ds-overview-link.ok i { background:var(--dsr-success); box-shadow:0 0 0 4px var(--dsr-success-soft); }
204
+ .ds-overview-link.off i { background:var(--dsr-error); box-shadow:0 0 0 4px var(--dsr-error-soft); }
205
+ .ds-overview-side { align-self:start; height:fit-content; padding:16px; border-color:var(--dsr-line); box-shadow:0 12px 30px var(--dsr-shadow); }
206
+ .ds-overview-panel-head { display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:8px; font-size:12px; font-weight:750; letter-spacing:.3px; }
207
+ .ds-overview-meta { color:var(--dsr-muted); font-size:11px; font-weight:500; }
208
+ .ds-overview-attention-list, .ds-overview-session-list { display:flex; flex-direction:column; gap:8px; }
209
+ .ds-overview-attention-item, .ds-overview-session-item { width:100%; min-width:0; display:flex; align-items:center; gap:10px; padding:11px 12px; border:1px solid var(--dsr-line); border-radius:12px; background:var(--dsr-bg-2); color:var(--dsr-text); text-align:left; }
210
+ button.ds-overview-attention-item, button.ds-overview-session-item { cursor:pointer; font:inherit; }
211
+ .ds-overview-attention-item { border-left:3px solid var(--dsr-warning); }
212
+ .ds-overview-attention-item.question { border-left-color:var(--dsr-accent-2); }
213
+ .ds-overview-mark { flex:0 0 auto; width:26px; height:26px; display:grid; place-items:center; border-radius:8px; background:var(--dsr-warning-soft); color:var(--dsr-warning); font-size:12px; }
214
+ .ds-overview-attention-item.question .ds-overview-mark { background:var(--dsr-accent-2-soft); color:var(--dsr-accent-2); }
215
+ .ds-overview-copy { flex:1; min-width:0; }
216
+ .ds-overview-item-title, .ds-overview-item-desc { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
217
+ .ds-overview-item-title { font-size:12px; font-weight:650; }
218
+ .ds-overview-item-desc { margin-top:3px; color:var(--dsr-muted); font-size:11px; }
219
+ .ds-overview-actions { flex:0 0 auto; display:flex; gap:4px; }
220
+ .ds-overview-actions .ds-btn { min-height:27px; padding:2px 8px; font-size:11px; }
221
+ .ds-overview-actions .allow { background:var(--dsr-success-soft); border-color:var(--dsr-success-line); color:var(--dsr-success); }
222
+ .ds-overview-actions .reject { background:var(--dsr-warning-soft); border-color:var(--dsr-warning-line); color:var(--dsr-warning); }
223
+ .ds-overview-arrow { color:var(--dsr-muted); font-size:19px; }
224
+ .ds-overview-runtime-head { margin-top:14px; }
225
+ .ds-overview-metrics { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:9px; }
226
+ .ds-overview-metric { min-width:0; padding:14px 16px; border:1px solid var(--dsr-line); border-radius:15px; background:linear-gradient(145deg, var(--dsr-panel), var(--dsr-bg-2)); box-shadow:inset 0 1px var(--dsr-divider); }
227
+ .ds-overview-metric span { display:block; color:var(--dsr-muted); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
228
+ .ds-overview-metric strong { display:block; margin-top:6px; color:var(--dsr-text); font-size:17px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
229
+ .ds-overview-session-item { background:linear-gradient(90deg, var(--dsr-panel), var(--dsr-bg-2)); border-color:var(--dsr-line); transition:transform .18s ease, border-color .18s ease, background .18s ease; }
230
+ .ds-overview-session-item:hover { transform:translateY(-1px); border-color:var(--dsr-accent-line); background:linear-gradient(90deg, var(--dsr-panel-2), var(--dsr-panel)); }
231
+ .ds-overview-session-item .ds-overview-mark { background:var(--dsr-info-soft); color:var(--dsr-info); }
232
+ .ds-overview-session-item.running .ds-overview-mark { background:var(--dsr-success-soft); color:var(--dsr-success); }
233
+ .ds-overview-empty { padding:10px; border:1px dashed var(--dsr-line); border-radius:12px; color:var(--dsr-muted); font-size:12px; text-align:center; }
157
234
  @keyframes dsFade { from { opacity: .5; } to { opacity: 1; } }
158
235
 
159
236
  /* 会话视图 */
@@ -176,6 +253,9 @@ a.ds-btn { text-decoration: none; }
176
253
  .ds-tool { align-self: flex-start; max-width: min(78%, 680px); width: fit-content; box-sizing: border-box; background: var(--dsr-bg-2); border: 1px solid var(--dsr-line); border-radius: 10px; padding: 8px 11px; font-size: 12px; }
177
254
  .ds-tool summary { cursor: pointer; color: var(--dsr-muted); }
178
255
  .ds-tool pre { margin: 6px 0 0; white-space: pre-wrap; word-break: break-all; font-size: 11px; color: var(--dsr-text); }
256
+ .ds-event-detail { width: min(96%, 780px); max-width: min(96%, 780px); }
257
+ .ds-event-detail summary { white-space: normal; overflow-wrap: anywhere; }
258
+ .ds-event-detail pre { max-height: 280px; overflow: auto; overflow-wrap: anywhere; }
179
259
  .ds-empty { color: var(--dsr-muted); text-align: center; padding: 30px 0; font-size: 13px; }
180
260
  .ds-presets-guide { padding: 2px 8px 10px; font-size: 11px; line-height: 1.5; }
181
261
  .ds-session-cards { flex: none; max-height: 220px; overflow-y: auto; padding: 10px 22px 0; display: flex; flex-direction: column; gap: 8px; }
@@ -216,6 +296,8 @@ a.ds-btn { text-decoration: none; }
216
296
  .ds-fs-path { flex: 1; min-width: 0; font-size: 12.5px; color: var(--dsr-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
217
297
  .ds-fs-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; border: 1px solid var(--dsr-line); border-radius: 12px; background: var(--dsr-panel); }
218
298
  .ds-fs-row { display: flex; align-items: center; gap: 9px; padding: 9px 12px; border-bottom: 1px solid var(--dsr-divider); font-size: 13px; }
299
+ .ds-fs-type { width: 20px; height: 20px; display: grid; place-items: center; color: var(--dsr-info); flex: none; }
300
+ .ds-fs-type svg { width: 18px; height: 18px; display: block; }
219
301
  .ds-fs-row:last-child { border-bottom: none; }
220
302
  .ds-fs-row:hover { background: var(--dsr-bg-2); }
221
303
  .ds-fs-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@@ -365,6 +447,22 @@ a.ds-btn { text-decoration: none; }
365
447
  }
366
448
  .ds-tip.hidden { display: none; }
367
449
 
450
+ .ds-btn:focus-visible, .ds-icon-btn:focus-visible, .ds-mini:focus-visible,
451
+ .ds-session-item:focus-visible, .ds-nav-item:focus-visible, a:focus-visible,
452
+ input:focus-visible, select:focus-visible, textarea:focus-visible {
453
+ outline: 2px solid var(--dsr-accent);
454
+ outline-offset: 2px;
455
+ }
456
+
457
+ @media (prefers-reduced-motion: reduce) {
458
+ *, *::before, *::after {
459
+ animation-duration: .01ms !important;
460
+ animation-iteration-count: 1 !important;
461
+ transition-duration: .01ms !important;
462
+ scroll-behavior: auto !important;
463
+ }
464
+ }
465
+
368
466
  .mobile-only { display: none; }
369
467
 
370
468
  /* 内置滚动条(去原生, 沿用皮肤变量) */
@@ -396,6 +494,8 @@ a.ds-btn { text-decoration: none; }
396
494
  .ds-msg { max-width: 90%; }
397
495
  .ds-toast-stack { left: 10px; right: 10px; width: auto; }
398
496
  .mobile-only { display: block; }
497
+ .ds-overview-grid { grid-template-columns:1fr; }
498
+ .ds-overview-pulse-card { padding:18px; }
399
499
  }
400
500
 
401
501
  @media (max-width: 520px) {
@@ -405,4 +505,11 @@ a.ds-btn { text-decoration: none; }
405
505
  .ds-composer-left { flex: 1 1 100%; gap: 5px; }
406
506
  .ds-composer-left .ds-btn { flex: 1 1 0; min-width: 0; padding-left: 7px; padding-right: 7px; overflow: hidden; text-overflow: ellipsis; }
407
507
  .ds-composer-right { margin-left: auto; }
508
+ .ds-overview-head { margin-bottom:14px; }
509
+ .ds-overview-title { font-size:23px; }
510
+ .ds-overview-pulse-card { grid-template-columns:minmax(0,1fr) auto; gap:12px; padding:15px; }
511
+ .ds-system-pulse-ring { width:92px; height:92px; padding:7px; }
512
+ .ds-system-pulse-core strong { font-size:14px; }
513
+ .ds-overview-metrics { grid-template-columns:repeat(2,minmax(0,1fr)); }
514
+ .ds-overview-actions .ds-btn { padding-left:5px; padding-right:5px; }
408
515
  }
@@ -48,8 +48,9 @@
48
48
  <div id="wb-panel" class="ds-wb-panel hidden"></div>
49
49
  </div>
50
50
  </div>
51
+ <button class="ds-nav-item" data-view="view-overview"><span class="ds-nav-ico">◌</span><span data-i18n="ds.overview">主页</span></button>
51
52
  <button class="ds-nav-item" data-view="view-files"><span class="ds-nav-ico">⇅</span><span data-i18n="ds.files">文件传输</span></button>
52
- <button class="ds-nav-item" data-view="view-settings"><span class="ds-nav-ico">⚙</span><span data-i18n="ds.settings">设置</span></button>
53
+ <button class="ds-nav-item" data-view="view-settings"><span class="ds-nav-ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1-1.8 1.8-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.5v.2h-2.5v-.2a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.9.3l-.1.1-1.8-1.8.1-.1A1.7 1.7 0 0 0 8.1 15a1.7 1.7 0 0 0-1.5-1H6v-2.5h.2a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.9l-.1-.1 1.8-1.8.1.1a1.7 1.7 0 0 0 1.9.3 1.7 1.7 0 0 0 1-1.5v-.2h2.5v.2a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.9-.3l.1-.1 1.8 1.8-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.5 1h.2V14h-.2a1.7 1.7 0 0 0-1.5 1Z"/></svg></span><span data-i18n="ds.settings">设置</span></button>
53
54
  <div class="ds-feedback">
54
55
  <button id="btn-feedback" class="ds-feedback-btn" aria-haspopup="menu" aria-expanded="false" data-i18n-title="ds.feedback" data-i18n-aria="ds.feedback">
55
56
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12a8 8 0 0 1-8 8H5l-1.5 2L4 20a8 8 0 0 1-1-4 8 8 0 0 1 18-4Z"/></svg>
@@ -83,17 +84,59 @@
83
84
 
84
85
  <div class="ds-main">
85
86
  <header class="ds-topbar">
86
- <button id="btn-mobile-nav" class="ds-icon-btn" data-i18n-aria="ds.menu" data-i18n-title="ds.menu">☰</button>
87
+ <button id="btn-mobile-nav" class="ds-icon-btn" data-i18n-aria="ds.menu" data-i18n-title="ds.menu"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16"/></svg></button>
87
88
  <div class="ds-title" id="ds-title" data-i18n="ds.sessions">会话</div>
88
89
  <div class="ds-top-right">
89
90
  <span class="ds-conn" id="conn-badge" title="">●</span>
90
91
  <span class="ds-server" id="server-badge"></span>
91
- <button id="btn-donate" class="ds-icon-btn" data-i18n-aria="ds.donate" data-i18n-title="ds.donate">🎁</button>
92
- <button id="btn-stats-top" class="ds-icon-btn" data-i18n-aria="ds.stats" data-i18n-title="ds.stats">📊</button>
92
+ <button id="btn-donate" class="ds-icon-btn" data-i18n-aria="ds.donate" data-i18n-title="ds.donate"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 8h11v6a4 4 0 0 1-4 4H10a4 4 0 0 1-4-4Z"/><path d="M17 10h1.5a2.5 2.5 0 0 1 0 5H17M9 4c0 1 1 1.2 1 2M13 4c0 1 1 1.2 1 2M5 20h13"/></svg></button>
93
+ <button id="btn-stats-top" class="ds-icon-btn" data-i18n-aria="ds.stats" data-i18n-title="ds.stats"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 19V9M12 19V5M19 19v-7M3 19h18"/></svg></button>
93
94
  </div>
94
95
  </header>
95
96
 
96
97
  <main class="ds-content">
98
+ <!-- 系统总览 -->
99
+ <section id="view-overview" class="ds-view hidden">
100
+ <div class="ds-overview-head">
101
+ <div>
102
+ <div class="ds-overview-eyebrow" data-i18n="ds.overviewEyebrow">SYSTEM OVERVIEW</div>
103
+ <h1 class="ds-overview-title" data-i18n="ds.overview">主页</h1>
104
+ <p class="ds-overview-subtitle" data-i18n="ds.overviewSubtitle">实时状态与需要你处理的事项</p>
105
+ </div>
106
+ <button id="ds-overview-refresh" class="ds-btn ds-overview-refresh" data-i18n="ds.refreshOverview">刷新总览</button>
107
+ </div>
108
+ <div class="ds-overview-grid">
109
+ <div class="ds-overview-pulse-card">
110
+ <div class="ds-overview-pulse-copy">
111
+ <div class="ds-overview-eyebrow" data-i18n="ds.systemPulse">系统链路</div>
112
+ <div id="ds-overview-status" class="ds-overview-status" data-i18n="ds.checking">检查中…</div>
113
+ <div id="ds-overview-status-desc" class="ds-overview-status-desc">—</div>
114
+ <button id="ds-overview-primary-action" class="ds-overview-primary-action" type="button" data-i18n="ds.action.openSession">打开最近会话</button>
115
+ </div>
116
+ <div id="ds-overview-pulse-ring" class="ds-system-pulse-ring" style="--pulse-pct:0%"><div class="ds-system-pulse-core"><strong id="ds-overview-health">—</strong><span id="ds-overview-health-caption">—</span></div></div>
117
+ <div class="ds-overview-links">
118
+ <div class="ds-overview-link" data-ds-overview-link="gateway"><i></i><span data-i18n="ds.gateway">网关</span><b>—</b></div>
119
+ <div class="ds-overview-link" data-ds-overview-link="dsh"><i></i><span data-i18n="ds.dshUpstream">DSH 上游</span><b>—</b></div>
120
+ <div class="ds-overview-link" data-ds-overview-link="mux"><i></i><span data-i18n="ds.mux">实时 mux</span><b>—</b></div>
121
+ <div class="ds-overview-link" data-ds-overview-link="host"><i></i><span data-i18n="ds.host">实时 host</span><b>—</b></div>
122
+ </div>
123
+ </div>
124
+ <div class="ds-overview-side">
125
+ <div class="ds-overview-panel-head"><span data-i18n="ds.attention">需要你处理</span><span id="ds-overview-attention-count" class="ds-overview-meta"></span></div>
126
+ <div id="ds-overview-attention-list" class="ds-overview-attention-list"></div>
127
+ </div>
128
+ </div>
129
+ <div class="ds-overview-panel-head ds-overview-runtime-head"><span data-i18n="ds.runtime">运行指标</span></div>
130
+ <div class="ds-overview-metrics">
131
+ <div class="ds-overview-metric"><span data-i18n="ds.dshVersion">DSH 版本</span><strong id="ds-overview-dsh-version">—</strong></div>
132
+ <div class="ds-overview-metric"><span data-i18n="ds.gatewayStatus">网关状态</span><strong id="ds-overview-gateway-version">—</strong></div>
133
+ <div class="ds-overview-metric"><span data-i18n="ds.activeSessions">活跃会话</span><strong id="ds-overview-active-sessions">0</strong></div>
134
+ <div class="ds-overview-metric"><span data-i18n="ds.connectionMode">连接模式</span><strong id="ds-overview-connection-mode">—</strong></div>
135
+ </div>
136
+ <div class="ds-overview-panel-head ds-overview-runtime-head"><span data-i18n="ds.recentActivity">近期活动</span><span id="ds-overview-active-count" class="ds-overview-meta"></span></div>
137
+ <div id="ds-overview-session-list" class="ds-overview-session-list"></div>
138
+ </section>
139
+
97
140
  <!-- 会话列表视图(窄屏回退用) -->
98
141
  <section id="view-sessions" class="ds-view">
99
142
  <div class="ds-section-label mobile-only" data-i18n="ds.sessions">会话</div>
@@ -261,7 +304,7 @@
261
304
  </div>
262
305
 
263
306
  <!-- 提问回答模态(多问题仍用模态) -->
264
- <div id="modal-question" class="ds-modal hidden">
307
+ <div id="modal-question" class="ds-modal hidden" role="dialog" aria-modal="true">
265
308
  <div class="ds-modal-card">
266
309
  <div class="ds-modal-title" data-i18n="ds.questionTitle">回答问题</div>
267
310
  <div id="question-body" class="ds-modal-body"></div>
@@ -273,7 +316,7 @@
273
316
  </div>
274
317
 
275
318
  <!-- 写反馈模态 -->
276
- <div id="modal-feedback" class="ds-modal hidden">
319
+ <div id="modal-feedback" class="ds-modal hidden" role="dialog" aria-modal="true">
277
320
  <div class="ds-modal-card">
278
321
  <div class="ds-modal-title" data-i18n="ds.feedbackModalTitle">写反馈</div>
279
322
  <div class="ds-modal-body">
@@ -293,7 +336,7 @@
293
336
  </div>
294
337
 
295
338
  <!-- 新建工作区模态 -->
296
- <div id="modal-workspace" class="ds-modal hidden">
339
+ <div id="modal-workspace" class="ds-modal hidden" role="dialog" aria-modal="true">
297
340
  <div class="ds-modal-card">
298
341
  <div class="ds-modal-title" data-i18n="ds.workspaceCreateTitle">新建工作区</div>
299
342
  <div class="ds-modal-body">
@@ -309,7 +352,7 @@
309
352
  </div>
310
353
 
311
354
  <!-- 预设提示词管理模态 -->
312
- <div id="modal-presets" class="ds-modal hidden">
355
+ <div id="modal-presets" class="ds-modal hidden" role="dialog" aria-modal="true">
313
356
  <div class="ds-modal-card">
314
357
  <div class="ds-modal-title" data-i18n="presets.title">预设提示词</div>
315
358
  <div class="ds-modal-body">
@@ -325,7 +368,7 @@
325
368
  </div>
326
369
  </div>
327
370
 
328
- <div id="modal-workbench" class="ds-modal hidden">
371
+ <div id="modal-workbench" class="ds-modal hidden" role="dialog" aria-modal="true">
329
372
  <div class="ds-modal-card ds-wb-modal-card">
330
373
  <div class="ds-modal-title" data-i18n="wb.modalTitle">绑定工作台</div>
331
374
  <div class="ds-modal-body">
@@ -348,7 +391,7 @@
348
391
  </div>
349
392
 
350
393
  <!-- 赞赏支持模态 -->
351
- <div id="modal-donate" class="ds-modal hidden">
394
+ <div id="modal-donate" class="ds-modal hidden" role="dialog" aria-modal="true">
352
395
  <div class="ds-modal-card">
353
396
  <div class="ds-modal-title" data-i18n="ds.donate">赞赏支持</div>
354
397
  <div class="ds-modal-body donate-body">
@@ -362,7 +405,7 @@
362
405
  </div>
363
406
 
364
407
  <!-- 更新内容模态 -->
365
- <div id="modal-notes" class="ds-modal hidden">
408
+ <div id="modal-notes" class="ds-modal hidden" role="dialog" aria-modal="true">
366
409
  <div class="ds-modal-card">
367
410
  <div class="ds-modal-title"><span id="notes-version" style="opacity:.75"></span> <span data-i18n="ds.notesTitle">更新内容</span></div>
368
411
  <div class="ds-modal-body notes-body">
@@ -379,13 +422,16 @@
379
422
  </div>
380
423
  </div>
381
424
 
382
- <div id="toast" class="ds-toast hidden"></div>
425
+ <div id="toast" class="ds-toast hidden" role="status" aria-live="polite"></div>
383
426
  <div id="ds-tip" class="ds-tip hidden" role="tooltip" aria-hidden="true"></div>
384
427
 
385
428
  <script>
386
429
  window.DESKTOP_STR = {
387
430
  zh: {
388
- 'ds.repo': 'GitHub 仓库', 'ds.newSession': '+ 新会话', 'ds.newWorkspace': '新建工作区', 'ds.sessions': '会话',
431
+ 'ds.repo': 'GitHub 仓库', 'ds.newSession': '+ 新会话', 'ds.newWorkspace': '新建工作区', 'ds.sessions': '会话', 'ds.overview': '主页', 'ds.overviewEyebrow': 'SYSTEM OVERVIEW', 'ds.overviewSubtitle': '实时状态与需要你处理的事项',
432
+ 'ds.systemPulse': '系统链路', 'ds.systemNominal': '系统链路正常', 'ds.systemDegraded': '部分链路需要关注', 'ds.systemOffline': '连接已断开', 'ds.checking': '检查中…', 'ds.components': '{n}/4 个模块在线', 'ds.live': 'LIVE', 'ds.allLinked': '全部链路', 'ds.offlineCore': 'OFFLINE',
433
+ 'ds.gateway': '网关', 'ds.dshUpstream': 'DSH 上游', 'ds.mux': '实时 mux', 'ds.host': '实时 host', 'ds.online': '在线', 'ds.offlineShort': '离线',
434
+ 'ds.attention': '需要你处理', 'ds.runtime': '运行指标', 'ds.recentActivity': '近期活动', 'ds.dshVersion': 'DSH 版本', 'ds.gatewayStatus': '网关状态', 'ds.activeSessions': '活跃会话', 'ds.connectionMode': '连接模式', 'ds.liveWs': '实时 WS', 'ds.poll': '降级轮询', 'ds.running': '运行中', 'ds.noReason': '无说明', 'ds.noActivity': '暂无后台活动', 'ds.noSessions': '暂无会话', 'ds.refreshOverview': '刷新总览', 'ds.pendingCount': '{n} 项待处理', 'ds.activeCount': '{n} 个活跃会话', 'ds.nothingPending': '暂无事项', 'ds.action.openSession': '打开最近会话', 'ds.action.newSession': '新建会话', 'ds.action.attention': '处理待办', 'ds.action.connect': '去设置连接', 'ds.action.refresh': '重新检查连接',
389
435
  'ds.sortLabel': '会话排序', 'ds.sortTime': '按时间', 'ds.sortWorkspace': '按工作区', 'ds.workspace': '工作区', 'ds.workspaceUnknown': '未指定工作区',
390
436
  'ds.files': '文件传输', 'ds.settings': '设置', 'ds.stats': '统计', 'ds.menu': '导航',
391
437
  'ds.send': '发送', 'ds.composerPlaceholder': '输入消息,Enter 发送…', 'ds.presets': '预设',
@@ -482,7 +528,10 @@
482
528
  'menu.modelTitle': '模型切换', 'menu.effortTitle': '思考深度',
483
529
  },
484
530
  en: {
485
- 'ds.repo': 'GitHub repo', 'ds.newSession': '+ New session', 'ds.newWorkspace': 'New workspace', 'ds.sessions': 'Sessions',
531
+ 'ds.repo': 'GitHub repo', 'ds.newSession': '+ New session', 'ds.newWorkspace': 'New workspace', 'ds.sessions': 'Sessions', 'ds.overview': 'Home', 'ds.overviewEyebrow': 'SYSTEM OVERVIEW', 'ds.overviewSubtitle': 'Live status and items needing your attention',
532
+ 'ds.systemPulse': 'System pulse', 'ds.systemNominal': 'System nominal', 'ds.systemDegraded': 'Some links need attention', 'ds.systemOffline': 'Connection offline', 'ds.checking': 'Checking…', 'ds.components': '{n}/4 components online', 'ds.live': 'LIVE', 'ds.allLinked': 'ALL LINKED', 'ds.offlineCore': 'OFFLINE',
533
+ 'ds.gateway': 'Gateway', 'ds.dshUpstream': 'DSH upstream', 'ds.mux': 'Live mux', 'ds.host': 'Live host', 'ds.online': 'Online', 'ds.offlineShort': 'Offline',
534
+ 'ds.attention': 'Needs attention', 'ds.runtime': 'Runtime metrics', 'ds.recentActivity': 'Recent activity', 'ds.dshVersion': 'DSH version', 'ds.gatewayStatus': 'Gateway status', 'ds.activeSessions': 'Active sessions', 'ds.connectionMode': 'Connection mode', 'ds.liveWs': 'Live WS', 'ds.poll': 'Degraded polling', 'ds.running': 'Running', 'ds.noReason': 'No reason given', 'ds.noActivity': 'No background activity', 'ds.noSessions': 'No sessions yet', 'ds.refreshOverview': 'Refresh overview', 'ds.pendingCount': '{n} pending', 'ds.activeCount': '{n} active sessions', 'ds.nothingPending': 'Nothing pending', 'ds.action.openSession': 'Open recent session', 'ds.action.newSession': 'New session', 'ds.action.attention': 'Review pending', 'ds.action.connect': 'Set up connection', 'ds.action.refresh': 'Check connection',
486
535
  'ds.sortLabel': 'Session sort', 'ds.sortTime': 'By time', 'ds.sortWorkspace': 'By workspace', 'ds.workspace': 'Workspace', 'ds.workspaceUnknown': 'No workspace',
487
536
  'ds.files': 'Files', 'ds.settings': 'Settings', 'ds.stats': 'Stats', 'ds.menu': 'Menu',
488
537
  'ds.send': 'Send', 'ds.composerPlaceholder': 'Type a message, Enter to send…', 'ds.presets': 'Presets',