dsh-router-core 0.3.21 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +77 -34
  2. package/docs/pool-sticky-block.md +158 -0
  3. package/lib/client-registry.js +351 -407
  4. package/lib/client.js +351 -407
  5. package/lib/index.js +383 -170
  6. package/lib/types/ext/contract.d.ts +0 -7
  7. package/lib/types/host-version.d.ts +15 -0
  8. package/lib/types/index.d.ts +6 -0
  9. package/lib/types/router/account-pool.d.ts +53 -18
  10. package/lib/types/router/index.d.ts +4 -7
  11. package/lib/types/router/prefix-affinity.d.ts +18 -1
  12. package/lib/types/router/types.d.ts +7 -4
  13. package/lib/types/router/usage-store.d.ts +12 -0
  14. package/lib/types/shared.d.ts +13 -21
  15. package/lib/types/supplier-config.d.ts +0 -3
  16. package/lib/types/suppliers/contract.d.ts +2 -2
  17. package/lib/types/suppliers/registry.d.ts +0 -1
  18. package/package.json +12 -13
  19. package/src/client/CombosTab.tsx +8 -53
  20. package/src/client/ExtDetail.tsx +15 -178
  21. package/src/client/LastHitDock.tsx +141 -0
  22. package/src/client/StatsTab.tsx +8 -6
  23. package/src/client/SupplierDetail.tsx +2 -34
  24. package/src/client/index.tsx +45 -0
  25. package/src/client/last-hit-store.ts +89 -0
  26. package/src/client/model-hint-copy.test.ts +7 -2
  27. package/src/client/model-hint-copy.ts +2 -2
  28. package/src/client/router.css +2106 -1630
  29. package/src/ext/contract.ts +0 -7
  30. package/src/host-version.test.ts +61 -0
  31. package/src/host-version.ts +101 -0
  32. package/src/index.ts +133 -59
  33. package/src/llm/adapter.test.ts +74 -0
  34. package/src/llm/adapter.ts +33 -0
  35. package/src/router/account-pool.test.ts +189 -83
  36. package/src/router/account-pool.ts +120 -31
  37. package/src/router/index.ts +22 -28
  38. package/src/router/models-cache.test.ts +9 -9
  39. package/src/router/precise-dispatch.test.ts +6 -6
  40. package/src/router/prefix-affinity.ts +22 -1
  41. package/src/router/types.ts +7 -5
  42. package/src/router/usage-store.ts +16 -0
  43. package/src/router/usage.test.ts +1 -1
  44. package/src/shared.ts +13 -24
  45. package/src/supplier-config.ts +2 -13
  46. package/src/suppliers/contract.ts +2 -2
  47. package/src/suppliers/loader.test.ts +2 -2
  48. package/src/suppliers/registry.ts +1 -20
  49. package/src/types.d.ts +2 -1
@@ -3,64 +3,64 @@
3
3
  ============================================================ */
4
4
 
5
5
  .dshr-entry {
6
- box-sizing: border-box;
7
- display: flex;
8
- width: 100%;
9
- min-height: 36px;
10
- align-items: center;
11
- gap: 10px;
12
- border: none;
13
- border-radius: 8px;
14
- padding: 0 10px;
15
- color: var(--dsw-alias-label-secondary);
16
- background: transparent;
17
- font-size: 13px;
18
- white-space: nowrap;
19
- cursor: pointer;
6
+ box-sizing: border-box;
7
+ display: flex;
8
+ width: 100%;
9
+ min-height: 36px;
10
+ align-items: center;
11
+ gap: 10px;
12
+ border: none;
13
+ border-radius: 8px;
14
+ padding: 0 10px;
15
+ color: var(--dsw-alias-label-secondary);
16
+ background: transparent;
17
+ font-size: 13px;
18
+ white-space: nowrap;
19
+ cursor: pointer;
20
20
  }
21
21
 
22
22
  .dshr-entry:hover {
23
- color: var(--dsw-alias-label-primary);
24
- background: var(--dsw-alias-interactive-bg-hover);
23
+ color: var(--dsw-alias-label-primary);
24
+ background: var(--dsw-alias-interactive-bg-hover);
25
25
  }
26
26
 
27
27
  .dshr-entry[data-active] {
28
- color: var(--dsw-alias-label-primary);
29
- background: var(--dsw-alias-interactive-bg-active);
30
- font-weight: 600;
28
+ color: var(--dsw-alias-label-primary);
29
+ background: var(--dsw-alias-interactive-bg-active);
30
+ font-weight: 600;
31
31
  }
32
32
 
33
33
  .dshr-entryIcon {
34
- display: inline-flex;
35
- flex: none;
36
- align-items: center;
37
- justify-content: center;
38
- width: 24px;
39
- height: 24px;
34
+ display: inline-flex;
35
+ flex: none;
36
+ align-items: center;
37
+ justify-content: center;
38
+ width: 24px;
39
+ height: 24px;
40
40
  }
41
41
 
42
42
  .dshr-entryIcon svg {
43
- display: block;
44
- width: 18px;
45
- height: 18px;
43
+ display: block;
44
+ width: 18px;
45
+ height: 18px;
46
46
  }
47
47
 
48
48
  .dshr-entryLabel {
49
- overflow: hidden;
50
- text-overflow: ellipsis;
49
+ overflow: hidden;
50
+ text-overflow: ellipsis;
51
51
  }
52
52
 
53
53
  [data-dsh-frame][data-sidebar-collapsed] .dshr-entry {
54
- width: 36px;
55
- min-height: 36px;
56
- justify-content: center;
57
- margin: 0 auto 12px;
58
- padding: 0;
59
- border-radius: 50%;
54
+ width: 36px;
55
+ min-height: 36px;
56
+ justify-content: center;
57
+ margin: 0 auto 12px;
58
+ padding: 0;
59
+ border-radius: 50%;
60
60
  }
61
61
 
62
62
  [data-dsh-frame][data-sidebar-collapsed] .dshr-entryLabel {
63
- display: none;
63
+ display: none;
64
64
  }
65
65
 
66
66
  /* ============================================================
@@ -69,28 +69,39 @@
69
69
 
70
70
  .dshr-settings,
71
71
  .dshr-shell {
72
- --rs-bg: var(--dsw-alias-bg-overlay, var(--dsw-alias-bg-base));
73
- --rs-layer-1: var(--dsw-alias-bg-layer-1);
74
- --rs-layer-2: var(--dsw-alias-bg-layer-2);
75
- --rs-input: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-2));
76
- --rs-text: var(--dsw-alias-label-primary);
77
- --rs-muted: var(--dsw-alias-label-secondary);
78
- --rs-faint: var(--dsw-alias-label-tertiary);
79
- --rs-line: var(--dsw-alias-border-l1);
80
- --rs-line-strong: var(--dsw-alias-border-l2);
81
- --rs-accent: var(--dsw-alias-state-business-primary);
82
- --rs-hover: var(--dsw-alias-interactive-bg-hover);
83
- --rs-danger: var(--dsw-alias-state-error-primary);
84
- --rs-success: var(--dsw-alias-state-success-primary);
85
- --rs-ok: var(--rs-success);
86
- --rs-warn: #9a6a18;
87
- --rs-mono: var(--ds-font-family-code, 'SFMono-Regular', Consolas, monospace);
88
- --rs-sans: var(--dsw-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
89
- box-sizing: border-box;
90
- min-width: 0;
91
- color: var(--rs-text);
92
- font: 13px/1.55 var(--rs-sans);
93
- -webkit-tap-highlight-color: transparent;
72
+ --rs-bg: var(--dsw-alias-bg-overlay, var(--dsw-alias-bg-base));
73
+ --rs-layer-1: var(--dsw-alias-bg-layer-1);
74
+ --rs-layer-2: var(--dsw-alias-bg-layer-2);
75
+ --rs-input: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-2));
76
+ --rs-text: var(--dsw-alias-label-primary);
77
+ --rs-muted: var(--dsw-alias-label-secondary);
78
+ --rs-faint: var(--dsw-alias-label-tertiary);
79
+ --rs-line: var(--dsw-alias-border-l1);
80
+ --rs-line-strong: var(--dsw-alias-border-l2);
81
+ --rs-accent: var(--dsw-alias-state-business-primary);
82
+ --rs-hover: var(--dsw-alias-interactive-bg-hover);
83
+ --rs-danger: var(--dsw-alias-state-error-primary);
84
+ --rs-success: var(--dsw-alias-state-success-primary);
85
+ --rs-ok: var(--rs-success);
86
+ --rs-warn: #9a6a18;
87
+ --rs-mono: var(
88
+ --ds-font-family-code,
89
+ "SFMono-Regular",
90
+ Consolas,
91
+ monospace
92
+ );
93
+ --rs-sans: var(
94
+ --dsw-font-family,
95
+ -apple-system,
96
+ BlinkMacSystemFont,
97
+ "Segoe UI",
98
+ sans-serif
99
+ );
100
+ box-sizing: border-box;
101
+ min-width: 0;
102
+ color: var(--rs-text);
103
+ font: 13px/1.55 var(--rs-sans);
104
+ -webkit-tap-highlight-color: transparent;
94
105
  }
95
106
 
96
107
  /* ============================================================
@@ -111,159 +122,187 @@
111
122
  关键字是 min-height:0 —— flex 子项默认 min-height:auto,不给 0 的话
112
123
  子项缩不小,overflow 永远不触发。 */
113
124
  .dshr-settings {
114
- display: flex;
115
- height: 100%;
116
- min-height: 0;
117
- flex-direction: column;
118
- gap: 14px;
125
+ display: flex;
126
+ height: 100%;
127
+ min-height: 0;
128
+ flex-direction: column;
129
+ gap: 14px;
119
130
  }
120
131
 
121
132
  .dshr-settings *,
122
133
  .dshr-settings *::before,
123
- .dshr-settings *::after { box-sizing: border-box; }
134
+ .dshr-settings *::after {
135
+ box-sizing: border-box;
136
+ }
124
137
 
125
138
  /* 主导航 = tab 条。照 DSH 原生的内容区 tab(插件页那套 pbvGtq_tab):
126
139
  容器一条 1px 底部分隔线,激活项用 ::after 画 2px 下划线压在线上。
127
140
  刻意**不用**填充色块——那会跟下面的周期按钮组撞成同一种控件,
128
141
  层级也反了(导航是页面级,周期是筛选级)。 */
129
142
  .dshr-tabs {
130
- display: flex;
131
- flex: none; /* 固定:内容区滚,tab 条不动 */
132
- align-items: center;
133
- gap: 4px;
134
- border-bottom: 1px solid var(--rs-line);
135
- /* 右端跟卡片对齐(实测数字,别凭感觉调):
143
+ display: flex;
144
+ flex: none; /* 固定:内容区滚,tab 条不动 */
145
+ align-items: center;
146
+ gap: 4px;
147
+ border-bottom: 1px solid var(--rs-line);
148
+ /* 右端跟卡片对齐(实测数字,别凭感觉调):
136
149
  root = 564;内容区因 padding-right 8px → 内容可视宽 556;
137
150
  卡片再贴着可视区排 → 548。
138
151
  tab 条是 .dshr-settings 的直接子项,起点是 root(564),
139
152
  要落到 548 就得让掉 8(padding) + 8(滚动条) = 16px。
140
153
  写成 margin 而不用 padding,是为了不把分隔线画到 padding 区域外。 */
141
- margin-right: 16px;
154
+ margin-right: 16px;
142
155
  }
143
156
 
144
157
  .dshr-tab {
145
- position: relative;
146
- min-width: 0;
147
- height: 36px;
148
- padding: 0 12px;
149
- border: none;
150
- border-radius: 0;
151
- color: var(--rs-muted);
152
- background: transparent;
153
- font-size: 13px;
154
- font-weight: 400;
155
- white-space: nowrap;
156
- cursor: pointer;
157
- transition: color .12s ease;
158
- }
159
-
160
- .dshr-tab:hover { color: var(--rs-text); }
158
+ position: relative;
159
+ min-width: 0;
160
+ height: 36px;
161
+ padding: 0 12px;
162
+ border: none;
163
+ border-radius: 0;
164
+ color: var(--rs-muted);
165
+ background: transparent;
166
+ font-size: 13px;
167
+ font-weight: 400;
168
+ white-space: nowrap;
169
+ cursor: pointer;
170
+ transition: color 0.12s ease;
171
+ }
172
+
173
+ .dshr-tab:hover {
174
+ color: var(--rs-text);
175
+ }
161
176
 
162
177
  /* 激活:主文字色 + 2px 下划线(bottom:-1px 压在容器的分隔线上)。
163
178
  双类是因为上面有 `.dshr-settings button { color: inherit; font: inherit }` (1,1),
164
179
  单类的 .dshr-tab-on 只有 (1,0),颜色和字号会被吃掉。 */
165
180
  .dshr-settings .dshr-tab-on {
166
- color: var(--rs-text);
167
- font-size: 13px;
168
- font-weight: 500;
181
+ color: var(--rs-text);
182
+ font-size: 13px;
183
+ font-weight: 500;
169
184
  }
170
185
 
171
186
  .dshr-settings .dshr-tab-on::after {
172
- position: absolute;
173
- right: 0;
174
- bottom: -1px;
175
- left: 0;
176
- height: 2px;
177
- border-radius: 2px 2px 0 0;
178
- content: '';
179
- background: var(--rs-text);
187
+ position: absolute;
188
+ right: 0;
189
+ bottom: -1px;
190
+ left: 0;
191
+ height: 2px;
192
+ border-radius: 2px 2px 0 0;
193
+ content: "";
194
+ background: var(--rs-text);
180
195
  }
181
196
 
182
197
  .dshr-tabBack {
183
- height: 26px;
184
- padding: 0 10px;
185
- border: 1px solid var(--rs-line);
186
- border-radius: 6px;
187
- color: var(--rs-muted);
188
- background: transparent;
189
- font-size: 12px;
190
- white-space: nowrap;
191
- cursor: pointer;
198
+ height: 26px;
199
+ padding: 0 10px;
200
+ border: 1px solid var(--rs-line);
201
+ border-radius: 6px;
202
+ color: var(--rs-muted);
203
+ background: transparent;
204
+ font-size: 12px;
205
+ white-space: nowrap;
206
+ cursor: pointer;
192
207
  }
193
208
 
194
- .dshr-tabBack:hover { color: var(--rs-text); background: var(--rs-hover); }
209
+ .dshr-tabBack:hover {
210
+ color: var(--rs-text);
211
+ background: var(--rs-hover);
212
+ }
195
213
 
196
214
  /* 内容区:吃掉剩余高度并**自己滚**,这样 tab 条永远留在顶部。
197
215
  flex:1 + min-height:0 是必须的(见 .dshr-settings 的注释)。 */
198
216
  .dshr-settingsBody {
199
- display: flex;
200
- min-width: 0;
201
- min-height: 0;
202
- flex: 1 1 auto;
203
- flex-direction: column;
204
- overflow-y: auto;
205
- /* 恒定预留滚动条槽位。
217
+ display: flex;
218
+ min-width: 0;
219
+ min-height: 0;
220
+ flex: 1 1 auto;
221
+ flex-direction: column;
222
+ overflow-y: auto;
223
+ /* 恒定预留滚动条槽位。
206
224
  实测不设它时 clientWidth 在 564(内容短、无滚动条)和 556(内容长、有滚动条)
207
225
  之间跳,卡片宽也跟着 556/548 跳 —— 切 tab 时内容会横向抖一下。
208
226
  不支持 scrollbar-gutter 的浏览器只是退化成「照样占宽」,不会坏。 */
209
- scrollbar-gutter: stable;
210
- /* 右内边距:内容别贴到滚动条上。滚动条宽 8px 且占布局宽度
227
+ scrollbar-gutter: stable;
228
+ /* 右内边距:内容别贴到滚动条上。滚动条宽 8px 且占布局宽度
211
229
  (offsetWidth 564 vs clientWidth 556),不撑开的话内容右边缘正好压在它上面。 */
212
- padding-right: 8px;
230
+ padding-right: 8px;
213
231
  }
214
232
 
215
233
  /* 细滚动条:跟 .dshr-content / .dshr-modalBody 一个套路 */
216
234
  .dshr-settingsBody::-webkit-scrollbar {
217
- width: 8px;
218
- height: 8px;
235
+ width: 8px;
236
+ height: 8px;
219
237
  }
220
238
 
221
239
  .dshr-settingsBody::-webkit-scrollbar-thumb {
222
- border-radius: 4px;
223
- background: var(--rs-line-strong);
240
+ border-radius: 4px;
241
+ background: var(--rs-line-strong);
224
242
  }
225
243
 
226
244
  .dshr-settingsBody::-webkit-scrollbar-track {
227
- background: transparent;
245
+ background: transparent;
228
246
  }
229
247
 
230
248
  /* ============================================================
231
249
  dsh-router — 老的中心栏劫持骨架(settings 不可用时的回退,非主路径)
232
250
  ============================================================ */
233
251
 
234
- [data-pane='conversation'] { position: relative; }
235
- .dshDesktopConversationSurface { position: relative; }
236
-
237
- [data-dsh-router-view] {
238
- position: absolute;
239
- z-index: 60;
240
- inset: 0;
241
- display: none;
242
- min-width: 0;
243
- min-height: 0;
244
- overflow: hidden;
245
- background: var(--dsw-alias-bg-overlay, var(--dsw-alias-bg-base));
252
+ [data-pane="conversation"] {
253
+ position: relative;
246
254
  }
247
-
248
- .dshr-panelView { isolation: isolate; }
249
-
250
- html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]):not([data-dsh-mnemon-active]) [data-dsh-router-view] {
251
- display: block;
255
+ .dshDesktopConversationSurface {
256
+ position: relative;
252
257
  }
253
258
 
254
- html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]):not([data-dsh-mnemon-active]) [data-pane='conversation'] > :not([data-dsh-router-view]),
255
- html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]):not([data-dsh-mnemon-active]) [class*='centerCol'] > :not([data-dsh-router-view]),
256
- html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]):not([data-dsh-mnemon-active]) .dshDesktopConversationSurface > :not([data-dsh-router-view]) {
257
- display: none !important;
259
+ [data-dsh-router-view] {
260
+ position: absolute;
261
+ z-index: 60;
262
+ inset: 0;
263
+ display: none;
264
+ min-width: 0;
265
+ min-height: 0;
266
+ overflow: hidden;
267
+ background: var(--dsw-alias-bg-overlay, var(--dsw-alias-bg-base));
268
+ }
269
+
270
+ .dshr-panelView {
271
+ isolation: isolate;
272
+ }
273
+
274
+ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
275
+ [data-dsh-ssh-active]
276
+ ):not([data-dsh-mnemon-active])
277
+ [data-dsh-router-view] {
278
+ display: block;
279
+ }
280
+
281
+ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
282
+ [data-dsh-ssh-active]
283
+ ):not([data-dsh-mnemon-active])
284
+ [data-pane="conversation"]
285
+ > :not([data-dsh-router-view]),
286
+ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
287
+ [data-dsh-ssh-active]
288
+ ):not([data-dsh-mnemon-active])
289
+ [class*="centerCol"]
290
+ > :not([data-dsh-router-view]),
291
+ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
292
+ [data-dsh-ssh-active]
293
+ ):not([data-dsh-mnemon-active])
294
+ .dshDesktopConversationSurface
295
+ > :not([data-dsh-router-view]) {
296
+ display: none !important;
258
297
  }
259
298
 
260
299
  .dshr-shell {
261
- display: flex;
262
- height: 100%;
263
- min-height: 0;
264
- flex-direction: column;
265
- overflow: hidden;
266
- background: var(--rs-bg);
300
+ display: flex;
301
+ height: 100%;
302
+ min-height: 0;
303
+ flex-direction: column;
304
+ overflow: hidden;
305
+ background: var(--rs-bg);
267
306
  }
268
307
 
269
308
  .dshr-settings *,
@@ -271,7 +310,9 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
271
310
  .dshr-settings *::after,
272
311
  .dshr-shell *,
273
312
  .dshr-shell *::before,
274
- .dshr-shell *::after { box-sizing: border-box; }
313
+ .dshr-shell *::after {
314
+ box-sizing: border-box;
315
+ }
275
316
 
276
317
  /* 按钮/表单重置 + 聚焦环:两个挂载容器都要覆盖。
277
318
  只写 .dshr-shell 的话设置页整套控件样式全掉(踩过:周期按钮变裸文字)。 */
@@ -282,7 +323,10 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
282
323
  .dshr-shell button,
283
324
  .dshr-shell input,
284
325
  .dshr-shell select,
285
- .dshr-shell textarea { color: inherit; font: inherit; }
326
+ .dshr-shell textarea {
327
+ color: inherit;
328
+ font: inherit;
329
+ }
286
330
 
287
331
  .dshr-settings button:focus-visible,
288
332
  .dshr-settings input:focus-visible,
@@ -292,288 +336,329 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
292
336
  .dshr-shell input:focus-visible,
293
337
  .dshr-shell select:focus-visible,
294
338
  .dshr-shell textarea:focus-visible {
295
- outline: 2px solid var(--rs-accent);
296
- outline-offset: 2px;
339
+ outline: 2px solid var(--rs-accent);
340
+ outline-offset: 2px;
297
341
  }
298
342
 
299
343
  /* Masthead */
300
344
  .dshr-masthead {
301
- display: flex;
302
- min-height: 56px;
303
- flex: 0 0 auto;
304
- align-items: center;
305
- gap: 16px;
306
- padding: 0 18px;
307
- border-bottom: 1px solid var(--rs-line);
345
+ display: flex;
346
+ min-height: 56px;
347
+ flex: 0 0 auto;
348
+ align-items: center;
349
+ gap: 16px;
350
+ padding: 0 18px;
351
+ border-bottom: 1px solid var(--rs-line);
308
352
  }
309
353
 
310
354
  .dshr-brand {
311
- display: grid;
312
- min-width: 0;
313
- flex: 0 1 auto;
314
- align-content: center;
315
- gap: 1px 9px;
355
+ display: grid;
356
+ min-width: 0;
357
+ flex: 0 1 auto;
358
+ align-content: center;
359
+ gap: 1px 9px;
316
360
  }
317
361
 
318
362
  .dshr-brandTitle {
319
- overflow: hidden;
320
- font-size: 15px;
321
- font-weight: 650;
322
- text-overflow: ellipsis;
323
- white-space: nowrap;
363
+ overflow: hidden;
364
+ font-size: 15px;
365
+ font-weight: 650;
366
+ text-overflow: ellipsis;
367
+ white-space: nowrap;
324
368
  }
325
369
 
326
370
  .dshr-brandSub {
327
- overflow: hidden;
328
- color: var(--rs-faint);
329
- font-size: 10px;
330
- text-overflow: ellipsis;
331
- white-space: nowrap;
371
+ overflow: hidden;
372
+ color: var(--rs-faint);
373
+ font-size: 10px;
374
+ text-overflow: ellipsis;
375
+ white-space: nowrap;
332
376
  }
333
377
 
334
378
  .dshr-statusCluster {
335
- display: inline-flex;
336
- min-width: 0;
337
- flex: 0 0 auto;
338
- align-items: center;
339
- gap: 7px;
340
- margin-left: auto;
341
- color: var(--rs-muted);
342
- font-size: 12px;
343
- white-space: nowrap;
379
+ display: inline-flex;
380
+ min-width: 0;
381
+ flex: 0 0 auto;
382
+ align-items: center;
383
+ gap: 7px;
384
+ margin-left: auto;
385
+ color: var(--rs-muted);
386
+ font-size: 12px;
387
+ white-space: nowrap;
344
388
  }
345
389
 
346
390
  .dshr-statusEndpoint {
347
- overflow: hidden;
348
- max-width: 220px;
349
- color: var(--rs-faint);
350
- font: 11px var(--rs-mono);
351
- text-overflow: ellipsis;
391
+ overflow: hidden;
392
+ max-width: 220px;
393
+ color: var(--rs-faint);
394
+ font: 11px var(--rs-mono);
395
+ text-overflow: ellipsis;
352
396
  }
353
397
 
354
398
  .dshr-headerActions {
355
- display: inline-flex;
356
- flex: 0 0 auto;
357
- align-items: center;
358
- gap: 10px;
399
+ display: inline-flex;
400
+ flex: 0 0 auto;
401
+ align-items: center;
402
+ gap: 10px;
359
403
  }
360
404
 
361
405
  .dshr-refreshedAt {
362
- color: var(--rs-faint);
363
- font-size: 11px;
364
- white-space: nowrap;
406
+ color: var(--rs-faint);
407
+ font-size: 11px;
408
+ white-space: nowrap;
365
409
  }
366
410
 
367
411
  .dshr-iconButton {
368
- display: inline-flex;
369
- width: 28px;
370
- height: 28px;
371
- align-items: center;
372
- justify-content: center;
373
- border: 1px solid var(--rs-line);
374
- border-radius: 6px;
375
- color: var(--rs-muted);
376
- background: var(--rs-layer-1);
377
- cursor: pointer;
412
+ display: inline-flex;
413
+ width: 28px;
414
+ height: 28px;
415
+ align-items: center;
416
+ justify-content: center;
417
+ border: 1px solid var(--rs-line);
418
+ border-radius: 6px;
419
+ color: var(--rs-muted);
420
+ background: var(--rs-layer-1);
421
+ cursor: pointer;
378
422
  }
379
423
 
380
- .dshr-iconButton:hover { color: var(--rs-text); background: var(--rs-hover); }
381
- .dshr-iconButton:disabled { opacity: 0.5; cursor: default; }
424
+ .dshr-iconButton:hover {
425
+ color: var(--rs-text);
426
+ background: var(--rs-hover);
427
+ }
428
+ .dshr-iconButton:disabled {
429
+ opacity: 0.5;
430
+ cursor: default;
431
+ }
382
432
 
383
433
  .dshr-backButton {
384
- display: inline-flex;
385
- height: 28px;
386
- align-items: center;
387
- gap: 5px;
388
- padding: 0 10px;
389
- border: 1px solid var(--rs-line);
390
- border-radius: 6px;
391
- color: var(--rs-text);
392
- background: transparent;
393
- font-size: 12px;
394
- cursor: pointer;
395
- white-space: nowrap;
396
- }
397
-
398
- .dshr-backButton:hover { background: var(--rs-hover); }
399
- .dshr-backButton svg { display: block; }
434
+ display: inline-flex;
435
+ height: 28px;
436
+ align-items: center;
437
+ gap: 5px;
438
+ padding: 0 10px;
439
+ border: 1px solid var(--rs-line);
440
+ border-radius: 6px;
441
+ color: var(--rs-text);
442
+ background: transparent;
443
+ font-size: 12px;
444
+ cursor: pointer;
445
+ white-space: nowrap;
446
+ }
447
+
448
+ .dshr-backButton:hover {
449
+ background: var(--rs-hover);
450
+ }
451
+ .dshr-backButton svg {
452
+ display: block;
453
+ }
400
454
 
401
455
  /* Alert banner */
402
456
  .dshr-alert {
403
- display: flex;
404
- flex: 0 0 auto;
405
- align-items: baseline;
406
- gap: 10px;
407
- margin: 12px 18px 0;
408
- padding: 10px 12px;
409
- border: 1px solid var(--rs-line-strong);
410
- border-radius: 8px;
411
- background: var(--rs-layer-1);
457
+ display: flex;
458
+ flex: 0 0 auto;
459
+ align-items: baseline;
460
+ gap: 10px;
461
+ margin: 12px 18px 0;
462
+ padding: 10px 12px;
463
+ border: 1px solid var(--rs-line-strong);
464
+ border-radius: 8px;
465
+ background: var(--rs-layer-1);
412
466
  }
413
467
 
414
- .dshr-alert strong { color: var(--rs-danger); font-size: 12px; }
415
- .dshr-alert span { color: var(--rs-muted); font-size: 12px; }
468
+ .dshr-alert strong {
469
+ color: var(--rs-danger);
470
+ font-size: 12px;
471
+ }
472
+ .dshr-alert span {
473
+ color: var(--rs-muted);
474
+ font-size: 12px;
475
+ }
416
476
 
417
477
  /* Nav tabs */
418
478
  .dshr-nav {
419
- display: flex;
420
- flex: 0 0 auto;
421
- gap: 2px;
422
- padding: 0 14px;
423
- border-bottom: 1px solid var(--rs-line);
479
+ display: flex;
480
+ flex: 0 0 auto;
481
+ gap: 2px;
482
+ padding: 0 14px;
483
+ border-bottom: 1px solid var(--rs-line);
424
484
  }
425
485
 
426
486
  .dshr-nav button {
427
- position: relative;
428
- min-height: 42px;
429
- padding: 0 12px;
430
- border: none;
431
- color: var(--rs-muted);
432
- background: transparent;
433
- font-size: 13px;
434
- cursor: pointer;
487
+ position: relative;
488
+ min-height: 42px;
489
+ padding: 0 12px;
490
+ border: none;
491
+ color: var(--rs-muted);
492
+ background: transparent;
493
+ font-size: 13px;
494
+ cursor: pointer;
435
495
  }
436
496
 
437
- .dshr-nav button:hover { color: var(--rs-text); }
497
+ .dshr-nav button:hover {
498
+ color: var(--rs-text);
499
+ }
438
500
 
439
- .dshr-nav button[aria-current='page'] {
440
- color: var(--rs-text);
441
- font-weight: 600;
501
+ .dshr-nav button[aria-current="page"] {
502
+ color: var(--rs-text);
503
+ font-weight: 600;
442
504
  }
443
505
 
444
- .dshr-nav button[aria-current='page']::after {
445
- position: absolute;
446
- right: 0;
447
- bottom: -1px;
448
- left: 0;
449
- height: 2px;
450
- border-radius: 2px 2px 0 0;
451
- content: '';
452
- background: var(--rs-accent);
506
+ .dshr-nav button[aria-current="page"]::after {
507
+ position: absolute;
508
+ right: 0;
509
+ bottom: -1px;
510
+ left: 0;
511
+ height: 2px;
512
+ border-radius: 2px 2px 0 0;
513
+ content: "";
514
+ background: var(--rs-accent);
453
515
  }
454
516
 
455
517
  .dshr-navCount {
456
- display: inline-block;
457
- margin-left: 5px;
458
- padding: 0 6px;
459
- border-radius: 9px;
460
- color: var(--rs-faint);
461
- background: var(--rs-layer-2);
462
- font-size: 11px;
463
- line-height: 16px;
518
+ display: inline-block;
519
+ margin-left: 5px;
520
+ padding: 0 6px;
521
+ border-radius: 9px;
522
+ color: var(--rs-faint);
523
+ background: var(--rs-layer-2);
524
+ font-size: 11px;
525
+ line-height: 16px;
464
526
  }
465
527
 
466
528
  /* Content */
467
529
  .dshr-content {
468
- display: flex;
469
- min-width: 0;
470
- min-height: 0;
471
- flex: 1 1 auto;
472
- flex-direction: column;
473
- overflow: auto;
530
+ display: flex;
531
+ min-width: 0;
532
+ min-height: 0;
533
+ flex: 1 1 auto;
534
+ flex-direction: column;
535
+ overflow: auto;
474
536
  }
475
537
 
476
538
  .dshr-empty {
477
- display: flex;
478
- min-height: 120px;
479
- align-items: center;
480
- justify-content: center;
481
- color: var(--rs-faint);
482
- font-size: 13px;
539
+ display: flex;
540
+ min-height: 120px;
541
+ align-items: center;
542
+ justify-content: center;
543
+ color: var(--rs-faint);
544
+ font-size: 13px;
483
545
  }
484
546
 
485
547
  /* Accounts table */
486
548
  .dshr-tableWrap {
487
- overflow: auto;
488
- padding: 12px 18px;
549
+ overflow: auto;
550
+ padding: 12px 18px;
489
551
  }
490
552
 
491
553
  .dshr-table {
492
- width: 100%;
493
- border-collapse: collapse;
494
- font-size: 12px;
554
+ width: 100%;
555
+ border-collapse: collapse;
556
+ font-size: 12px;
495
557
  }
496
558
 
497
559
  .dshr-table th {
498
- position: sticky;
499
- top: 0;
500
- padding: 8px 10px;
501
- border-bottom: 1px solid var(--rs-line-strong);
502
- color: var(--rs-faint);
503
- background: var(--rs-bg);
504
- font-size: 11px;
505
- font-weight: 600;
506
- text-align: left;
507
- white-space: nowrap;
560
+ position: sticky;
561
+ top: 0;
562
+ padding: 8px 10px;
563
+ border-bottom: 1px solid var(--rs-line-strong);
564
+ color: var(--rs-faint);
565
+ background: var(--rs-bg);
566
+ font-size: 11px;
567
+ font-weight: 600;
568
+ text-align: left;
569
+ white-space: nowrap;
508
570
  }
509
571
 
510
572
  .dshr-table td {
511
- padding: 7px 10px;
512
- border-bottom: 1px solid var(--rs-line);
513
- vertical-align: middle;
573
+ padding: 7px 10px;
574
+ border-bottom: 1px solid var(--rs-line);
575
+ vertical-align: middle;
514
576
  }
515
577
 
516
- .dshr-table tbody tr:hover { background: var(--rs-hover); }
578
+ .dshr-table tbody tr:hover {
579
+ background: var(--rs-hover);
580
+ }
517
581
 
518
- .dshr-mono { font-family: var(--rs-mono); font-size: 11px; }
519
- .dshr-num { text-align: right; }
520
- .dshr-muted { color: var(--rs-faint); }
521
- .dshr-reason { color: var(--rs-muted); font-size: 11px; }
582
+ .dshr-mono {
583
+ font-family: var(--rs-mono);
584
+ font-size: 11px;
585
+ }
586
+ .dshr-num {
587
+ text-align: right;
588
+ }
589
+ .dshr-muted {
590
+ color: var(--rs-faint);
591
+ }
592
+ .dshr-reason {
593
+ color: var(--rs-muted);
594
+ font-size: 11px;
595
+ }
522
596
 
523
597
  .dshr-badge {
524
- display: inline-block;
525
- padding: 1px 8px;
526
- border-radius: 9px;
527
- font-size: 11px;
528
- line-height: 16px;
598
+ display: inline-block;
599
+ padding: 1px 8px;
600
+ border-radius: 9px;
601
+ font-size: 11px;
602
+ line-height: 16px;
529
603
  }
530
604
 
531
- .dshr-badge-ok { color: var(--rs-success); background: color-mix(in srgb, var(--rs-success) 12%, transparent); }
532
- .dshr-badge-warn { color: var(--rs-warn); background: color-mix(in srgb, var(--rs-warn) 14%, transparent); }
533
- .dshr-badge-danger { color: var(--rs-danger); background: color-mix(in srgb, var(--rs-danger) 12%, transparent); }
605
+ .dshr-badge-ok {
606
+ color: var(--rs-success);
607
+ background: color-mix(in srgb, var(--rs-success) 12%, transparent);
608
+ }
609
+ .dshr-badge-warn {
610
+ color: var(--rs-warn);
611
+ background: color-mix(in srgb, var(--rs-warn) 14%, transparent);
612
+ }
613
+ .dshr-badge-danger {
614
+ color: var(--rs-danger);
615
+ background: color-mix(in srgb, var(--rs-danger) 12%, transparent);
616
+ }
534
617
 
535
618
  /* Models grid */
536
619
  .dshr-modelGrid {
537
- display: grid;
538
- grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
539
- gap: 10px;
540
- padding: 14px 18px;
620
+ display: grid;
621
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
622
+ gap: 10px;
623
+ padding: 14px 18px;
541
624
  }
542
625
 
543
626
  /* 设置页里横向 padding 归零:内容区已经贴着容器边,再加 18px 会把卡片挤成
544
627
  1 列、图表也跟着变窄。上下 padding 保留。 */
545
628
  .dshr-settings .dshr-modelGrid,
546
629
  .dshr-settings .dshr-tableWrap {
547
- padding-right: 0;
548
- padding-left: 0;
630
+ padding-right: 0;
631
+ padding-left: 0;
549
632
  }
550
633
 
551
634
  .dshr-modelCard {
552
- display: flex;
553
- min-width: 0;
554
- align-items: center;
555
- justify-content: space-between;
556
- gap: 10px;
557
- padding: 10px 12px;
558
- border: 1px solid var(--rs-line);
559
- border-radius: 8px;
560
- background: var(--rs-layer-1);
635
+ display: flex;
636
+ min-width: 0;
637
+ align-items: center;
638
+ justify-content: space-between;
639
+ gap: 10px;
640
+ padding: 10px 12px;
641
+ border: 1px solid var(--rs-line);
642
+ border-radius: 8px;
643
+ background: var(--rs-layer-1);
561
644
  }
562
645
 
563
- .dshr-modelCard:hover { border-color: var(--rs-line-strong); }
646
+ .dshr-modelCard:hover {
647
+ border-color: var(--rs-line-strong);
648
+ }
564
649
 
565
650
  .dshr-modelId {
566
- overflow: hidden;
567
- font-family: var(--rs-mono);
568
- font-size: 12px;
569
- text-overflow: ellipsis;
570
- white-space: nowrap;
651
+ overflow: hidden;
652
+ font-family: var(--rs-mono);
653
+ font-size: 12px;
654
+ text-overflow: ellipsis;
655
+ white-space: nowrap;
571
656
  }
572
657
 
573
658
  .dshr-modelCtx {
574
- flex: none;
575
- color: var(--rs-faint);
576
- font-size: 10px;
659
+ flex: none;
660
+ color: var(--rs-faint);
661
+ font-size: 10px;
577
662
  }
578
663
 
579
664
  /* ============================================================
@@ -584,123 +669,126 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
584
669
  那一块)。这里再给 overflow 就会出现嵌套滚动条(内容区一个、tabBody 一个)。
585
670
  老的 .dshr-shell 中心栏挂载方式没有 settingsBody 那层,滚动由它自己承担。 */
586
671
  .dshr-tabBody {
587
- display: flex;
588
- min-width: 0;
589
- flex-direction: column;
590
- gap: 14px;
591
- padding: 0;
672
+ display: flex;
673
+ min-width: 0;
674
+ flex-direction: column;
675
+ gap: 14px;
676
+ padding: 0;
592
677
  }
593
678
 
594
679
  .dshr-shell .dshr-tabBody {
595
- flex: 1 1 auto;
596
- min-height: 0;
597
- padding: 14px 18px;
598
- overflow-y: auto;
680
+ flex: 1 1 auto;
681
+ min-height: 0;
682
+ padding: 14px 18px;
683
+ overflow-y: auto;
599
684
  }
600
685
 
601
686
  .dshr-card {
602
- flex: none; /* 不参与 flex 伸缩:高度=内容,避免被压缩裁切 */
603
- min-width: 0;
604
- border: 1px solid var(--rs-line);
605
- border-radius: 10px;
606
- background: var(--rs-layer-1);
607
- overflow: hidden;
687
+ flex: none; /* 不参与 flex 伸缩:高度=内容,避免被压缩裁切 */
688
+ min-width: 0;
689
+ border: 1px solid var(--rs-line);
690
+ border-radius: 10px;
691
+ background: var(--rs-layer-1);
692
+ overflow: hidden;
608
693
  }
609
694
 
610
695
  .dshr-cardHead {
611
- display: flex;
612
- min-height: 44px;
613
- align-items: center;
614
- gap: 10px;
615
- padding: 10px 14px;
616
- border-bottom: 1px solid var(--rs-line);
696
+ display: flex;
697
+ min-height: 44px;
698
+ align-items: center;
699
+ gap: 10px;
700
+ padding: 10px 14px;
701
+ border-bottom: 1px solid var(--rs-line);
617
702
  }
618
703
 
619
704
  .dshr-cardTitle {
620
- font-size: 13px;
621
- font-weight: 650;
705
+ font-size: 13px;
706
+ font-weight: 650;
622
707
  }
623
708
 
624
709
  .dshr-cardMeta {
625
- margin-left: auto;
626
- font-size: 11px;
627
- white-space: nowrap;
710
+ margin-left: auto;
711
+ font-size: 11px;
712
+ white-space: nowrap;
628
713
  }
629
714
 
630
715
  /* 组合链 */
631
716
  .dshr-comboChain {
632
- display: flex;
633
- flex-wrap: wrap;
634
- align-items: center;
635
- gap: 8px;
636
- padding: 14px;
717
+ display: flex;
718
+ flex-wrap: wrap;
719
+ align-items: center;
720
+ gap: 8px;
721
+ padding: 14px;
637
722
  }
638
723
 
639
724
  .dshr-comboStep {
640
- display: inline-flex;
641
- align-items: center;
642
- gap: 6px;
725
+ display: inline-flex;
726
+ align-items: center;
727
+ gap: 6px;
643
728
  }
644
729
 
645
730
  .dshr-comboArrow {
646
- color: var(--rs-faint);
647
- margin-right: 8px;
731
+ color: var(--rs-faint);
732
+ margin-right: 8px;
648
733
  }
649
734
 
650
735
  .dshr-comboSupplier {
651
- font-family: var(--rs-mono);
652
- font-size: 12px;
736
+ font-family: var(--rs-mono);
737
+ font-size: 12px;
653
738
  }
654
739
 
655
740
  /* 端点与密钥 */
656
741
  .dshr-endpointRow {
657
- display: flex;
658
- align-items: center;
659
- gap: 8px;
660
- padding: 12px 14px;
742
+ display: flex;
743
+ align-items: center;
744
+ gap: 8px;
745
+ padding: 12px 14px;
661
746
  }
662
747
 
663
748
  .dshr-endpointCode {
664
- min-width: 0;
665
- flex: 1 1 auto;
666
- overflow: hidden;
667
- padding: 8px 10px;
668
- border: 1px solid var(--rs-line);
669
- border-radius: 6px;
670
- background: var(--rs-layer-2);
671
- color: var(--rs-text);
672
- font-size: 12px;
673
- text-overflow: ellipsis;
674
- white-space: nowrap;
749
+ min-width: 0;
750
+ flex: 1 1 auto;
751
+ overflow: hidden;
752
+ padding: 8px 10px;
753
+ border: 1px solid var(--rs-line);
754
+ border-radius: 6px;
755
+ background: var(--rs-layer-2);
756
+ color: var(--rs-text);
757
+ font-size: 12px;
758
+ text-overflow: ellipsis;
759
+ white-space: nowrap;
675
760
  }
676
761
 
677
762
  .dshr-miniButton {
678
- display: inline-flex;
679
- flex: none;
680
- height: 28px;
681
- align-items: center;
682
- justify-content: center;
683
- padding: 0 10px;
684
- border: 1px solid var(--rs-line);
685
- border-radius: 6px;
686
- color: var(--rs-muted);
687
- background: var(--rs-layer-1);
688
- font-size: 12px;
689
- cursor: pointer;
690
- white-space: nowrap;
691
- }
692
-
693
- .dshr-miniButton:hover { color: var(--rs-text); background: var(--rs-hover); }
763
+ display: inline-flex;
764
+ flex: none;
765
+ height: 28px;
766
+ align-items: center;
767
+ justify-content: center;
768
+ padding: 0 10px;
769
+ border: 1px solid var(--rs-line);
770
+ border-radius: 6px;
771
+ color: var(--rs-muted);
772
+ background: var(--rs-layer-1);
773
+ font-size: 12px;
774
+ cursor: pointer;
775
+ white-space: nowrap;
776
+ }
777
+
778
+ .dshr-miniButton:hover {
779
+ color: var(--rs-text);
780
+ background: var(--rs-hover);
781
+ }
694
782
 
695
783
  .dshr-code {
696
- margin: 0;
697
- padding: 12px 14px;
698
- overflow-x: auto;
699
- color: var(--rs-text);
700
- background: var(--rs-layer-2);
701
- font: 12px/1.6 var(--rs-mono);
702
- white-space: pre-wrap;
703
- word-break: break-all;
784
+ margin: 0;
785
+ padding: 12px 14px;
786
+ overflow-x: auto;
787
+ color: var(--rs-text);
788
+ background: var(--rs-layer-2);
789
+ font: 12px/1.6 var(--rs-mono);
790
+ white-space: pre-wrap;
791
+ word-break: break-all;
704
792
  }
705
793
 
706
794
  /* ============================================================
@@ -709,263 +797,259 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
709
797
 
710
798
  /* 详情页头 */
711
799
  .dshr-detailHead {
712
- display: flex;
713
- align-items: center;
714
- gap: 10px;
715
- min-height: 36px;
800
+ display: flex;
801
+ align-items: center;
802
+ gap: 10px;
803
+ min-height: 36px;
716
804
  }
717
805
 
718
806
  .dshr-detailTitle {
719
- font-size: 14px;
720
- font-weight: 650;
807
+ font-size: 14px;
808
+ font-weight: 650;
721
809
  }
722
810
 
723
811
  /* 可点击卡片 */
724
812
  .dshr-card-click {
725
- cursor: pointer;
726
- transition: border-color .12s ease;
813
+ cursor: pointer;
814
+ transition: border-color 0.12s ease;
727
815
  }
728
816
 
729
- .dshr-card-click:hover { border-color: var(--rs-accent); }
817
+ .dshr-card-click:hover {
818
+ border-color: var(--rs-accent);
819
+ }
730
820
 
731
821
  .dshr-cardHint {
732
- padding: 0 14px 12px;
822
+ padding: 0 14px 12px;
733
823
  }
734
824
 
735
825
  /* 供应商小卡片(grid 布局,替代整行大卡片) */
736
826
  .dshr-supplierGrid {
737
- display: grid;
738
- grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
739
- gap: 12px;
827
+ display: grid;
828
+ grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
829
+ gap: 12px;
740
830
  }
741
831
 
742
832
  /* 供应商分组(内置 / 插件分开) */
743
833
  .dshr-supplierGroup {
744
- display: flex;
745
- flex-direction: column;
746
- gap: 10px;
834
+ display: flex;
835
+ flex-direction: column;
836
+ gap: 10px;
747
837
  }
748
838
 
749
839
  .dshr-supplierGroup + .dshr-supplierGroup {
750
- margin-top: 22px;
840
+ margin-top: 22px;
751
841
  }
752
842
 
753
843
  .dshr-supplierGroupTitle {
754
- font-size: 12px;
755
- font-weight: 600;
756
- color: var(--rs-muted);
757
- letter-spacing: .04em;
758
- padding-left: 2px;
844
+ font-size: 12px;
845
+ font-weight: 600;
846
+ color: var(--rs-muted);
847
+ letter-spacing: 0.04em;
848
+ padding-left: 2px;
759
849
  }
760
850
 
761
851
  .dshr-supplierCard {
762
- display: flex;
763
- flex-direction: column;
764
- gap: 8px;
765
- min-width: 0;
766
- padding: 16px 18px;
767
- border: 1px solid var(--rs-line);
768
- border-radius: 12px;
769
- background: var(--rs-layer-1);
770
- cursor: pointer;
771
- transition: border-color .12s ease;
852
+ display: flex;
853
+ flex-direction: column;
854
+ gap: 8px;
855
+ min-width: 0;
856
+ padding: 16px 18px;
857
+ border: 1px solid var(--rs-line);
858
+ border-radius: 12px;
859
+ background: var(--rs-layer-1);
860
+ cursor: pointer;
861
+ transition: border-color 0.12s ease;
772
862
  }
773
863
 
774
- .dshr-supplierCard:hover { border-color: var(--rs-accent); }
864
+ .dshr-supplierCard:hover {
865
+ border-color: var(--rs-accent);
866
+ }
775
867
 
776
868
  .dshr-supplierName {
777
- font-size: 14px;
778
- font-weight: 650;
779
- white-space: nowrap;
780
- overflow: hidden;
781
- text-overflow: ellipsis;
869
+ font-size: 14px;
870
+ font-weight: 650;
871
+ white-space: nowrap;
872
+ overflow: hidden;
873
+ text-overflow: ellipsis;
782
874
  }
783
875
 
784
876
  .dshr-supplierRow {
785
- display: flex;
786
- align-items: center;
787
- gap: 9px;
788
- min-width: 0;
877
+ display: flex;
878
+ align-items: center;
879
+ gap: 9px;
880
+ min-width: 0;
789
881
  }
790
882
 
791
883
  .dshr-supplierIcon {
792
- width: 24px;
793
- height: 24px;
794
- flex: none;
795
- border-radius: 5px;
796
- object-fit: contain;
797
- color: var(--rs-faint);
884
+ width: 24px;
885
+ height: 24px;
886
+ flex: none;
887
+ border-radius: 5px;
888
+ object-fit: contain;
889
+ color: var(--rs-faint);
798
890
  }
799
891
 
800
892
  .dshr-supplierMeta {
801
- display: flex;
802
- align-items: center;
803
- gap: 8px;
804
- font-size: 11px;
805
- white-space: nowrap;
893
+ display: flex;
894
+ align-items: center;
895
+ gap: 8px;
896
+ font-size: 11px;
897
+ white-space: nowrap;
806
898
  }
807
899
 
808
900
  .dshr-chevron {
809
- color: var(--rs-faint);
810
- font-size: 18px;
811
- line-height: 1;
812
- margin-left: auto;
901
+ color: var(--rs-faint);
902
+ font-size: 18px;
903
+ line-height: 1;
904
+ margin-left: auto;
813
905
  }
814
906
 
815
907
  /* 登录框 */
816
908
  .dshr-loginBox {
817
- display: flex;
818
- flex-direction: column;
819
- gap: 8px;
820
- padding: 12px 14px;
821
- border-bottom: 1px solid var(--rs-line);
822
- background: var(--rs-layer-2);
909
+ display: flex;
910
+ flex-direction: column;
911
+ gap: 8px;
912
+ padding: 12px 14px;
913
+ border-bottom: 1px solid var(--rs-line);
914
+ background: var(--rs-layer-2);
823
915
  }
824
916
 
825
917
  .dshr-loginUrl {
826
- display: block;
827
- overflow: hidden;
828
- padding: 8px 10px;
829
- border: 1px solid var(--rs-line);
830
- border-radius: 6px;
831
- background: var(--rs-layer-1);
832
- color: var(--rs-accent);
833
- font: 11px/1.5 var(--rs-mono);
834
- text-overflow: ellipsis;
835
- white-space: nowrap;
836
- word-break: break-all;
918
+ display: block;
919
+ overflow: hidden;
920
+ padding: 8px 10px;
921
+ border: 1px solid var(--rs-line);
922
+ border-radius: 6px;
923
+ background: var(--rs-layer-1);
924
+ color: var(--rs-accent);
925
+ font: 11px/1.5 var(--rs-mono);
926
+ text-overflow: ellipsis;
927
+ white-space: nowrap;
928
+ word-break: break-all;
837
929
  }
838
930
 
839
931
  /* 输入框 */
840
932
  .dshr-input {
841
- flex: 1 1 auto;
842
- min-width: 0;
843
- height: 30px;
844
- padding: 0 10px;
845
- border: 1px solid var(--rs-line);
846
- border-radius: 6px;
847
- background: var(--rs-layer-1);
848
- color: var(--rs-text);
849
- font-size: 12px;
933
+ flex: 1 1 auto;
934
+ min-width: 0;
935
+ height: 30px;
936
+ padding: 0 10px;
937
+ border: 1px solid var(--rs-line);
938
+ border-radius: 6px;
939
+ background: var(--rs-layer-1);
940
+ color: var(--rs-text);
941
+ font-size: 12px;
850
942
  }
851
943
 
852
944
  .dshr-input:focus {
853
- outline: none;
854
- border-color: var(--rs-accent);
945
+ outline: none;
946
+ border-color: var(--rs-accent);
855
947
  }
856
948
 
857
949
  /* 成功提示 */
858
950
  .dshr-alert-ok {
859
- border-color: color-mix(in srgb, var(--rs-ok) 45%, transparent);
860
- background: color-mix(in srgb, var(--rs-ok) 10%, transparent);
951
+ border-color: color-mix(in srgb, var(--rs-ok) 45%, transparent);
952
+ background: color-mix(in srgb, var(--rs-ok) 10%, transparent);
861
953
  }
862
954
 
863
955
  .dshr-createdKey {
864
- display: block;
865
- margin: 6px 0;
866
- padding: 8px 10px;
867
- border-radius: 6px;
868
- background: var(--rs-layer-1);
869
- word-break: break-all;
956
+ display: block;
957
+ margin: 6px 0;
958
+ padding: 8px 10px;
959
+ border-radius: 6px;
960
+ background: var(--rs-layer-1);
961
+ word-break: break-all;
870
962
  }
871
963
 
872
964
  /* 模型卡片行 */
873
965
  .dshr-modelRow {
874
- display: flex;
875
- align-items: center;
876
- gap: 8px;
877
- min-width: 0;
966
+ display: flex;
967
+ align-items: center;
968
+ gap: 8px;
969
+ min-width: 0;
878
970
  }
879
971
 
880
972
  .dshr-modelCard-off {
881
- opacity: .55;
973
+ opacity: 0.55;
882
974
  }
883
975
 
884
976
  /* 开关 */
885
977
  .dshr-toggle {
886
- position: relative;
887
- flex: none;
888
- width: 30px;
889
- height: 16px;
890
- border: none;
891
- border-radius: 8px;
892
- background: var(--rs-line);
893
- cursor: pointer;
894
- padding: 0;
895
- transition: background .15s ease;
978
+ position: relative;
979
+ flex: none;
980
+ width: 30px;
981
+ height: 16px;
982
+ border: none;
983
+ border-radius: 8px;
984
+ background: var(--rs-line);
985
+ cursor: pointer;
986
+ padding: 0;
987
+ transition: background 0.15s ease;
896
988
  }
897
989
 
898
- .dshr-toggle-on { background: var(--rs-ok); }
990
+ .dshr-toggle-on {
991
+ background: var(--rs-ok);
992
+ }
899
993
 
900
994
  .dshr-toggleKnob {
901
- position: absolute;
902
- top: 2px;
903
- left: 2px;
904
- width: 12px;
905
- height: 12px;
906
- border-radius: 50%;
907
- background: #fff;
908
- transition: transform .15s ease;
995
+ position: absolute;
996
+ top: 2px;
997
+ left: 2px;
998
+ width: 12px;
999
+ height: 12px;
1000
+ border-radius: 50%;
1001
+ background: #fff;
1002
+ transition: transform 0.15s ease;
909
1003
  }
910
1004
 
911
- .dshr-toggle-on .dshr-toggleKnob { transform: translateX(14px); }
1005
+ .dshr-toggle-on .dshr-toggleKnob {
1006
+ transform: translateX(14px);
1007
+ }
912
1008
 
913
1009
  /* 开关禁用态:不可用(未就绪)且未开启时,灰显 + 不可点 */
914
1010
  .dshr-toggle:disabled {
915
- cursor: default;
916
- opacity: .45;
1011
+ cursor: default;
1012
+ opacity: 0.45;
917
1013
  }
918
1014
 
919
1015
  /* 扩展页:未就绪问题描述(红字) */
920
1016
  .dshr-ext-error {
921
- color: var(--rs-danger);
922
- font-size: 11px;
923
- margin-top: 4px;
924
- }
925
-
926
- /* watch 进程行动作区(复制 PID / kill 命令,只读) */
927
- .dshr-procOps {
928
- display: inline-flex;
929
- align-items: center;
930
- justify-content: flex-end;
931
- gap: 4px;
932
- white-space: nowrap;
1017
+ color: var(--rs-danger);
1018
+ font-size: 11px;
1019
+ margin-top: 4px;
933
1020
  }
934
1021
 
935
1022
  /* 扩展供应商式小卡片:未就绪红字(描述只在详情页,卡片不放) */
936
1023
  .dshr-extCardError {
937
- color: var(--rs-danger);
938
- font-size: 11px;
939
- }
940
-
941
- /* 扩展卡 logo(如 rtk 白底 logo):黑底 + 内边距,白色 logo 在黑底上显形 */
942
- .dshr-extLogo {
943
- background: #000;
944
- padding: 3px;
945
- box-sizing: border-box;
946
- object-fit: contain;
1024
+ color: var(--rs-danger);
1025
+ font-size: 11px;
947
1026
  }
948
1027
 
949
1028
  /* 扩展详情头部右侧的开关(顶到标题行右边,同供应商详情的编辑按钮位) */
950
1029
  .dshr-extDetailToggle {
951
- margin-left: auto;
1030
+ margin-left: auto;
952
1031
  }
953
1032
 
954
1033
  /* 扩展卡片内容区:文字左对齐,左侧留白与标题行的图标位对齐 */
955
1034
  .dshr-extBody {
956
- padding: 10px 14px 12px 48px;
957
- text-align: left;
1035
+ padding: 10px 14px 12px 48px;
1036
+ text-align: left;
958
1037
  }
959
1038
 
960
1039
  /* 操作按钮组 */
961
1040
  .dshr-ops {
962
- display: flex;
963
- gap: 6px;
964
- white-space: nowrap;
1041
+ display: flex;
1042
+ gap: 6px;
1043
+ white-space: nowrap;
965
1044
  }
966
1045
 
967
- .dshr-danger { color: var(--rs-danger); }
968
- .dshr-danger:hover { color: var(--rs-danger); border-color: var(--rs-danger); }
1046
+ .dshr-danger {
1047
+ color: var(--rs-danger);
1048
+ }
1049
+ .dshr-danger:hover {
1050
+ color: var(--rs-danger);
1051
+ border-color: var(--rs-danger);
1052
+ }
969
1053
 
970
1054
  /* ============================================================
971
1055
  dsh-router — 弹窗 + 按钮 + 整体打磨
@@ -973,185 +1057,213 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
973
1057
 
974
1058
  /* 弹窗 */
975
1059
  .dshr-modalOverlay {
976
- position: fixed;
977
- z-index: 1000;
978
- inset: 0;
979
- display: flex;
980
- align-items: center;
981
- justify-content: center;
982
- padding: 24px;
983
- background: color-mix(in srgb, #000 42%, transparent);
984
- backdrop-filter: blur(2px);
985
- animation: dshrFadeIn .12s ease;
1060
+ position: fixed;
1061
+ z-index: 1000;
1062
+ inset: 0;
1063
+ display: flex;
1064
+ align-items: center;
1065
+ justify-content: center;
1066
+ padding: 24px;
1067
+ background: color-mix(in srgb, #000 42%, transparent);
1068
+ backdrop-filter: blur(2px);
1069
+ animation: dshrFadeIn 0.12s ease;
986
1070
  }
987
1071
 
988
1072
  .dshr-modal {
989
- width: min(560px, 100%);
990
- max-height: min(80vh, 640px);
991
- display: flex;
992
- flex-direction: column;
993
- overflow: hidden;
994
- border: 1px solid var(--rs-line-strong);
995
- border-radius: 12px;
996
- background: var(--rs-layer-1);
997
- box-shadow: 0 20px 50px rgb(0 0 0 / .35), 0 0 0 1px rgb(0 0 0 / .05);
998
- animation: dshrModalIn .16s ease;
1073
+ width: min(560px, 100%);
1074
+ max-height: min(80vh, 640px);
1075
+ display: flex;
1076
+ flex-direction: column;
1077
+ overflow: hidden;
1078
+ border: 1px solid var(--rs-line-strong);
1079
+ border-radius: 12px;
1080
+ background: var(--rs-layer-1);
1081
+ box-shadow:
1082
+ 0 20px 50px rgb(0 0 0 / 0.35),
1083
+ 0 0 0 1px rgb(0 0 0 / 0.05);
1084
+ animation: dshrModalIn 0.16s ease;
999
1085
  }
1000
1086
 
1001
1087
  .dshr-modalHead {
1002
- display: flex;
1003
- min-height: 48px;
1004
- flex: 0 0 auto;
1005
- align-items: center;
1006
- gap: 10px;
1007
- padding: 0 16px;
1008
- border-bottom: 1px solid var(--rs-line);
1088
+ display: flex;
1089
+ min-height: 48px;
1090
+ flex: 0 0 auto;
1091
+ align-items: center;
1092
+ gap: 10px;
1093
+ padding: 0 16px;
1094
+ border-bottom: 1px solid var(--rs-line);
1009
1095
  }
1010
1096
 
1011
1097
  .dshr-modalTitle {
1012
- min-width: 0;
1013
- flex: 1 1 auto;
1014
- overflow: hidden;
1015
- font-size: 14px;
1016
- font-weight: 650;
1017
- text-overflow: ellipsis;
1018
- white-space: nowrap;
1098
+ min-width: 0;
1099
+ flex: 1 1 auto;
1100
+ overflow: hidden;
1101
+ font-size: 14px;
1102
+ font-weight: 650;
1103
+ text-overflow: ellipsis;
1104
+ white-space: nowrap;
1019
1105
  }
1020
1106
 
1021
1107
  .dshr-modalClose {
1022
- display: inline-flex;
1023
- flex: none;
1024
- width: 26px;
1025
- height: 26px;
1026
- align-items: center;
1027
- justify-content: center;
1028
- border: none;
1029
- border-radius: 6px;
1030
- color: var(--rs-muted);
1031
- background: transparent;
1032
- cursor: pointer;
1108
+ display: inline-flex;
1109
+ flex: none;
1110
+ width: 26px;
1111
+ height: 26px;
1112
+ align-items: center;
1113
+ justify-content: center;
1114
+ border: none;
1115
+ border-radius: 6px;
1116
+ color: var(--rs-muted);
1117
+ background: transparent;
1118
+ cursor: pointer;
1033
1119
  }
1034
1120
 
1035
- .dshr-modalClose:hover { color: var(--rs-text); background: var(--rs-hover); }
1121
+ .dshr-modalClose:hover {
1122
+ color: var(--rs-text);
1123
+ background: var(--rs-hover);
1124
+ }
1036
1125
 
1037
1126
  .dshr-modalBody {
1038
- min-height: 0;
1039
- overflow: auto;
1040
- padding: 16px;
1127
+ min-height: 0;
1128
+ overflow: auto;
1129
+ padding: 16px;
1041
1130
  }
1042
1131
 
1043
1132
  .dshr-modalActions {
1044
- display: flex;
1045
- justify-content: flex-end;
1046
- gap: 8px;
1047
- margin-top: 18px;
1133
+ display: flex;
1134
+ justify-content: flex-end;
1135
+ gap: 8px;
1136
+ margin-top: 18px;
1137
+ }
1138
+
1139
+ @keyframes dshrFadeIn {
1140
+ from {
1141
+ opacity: 0;
1142
+ }
1143
+ to {
1144
+ opacity: 1;
1145
+ }
1146
+ }
1147
+ @keyframes dshrModalIn {
1148
+ from {
1149
+ opacity: 0;
1150
+ transform: translateY(8px) scale(0.98);
1151
+ }
1152
+ to {
1153
+ opacity: 1;
1154
+ transform: none;
1155
+ }
1048
1156
  }
1049
1157
 
1050
- @keyframes dshrFadeIn { from { opacity: 0; } to { opacity: 1; } }
1051
- @keyframes dshrModalIn { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
1052
-
1053
1158
  /* 按钮 */
1054
1159
  .dshr-settings .dshr-primaryButton,
1055
1160
  .dshr-shell .dshr-primaryButton {
1056
- display: inline-flex;
1057
- height: 30px;
1058
- align-items: center;
1059
- justify-content: center;
1060
- padding: 0 14px;
1061
- border: none;
1062
- border-radius: 7px;
1063
- color: #fff;
1064
- background: var(--rs-accent);
1065
- font-size: 12px;
1066
- font-weight: 600;
1067
- cursor: pointer;
1068
- white-space: nowrap;
1069
- transition: filter .12s ease;
1161
+ display: inline-flex;
1162
+ height: 30px;
1163
+ align-items: center;
1164
+ justify-content: center;
1165
+ padding: 0 14px;
1166
+ border: none;
1167
+ border-radius: 7px;
1168
+ color: #fff;
1169
+ background: var(--rs-accent);
1170
+ font-size: 12px;
1171
+ font-weight: 600;
1172
+ cursor: pointer;
1173
+ white-space: nowrap;
1174
+ transition: filter 0.12s ease;
1070
1175
  }
1071
1176
 
1072
1177
  .dshr-settings .dshr-primaryButton:hover,
1073
- .dshr-shell .dshr-primaryButton:hover { filter: brightness(1.08); }
1178
+ .dshr-shell .dshr-primaryButton:hover {
1179
+ filter: brightness(1.08);
1180
+ }
1074
1181
  .dshr-settings .dshr-primaryButton:disabled,
1075
- .dshr-shell .dshr-primaryButton:disabled { opacity: .55; cursor: default; }
1182
+ .dshr-shell .dshr-primaryButton:disabled {
1183
+ opacity: 0.55;
1184
+ cursor: default;
1185
+ }
1076
1186
 
1077
1187
  .dshr-settings .dshr-dangerButton,
1078
1188
  .dshr-shell .dshr-dangerButton {
1079
- display: inline-flex;
1080
- height: 30px;
1081
- align-items: center;
1082
- justify-content: center;
1083
- padding: 0 14px;
1084
- border: none;
1085
- border-radius: 7px;
1086
- color: #fff;
1087
- background: var(--rs-danger);
1088
- font-size: 12px;
1089
- font-weight: 600;
1090
- cursor: pointer;
1091
- white-space: nowrap;
1092
- transition: filter .12s ease;
1189
+ display: inline-flex;
1190
+ height: 30px;
1191
+ align-items: center;
1192
+ justify-content: center;
1193
+ padding: 0 14px;
1194
+ border: none;
1195
+ border-radius: 7px;
1196
+ color: #fff;
1197
+ background: var(--rs-danger);
1198
+ font-size: 12px;
1199
+ font-weight: 600;
1200
+ cursor: pointer;
1201
+ white-space: nowrap;
1202
+ transition: filter 0.12s ease;
1093
1203
  }
1094
1204
 
1095
1205
  .dshr-settings .dshr-dangerButton:hover,
1096
- .dshr-shell .dshr-dangerButton:hover { filter: brightness(1.1); }
1206
+ .dshr-shell .dshr-dangerButton:hover {
1207
+ filter: brightness(1.1);
1208
+ }
1097
1209
 
1098
1210
  /* 登录步骤 */
1099
1211
  .dshr-loginBox {
1100
- display: flex;
1101
- flex-direction: column;
1102
- gap: 10px;
1212
+ display: flex;
1213
+ flex-direction: column;
1214
+ gap: 10px;
1103
1215
  }
1104
1216
 
1105
1217
  .dshr-loginStep {
1106
- display: flex;
1107
- align-items: flex-start;
1108
- gap: 8px;
1109
- color: var(--rs-muted);
1110
- font-size: 12px;
1111
- line-height: 1.6;
1218
+ display: flex;
1219
+ align-items: flex-start;
1220
+ gap: 8px;
1221
+ color: var(--rs-muted);
1222
+ font-size: 12px;
1223
+ line-height: 1.6;
1112
1224
  }
1113
1225
 
1114
1226
  .dshr-loginNum {
1115
- display: inline-flex;
1116
- flex: none;
1117
- width: 18px;
1118
- height: 18px;
1119
- align-items: center;
1120
- justify-content: center;
1121
- border-radius: 50%;
1122
- color: var(--rs-accent);
1123
- background: color-mix(in srgb, var(--rs-accent) 14%, transparent);
1124
- font-size: 11px;
1125
- font-weight: 700;
1227
+ display: inline-flex;
1228
+ flex: none;
1229
+ width: 18px;
1230
+ height: 18px;
1231
+ align-items: center;
1232
+ justify-content: center;
1233
+ border-radius: 50%;
1234
+ color: var(--rs-accent);
1235
+ background: color-mix(in srgb, var(--rs-accent) 14%, transparent);
1236
+ font-size: 11px;
1237
+ font-weight: 700;
1126
1238
  }
1127
1239
 
1128
1240
  .dshr-loginUrl {
1129
- display: block;
1130
- overflow: hidden;
1131
- padding: 9px 11px;
1132
- border: 1px solid var(--rs-line);
1133
- border-radius: 8px;
1134
- background: var(--rs-layer-2);
1135
- color: var(--rs-accent);
1136
- font: 11px/1.5 var(--rs-mono);
1137
- text-overflow: ellipsis;
1138
- white-space: nowrap;
1139
- word-break: break-all;
1241
+ display: block;
1242
+ overflow: hidden;
1243
+ padding: 9px 11px;
1244
+ border: 1px solid var(--rs-line);
1245
+ border-radius: 8px;
1246
+ background: var(--rs-layer-2);
1247
+ color: var(--rs-accent);
1248
+ font: 11px/1.5 var(--rs-mono);
1249
+ text-overflow: ellipsis;
1250
+ white-space: nowrap;
1251
+ word-break: break-all;
1140
1252
  }
1141
1253
 
1142
1254
  /* 新 Key 弹窗 */
1143
1255
  .dshr-createdKeyBox {
1144
- display: flex;
1145
- flex-direction: column;
1146
- gap: 10px;
1256
+ display: flex;
1257
+ flex-direction: column;
1258
+ gap: 10px;
1147
1259
  }
1148
1260
 
1149
1261
  .dshr-createdKey {
1150
- padding: 10px 12px;
1151
- border-radius: 8px;
1152
- background: var(--rs-layer-2);
1153
- word-break: break-all;
1154
- user-select: all;
1262
+ padding: 10px 12px;
1263
+ border-radius: 8px;
1264
+ background: var(--rs-layer-2);
1265
+ word-break: break-all;
1266
+ user-select: all;
1155
1267
  }
1156
1268
 
1157
1269
  /* ============================================================
@@ -1160,80 +1272,100 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
1160
1272
 
1161
1273
  /* Masthead: 细腻渐变 + 底部微阴影 */
1162
1274
  .dshr-masthead {
1163
- background: linear-gradient(to bottom, color-mix(in srgb, var(--rs-layer-1) 62%, transparent), transparent);
1275
+ background: linear-gradient(
1276
+ to bottom,
1277
+ color-mix(in srgb, var(--rs-layer-1) 62%, transparent),
1278
+ transparent
1279
+ );
1164
1280
  }
1165
1281
 
1166
1282
  /* Brand 标题更突出 */
1167
1283
  .dshr-brandTitle {
1168
- letter-spacing: .01em;
1284
+ letter-spacing: 0.01em;
1169
1285
  }
1170
1286
 
1171
1287
  /* 卡片:阴影 + hover 微抬升 */
1172
1288
  .dshr-card {
1173
- box-shadow: 0 1px 2px rgb(0 0 0 / .04);
1174
- transition: box-shadow .15s ease, transform .15s ease, border-color .15s ease;
1289
+ box-shadow: 0 1px 2px rgb(0 0 0 / 0.04);
1290
+ transition:
1291
+ box-shadow 0.15s ease,
1292
+ transform 0.15s ease,
1293
+ border-color 0.15s ease;
1175
1294
  }
1176
1295
 
1177
1296
  .dshr-card-click:hover {
1178
- transform: translateY(-1px);
1179
- border-color: color-mix(in srgb, var(--rs-accent) 55%, var(--rs-line));
1180
- box-shadow: 0 6px 18px rgb(0 0 0 / .10);
1297
+ transform: translateY(-1px);
1298
+ border-color: color-mix(in srgb, var(--rs-accent) 55%, var(--rs-line));
1299
+ box-shadow: 0 6px 18px rgb(0 0 0 / 0.1);
1181
1300
  }
1182
1301
 
1183
1302
  /* Tab:悬停背景 + 计数徽标配色 */
1184
1303
  .dshr-nav button {
1185
- transition: color .12s ease, background .12s ease;
1304
+ transition:
1305
+ color 0.12s ease,
1306
+ background 0.12s ease;
1186
1307
  }
1187
1308
 
1188
1309
  .dshr-nav button:hover {
1189
- background: var(--rs-hover);
1190
- border-radius: 6px 6px 0 0;
1310
+ background: var(--rs-hover);
1311
+ border-radius: 6px 6px 0 0;
1191
1312
  }
1192
1313
 
1193
1314
  .dshr-navCount {
1194
- background: color-mix(in srgb, var(--rs-accent) 12%, transparent);
1195
- color: var(--rs-accent);
1196
- font-weight: 600;
1315
+ background: color-mix(in srgb, var(--rs-accent) 12%, transparent);
1316
+ color: var(--rs-accent);
1317
+ font-weight: 600;
1197
1318
  }
1198
1319
 
1199
1320
  /* 徽标:更柔和 */
1200
1321
  .dshr-badge {
1201
- box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 12%, transparent);
1322
+ box-shadow: inset 0 0 0 1px
1323
+ color-mix(in srgb, currentColor 12%, transparent);
1202
1324
  }
1203
1325
 
1204
1326
  /* 表格行悬停 + 表头层级 */
1205
- .dshr-table tbody tr { transition: background .1s ease; }
1206
- .dshr-table th { letter-spacing: .02em; }
1327
+ .dshr-table tbody tr {
1328
+ transition: background 0.1s ease;
1329
+ }
1330
+ .dshr-table th {
1331
+ letter-spacing: 0.02em;
1332
+ }
1207
1333
 
1208
1334
  /* 输入框聚焦 */
1209
1335
  .dshr-input:focus {
1210
- border-color: var(--rs-accent);
1211
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--rs-accent) 18%, transparent);
1336
+ border-color: var(--rs-accent);
1337
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--rs-accent) 18%, transparent);
1212
1338
  }
1213
1339
 
1214
1340
  /* 开关微过渡 */
1215
- .dshr-toggle { transition: background .15s ease, box-shadow .15s ease; }
1216
- .dshr-toggle:hover { box-shadow: 0 0 0 3px color-mix(in srgb, var(--rs-accent) 18%, transparent); }
1341
+ .dshr-toggle {
1342
+ transition:
1343
+ background 0.15s ease,
1344
+ box-shadow 0.15s ease;
1345
+ }
1346
+ .dshr-toggle:hover {
1347
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--rs-accent) 18%, transparent);
1348
+ }
1217
1349
 
1218
1350
  /* 内容区细滚动条 */
1219
1351
  .dshr-content::-webkit-scrollbar,
1220
1352
  .dshr-tableWrap::-webkit-scrollbar,
1221
1353
  .dshr-modalBody::-webkit-scrollbar {
1222
- width: 8px;
1223
- height: 8px;
1354
+ width: 8px;
1355
+ height: 8px;
1224
1356
  }
1225
1357
 
1226
1358
  .dshr-content::-webkit-scrollbar-thumb,
1227
1359
  .dshr-tableWrap::-webkit-scrollbar-thumb,
1228
1360
  .dshr-modalBody::-webkit-scrollbar-thumb {
1229
- border-radius: 4px;
1230
- background: var(--rs-line-strong);
1361
+ border-radius: 4px;
1362
+ background: var(--rs-line-strong);
1231
1363
  }
1232
1364
 
1233
1365
  .dshr-content::-webkit-scrollbar-track,
1234
1366
  .dshr-tableWrap::-webkit-scrollbar-track,
1235
1367
  .dshr-modalBody::-webkit-scrollbar-track {
1236
- background: transparent;
1368
+ background: transparent;
1237
1369
  }
1238
1370
 
1239
1371
  /* ============================================================
@@ -1242,257 +1374,292 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
1242
1374
 
1243
1375
  /* 卡片头图标 */
1244
1376
  .dshr-cardIcon {
1245
- display: inline-flex;
1246
- flex: none;
1247
- align-items: center;
1248
- justify-content: center;
1249
- width: 24px;
1250
- height: 24px;
1251
- border-radius: 6px;
1252
- color: var(--rs-accent);
1253
- background: color-mix(in srgb, var(--rs-accent) 12%, transparent);
1377
+ display: inline-flex;
1378
+ flex: none;
1379
+ align-items: center;
1380
+ justify-content: center;
1381
+ width: 24px;
1382
+ height: 24px;
1383
+ border-radius: 6px;
1384
+ color: var(--rs-accent);
1385
+ background: color-mix(in srgb, var(--rs-accent) 12%, transparent);
1254
1386
  }
1255
1387
 
1256
1388
  .dshr-cardAction {
1257
- margin-left: auto;
1389
+ margin-left: auto;
1258
1390
  }
1259
1391
 
1260
1392
  /* Endpoint 列表 */
1261
1393
  .dshr-endpointList {
1262
- display: flex;
1263
- flex-direction: column;
1264
- gap: 4px;
1265
- padding: 12px 14px;
1394
+ display: flex;
1395
+ flex-direction: column;
1396
+ gap: 4px;
1397
+ padding: 12px 14px;
1266
1398
  }
1267
1399
 
1268
1400
  .dshr-endpointRow {
1269
- display: flex;
1270
- align-items: center;
1271
- gap: 8px;
1401
+ display: flex;
1402
+ align-items: center;
1403
+ gap: 8px;
1272
1404
  }
1273
1405
 
1274
1406
  .dshr-endpointLabel {
1275
- flex: none;
1276
- min-width: 88px;
1277
- padding: 3px 8px;
1278
- border-radius: 6px;
1279
- color: var(--rs-muted);
1280
- background: var(--rs-layer-2);
1281
- font: 11px var(--rs-mono);
1282
- text-align: center;
1407
+ flex: none;
1408
+ min-width: 88px;
1409
+ padding: 3px 8px;
1410
+ border-radius: 6px;
1411
+ color: var(--rs-muted);
1412
+ background: var(--rs-layer-2);
1413
+ font: 11px var(--rs-mono);
1414
+ text-align: center;
1283
1415
  }
1284
1416
 
1285
1417
  .dshr-endpointRow .dshr-input {
1286
- flex: 1 1 auto;
1287
- min-width: 0;
1288
- color: var(--rs-muted);
1418
+ flex: 1 1 auto;
1419
+ min-width: 0;
1420
+ color: var(--rs-muted);
1289
1421
  }
1290
1422
 
1291
1423
  .dshr-endpointNote {
1292
- padding: 2px 2px 0;
1424
+ padding: 2px 2px 0;
1293
1425
  }
1294
1426
 
1295
1427
  /* 图标按钮 */
1296
1428
  .dshr-iconBtn {
1297
- display: inline-flex;
1298
- flex: none;
1299
- width: 30px;
1300
- height: 30px;
1301
- align-items: center;
1302
- justify-content: center;
1303
- border: none;
1304
- border-radius: 6px;
1305
- color: var(--rs-muted);
1306
- background: transparent;
1307
- cursor: pointer;
1308
- transition: color .12s ease, background .12s ease;
1429
+ display: inline-flex;
1430
+ flex: none;
1431
+ width: 30px;
1432
+ height: 30px;
1433
+ align-items: center;
1434
+ justify-content: center;
1435
+ border: none;
1436
+ border-radius: 6px;
1437
+ color: var(--rs-muted);
1438
+ background: transparent;
1439
+ cursor: pointer;
1440
+ transition:
1441
+ color 0.12s ease,
1442
+ background 0.12s ease;
1309
1443
  }
1310
1444
 
1311
- .dshr-iconBtn:hover { color: var(--rs-accent); background: var(--rs-hover); }
1445
+ .dshr-iconBtn:hover {
1446
+ color: var(--rs-accent);
1447
+ background: var(--rs-hover);
1448
+ }
1312
1449
 
1313
- .dshr-iconBtn svg { display: block; }
1450
+ .dshr-iconBtn svg {
1451
+ display: block;
1452
+ }
1314
1453
 
1315
- .dshr-iconBtn-sm { width: 26px; height: 26px; }
1454
+ .dshr-iconBtn-sm {
1455
+ width: 26px;
1456
+ height: 26px;
1457
+ }
1316
1458
 
1317
1459
  /* 禁用态必须看得出来:纯图标按钮没有文字可读(不像「刷新中…」),
1318
1460
  只靠 hover 反馈会让人以为还能点。 */
1319
- .dshr-iconBtn:disabled { opacity: .4; cursor: default; }
1461
+ .dshr-iconBtn:disabled {
1462
+ opacity: 0.4;
1463
+ cursor: default;
1464
+ }
1320
1465
 
1321
- .dshr-iconBtn:disabled:hover { color: var(--rs-muted); background: transparent; }
1466
+ .dshr-iconBtn:disabled:hover {
1467
+ color: var(--rs-muted);
1468
+ background: transparent;
1469
+ }
1322
1470
 
1323
1471
  /* Require API key 行 */
1324
1472
  .dshr-requireRow {
1325
- display: flex;
1326
- align-items: center;
1327
- justify-content: space-between;
1328
- gap: 12px;
1329
- padding: 12px 14px;
1330
- border-bottom: 1px solid var(--rs-line);
1473
+ display: flex;
1474
+ align-items: center;
1475
+ justify-content: space-between;
1476
+ gap: 12px;
1477
+ padding: 12px 14px;
1478
+ border-bottom: 1px solid var(--rs-line);
1331
1479
  }
1332
1480
 
1333
1481
  .dshr-requireTitle {
1334
- margin: 0;
1335
- font-size: 13px;
1336
- font-weight: 600;
1482
+ margin: 0;
1483
+ font-size: 13px;
1484
+ font-weight: 600;
1337
1485
  }
1338
1486
 
1339
1487
  .dshr-requireDesc {
1340
- margin: 2px 0 0;
1341
- color: var(--rs-faint);
1342
- font-size: 12px;
1488
+ margin: 2px 0 0;
1489
+ color: var(--rs-faint);
1490
+ font-size: 12px;
1343
1491
  }
1344
1492
 
1345
1493
  /* 空状态 */
1346
1494
  .dshr-keyEmpty {
1347
- display: flex;
1348
- flex-direction: column;
1349
- align-items: center;
1350
- gap: 8px;
1351
- padding: 40px 16px 44px;
1495
+ display: flex;
1496
+ flex-direction: column;
1497
+ align-items: center;
1498
+ gap: 8px;
1499
+ padding: 40px 16px 44px;
1352
1500
  }
1353
1501
 
1354
1502
  .dshr-keyEmptyIcon {
1355
- display: inline-flex;
1356
- align-items: center;
1357
- justify-content: center;
1358
- width: 56px;
1359
- height: 56px;
1360
- margin-bottom: 6px;
1361
- border-radius: 50%;
1362
- color: var(--rs-accent);
1363
- background: color-mix(in srgb, var(--rs-accent) 10%, transparent);
1503
+ display: inline-flex;
1504
+ align-items: center;
1505
+ justify-content: center;
1506
+ width: 56px;
1507
+ height: 56px;
1508
+ margin-bottom: 6px;
1509
+ border-radius: 50%;
1510
+ color: var(--rs-accent);
1511
+ background: color-mix(in srgb, var(--rs-accent) 10%, transparent);
1364
1512
  }
1365
1513
 
1366
1514
  .dshr-keyEmptyTitle {
1367
- margin: 0;
1368
- font-size: 14px;
1369
- font-weight: 600;
1515
+ margin: 0;
1516
+ font-size: 14px;
1517
+ font-weight: 600;
1370
1518
  }
1371
1519
 
1372
1520
  .dshr-keyEmptyDesc {
1373
- margin: 0 0 8px;
1374
- color: var(--rs-faint);
1375
- font-size: 12px;
1521
+ margin: 0 0 8px;
1522
+ color: var(--rs-faint);
1523
+ font-size: 12px;
1376
1524
  }
1377
1525
 
1378
1526
  /* key 列表(flex 行,非表格) */
1379
1527
  .dshr-keyList {
1380
- display: flex;
1381
- flex-direction: column;
1528
+ display: flex;
1529
+ flex-direction: column;
1382
1530
  }
1383
1531
 
1384
1532
  .dshr-keyRow {
1385
- display: flex;
1386
- align-items: center;
1387
- justify-content: space-between;
1388
- gap: 12px;
1389
- padding: 12px 14px;
1390
- border-bottom: 1px solid var(--rs-line);
1391
- transition: opacity .12s ease;
1533
+ display: flex;
1534
+ align-items: center;
1535
+ justify-content: space-between;
1536
+ gap: 12px;
1537
+ padding: 12px 14px;
1538
+ border-bottom: 1px solid var(--rs-line);
1539
+ transition: opacity 0.12s ease;
1392
1540
  }
1393
1541
 
1394
- .dshr-keyRow:last-child { border-bottom: none; }
1395
- .dshr-keyRow-paused { opacity: .6; }
1542
+ .dshr-keyRow:last-child {
1543
+ border-bottom: none;
1544
+ }
1545
+ .dshr-keyRow-paused {
1546
+ opacity: 0.6;
1547
+ }
1396
1548
 
1397
1549
  .dshr-keyInfo {
1398
- min-width: 0;
1399
- flex: 1 1 auto;
1550
+ min-width: 0;
1551
+ flex: 1 1 auto;
1400
1552
  }
1401
1553
 
1402
1554
  .dshr-keyNameRow {
1403
- display: flex;
1404
- align-items: center;
1405
- gap: 4px;
1555
+ display: flex;
1556
+ align-items: center;
1557
+ gap: 4px;
1406
1558
  }
1407
1559
 
1408
1560
  .dshr-keyName {
1409
- margin: 0;
1410
- font-size: 13px;
1411
- font-weight: 600;
1561
+ margin: 0;
1562
+ font-size: 13px;
1563
+ font-weight: 600;
1412
1564
  }
1413
1565
 
1414
1566
  .dshr-keyValue {
1415
- display: flex;
1416
- align-items: center;
1417
- gap: 2px;
1418
- margin-top: 2px;
1567
+ display: flex;
1568
+ align-items: center;
1569
+ gap: 2px;
1570
+ margin-top: 2px;
1419
1571
  }
1420
1572
 
1421
1573
  .dshr-keyValue code {
1422
- overflow: hidden;
1423
- color: var(--rs-muted);
1424
- text-overflow: ellipsis;
1425
- white-space: nowrap;
1574
+ overflow: hidden;
1575
+ color: var(--rs-muted);
1576
+ text-overflow: ellipsis;
1577
+ white-space: nowrap;
1426
1578
  }
1427
1579
 
1428
1580
  .dshr-keyCreated {
1429
- margin: 3px 0 0;
1430
- color: var(--rs-faint);
1431
- font-size: 11px;
1581
+ margin: 3px 0 0;
1582
+ color: var(--rs-faint);
1583
+ font-size: 11px;
1432
1584
  }
1433
1585
 
1434
- .dshr-keyPaused { color: var(--rs-warn); }
1586
+ .dshr-keyPaused {
1587
+ color: var(--rs-warn);
1588
+ }
1435
1589
 
1436
1590
  .dshr-keyOps {
1437
- display: flex;
1438
- flex: none;
1439
- align-items: center;
1440
- gap: 4px;
1591
+ display: flex;
1592
+ flex: none;
1593
+ align-items: center;
1594
+ gap: 4px;
1441
1595
  }
1442
1596
 
1443
1597
  /* 删除按钮 hover 才明显(9router:group-hover 显示) */
1444
1598
  .dshr-keyDelete {
1445
- color: var(--rs-muted);
1446
- opacity: 0;
1447
- transition: opacity .12s ease, color .12s ease, background .12s ease;
1599
+ color: var(--rs-muted);
1600
+ opacity: 0;
1601
+ transition:
1602
+ opacity 0.12s ease,
1603
+ color 0.12s ease,
1604
+ background 0.12s ease;
1448
1605
  }
1449
1606
 
1450
- .dshr-keyRow:hover .dshr-keyDelete { opacity: 1; }
1451
- .dshr-keyDelete:focus-visible { opacity: 1; }
1607
+ .dshr-keyRow:hover .dshr-keyDelete {
1608
+ opacity: 1;
1609
+ }
1610
+ .dshr-keyDelete:focus-visible {
1611
+ opacity: 1;
1612
+ }
1452
1613
  .dshr-keyDelete:hover {
1453
- color: var(--rs-danger);
1454
- background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
1614
+ color: var(--rs-danger);
1615
+ background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
1455
1616
  }
1456
1617
 
1457
1618
  /* 弹窗表单 */
1458
1619
  .dshr-modalForm {
1459
- display: flex;
1460
- flex-direction: column;
1461
- gap: 14px;
1620
+ display: flex;
1621
+ flex-direction: column;
1622
+ gap: 14px;
1462
1623
  }
1463
1624
 
1464
1625
  .dshr-fieldLabel {
1465
- font-size: 12px;
1466
- font-weight: 650;
1467
- color: var(--rs-text);
1468
- margin-top: 4px;
1626
+ font-size: 12px;
1627
+ font-weight: 650;
1628
+ color: var(--rs-text);
1629
+ margin-top: 4px;
1469
1630
  }
1470
1631
 
1471
1632
  .dshr-warnBox {
1472
- padding: 12px 14px;
1473
- border: 1px solid color-mix(in srgb, var(--rs-warn) 40%, transparent);
1474
- border-radius: 8px;
1475
- background: color-mix(in srgb, var(--rs-warn) 8%, transparent);
1633
+ padding: 12px 14px;
1634
+ border: 1px solid color-mix(in srgb, var(--rs-warn) 40%, transparent);
1635
+ border-radius: 8px;
1636
+ background: color-mix(in srgb, var(--rs-warn) 8%, transparent);
1476
1637
  }
1477
1638
 
1478
1639
  .dshr-warnTitle {
1479
- margin: 0 0 4px;
1480
- color: var(--rs-warn);
1481
- font-size: 13px;
1482
- font-weight: 700;
1640
+ margin: 0 0 4px;
1641
+ color: var(--rs-warn);
1642
+ font-size: 13px;
1643
+ font-weight: 700;
1483
1644
  }
1484
1645
 
1485
1646
  .dshr-warnDesc {
1486
- margin: 0;
1487
- color: var(--rs-muted);
1488
- font-size: 12px;
1647
+ margin: 0;
1648
+ color: var(--rs-muted);
1649
+ font-size: 12px;
1489
1650
  }
1490
1651
 
1491
- .dshr-createdRow { padding: 0; }
1652
+ .dshr-createdRow {
1653
+ padding: 0;
1654
+ }
1492
1655
 
1493
- .dshr-createdRow .dshr-input { color: var(--rs-text); }
1656
+ .dshr-createdRow .dshr-input {
1657
+ color: var(--rs-text);
1658
+ }
1494
1659
 
1495
- .dshr-fullButton { width: 100%; }
1660
+ .dshr-fullButton {
1661
+ width: 100%;
1662
+ }
1496
1663
 
1497
1664
  /* ============================================================
1498
1665
  dsh-router — 供应商详情(9router 风格)
@@ -1500,270 +1667,324 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
1500
1667
 
1501
1668
  /* Header */
1502
1669
  .dshr-providerHead {
1503
- display: flex;
1504
- flex-direction: column;
1505
- gap: 10px;
1670
+ display: flex;
1671
+ flex-direction: column;
1672
+ gap: 10px;
1506
1673
  }
1507
1674
 
1508
1675
  .dshr-backLink {
1509
- display: inline-flex;
1510
- align-items: center;
1511
- align-self: flex-start;
1512
- gap: 4px;
1513
- border: none;
1514
- padding: 2px 0;
1515
- color: var(--rs-muted);
1516
- background: transparent;
1517
- font-size: 12px;
1518
- cursor: pointer;
1519
- transition: color .12s ease;
1676
+ display: inline-flex;
1677
+ align-items: center;
1678
+ align-self: flex-start;
1679
+ gap: 4px;
1680
+ border: none;
1681
+ padding: 2px 0;
1682
+ color: var(--rs-muted);
1683
+ background: transparent;
1684
+ font-size: 12px;
1685
+ cursor: pointer;
1686
+ transition: color 0.12s ease;
1520
1687
  }
1521
1688
 
1522
- .dshr-backLink:hover { color: var(--rs-accent); }
1689
+ .dshr-backLink:hover {
1690
+ color: var(--rs-accent);
1691
+ }
1523
1692
 
1524
1693
  .dshr-providerTitleRow {
1525
- display: flex;
1526
- align-items: center;
1527
- gap: 12px;
1694
+ display: flex;
1695
+ align-items: center;
1696
+ gap: 12px;
1528
1697
  }
1529
1698
 
1530
1699
  .dshr-providerIcon {
1531
- display: inline-flex;
1532
- flex: none;
1533
- width: 44px;
1534
- height: 44px;
1535
- align-items: center;
1536
- justify-content: center;
1537
- border-radius: 10px;
1700
+ display: inline-flex;
1701
+ flex: none;
1702
+ width: 44px;
1703
+ height: 44px;
1704
+ align-items: center;
1705
+ justify-content: center;
1706
+ border-radius: 10px;
1538
1707
  }
1539
1708
 
1540
1709
  .dshr-providerImg {
1541
- width: 100%;
1542
- height: 100%;
1543
- object-fit: contain;
1710
+ width: 100%;
1711
+ height: 100%;
1712
+ object-fit: contain;
1544
1713
  }
1545
1714
 
1546
1715
  .dshr-providerName {
1547
- margin: 0;
1548
- font-size: 20px;
1549
- font-weight: 700;
1550
- letter-spacing: -.01em;
1716
+ margin: 0;
1717
+ font-size: 20px;
1718
+ font-weight: 700;
1719
+ letter-spacing: -0.01em;
1551
1720
  }
1552
1721
 
1553
1722
  .dshr-providerCount {
1554
- margin: 2px 0 0;
1555
- color: var(--rs-muted);
1556
- font-size: 12px;
1723
+ margin: 2px 0 0;
1724
+ color: var(--rs-muted);
1725
+ font-size: 12px;
1557
1726
  }
1558
1727
 
1559
1728
  /* 链接池空状态 */
1560
1729
  .dshr-linkEmpty {
1561
- display: flex;
1562
- flex-direction: column;
1563
- align-items: center;
1564
- gap: 10px;
1565
- padding: 36px 16px 40px;
1730
+ display: flex;
1731
+ flex-direction: column;
1732
+ align-items: center;
1733
+ gap: 10px;
1734
+ padding: 36px 16px 40px;
1566
1735
  }
1567
1736
 
1568
1737
  .dshr-linkEmptyIcon {
1569
- display: inline-flex;
1570
- align-items: center;
1571
- justify-content: center;
1572
- width: 52px;
1573
- height: 52px;
1574
- border-radius: 50%;
1575
- color: var(--rs-accent);
1576
- background: color-mix(in srgb, var(--rs-accent) 10%, transparent);
1738
+ display: inline-flex;
1739
+ align-items: center;
1740
+ justify-content: center;
1741
+ width: 52px;
1742
+ height: 52px;
1743
+ border-radius: 50%;
1744
+ color: var(--rs-accent);
1745
+ background: color-mix(in srgb, var(--rs-accent) 10%, transparent);
1577
1746
  }
1578
1747
 
1579
- .dshr-linkEmptyText { text-align: center; }
1748
+ .dshr-linkEmptyText {
1749
+ text-align: center;
1750
+ }
1580
1751
 
1581
1752
  .dshr-linkEmptyTitle {
1582
- margin: 0;
1583
- font-size: 14px;
1584
- font-weight: 600;
1753
+ margin: 0;
1754
+ font-size: 14px;
1755
+ font-weight: 600;
1585
1756
  }
1586
1757
 
1587
1758
  .dshr-linkEmptyDesc {
1588
- margin: 2px 0 0;
1589
- color: var(--rs-faint);
1590
- font-size: 12px;
1759
+ margin: 2px 0 0;
1760
+ color: var(--rs-faint);
1761
+ font-size: 12px;
1591
1762
  }
1592
1763
 
1593
1764
  /* 链接列表(9router ConnectionRow 风格行) */
1594
1765
  .dshr-linkList {
1595
- display: flex;
1596
- flex-direction: column;
1766
+ display: flex;
1767
+ flex-direction: column;
1597
1768
  }
1598
1769
 
1599
1770
  .dshr-linkRow {
1600
- display: flex;
1601
- align-items: center;
1602
- justify-content: space-between;
1603
- gap: 12px;
1604
- padding: 12px 14px;
1605
- border-bottom: 1px solid var(--rs-line);
1606
- transition: background .1s ease;
1771
+ display: flex;
1772
+ align-items: center;
1773
+ justify-content: space-between;
1774
+ gap: 12px;
1775
+ padding: 12px 14px;
1776
+ border-bottom: 1px solid var(--rs-line);
1777
+ transition: background 0.1s ease;
1607
1778
  }
1608
1779
 
1609
- .dshr-linkRow:last-child { border-bottom: none; }
1610
- .dshr-linkRow:hover { background: var(--rs-hover); }
1611
- .dshr-linkRow[draggable='true'] { cursor: grab; }
1612
- .dshr-linkRow[draggable='true']:active { cursor: grabbing; }
1613
- .dshr-linkRowDragging { opacity: .45; background: var(--rs-hover); }
1780
+ .dshr-linkRow:last-child {
1781
+ border-bottom: none;
1782
+ }
1783
+ .dshr-linkRow:hover {
1784
+ background: var(--rs-hover);
1785
+ }
1786
+ .dshr-linkRow[draggable="true"] {
1787
+ cursor: grab;
1788
+ }
1789
+ .dshr-linkRow[draggable="true"]:active {
1790
+ cursor: grabbing;
1791
+ }
1792
+ .dshr-linkRowDragging {
1793
+ opacity: 0.45;
1794
+ background: var(--rs-hover);
1795
+ }
1614
1796
 
1615
1797
  .dshr-linkGrip {
1616
- display: inline-flex;
1617
- align-items: center;
1618
- justify-content: center;
1619
- color: var(--rs-muted);
1620
- flex: 0 0 auto;
1621
- cursor: grab;
1622
- padding: 4px 2px;
1623
- user-select: none;
1624
- }
1625
- .dshr-linkGrip:active { cursor: grabbing; }
1626
- .dshr-linkGrip svg { opacity: .65; }
1627
- .dshr-linkRow:hover .dshr-linkGrip svg { opacity: 1; }
1798
+ display: inline-flex;
1799
+ align-items: center;
1800
+ justify-content: center;
1801
+ color: var(--rs-muted);
1802
+ flex: 0 0 auto;
1803
+ cursor: grab;
1804
+ padding: 4px 2px;
1805
+ user-select: none;
1806
+ }
1807
+ .dshr-linkGrip:active {
1808
+ cursor: grabbing;
1809
+ }
1810
+ .dshr-linkGrip svg {
1811
+ opacity: 0.65;
1812
+ }
1813
+ .dshr-linkRow:hover .dshr-linkGrip svg {
1814
+ opacity: 1;
1815
+ }
1628
1816
 
1629
1817
  .dshr-linkMain {
1630
- min-width: 0;
1631
- flex: 1 1 auto;
1818
+ min-width: 0;
1819
+ flex: 1 1 auto;
1632
1820
  }
1633
1821
 
1634
1822
  .dshr-linkTitleLine {
1635
- display: flex;
1636
- align-items: center;
1637
- gap: 8px;
1823
+ display: flex;
1824
+ align-items: center;
1825
+ gap: 8px;
1638
1826
  }
1639
1827
 
1640
1828
  .dshr-linkName {
1641
- overflow: hidden;
1642
- font-size: 13px;
1643
- font-weight: 600;
1644
- text-overflow: ellipsis;
1645
- white-space: nowrap;
1829
+ overflow: hidden;
1830
+ font-size: 13px;
1831
+ font-weight: 600;
1832
+ text-overflow: ellipsis;
1833
+ white-space: nowrap;
1646
1834
  }
1647
1835
 
1648
1836
  .dshr-linkSub {
1649
- display: flex;
1650
- flex-wrap: wrap;
1651
- align-items: center;
1652
- gap: 6px;
1653
- margin-top: 3px;
1654
- color: var(--rs-faint);
1655
- font-size: 11px;
1837
+ display: flex;
1838
+ flex-wrap: wrap;
1839
+ align-items: center;
1840
+ gap: 6px;
1841
+ margin-top: 3px;
1842
+ color: var(--rs-faint);
1843
+ font-size: 11px;
1656
1844
  }
1657
1845
 
1658
- .dshr-linkUid { color: var(--rs-faint); }
1659
- .dshr-linkCredits { color: var(--rs-muted); }
1660
- .dshr-linkErr { color: var(--rs-warn); }
1661
- .dshr-linkCooling { color: var(--rs-warn); }
1662
- .dshr-linkDot { color: var(--rs-faint); opacity: .6; }
1846
+ .dshr-linkUid {
1847
+ color: var(--rs-faint);
1848
+ }
1849
+ .dshr-linkCredits {
1850
+ color: var(--rs-muted);
1851
+ }
1852
+ .dshr-linkErr {
1853
+ color: var(--rs-warn);
1854
+ }
1855
+ .dshr-linkCooling {
1856
+ color: var(--rs-warn);
1857
+ }
1858
+ .dshr-linkDot {
1859
+ color: var(--rs-faint);
1860
+ opacity: 0.6;
1861
+ }
1663
1862
 
1664
1863
  .dshr-linkOps {
1665
- display: flex;
1666
- flex: none;
1667
- align-items: center;
1864
+ display: flex;
1865
+ flex: none;
1866
+ align-items: center;
1668
1867
  }
1669
1868
 
1670
1869
  /* 删除链接 hover 显示 + 红色 */
1671
1870
  .dshr-linkDelete {
1672
- color: var(--rs-muted);
1673
- opacity: 0;
1674
- transition: opacity .12s ease, color .12s ease, background .12s ease;
1871
+ color: var(--rs-muted);
1872
+ opacity: 0;
1873
+ transition:
1874
+ opacity 0.12s ease,
1875
+ color 0.12s ease,
1876
+ background 0.12s ease;
1675
1877
  }
1676
1878
 
1677
- .dshr-linkRow:hover .dshr-linkDelete { opacity: 1; }
1678
- .dshr-linkDelete:focus-visible { opacity: 1; }
1879
+ .dshr-linkRow:hover .dshr-linkDelete {
1880
+ opacity: 1;
1881
+ }
1882
+ .dshr-linkDelete:focus-visible {
1883
+ opacity: 1;
1884
+ }
1679
1885
  .dshr-linkDelete:hover {
1680
- color: var(--rs-danger);
1681
- background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
1886
+ color: var(--rs-danger);
1887
+ background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
1682
1888
  }
1683
1889
 
1684
1890
  /* 改名:与删除一致,hover 行才显示;编辑中保持可见(否则保存按钮被藏住) */
1685
1891
  .dshr-linkEdit {
1686
- color: var(--rs-muted);
1687
- opacity: 0;
1688
- transition: opacity .12s ease, color .12s ease, background .12s ease;
1892
+ color: var(--rs-muted);
1893
+ opacity: 0;
1894
+ transition:
1895
+ opacity 0.12s ease,
1896
+ color 0.12s ease,
1897
+ background 0.12s ease;
1898
+ }
1899
+ .dshr-linkRow:hover .dshr-linkEdit {
1900
+ opacity: 1;
1901
+ }
1902
+ .dshr-linkEdit:focus-visible {
1903
+ opacity: 1;
1689
1904
  }
1690
- .dshr-linkRow:hover .dshr-linkEdit { opacity: 1; }
1691
- .dshr-linkEdit:focus-visible { opacity: 1; }
1692
1905
  .dshr-linkEdit:hover {
1693
- color: var(--rs-accent);
1694
- background: color-mix(in srgb, var(--rs-accent) 14%, transparent);
1906
+ color: var(--rs-accent);
1907
+ background: color-mix(in srgb, var(--rs-accent) 14%, transparent);
1908
+ }
1909
+ .dshr-linkEdit.dshr-linkEdit-active {
1910
+ opacity: 1;
1695
1911
  }
1696
- .dshr-linkEdit.dshr-linkEdit-active { opacity: 1; }
1697
1912
 
1698
1913
  /* 模型 chips(9router ModelRow 风格) */
1699
1914
  .dshr-modelChips {
1700
- display: flex;
1701
- flex-wrap: wrap;
1702
- gap: 8px;
1703
- padding: 14px;
1915
+ display: flex;
1916
+ flex-wrap: wrap;
1917
+ gap: 8px;
1918
+ padding: 14px;
1704
1919
  }
1705
1920
 
1706
1921
  .dshr-modelChip {
1707
- display: inline-flex;
1708
- align-items: center;
1709
- gap: 6px;
1710
- padding: 6px 10px;
1711
- border: 1px solid var(--rs-line);
1712
- border-radius: 8px;
1713
- color: var(--rs-text);
1714
- background: var(--rs-layer-1);
1715
- font-size: 12px;
1716
- cursor: pointer;
1717
- transition: border-color .12s ease, background .12s ease, color .12s ease;
1922
+ display: inline-flex;
1923
+ align-items: center;
1924
+ gap: 6px;
1925
+ padding: 6px 10px;
1926
+ border: 1px solid var(--rs-line);
1927
+ border-radius: 8px;
1928
+ color: var(--rs-text);
1929
+ background: var(--rs-layer-1);
1930
+ font-size: 12px;
1931
+ cursor: pointer;
1932
+ transition:
1933
+ border-color 0.12s ease,
1934
+ background 0.12s ease,
1935
+ color 0.12s ease;
1718
1936
  }
1719
1937
 
1720
1938
  .dshr-modelChip:hover {
1721
- border-color: var(--rs-accent);
1722
- background: color-mix(in srgb, var(--rs-accent) 6%, transparent);
1939
+ border-color: var(--rs-accent);
1940
+ background: color-mix(in srgb, var(--rs-accent) 6%, transparent);
1723
1941
  }
1724
1942
 
1725
- .dshr-modelChip:disabled { opacity: .6; cursor: default; }
1943
+ .dshr-modelChip:disabled {
1944
+ opacity: 0.6;
1945
+ cursor: default;
1946
+ }
1726
1947
 
1727
1948
  .dshr-modelChipId {
1728
- font-family: var(--rs-mono);
1729
- font-size: 11px;
1949
+ font-family: var(--rs-mono);
1950
+ font-size: 11px;
1730
1951
  }
1731
1952
 
1732
1953
  .dshr-modelChipCtx {
1733
- flex: none;
1734
- color: var(--rs-faint);
1735
- font-size: 10px;
1954
+ flex: none;
1955
+ color: var(--rs-faint);
1956
+ font-size: 10px;
1736
1957
  }
1737
1958
 
1738
1959
  .dshr-modelChip-off {
1739
- border-style: dashed;
1740
- color: var(--rs-faint);
1741
- opacity: .8;
1960
+ border-style: dashed;
1961
+ color: var(--rs-faint);
1962
+ opacity: 0.8;
1742
1963
  }
1743
1964
 
1744
1965
  .dshr-modelChip-off:hover {
1745
- color: var(--rs-accent);
1746
- border-color: var(--rs-accent);
1966
+ color: var(--rs-accent);
1967
+ border-color: var(--rs-accent);
1747
1968
  }
1748
1969
 
1749
1970
  .dshr-modelChipRestore {
1750
- color: var(--rs-accent);
1751
- font-size: 10px;
1971
+ color: var(--rs-accent);
1972
+ font-size: 10px;
1752
1973
  }
1753
1974
 
1754
1975
  /* 已禁用区 */
1755
1976
  .dshr-disabledModels {
1756
- width: 100%;
1977
+ width: 100%;
1757
1978
  }
1758
1979
 
1759
1980
  .dshr-disabledLabel {
1760
- margin: 4px 0 0;
1761
- color: var(--rs-faint);
1762
- font-size: 11px;
1981
+ margin: 4px 0 0;
1982
+ color: var(--rs-faint);
1983
+ font-size: 11px;
1763
1984
  }
1764
1985
 
1765
1986
  .dshr-disabledModels .dshr-modelChips {
1766
- padding: 8px 0 0;
1987
+ padding: 8px 0 0;
1767
1988
  }
1768
1989
 
1769
1990
  /* ============================================================
@@ -1772,561 +1993,609 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
1772
1993
 
1773
1994
  /* 卡片头操作组 */
1774
1995
  .dshr-cardActions {
1775
- display: flex;
1776
- align-items: center;
1777
- gap: 6px;
1778
- margin-left: auto;
1996
+ display: flex;
1997
+ align-items: center;
1998
+ gap: 6px;
1999
+ margin-left: auto;
1779
2000
  }
1780
2001
 
1781
2002
  /* 连接池策略选择 */
1782
- .dshr-poolStrategy {
1783
- display: inline-flex;
1784
- align-items: center;
1785
- gap: 6px;
1786
- font-size: 12px;
1787
- }
1788
2003
  .dshr-select {
1789
- appearance: none;
1790
- border: 1px solid var(--rs-line);
1791
- border-radius: 6px;
1792
- background: var(--rs-surface, transparent);
1793
- color: inherit;
1794
- font-size: 12px;
1795
- padding: 3px 22px 3px 8px;
1796
- cursor: pointer;
1797
- background-image: linear-gradient(45deg, transparent 50%, var(--rs-muted) 50%), linear-gradient(135deg, var(--rs-muted) 50%, transparent 50%);
1798
- background-position: calc(100% - 12px) 55%, calc(100% - 7px) 55%;
1799
- background-size: 5px 5px;
1800
- background-repeat: no-repeat;
1801
- }
1802
- .dshr-select:focus { outline: none; border-color: var(--rs-accent, #4c7dff); }
1803
-
2004
+ appearance: none;
2005
+ border: 1px solid var(--rs-line);
2006
+ border-radius: 6px;
2007
+ background: var(--rs-surface, transparent);
2008
+ color: inherit;
2009
+ font-size: 12px;
2010
+ padding: 3px 22px 3px 8px;
2011
+ cursor: pointer;
2012
+ background-image:
2013
+ linear-gradient(45deg, transparent 50%, var(--rs-muted) 50%),
2014
+ linear-gradient(135deg, var(--rs-muted) 50%, transparent 50%);
2015
+ background-position:
2016
+ calc(100% - 12px) 55%,
2017
+ calc(100% - 7px) 55%;
2018
+ background-size: 5px 5px;
2019
+ background-repeat: no-repeat;
2020
+ }
2021
+ .dshr-select:focus {
2022
+ outline: none;
2023
+ border-color: var(--rs-accent, #4c7dff);
2024
+ }
1804
2025
 
1805
2026
  /* 模型 chip 包装(状态边框) */
1806
2027
  .dshr-modelChipWrap {
1807
- position: relative;
1808
- display: inline-flex;
1809
- align-items: center;
1810
- border: 1px solid var(--rs-line);
1811
- border-radius: 8px;
1812
- background: var(--rs-layer-1);
1813
- transition: border-color .12s ease, background .12s ease;
2028
+ position: relative;
2029
+ display: inline-flex;
2030
+ align-items: center;
2031
+ border: 1px solid var(--rs-line);
2032
+ border-radius: 8px;
2033
+ background: var(--rs-layer-1);
2034
+ transition:
2035
+ border-color 0.12s ease,
2036
+ background 0.12s ease;
1814
2037
  }
1815
2038
 
1816
2039
  .dshr-modelChipWrap:hover {
1817
- border-color: var(--rs-accent);
1818
- background: color-mix(in srgb, var(--rs-accent) 6%, transparent);
2040
+ border-color: var(--rs-accent);
2041
+ background: color-mix(in srgb, var(--rs-accent) 6%, transparent);
1819
2042
  }
1820
2043
 
1821
- .dshr-modelChipWrap.dshr-modelChip-ok { border-color: var(--rs-ok); }
1822
- .dshr-modelChipWrap.dshr-modelChip-err { border-color: var(--rs-danger); }
2044
+ .dshr-modelChipWrap.dshr-modelChip-ok {
2045
+ border-color: var(--rs-ok);
2046
+ }
2047
+ .dshr-modelChipWrap.dshr-modelChip-err {
2048
+ border-color: var(--rs-danger);
2049
+ }
1823
2050
 
1824
2051
  /* chip 本体(点击禁用) */
1825
2052
  .dshr-modelChipWrap .dshr-modelChip {
1826
- display: inline-flex;
1827
- align-items: center;
1828
- gap: 6px;
1829
- padding: 6px 8px 6px 6px;
1830
- border: none;
1831
- border-radius: 8px;
1832
- color: var(--rs-text);
1833
- background: transparent;
1834
- font-size: 12px;
1835
- cursor: pointer;
2053
+ display: inline-flex;
2054
+ align-items: center;
2055
+ gap: 6px;
2056
+ padding: 6px 8px 6px 6px;
2057
+ border: none;
2058
+ border-radius: 8px;
2059
+ color: var(--rs-text);
2060
+ background: transparent;
2061
+ font-size: 12px;
2062
+ cursor: pointer;
1836
2063
  }
1837
2064
 
1838
2065
  .dshr-modelChipStatus {
1839
- display: inline-flex;
1840
- flex: none;
1841
- align-items: center;
1842
- justify-content: center;
1843
- color: var(--rs-faint);
2066
+ display: inline-flex;
2067
+ flex: none;
2068
+ align-items: center;
2069
+ justify-content: center;
2070
+ color: var(--rs-faint);
1844
2071
  }
1845
2072
 
1846
- .dshr-modelChipWrap.dshr-modelChip-ok .dshr-modelChipStatus { color: var(--rs-ok); }
1847
- .dshr-modelChipWrap.dshr-modelChip-err .dshr-modelChipStatus { color: var(--rs-danger); }
2073
+ .dshr-modelChipWrap.dshr-modelChip-ok .dshr-modelChipStatus {
2074
+ color: var(--rs-ok);
2075
+ }
2076
+ .dshr-modelChipWrap.dshr-modelChip-err .dshr-modelChipStatus {
2077
+ color: var(--rs-danger);
2078
+ }
1848
2079
 
1849
2080
  /* chip 右侧操作(hover 显示) */
1850
2081
  .dshr-modelChipOps {
1851
- display: inline-flex;
1852
- align-items: center;
1853
- gap: 0;
1854
- padding-right: 4px;
1855
- opacity: 0;
1856
- transition: opacity .12s ease;
2082
+ display: inline-flex;
2083
+ align-items: center;
2084
+ gap: 0;
2085
+ padding-right: 4px;
2086
+ opacity: 0;
2087
+ transition: opacity 0.12s ease;
1857
2088
  }
1858
2089
 
1859
2090
  .dshr-modelChipWrap:hover .dshr-modelChipOps,
1860
- .dshr-modelChipOps:focus-within { opacity: 1; }
2091
+ .dshr-modelChipOps:focus-within {
2092
+ opacity: 1;
2093
+ }
1861
2094
 
1862
2095
  /* 旧 .dshr-modelChip 独立样式(disabled 区仍用) */
1863
2096
  .dshr-modelChip {
1864
- display: inline-flex;
1865
- align-items: center;
1866
- gap: 6px;
1867
- padding: 6px 10px;
1868
- border: 1px solid var(--rs-line);
1869
- border-radius: 8px;
1870
- color: var(--rs-text);
1871
- background: var(--rs-layer-1);
1872
- font-size: 12px;
1873
- cursor: pointer;
1874
- transition: border-color .12s ease, background .12s ease, color .12s ease;
2097
+ display: inline-flex;
2098
+ align-items: center;
2099
+ gap: 6px;
2100
+ padding: 6px 10px;
2101
+ border: 1px solid var(--rs-line);
2102
+ border-radius: 8px;
2103
+ color: var(--rs-text);
2104
+ background: var(--rs-layer-1);
2105
+ font-size: 12px;
2106
+ cursor: pointer;
2107
+ transition:
2108
+ border-color 0.12s ease,
2109
+ background 0.12s ease,
2110
+ color 0.12s ease;
1875
2111
  }
1876
2112
 
1877
2113
  .dshr-modelChip:hover {
1878
- border-color: var(--rs-accent);
1879
- background: color-mix(in srgb, var(--rs-accent) 6%, transparent);
2114
+ border-color: var(--rs-accent);
2115
+ background: color-mix(in srgb, var(--rs-accent) 6%, transparent);
1880
2116
  }
1881
2117
 
1882
- .dshr-modelChip:disabled { opacity: .6; cursor: default; }
2118
+ .dshr-modelChip:disabled {
2119
+ opacity: 0.6;
2120
+ cursor: default;
2121
+ }
1883
2122
 
1884
2123
  .dshr-modelChipId {
1885
- font-family: var(--rs-mono);
1886
- font-size: 11px;
2124
+ font-family: var(--rs-mono);
2125
+ font-size: 11px;
1887
2126
  }
1888
2127
 
1889
2128
  .dshr-modelChipCtx {
1890
- flex: none;
1891
- color: var(--rs-faint);
1892
- font-size: 10px;
2129
+ flex: none;
2130
+ color: var(--rs-faint);
2131
+ font-size: 10px;
1893
2132
  }
1894
2133
 
1895
2134
  .dshr-modelChip-off {
1896
- border-style: dashed;
1897
- color: var(--rs-faint);
1898
- opacity: .8;
2135
+ border-style: dashed;
2136
+ color: var(--rs-faint);
2137
+ opacity: 0.8;
1899
2138
  }
1900
2139
 
1901
2140
  .dshr-modelChip-off:hover {
1902
- color: var(--rs-accent);
1903
- border-color: var(--rs-accent);
2141
+ color: var(--rs-accent);
2142
+ border-color: var(--rs-accent);
1904
2143
  }
1905
2144
 
1906
2145
  .dshr-modelChipRestore {
1907
- color: var(--rs-accent);
1908
- font-size: 10px;
2146
+ color: var(--rs-accent);
2147
+ font-size: 10px;
1909
2148
  }
1910
2149
 
1911
2150
  /* 计数徽标跟在标题/操作按钮右侧(模型卡片) */
1912
2151
  .dshr-cardMetaAfter {
1913
- margin-left: 0;
2152
+ margin-left: 0;
1914
2153
  }
1915
2154
 
1916
2155
  /* 测试 loading 转圈 */
1917
2156
  .dshr-spin {
1918
- display: inline-flex;
1919
- animation: dshrSpin .8s linear infinite;
2157
+ display: inline-flex;
2158
+ animation: dshrSpin 0.8s linear infinite;
1920
2159
  }
1921
2160
 
1922
2161
  @keyframes dshrSpin {
1923
- to { transform: rotate(360deg); }
2162
+ to {
2163
+ transform: rotate(360deg);
2164
+ }
1924
2165
  }
1925
2166
 
1926
2167
  /* 供应商标题行编辑按钮(靠右) */
1927
2168
  .dshr-providerEdit {
1928
- margin-left: auto;
2169
+ margin-left: auto;
1929
2170
  }
1930
2171
 
1931
2172
  /* 模型搜索栏 */
1932
2173
  .dshr-modelSearch {
1933
- display: flex;
1934
- align-items: center;
1935
- gap: 6px;
1936
- padding: 8px 14px 0;
2174
+ display: flex;
2175
+ align-items: center;
2176
+ gap: 6px;
2177
+ padding: 8px 14px 0;
1937
2178
  }
1938
2179
 
1939
2180
  .dshr-modelSearchIcon {
1940
- display: inline-flex;
1941
- flex: none;
1942
- align-items: center;
1943
- justify-content: center;
1944
- color: var(--rs-faint);
2181
+ display: inline-flex;
2182
+ flex: none;
2183
+ align-items: center;
2184
+ justify-content: center;
2185
+ color: var(--rs-faint);
1945
2186
  }
1946
2187
 
1947
2188
  .dshr-modelSearch .dshr-input {
1948
- flex: 1 1 auto;
1949
- min-width: 0;
2189
+ flex: 1 1 auto;
2190
+ min-width: 0;
1950
2191
  }
1951
2192
 
1952
2193
  /* 自定义模型删除按钮(hover 红色) */
1953
2194
  .dshr-modelDelete {
1954
- color: var(--rs-muted);
1955
- transition: color .12s ease, background .12s ease;
2195
+ color: var(--rs-muted);
2196
+ transition:
2197
+ color 0.12s ease,
2198
+ background 0.12s ease;
1956
2199
  }
1957
2200
 
1958
2201
  .dshr-modelDelete:hover {
1959
- color: var(--rs-danger);
1960
- background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
2202
+ color: var(--rs-danger);
2203
+ background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
1961
2204
  }
1962
2205
 
1963
2206
  /* 全局浮窗提示(toast) */
1964
2207
  .dshr-toast {
1965
- position: fixed;
1966
- z-index: 2000;
1967
- left: 50%;
1968
- bottom: 28px;
1969
- transform: translateX(-50%);
1970
- padding: 8px 16px;
1971
- border-radius: 8px;
1972
- color: var(--rs-text);
1973
- background: var(--rs-layer-2);
1974
- border: 1px solid var(--rs-line-strong);
1975
- box-shadow: 0 6px 20px rgb(0 0 0 / .18);
1976
- font-size: 12px;
1977
- font-weight: 500;
1978
- white-space: nowrap;
1979
- animation: dshrToastIn .18s ease;
2208
+ position: fixed;
2209
+ z-index: 2000;
2210
+ left: 50%;
2211
+ bottom: 28px;
2212
+ transform: translateX(-50%);
2213
+ padding: 8px 16px;
2214
+ border-radius: 8px;
2215
+ color: var(--rs-text);
2216
+ background: var(--rs-layer-2);
2217
+ border: 1px solid var(--rs-line-strong);
2218
+ box-shadow: 0 6px 20px rgb(0 0 0 / 0.18);
2219
+ font-size: 12px;
2220
+ font-weight: 500;
2221
+ white-space: nowrap;
2222
+ animation: dshrToastIn 0.18s ease;
1980
2223
  }
1981
2224
 
1982
2225
  @keyframes dshrToastIn {
1983
- from { opacity: 0; transform: translateX(-50%) translateY(8px); }
1984
- to { opacity: 1; transform: translateX(-50%) translateY(0); }
2226
+ from {
2227
+ opacity: 0;
2228
+ transform: translateX(-50%) translateY(8px);
2229
+ }
2230
+ to {
2231
+ opacity: 1;
2232
+ transform: translateX(-50%) translateY(0);
2233
+ }
1985
2234
  }
1986
2235
 
1987
2236
  /* ============ 组合(9router combos 布局交互) ============ */
1988
- .dshr-comboIntro { overflow: visible; }
2237
+ .dshr-comboIntro {
2238
+ overflow: visible;
2239
+ }
1989
2240
 
1990
2241
  .dshr-comboIntroDesc {
1991
- font-size: 12px;
1992
- white-space: nowrap;
1993
- overflow: hidden;
1994
- text-overflow: ellipsis;
2242
+ font-size: 12px;
2243
+ white-space: nowrap;
2244
+ overflow: hidden;
2245
+ text-overflow: ellipsis;
1995
2246
  }
1996
2247
 
1997
2248
  .dshr-comboIntroBody {
1998
- display: flex;
1999
- flex-wrap: wrap;
2000
- align-items: center;
2001
- gap: 8px 14px;
2002
- padding: 10px 14px;
2003
- font-size: 12px;
2004
- color: var(--rs-muted);
2005
- border-top: 1px solid var(--rs-line);
2249
+ display: flex;
2250
+ flex-wrap: wrap;
2251
+ align-items: center;
2252
+ gap: 8px 14px;
2253
+ padding: 10px 14px;
2254
+ font-size: 12px;
2255
+ color: var(--rs-muted);
2256
+ border-top: 1px solid var(--rs-line);
2006
2257
  }
2007
2258
 
2008
2259
  .dshr-comboHeaderKey {
2009
- font-weight: 600;
2010
- color: var(--rs-text);
2011
- background: color-mix(in srgb, var(--rs-success) 14%, transparent);
2012
- border-radius: 4px;
2013
- padding: 1px 6px;
2014
- font-size: 11px;
2260
+ font-weight: 600;
2261
+ color: var(--rs-text);
2262
+ background: color-mix(in srgb, var(--rs-success) 14%, transparent);
2263
+ border-radius: 4px;
2264
+ padding: 1px 6px;
2265
+ font-size: 11px;
2015
2266
  }
2016
2267
 
2017
2268
  .dshr-comboHeaderKey-2 {
2018
- margin-left: 4px;
2019
- background: color-mix(in srgb, var(--rs-accent) 14%, transparent);
2269
+ margin-left: 4px;
2270
+ background: color-mix(in srgb, var(--rs-accent) 14%, transparent);
2020
2271
  }
2021
2272
 
2022
- .dshr-comboList { display: flex; flex-direction: column; gap: 10px; }
2273
+ .dshr-comboList {
2274
+ display: flex;
2275
+ flex-direction: column;
2276
+ gap: 10px;
2277
+ }
2023
2278
 
2024
- .dshr-comboCard { display: flex; flex-direction: column; }
2279
+ .dshr-comboCard {
2280
+ display: flex;
2281
+ flex-direction: column;
2282
+ }
2025
2283
 
2026
2284
  .dshr-comboName {
2027
- font-family: var(--rs-mono);
2028
- font-size: 13px;
2029
- font-weight: 600;
2030
- color: var(--rs-text);
2031
- white-space: nowrap;
2032
- overflow: hidden;
2033
- text-overflow: ellipsis;
2034
- max-width: 200px;
2285
+ font-family: var(--rs-mono);
2286
+ font-size: 13px;
2287
+ font-weight: 600;
2288
+ color: var(--rs-text);
2289
+ white-space: nowrap;
2290
+ overflow: hidden;
2291
+ text-overflow: ellipsis;
2292
+ max-width: 200px;
2035
2293
  }
2036
2294
 
2037
2295
  .dshr-comboOps {
2038
- display: flex;
2039
- align-items: center;
2040
- gap: 2px;
2041
- flex-shrink: 0;
2042
- margin-left: 10px;
2296
+ display: flex;
2297
+ align-items: center;
2298
+ gap: 2px;
2299
+ flex-shrink: 0;
2300
+ margin-left: 10px;
2043
2301
  }
2044
2302
 
2045
- .dshr-comboOpBtn-danger { color: var(--rs-danger); }
2303
+ .dshr-comboOpBtn-danger {
2304
+ color: var(--rs-danger);
2305
+ }
2046
2306
  .dshr-comboOpBtn-danger:hover {
2047
- color: var(--rs-danger);
2048
- background: color-mix(in srgb, var(--rs-danger) 12%, transparent);
2307
+ color: var(--rs-danger);
2308
+ background: color-mix(in srgb, var(--rs-danger) 12%, transparent);
2049
2309
  }
2050
2310
 
2051
2311
  .dshr-comboCardBody {
2052
- display: flex;
2053
- flex-direction: column;
2054
- gap: 8px;
2055
- padding: 12px 14px;
2056
- border-top: 1px solid var(--rs-line);
2312
+ display: flex;
2313
+ flex-direction: column;
2314
+ gap: 8px;
2315
+ padding: 12px 14px;
2316
+ border-top: 1px solid var(--rs-line);
2057
2317
  }
2058
2318
 
2059
2319
  .dshr-comboChips {
2060
- display: flex;
2061
- flex-wrap: wrap;
2062
- align-items: center;
2063
- gap: 6px;
2064
- min-width: 0;
2320
+ display: flex;
2321
+ flex-wrap: wrap;
2322
+ align-items: center;
2323
+ gap: 6px;
2324
+ min-width: 0;
2065
2325
  }
2066
2326
 
2067
2327
  .dshr-comboChip {
2068
- display: inline-flex;
2069
- align-items: center;
2070
- gap: 5px;
2071
- background: color-mix(in srgb, var(--rs-text) 6%, transparent);
2072
- border: 1px solid var(--rs-line);
2073
- border-radius: 6px;
2074
- padding: 3px 8px 3px 5px;
2328
+ display: inline-flex;
2329
+ align-items: center;
2330
+ gap: 5px;
2331
+ background: color-mix(in srgb, var(--rs-text) 6%, transparent);
2332
+ border: 1px solid var(--rs-line);
2333
+ border-radius: 6px;
2334
+ padding: 3px 8px 3px 5px;
2075
2335
  }
2076
2336
 
2077
2337
  .dshr-comboChipNum {
2078
- width: 15px;
2079
- height: 15px;
2080
- border-radius: 50%;
2081
- display: inline-flex;
2082
- align-items: center;
2083
- justify-content: center;
2084
- font-size: 10px;
2085
- font-weight: 600;
2086
- color: var(--rs-primary);
2087
- background: color-mix(in srgb, var(--rs-primary) 12%, transparent);
2338
+ width: 15px;
2339
+ height: 15px;
2340
+ border-radius: 50%;
2341
+ display: inline-flex;
2342
+ align-items: center;
2343
+ justify-content: center;
2344
+ font-size: 10px;
2345
+ font-weight: 600;
2346
+ color: var(--rs-primary);
2347
+ background: color-mix(in srgb, var(--rs-primary) 12%, transparent);
2088
2348
  }
2089
2349
 
2090
2350
  .dshr-comboChipSupplier {
2091
- font-family: var(--rs-mono);
2092
- font-size: 11px;
2093
- color: var(--rs-text);
2351
+ font-family: var(--rs-mono);
2352
+ font-size: 11px;
2353
+ color: var(--rs-text);
2094
2354
  }
2095
2355
 
2096
- .dshr-comboEmptySteps { font-style: italic; font-size: 12px; }
2097
-
2098
- .dshr-comboMore { font-size: 10px; color: var(--rs-muted); }
2099
-
2100
- .dshr-comboStrategySelect {
2101
- width: 84px;
2102
- height: 26px;
2103
- padding: 0 6px;
2104
- font-size: 12px;
2356
+ .dshr-comboEmptySteps {
2357
+ font-style: italic;
2358
+ font-size: 12px;
2105
2359
  }
2106
2360
 
2107
- .dshr-comboStrategySelect:disabled {
2108
- opacity: .55;
2109
- cursor: not-allowed;
2361
+ .dshr-comboMore {
2362
+ font-size: 10px;
2363
+ color: var(--rs-muted);
2110
2364
  }
2111
2365
 
2112
2366
  /* 表单 */
2113
2367
  .dshr-formLabel {
2114
- font-size: 12px;
2115
- font-weight: 600;
2116
- color: var(--rs-text);
2117
- margin: 0 0 6px;
2368
+ font-size: 12px;
2369
+ font-weight: 600;
2370
+ color: var(--rs-text);
2371
+ margin: 0 0 6px;
2118
2372
  }
2119
2373
 
2120
2374
  .dshr-formHint {
2121
- font-size: 10px;
2122
- color: var(--rs-muted);
2123
- margin: 4px 0 0;
2375
+ font-size: 10px;
2376
+ color: var(--rs-muted);
2377
+ margin: 4px 0 0;
2124
2378
  }
2125
2379
 
2126
2380
  .dshr-comboEmptyStepsBox {
2127
- display: flex;
2128
- flex-direction: column;
2129
- align-items: center;
2130
- gap: 6px;
2131
- padding: 20px 0;
2132
- border: 1px dashed color-mix(in srgb, var(--rs-text) 16%, transparent);
2133
- border-radius: 9px;
2134
- color: var(--rs-muted);
2381
+ display: flex;
2382
+ flex-direction: column;
2383
+ align-items: center;
2384
+ gap: 6px;
2385
+ padding: 20px 0;
2386
+ border: 1px dashed color-mix(in srgb, var(--rs-text) 16%, transparent);
2387
+ border-radius: 9px;
2388
+ color: var(--rs-muted);
2135
2389
  }
2136
2390
 
2137
2391
  .dshr-comboStepList {
2138
- display: flex;
2139
- flex-direction: column;
2140
- gap: 6px;
2141
- max-height: 260px;
2142
- overflow-y: auto;
2392
+ display: flex;
2393
+ flex-direction: column;
2394
+ gap: 6px;
2395
+ max-height: 260px;
2396
+ overflow-y: auto;
2143
2397
  }
2144
2398
 
2145
2399
  .dshr-comboStepRow {
2146
- display: flex;
2147
- align-items: center;
2148
- gap: 8px;
2149
- padding: 3px 4px;
2150
- border: 1px solid transparent;
2151
- border-radius: 7px;
2152
- cursor: grab;
2400
+ display: flex;
2401
+ align-items: center;
2402
+ gap: 8px;
2403
+ padding: 3px 4px;
2404
+ border: 1px solid transparent;
2405
+ border-radius: 7px;
2406
+ cursor: grab;
2153
2407
  }
2154
2408
 
2155
- .dshr-comboStepRow:active { cursor: grabbing; }
2409
+ .dshr-comboStepRow:active {
2410
+ cursor: grabbing;
2411
+ }
2156
2412
 
2157
2413
  .dshr-comboStepRow-dragging {
2158
- opacity: .45;
2159
- border-color: var(--rs-accent);
2414
+ opacity: 0.45;
2415
+ border-color: var(--rs-accent);
2160
2416
  }
2161
2417
 
2162
2418
  .dshr-comboStepRow-over {
2163
- border-color: var(--rs-accent);
2164
- background: color-mix(in srgb, var(--rs-accent) 8%, transparent);
2419
+ border-color: var(--rs-accent);
2420
+ background: color-mix(in srgb, var(--rs-accent) 8%, transparent);
2165
2421
  }
2166
2422
 
2167
2423
  .dshr-comboGrip {
2168
- flex: none;
2169
- display: inline-flex;
2170
- align-items: center;
2171
- justify-content: center;
2172
- color: var(--rs-faint);
2173
- cursor: grab;
2424
+ flex: none;
2425
+ display: inline-flex;
2426
+ align-items: center;
2427
+ justify-content: center;
2428
+ color: var(--rs-faint);
2429
+ cursor: grab;
2174
2430
  }
2175
2431
 
2176
2432
  .dshr-comboStepNum {
2177
- width: 20px;
2178
- height: 20px;
2179
- border-radius: 50%;
2180
- flex-shrink: 0;
2181
- display: flex;
2182
- align-items: center;
2183
- justify-content: center;
2184
- font-size: 11px;
2185
- font-weight: 600;
2186
- color: var(--rs-primary);
2187
- background: color-mix(in srgb, var(--rs-primary) 12%, transparent);
2433
+ width: 20px;
2434
+ height: 20px;
2435
+ border-radius: 50%;
2436
+ flex-shrink: 0;
2437
+ display: flex;
2438
+ align-items: center;
2439
+ justify-content: center;
2440
+ font-size: 11px;
2441
+ font-weight: 600;
2442
+ color: var(--rs-primary);
2443
+ background: color-mix(in srgb, var(--rs-primary) 12%, transparent);
2188
2444
  }
2189
2445
 
2190
- .dshr-comboStepSelect { flex: 1; min-width: 0; }
2446
+ .dshr-comboStepSelect {
2447
+ flex: 1;
2448
+ min-width: 0;
2449
+ }
2191
2450
 
2192
2451
  .dshr-comboStepRemove:hover {
2193
- color: var(--rs-danger);
2194
- background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
2452
+ color: var(--rs-danger);
2453
+ background: color-mix(in srgb, var(--rs-danger) 14%, transparent);
2195
2454
  }
2196
2455
 
2197
2456
  .dshr-comboAddStep {
2198
- width: 100%;
2199
- margin-top: 8px;
2200
- padding: 8px 0;
2201
- border: 1px dashed color-mix(in srgb, var(--rs-text) 20%, transparent);
2202
- border-radius: 9px;
2203
- background: transparent;
2204
- color: var(--rs-primary);
2205
- font-size: 12px;
2206
- font-weight: 500;
2207
- cursor: pointer;
2208
- display: flex;
2209
- align-items: center;
2210
- justify-content: center;
2211
- gap: 6px;
2212
- transition: border-color .12s ease, background .12s ease;
2457
+ width: 100%;
2458
+ margin-top: 8px;
2459
+ padding: 8px 0;
2460
+ border: 1px dashed color-mix(in srgb, var(--rs-text) 20%, transparent);
2461
+ border-radius: 9px;
2462
+ background: transparent;
2463
+ color: var(--rs-primary);
2464
+ font-size: 12px;
2465
+ font-weight: 500;
2466
+ cursor: pointer;
2467
+ display: flex;
2468
+ align-items: center;
2469
+ justify-content: center;
2470
+ gap: 6px;
2471
+ transition:
2472
+ border-color 0.12s ease,
2473
+ background 0.12s ease;
2213
2474
  }
2214
2475
 
2215
2476
  .dshr-comboAddStep:hover {
2216
- border-color: color-mix(in srgb, var(--rs-primary) 50%, transparent);
2217
- background: color-mix(in srgb, var(--rs-primary) 5%, transparent);
2477
+ border-color: color-mix(in srgb, var(--rs-primary) 50%, transparent);
2478
+ background: color-mix(in srgb, var(--rs-primary) 5%, transparent);
2218
2479
  }
2219
2480
 
2220
2481
  /* 组合:已选模型行 + 添加模型挑选列表 */
2221
2482
  .dshr-comboSelectedModel {
2222
- flex: 1;
2223
- min-width: 0;
2224
- font-family: var(--rs-mono);
2225
- font-size: 12px;
2226
- color: var(--rs-text);
2227
- overflow: hidden;
2228
- text-overflow: ellipsis;
2229
- white-space: nowrap;
2483
+ flex: 1;
2484
+ min-width: 0;
2485
+ font-family: var(--rs-mono);
2486
+ font-size: 12px;
2487
+ color: var(--rs-text);
2488
+ overflow: hidden;
2489
+ text-overflow: ellipsis;
2490
+ white-space: nowrap;
2230
2491
  }
2231
2492
 
2232
- .dshr-comboPickLabel { margin-top: 12px; }
2493
+ .dshr-comboPickLabel {
2494
+ margin-top: 12px;
2495
+ }
2233
2496
 
2234
- .dshr-comboModelSearch { margin-bottom: 6px; }
2497
+ .dshr-comboModelSearch {
2498
+ margin-bottom: 6px;
2499
+ }
2235
2500
 
2236
2501
  .dshr-comboPickList {
2237
- display: flex;
2238
- flex-direction: column;
2239
- gap: 2px;
2240
- max-height: 180px;
2241
- overflow-y: auto;
2502
+ display: flex;
2503
+ flex-direction: column;
2504
+ gap: 2px;
2505
+ max-height: 180px;
2506
+ overflow-y: auto;
2242
2507
  }
2243
2508
 
2244
2509
  .dshr-comboPickItem {
2245
- display: flex;
2246
- align-items: center;
2247
- gap: 8px;
2248
- min-width: 0;
2249
- padding: 6px 8px;
2250
- border: none;
2251
- border-radius: 6px;
2252
- background: transparent;
2253
- color: var(--rs-text);
2254
- font-size: 12px;
2255
- text-align: left;
2256
- cursor: pointer;
2257
- transition: background .12s ease;
2258
- }
2259
-
2260
- .dshr-comboPickItem:hover { background: var(--rs-hover); }
2510
+ display: flex;
2511
+ align-items: center;
2512
+ gap: 8px;
2513
+ min-width: 0;
2514
+ padding: 6px 8px;
2515
+ border: none;
2516
+ border-radius: 6px;
2517
+ background: transparent;
2518
+ color: var(--rs-text);
2519
+ font-size: 12px;
2520
+ text-align: left;
2521
+ cursor: pointer;
2522
+ transition: background 0.12s ease;
2523
+ }
2524
+
2525
+ .dshr-comboPickItem:hover {
2526
+ background: var(--rs-hover);
2527
+ }
2261
2528
 
2262
2529
  .dshr-comboPickName {
2263
- flex: 1;
2264
- min-width: 0;
2265
- font-family: var(--rs-mono);
2266
- overflow: hidden;
2267
- text-overflow: ellipsis;
2268
- white-space: nowrap;
2530
+ flex: 1;
2531
+ min-width: 0;
2532
+ font-family: var(--rs-mono);
2533
+ overflow: hidden;
2534
+ text-overflow: ellipsis;
2535
+ white-space: nowrap;
2269
2536
  }
2270
2537
 
2271
2538
  .dshr-comboPickEmpty {
2272
- font-size: 12px;
2273
- font-style: italic;
2274
- padding: 8px 2px;
2539
+ font-size: 12px;
2540
+ font-style: italic;
2541
+ padding: 8px 2px;
2275
2542
  }
2276
2543
 
2277
2544
  /* 组合:添加模型按供应商分组 */
2278
- .dshr-comboPickGroup { margin-bottom: 6px; }
2545
+ .dshr-comboPickGroup {
2546
+ margin-bottom: 6px;
2547
+ }
2279
2548
 
2280
2549
  .dshr-comboPickGroupTitle {
2281
- margin: 0 0 2px;
2282
- padding: 0 8px;
2283
- font-size: 11px;
2284
- font-weight: 600;
2285
- color: var(--rs-faint);
2550
+ margin: 0 0 2px;
2551
+ padding: 0 8px;
2552
+ font-size: 11px;
2553
+ font-weight: 600;
2554
+ color: var(--rs-faint);
2286
2555
  }
2287
2556
 
2288
2557
  /* 组合表单:左右分栏(左=组合名/策略/已选,右=添加模型) */
2289
2558
  .dshr-comboFormSplit {
2290
- position: relative;
2291
- display: grid;
2292
- grid-template-columns: 1fr 1fr;
2293
- gap: 24px;
2294
- align-items: start;
2559
+ position: relative;
2560
+ display: grid;
2561
+ grid-template-columns: 1fr 1fr;
2562
+ gap: 24px;
2563
+ align-items: start;
2295
2564
  }
2296
2565
 
2297
2566
  .dshr-comboFormLeft {
2298
- display: flex;
2299
- flex-direction: column;
2300
- gap: 12px;
2301
- min-width: 0;
2567
+ display: flex;
2568
+ flex-direction: column;
2569
+ gap: 12px;
2570
+ min-width: 0;
2302
2571
  }
2303
2572
 
2304
2573
  .dshr-comboFormRight {
2305
- display: flex;
2306
- flex-direction: column;
2307
- gap: 6px;
2308
- min-width: 0;
2309
- max-height: 340px;
2574
+ display: flex;
2575
+ flex-direction: column;
2576
+ gap: 6px;
2577
+ min-width: 0;
2578
+ max-height: 340px;
2310
2579
  }
2311
2580
 
2312
2581
  .dshr-comboFormRight .dshr-comboPickList {
2313
- flex: 1;
2314
- min-height: 0;
2582
+ flex: 1;
2583
+ min-height: 0;
2315
2584
  }
2316
2585
 
2317
2586
  /* 组合编辑弹窗:加宽 */
2318
2587
  .dshr-modal-wide {
2319
- width: min(760px, 100%);
2588
+ width: min(760px, 100%);
2320
2589
  }
2321
2590
 
2322
2591
  /* 左右分栏之间的分割线 */
2323
2592
  .dshr-comboFormDivider {
2324
- position: absolute;
2325
- top: 12px;
2326
- bottom: 12px;
2327
- left: 50%;
2328
- width: 1px;
2329
- background: var(--rs-line);
2593
+ position: absolute;
2594
+ top: 12px;
2595
+ bottom: 12px;
2596
+ left: 50%;
2597
+ width: 1px;
2598
+ background: var(--rs-line);
2330
2599
  }
2331
2600
 
2332
2601
  /* ============================================================
@@ -2335,20 +2604,20 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
2335
2604
 
2336
2605
  /* 周期切换 + 操作条 */
2337
2606
  .dshr-statsBar {
2338
- display: flex;
2339
- flex: none;
2340
- flex-wrap: wrap;
2341
- align-items: center;
2342
- gap: 10px;
2607
+ display: flex;
2608
+ flex: none;
2609
+ flex-wrap: wrap;
2610
+ align-items: center;
2611
+ gap: 10px;
2343
2612
  }
2344
2613
 
2345
2614
  .dshr-periods {
2346
- display: inline-flex;
2347
- gap: 2px;
2348
- padding: 2px;
2349
- border: 1px solid var(--rs-line);
2350
- border-radius: 8px;
2351
- background: var(--rs-layer-2);
2615
+ display: inline-flex;
2616
+ gap: 2px;
2617
+ padding: 2px;
2618
+ border: 1px solid var(--rs-line);
2619
+ border-radius: 8px;
2620
+ background: var(--rs-layer-2);
2352
2621
  }
2353
2622
 
2354
2623
  /* 周期按钮三态(按钮组:一组互斥的筛选按钮,不是导航 tab)。
@@ -2361,439 +2630,498 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
2361
2630
  两种 hover 用 :not() 做成互斥,谁赢跟源码顺序无关(免得以后有人挪块就翻车)。 */
2362
2631
  .dshr-settings .dshr-period,
2363
2632
  .dshr-shell .dshr-period {
2364
- min-width: 46px;
2365
- height: 26px;
2366
- padding: 0 10px;
2367
- border: none;
2368
- border-radius: 6px;
2369
- color: var(--rs-muted);
2370
- background: transparent;
2371
- font-size: 12px;
2372
- font-weight: 500;
2373
- cursor: pointer;
2374
- transition: color .12s ease, background .12s ease, filter .12s ease;
2633
+ min-width: 46px;
2634
+ height: 26px;
2635
+ padding: 0 10px;
2636
+ border: none;
2637
+ border-radius: 6px;
2638
+ color: var(--rs-muted);
2639
+ background: transparent;
2640
+ font-size: 12px;
2641
+ font-weight: 500;
2642
+ cursor: pointer;
2643
+ transition:
2644
+ color 0.12s ease,
2645
+ background 0.12s ease,
2646
+ filter 0.12s ease;
2375
2647
  }
2376
2648
 
2377
2649
  /* 未激活悬停:跟 .dshr-miniButton / .dshr-iconButton 一个套路(主文字色 + --rs-hover 底) */
2378
2650
  .dshr-settings .dshr-period:not(.dshr-period-on):hover,
2379
2651
  .dshr-shell .dshr-period:not(.dshr-period-on):hover {
2380
- color: var(--rs-text);
2381
- background: var(--rs-hover);
2652
+ color: var(--rs-text);
2653
+ background: var(--rs-hover);
2382
2654
  }
2383
2655
 
2384
2656
  /* 激活:强调色块 + 白字。底色用 layer-1 时跟卡片同色,根本看不出选中了哪个 */
2385
2657
  .dshr-settings .dshr-period-on,
2386
2658
  .dshr-shell .dshr-period-on {
2387
- color: #fff;
2388
- background: var(--rs-accent);
2389
- font-weight: 600;
2390
- box-shadow: 0 1px 2px rgb(0 0 0 / .12);
2659
+ color: #fff;
2660
+ background: var(--rs-accent);
2661
+ font-weight: 600;
2662
+ box-shadow: 0 1px 2px rgb(0 0 0 / 0.12);
2391
2663
  }
2392
2664
 
2393
2665
  /* 激活态被悬停:跟 .dshr-primaryButton 一样提亮,表示「它还是能点的」 */
2394
2666
  .dshr-settings .dshr-period-on:hover,
2395
2667
  .dshr-shell .dshr-period-on:hover {
2396
- color: #fff;
2397
- background: var(--rs-accent);
2398
- filter: brightness(1.08);
2668
+ color: #fff;
2669
+ background: var(--rs-accent);
2670
+ filter: brightness(1.08);
2399
2671
  }
2400
2672
 
2401
2673
  .dshr-statsBarRight {
2402
- display: flex;
2403
- align-items: center;
2404
- gap: 6px;
2405
- margin-left: auto;
2674
+ display: flex;
2675
+ align-items: center;
2676
+ gap: 6px;
2677
+ margin-left: auto;
2406
2678
  }
2407
2679
 
2408
2680
  .dshr-lifetime {
2409
- font-size: 11px;
2410
- white-space: nowrap;
2681
+ font-size: 11px;
2682
+ white-space: nowrap;
2411
2683
  }
2412
2684
 
2413
2685
  /* 汇总卡(照 9router OverviewCards 的自适应五宫格) */
2414
2686
  .dshr-statGrid {
2415
- display: grid;
2416
- flex: none;
2417
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
2418
- gap: 10px;
2687
+ display: grid;
2688
+ flex: none;
2689
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
2690
+ gap: 10px;
2419
2691
  }
2420
2692
 
2421
2693
  .dshr-statCard {
2422
- display: flex;
2423
- min-width: 0;
2424
- flex-direction: column;
2425
- gap: 3px;
2426
- padding: 12px 14px;
2427
- border: 1px solid var(--rs-line);
2428
- border-radius: 10px;
2429
- background: var(--rs-layer-1);
2430
- box-shadow: 0 1px 2px rgb(0 0 0 / .04);
2694
+ display: flex;
2695
+ min-width: 0;
2696
+ flex-direction: column;
2697
+ gap: 3px;
2698
+ padding: 12px 14px;
2699
+ border: 1px solid var(--rs-line);
2700
+ border-radius: 10px;
2701
+ background: var(--rs-layer-1);
2702
+ box-shadow: 0 1px 2px rgb(0 0 0 / 0.04);
2431
2703
  }
2432
2704
 
2433
2705
  .dshr-statLabel {
2434
- overflow: hidden;
2435
- color: var(--rs-faint);
2436
- font-size: 11px;
2437
- font-weight: 600;
2438
- letter-spacing: .03em;
2439
- text-overflow: ellipsis;
2440
- text-transform: uppercase;
2441
- white-space: nowrap;
2706
+ overflow: hidden;
2707
+ color: var(--rs-faint);
2708
+ font-size: 11px;
2709
+ font-weight: 600;
2710
+ letter-spacing: 0.03em;
2711
+ text-overflow: ellipsis;
2712
+ text-transform: uppercase;
2713
+ white-space: nowrap;
2442
2714
  }
2443
2715
 
2444
2716
  .dshr-statValue {
2445
- overflow: hidden;
2446
- font-size: 22px;
2447
- font-weight: 700;
2448
- letter-spacing: -.01em;
2449
- line-height: 1.2;
2450
- text-overflow: ellipsis;
2717
+ overflow: hidden;
2718
+ font-size: 22px;
2719
+ font-weight: 700;
2720
+ letter-spacing: -0.01em;
2721
+ line-height: 1.2;
2722
+ text-overflow: ellipsis;
2451
2723
  }
2452
2724
 
2453
2725
  .dshr-statHint {
2454
- color: var(--rs-faint);
2455
- font-size: 11px;
2726
+ color: var(--rs-faint);
2727
+ font-size: 11px;
2456
2728
  }
2457
2729
 
2458
- .dshr-statCard-primary .dshr-statValue { color: var(--rs-accent); }
2459
- .dshr-statCard-ok .dshr-statValue { color: var(--rs-success); }
2460
- .dshr-statCard-warn .dshr-statValue { color: var(--rs-warn); }
2461
- .dshr-statCard-danger .dshr-statValue { color: var(--rs-danger); }
2730
+ .dshr-statCard-primary .dshr-statValue {
2731
+ color: var(--rs-accent);
2732
+ }
2733
+ .dshr-statCard-ok .dshr-statValue {
2734
+ color: var(--rs-success);
2735
+ }
2736
+ .dshr-statCard-warn .dshr-statValue {
2737
+ color: var(--rs-warn);
2738
+ }
2739
+ .dshr-statCard-danger .dshr-statValue {
2740
+ color: var(--rs-danger);
2741
+ }
2462
2742
 
2463
2743
  /* 签到卡:跟统计卡同宽同高,但里面是按钮不是数字。
2464
2744
  gap 沿用卡片的 3px(不覆写)—— 之前改成 6px 让这一行比别的高 6px,
2465
2745
  两行卡片因此不齐(92 vs 98px)。
2466
2746
  今日已点过 → 边框转成功色,一眼看出「今天点过了」 */
2467
- .dshr-statCard-checkin { gap: 3px; }
2747
+ .dshr-statCard-checkin {
2748
+ gap: 3px;
2749
+ }
2468
2750
 
2469
2751
  .dshr-statCard-done {
2470
- border-color: color-mix(in srgb, var(--rs-success) 45%, transparent);
2752
+ border-color: color-mix(in srgb, var(--rs-success) 45%, transparent);
2471
2753
  }
2472
2754
 
2473
2755
  /* 按钮撑满卡片宽度:卡片本来就窄,居左的小按钮看着像没对齐 */
2474
2756
  .dshr-checkinButton {
2475
- display: inline-flex;
2476
- width: 100%;
2477
- /* 26px ≈ .dshr-statValue 的行高(22px × 1.2),让按钮那一行跟数字的
2757
+ display: inline-flex;
2758
+ width: 100%;
2759
+ /* 26px ≈ .dshr-statValue 的行高(22px × 1.2),让按钮那一行跟数字的
2478
2760
  那一行一样高,卡片整体高度才跟邻卡一致 */
2479
- height: 26px;
2480
- align-items: center;
2481
- justify-content: center;
2482
- gap: 5px;
2483
- border: 1px solid var(--rs-line);
2484
- border-radius: 6px;
2485
- color: var(--rs-text);
2486
- background: var(--rs-layer-2);
2487
- font-size: 12px;
2488
- font-weight: 500;
2489
- white-space: nowrap;
2490
- cursor: pointer;
2491
- transition: color .12s ease, background .12s ease, border-color .12s ease;
2761
+ height: 26px;
2762
+ align-items: center;
2763
+ justify-content: center;
2764
+ gap: 5px;
2765
+ border: 1px solid var(--rs-line);
2766
+ border-radius: 6px;
2767
+ color: var(--rs-text);
2768
+ background: var(--rs-layer-2);
2769
+ font-size: 12px;
2770
+ font-weight: 500;
2771
+ white-space: nowrap;
2772
+ cursor: pointer;
2773
+ transition:
2774
+ color 0.12s ease,
2775
+ background 0.12s ease,
2776
+ border-color 0.12s ease;
2492
2777
  }
2493
2778
 
2494
2779
  .dshr-checkinButton:hover:not(:disabled) {
2495
- border-color: var(--rs-accent);
2496
- color: var(--rs-accent);
2497
- background: color-mix(in srgb, var(--rs-accent) 8%, transparent);
2780
+ border-color: var(--rs-accent);
2781
+ color: var(--rs-accent);
2782
+ background: color-mix(in srgb, var(--rs-accent) 8%, transparent);
2498
2783
  }
2499
2784
 
2500
- .dshr-checkinButton:disabled { opacity: .6; cursor: default; }
2785
+ .dshr-checkinButton:disabled {
2786
+ opacity: 0.6;
2787
+ cursor: default;
2788
+ }
2501
2789
 
2502
2790
  /* 已点过:按钮转成成功色柔和态(仍可再点) */
2503
2791
  .dshr-statCard-done .dshr-checkinButton {
2504
- border-color: color-mix(in srgb, var(--rs-success) 40%, transparent);
2505
- color: var(--rs-success);
2506
- background: color-mix(in srgb, var(--rs-success) 8%, transparent);
2792
+ border-color: color-mix(in srgb, var(--rs-success) 40%, transparent);
2793
+ color: var(--rs-success);
2794
+ background: color-mix(in srgb, var(--rs-success) 8%, transparent);
2507
2795
  }
2508
2796
 
2509
2797
  /* 结果/失败都压在 hint 那一行里(卡片行数必须跟邻卡一致):
2510
2798
  失败时才转红,其余沿用 hint 的弱色,不成功后多出一行 */
2511
2799
  .dshr-statHint-err {
2512
- overflow: hidden;
2513
- color: var(--rs-danger);
2514
- text-overflow: ellipsis;
2515
- white-space: nowrap;
2800
+ overflow: hidden;
2801
+ color: var(--rs-danger);
2802
+ text-overflow: ellipsis;
2803
+ white-space: nowrap;
2516
2804
  }
2517
2805
 
2518
2806
  /* 忙碌态:按钮转成弱色,跟「已点过」的成功色区分开 */
2519
2807
  .dshr-checkinButton-busy {
2520
- color: var(--rs-faint);
2521
- background: var(--rs-layer-2);
2522
- border-color: var(--rs-line);
2808
+ color: var(--rs-faint);
2809
+ background: var(--rs-layer-2);
2810
+ border-color: var(--rs-line);
2523
2811
  }
2524
2812
 
2525
2813
  .dshr-estimateNote {
2526
- margin: 0;
2527
- color: var(--rs-faint);
2528
- font-size: 11px;
2529
- line-height: 1.6;
2814
+ margin: 0;
2815
+ color: var(--rs-faint);
2816
+ font-size: 11px;
2817
+ line-height: 1.6;
2530
2818
  }
2531
2819
 
2532
2820
  .dshr-estimateNote code {
2533
- padding: 0 3px;
2534
- border-radius: 3px;
2535
- background: var(--rs-layer-2);
2536
- font-family: var(--rs-mono);
2821
+ padding: 0 3px;
2822
+ border-radius: 3px;
2823
+ background: var(--rs-layer-2);
2824
+ font-family: var(--rs-mono);
2537
2825
  }
2538
2826
 
2539
2827
  /* 趋势折线图(纯 SVG + HTML 叠加层,不引图表库) */
2540
2828
  .dshr-trendWrap {
2541
- position: relative;
2542
- padding: 14px 14px 10px;
2829
+ position: relative;
2830
+ padding: 14px 14px 10px;
2543
2831
  }
2544
2832
 
2545
2833
  .dshr-trendBusy {
2546
- position: absolute;
2547
- inset: 0;
2548
- background: color-mix(in srgb, var(--rs-layer-1) 55%, transparent);
2549
- pointer-events: none;
2834
+ position: absolute;
2835
+ inset: 0;
2836
+ background: color-mix(in srgb, var(--rs-layer-1) 55%, transparent);
2837
+ pointer-events: none;
2550
2838
  }
2551
2839
 
2552
2840
  /* 绘图区:高度跟 SVG 视口一致,叠加层用百分比定位才对得上 */
2553
2841
  .dshr-linePlot {
2554
- position: relative;
2555
- height: 150px;
2556
- cursor: crosshair;
2842
+ position: relative;
2843
+ height: 150px;
2844
+ cursor: crosshair;
2557
2845
  }
2558
2846
 
2559
2847
  /* 键盘可达(←/→ 逐格):聚焦环跟面板其它控件一致 */
2560
2848
  .dshr-linePlot:focus-visible {
2561
- outline: 2px solid var(--rs-accent);
2562
- outline-offset: 2px;
2849
+ outline: 2px solid var(--rs-accent);
2850
+ outline-offset: 2px;
2563
2851
  }
2564
2852
 
2565
2853
  /* 峰值:给读数一个量级参照;半透明底是怕压在折线上看不清 */
2566
2854
  .dshr-linePeak {
2567
- position: absolute;
2568
- top: 0;
2569
- right: 0;
2570
- padding: 0 4px;
2571
- border-radius: 3px;
2572
- color: var(--rs-faint);
2573
- background: color-mix(in srgb, var(--rs-layer-1) 72%, transparent);
2574
- font-size: 9px;
2575
- font-variant-numeric: tabular-nums;
2576
- pointer-events: none;
2855
+ position: absolute;
2856
+ top: 0;
2857
+ right: 0;
2858
+ padding: 0 4px;
2859
+ border-radius: 3px;
2860
+ color: var(--rs-faint);
2861
+ background: color-mix(in srgb, var(--rs-layer-1) 72%, transparent);
2862
+ font-size: 9px;
2863
+ font-variant-numeric: tabular-nums;
2864
+ pointer-events: none;
2577
2865
  }
2578
2866
 
2579
2867
  .dshr-lineSvg {
2580
- position: absolute;
2581
- display: block;
2582
- width: 100%;
2583
- height: 100%;
2584
- inset: 0;
2585
- overflow: visible;
2868
+ position: absolute;
2869
+ display: block;
2870
+ width: 100%;
2871
+ height: 100%;
2872
+ inset: 0;
2873
+ overflow: visible;
2586
2874
  }
2587
2875
 
2588
2876
  .dshr-lineGrid {
2589
- stroke: var(--rs-line);
2590
- stroke-dasharray: 3 3;
2877
+ stroke: var(--rs-line);
2878
+ stroke-dasharray: 3 3;
2591
2879
  }
2592
2880
 
2593
2881
  .dshr-lineArea {
2594
- fill: color-mix(in srgb, var(--rs-accent) 14%, transparent);
2595
- stroke: none;
2882
+ fill: color-mix(in srgb, var(--rs-accent) 14%, transparent);
2883
+ stroke: none;
2596
2884
  }
2597
2885
 
2598
2886
  .dshr-linePath {
2599
- fill: none;
2600
- stroke: var(--rs-accent);
2601
- stroke-width: 2;
2602
- stroke-linejoin: round;
2603
- stroke-linecap: round;
2887
+ fill: none;
2888
+ stroke: var(--rs-accent);
2889
+ stroke-width: 2;
2890
+ stroke-linejoin: round;
2891
+ stroke-linecap: round;
2604
2892
  }
2605
2893
 
2606
2894
  /* 数值点:空心小圆(SVG 会被横向拉伸,所以画在 HTML 层) */
2607
2895
  .dshr-linePoint {
2608
- position: absolute;
2609
- width: 5px;
2610
- height: 5px;
2611
- border: 1.5px solid var(--rs-accent);
2612
- border-radius: 50%;
2613
- background: var(--rs-layer-1);
2614
- transform: translate(-50%, -50%);
2615
- pointer-events: none;
2896
+ position: absolute;
2897
+ width: 5px;
2898
+ height: 5px;
2899
+ border: 1.5px solid var(--rs-accent);
2900
+ border-radius: 50%;
2901
+ background: var(--rs-layer-1);
2902
+ transform: translate(-50%, -50%);
2903
+ pointer-events: none;
2616
2904
  }
2617
2905
 
2618
2906
  .dshr-lineGuide {
2619
- position: absolute;
2620
- top: 0;
2621
- bottom: 0;
2622
- width: 1px;
2623
- background: var(--rs-line-strong);
2624
- pointer-events: none;
2907
+ position: absolute;
2908
+ top: 0;
2909
+ bottom: 0;
2910
+ width: 1px;
2911
+ background: var(--rs-line-strong);
2912
+ pointer-events: none;
2625
2913
  }
2626
2914
 
2627
2915
  .dshr-lineDot {
2628
- position: absolute;
2629
- width: 9px;
2630
- height: 9px;
2631
- border: 2px solid var(--rs-layer-1);
2632
- border-radius: 50%;
2633
- background: var(--rs-accent);
2634
- box-shadow: 0 0 0 1px var(--rs-accent);
2635
- transform: translate(-50%, -50%);
2636
- pointer-events: none;
2916
+ position: absolute;
2917
+ width: 9px;
2918
+ height: 9px;
2919
+ border: 2px solid var(--rs-layer-1);
2920
+ border-radius: 50%;
2921
+ background: var(--rs-accent);
2922
+ box-shadow: 0 0 0 1px var(--rs-accent);
2923
+ transform: translate(-50%, -50%);
2924
+ pointer-events: none;
2637
2925
  }
2638
2926
 
2639
2927
  .dshr-lineLabels {
2640
- position: relative;
2641
- height: 14px;
2642
- margin-top: 5px;
2928
+ position: relative;
2929
+ height: 14px;
2930
+ margin-top: 5px;
2643
2931
  }
2644
2932
 
2645
2933
  .dshr-lineLabel {
2646
- position: absolute;
2647
- top: 0;
2648
- overflow: visible;
2649
- color: var(--rs-faint);
2650
- font-size: 9px;
2651
- font-variant-numeric: tabular-nums;
2652
- white-space: nowrap;
2653
- transform: translateX(-50%);
2934
+ position: absolute;
2935
+ top: 0;
2936
+ overflow: visible;
2937
+ color: var(--rs-faint);
2938
+ font-size: 9px;
2939
+ font-variant-numeric: tabular-nums;
2940
+ white-space: nowrap;
2941
+ transform: translateX(-50%);
2654
2942
  }
2655
2943
 
2656
2944
  /* 选中的时段:标签跟着高亮,不用抬头对读数才知道看的是哪一段 */
2657
2945
  .dshr-lineLabel-on {
2658
- color: var(--rs-accent);
2659
- font-weight: 700;
2946
+ color: var(--rs-accent);
2947
+ font-weight: 700;
2660
2948
  }
2661
2949
 
2662
2950
  .dshr-trendReadout {
2663
- display: flex;
2664
- align-items: center;
2665
- gap: 2px;
2666
- min-height: 18px;
2667
- padding-top: 6px;
2668
- font-size: 11px;
2951
+ display: flex;
2952
+ align-items: center;
2953
+ gap: 2px;
2954
+ min-height: 18px;
2955
+ padding-top: 6px;
2956
+ font-size: 11px;
2669
2957
  }
2670
2958
 
2671
2959
  .dshr-trendEmpty {
2672
- display: flex;
2673
- height: 150px;
2674
- flex-direction: column;
2675
- align-items: center;
2676
- justify-content: center;
2677
- gap: 6px;
2678
- color: var(--rs-faint);
2679
- font-size: 12px;
2960
+ display: flex;
2961
+ height: 150px;
2962
+ flex-direction: column;
2963
+ align-items: center;
2964
+ justify-content: center;
2965
+ gap: 6px;
2966
+ color: var(--rs-faint);
2967
+ font-size: 12px;
2680
2968
  }
2681
2969
 
2682
2970
  .dshr-trendEmptyIcon {
2683
- display: inline-flex;
2684
- align-items: center;
2685
- justify-content: center;
2686
- width: 44px;
2687
- height: 44px;
2688
- border-radius: 50%;
2689
- color: var(--rs-accent);
2690
- background: color-mix(in srgb, var(--rs-accent) 10%, transparent);
2971
+ display: inline-flex;
2972
+ align-items: center;
2973
+ justify-content: center;
2974
+ width: 44px;
2975
+ height: 44px;
2976
+ border-radius: 50%;
2977
+ color: var(--rs-accent);
2978
+ background: color-mix(in srgb, var(--rs-accent) 10%, transparent);
2691
2979
  }
2692
2980
 
2693
2981
  /* Top 榜(供应商 / 模型并排,窄屏堆叠) */
2694
2982
  .dshr-rankPair {
2695
- display: grid;
2696
- flex: none;
2697
- grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
2698
- gap: 12px;
2699
- align-items: start;
2983
+ display: grid;
2984
+ flex: none;
2985
+ grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
2986
+ gap: 12px;
2987
+ align-items: start;
2700
2988
  }
2701
2989
 
2702
2990
  .dshr-rankList,
2703
2991
  .dshr-recentList {
2704
- display: flex;
2705
- flex-direction: column;
2706
- padding: 6px 14px 12px;
2992
+ display: flex;
2993
+ flex-direction: column;
2994
+ padding: 6px 14px 12px;
2707
2995
  }
2708
2996
 
2709
2997
  .dshr-rankRow,
2710
2998
  .dshr-recentRow {
2711
- display: flex;
2712
- align-items: center;
2713
- gap: 10px;
2714
- min-width: 0;
2715
- padding: 7px 0;
2716
- border-bottom: 1px solid var(--rs-line);
2717
- font-size: 12px;
2999
+ display: flex;
3000
+ align-items: center;
3001
+ gap: 10px;
3002
+ min-width: 0;
3003
+ padding: 7px 0;
3004
+ border-bottom: 1px solid var(--rs-line);
3005
+ font-size: 12px;
2718
3006
  }
2719
3007
 
2720
3008
  .dshr-rankRow:last-child,
2721
- .dshr-recentRow:last-child { border-bottom: none; }
3009
+ .dshr-recentRow:last-child {
3010
+ border-bottom: none;
3011
+ }
2722
3012
 
2723
3013
  /* 表头:不参与 hover,且不画分隔线(视觉上属于卡片头) */
2724
3014
  .dshr-rankHead {
2725
- border-bottom: 1px solid var(--rs-line);
2726
- color: var(--rs-faint);
2727
- font-size: 11px;
2728
- font-weight: 600;
2729
- letter-spacing: .03em;
2730
- text-transform: uppercase;
3015
+ border-bottom: 1px solid var(--rs-line);
3016
+ color: var(--rs-faint);
3017
+ font-size: 11px;
3018
+ font-weight: 600;
3019
+ letter-spacing: 0.03em;
3020
+ text-transform: uppercase;
2731
3021
  }
2732
3022
 
2733
- .dshr-rankRow:not(.dshr-rankHead):hover { background: var(--rs-hover); }
3023
+ .dshr-rankRow:not(.dshr-rankHead):hover {
3024
+ background: var(--rs-hover);
3025
+ }
2734
3026
 
2735
3027
  .dshr-rankName {
2736
- min-width: 0;
2737
- flex: 1 1 auto;
2738
- overflow: hidden;
2739
- text-overflow: ellipsis;
2740
- white-space: nowrap;
3028
+ min-width: 0;
3029
+ flex: 1 1 auto;
3030
+ overflow: hidden;
3031
+ text-overflow: ellipsis;
3032
+ white-space: nowrap;
2741
3033
  }
2742
3034
 
2743
3035
  .dshr-rankNum {
2744
- flex: none;
2745
- min-width: 52px;
2746
- text-align: right;
2747
- font-variant-numeric: tabular-nums;
2748
- white-space: nowrap;
3036
+ flex: none;
3037
+ min-width: 52px;
3038
+ text-align: right;
3039
+ font-variant-numeric: tabular-nums;
3040
+ white-space: nowrap;
2749
3041
  }
2750
3042
 
2751
- .dshr-rankFail { color: var(--rs-danger); }
3043
+ .dshr-rankFail {
3044
+ color: var(--rs-danger);
3045
+ }
2752
3046
 
2753
- .dshr-tokenIn { color: var(--rs-accent); }
2754
- .dshr-tokenOut { color: var(--rs-success); }
3047
+ .dshr-tokenIn {
3048
+ color: var(--rs-accent);
3049
+ }
3050
+ .dshr-tokenOut {
3051
+ color: var(--rs-success);
3052
+ }
2755
3053
 
2756
3054
  /* 最近请求列宽(比 Top 榜宽,要放得下模型名) */
2757
3055
  .dshr-recentTime {
2758
- display: flex;
2759
- flex: none;
2760
- align-items: center;
2761
- gap: 5px;
2762
- width: 78px;
2763
- color: var(--rs-muted);
2764
- font-variant-numeric: tabular-nums;
3056
+ display: flex;
3057
+ flex: none;
3058
+ align-items: center;
3059
+ gap: 5px;
3060
+ width: 78px;
3061
+ color: var(--rs-muted);
3062
+ font-variant-numeric: tabular-nums;
2765
3063
  }
2766
3064
 
2767
3065
  .dshr-recentModel {
2768
- min-width: 0;
2769
- flex: 1 1 auto;
2770
- overflow: hidden;
2771
- text-overflow: ellipsis;
2772
- white-space: nowrap;
3066
+ min-width: 0;
3067
+ flex: 1 1 auto;
3068
+ overflow: hidden;
3069
+ text-overflow: ellipsis;
3070
+ white-space: nowrap;
2773
3071
  }
2774
3072
 
2775
3073
  .dshr-recentSupplier {
2776
- flex: none;
2777
- width: 92px;
2778
- overflow: hidden;
2779
- color: var(--rs-muted);
2780
- text-overflow: ellipsis;
2781
- white-space: nowrap;
3074
+ flex: none;
3075
+ width: 92px;
3076
+ overflow: hidden;
3077
+ color: var(--rs-muted);
3078
+ text-align: center;
3079
+ text-overflow: ellipsis;
3080
+ white-space: nowrap;
3081
+ }
3082
+
3083
+ /* 最近请求的 In/Out 与耗时列:**固定宽度**(不是 min-width)——
3084
+ rankNum 的 min-width 会让表头(纯文本)与数据行(更长)算出的列宽不同,
3085
+ 两行的后一列就对不齐。固定宽度让表头与每一行严格同宽。 */
3086
+ .dshr-recentTokens {
3087
+ flex: none;
3088
+ width: 80px;
3089
+ overflow: hidden;
3090
+ text-align: right;
3091
+ text-overflow: ellipsis;
3092
+ font-variant-numeric: tabular-nums;
3093
+ white-space: nowrap;
3094
+ }
3095
+
3096
+ .dshr-recentDuration {
3097
+ flex: none;
3098
+ width: 40px;
3099
+ overflow: hidden;
3100
+ text-align: right;
3101
+ text-overflow: ellipsis;
3102
+ font-variant-numeric: tabular-nums;
3103
+ white-space: nowrap;
3104
+ }
3105
+
3106
+ .dshr-recentRow-fail .dshr-recentModel {
3107
+ color: var(--rs-danger);
2782
3108
  }
2783
3109
 
2784
- .dshr-recentRow-fail .dshr-recentModel { color: var(--rs-danger); }
2785
-
2786
3110
  /* 状态点 */
2787
3111
  .dshr-dot {
2788
- display: inline-block;
2789
- flex: none;
2790
- width: 6px;
2791
- height: 6px;
2792
- border-radius: 50%;
3112
+ display: inline-block;
3113
+ flex: none;
3114
+ width: 6px;
3115
+ height: 6px;
3116
+ border-radius: 50%;
2793
3117
  }
2794
3118
 
2795
- .dshr-dot-ok { background: var(--rs-success); }
2796
- .dshr-dot-fail { background: var(--rs-danger); }
3119
+ .dshr-dot-ok {
3120
+ background: var(--rs-success);
3121
+ }
3122
+ .dshr-dot-fail {
3123
+ background: var(--rs-danger);
3124
+ }
2797
3125
 
2798
3126
  /* ============================================================
2799
3127
  dsh-router — 设置导航图标(换掉宿主的默认齿轮)
@@ -2805,15 +3133,163 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-
2805
3133
  渲染路由字形:跟随宿主导航的 hover/active 配色,也保持 16px 图标节奏。
2806
3134
  升级路径:等契约长出 icon 字段,删掉 settings-nav-icon.ts 和这一整块。 */
2807
3135
  [data-dsh-router-settings-nav] > svg:first-child {
2808
- display: none;
3136
+ display: none;
2809
3137
  }
2810
3138
 
2811
3139
  [data-dsh-router-settings-nav]::before {
2812
- content: '';
2813
- flex: none;
2814
- width: 16px;
2815
- height: 16px;
2816
- background: currentColor;
2817
- -webkit-mask: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'><circle%20cx='5'%20cy='5'%20r='2.4'/><circle%20cx='19'%20cy='5'%20r='2.4'/><circle%20cx='12'%20cy='19'%20r='2.4'/><path%20d='M7.4%205h9.2'/><path%20d='M5%207.4v6.2c0%202.6%203%203.4%204.6%203.8'/><path%20d='M19%207.4v6.2c0%202.6-3%203.4-4.6%203.8'/></svg>") center / contain no-repeat;
2818
- mask: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'><circle%20cx='5'%20cy='5'%20r='2.4'/><circle%20cx='19'%20cy='5'%20r='2.4'/><circle%20cx='12'%20cy='19'%20r='2.4'/><path%20d='M7.4%205h9.2'/><path%20d='M5%207.4v6.2c0%202.6%203%203.4%204.6%203.8'/><path%20d='M19%207.4v6.2c0%202.6-3%203.4-4.6%203.8'/></svg>") center / contain no-repeat;
3140
+ content: "";
3141
+ flex: none;
3142
+ width: 16px;
3143
+ height: 16px;
3144
+ background: currentColor;
3145
+ -webkit-mask: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'><circle%20cx='5'%20cy='5'%20r='2.4'/><circle%20cx='19'%20cy='5'%20r='2.4'/><circle%20cx='12'%20cy='19'%20r='2.4'/><path%20d='M7.4%205h9.2'/><path%20d='M5%207.4v6.2c0%202.6%203%203.4%204.6%203.8'/><path%20d='M19%207.4v6.2c0%202.6-3%203.4-4.6%203.8'/></svg>")
3146
+ center / contain no-repeat;
3147
+ mask: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'><circle%20cx='5'%20cy='5'%20r='2.4'/><circle%20cx='19'%20cy='5'%20r='2.4'/><circle%20cx='12'%20cy='19'%20r='2.4'/><path%20d='M7.4%205h9.2'/><path%20d='M5%207.4v6.2c0%202.6%203%203.4%204.6%203.8'/><path%20d='M19%207.4v6.2c0%202.6-3%203.4-4.6%203.8'/></svg>")
3148
+ center / contain no-repeat;
3149
+ }
3150
+
3151
+ /* ============================================================
3152
+ last-hit —— 输入框底部 dock 里的「最近命中」徽章
3153
+ (LastHitDock.tsx 注册到官方 conversation.composer.dock,
3154
+ 即 .uV2eYG_dock 操作行里、原生上下文环旁边;scope: session)
3155
+
3156
+ 与同排控件对齐:28px 高胶囊、hover 用 interactive-bg-hover、
3157
+ 图标 14px 用 label-tertiary;弹卡对齐原生 panel 规格
3158
+ (--dsw-specific-menu / --dsw-elevation-prominent / 12px 圆角 / 264px)。
3159
+ ============================================================ */
3160
+
3161
+ .dshr-lastHit {
3162
+ position: relative;
3163
+ display: inline-flex;
3164
+ flex: none;
3165
+ align-items: center;
3166
+ }
3167
+
3168
+ .dshr-lastHit-btn {
3169
+ position: relative;
3170
+ display: inline-flex;
3171
+ height: 28px;
3172
+ flex: none;
3173
+ align-items: center;
3174
+ gap: 6px;
3175
+ color: var(--dsw-alias-label-secondary);
3176
+ background: 0 0;
3177
+ border: none;
3178
+ border-radius: 999px;
3179
+ padding: 0 8px;
3180
+ font-size: 12px;
3181
+ line-height: 1;
3182
+ cursor: pointer;
3183
+ max-width: 220px;
3184
+ }
3185
+
3186
+ .dshr-lastHit-btn:hover {
3187
+ background: var(--dsw-alias-interactive-bg-hover);
3188
+ }
3189
+
3190
+ /* 图标:与隔壁上下文环的描边同色(它用 label-tertiary 画进度弧),
3191
+ 尺寸 14px 也对齐该环的 svg —— 两个控件并排时看着是一套。 */
3192
+ .dshr-lastHit-btn svg {
3193
+ width: 14px;
3194
+ height: 14px;
3195
+ flex: none;
3196
+ color: var(--dsw-alias-label-tertiary);
3197
+ }
3198
+
3199
+ .dshr-lastHit-label {
3200
+ overflow: hidden;
3201
+ text-overflow: ellipsis;
3202
+ white-space: nowrap;
3203
+ }
3204
+
3205
+ .dshr-lastHit-fail {
3206
+ color: var(--dsw-alias-label-error, #e5534b);
3207
+ }
3208
+
3209
+ .dshr-lastHit-fail svg {
3210
+ color: var(--dsw-alias-label-error, #e5534b);
3211
+ }
3212
+
3213
+ .dshr-lastHit-card {
3214
+ position: absolute;
3215
+ right: 0;
3216
+ bottom: calc(100% + 8px);
3217
+ z-index: 100;
3218
+ box-sizing: border-box;
3219
+ width: 264px;
3220
+ border: 0;
3221
+ border-radius: 12px;
3222
+ padding: 12px;
3223
+ color: var(--dsw-alias-label-secondary);
3224
+ /* --dsw-specific-menu 是**半透明**色,原生 panel 靠 backdrop-filter 做毛玻璃;
3225
+ 缺了它只剩半透明、看着像没背景。这两条必须成对出现。 */
3226
+ background: var(--dsw-specific-menu, var(--dsw-alias-bg-primary, #fff));
3227
+ backdrop-filter: var(--dsw-menu-backdrop-filter, blur(40px) saturate(150%));
3228
+ -webkit-backdrop-filter: var(--dsw-menu-backdrop-filter, blur(40px) saturate(150%));
3229
+ --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
3230
+ box-shadow: var(--dsw-elevation-prominent, 0 6px 24px rgba(0, 0, 0, 0.18));
3231
+ font-size: 12px;
3232
+ line-height: 20px;
3233
+ cursor: default;
3234
+ }
3235
+
3236
+ /* 头部:照宿主聊天气泡的 .bRhRbq_title 规格
3237
+ (label-primary / space-between / gap16 / margin-bottom8 / font-weight500)
3238
+ 左标签带 14px 图标,右值 tabular-nums,下接一条 0.5px 分隔线。 */
3239
+ .dshr-lastHit-title {
3240
+ display: flex;
3241
+ align-items: center;
3242
+ justify-content: space-between;
3243
+ gap: 16px;
3244
+ margin-bottom: 8px;
3245
+ color: var(--dsw-alias-label-primary);
3246
+ font-weight: 500;
3247
+ }
3248
+
3249
+ .dshr-lastHit-titleLabel {
3250
+ display: inline-flex;
3251
+ align-items: center;
3252
+ gap: 6px;
3253
+ min-width: 0;
3254
+ }
3255
+
3256
+ .dshr-lastHit-titleLabel svg {
3257
+ width: 14px;
3258
+ height: 14px;
3259
+ flex: none;
3260
+ color: var(--dsw-alias-label-tertiary);
3261
+ }
3262
+
3263
+ .dshr-lastHit-titleValue {
3264
+ overflow: hidden;
3265
+ font-variant-numeric: tabular-nums;
3266
+ text-overflow: ellipsis;
3267
+ white-space: nowrap;
3268
+ }
3269
+
3270
+ .dshr-lastHit-titleRule {
3271
+ border-top: .5px solid var(--dsw-alias-border-l2);
3272
+ margin-bottom: 10px;
3273
+ }
3274
+
3275
+ .dshr-lastHit-row {
3276
+ display: flex;
3277
+ align-items: center;
3278
+ justify-content: space-between;
3279
+ gap: 12px;
3280
+ padding: 2px 0;
3281
+ }
3282
+
3283
+ .dshr-lastHit-key {
3284
+ flex: none;
3285
+ color: var(--dsw-alias-label-secondary);
3286
+ }
3287
+
3288
+ .dshr-lastHit-val {
3289
+ overflow: hidden;
3290
+ color: var(--dsw-alias-label-primary);
3291
+ font-variant-numeric: tabular-nums;
3292
+ text-align: right;
3293
+ text-overflow: ellipsis;
3294
+ white-space: nowrap;
2819
3295
  }