@teamix-evo/skills 0.4.0 → 0.6.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 (97) hide show
  1. package/README.md +7 -3
  2. package/manifest.json +3 -2
  3. package/package.json +2 -2
  4. package/src/teamix-evo-code-opentrek/SKILL.md +12 -10
  5. package/src/teamix-evo-code-opentrek/api-layering.md +8 -5
  6. package/src/teamix-evo-code-opentrek/checklist.md +2 -0
  7. package/src/teamix-evo-code-opentrek/error-and-loading.md +38 -25
  8. package/src/teamix-evo-code-opentrek/file-structure.md +63 -54
  9. package/src/teamix-evo-code-opentrek/forms-and-validation.md +14 -12
  10. package/src/teamix-evo-code-opentrek/reuse-first.md +2 -0
  11. package/src/teamix-evo-code-opentrek/routing-and-codesplit.md +23 -21
  12. package/src/teamix-evo-code-opentrek/testing.md +32 -28
  13. package/src/teamix-evo-code-uni-manager/SKILL.md +12 -10
  14. package/src/teamix-evo-code-uni-manager/api-layering.md +2 -0
  15. package/src/teamix-evo-code-uni-manager/checklist.md +2 -0
  16. package/src/teamix-evo-code-uni-manager/error-and-loading.md +3 -1
  17. package/src/teamix-evo-code-uni-manager/file-structure.md +2 -0
  18. package/src/teamix-evo-code-uni-manager/forms-and-validation.md +2 -0
  19. package/src/teamix-evo-code-uni-manager/reuse-first.md +3 -1
  20. package/src/teamix-evo-code-uni-manager/routing-and-codesplit.md +3 -1
  21. package/src/teamix-evo-code-uni-manager/testing.md +2 -0
  22. package/src/teamix-evo-design-opentrek/SKILL.md +213 -52
  23. package/src/teamix-evo-design-opentrek/boundaries.md +25 -5
  24. package/src/teamix-evo-design-opentrek/brand.md +7 -7
  25. package/src/teamix-evo-design-opentrek/checklist.md +15 -13
  26. package/src/teamix-evo-design-opentrek/components.md +89 -39
  27. package/src/teamix-evo-design-opentrek/examples/detail-ai-gateway-1.html +1069 -0
  28. package/src/teamix-evo-design-opentrek/examples/detail-ai-gateway-instance.html +941 -0
  29. package/src/teamix-evo-design-opentrek/examples/detail-page-api-doc.html +906 -0
  30. package/src/teamix-evo-design-opentrek/examples/detail-page-config.html +993 -0
  31. package/src/teamix-evo-design-opentrek/examples/detail-page-monitor.html +1339 -0
  32. package/src/teamix-evo-design-opentrek/examples/detail-page.html +933 -0
  33. package/src/teamix-evo-design-opentrek/examples/settings-page.html +1119 -0
  34. package/src/teamix-evo-design-opentrek/examples/standard-card-list.html +1094 -0
  35. package/src/teamix-evo-design-opentrek/examples/standard-table-list.html +1361 -0
  36. package/src/teamix-evo-design-opentrek/examples/wizard-form-page.html +877 -0
  37. package/src/teamix-evo-design-opentrek/flows.md +85 -12
  38. package/src/teamix-evo-design-opentrek/foundations.md +12 -9
  39. package/src/teamix-evo-design-opentrek/generation-flow.md +84 -14
  40. package/src/teamix-evo-design-opentrek/pages/detail-page/SKILL.md +260 -0
  41. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/api-doc-detail.md +163 -0
  42. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/comparison-detail.md +100 -0
  43. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/monitor-detail.md +190 -0
  44. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/resource-detail.md +148 -0
  45. package/src/teamix-evo-design-opentrek/pages/form-page/SKILL.md +362 -0
  46. package/src/teamix-evo-design-opentrek/pages/list-page/SKILL.md +286 -0
  47. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/action-column-spec.md +60 -0
  48. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/column-meta-rules.md +117 -0
  49. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/search-combo-spec.md +194 -0
  50. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/state-action-pattern.md +51 -0
  51. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/advanced-filter-list.md +94 -0
  52. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/card-list.md +558 -0
  53. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/drawer-list.md +76 -0
  54. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/expandable-list.md +70 -0
  55. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/l2-sidebar-list.md +73 -0
  56. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/standard-list.md +198 -0
  57. package/src/teamix-evo-design-opentrek/patterns/color-mapping.md +96 -0
  58. package/src/teamix-evo-design-opentrek/patterns/dashboard.md +2 -0
  59. package/src/teamix-evo-design-opentrek/patterns/detail-page.md +218 -152
  60. package/src/teamix-evo-design-opentrek/patterns/form-page.md +437 -228
  61. package/src/teamix-evo-design-opentrek/patterns/list-page.md +221 -260
  62. package/src/teamix-evo-design-opentrek/patterns/page-types.md +40 -125
  63. package/src/teamix-evo-design-opentrek/philosophy.md +7 -5
  64. package/src/teamix-evo-design-opentrek/rules/_assets/OP_AGENT RUNTIME.svg +1 -0
  65. package/src/teamix-evo-design-opentrek/rules/_assets/OP_AI GATEWAY.svg +1 -0
  66. package/src/teamix-evo-design-opentrek/rules/_assets/OP_AI STUDIO.svg +1 -0
  67. package/src/teamix-evo-design-opentrek/rules/_assets/OP_DEV-2.svg +1 -0
  68. package/src/teamix-evo-design-opentrek/rules/_assets/OP_LOGO.svg +1 -0
  69. package/src/teamix-evo-design-opentrek/rules/_assets/OP_OPS.svg +1 -0
  70. package/src/teamix-evo-design-opentrek/rules/boundaries.rules.json +3 -3
  71. package/src/teamix-evo-design-opentrek/rules/business-mapping.json +124 -0
  72. package/src/teamix-evo-design-opentrek/rules/common-components.json +924 -0
  73. package/src/teamix-evo-design-opentrek/rules/component-specs.json +1083 -0
  74. package/src/teamix-evo-design-opentrek/rules/design-tokens.css +433 -0
  75. package/src/teamix-evo-design-opentrek/rules/design-tokens.json +2798 -0
  76. package/src/teamix-evo-design-opentrek/rules/layout-rules.json +218 -0
  77. package/src/teamix-evo-design-opentrek/rules/page-flow.json +351 -0
  78. package/src/teamix-evo-design-opentrek/rules/page-frame.json +241 -0
  79. package/src/teamix-evo-design-opentrek/rules/page-header-spec.md +123 -0
  80. package/src/teamix-evo-design-opentrek/rules/page-types.json +206 -0
  81. package/src/teamix-evo-design-opentrek/rules/sidebar-spec.md +217 -0
  82. package/src/teamix-evo-design-opentrek/rules/styling.json +188 -0
  83. package/src/teamix-evo-design-opentrek/rules/token-mapping.md +284 -0
  84. package/src/teamix-evo-design-uni-manager/SKILL.md +18 -27
  85. package/src/teamix-evo-design-uni-manager/boundaries.md +7 -4
  86. package/src/teamix-evo-design-uni-manager/brand.md +1 -1
  87. package/src/teamix-evo-design-uni-manager/components.md +33 -28
  88. package/src/teamix-evo-design-uni-manager/foundations.md +24 -21
  89. package/src/teamix-evo-design-uni-manager/generation-flow.md +46 -8
  90. package/src/teamix-evo-design-uni-manager/patterns/dashboard.md +3 -1
  91. package/src/teamix-evo-design-uni-manager/patterns/detail-page.md +42 -13
  92. package/src/teamix-evo-design-uni-manager/patterns/form-page.md +67 -30
  93. package/src/teamix-evo-design-uni-manager/patterns/list-page.md +73 -40
  94. package/src/teamix-evo-design-uni-manager/patterns/page-types.md +14 -12
  95. package/src/teamix-evo-design-uni-manager/philosophy.md +4 -2
  96. package/src/teamix-evo-design-uni-manager/rules/boundaries.rules.json +3 -3
  97. package/src/teamix-evo-manage/SKILL.md +74 -66
@@ -0,0 +1,1094 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>卡片列表页 · 标准参考范例 — v7.8.4</title>
7
+ <!--
8
+ ★ 卡片列表页标准参考范例(Standard Card List Reference)
9
+ ─────────────────────────────────────────────────────────────
10
+ 用途:AI 生成卡片列表页时的基础参考,展示完整页面骨架与组件组合
11
+ ─────────────────────────────────────────────────────────────
12
+ 布局:TWO_COL(Sidebar + ContentCard 单例容器)
13
+ Sidebar:完整 L1 框架(折叠/展开 240px↔68px / flyout / sub-menu)
14
+ 内容区模式:D-CARD(standard-card)
15
+ ─────────────────────────────────────────────────────────────
16
+ 组件清单:
17
+ • PageHeader
18
+ • ActionToolbar — 含 SearchCombo (来源 _shared/search-combo-spec.md)
19
+ • CardGrid — preset=standard, min 300px / gap 16px
20
+ • ItemCard — density=standard, iconStyle=avatar
21
+ • CardActionBar — mode=hover-slidebar
22
+ • Pagination — 12 条/页
23
+ ─────────────────────────────────────────────────────────────
24
+ 规范来源:pages/list-page/patterns/card-list.md §0/§1/§9
25
+ Tokens 版本:v7.8.4(分层 padding 模型 v7.5 + v7.6 ContentCard 表面规则 + v7.8.4 字体族变量)
26
+ -->
27
+ <style>
28
+ /* ====================================================================
29
+ Design Tokens v7.3
30
+ ==================================================================== */
31
+ :root {
32
+ /* Brand */
33
+ --primary: 218.6 100% 46.7%;
34
+ --primary-foreground: 0 0% 100%;
35
+ --primary-hover: 218.6 100% 42%;
36
+ --primary-click: 218.6 100% 37.5%;
37
+
38
+ /* Gray (v7.4) */
39
+ --gray-primary: 220 9% 7%;
40
+ --gray-primary-foreground: 210 33% 99%;
41
+ --gray-secondary-foreground: 216 4% 26%;
42
+ --muted-foreground: 216 2% 45%;
43
+ --gray-disabled: 210 3% 63%;
44
+ --gray-line: 210 9% 91%;
45
+ --gray-sidebar-accent: 210 12% 93%;
46
+ --gray-muted: 220 18% 97%;
47
+ --gray-white: 0 0% 100%;
48
+ /* Legacy 别名(v7.4 向后兼容) */
49
+ --gray-title: 220 9% 7%;
50
+ --gray-secondary: 216 4% 26%;
51
+ --gray-tertiary: 216 2% 45%;
52
+ --gray-border: 210 9% 91%;
53
+ --gray-fill: 220 18% 97%;
54
+ --gray-bg-dark: 220 18% 97%;
55
+ --gray-bg: 220 18% 97%;
56
+
57
+ /* Semantic */
58
+ --background: 220 18% 97%;
59
+ --foreground: 220 9% 7%;
60
+ --card: 0 0% 100%;
61
+ --border: 210 9% 91%;
62
+ --ring: 218.6 100% 46.7%;
63
+
64
+ /* Status */
65
+ --success: 142 76% 36%;
66
+ --success-bg: 142 84% 95%;
67
+ --success-text: 142 76.6% 35%;
68
+ --destructive: 0 72% 51%;
69
+ --destructive-foreground: 0 0% 100%;
70
+ --destructive-bg: 0 86% 97%;
71
+ --warning: 40 88% 48%;
72
+ --warning-bg: 43 100% 94%;
73
+ --warning-text: 40 88% 40%;
74
+ --info: 217 91% 53%;
75
+ --info-bg: 214 100% 97%;
76
+ --info-text: 217 91% 45%;
77
+ --status-running: 142 76% 36%;
78
+ --status-stopped: 222 7.6% 74.1%;
79
+ --status-error: 0 72% 51%;
80
+
81
+ /* Sidebar */
82
+ --sidebar: 220 18% 97%;
83
+ --sidebar-foreground: 220 9% 7%;
84
+ --sidebar-active: 210 12% 93%;
85
+ --sidebar-active-foreground: 220 9% 7%;
86
+ --sidebar-hover: 220 18% 97%;
87
+ --sidebar-group: 216 2% 45%;
88
+ --sidebar-item: 220 9% 7%;
89
+ --sidebar-item-muted: 216 4% 26%;
90
+ --sidebar-border: 210 9% 91%;
91
+
92
+ /* Avatar 色块 */
93
+ --avatar-blue: 218.6 100% 46.7%;
94
+ --avatar-success: 142 76% 36%;
95
+ --avatar-mcp: 271 81% 56%;
96
+ --avatar-warning: 40 88% 48%;
97
+ --avatar-data8: 49.4 65.0% 42.5%;
98
+ --avatar-berry: 341.2 80.1% 66.5%;
99
+
100
+ /* Layout(分层模型 v7.5)*/
101
+ --layout-sidebar-width: 240px;
102
+ --page-container-padding: 16px;
103
+ --page-container-padding-left: 0px;
104
+ --card-padding-x: 20px;
105
+ --page-container-gap: 16px;
106
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
107
+ --page-header-height: 64px;
108
+
109
+ /* Typography */
110
+ --font-size-base: 12px;
111
+ --font-size-lg: 14px;
112
+ --font-size-xl: 16px;
113
+ --font-size-2xl: 18px;
114
+ --font-size-page-header: 18px;
115
+ --font-sans: 'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
116
+ --font-mono: 'SF Mono', Monaco, 'Courier New', monospace;
117
+ --font-weight-normal: 400;
118
+ --font-weight-medium: 500;
119
+ --font-weight-black: 900;
120
+
121
+ /* Spacing & gap */
122
+ --gap-xs: 4px;
123
+ --btn-padding-x: 16px;
124
+ --btn-padding-x-sm: 12px;
125
+ --button-gap: 8px;
126
+ --tabs-gap: 24px;
127
+ --card-gap: 16px;
128
+
129
+ /* CardGrid presets */
130
+ --card-grid-min-compact: 240px;
131
+ --card-grid-min-standard: 300px;
132
+ --card-grid-min-comfortable: 320px;
133
+ --card-grid-min-feature: 360px;
134
+
135
+ /* Radius */
136
+ --radius-sm: 4px;
137
+ --radius-md: 8px;
138
+ --radius-lg: 12px;
139
+ --card-radius: 12px;
140
+ --input-radius: 8px;
141
+
142
+ /* Shadow */
143
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
144
+
145
+ /* Animation */
146
+ --duration-fast: 150ms;
147
+ --duration-normal: 200ms;
148
+ --easing-ease: cubic-bezier(0.25, 0.1, 0.25, 1);
149
+ }
150
+
151
+ /* ==================================================================== */
152
+ * { box-sizing: border-box; margin: 0; padding: 0; }
153
+ html, body {
154
+ font-family: var(--font-sans);
155
+ font-size: var(--font-size-base);
156
+ color: hsl(var(--gray-primary));
157
+ background: hsl(var(--background));
158
+ -webkit-font-smoothing: antialiased;
159
+ }
160
+ button { font-family: inherit; }
161
+
162
+ /* ====================================================================
163
+ Sidebar — 完整 L1 框架(含折叠/展开/flyout)
164
+ ==================================================================== */
165
+ .sidebar {
166
+ position: fixed; top: 0; left: 0; bottom: 0;
167
+ width: var(--layout-sidebar-width);
168
+ background: hsl(var(--sidebar));
169
+ z-index: 100;
170
+ display: flex; flex-direction: column;
171
+ overflow: hidden;
172
+ transition: width 0.2s ease;
173
+ }
174
+ .sidebar-header {
175
+ height: 56px; padding: 0 16px;
176
+ display: flex; align-items: center; gap: var(--gap-xs);
177
+ flex-shrink: 0;
178
+ }
179
+ .sidebar-logo {
180
+ height: 28px; flex-shrink: 0;
181
+ display: flex; align-items: center;
182
+ overflow: hidden;
183
+ }
184
+ .sidebar-logo img { height: 28px; width: auto; display: block; }
185
+ .sidebar-logo .collapsed-logo { display: none; width: 30px; height: 30px; }
186
+ .sidebar-logo .expand-logo { display: none; width: 18px; height: 18px; color: hsl(var(--muted-foreground)); }
187
+ .sidebar-collapse-btn {
188
+ margin-left: auto; width: 18px; height: 18px;
189
+ background: none; border: none; padding: 0; cursor: pointer;
190
+ display: flex; align-items: center; justify-content: center;
191
+ color: hsl(var(--muted-foreground)); flex-shrink: 0;
192
+ }
193
+ .sidebar-collapse-btn svg { width: 18px; height: 18px; }
194
+
195
+ /* Sidebar Collapsed State */
196
+ .sidebar.collapsed { width: 68px; overflow: visible; }
197
+ .sidebar.collapsed .sidebar-header { padding: 0 12px; justify-content: center; }
198
+ .sidebar.collapsed .sidebar-logo { cursor: pointer; }
199
+ .sidebar.collapsed .sidebar-logo img { display: none; }
200
+ .sidebar.collapsed .sidebar-logo .collapsed-logo { display: block; }
201
+ .sidebar.collapsed .sidebar-logo:hover .collapsed-logo { display: none; }
202
+ .sidebar.collapsed .sidebar-logo:hover .expand-logo { display: block; }
203
+ .sidebar.collapsed .sidebar-collapse-btn { display: none; }
204
+ .sidebar.collapsed .sidebar-content { padding: 12px 0; overflow-y: auto; overflow-x: hidden; }
205
+ .sidebar.collapsed .sidebar-menu { padding: 0; }
206
+ .sidebar.collapsed .sidebar-menu > li { display: flex; justify-content: center; }
207
+ .sidebar.collapsed .sidebar-menu > li > a.sidebar-menu-item {
208
+ justify-content: center; padding: 0; width: 40px; height: 40px;
209
+ border-radius: var(--radius-md); position: relative; flex-shrink: 0; gap: 0;
210
+ }
211
+ .sidebar.collapsed .sidebar-menu > li > a.sidebar-menu-item .item-icon { margin: 0; }
212
+ .sidebar.collapsed .sidebar-menu > li > a > span:not(.item-icon),
213
+ .sidebar.collapsed .sidebar-menu > li > a > .expand-icon,
214
+ .sidebar.collapsed .sidebar-menu-item:not(.item-icon):after { display: none; }
215
+ .sidebar.collapsed .sidebar-menu > li > a { font-size: 0; }
216
+ .sidebar.collapsed .sidebar-menu > li > a > .item-icon { font-size: var(--font-size-lg); }
217
+ .sidebar.collapsed .sidebar-sub-menu { display: none !important; }
218
+ .sidebar.collapsed .sidebar-divider { margin: 0 14px; }
219
+ .sidebar.collapsed .sidebar-footer { padding: 12px 10px 16px; justify-content: center; }
220
+ .sidebar.collapsed .sidebar-username,
221
+ .sidebar.collapsed .sidebar-more { display: none; }
222
+
223
+ /* Sidebar Collapsed Flyout */
224
+ .sidebar.collapsed .sidebar-menu > li { position: relative; }
225
+ .sidebar.collapsed .sidebar-menu > li:hover > .sidebar-flyout { display: block; }
226
+ .sidebar-flyout {
227
+ display: none;
228
+ position: absolute; left: 100%; top: 0;
229
+ min-width: 160px; padding: 4px;
230
+ background: hsl(var(--card));
231
+ border: 1px solid hsl(var(--gray-line));
232
+ border-radius: var(--radius-md);
233
+ box-shadow: 0 4px 12px rgba(0,0,0,0.08);
234
+ z-index: 200;
235
+ }
236
+ .sidebar-flyout .sidebar-menu-item {
237
+ height: 36px; padding: 0 12px;
238
+ font-size: var(--font-size-base) !important;
239
+ font-weight: var(--font-weight-normal);
240
+ color: hsl(var(--gray-primary));
241
+ border-radius: var(--radius-sm);
242
+ white-space: nowrap;
243
+ }
244
+ .sidebar-flyout .sidebar-menu-item:hover { background: hsl(var(--gray-muted)); }
245
+
246
+ /* Sidebar Content */
247
+ .sidebar-content { flex: 1; overflow-y: auto; padding: 12px 0; }
248
+ .sidebar-group-label {
249
+ padding: 0 16px; height: 26px; line-height: 26px;
250
+ font-size: var(--font-size-base); font-weight: var(--font-weight-normal);
251
+ color: hsl(var(--sidebar-group));
252
+ }
253
+ .sidebar-group-label:not(:first-child) { margin-top: 16px; }
254
+ .sidebar-menu { list-style: none; padding: 0 8px; display: flex; flex-direction: column; gap: 2px; }
255
+ .sidebar-menu-item {
256
+ display: flex; align-items: center; gap: var(--button-gap);
257
+ padding: 0 12px; height: 40px;
258
+ border-radius: var(--radius-md);
259
+ font-size: var(--font-size-lg); font-weight: var(--font-weight-medium);
260
+ color: hsl(var(--sidebar-item-muted));
261
+ text-decoration: none; cursor: pointer;
262
+ transition: background var(--duration-fast), color var(--duration-fast);
263
+ white-space: nowrap;
264
+ }
265
+ .sidebar-menu-item:hover { background: hsl(var(--sidebar-hover)); color: hsl(var(--sidebar-item)); }
266
+ .sidebar-menu-item.active { background: hsl(var(--sidebar-active)); color: hsl(var(--sidebar-active-foreground)); }
267
+ .sidebar-menu-item .item-icon {
268
+ width: 16px; height: 16px; flex-shrink: 0;
269
+ display: flex; align-items: center; justify-content: center;
270
+ }
271
+ .sidebar-menu-item .expand-icon {
272
+ margin-left: auto; width: 16px; height: 16px;
273
+ transition: transform var(--duration-fast);
274
+ }
275
+ .sidebar-menu-item.expanded .expand-icon { transform: rotate(90deg); }
276
+ .sidebar-sub-menu { list-style: none; padding: 0 0 0 24px; display: none; }
277
+ .sidebar-menu > li > .sidebar-sub-menu { padding-left: 0; }
278
+ .sidebar-sub-menu.show { display: block; }
279
+ .sidebar-sub-menu .sidebar-menu-item {
280
+ height: 36px; font-size: var(--font-size-base); font-weight: var(--font-weight-normal);
281
+ padding-left: 36px;
282
+ }
283
+ .sidebar-divider { height: 1px; background: hsl(var(--sidebar-border)); margin: 0 12px; flex-shrink: 0; }
284
+ .sidebar-footer {
285
+ flex-shrink: 0; display: flex; align-items: center;
286
+ gap: var(--button-gap); padding: 12px 12px 16px 24px;
287
+ }
288
+ .sidebar-avatar {
289
+ width: 28px; height: 28px; border-radius: 50%;
290
+ background: hsl(var(--sidebar-active));
291
+ display: flex; align-items: center; justify-content: center;
292
+ font-size: var(--font-size-base); font-weight: 600;
293
+ color: hsl(var(--gray-primary)); flex-shrink: 0;
294
+ }
295
+ .sidebar-username {
296
+ flex: 1; font-size: var(--font-size-lg); font-weight: var(--font-weight-medium);
297
+ color: hsl(var(--sidebar-item)); overflow: hidden;
298
+ text-overflow: ellipsis; white-space: nowrap;
299
+ }
300
+ .sidebar-more {
301
+ width: 28px; height: 28px; border-radius: var(--radius-sm);
302
+ border: none; background: transparent; cursor: pointer;
303
+ display: flex; align-items: center; justify-content: center;
304
+ color: hsl(var(--muted-foreground));
305
+ }
306
+ .sidebar-more:hover { background: hsl(var(--sidebar-hover)); color: hsl(var(--gray-primary)); }
307
+
308
+ /* ====================================================================
309
+ Main Content — PageContainer
310
+ ==================================================================== */
311
+ .main-content {
312
+ margin-left: var(--layout-sidebar-width);
313
+ min-height: 100vh;
314
+ padding: var(--page-container-padding)
315
+ var(--page-container-padding)
316
+ var(--page-container-padding)
317
+ var(--page-container-padding-left);
318
+ transition: margin-left 0.2s ease;
319
+ }
320
+ .sidebar.collapsed ~ .main-content { margin-left: 68px; }
321
+
322
+ /* ====================================================================
323
+ ContentCard — 白卡容器,分层 padding 模型 v7.5
324
+ ==================================================================== */
325
+ .card-wrapper {
326
+ background: hsl(var(--card));
327
+ /* v7.6:去掉 1px border,使用最弱阴影 var(--shadow-sm) */
328
+ box-shadow: var(--shadow-sm, 0 1px 2px rgba(0,0,0,0.05));
329
+ border-radius: var(--card-radius);
330
+ overflow: hidden;
331
+ display: flex; flex-direction: column;
332
+ }
333
+ .card-wrapper > .page-header { padding: 0 var(--card-padding-x); }
334
+ .card-wrapper > .action-toolbar { padding: 16px var(--card-padding-x); }
335
+ .card-wrapper > .card-grid { padding: 0 var(--card-padding-x) 16px; }
336
+ .card-wrapper > .pagination {
337
+ padding: 16px var(--card-padding-x);
338
+ margin-top: 16px;
339
+ border-top: 1px solid hsl(var(--gray-line));
340
+ }
341
+
342
+ /* ====================================================================
343
+ PageHeader — Mode 1 简单标题,64px
344
+ ==================================================================== */
345
+ .page-header {
346
+ height: var(--page-header-height);
347
+ display: flex; align-items: center; justify-content: space-between;
348
+ }
349
+ .page-header-title {
350
+ font-size: var(--font-size-page-header);
351
+ font-weight: var(--font-weight-medium);
352
+ color: hsl(var(--gray-primary));
353
+ line-height: 1.4;
354
+ }
355
+
356
+ /* ====================================================================
357
+ ActionToolbar
358
+ ==================================================================== */
359
+ .action-toolbar { display: flex; align-items: center; gap: var(--button-gap); }
360
+ .action-toolbar-left { display: flex; align-items: center; gap: var(--button-gap); }
361
+ .action-toolbar-right { margin-left: auto; display: flex; align-items: center; gap: var(--button-gap); }
362
+
363
+ /* Button */
364
+ .btn {
365
+ display: inline-flex; align-items: center; gap: var(--button-gap);
366
+ height: 32px; padding: 0 var(--btn-padding-x-sm);
367
+ border-radius: var(--radius-sm);
368
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
369
+ cursor: pointer; border: none;
370
+ transition: all var(--duration-normal) var(--easing-ease);
371
+ white-space: nowrap;
372
+ }
373
+ .btn svg { width: 14px; height: 14px; }
374
+ .btn-primary { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); }
375
+ .btn-primary:hover { background: hsl(var(--primary-hover)); }
376
+ .btn-default { background: hsl(var(--gray-white)); color: hsl(var(--gray-primary)); border: 1px solid hsl(var(--gray-line)); }
377
+ .btn-default:hover { border-color: hsl(var(--primary)); color: hsl(var(--primary)); }
378
+
379
+ /* SearchCombo — 容器式 border */
380
+ .search-combo {
381
+ display: inline-flex; align-items: center;
382
+ height: 32px; min-width: 280px;
383
+ border: 1px solid hsl(var(--gray-line));
384
+ border-radius: var(--input-radius);
385
+ background: hsl(var(--gray-white));
386
+ margin-left: 12px;
387
+ }
388
+ .search-combo:focus-within { border-color: hsl(var(--primary)); }
389
+ .search-combo-dim {
390
+ height: 100%; padding: 0 8px;
391
+ display: inline-flex; align-items: center; gap: 4px;
392
+ font-size: var(--font-size-base); color: hsl(var(--gray-secondary-foreground));
393
+ border-right: 1px solid hsl(var(--gray-line));
394
+ cursor: pointer;
395
+ }
396
+ .search-combo-dim svg { width: 12px; height: 12px; color: hsl(var(--muted-foreground)); }
397
+ .search-combo input {
398
+ flex: 1; height: 100%; border: none; outline: none;
399
+ background: transparent; padding: 0 8px;
400
+ font-size: var(--font-size-base); color: hsl(var(--gray-primary));
401
+ }
402
+ .search-combo input::placeholder { color: hsl(var(--muted-foreground)); }
403
+ .search-combo-search-btn {
404
+ height: 100%; width: 32px; border: none; background: transparent;
405
+ display: inline-flex; align-items: center; justify-content: center;
406
+ cursor: pointer; color: hsl(var(--muted-foreground));
407
+ }
408
+ .search-combo-search-btn:hover { color: hsl(var(--primary)); }
409
+ .search-combo-search-btn svg { width: 14px; height: 14px; }
410
+
411
+ /* ToggleGroup */
412
+ .toggle-group {
413
+ display: inline-flex; background: hsl(var(--gray-muted));
414
+ border-radius: var(--radius-md); padding: 2px;
415
+ }
416
+ .toggle-item {
417
+ height: 26px; padding: 0 12px;
418
+ display: inline-flex; align-items: center;
419
+ font-size: var(--font-size-base); color: hsl(var(--gray-secondary-foreground));
420
+ border-radius: var(--radius-sm); cursor: pointer;
421
+ transition: all var(--duration-fast) var(--easing-ease);
422
+ white-space: nowrap; border: none; background: transparent;
423
+ }
424
+ .toggle-item:hover { color: hsl(var(--gray-primary)); }
425
+ .toggle-item.active {
426
+ background: hsl(var(--gray-white)); color: hsl(var(--gray-primary));
427
+ font-weight: var(--font-weight-medium); box-shadow: var(--shadow-sm);
428
+ }
429
+
430
+ /* ====================================================================
431
+ CardGrid — preset=standard
432
+ ==================================================================== */
433
+ .card-grid {
434
+ display: grid;
435
+ grid-template-columns: repeat(auto-fill, minmax(var(--card-grid-min, var(--card-grid-min-standard)), 1fr));
436
+ gap: var(--card-gap);
437
+ align-content: start;
438
+ }
439
+
440
+ /* ====================================================================
441
+ ItemCard — density=standard / iconStyle=avatar
442
+ ==================================================================== */
443
+ .item-card {
444
+ position: relative;
445
+ background: hsl(var(--card));
446
+ border: 1px solid hsl(var(--gray-line));
447
+ border-radius: var(--radius-lg);
448
+ padding: 16px;
449
+ display: flex; flex-direction: column;
450
+ cursor: pointer; overflow: hidden;
451
+ transition: border-color var(--duration-normal) var(--easing-ease),
452
+ box-shadow var(--duration-normal) var(--easing-ease);
453
+ }
454
+ .item-card:hover { border-color: hsl(var(--primary)); box-shadow: var(--shadow-sm); }
455
+ .item-card[data-disabled="true"] { background: hsl(var(--gray-muted)); cursor: not-allowed; opacity: 0.7; }
456
+
457
+ .card-title-row { display: flex; align-items: center; gap: 10px; }
458
+ .card-avatar {
459
+ position: relative; width: 32px; height: 32px;
460
+ border-radius: var(--input-radius); flex-shrink: 0;
461
+ display: flex; align-items: center; justify-content: center;
462
+ color: hsl(var(--gray-white)); font-size: 14px; font-weight: 600; overflow: hidden;
463
+ }
464
+ .card-avatar::after {
465
+ content: ""; position: absolute; width: 18px; height: 32px; right: 0; top: 0;
466
+ background: linear-gradient(180deg, rgba(255,255,255,0.4) 0%, rgba(255,255,255,0.2) 40%, transparent 100%);
467
+ pointer-events: none;
468
+ }
469
+ .avatar-blue { background: hsl(var(--avatar-blue)); }
470
+ .avatar-success { background: hsl(var(--avatar-success)); }
471
+ .avatar-mcp { background: hsl(var(--avatar-mcp)); }
472
+ .avatar-warning { background: hsl(var(--avatar-warning)); }
473
+ .avatar-data8 { background: hsl(var(--avatar-data8)); }
474
+ .avatar-berry { background: hsl(var(--avatar-berry)); }
475
+
476
+ .card-title {
477
+ flex: 1; min-width: 0; font-size: var(--font-size-lg);
478
+ font-weight: var(--font-weight-medium); color: hsl(var(--gray-primary));
479
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
480
+ }
481
+ .card-badge {
482
+ display: inline-flex; align-items: center; height: 16px; padding: 1px 4px;
483
+ font-size: 10px; border: 1px solid hsl(var(--gray-line));
484
+ border-radius: 2px; color: hsl(var(--gray-secondary-foreground)); background: transparent; flex-shrink: 0;
485
+ }
486
+ .status-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
487
+ .status-running { background: hsl(var(--status-running)); }
488
+ .status-stopped { background: hsl(var(--status-stopped)); }
489
+ .status-error { background: hsl(var(--status-error)); }
490
+
491
+ .card-desc {
492
+ margin-top: 4px; font-size: var(--font-size-base); color: hsl(var(--muted-foreground));
493
+ line-height: 1.5; overflow: hidden; text-overflow: ellipsis;
494
+ display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
495
+ }
496
+ .card-field-row { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; }
497
+ .card-field { display: flex; align-items: center; gap: 6px; font-size: var(--font-size-base); color: hsl(var(--gray-secondary-foreground)); }
498
+ .card-field svg { width: 12px; height: 12px; flex-shrink: 0; color: hsl(var(--muted-foreground)); }
499
+ .card-field-label { color: hsl(var(--muted-foreground)); flex-shrink: 0; }
500
+ .card-field-value { font-size: var(--font-size-lg); color: hsl(var(--gray-primary)); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
501
+
502
+ .card-supplementary {
503
+ margin-top: 8px; padding-bottom: 12px;
504
+ display: flex; align-items: center; gap: 12px;
505
+ font-size: var(--font-size-base); color: hsl(var(--muted-foreground));
506
+ }
507
+ .card-supplementary .item { display: inline-flex; align-items: center; gap: 4px; }
508
+ .card-supplementary svg { width: 12px; height: 12px; }
509
+
510
+ /* CardActionBar — mode=hover-slidebar */
511
+ .card-action-bar {
512
+ position: absolute; bottom: 0; left: 0; right: 0;
513
+ background: hsl(var(--card));
514
+ border-top: 1px solid hsl(var(--gray-line));
515
+ display: flex; z-index: 2;
516
+ transform: translateY(100%);
517
+ transition: transform var(--duration-normal) var(--easing-ease);
518
+ }
519
+ .item-card:hover .card-action-bar { transform: translateY(0); }
520
+ .card-action-bar .action-btn {
521
+ flex: 1; padding: 8px; text-align: center;
522
+ color: hsl(var(--gray-primary)); font-size: 13px;
523
+ font-weight: var(--font-weight-medium); cursor: pointer;
524
+ border: none; background: transparent;
525
+ border-right: 1px solid hsl(var(--gray-line));
526
+ transition: background var(--duration-fast), color var(--duration-fast);
527
+ }
528
+ .card-action-bar .action-btn:last-child { border-right: none; }
529
+ .card-action-bar .action-btn:hover { background: hsl(var(--gray-muted)); color: hsl(var(--primary)); }
530
+ .card-action-bar .action-btn.destructive { color: hsl(var(--destructive)); }
531
+ .card-action-bar .action-btn.destructive:hover { background: hsl(var(--destructive-bg)); }
532
+
533
+ /* ====================================================================
534
+ Pagination
535
+ ==================================================================== */
536
+ .pagination { display: flex; align-items: center; justify-content: space-between; }
537
+ .pagination-info { font-size: var(--font-size-base); color: hsl(var(--muted-foreground)); }
538
+ .pagination-controls { display: flex; align-items: center; gap: 4px; }
539
+ .page-btn {
540
+ min-width: 32px; height: 32px; padding: 0 8px;
541
+ border: 1px solid hsl(var(--gray-line)); border-radius: var(--radius-sm);
542
+ background: hsl(var(--gray-white)); color: hsl(var(--gray-primary));
543
+ font-size: var(--font-size-base); cursor: pointer;
544
+ display: inline-flex; align-items: center; justify-content: center;
545
+ transition: all var(--duration-fast);
546
+ }
547
+ .page-btn:hover { border-color: hsl(var(--primary)); color: hsl(var(--primary)); }
548
+ .page-btn.active { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); border-color: hsl(var(--primary)); }
549
+ .page-btn:disabled { cursor: not-allowed; color: hsl(var(--gray-disabled)); border-color: hsl(var(--gray-line)); }
550
+ .page-size { margin-left: 12px; font-size: var(--font-size-base); color: hsl(var(--gray-secondary-foreground)); }
551
+ .page-size select {
552
+ height: 28px; padding: 0 6px;
553
+ border: 1px solid hsl(var(--gray-line)); border-radius: var(--radius-sm);
554
+ background: hsl(var(--gray-white)); font-size: var(--font-size-base);
555
+ color: hsl(var(--gray-primary)); margin-left: 6px;
556
+ }
557
+ </style>
558
+ </head>
559
+ <body>
560
+
561
+ <!-- ===== Sidebar — 完整 L1 框架 ===== -->
562
+ <aside class="sidebar">
563
+ <div class="sidebar-header">
564
+ <div class="sidebar-logo" id="sidebarLogoArea">
565
+ <img src="./_assets/op-ai-gateway-logo.svg" alt="OP AI Gateway" />
566
+ <img class="collapsed-logo" src="./_assets/op-logo-collapsed.png" alt="OP" />
567
+ <svg class="expand-logo" viewBox="0 0 1024 1024" fill="currentColor" width="18" height="18"><path d="M151.68 616.96l82.56-82.56c12.8-12.8 12.8-32.64 0-45.44L151.68 406.4c-19.84-19.84-54.4-5.76-54.4 22.4v165.76c-0.64 28.16 33.92 42.88 54.4 22.4zM128.64 288h768c14.08 0 32-14.08 32-32s-17.92-32-32-32h-768c-14.08 0-32 14.08-32 32s17.92 32 32 32zM896.64 736h-768c-14.08 0-32 14.08-32 32s17.92 32 32 32h768c14.08 0 32-14.08 32-32s-17.28-32-32-32zM896.64 480h-480c-14.08 0-32 14.08-32 32s17.92 32 32 32h480c14.08 0 32-14.08 32-32s-17.28-32-32-32z"/></svg>
568
+ </div>
569
+ <button class="sidebar-collapse-btn" title="收起侧边栏">
570
+ <svg viewBox="0 0 1024 1024" fill="currentColor" width="18" height="18"><path d="M874.24 406.4l-82.56 82.56c-12.8 12.8-12.8 32.64 0 45.44l82.56 82.56c19.84 19.84 54.4 5.76 54.4-22.4V428.8c0-28.16-33.92-42.88-54.4-22.4zM128.64 288h768c14.08 0 32-14.08 32-32s-17.92-32-32-32h-768c-14.08 0-32 14.08-32 32s17.92 32 32 32zM896.64 736h-768c-14.08 0-32 14.08-32 32s17.92 32 32 32h768c14.08 0 32-14.08 32-32s-17.28-32-32-32zM128.64 544h480c14.08 0 32-14.08 32-32s-17.92-32-32-32h-480c-14.08 0-32 14.08-32 32s17.92 32 32 32z"/></svg>
571
+ </button>
572
+ </div>
573
+
574
+ <div class="sidebar-content">
575
+ <ul class="sidebar-menu">
576
+ <!-- AI 网关(当前活跃) -->
577
+ <li><a class="sidebar-menu-item active" href="#">
578
+ <span class="item-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg></span>
579
+ AI 网关
580
+ </a></li>
581
+
582
+ <!-- API 网关(父菜单) -->
583
+ <li>
584
+ <a class="sidebar-menu-item expanded" href="#" data-toggle="api-gateway">
585
+ <span class="item-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg></span>
586
+ API 网关
587
+ <span class="expand-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg></span>
588
+ </a>
589
+ <ul class="sidebar-sub-menu show" id="api-gateway">
590
+ <li><a class="sidebar-menu-item" href="#">实例管理</a></li>
591
+ <li><a class="sidebar-menu-item" href="#">共享实例管理</a></li>
592
+ </ul>
593
+ <div class="sidebar-flyout">
594
+ <a class="sidebar-menu-item" href="#">实例管理</a>
595
+ <a class="sidebar-menu-item" href="#">共享实例管理</a>
596
+ </div>
597
+ </li>
598
+
599
+ <!-- 云原生网关 -->
600
+ <li>
601
+ <a class="sidebar-menu-item" href="#" data-toggle="cloud-native-gw">
602
+ <span class="item-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 10h-1.26A8 8 0 109 20h9a5 5 0 000-10z"/></svg></span>
603
+ 云原生网关
604
+ <span class="expand-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg></span>
605
+ </a>
606
+ <ul class="sidebar-sub-menu" id="cloud-native-gw">
607
+ <li><a class="sidebar-menu-item" href="#">实例列表</a></li>
608
+ <li><a class="sidebar-menu-item" href="#">Nginx Ingress 迁移</a></li>
609
+ </ul>
610
+ <div class="sidebar-flyout">
611
+ <a class="sidebar-menu-item" href="#">实例列表</a>
612
+ <a class="sidebar-menu-item" href="#">Nginx Ingress 迁移</a>
613
+ </div>
614
+ </li>
615
+
616
+ <!-- 集群管理 -->
617
+ <li><a class="sidebar-menu-item" href="#">
618
+ <span class="item-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83"/></svg></span>
619
+ 集群管理
620
+ </a></li>
621
+
622
+ <!-- 认证授权 -->
623
+ <li>
624
+ <a class="sidebar-menu-item" href="#" data-toggle="auth-mgmt">
625
+ <span class="item-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg></span>
626
+ 认证授权
627
+ <span class="expand-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg></span>
628
+ </a>
629
+ <ul class="sidebar-sub-menu" id="auth-mgmt">
630
+ <li><a class="sidebar-menu-item" href="#">用户管理</a></li>
631
+ <li><a class="sidebar-menu-item" href="#">角色管理</a></li>
632
+ <li><a class="sidebar-menu-item" href="#">访问凭证</a></li>
633
+ </ul>
634
+ <div class="sidebar-flyout">
635
+ <a class="sidebar-menu-item" href="#">用户管理</a>
636
+ <a class="sidebar-menu-item" href="#">角色管理</a>
637
+ <a class="sidebar-menu-item" href="#">访问凭证</a>
638
+ </div>
639
+ </li>
640
+ </ul>
641
+ </div>
642
+
643
+ <div class="sidebar-divider"></div>
644
+ <div class="sidebar-footer">
645
+ <div class="sidebar-avatar">A</div>
646
+ <span class="sidebar-username">admin</span>
647
+ <button class="sidebar-more">
648
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/></svg>
649
+ </button>
650
+ </div>
651
+ </aside>
652
+
653
+ <!-- ============================================================
654
+ Main Content — ContentCard 单例容器
655
+ ============================================================ -->
656
+ <main class="main-content">
657
+ <div class="card-wrapper">
658
+
659
+ <!-- PageHeader -->
660
+ <div class="page-header">
661
+ <h1 class="page-header-title">实例管理</h1>
662
+ </div>
663
+
664
+ <!-- ActionToolbar -->
665
+ <div class="action-toolbar">
666
+ <div class="action-toolbar-left">
667
+ <button class="btn btn-primary">
668
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
669
+ 新建实例
670
+ </button>
671
+ <button class="btn btn-default">
672
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
673
+ 导入
674
+ </button>
675
+ </div>
676
+
677
+ <!-- SearchCombo -->
678
+ <div class="search-combo">
679
+ <span class="search-combo-dim">
680
+ 实例名称
681
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>
682
+ </span>
683
+ <input type="text" placeholder="请输入关键字" />
684
+ <button class="search-combo-search-btn" aria-label="搜索">
685
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
686
+ </button>
687
+ </div>
688
+
689
+ <div class="action-toolbar-right">
690
+ <div class="toggle-group" role="tablist" aria-label="状态筛选">
691
+ <span class="toggle-item active">全部</span>
692
+ <span class="toggle-item">运行中</span>
693
+ <span class="toggle-item">已停止</span>
694
+ <span class="toggle-item">异常</span>
695
+ </div>
696
+ </div>
697
+ </div>
698
+
699
+ <!-- ============================================================
700
+ CardGrid → ItemCard × 8
701
+ density=standard / iconStyle=avatar / mode=hover-slidebar
702
+ ============================================================ -->
703
+ <div class="card-grid" style="--card-grid-min: var(--card-grid-min-standard);">
704
+
705
+ <!-- ItemCard 1 — 运行中 -->
706
+ <article class="item-card" data-status="running">
707
+ <div class="card-title-row">
708
+ <div class="card-avatar avatar-blue" aria-hidden="true">P</div>
709
+ <span class="card-title">prod-gateway-cn-east</span>
710
+ <span class="card-badge">v2.1</span>
711
+ <span class="status-dot status-running" title="运行中"></span>
712
+ </div>
713
+ <p class="card-desc">production-cluster · 生产环境主集群</p>
714
+ <div class="card-field-row">
715
+ <div class="card-field">
716
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
717
+ <span class="card-field-label">对外访问</span>
718
+ <span class="card-field-value">api.gw.example.com</span>
719
+ </div>
720
+ <div class="card-field">
721
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
722
+ <span class="card-field-label">命名空间</span>
723
+ <span class="card-field-value">prod-default</span>
724
+ </div>
725
+ </div>
726
+ <div class="card-supplementary">
727
+ <span class="item">
728
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
729
+ 华东 1(杭州)
730
+ </span>
731
+ <span class="item">
732
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
733
+ 2 天前
734
+ </span>
735
+ </div>
736
+ <div class="card-action-bar" role="toolbar" aria-label="实例操作">
737
+ <button class="action-btn">停止</button>
738
+ <button class="action-btn">详情</button>
739
+ <button class="action-btn">编辑</button>
740
+ <button class="action-btn destructive">删除</button>
741
+ </div>
742
+ </article>
743
+
744
+ <!-- ItemCard 2 — 运行中 -->
745
+ <article class="item-card" data-status="running">
746
+ <div class="card-title-row">
747
+ <div class="card-avatar avatar-success" aria-hidden="true">D</div>
748
+ <span class="card-title">dev-gateway-test-01</span>
749
+ <span class="card-badge">v2.0</span>
750
+ <span class="status-dot status-running" title="运行中"></span>
751
+ </div>
752
+ <p class="card-desc">dev-cluster · 开发联调环境</p>
753
+ <div class="card-field-row">
754
+ <div class="card-field">
755
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
756
+ <span class="card-field-label">对外访问</span>
757
+ <span class="card-field-value">dev-api.gw.example.com</span>
758
+ </div>
759
+ <div class="card-field">
760
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
761
+ <span class="card-field-label">命名空间</span>
762
+ <span class="card-field-value">dev-team-a</span>
763
+ </div>
764
+ </div>
765
+ <div class="card-supplementary">
766
+ <span class="item">
767
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
768
+ 华北 2(北京)
769
+ </span>
770
+ <span class="item">
771
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
772
+ 5 小时前
773
+ </span>
774
+ </div>
775
+ <div class="card-action-bar">
776
+ <button class="action-btn">停止</button>
777
+ <button class="action-btn">详情</button>
778
+ <button class="action-btn">编辑</button>
779
+ <button class="action-btn destructive">删除</button>
780
+ </div>
781
+ </article>
782
+
783
+ <!-- ItemCard 3 — 已停止 -->
784
+ <article class="item-card" data-status="stopped">
785
+ <div class="card-title-row">
786
+ <div class="card-avatar avatar-data8" aria-hidden="true">S</div>
787
+ <span class="card-title">staging-gateway-bak</span>
788
+ <span class="card-badge">v1.9</span>
789
+ <span class="status-dot status-stopped" title="已停止"></span>
790
+ </div>
791
+ <p class="card-desc">staging-cluster · 预发环境备用节点</p>
792
+ <div class="card-field-row">
793
+ <div class="card-field">
794
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
795
+ <span class="card-field-label">对外访问</span>
796
+ <span class="card-field-value">—</span>
797
+ </div>
798
+ <div class="card-field">
799
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
800
+ <span class="card-field-label">命名空间</span>
801
+ <span class="card-field-value">staging-default</span>
802
+ </div>
803
+ </div>
804
+ <div class="card-supplementary">
805
+ <span class="item">
806
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
807
+ 华东 1(杭州)
808
+ </span>
809
+ <span class="item">
810
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
811
+ 7 天前
812
+ </span>
813
+ </div>
814
+ <div class="card-action-bar">
815
+ <button class="action-btn">启动</button>
816
+ <button class="action-btn">详情</button>
817
+ <button class="action-btn">编辑</button>
818
+ <button class="action-btn destructive">删除</button>
819
+ </div>
820
+ </article>
821
+
822
+ <!-- ItemCard 4 — 异常 -->
823
+ <article class="item-card" data-status="error">
824
+ <div class="card-title-row">
825
+ <div class="card-avatar avatar-berry" aria-hidden="true">E</div>
826
+ <span class="card-title">edge-gateway-sg-01</span>
827
+ <span class="card-badge">v2.1</span>
828
+ <span class="status-dot status-error" title="异常"></span>
829
+ </div>
830
+ <p class="card-desc">edge-cluster · 海外边缘节点(连接异常)</p>
831
+ <div class="card-field-row">
832
+ <div class="card-field">
833
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
834
+ <span class="card-field-label">对外访问</span>
835
+ <span class="card-field-value">sg-api.gw.example.com</span>
836
+ </div>
837
+ <div class="card-field">
838
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
839
+ <span class="card-field-label">命名空间</span>
840
+ <span class="card-field-value">edge-overseas</span>
841
+ </div>
842
+ </div>
843
+ <div class="card-supplementary">
844
+ <span class="item">
845
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
846
+ 新加坡
847
+ </span>
848
+ <span class="item">
849
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
850
+ 12 分钟前
851
+ </span>
852
+ </div>
853
+ <div class="card-action-bar">
854
+ <button class="action-btn">重启</button>
855
+ <button class="action-btn">详情</button>
856
+ <button class="action-btn">编辑</button>
857
+ <button class="action-btn destructive">删除</button>
858
+ </div>
859
+ </article>
860
+
861
+ <!-- ItemCard 5 — 运行中 -->
862
+ <article class="item-card" data-status="running">
863
+ <div class="card-title-row">
864
+ <div class="card-avatar avatar-mcp" aria-hidden="true">M</div>
865
+ <span class="card-title">mcp-gateway-prod</span>
866
+ <span class="card-badge">v2.1</span>
867
+ <span class="status-dot status-running" title="运行中"></span>
868
+ </div>
869
+ <p class="card-desc">mcp-cluster · MCP 协议生产网关</p>
870
+ <div class="card-field-row">
871
+ <div class="card-field">
872
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
873
+ <span class="card-field-label">对外访问</span>
874
+ <span class="card-field-value">mcp.gw.example.com</span>
875
+ </div>
876
+ <div class="card-field">
877
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
878
+ <span class="card-field-label">命名空间</span>
879
+ <span class="card-field-value">prod-mcp</span>
880
+ </div>
881
+ </div>
882
+ <div class="card-supplementary">
883
+ <span class="item">
884
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
885
+ 华东 1(杭州)
886
+ </span>
887
+ <span class="item">
888
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
889
+ 1 天前
890
+ </span>
891
+ </div>
892
+ <div class="card-action-bar">
893
+ <button class="action-btn">停止</button>
894
+ <button class="action-btn">详情</button>
895
+ <button class="action-btn">编辑</button>
896
+ <button class="action-btn destructive">删除</button>
897
+ </div>
898
+ </article>
899
+
900
+ <!-- ItemCard 6 — 运行中 -->
901
+ <article class="item-card" data-status="running">
902
+ <div class="card-title-row">
903
+ <div class="card-avatar avatar-warning" aria-hidden="true">L</div>
904
+ <span class="card-title">llm-router-gateway</span>
905
+ <span class="card-badge">Beta</span>
906
+ <span class="status-dot status-running" title="运行中"></span>
907
+ </div>
908
+ <p class="card-desc">router-cluster · LLM 多模型智能路由网关</p>
909
+ <div class="card-field-row">
910
+ <div class="card-field">
911
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
912
+ <span class="card-field-label">对外访问</span>
913
+ <span class="card-field-value">llm.gw.example.com</span>
914
+ </div>
915
+ <div class="card-field">
916
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
917
+ <span class="card-field-label">命名空间</span>
918
+ <span class="card-field-value">prod-llm</span>
919
+ </div>
920
+ </div>
921
+ <div class="card-supplementary">
922
+ <span class="item">
923
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
924
+ 华南 1(深圳)
925
+ </span>
926
+ <span class="item">
927
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
928
+ 刚刚
929
+ </span>
930
+ </div>
931
+ <div class="card-action-bar">
932
+ <button class="action-btn">停止</button>
933
+ <button class="action-btn">详情</button>
934
+ <button class="action-btn">编辑</button>
935
+ <button class="action-btn destructive">删除</button>
936
+ </div>
937
+ </article>
938
+
939
+ <!-- ItemCard 7 — 运行中 -->
940
+ <article class="item-card" data-status="running">
941
+ <div class="card-title-row">
942
+ <div class="card-avatar avatar-blue" aria-hidden="true">F</div>
943
+ <span class="card-title">finance-gateway-cn</span>
944
+ <span class="card-badge">v2.1</span>
945
+ <span class="status-dot status-running" title="运行中"></span>
946
+ </div>
947
+ <p class="card-desc">finance-cluster · 金融业务专用集群</p>
948
+ <div class="card-field-row">
949
+ <div class="card-field">
950
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
951
+ <span class="card-field-label">对外访问</span>
952
+ <span class="card-field-value">fin.gw.example.com</span>
953
+ </div>
954
+ <div class="card-field">
955
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
956
+ <span class="card-field-label">命名空间</span>
957
+ <span class="card-field-value">prod-finance</span>
958
+ </div>
959
+ </div>
960
+ <div class="card-supplementary">
961
+ <span class="item">
962
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
963
+ 华东 2(上海)
964
+ </span>
965
+ <span class="item">
966
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
967
+ 3 天前
968
+ </span>
969
+ </div>
970
+ <div class="card-action-bar">
971
+ <button class="action-btn">停止</button>
972
+ <button class="action-btn">详情</button>
973
+ <button class="action-btn">编辑</button>
974
+ <button class="action-btn destructive">删除</button>
975
+ </div>
976
+ </article>
977
+
978
+ <!-- ItemCard 8 — 已停止 -->
979
+ <article class="item-card" data-status="stopped">
980
+ <div class="card-title-row">
981
+ <div class="card-avatar avatar-success" aria-hidden="true">A</div>
982
+ <span class="card-title">archive-gateway-old</span>
983
+ <span class="card-badge">v1.8</span>
984
+ <span class="status-dot status-stopped" title="已停止"></span>
985
+ </div>
986
+ <p class="card-desc">archive-cluster · 旧版归档(待清理)</p>
987
+ <div class="card-field-row">
988
+ <div class="card-field">
989
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
990
+ <span class="card-field-label">对外访问</span>
991
+ <span class="card-field-value">—</span>
992
+ </div>
993
+ <div class="card-field">
994
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
995
+ <span class="card-field-label">命名空间</span>
996
+ <span class="card-field-value">archive-default</span>
997
+ </div>
998
+ </div>
999
+ <div class="card-supplementary">
1000
+ <span class="item">
1001
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
1002
+ 华北 1(青岛)
1003
+ </span>
1004
+ <span class="item">
1005
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
1006
+ 30 天前
1007
+ </span>
1008
+ </div>
1009
+ <div class="card-action-bar">
1010
+ <button class="action-btn">启动</button>
1011
+ <button class="action-btn">详情</button>
1012
+ <button class="action-btn">编辑</button>
1013
+ <button class="action-btn destructive">删除</button>
1014
+ </div>
1015
+ </article>
1016
+
1017
+ </div>
1018
+
1019
+ <!-- Pagination — standard-card 默认 12 条/页 -->
1020
+ <div class="pagination">
1021
+ <span class="pagination-info">共 28 条</span>
1022
+ <div class="pagination-controls">
1023
+ <button class="page-btn" disabled aria-label="上一页">
1024
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>
1025
+ </button>
1026
+ <button class="page-btn active">1</button>
1027
+ <button class="page-btn">2</button>
1028
+ <button class="page-btn">3</button>
1029
+ <button class="page-btn" aria-label="下一页">
1030
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
1031
+ </button>
1032
+ <span class="page-size">
1033
+ 每页
1034
+ <select>
1035
+ <option>12</option>
1036
+ <option>24</option>
1037
+ <option>48</option>
1038
+ </select>
1039
+
1040
+ </span>
1041
+ </div>
1042
+ </div>
1043
+
1044
+ </div>
1045
+ </main>
1046
+
1047
+ <script>
1048
+ // Sidebar collapse toggle
1049
+ const sidebar = document.querySelector('.sidebar');
1050
+ document.querySelector('.sidebar-collapse-btn').addEventListener('click', function() {
1051
+ sidebar.classList.toggle('collapsed');
1052
+ });
1053
+ // Sidebar expand via logo click (collapsed state)
1054
+ document.getElementById('sidebarLogoArea').addEventListener('click', function() {
1055
+ if (sidebar.classList.contains('collapsed')) {
1056
+ sidebar.classList.remove('collapsed');
1057
+ }
1058
+ });
1059
+ // Sidebar sub-menu expand toggle
1060
+ document.querySelectorAll('.sidebar-menu-item[data-toggle]').forEach(item => {
1061
+ item.addEventListener('click', function(e) {
1062
+ e.preventDefault();
1063
+ this.classList.toggle('expanded');
1064
+ const targetId = this.getAttribute('data-toggle');
1065
+ const target = document.getElementById(targetId);
1066
+ if (target) target.classList.toggle('show');
1067
+ });
1068
+ });
1069
+ // ToggleGroup 切换
1070
+ document.querySelectorAll('.toggle-group').forEach(group => {
1071
+ group.addEventListener('click', e => {
1072
+ const item = e.target.closest('.toggle-item');
1073
+ if (!item) return;
1074
+ group.querySelectorAll('.toggle-item').forEach(i => i.classList.remove('active'));
1075
+ item.classList.add('active');
1076
+ });
1077
+ });
1078
+ // ItemCard 点击导航
1079
+ document.querySelectorAll('.item-card').forEach(card => {
1080
+ card.addEventListener('click', () => {
1081
+ console.log('navigate to detail:', card.querySelector('.card-title').textContent);
1082
+ });
1083
+ });
1084
+ // ActionBar stopPropagation
1085
+ document.querySelectorAll('.card-action-bar .action-btn').forEach(btn => {
1086
+ btn.addEventListener('click', e => {
1087
+ e.stopPropagation();
1088
+ console.log('action:', btn.textContent.trim());
1089
+ });
1090
+ });
1091
+ </script>
1092
+
1093
+ </body>
1094
+ </html>