@yss123/cage-admin 0.1.0 → 0.3.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 (53) hide show
  1. package/README.md +62 -3
  2. package/dist/bootstrap.d.ts +27 -1
  3. package/dist/bootstrap.js +52 -16
  4. package/dist/bootstrap.js.map +1 -1
  5. package/dist/catalog.d.ts +48 -0
  6. package/dist/catalog.js +96 -0
  7. package/dist/catalog.js.map +1 -0
  8. package/dist/diagnostics.d.ts +14 -0
  9. package/dist/diagnostics.js +163 -0
  10. package/dist/diagnostics.js.map +1 -0
  11. package/dist/domain/constraints.d.ts +23 -0
  12. package/dist/domain/constraints.js +27 -0
  13. package/dist/domain/constraints.js.map +1 -1
  14. package/dist/domain/index.d.ts +5 -0
  15. package/dist/domain/index.js +5 -0
  16. package/dist/domain/index.js.map +1 -1
  17. package/dist/domain/org.d.ts +230 -149
  18. package/dist/domain/org.js +98 -4
  19. package/dist/domain/org.js.map +1 -1
  20. package/dist/http.d.ts +13 -1
  21. package/dist/http.js +28 -13
  22. package/dist/http.js.map +1 -1
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.js +6 -0
  25. package/dist/index.js.map +1 -1
  26. package/package.json +9 -5
  27. package/ui/dist/app/shell.js +135 -0
  28. package/ui/dist/app.js +34 -0
  29. package/ui/dist/modules/audit/audit-page.js +107 -0
  30. package/ui/dist/modules/audit/index.js +5 -0
  31. package/ui/dist/modules/auth/index.js +5 -0
  32. package/ui/dist/modules/auth/login-page.js +38 -0
  33. package/ui/dist/modules/models/index.js +5 -0
  34. package/ui/dist/modules/models/models-page.js +60 -0
  35. package/ui/dist/modules/operations/index.js +6 -0
  36. package/ui/dist/modules/operations/operations-page.js +110 -0
  37. package/ui/dist/modules/operations/sync-page.js +60 -0
  38. package/ui/dist/modules/org/index.js +5 -0
  39. package/ui/dist/modules/org/org-page.js +243 -0
  40. package/ui/dist/modules/personalities/index.js +5 -0
  41. package/ui/dist/modules/personalities/personalities-page.js +161 -0
  42. package/ui/dist/modules/roles/index.js +5 -0
  43. package/ui/dist/modules/roles/roles-page.js +348 -0
  44. package/ui/dist/modules/tasks/index.js +5 -0
  45. package/ui/dist/modules/tasks/tasks-page.js +68 -0
  46. package/ui/dist/shared/api.js +166 -0
  47. package/ui/dist/shared/dom.js +139 -0
  48. package/ui/dist/shared/labels.js +84 -0
  49. package/ui/dist/shared/navigation.js +14 -0
  50. package/ui/dist/shared/types.js +1 -0
  51. package/ui/index.html +12 -10
  52. package/ui/style.css +1657 -41
  53. package/ui/app.js +0 -339
package/ui/style.css CHANGED
@@ -1,42 +1,1658 @@
1
+ /* 系统管理页面样式:基础变量、应用壳、表单表格、授权编辑与 AI 配置区按既有层叠顺序组织。
2
+ * 页面状态由 TS 添加类名或属性,CSS 只负责显示、布局和响应式适配,不承载授权判断或业务状态转换。 */
3
+ /* 管理工作台采用同一套色彩与间距。仅为桌面排版,不引入远程字体或 UI 运行时。 */
1
4
  :root {
2
- --bg: #f6f7f9; --panel: #fff; --text: #1f2328; --muted: #656d76; --line: #d8dee4;
3
- --accent: #1f6feb; --accent-text: #fff; --danger: #cf222e; --ok: #1a7f37; --warn: #9a6700;
4
- }
5
- @media (prefers-color-scheme: dark) {
6
- :root { --bg: #0d1117; --panel: #161b22; --text: #e6edf3; --muted: #8d96a0; --line: #30363d; --accent: #2f81f7; --danger: #f85149; --ok: #3fb950; --warn: #d29922; }
7
- }
8
- * { box-sizing: border-box; }
9
- body { margin: 0; font: 14px/1.5 system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif; background: var(--bg); color: var(--text); }
10
- header { display: flex; align-items: center; gap: 16px; padding: 10px 20px; background: var(--panel); border-bottom: 1px solid var(--line); flex-wrap: wrap; }
11
- header strong { font-size: 15px; }
12
- nav { display: flex; gap: 4px; flex-wrap: wrap; }
13
- nav a { padding: 4px 10px; border-radius: 6px; color: var(--muted); text-decoration: none; }
14
- nav a.on { background: var(--bg); color: var(--text); font-weight: 600; }
15
- header .me { margin-left: auto; color: var(--muted); display: flex; gap: 8px; align-items: center; }
16
- main { padding: 20px; max-width: 1200px; margin: 0 auto; }
17
- section { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 16px; margin-bottom: 16px; overflow-x: auto; }
18
- h2 { font-size: 16px; margin: 0 0 12px; }
19
- h3 { font-size: 14px; margin: 16px 0 8px; color: var(--muted); }
20
- table { border-collapse: collapse; width: 100%; }
21
- th, td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
22
- th { color: var(--muted); font-weight: 500; white-space: nowrap; }
23
- td code, pre { font: 12px ui-monospace, SFMono-Regular, Menlo, monospace; }
24
- pre { margin: 0; white-space: pre-wrap; word-break: break-all; max-width: 420px; }
25
- form.row, .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
26
- input, select, textarea { font: inherit; color: inherit; background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px; }
27
- button { font: inherit; border: 1px solid var(--line); background: var(--panel); color: var(--text); border-radius: 6px; padding: 5px 12px; cursor: pointer; }
28
- button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
29
- button.danger { color: var(--danger); }
30
- button:disabled { opacity: .5; cursor: not-allowed; }
31
- .muted { color: var(--muted); }
32
- .tag { display: inline-block; padding: 0 6px; border-radius: 10px; border: 1px solid var(--line); font-size: 12px; margin: 1px; }
33
- .ok { color: var(--ok); } .bad { color: var(--danger); } .warn { color: var(--warn); }
34
- .caps { columns: 3 260px; }
35
- .caps label { display: block; break-inside: avoid; padding: 2px 0; }
36
- .toast { position: fixed; right: 16px; bottom: 16px; max-width: 420px; padding: 10px 14px; border-radius: 8px; background: var(--panel); border: 1px solid var(--line); box-shadow: 0 4px 16px rgba(0,0,0,.15); }
37
- .login { max-width: 360px; margin: 10vh auto; }
38
- .login input { width: 100%; margin-bottom: 10px; }
39
- .split { display: grid; grid-template-columns: 280px 1fr; gap: 16px; }
40
- @media (max-width: 760px) { .split { grid-template-columns: 1fr; } main { padding: 12px; } }
41
- .list-item { padding: 6px 8px; border-radius: 6px; cursor: pointer; }
42
- .list-item.on { background: var(--bg); font-weight: 600; }
5
+ color-scheme: light;
6
+ --canvas: #f4f7f5;
7
+ --surface: #fff;
8
+ --ink: #23352f;
9
+ --secondary: #63756c;
10
+ --muted: #79887f;
11
+ --line: #e4ebe6;
12
+ --line-strong: #cfdad3;
13
+ --accent: #23765a;
14
+ --accent-dark: #175d45;
15
+ --accent-soft: #edf6f0;
16
+ --red: #b74c43;
17
+ --amber: #a87a32;
18
+ --radius: 12px;
19
+ --sidebar: 220px;
20
+ font-family: 'Microsoft YaHei UI', 'PingFang SC', 'Noto Sans CJK SC', sans-serif;
21
+ font-size: 13px;
22
+ }
23
+ * {
24
+ box-sizing: border-box;
25
+ }
26
+ [hidden] {
27
+ display: none !important;
28
+ }
29
+ body {
30
+ min-width: 1080px;
31
+ margin: 0;
32
+ background: var(--canvas);
33
+ color: var(--ink);
34
+ line-height: 1.6;
35
+ }
36
+ button,
37
+ input,
38
+ select,
39
+ textarea {
40
+ font: inherit;
41
+ }
42
+ button,
43
+ a,
44
+ input,
45
+ select,
46
+ textarea {
47
+ -webkit-tap-highlight-color: transparent;
48
+ }
49
+ button {
50
+ display: inline-flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ gap: 7px;
54
+ min-height: 36px;
55
+ padding: 7px 14px;
56
+ border: 1px solid var(--line-strong);
57
+ border-radius: 7px;
58
+ background: white;
59
+ color: var(--ink);
60
+ cursor: pointer;
61
+ transition:
62
+ background 0.15s,
63
+ border-color 0.15s,
64
+ box-shadow 0.15s;
65
+ white-space: nowrap;
66
+ }
67
+ button:hover {
68
+ background: #f6f9f7;
69
+ border-color: #a9beb0;
70
+ }
71
+ button.primary {
72
+ background: var(--accent);
73
+ color: #fff;
74
+ border-color: var(--accent);
75
+ }
76
+ button.primary:hover {
77
+ background: var(--accent-dark);
78
+ border-color: var(--accent-dark);
79
+ }
80
+ button.danger {
81
+ color: var(--red);
82
+ }
83
+ button.danger:hover {
84
+ border-color: #dfb9b4;
85
+ background: #fff7f5;
86
+ }
87
+ button:disabled {
88
+ opacity: 0.48;
89
+ cursor: not-allowed;
90
+ }
91
+ button.small {
92
+ min-height: 30px;
93
+ padding: 4px 10px;
94
+ font-size: 12px;
95
+ }
96
+ button.icon-button {
97
+ width: 34px;
98
+ min-height: 34px;
99
+ padding: 8px;
100
+ background: transparent;
101
+ border-color: transparent;
102
+ color: var(--secondary);
103
+ }
104
+ button.icon-button:hover {
105
+ background: var(--accent-soft);
106
+ }
107
+ button.text-button {
108
+ min-height: 26px;
109
+ padding: 2px 4px;
110
+ background: none;
111
+ border-color: transparent;
112
+ color: var(--accent);
113
+ font-size: 12px;
114
+ }
115
+ button.text-button.danger {
116
+ color: var(--red);
117
+ }
118
+ button.text-button:hover {
119
+ text-decoration: underline;
120
+ }
121
+ :focus-visible {
122
+ outline: 3px solid #8ab9a0;
123
+ outline-offset: 3px;
124
+ }
125
+ input:not([type='checkbox']),
126
+ select,
127
+ textarea {
128
+ width: 100%;
129
+ min-width: 0;
130
+ min-height: 38px;
131
+ padding: 8px 11px;
132
+ border: 1px solid var(--line-strong);
133
+ border-radius: 7px;
134
+ background: #fff;
135
+ color: var(--ink);
136
+ transition:
137
+ border-color 0.15s,
138
+ box-shadow 0.15s;
139
+ }
140
+ input::placeholder,
141
+ textarea::placeholder {
142
+ color: #8a968f;
143
+ }
144
+ input:focus,
145
+ select:focus,
146
+ textarea:focus {
147
+ border-color: #71a88c;
148
+ outline: none;
149
+ box-shadow: 0 0 0 3px #23765a0d;
150
+ }
151
+ input:disabled,
152
+ select:disabled,
153
+ textarea:disabled {
154
+ background: #f5f7f5;
155
+ color: var(--secondary);
156
+ cursor: not-allowed;
157
+ }
158
+ input[type='checkbox'] {
159
+ width: 16px;
160
+ height: 16px;
161
+ flex-shrink: 0;
162
+ accent-color: var(--accent);
163
+ cursor: pointer;
164
+ }
165
+ textarea {
166
+ resize: vertical;
167
+ }
168
+ a {
169
+ color: var(--accent);
170
+ text-decoration: none;
171
+ }
172
+ h1,
173
+ h2,
174
+ h3,
175
+ p {
176
+ margin: 0;
177
+ }
178
+ h1 {
179
+ font-size: 26px;
180
+ line-height: 1.5;
181
+ font-weight: 650;
182
+ letter-spacing: 0.5px;
183
+ }
184
+ h2 {
185
+ font-size: 15px;
186
+ font-weight: 650;
187
+ }
188
+ h3 {
189
+ font-size: 14px;
190
+ font-weight: 600;
191
+ }
192
+ strong {
193
+ font-weight: 600;
194
+ }
195
+ small {
196
+ font-size: 11px;
197
+ }
198
+ code,
199
+ pre {
200
+ font-family: 'Cascadia Code', Consolas, monospace;
201
+ font-size: 11px;
202
+ }
203
+ code {
204
+ overflow-wrap: anywhere;
205
+ }
206
+ pre {
207
+ max-width: 520px;
208
+ max-height: 300px;
209
+ overflow: auto;
210
+ margin: 10px 0 0;
211
+ padding: 12px;
212
+ background: #f4f7f5;
213
+ border: 1px solid var(--line);
214
+ border-radius: 6px;
215
+ color: var(--secondary);
216
+ white-space: pre-wrap;
217
+ overflow-wrap: anywhere;
218
+ }
219
+ .icon {
220
+ width: 18px;
221
+ height: 18px;
222
+ flex-shrink: 0;
223
+ vertical-align: middle;
224
+ }
225
+ .muted {
226
+ color: var(--muted);
227
+ }
228
+ .eyebrow {
229
+ display: block;
230
+ margin-bottom: 4px;
231
+ font-size: 10px;
232
+ letter-spacing: 2px;
233
+ color: var(--muted);
234
+ }
235
+
236
+ /* 固定导航与独立内容滚动视觉,避免每个管理页面再创造一套页面骨架。 */
237
+ .app-sidebar {
238
+ position: fixed;
239
+ inset: 0 auto 0 0;
240
+ z-index: 10;
241
+ display: flex;
242
+ flex-direction: column;
243
+ width: var(--sidebar);
244
+ padding: 29px 17px 20px;
245
+ background: #fbfcfa;
246
+ border-right: 1px solid var(--line);
247
+ }
248
+ .brand {
249
+ display: flex;
250
+ align-items: center;
251
+ gap: 11px;
252
+ padding: 0 14px 30px;
253
+ color: var(--ink);
254
+ }
255
+ .brand > span:last-child {
256
+ font:
257
+ 600 26px/1 Bahnschrift,
258
+ sans-serif;
259
+ letter-spacing: -0.8px;
260
+ }
261
+ .brand small {
262
+ display: block;
263
+ margin-top: 8px;
264
+ font:
265
+ 10px/1.4 'Microsoft YaHei UI',
266
+ sans-serif;
267
+ letter-spacing: 3px;
268
+ color: var(--secondary);
269
+ }
270
+ .brand-mark {
271
+ display: inline-flex;
272
+ align-items: center;
273
+ justify-content: center;
274
+ width: 37px;
275
+ height: 40px;
276
+ border-radius: 10px;
277
+ background: var(--accent);
278
+ color: white;
279
+ box-shadow: inset 0 0 0 1px #ffffff20;
280
+ }
281
+ .brand-mark .icon {
282
+ width: 21px;
283
+ height: 21px;
284
+ stroke-width: 1.6;
285
+ }
286
+ .nav-group {
287
+ margin-top: 15px;
288
+ }
289
+ .nav-caption {
290
+ margin: 0 14px 10px;
291
+ color: #87938a;
292
+ font-size: 10px;
293
+ letter-spacing: 1px;
294
+ }
295
+ .nav-item {
296
+ display: flex;
297
+ align-items: center;
298
+ gap: 12px;
299
+ min-height: 45px;
300
+ margin: 4px 0;
301
+ padding: 10px 14px;
302
+ border-radius: 8px;
303
+ color: var(--secondary);
304
+ }
305
+ .nav-item:hover {
306
+ background: #f0f4ef;
307
+ }
308
+ .nav-item.active {
309
+ background: #e8f2eb;
310
+ color: var(--accent-dark);
311
+ font-weight: 600;
312
+ }
313
+ .nav-active-dot {
314
+ width: 5px;
315
+ height: 5px;
316
+ margin-left: auto;
317
+ border-radius: 100%;
318
+ background: var(--accent);
319
+ }
320
+ .sidebar-bottom {
321
+ margin-top: auto;
322
+ padding: 18px 11px 0;
323
+ }
324
+ .workspace-label {
325
+ display: flex;
326
+ align-items: center;
327
+ gap: 7px;
328
+ padding: 14px 0;
329
+ border-top: 1px solid var(--line);
330
+ font-size: 10px;
331
+ color: var(--muted);
332
+ }
333
+ .connection-dot {
334
+ width: 6px;
335
+ height: 6px;
336
+ border-radius: 50%;
337
+ background: #69a27d;
338
+ }
339
+ .back-to-business {
340
+ display: flex;
341
+ gap: 7px;
342
+ align-items: center;
343
+ font-size: 11px;
344
+ color: var(--secondary);
345
+ }
346
+ .back-to-business .icon {
347
+ width: 14px;
348
+ height: 14px;
349
+ }
350
+ .app-main {
351
+ min-height: 100vh;
352
+ margin-left: var(--sidebar);
353
+ }
354
+ .app-topbar {
355
+ position: sticky;
356
+ top: 0;
357
+ z-index: 8;
358
+ display: flex;
359
+ justify-content: space-between;
360
+ align-items: center;
361
+ height: 75px;
362
+ padding: 0 34px;
363
+ border-bottom: 1px solid var(--line);
364
+ background: #ffffffed;
365
+ backdrop-filter: blur(16px);
366
+ }
367
+ .breadcrumb {
368
+ display: flex;
369
+ align-items: center;
370
+ gap: 12px;
371
+ color: var(--muted);
372
+ font-size: 11px;
373
+ }
374
+ .breadcrumb .icon {
375
+ width: 10px;
376
+ height: 10px;
377
+ color: #adb8b0;
378
+ }
379
+ .breadcrumb strong {
380
+ color: var(--ink);
381
+ font-weight: 500;
382
+ }
383
+ .account {
384
+ display: flex;
385
+ align-items: center;
386
+ gap: 10px;
387
+ }
388
+ .avatar,
389
+ .person-avatar {
390
+ display: inline-flex;
391
+ align-items: center;
392
+ justify-content: center;
393
+ width: 32px;
394
+ height: 32px;
395
+ border-radius: 50%;
396
+ background: #e9efe9;
397
+ color: #49705c;
398
+ font-size: 12px;
399
+ }
400
+ .account-copy {
401
+ display: flex;
402
+ flex-direction: column;
403
+ min-width: 76px;
404
+ line-height: 1.7;
405
+ }
406
+ .account-copy strong {
407
+ font-size: 11px;
408
+ }
409
+ .account-copy small {
410
+ font-size: 9px;
411
+ color: var(--muted);
412
+ }
413
+ .page-container {
414
+ max-width: 1700px;
415
+ margin: 0 auto;
416
+ padding: 28px 34px 18px;
417
+ }
418
+ .page-heading {
419
+ display: flex;
420
+ align-items: center;
421
+ justify-content: space-between;
422
+ gap: 20px;
423
+ margin-bottom: 25px;
424
+ }
425
+ .page-heading p {
426
+ margin-top: 6px;
427
+ font-size: 12px;
428
+ color: var(--secondary);
429
+ }
430
+ .refresh-button {
431
+ color: var(--secondary);
432
+ font-size: 12px;
433
+ }
434
+ .refresh-button .icon {
435
+ width: 14px;
436
+ height: 14px;
437
+ }
438
+ .page-content {
439
+ animation: enter 0.25s ease-out;
440
+ }
441
+ .page-footer {
442
+ display: flex;
443
+ justify-content: space-between;
444
+ align-items: center;
445
+ margin-top: 28px;
446
+ padding-top: 18px;
447
+ border-top: 1px solid var(--line);
448
+ color: var(--muted);
449
+ font-size: 10px;
450
+ }
451
+ .page-footer > span:last-child {
452
+ display: inline-flex;
453
+ align-items: center;
454
+ gap: 5px;
455
+ }
456
+ .page-footer .icon {
457
+ width: 12px;
458
+ height: 12px;
459
+ }
460
+
461
+ /* 通用记录页面:低对比表头、可展开明细,中文名称始终比代码标识更醒目。 */
462
+ .panel {
463
+ min-width: 0;
464
+ margin-bottom: 20px;
465
+ overflow: hidden;
466
+ border: 1px solid var(--line);
467
+ border-radius: var(--radius);
468
+ background: var(--surface);
469
+ }
470
+ .panel-heading {
471
+ display: flex;
472
+ align-items: center;
473
+ justify-content: space-between;
474
+ gap: 16px;
475
+ padding: 21px 24px;
476
+ }
477
+ .panel-heading p {
478
+ margin-top: 5px;
479
+ font-size: 11px;
480
+ color: var(--secondary);
481
+ }
482
+ .table-wrap {
483
+ width: 100%;
484
+ overflow-x: auto;
485
+ }
486
+ table {
487
+ width: 100%;
488
+ border-collapse: collapse;
489
+ text-align: left;
490
+ }
491
+ th {
492
+ padding: 12px 22px;
493
+ border-block: 1px solid var(--line);
494
+ background: #f8faf8;
495
+ color: var(--secondary);
496
+ font-weight: 500;
497
+ font-size: 11px;
498
+ white-space: nowrap;
499
+ }
500
+ td {
501
+ padding: 16px 22px;
502
+ border-bottom: 1px solid #edf1ed;
503
+ vertical-align: middle;
504
+ font-size: 12px;
505
+ }
506
+ tbody tr:last-child td {
507
+ border-bottom: 0;
508
+ }
509
+ tbody tr:hover {
510
+ background: #fbfdfb;
511
+ }
512
+ td select {
513
+ min-width: 180px;
514
+ max-width: 260px;
515
+ font-size: 12px;
516
+ }
517
+ .table-empty {
518
+ height: 128px;
519
+ text-align: center;
520
+ color: var(--muted);
521
+ }
522
+ .stack-cell {
523
+ display: flex;
524
+ flex-direction: column;
525
+ gap: 4px;
526
+ min-width: 95px;
527
+ }
528
+ .stack-cell code,
529
+ .stack-cell small {
530
+ color: var(--muted);
531
+ }
532
+ .entity-cell,
533
+ .person-cell {
534
+ display: flex;
535
+ align-items: center;
536
+ gap: 11px;
537
+ }
538
+ .entity-icon {
539
+ display: flex;
540
+ color: #76927f;
541
+ }
542
+ .person-cell small {
543
+ display: block;
544
+ color: var(--muted);
545
+ }
546
+ .tag-list,
547
+ .row-actions,
548
+ .section-actions {
549
+ display: flex;
550
+ flex-wrap: wrap;
551
+ align-items: center;
552
+ gap: 7px;
553
+ }
554
+ .row-actions {
555
+ flex-wrap: nowrap;
556
+ }
557
+ .badge {
558
+ display: inline-flex;
559
+ align-items: center;
560
+ align-self: flex-start;
561
+ padding: 2px 8px;
562
+ border: 1px solid #e7ece7;
563
+ border-radius: 5px;
564
+ background: #f4f6f3;
565
+ color: #697970;
566
+ font-size: 10px;
567
+ line-height: 1.65;
568
+ white-space: nowrap;
569
+ }
570
+ .badge.green {
571
+ color: #338160;
572
+ background: #edf7f0;
573
+ border-color: #dceee2;
574
+ }
575
+ .badge.red {
576
+ color: var(--red);
577
+ background: #fdf1ee;
578
+ border-color: #f1dad6;
579
+ }
580
+ .badge.amber {
581
+ color: var(--amber);
582
+ background: #fcf6e9;
583
+ border-color: #f1e6cc;
584
+ }
585
+ .stats-row {
586
+ display: grid;
587
+ grid-template-columns: repeat(3, 1fr);
588
+ gap: 18px;
589
+ margin-bottom: 22px;
590
+ }
591
+ .stat-card {
592
+ display: flex;
593
+ align-items: center;
594
+ gap: 18px;
595
+ padding: 22px 24px;
596
+ border: 1px solid var(--line);
597
+ border-radius: var(--radius);
598
+ background: var(--surface);
599
+ }
600
+ .stat-icon {
601
+ display: flex;
602
+ align-items: center;
603
+ justify-content: center;
604
+ width: 44px;
605
+ height: 44px;
606
+ border-radius: 11px;
607
+ background: #f0f5ef;
608
+ color: #688e73;
609
+ }
610
+ .stat-card > div {
611
+ display: flex;
612
+ flex: 1;
613
+ align-items: center;
614
+ justify-content: space-between;
615
+ gap: 12px;
616
+ }
617
+ .stat-card > div > span {
618
+ font-size: 12px;
619
+ color: var(--secondary);
620
+ }
621
+ .stat-card strong {
622
+ font:
623
+ 500 30px/1 Bahnschrift,
624
+ sans-serif;
625
+ color: var(--ink);
626
+ }
627
+ .stat-card.attention .stat-icon {
628
+ background: #fcf4e6;
629
+ color: var(--amber);
630
+ }
631
+ .table-toolbar {
632
+ display: flex;
633
+ align-items: center;
634
+ justify-content: space-between;
635
+ gap: 16px;
636
+ padding: 0 24px 20px;
637
+ }
638
+ .table-toolbar .search-field {
639
+ max-width: 350px;
640
+ }
641
+ details summary {
642
+ cursor: pointer;
643
+ color: var(--accent);
644
+ font-size: 11px;
645
+ }
646
+ .failure-summary {
647
+ max-width: 320px;
648
+ color: var(--red);
649
+ }
650
+ .audit-filters,
651
+ .sync-filters {
652
+ display: grid;
653
+ grid-template-columns: repeat(3, minmax(0, 1fr));
654
+ align-items: end;
655
+ gap: 14px;
656
+ margin: 0 24px 24px;
657
+ padding: 18px;
658
+ border: 1px solid var(--line);
659
+ border-radius: 8px;
660
+ background: #fafcf9;
661
+ }
662
+ .audit-filters > button {
663
+ justify-self: end;
664
+ }
665
+ .sync-filters {
666
+ grid-template-columns: minmax(240px, 1fr) minmax(180px, 1fr) auto;
667
+ }
668
+ .pagination {
669
+ display: flex;
670
+ align-items: center;
671
+ justify-content: space-between;
672
+ padding: 16px 24px;
673
+ border-top: 1px solid var(--line);
674
+ font-size: 11px;
675
+ }
676
+
677
+ /* 角色页把“选谁”和“配什么”分开;权限按业务对象分组,保留稳定标识便于排障。 */
678
+ .role-workspace {
679
+ display: grid;
680
+ grid-template-columns: 244px minmax(0, 1fr);
681
+ gap: 22px;
682
+ align-items: start;
683
+ }
684
+ .role-sidebar {
685
+ position: sticky;
686
+ top: 99px;
687
+ padding: 21px 15px 16px;
688
+ border: 1px solid var(--line);
689
+ border-radius: var(--radius);
690
+ background: var(--surface);
691
+ }
692
+ .role-list-heading {
693
+ display: flex;
694
+ align-items: center;
695
+ justify-content: space-between;
696
+ padding: 0 5px;
697
+ }
698
+ .sidebar-description {
699
+ margin: 10px 5px 17px;
700
+ font-size: 11px;
701
+ line-height: 1.9;
702
+ }
703
+ .role-sidebar .search-field {
704
+ margin: 0 3px 15px;
705
+ }
706
+ .role-sidebar .search-field input {
707
+ font-size: 10px;
708
+ }
709
+ .role-list {
710
+ display: flex;
711
+ flex-direction: column;
712
+ gap: 5px;
713
+ max-height: calc(100vh - 360px);
714
+ min-height: 80px;
715
+ overflow-y: auto;
716
+ }
717
+ .role-item {
718
+ width: 100%;
719
+ min-height: 65px;
720
+ padding: 10px;
721
+ gap: 10px;
722
+ border-color: transparent;
723
+ background: transparent;
724
+ text-align: left;
725
+ white-space: normal;
726
+ }
727
+ .role-item.selected {
728
+ border-color: #d8e8dc;
729
+ background: #eef6ef;
730
+ }
731
+ .role-avatar {
732
+ display: flex;
733
+ align-items: center;
734
+ justify-content: center;
735
+ width: 31px;
736
+ height: 34px;
737
+ flex-shrink: 0;
738
+ border: 1px solid #e1e9e1;
739
+ border-radius: 7px;
740
+ background: #fafcf9;
741
+ color: #83968a;
742
+ }
743
+ .role-item.selected .role-avatar {
744
+ background: #fff;
745
+ color: var(--accent);
746
+ border-color: #d5e6d9;
747
+ }
748
+ .role-avatar .icon {
749
+ width: 16px;
750
+ height: 16px;
751
+ }
752
+ .role-item-copy {
753
+ flex: 1;
754
+ min-width: 0;
755
+ }
756
+ .role-item-copy strong {
757
+ display: block;
758
+ font-size: 12px;
759
+ }
760
+ .role-item-copy small {
761
+ display: block;
762
+ margin-top: 2px;
763
+ font:
764
+ 10px/1.5 'Cascadia Code',
765
+ Consolas,
766
+ monospace;
767
+ overflow-wrap: anywhere;
768
+ color: var(--muted);
769
+ }
770
+ .role-item-count {
771
+ font:
772
+ 12px/1 Bahnschrift,
773
+ sans-serif;
774
+ color: #829388;
775
+ }
776
+ .create-role {
777
+ width: 100%;
778
+ margin-top: 19px;
779
+ }
780
+ .list-empty {
781
+ padding: 25px 10px;
782
+ font-size: 11px;
783
+ text-align: center;
784
+ color: var(--muted);
785
+ }
786
+ .role-details {
787
+ min-width: 0;
788
+ }
789
+ .role-summary {
790
+ display: flex;
791
+ align-items: center;
792
+ justify-content: space-between;
793
+ gap: 15px;
794
+ padding: 26px;
795
+ border: 1px solid var(--line);
796
+ border-bottom: 0;
797
+ border-radius: var(--radius) var(--radius) 0 0;
798
+ background: white;
799
+ }
800
+ .role-title {
801
+ display: flex;
802
+ align-items: center;
803
+ gap: 15px;
804
+ min-width: 0;
805
+ }
806
+ .role-emblem {
807
+ display: flex;
808
+ align-items: center;
809
+ justify-content: center;
810
+ width: 48px;
811
+ height: 52px;
812
+ border-radius: 11px;
813
+ background: #edf5ed;
814
+ color: var(--accent);
815
+ }
816
+ .role-emblem .icon {
817
+ width: 25px;
818
+ height: 25px;
819
+ }
820
+ .title-line {
821
+ display: flex;
822
+ align-items: center;
823
+ gap: 10px;
824
+ }
825
+ .title-line h2 {
826
+ font-size: 20px;
827
+ }
828
+ .role-title p {
829
+ display: flex;
830
+ align-items: center;
831
+ gap: 8px;
832
+ margin-top: 5px;
833
+ color: var(--muted);
834
+ font-size: 10px;
835
+ }
836
+ .permission-total {
837
+ display: flex;
838
+ align-items: center;
839
+ gap: 8px;
840
+ padding-left: 23px;
841
+ border-left: 1px solid var(--line);
842
+ }
843
+ .permission-total strong {
844
+ font:
845
+ 500 28px/1 Bahnschrift,
846
+ sans-serif;
847
+ color: var(--accent);
848
+ }
849
+ .permission-total span {
850
+ font-size: 10px;
851
+ color: var(--secondary);
852
+ }
853
+ .role-tabs {
854
+ display: flex;
855
+ gap: 29px;
856
+ padding: 0 26px;
857
+ border: 1px solid var(--line);
858
+ border-top: 0;
859
+ border-radius: 0 0 var(--radius) var(--radius);
860
+ background: white;
861
+ }
862
+ .role-tabs button {
863
+ position: relative;
864
+ min-height: 51px;
865
+ padding: 12px 1px;
866
+ border: 0;
867
+ border-radius: 0;
868
+ background: none;
869
+ font-size: 12px;
870
+ color: var(--secondary);
871
+ }
872
+ .role-tabs .icon {
873
+ width: 15px;
874
+ height: 15px;
875
+ }
876
+ .role-tabs button.active {
877
+ color: var(--accent);
878
+ font-weight: 600;
879
+ }
880
+ .role-tabs button.active::after {
881
+ position: absolute;
882
+ bottom: 0;
883
+ inset-inline: 0;
884
+ height: 3px;
885
+ border-radius: 3px 3px 0 0;
886
+ background: var(--accent);
887
+ content: '';
888
+ }
889
+ .role-tab-body {
890
+ padding-top: 22px;
891
+ }
892
+ .permission-toolbar {
893
+ display: flex;
894
+ align-items: center;
895
+ justify-content: space-between;
896
+ gap: 12px;
897
+ }
898
+ .permission-toolbar .search-field {
899
+ max-width: 370px;
900
+ }
901
+ .search-field {
902
+ display: flex;
903
+ align-items: center;
904
+ gap: 8px;
905
+ flex: 1;
906
+ min-width: 0;
907
+ padding-left: 11px;
908
+ border: 1px solid var(--line-strong);
909
+ border-radius: 7px;
910
+ background: white;
911
+ color: #8a9a90;
912
+ }
913
+ .search-field .icon {
914
+ width: 15px;
915
+ height: 15px;
916
+ }
917
+ .search-field input {
918
+ min-height: 36px;
919
+ padding-left: 0;
920
+ border: 0;
921
+ background: transparent;
922
+ font-size: 11px;
923
+ box-shadow: none;
924
+ }
925
+ .search-field:focus-within {
926
+ border-color: #71a88c;
927
+ box-shadow: 0 0 0 3px #23765a0d;
928
+ }
929
+ .search-field input:focus {
930
+ box-shadow: none;
931
+ }
932
+ .segmented {
933
+ display: flex;
934
+ flex-shrink: 0;
935
+ padding: 3px;
936
+ gap: 2px;
937
+ border: 1px solid var(--line);
938
+ border-radius: 7px;
939
+ background: #eaf0eb;
940
+ }
941
+ .segmented button {
942
+ min-height: 29px;
943
+ padding: 4px 12px;
944
+ border: 0;
945
+ border-radius: 4px;
946
+ background: transparent;
947
+ font-size: 11px;
948
+ color: var(--secondary);
949
+ }
950
+ .segmented button.active {
951
+ background: #fff;
952
+ color: var(--accent-dark);
953
+ box-shadow: 0 1px 4px #243e2912;
954
+ }
955
+ .permission-help {
956
+ display: flex;
957
+ justify-content: space-between;
958
+ gap: 12px;
959
+ margin: 14px 0 17px;
960
+ font-size: 10px;
961
+ color: var(--secondary);
962
+ }
963
+ .permission-help > span:first-child {
964
+ display: flex;
965
+ gap: 5px;
966
+ align-items: center;
967
+ }
968
+ .permission-help .icon {
969
+ width: 13px;
970
+ height: 13px;
971
+ color: #94a59a;
972
+ }
973
+ .result-count {
974
+ white-space: nowrap;
975
+ }
976
+ .permission-grid {
977
+ display: grid;
978
+ grid-template-columns: repeat(2, minmax(0, 1fr));
979
+ align-items: start;
980
+ gap: 16px;
981
+ }
982
+ .permission-card {
983
+ min-width: 0;
984
+ overflow: hidden;
985
+ border: 1px solid var(--line);
986
+ border-radius: var(--radius);
987
+ background: var(--surface);
988
+ }
989
+ .permission-card-heading {
990
+ display: flex;
991
+ align-items: center;
992
+ gap: 11px;
993
+ padding: 17px 19px;
994
+ border-bottom: 1px solid var(--line);
995
+ background: #fcfdfb;
996
+ }
997
+ .group-icon {
998
+ display: flex;
999
+ justify-content: center;
1000
+ align-items: center;
1001
+ width: 33px;
1002
+ height: 35px;
1003
+ border: 1px solid #e1ebe1;
1004
+ border-radius: 7px;
1005
+ background: #f0f6ef;
1006
+ color: #6a9477;
1007
+ }
1008
+ .group-icon.system {
1009
+ background: #f4f1e9;
1010
+ color: #9b8e69;
1011
+ border-color: #ede7da;
1012
+ }
1013
+ .group-icon .icon {
1014
+ width: 17px;
1015
+ height: 17px;
1016
+ }
1017
+ .group-title {
1018
+ flex: 1;
1019
+ min-width: 0;
1020
+ }
1021
+ .group-title h3 {
1022
+ font-size: 13px;
1023
+ }
1024
+ .group-title code {
1025
+ color: var(--muted);
1026
+ font-size: 10px;
1027
+ }
1028
+ .group-progress {
1029
+ padding: 2px 7px;
1030
+ border: 1px solid #e6ece6;
1031
+ border-radius: 5px;
1032
+ font:
1033
+ 10px/1.6 'Cascadia Code',
1034
+ Consolas,
1035
+ monospace;
1036
+ color: var(--muted);
1037
+ }
1038
+ .permission-row {
1039
+ position: relative;
1040
+ display: flex;
1041
+ flex-wrap: wrap;
1042
+ align-items: center;
1043
+ gap: 6px;
1044
+ padding: 13px 19px;
1045
+ border-bottom: 1px solid #f0f3ef;
1046
+ }
1047
+ .permission-row:last-child {
1048
+ border-bottom: 0;
1049
+ }
1050
+ .permission-toggle {
1051
+ display: flex;
1052
+ align-items: center;
1053
+ flex: 1;
1054
+ gap: 11px;
1055
+ min-width: 0;
1056
+ cursor: pointer;
1057
+ }
1058
+ /* 保留真实 checkbox 的键盘与读屏语义,仅替换视觉外观。 */
1059
+ .permission-toggle > input {
1060
+ position: absolute;
1061
+ width: 1px;
1062
+ height: 1px;
1063
+ opacity: 0;
1064
+ }
1065
+ .checkbox-visual {
1066
+ display: inline-flex;
1067
+ align-items: center;
1068
+ justify-content: center;
1069
+ width: 16px;
1070
+ height: 16px;
1071
+ flex-shrink: 0;
1072
+ border: 1px solid #cdd9cf;
1073
+ border-radius: 4px;
1074
+ background: #fff;
1075
+ transition: background 0.12s;
1076
+ }
1077
+ .checkbox-visual .icon {
1078
+ width: 12px;
1079
+ height: 12px;
1080
+ stroke-width: 2.5;
1081
+ opacity: 0;
1082
+ }
1083
+ .permission-toggle > input:checked + .checkbox-visual {
1084
+ border-color: var(--accent);
1085
+ background: var(--accent);
1086
+ color: white;
1087
+ }
1088
+ .permission-toggle > input:checked + .checkbox-visual .icon {
1089
+ opacity: 1;
1090
+ }
1091
+ .permission-toggle > input:focus-visible + .checkbox-visual {
1092
+ outline: 3px solid #8ab9a0;
1093
+ outline-offset: 3px;
1094
+ }
1095
+ .permission-toggle > input:disabled + .checkbox-visual {
1096
+ opacity: 0.45;
1097
+ }
1098
+ .permission-toggle:has(input:disabled) {
1099
+ cursor: not-allowed;
1100
+ }
1101
+ .permission-copy {
1102
+ display: flex;
1103
+ flex-direction: column;
1104
+ gap: 1px;
1105
+ min-width: 0;
1106
+ }
1107
+ .permission-name {
1108
+ font-size: 12px;
1109
+ color: var(--ink);
1110
+ }
1111
+ .permission-copy code {
1112
+ font-size: 10px;
1113
+ color: #88968d;
1114
+ }
1115
+ .invocation-badge {
1116
+ padding: 1px 5px;
1117
+ border-radius: 4px;
1118
+ background: #f3f4ef;
1119
+ font-size: 9px;
1120
+ color: #8c947c;
1121
+ }
1122
+ .limit-form {
1123
+ display: flex;
1124
+ align-items: center;
1125
+ gap: 7px;
1126
+ width: 100%;
1127
+ padding: 9px 0 1px 27px;
1128
+ font-size: 10px;
1129
+ color: var(--secondary);
1130
+ }
1131
+ .limit-form input {
1132
+ width: 110px;
1133
+ min-height: 29px;
1134
+ padding: 4px 7px;
1135
+ font-size: 11px;
1136
+ }
1137
+ .limit-form button {
1138
+ min-height: 29px;
1139
+ font-size: 10px;
1140
+ }
1141
+ .scope-grid {
1142
+ display: grid;
1143
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1144
+ gap: 16px;
1145
+ margin-top: 17px;
1146
+ align-items: start;
1147
+ }
1148
+ .scope-card {
1149
+ padding: 21px;
1150
+ border: 1px solid var(--line);
1151
+ border-radius: var(--radius);
1152
+ background: white;
1153
+ }
1154
+ .scope-card.default-scope {
1155
+ grid-column: 1 / -1;
1156
+ border-color: #cbded0;
1157
+ background: #fafdf9;
1158
+ }
1159
+ .scope-heading {
1160
+ display: flex;
1161
+ justify-content: space-between;
1162
+ gap: 10px;
1163
+ margin-bottom: 17px;
1164
+ }
1165
+ .scope-heading code {
1166
+ display: block;
1167
+ margin-top: 3px;
1168
+ color: var(--muted);
1169
+ font-size: 10px;
1170
+ }
1171
+ .scope-description {
1172
+ min-height: 35px;
1173
+ margin-top: 9px;
1174
+ color: var(--secondary);
1175
+ font-size: 11px;
1176
+ }
1177
+ .scope-footer {
1178
+ display: flex;
1179
+ justify-content: space-between;
1180
+ align-items: center;
1181
+ margin-top: 13px;
1182
+ padding-top: 13px;
1183
+ border-top: 1px solid var(--line);
1184
+ }
1185
+ .save-state {
1186
+ color: var(--muted);
1187
+ font-size: 10px;
1188
+ }
1189
+ .save-state.pending {
1190
+ color: var(--amber);
1191
+ }
1192
+ .department-options {
1193
+ display: grid;
1194
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1195
+ gap: 8px;
1196
+ max-height: 200px;
1197
+ overflow: auto;
1198
+ margin-top: 10px;
1199
+ padding: 12px;
1200
+ border: 1px solid var(--line);
1201
+ border-radius: 6px;
1202
+ }
1203
+ .department-options label {
1204
+ display: flex;
1205
+ align-items: center;
1206
+ gap: 7px;
1207
+ font-size: 11px;
1208
+ }
1209
+
1210
+ /* 表单和反馈共用清晰的保存状态;原生 dialog 提供焦点隔离与 Escape 关闭。 */
1211
+ .field {
1212
+ display: flex;
1213
+ flex-direction: column;
1214
+ gap: 7px;
1215
+ min-width: 0;
1216
+ }
1217
+ .field > span {
1218
+ font-size: 12px;
1219
+ font-weight: 500;
1220
+ }
1221
+ .field > small {
1222
+ color: var(--muted);
1223
+ line-height: 1.8;
1224
+ }
1225
+ .stack-form {
1226
+ display: flex;
1227
+ flex-direction: column;
1228
+ gap: 19px;
1229
+ }
1230
+ .form-actions {
1231
+ display: flex;
1232
+ justify-content: flex-end;
1233
+ margin-top: 5px;
1234
+ padding-top: 18px;
1235
+ border-top: 1px solid var(--line);
1236
+ }
1237
+ .model-overview { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 26px 0; }
1238
+ body:has(.model-overview) { min-width: 0; }
1239
+ .model-overview h2 { margin: 8px 0; font-size: 24px; font-weight: 500; }
1240
+ .model-overview p, .model-meta, .model-save-status { color: var(--muted); font-size: 12px; line-height: 1.8; }
1241
+ .model-meta { display: flex; gap: 18px; align-items: center; padding: 0 24px 20px; flex-wrap: wrap; }
1242
+ .model-form { padding: 0 24px 24px; }
1243
+ .model-fields { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; }
1244
+ .model-fields input:not([type=checkbox]) { width: 100%; box-sizing: border-box; }
1245
+ .model-enabled { display: flex; gap: 10px; align-items: center; }
1246
+ .model-actions { display: flex; gap: 12px; align-items: center; border-top: 1px solid var(--line); margin-top: 24px; padding-top: 20px; }
1247
+ .model-save-status { flex: 1; }
1248
+ @media (max-width: 700px) { .model-fields { grid-template-columns: 1fr; } .model-actions, .model-overview { flex-wrap: wrap; } .model-save-status { flex-basis: 100%; } }
1249
+ .modal {
1250
+ width: 470px;
1251
+ max-width: 80vw;
1252
+ max-height: 85vh;
1253
+ padding: 25px;
1254
+ border: 1px solid var(--line);
1255
+ border-radius: 14px;
1256
+ background: white;
1257
+ color: var(--ink);
1258
+ box-shadow: 0 25px 100px #1c382b26;
1259
+ }
1260
+ .modal::backdrop {
1261
+ background: #1a302c55;
1262
+ backdrop-filter: blur(4px);
1263
+ }
1264
+ .modal-heading {
1265
+ display: flex;
1266
+ justify-content: space-between;
1267
+ align-items: center;
1268
+ margin-bottom: 22px;
1269
+ }
1270
+ .modal-heading h2 {
1271
+ font-size: 18px;
1272
+ }
1273
+ .modal-heading .icon-button {
1274
+ font-size: 23px;
1275
+ font-weight: 300;
1276
+ }
1277
+ .choice-list {
1278
+ display: flex;
1279
+ flex-direction: column;
1280
+ gap: 8px;
1281
+ max-height: 330px;
1282
+ overflow: auto;
1283
+ }
1284
+ .choice-list label {
1285
+ display: flex;
1286
+ align-items: center;
1287
+ gap: 12px;
1288
+ padding: 13px;
1289
+ border: 1px solid var(--line);
1290
+ border-radius: 7px;
1291
+ cursor: pointer;
1292
+ }
1293
+ .choice-list small {
1294
+ display: block;
1295
+ color: var(--muted);
1296
+ font-family: 'Cascadia Code', Consolas, monospace;
1297
+ }
1298
+ .inline-info {
1299
+ display: flex;
1300
+ gap: 8px;
1301
+ align-items: flex-start;
1302
+ padding: 12px 14px;
1303
+ border: 1px solid #e0e9de;
1304
+ border-radius: 7px;
1305
+ background: #f4f8f1;
1306
+ color: #6e8069;
1307
+ font-size: 11px;
1308
+ line-height: 1.9;
1309
+ }
1310
+ .inline-info .icon {
1311
+ width: 15px;
1312
+ height: 15px;
1313
+ margin-top: 3px;
1314
+ }
1315
+ #notifications {
1316
+ position: fixed;
1317
+ top: 89px;
1318
+ right: 28px;
1319
+ z-index: 100;
1320
+ display: flex;
1321
+ flex-direction: column;
1322
+ gap: 9px;
1323
+ pointer-events: none;
1324
+ }
1325
+ .toast {
1326
+ display: flex;
1327
+ align-items: flex-start;
1328
+ gap: 9px;
1329
+ max-width: 420px;
1330
+ padding: 14px 18px;
1331
+ border: 1px solid #cde2d3;
1332
+ border-radius: 9px;
1333
+ background: #fafffa;
1334
+ box-shadow: 0 6px 24px #20382a12;
1335
+ color: var(--accent-dark);
1336
+ font-size: 12px;
1337
+ animation: enter 0.2s ease-out;
1338
+ }
1339
+ .toast .icon {
1340
+ width: 16px;
1341
+ height: 16px;
1342
+ margin-top: 2px;
1343
+ }
1344
+ .toast.error {
1345
+ border-color: #e9c9c3;
1346
+ background: #fff9f7;
1347
+ color: var(--red);
1348
+ }
1349
+ .empty-state {
1350
+ display: flex;
1351
+ flex-direction: column;
1352
+ align-items: center;
1353
+ justify-content: center;
1354
+ min-height: 280px;
1355
+ padding: 40px;
1356
+ text-align: center;
1357
+ }
1358
+ .empty-icon {
1359
+ display: flex;
1360
+ align-items: center;
1361
+ justify-content: center;
1362
+ width: 60px;
1363
+ height: 60px;
1364
+ margin-bottom: 19px;
1365
+ border: 1px solid #e1eadf;
1366
+ border-radius: 18px;
1367
+ background: #f3f7f0;
1368
+ color: #8aa080;
1369
+ }
1370
+ .empty-icon .icon {
1371
+ width: 27px;
1372
+ height: 27px;
1373
+ }
1374
+ .empty-state h3 {
1375
+ margin-bottom: 9px;
1376
+ font-size: 16px;
1377
+ }
1378
+ .empty-state p {
1379
+ max-width: 440px;
1380
+ color: var(--secondary);
1381
+ font-size: 12px;
1382
+ line-height: 1.9;
1383
+ }
1384
+ .permission-grid > .empty-state {
1385
+ grid-column: 1 / -1;
1386
+ border: 1px dashed var(--line-strong);
1387
+ border-radius: var(--radius);
1388
+ }
1389
+ .loading-panel {
1390
+ display: flex;
1391
+ align-items: center;
1392
+ justify-content: center;
1393
+ gap: 10px;
1394
+ min-height: 180px;
1395
+ color: var(--secondary);
1396
+ }
1397
+ .spinner {
1398
+ width: 17px;
1399
+ height: 17px;
1400
+ border: 2px solid #e0ebe1;
1401
+ border-top-color: var(--accent);
1402
+ border-radius: 50%;
1403
+ animation: rotate 0.7s linear infinite;
1404
+ }
1405
+ .error-panel {
1406
+ display: flex;
1407
+ gap: 14px;
1408
+ align-items: flex-start;
1409
+ padding: 28px;
1410
+ border: 1px solid #eadbd4;
1411
+ border-radius: var(--radius);
1412
+ background: #fffdfa;
1413
+ }
1414
+ .error-panel > .icon {
1415
+ margin-top: 3px;
1416
+ color: var(--amber);
1417
+ }
1418
+ .error-panel > div {
1419
+ flex: 1;
1420
+ }
1421
+ .error-panel p {
1422
+ margin-top: 8px;
1423
+ color: var(--secondary);
1424
+ font-size: 12px;
1425
+ }
1426
+ .task-actions {
1427
+ display: flex;
1428
+ flex-wrap: wrap;
1429
+ gap: 7px;
1430
+ min-width: 280px;
1431
+ }
1432
+ .task-actions input {
1433
+ width: 100%;
1434
+ }
1435
+
1436
+ /* 登录页保持同一品牌色,以较大的留白和标题区分日常数据页面。 */
1437
+ .login-layout {
1438
+ display: grid;
1439
+ grid-template-columns: 1.08fr 1fr;
1440
+ min-height: 100vh;
1441
+ background: #fbfcf9;
1442
+ }
1443
+ .login-story {
1444
+ position: relative;
1445
+ display: flex;
1446
+ flex-direction: column;
1447
+ justify-content: space-between;
1448
+ overflow: hidden;
1449
+ padding: 48px 66px 38px;
1450
+ background: #214a3b;
1451
+ color: #fff;
1452
+ }
1453
+ .login-story::after {
1454
+ position: absolute;
1455
+ width: 660px;
1456
+ height: 660px;
1457
+ right: -380px;
1458
+ bottom: -290px;
1459
+ border: 1px solid #abc8a933;
1460
+ border-radius: 50%;
1461
+ box-shadow:
1462
+ 0 0 0 60px #abc8a90a,
1463
+ 0 0 0 120px #abc8a90a,
1464
+ 0 0 0 180px #abc8a909;
1465
+ content: '';
1466
+ pointer-events: none;
1467
+ }
1468
+ .login-story > * {
1469
+ position: relative;
1470
+ z-index: 1;
1471
+ }
1472
+ .login-brand {
1473
+ display: flex;
1474
+ align-items: center;
1475
+ gap: 13px;
1476
+ font:
1477
+ 500 31px/1 Bahnschrift,
1478
+ sans-serif;
1479
+ letter-spacing: -0.7px;
1480
+ }
1481
+ .login-brand .brand-mark {
1482
+ background: #ffffff12;
1483
+ border: 1px solid #ffffff30;
1484
+ }
1485
+ .login-story .eyebrow {
1486
+ margin-bottom: 19px;
1487
+ color: #a8c6b4;
1488
+ font-size: 11px;
1489
+ }
1490
+ .login-story h1 {
1491
+ margin-bottom: 25px;
1492
+ font-size: 42px;
1493
+ line-height: 1.6;
1494
+ letter-spacing: 3px;
1495
+ font-weight: 500;
1496
+ }
1497
+ .login-story p {
1498
+ color: #bbd1c3;
1499
+ font-size: 13px;
1500
+ line-height: 2.1;
1501
+ }
1502
+ .login-story > small {
1503
+ color: #9fbdac;
1504
+ font-size: 10px;
1505
+ letter-spacing: 2px;
1506
+ }
1507
+ .login-panel {
1508
+ align-self: center;
1509
+ width: 100%;
1510
+ max-width: 490px;
1511
+ padding: 50px 55px;
1512
+ margin: 0 auto;
1513
+ }
1514
+ .login-panel > .eyebrow {
1515
+ margin-bottom: 12px;
1516
+ color: var(--accent);
1517
+ }
1518
+ .login-panel h2 {
1519
+ margin-bottom: 10px;
1520
+ font-size: 26px;
1521
+ }
1522
+ .login-panel > p {
1523
+ font-size: 12px;
1524
+ }
1525
+ .login-panel .stack-form {
1526
+ margin-top: 38px;
1527
+ }
1528
+ .login-panel .stack-form > button {
1529
+ justify-content: space-between;
1530
+ min-height: 44px;
1531
+ margin-top: 7px;
1532
+ }
1533
+ .sso-link {
1534
+ display: flex;
1535
+ justify-content: center;
1536
+ align-items: center;
1537
+ gap: 9px;
1538
+ margin-top: 22px;
1539
+ font-size: 11px;
1540
+ }
1541
+ .sso-link .icon {
1542
+ width: 13px;
1543
+ height: 13px;
1544
+ }
1545
+ .login-footnote {
1546
+ display: flex;
1547
+ align-items: flex-start;
1548
+ gap: 7px;
1549
+ margin-top: 46px;
1550
+ color: var(--muted);
1551
+ font-size: 10px !important;
1552
+ }
1553
+ .login-footnote .icon {
1554
+ width: 13px;
1555
+ height: 13px;
1556
+ margin-top: 2px;
1557
+ }
1558
+ .connection-state {
1559
+ display: flex;
1560
+ flex-direction: column;
1561
+ align-items: center;
1562
+ justify-content: center;
1563
+ gap: 20px;
1564
+ min-height: 100vh;
1565
+ }
1566
+ .connection-state p {
1567
+ color: var(--secondary);
1568
+ }
1569
+ @keyframes enter {
1570
+ from {
1571
+ opacity: 0;
1572
+ transform: translateY(5px);
1573
+ }
1574
+ to {
1575
+ opacity: 1;
1576
+ transform: translateY(0);
1577
+ }
1578
+ }
1579
+ @keyframes rotate {
1580
+ to {
1581
+ transform: rotate(360deg);
1582
+ }
1583
+ }
1584
+ @media (prefers-reduced-motion: reduce) {
1585
+ *,
1586
+ *::before,
1587
+ *::after {
1588
+ animation: none !important;
1589
+ transition: none !important;
1590
+ }
1591
+ }
1592
+
1593
+ /* 助理性格:预设卡片与并排试聊,沿用管理工作台的绿色和纸面层次。 */
1594
+ body:has(.persona-overview) { min-width: 0; }
1595
+ .persona-overview { display: flex; justify-content: space-between; align-items: center; gap: 24px; padding: 22px 4px 28px; }
1596
+ .persona-overview h2 { margin: 8px 0; font-size: 26px; letter-spacing: -.4px; }
1597
+ .persona-overview p { color: var(--secondary); }
1598
+ .persona-default { display: flex; justify-content: space-between; align-items: center; gap: 20px; padding: 20px 24px; border: 1px solid var(--line); border-radius: 12px; background: #fff; margin-bottom: 18px; }
1599
+ .persona-default p { margin: 4px 0 0; font-size: 11px; color: var(--muted); }
1600
+ .persona-default-actions { display: flex; align-items: center; gap: 10px; }
1601
+ .persona-default select { min-width: 180px; }
1602
+ .persona-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 24px; }
1603
+ .persona-card { display: flex; position: relative; gap: 13px; align-items: flex-start; min-width: 0; padding: 21px 18px 42px; border: 1px solid var(--line); border-radius: 12px; background: #fff; text-align: left; white-space: normal; }
1604
+ .persona-card.selected { border-color: #7baf8f; background: #f0f7ed; box-shadow: inset 0 0 0 1px #7baf8f; }
1605
+ .persona-avatar { display: grid; place-items: center; width: 38px; height: 38px; flex-shrink: 0; border: 1px solid #e2eadc; border-radius: 11px; background: #f8faf5; font-size: 22px; }
1606
+ .persona-card-copy { display: block; min-width: 0; }
1607
+ .persona-card-copy strong { display: block; color: #284f3e; font-size: 14px; margin-bottom: 5px; }
1608
+ .persona-card-copy small { display: -webkit-box; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; color: var(--secondary); font-size: 11px; line-height: 1.8; font-weight: 400; }
1609
+ .persona-card-tags { position: absolute; right: 16px; bottom: 12px; }
1610
+ .persona-card-tags .badge { font-size: 9px; }
1611
+ .persona-editor-area { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: 20px; align-items: start; }
1612
+ .persona-form { padding: 27px; background: #fff; border: 1px solid var(--line); border-radius: 14px; }
1613
+ .persona-section-heading { margin-bottom: 23px; }
1614
+ .persona-section-heading h2, .persona-preview h2 { margin: 7px 0; font-size: 20px; }
1615
+ .persona-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
1616
+ .persona-form .field { margin-bottom: 17px; }
1617
+ .persona-form textarea { resize: vertical; min-height: 120px; }
1618
+ .persona-examples { display: grid; gap: 9px; margin: 5px 0 18px; }
1619
+ .persona-examples strong { font-size: 12px; font-weight: 500; }
1620
+ .persona-examples small { color: var(--muted); font-size: 10px; margin-top: -4px; }
1621
+ .persona-enabled { display: flex; align-items: center; gap: 9px; color: var(--secondary); font-size: 12px; }
1622
+ .persona-enabled input { width: auto; }
1623
+ .persona-save-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 22px; margin-top: 22px; border-top: 1px solid var(--line); }
1624
+ .persona-save-status { font-size: 10px; color: var(--secondary); margin: 0; }
1625
+ .persona-preview { position: sticky; top: 20px; padding: 27px; border: 1px solid #d4dfcb; border-radius: 14px; background: #f4f7ee; }
1626
+ .persona-preview-intro { font-size: 11px; color: #7a886d; margin: 0 0 23px; line-height: 1.9; }
1627
+ .persona-preview-answer { min-height: 220px; max-height: 390px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; padding: 18px; border: 1px solid #e0e7d7; border-radius: 10px; background: #fffef9; color: #3d5943; font-size: 13px; line-height: 1.9; }
1628
+ .persona-preview-status { min-height: 20px; margin: 10px 0; color: var(--secondary); font-size: 10px; }
1629
+ .persona-preview textarea { width: 100%; resize: vertical; min-height: 75px; }
1630
+ .persona-preview-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 15px; }
1631
+ @media (max-width: 1250px) { .persona-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .persona-editor-area { grid-template-columns: minmax(0, 1fr) minmax(0, .9fr); } .persona-default { flex-wrap: wrap; } }
1632
+ @media (max-width: 900px) {
1633
+ .persona-editor-area { grid-template-columns: minmax(0, 1fr); }
1634
+ .persona-preview { position: static; }
1635
+ .persona-overview { flex-wrap: wrap; }
1636
+ }
1637
+ @media (max-width: 700px) {
1638
+ body:has(.persona-overview, .model-overview) .app-sidebar { position: static; width: auto; padding: 18px; border-right: 0; border-bottom: 1px solid var(--line); }
1639
+ body:has(.persona-overview, .model-overview) .brand { padding: 0 0 10px; }
1640
+ body:has(.persona-overview, .model-overview) .nav-group { margin-top: 8px; }
1641
+ body:has(.persona-overview, .model-overview) .nav-caption { margin: 0 0 5px; }
1642
+ body:has(.persona-overview, .model-overview) .app-sidebar nav { display: flex; flex-wrap: wrap; gap: 5px; }
1643
+ body:has(.persona-overview, .model-overview) .nav-item { min-height: 38px; padding: 8px 10px; margin: 0; gap: 6px; }
1644
+ body:has(.persona-overview, .model-overview) .sidebar-bottom { padding: 10px 0 0; }
1645
+ body:has(.persona-overview, .model-overview) .workspace-label { display: none; }
1646
+ body:has(.persona-overview, .model-overview) .app-main { margin-left: 0; }
1647
+ body:has(.persona-overview, .model-overview) .app-topbar { padding: 0 18px; gap: 10px; }
1648
+ body:has(.persona-overview, .model-overview) .breadcrumb > :not(strong), body:has(.persona-overview, .model-overview) .account-copy { display: none; }
1649
+ body:has(.persona-overview, .model-overview) .page-container { padding: 24px 16px; }
1650
+ body:has(.persona-overview, .model-overview) .page-heading, body:has(.persona-overview, .model-overview) .page-footer { align-items: flex-start; flex-wrap: wrap; }
1651
+ .persona-grid { grid-template-columns: minmax(0, 1fr); }
1652
+ .persona-default { padding: 18px; }
1653
+ .persona-default-actions { width: 100%; flex-wrap: wrap; }
1654
+ .persona-default select { flex: 1; min-width: 0; }
1655
+ .persona-form, .persona-preview { padding: 20px; }
1656
+ .persona-save-row { flex-wrap: wrap; }
1657
+ .persona-overview h2 { font-size: 23px; }
1658
+ }