@teamix-evo/skills 0.5.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 (72) hide show
  1. package/package.json +2 -2
  2. package/src/teamix-evo-design-opentrek/SKILL.md +210 -42
  3. package/src/teamix-evo-design-opentrek/boundaries.md +3 -3
  4. package/src/teamix-evo-design-opentrek/components.md +41 -40
  5. package/src/teamix-evo-design-opentrek/examples/detail-ai-gateway-1.html +1069 -0
  6. package/src/teamix-evo-design-opentrek/examples/detail-ai-gateway-instance.html +941 -0
  7. package/src/teamix-evo-design-opentrek/examples/detail-page-api-doc.html +906 -0
  8. package/src/teamix-evo-design-opentrek/examples/detail-page-config.html +993 -0
  9. package/src/teamix-evo-design-opentrek/examples/detail-page-monitor.html +1339 -0
  10. package/src/teamix-evo-design-opentrek/examples/detail-page.html +933 -0
  11. package/src/teamix-evo-design-opentrek/examples/settings-page.html +1119 -0
  12. package/src/teamix-evo-design-opentrek/examples/standard-card-list.html +1094 -0
  13. package/src/teamix-evo-design-opentrek/examples/standard-table-list.html +1361 -0
  14. package/src/teamix-evo-design-opentrek/examples/wizard-form-page.html +877 -0
  15. package/src/teamix-evo-design-opentrek/flows.md +85 -12
  16. package/src/teamix-evo-design-opentrek/foundations.md +9 -9
  17. package/src/teamix-evo-design-opentrek/generation-flow.md +15 -3
  18. package/src/teamix-evo-design-opentrek/pages/detail-page/SKILL.md +260 -0
  19. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/api-doc-detail.md +163 -0
  20. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/comparison-detail.md +100 -0
  21. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/monitor-detail.md +190 -0
  22. package/src/teamix-evo-design-opentrek/pages/detail-page/patterns/resource-detail.md +148 -0
  23. package/src/teamix-evo-design-opentrek/pages/form-page/SKILL.md +362 -0
  24. package/src/teamix-evo-design-opentrek/pages/list-page/SKILL.md +286 -0
  25. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/action-column-spec.md +60 -0
  26. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/column-meta-rules.md +117 -0
  27. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/search-combo-spec.md +194 -0
  28. package/src/teamix-evo-design-opentrek/pages/list-page/_shared/state-action-pattern.md +51 -0
  29. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/advanced-filter-list.md +94 -0
  30. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/card-list.md +558 -0
  31. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/drawer-list.md +76 -0
  32. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/expandable-list.md +70 -0
  33. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/l2-sidebar-list.md +73 -0
  34. package/src/teamix-evo-design-opentrek/pages/list-page/patterns/standard-list.md +198 -0
  35. package/src/teamix-evo-design-opentrek/patterns/color-mapping.md +1 -1
  36. package/src/teamix-evo-design-opentrek/patterns/detail-page.md +217 -152
  37. package/src/teamix-evo-design-opentrek/patterns/form-page.md +437 -231
  38. package/src/teamix-evo-design-opentrek/patterns/list-page.md +220 -292
  39. package/src/teamix-evo-design-opentrek/patterns/page-types.md +40 -130
  40. package/src/teamix-evo-design-opentrek/rules/_assets/OP_AGENT RUNTIME.svg +1 -0
  41. package/src/teamix-evo-design-opentrek/rules/_assets/OP_AI GATEWAY.svg +1 -0
  42. package/src/teamix-evo-design-opentrek/rules/_assets/OP_AI STUDIO.svg +1 -0
  43. package/src/teamix-evo-design-opentrek/rules/_assets/OP_DEV-2.svg +1 -0
  44. package/src/teamix-evo-design-opentrek/rules/_assets/OP_LOGO.svg +1 -0
  45. package/src/teamix-evo-design-opentrek/rules/_assets/OP_OPS.svg +1 -0
  46. package/src/teamix-evo-design-opentrek/rules/boundaries.rules.json +3 -3
  47. package/src/teamix-evo-design-opentrek/rules/business-mapping.json +124 -0
  48. package/src/teamix-evo-design-opentrek/rules/common-components.json +924 -0
  49. package/src/teamix-evo-design-opentrek/rules/component-specs.json +1083 -0
  50. package/src/teamix-evo-design-opentrek/rules/design-tokens.css +433 -0
  51. package/src/teamix-evo-design-opentrek/rules/design-tokens.json +2798 -0
  52. package/src/teamix-evo-design-opentrek/rules/layout-rules.json +218 -0
  53. package/src/teamix-evo-design-opentrek/rules/page-flow.json +351 -0
  54. package/src/teamix-evo-design-opentrek/rules/page-frame.json +241 -0
  55. package/src/teamix-evo-design-opentrek/rules/page-header-spec.md +123 -0
  56. package/src/teamix-evo-design-opentrek/rules/page-types.json +206 -0
  57. package/src/teamix-evo-design-opentrek/rules/sidebar-spec.md +217 -0
  58. package/src/teamix-evo-design-opentrek/rules/styling.json +188 -0
  59. package/src/teamix-evo-design-opentrek/rules/token-mapping.md +284 -0
  60. package/src/teamix-evo-design-uni-manager/SKILL.md +1 -1
  61. package/src/teamix-evo-design-uni-manager/boundaries.md +3 -3
  62. package/src/teamix-evo-design-uni-manager/brand.md +1 -1
  63. package/src/teamix-evo-design-uni-manager/components.md +30 -28
  64. package/src/teamix-evo-design-uni-manager/foundations.md +21 -21
  65. package/src/teamix-evo-design-uni-manager/generation-flow.md +3 -1
  66. package/src/teamix-evo-design-uni-manager/patterns/detail-page.md +1 -1
  67. package/src/teamix-evo-design-uni-manager/patterns/form-page.md +18 -18
  68. package/src/teamix-evo-design-uni-manager/patterns/list-page.md +29 -29
  69. package/src/teamix-evo-design-uni-manager/patterns/page-types.md +11 -11
  70. package/src/teamix-evo-design-uni-manager/philosophy.md +1 -1
  71. package/src/teamix-evo-design-uni-manager/rules/boundaries.rules.json +3 -3
  72. package/src/teamix-evo-design-opentrek/patterns/sidebar.md +0 -122
@@ -0,0 +1,1069 @@
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>AI 网关实例详情 · 概览 — v7.8.4</title>
7
+ <!--
8
+ ★ AI 网关实例详情页(概览)— Detail Page Instance Overview
9
+ ─────────────────────────────────────────────────────────────
10
+ 布局:TWO_COL(实例级 Sidebar + ContentCard 单例容器)
11
+ Sidebar:14 项实例上下文菜单(13 L1 + 1 父菜单含 2 L2 子项)
12
+ 内容区模式:PageHeader(面包屑)+ 网关类型标签 + Tabs(基本信息 / 接入点)
13
+ ─────────────────────────────────────────────────────────────
14
+ 组件清单:
15
+ • PageHeader — 面包屑模式
16
+ • GatewayTypeTag — 网关类型标签
17
+ • Tabs
18
+ • OverviewStatGrid — 7 张统计卡片
19
+ • StatCard — 三段式统计卡
20
+ • DescriptionList — 4 列布局
21
+ • StatusBadge — 状态徽章
22
+ • DataTable — 接入点表格
23
+ ─────────────────────────────────────────────────────────────
24
+ 规范:page-rule-system v7.8.4 / Tokens v4.1 (TrekClaw)
25
+ -->
26
+ <style>
27
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
28
+
29
+ :root {
30
+ /* ===== Brand / Primary ===== */
31
+ --primary: 218.6 100% 46.7%;
32
+ --primary-foreground: 0 0% 100%;
33
+ --primary-hover: 218.6 100% 42%;
34
+ --primary-click: 218.6 100% 37.5%;
35
+
36
+ /* ===== Gray Scale (v7.4) ===== */
37
+ --gray-primary: 220 9% 7%;
38
+ --gray-primary-foreground: 210 33% 99%;
39
+ --gray-secondary-foreground: 216 4% 26%;
40
+ --muted-foreground: 216 2% 45%;
41
+ --gray-disabled: 210 3% 63%;
42
+ --gray-line: 210 9% 91%;
43
+ --gray-sidebar-accent: 210 12% 93%;
44
+ --gray-muted: 220 18% 97%;
45
+ --gray-white: 0 0% 100%;
46
+
47
+ /* Legacy aliases */
48
+ --gray-title: 220 9% 7%;
49
+ --gray-secondary: 216 4% 26%;
50
+ --gray-tertiary: 216 2% 45%;
51
+ --gray-border: 210 9% 91%;
52
+ --gray-fill: 220 18% 97%;
53
+ --gray-bg-dark: 220 18% 97%;
54
+ --gray-bg: 220 18% 97%;
55
+
56
+ /* ===== Semantic ===== */
57
+ --success: 142 76% 36%;
58
+ --success-bg: 152 82% 96%;
59
+ --success-border: 142 77% 73%;
60
+ --warning: 40 88% 48%;
61
+ --warning-bg: 43 100% 94%;
62
+ --warning-border: 40 92% 68%;
63
+ --destructive: 0 72% 51%;
64
+ --destructive-bg: 0 86% 97%;
65
+ --destructive-border: 0 88.7% 86.1%;
66
+ --info: 221 83% 53%;
67
+ --info-bg: 214 100% 97%;
68
+ --info-border: 213 94% 82.5%;
69
+
70
+ /* ===== Surface ===== */
71
+ --background: 220 18% 97%;
72
+ --card: 0 0% 100%;
73
+ --card-foreground: 220 9% 7%;
74
+ --border: 210 9% 91%;
75
+ --ring: 218.6 100% 46.7%;
76
+
77
+ /* ===== Sidebar ===== */
78
+ --sidebar: 220 18% 97%;
79
+ --sidebar-foreground: 220 9% 7%;
80
+ --sidebar-active: 210 12% 93%;
81
+ --sidebar-active-foreground: 220 9% 7%;
82
+ --sidebar-hover: 220 18% 97%;
83
+ --sidebar-group: 216 2% 45%;
84
+ --sidebar-item: 220 9% 7%;
85
+ --sidebar-item-muted: 216 4% 26%;
86
+ --sidebar-border: 210 9% 91%;
87
+
88
+ /* ===== Geometry ===== */
89
+ --radius: 1rem;
90
+ --radius-sm: 4px;
91
+ --radius-md: 8px;
92
+ --radius-lg: 12px;
93
+
94
+ /* ===== Spacing (v7.5 layered padding) ===== */
95
+ --gap-xs: 4px;
96
+ --btn-padding-x: 16px;
97
+ --btn-padding-x-sm: 12px;
98
+ --button-gap: 8px;
99
+ --tabs-gap: 24px;
100
+ --card-gap: 16px;
101
+ --page-container-gap: 16px;
102
+ --page-container-padding: 16px;
103
+ --page-container-padding-left: 0px;
104
+ --card-padding-x: 20px;
105
+
106
+ /* ===== Shadow (v7.6 surface) ===== */
107
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
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
+ /* ===== Input ===== */
122
+ --input-height: 32px;
123
+ --input-radius: 8px;
124
+
125
+ /* ===== Layout ===== */
126
+ --layout-sidebar-width: 240px;
127
+
128
+ /* ===== Motion ===== */
129
+ --duration-fast: 150ms;
130
+ --duration-normal: 200ms;
131
+ --easing-ease: ease;
132
+ }
133
+
134
+ body {
135
+ font-family: var(--font-sans);
136
+ font-size: var(--font-size-base);
137
+ color: hsl(var(--gray-primary));
138
+ background: hsl(var(--background));
139
+ min-height: 100vh;
140
+ min-width: 1280px;
141
+ }
142
+
143
+ /* ===== Sidebar ===== */
144
+ .sidebar {
145
+ position: fixed; top: 0; left: 0; bottom: 0;
146
+ width: var(--layout-sidebar-width);
147
+ background: hsl(var(--sidebar));
148
+ z-index: 100;
149
+ display: flex; flex-direction: column;
150
+ overflow: hidden;
151
+ transition: width 0.2s ease;
152
+ }
153
+ .sidebar-header {
154
+ height: 56px; padding: 0 16px;
155
+ display: flex; align-items: center; gap: var(--gap-xs);
156
+ flex-shrink: 0;
157
+ }
158
+ .sidebar-logo {
159
+ height: 28px; flex-shrink: 0;
160
+ display: flex; align-items: center;
161
+ overflow: hidden;
162
+ }
163
+ .sidebar-logo img {
164
+ height: 28px; width: auto; display: block;
165
+ }
166
+ .sidebar-logo .collapsed-logo {
167
+ display: none; width: 30px; height: 30px;
168
+ }
169
+ .sidebar-logo .expand-logo {
170
+ display: none; width: 18px; height: 18px;
171
+ color: hsl(var(--muted-foreground));
172
+ }
173
+ .sidebar-collapse-btn {
174
+ margin-left: auto; width: 18px; height: 18px;
175
+ background: none; border: none; padding: 0; cursor: pointer;
176
+ display: flex; align-items: center; justify-content: center;
177
+ color: hsl(var(--muted-foreground)); flex-shrink: 0;
178
+ }
179
+ .sidebar-collapse-btn svg { width: 18px; height: 18px; }
180
+
181
+ /* ===== Sidebar Collapsed State ===== */
182
+ .sidebar.collapsed { width: 68px; overflow: visible; }
183
+ .sidebar.collapsed .sidebar-header { padding: 0 12px; justify-content: center; }
184
+ .sidebar.collapsed .sidebar-logo { cursor: pointer; }
185
+ .sidebar.collapsed .sidebar-logo img { display: none; }
186
+ .sidebar.collapsed .sidebar-logo .collapsed-logo { display: block; }
187
+ .sidebar.collapsed .sidebar-logo:hover .collapsed-logo { display: none; }
188
+ .sidebar.collapsed .sidebar-logo:hover .expand-logo { display: block; }
189
+ .sidebar.collapsed .sidebar-collapse-btn { display: none; }
190
+ .sidebar.collapsed .sidebar-content { padding: 12px 0; overflow-y: auto; overflow-x: hidden; }
191
+ .sidebar.collapsed .sidebar-menu { padding: 0; }
192
+ .sidebar.collapsed .sidebar-menu > li { display: flex; justify-content: center; }
193
+ .sidebar.collapsed .sidebar-menu > li > a.sidebar-menu-item {
194
+ justify-content: center; padding: 0; width: 40px; height: 40px;
195
+ border-radius: var(--radius-md); position: relative; flex-shrink: 0;
196
+ gap: 0;
197
+ }
198
+ .sidebar.collapsed .sidebar-menu > li > a.sidebar-menu-item .item-icon { margin: 0; }
199
+ .sidebar.collapsed .sidebar-menu > li > a > span:not(.item-icon),
200
+ .sidebar.collapsed .sidebar-menu > li > a > .expand-icon,
201
+ .sidebar.collapsed .sidebar-menu-item:not(.item-icon):after { display: none; }
202
+ .sidebar.collapsed .sidebar-menu > li > a { font-size: 0; }
203
+ .sidebar.collapsed .sidebar-menu > li > a > .item-icon { font-size: var(--font-size-lg); }
204
+ .sidebar.collapsed .sidebar-sub-menu { display: none !important; }
205
+ .sidebar.collapsed .sidebar-divider { margin: 0 14px; }
206
+ .sidebar.collapsed .sidebar-footer { padding: 12px 10px 16px; justify-content: center; }
207
+ .sidebar.collapsed .sidebar-username,
208
+ .sidebar.collapsed .sidebar-more { display: none; }
209
+
210
+ /* ===== Sidebar Flyout (collapsed hover) ===== */
211
+ .sidebar.collapsed .sidebar-menu > li { position: relative; }
212
+ .sidebar.collapsed .sidebar-menu > li:hover > .sidebar-flyout {
213
+ display: block;
214
+ }
215
+ .sidebar-flyout {
216
+ display: none;
217
+ position: absolute; left: 100%; top: 0;
218
+ min-width: 160px; padding: 4px;
219
+ background: hsl(var(--card));
220
+ border: 1px solid hsl(var(--gray-line));
221
+ border-radius: var(--radius-md);
222
+ box-shadow: 0 4px 12px rgba(0,0,0,0.08);
223
+ z-index: 200;
224
+ }
225
+ .sidebar-flyout .sidebar-menu-item {
226
+ height: 36px; padding: 0 12px;
227
+ font-size: var(--font-size-base) !important;
228
+ font-weight: var(--font-weight-normal);
229
+ color: hsl(var(--gray-primary));
230
+ border-radius: var(--radius-sm);
231
+ white-space: nowrap;
232
+ }
233
+ .sidebar-flyout .sidebar-menu-item:hover {
234
+ background: hsl(var(--gray-muted));
235
+ }
236
+
237
+ /* ===== Main Layout ===== */
238
+ .main-content {
239
+ margin-left: var(--layout-sidebar-width);
240
+ min-height: 100vh;
241
+ transition: margin-left 0.2s ease;
242
+ }
243
+ .sidebar.collapsed ~ .main-content { margin-left: 68px; }
244
+ .sidebar-content {
245
+ flex: 1; overflow-y: auto; padding: 12px 0;
246
+ }
247
+ .sidebar-menu { list-style: none; padding: 0 8px; display: flex; flex-direction: column; gap: 2px; }
248
+ .sidebar-menu-item {
249
+ display: flex; align-items: center; gap: var(--button-gap);
250
+ padding: 0 12px; height: 40px;
251
+ border-radius: var(--radius-md);
252
+ font-size: var(--font-size-lg); font-weight: var(--font-weight-medium);
253
+ color: hsl(var(--sidebar-item-muted));
254
+ text-decoration: none; cursor: pointer;
255
+ transition: background var(--duration-fast), color var(--duration-fast);
256
+ white-space: nowrap;
257
+ }
258
+ .sidebar-menu-item:hover {
259
+ background: hsl(var(--sidebar-hover));
260
+ color: hsl(var(--sidebar-item));
261
+ }
262
+ .sidebar-menu-item.active {
263
+ background: hsl(var(--sidebar-active));
264
+ color: hsl(var(--sidebar-active-foreground));
265
+ }
266
+ .sidebar-menu-item .item-icon {
267
+ width: 16px; height: 16px; flex-shrink: 0;
268
+ display: flex; align-items: center; justify-content: center;
269
+ }
270
+ .sidebar-menu-item .expand-icon {
271
+ margin-left: auto; width: 16px; height: 16px;
272
+ transition: transform var(--duration-fast);
273
+ }
274
+ .sidebar-menu-item.expanded .expand-icon { transform: rotate(90deg); }
275
+ .sidebar-sub-menu {
276
+ list-style: none; padding: 0;
277
+ display: none;
278
+ }
279
+ .sidebar-sub-menu.show { display: block; }
280
+ .sidebar-sub-menu .sidebar-menu-item {
281
+ height: 36px; font-size: var(--font-size-base); font-weight: var(--font-weight-normal);
282
+ padding-left: 36px;
283
+ }
284
+ .sidebar-divider {
285
+ height: 1px; background: hsl(var(--sidebar-border));
286
+ margin: 0 12px; flex-shrink: 0;
287
+ }
288
+ .sidebar-footer {
289
+ flex-shrink: 0; display: flex; align-items: center;
290
+ gap: var(--button-gap); padding: 12px 12px 16px 24px;
291
+ }
292
+ .sidebar-avatar {
293
+ width: 28px; height: 28px; border-radius: 50%;
294
+ background: hsl(var(--sidebar-active));
295
+ display: flex; align-items: center; justify-content: center;
296
+ font-size: var(--font-size-base); font-weight: 600;
297
+ color: hsl(var(--gray-primary)); flex-shrink: 0;
298
+ }
299
+ .sidebar-username {
300
+ flex: 1; font-size: var(--font-size-lg); font-weight: var(--font-weight-medium);
301
+ color: hsl(var(--sidebar-item)); overflow: hidden;
302
+ text-overflow: ellipsis; white-space: nowrap;
303
+ }
304
+ .sidebar-more {
305
+ width: 28px; height: 28px; border-radius: var(--radius-sm);
306
+ border: none; background: transparent; cursor: pointer;
307
+ display: flex; align-items: center; justify-content: center;
308
+ color: hsl(var(--muted-foreground));
309
+ }
310
+ .sidebar-more:hover { background: hsl(var(--sidebar-hover)); color: hsl(var(--gray-primary)); }
311
+
312
+ /* ===== Page Container ===== */
313
+ .page-container {
314
+ padding: var(--page-container-padding) var(--page-container-padding) var(--page-container-padding) var(--page-container-padding-left);
315
+ }
316
+ .card {
317
+ background: hsl(var(--card));
318
+ border-radius: var(--radius-lg);
319
+ border: none;
320
+ box-shadow: var(--shadow-sm, 0 1px 2px rgba(0,0,0,0.05));
321
+ overflow: hidden;
322
+ display: flex; flex-direction: column;
323
+ min-height: calc(100vh - 32px);
324
+ padding: 0 var(--card-padding-x);
325
+ }
326
+
327
+ /* ===== PageHeader — Breadcrumb Mode ===== */
328
+ .page-header {
329
+ height: 64px; padding: 0;
330
+ display: flex; align-items: center; justify-content: space-between;
331
+ background: transparent; border: none; box-shadow: none;
332
+ flex-shrink: 0;
333
+ }
334
+ .page-header-left { display: flex; align-items: center; }
335
+ .breadcrumb {
336
+ display: flex; align-items: center; gap: 4px;
337
+ font-size: var(--font-size-page-header); font-weight: var(--font-weight-medium);
338
+ color: hsl(var(--gray-secondary-foreground));
339
+ }
340
+ .breadcrumb a { color: hsl(var(--gray-secondary-foreground)); text-decoration: none; cursor: pointer; }
341
+ .breadcrumb a:hover { color: hsl(var(--gray-primary)); }
342
+ .breadcrumb .separator {
343
+ color: hsl(var(--muted-foreground));
344
+ display: flex; align-items: center;
345
+ }
346
+ .breadcrumb .separator svg { width: 20px; height: 20px; }
347
+ .breadcrumb .current { color: hsl(var(--gray-primary)); }
348
+
349
+ /* ===== Gateway Type Tag (面包屑后缀) ===== */
350
+ .gateway-type-tag {
351
+ margin-left: 16px;
352
+ display: inline-flex;
353
+ align-items: center;
354
+ height: 24px;
355
+ padding: 0 10px;
356
+ font-size: 14px;
357
+ line-height: 16px;
358
+ color: hsl(var(--primary));
359
+ background: hsl(var(--primary) / 0.08);
360
+ border-radius: 4px;
361
+ font-weight: var(--font-weight-medium);
362
+ }
363
+
364
+ /* ===== Tabs ===== */
365
+ .tabs {
366
+ border-bottom: 1px solid hsl(var(--gray-line));
367
+ }
368
+ .tabs-list {
369
+ display: flex; gap: var(--tabs-gap); list-style: none;
370
+ }
371
+ .tab-item {
372
+ padding: 10px 0; font-size: var(--font-size-lg);
373
+ color: hsl(var(--gray-secondary-foreground)); cursor: pointer;
374
+ border-bottom: 2px solid transparent;
375
+ transition: color var(--duration-fast), border-color var(--duration-fast);
376
+ font-weight: var(--font-weight-normal);
377
+ background: transparent; border-left: none; border-right: none; border-top: none;
378
+ }
379
+ .tab-item:hover { color: hsl(var(--gray-primary)); }
380
+ .tab-item.active {
381
+ color: hsl(var(--primary));
382
+ border-bottom-color: hsl(var(--primary));
383
+ font-weight: var(--font-weight-medium);
384
+ }
385
+ .tab-content { display: none; padding: 20px 0; }
386
+ .tab-content.active { display: block; }
387
+
388
+ /* ===== Section ===== */
389
+ .list-section { padding-top: 24px; }
390
+ .list-section:first-child { padding-top: 0; }
391
+ .list-section-title {
392
+ font-size: var(--font-size-lg); font-weight: 600;
393
+ color: hsl(var(--gray-primary)); margin-bottom: 12px;
394
+ }
395
+
396
+ /* ===== StatCard + OverviewStatGrid ===== */
397
+ .stat-grid {
398
+ display: grid;
399
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
400
+ gap: 12px;
401
+ }
402
+ .stat-card {
403
+ position: relative;
404
+ border-radius: var(--radius-md);
405
+ padding: 16px;
406
+ display: flex; flex-direction: column;
407
+ gap: 6px;
408
+ cursor: pointer;
409
+ transition: background var(--duration-fast), box-shadow var(--duration-fast), transform var(--duration-fast);
410
+ }
411
+ .stat-card:hover {
412
+ box-shadow: var(--shadow-sm);
413
+ transform: translateY(-1px);
414
+ }
415
+ .stat-card-icon {
416
+ position: absolute;
417
+ top: 12px;
418
+ right: 12px;
419
+ width: 32px;
420
+ height: 32px;
421
+ transition: color var(--duration-fast);
422
+ }
423
+ .stat-card-link {
424
+ position: absolute;
425
+ top: 16px;
426
+ right: 16px;
427
+ font-size: 12px;
428
+ line-height: 18px;
429
+ color: hsl(var(--primary));
430
+ opacity: 0;
431
+ transition: opacity var(--duration-fast);
432
+ cursor: pointer;
433
+ }
434
+ .stat-card:hover .stat-card-link {
435
+ opacity: 1;
436
+ }
437
+ .stat-card:hover .stat-card-icon {
438
+ opacity: 0;
439
+ }
440
+ .stat-card-label {
441
+ font-size: 12px;
442
+ line-height: 18px;
443
+ color: hsl(var(--muted-foreground));
444
+ font-weight: var(--font-weight-normal);
445
+ }
446
+ .stat-card-value {
447
+ font-size: 24px;
448
+ line-height: 32px;
449
+ font-weight: 600;
450
+ color: hsl(var(--gray-primary));
451
+ }
452
+
453
+ /* 渐变背景 + 装饰 icon 配色(每张卡片不同色系) */
454
+ .stat-card-1 { background: linear-gradient(135deg, hsl(210 100% 97%) 0%, hsl(210 80% 94%) 100%); }
455
+ .stat-card-1:hover { background: linear-gradient(135deg, hsl(210 100% 95%) 0%, hsl(210 80% 91%) 100%); }
456
+ .stat-card-1 .stat-card-icon { color: hsl(210 80% 75% / 0.4); }
457
+ .stat-card-1:hover .stat-card-icon { color: hsl(210 80% 65% / 0.5); }
458
+
459
+ .stat-card-2 { background: linear-gradient(135deg, hsl(142 60% 97%) 0%, hsl(142 50% 93%) 100%); }
460
+ .stat-card-2:hover { background: linear-gradient(135deg, hsl(142 60% 95%) 0%, hsl(142 50% 90%) 100%); }
461
+ .stat-card-2 .stat-card-icon { color: hsl(142 50% 70% / 0.4); }
462
+ .stat-card-2:hover .stat-card-icon { color: hsl(142 50% 55% / 0.5); }
463
+
464
+ .stat-card-3 { background: linear-gradient(135deg, hsl(262 60% 97%) 0%, hsl(262 50% 93%) 100%); }
465
+ .stat-card-3:hover { background: linear-gradient(135deg, hsl(262 60% 95%) 0%, hsl(262 50% 90%) 100%); }
466
+ .stat-card-3 .stat-card-icon { color: hsl(262 50% 75% / 0.4); }
467
+ .stat-card-3:hover .stat-card-icon { color: hsl(262 50% 65% / 0.5); }
468
+
469
+ .stat-card-4 { background: linear-gradient(135deg, hsl(40 80% 97%) 0%, hsl(40 60% 93%) 100%); }
470
+ .stat-card-4:hover { background: linear-gradient(135deg, hsl(40 80% 95%) 0%, hsl(40 60% 90%) 100%); }
471
+ .stat-card-4 .stat-card-icon { color: hsl(40 60% 70% / 0.4); }
472
+ .stat-card-4:hover .stat-card-icon { color: hsl(40 60% 55% / 0.5); }
473
+
474
+ .stat-card-5 { background: linear-gradient(135deg, hsl(190 60% 97%) 0%, hsl(190 50% 93%) 100%); }
475
+ .stat-card-5:hover { background: linear-gradient(135deg, hsl(190 60% 95%) 0%, hsl(190 50% 90%) 100%); }
476
+ .stat-card-5 .stat-card-icon { color: hsl(190 50% 70% / 0.4); }
477
+ .stat-card-5:hover .stat-card-icon { color: hsl(190 50% 55% / 0.5); }
478
+
479
+ .stat-card-6 { background: linear-gradient(135deg, hsl(340 60% 97%) 0%, hsl(340 50% 94%) 100%); }
480
+ .stat-card-6:hover { background: linear-gradient(135deg, hsl(340 60% 95%) 0%, hsl(340 50% 91%) 100%); }
481
+ .stat-card-6 .stat-card-icon { color: hsl(340 50% 75% / 0.4); }
482
+ .stat-card-6:hover .stat-card-icon { color: hsl(340 50% 65% / 0.5); }
483
+
484
+ .stat-card-7 { background: linear-gradient(135deg, hsl(25 70% 97%) 0%, hsl(25 60% 93%) 100%); }
485
+ .stat-card-7:hover { background: linear-gradient(135deg, hsl(25 70% 95%) 0%, hsl(25 60% 90%) 100%); }
486
+ .stat-card-7 .stat-card-icon { color: hsl(25 60% 70% / 0.4); }
487
+ .stat-card-7:hover .stat-card-icon { color: hsl(25 60% 55% / 0.5); }
488
+
489
+ /* ===== DescriptionList — 4 cols ===== */
490
+ .description-list {
491
+ display: grid;
492
+ grid-template-columns: repeat(4, 1fr);
493
+ gap: 0 24px;
494
+ }
495
+ .description-item {
496
+ display: flex; align-items: center;
497
+ height: 36px; padding: 8px 0;
498
+ gap: 12px;
499
+ min-width: 0;
500
+ }
501
+ .description-label {
502
+ min-width: 96px;
503
+ font-size: var(--font-size-base);
504
+ color: hsl(var(--muted-foreground));
505
+ font-weight: var(--font-weight-normal);
506
+ flex-shrink: 0;
507
+ }
508
+ .description-value {
509
+ font-size: var(--font-size-base);
510
+ color: hsl(var(--gray-primary));
511
+ font-weight: var(--font-weight-normal);
512
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
513
+ display: flex; align-items: center; gap: 4px;
514
+ flex: 1; min-width: 0;
515
+ }
516
+ .description-value .copy-btn {
517
+ width: 16px; height: 16px; padding: 0;
518
+ background: transparent; border: none; cursor: pointer;
519
+ color: hsl(var(--muted-foreground));
520
+ display: inline-flex; align-items: center; justify-content: center;
521
+ opacity: 0;
522
+ transition: opacity var(--duration-fast), color var(--duration-fast);
523
+ flex-shrink: 0;
524
+ }
525
+ .description-item:hover .copy-btn { opacity: 1; }
526
+ .copy-btn:hover { color: hsl(var(--primary)); }
527
+
528
+ /* ===== StatusBadge ===== */
529
+ .status-badge {
530
+ display: inline-flex; align-items: center; gap: 6px;
531
+ font-size: var(--font-size-base);
532
+ }
533
+ .status-dot {
534
+ width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
535
+ }
536
+ .status-running .status-dot { background: hsl(var(--success)); }
537
+ .status-creating .status-dot { background: hsl(var(--primary)); animation: pulse 1.5s infinite; }
538
+ .status-stopped .status-dot { background: hsl(var(--gray-disabled)); }
539
+ .status-error .status-dot { background: hsl(var(--destructive)); }
540
+ .status-running { color: hsl(var(--success)); }
541
+ .status-creating { color: hsl(var(--primary)); }
542
+ .status-stopped { color: hsl(var(--gray-disabled)); }
543
+ .status-error { color: hsl(var(--destructive)); }
544
+ @keyframes pulse {
545
+ 0%, 100% { opacity: 1; }
546
+ 50% { opacity: 0.5; }
547
+ }
548
+
549
+ /* ===== Endpoint Table ===== */
550
+ .endpoint-section-title {
551
+ font-size: var(--font-size-lg); font-weight: 600;
552
+ color: hsl(var(--gray-primary)); margin-bottom: 12px;
553
+ }
554
+ .data-table-wrapper {
555
+ width: 100%; overflow-x: auto;
556
+ }
557
+ .data-table {
558
+ width: 100%; border-collapse: collapse;
559
+ background: hsl(var(--card));
560
+ }
561
+ .data-table thead th {
562
+ padding: 12px 12px; text-align: left;
563
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
564
+ color: hsl(var(--muted-foreground));
565
+ background: hsl(var(--gray-muted));
566
+ border-bottom: 1px solid hsl(var(--gray-line));
567
+ white-space: nowrap;
568
+ }
569
+ .data-table tbody tr {
570
+ border-bottom: 1px solid hsl(var(--gray-line));
571
+ transition: background var(--duration-fast);
572
+ }
573
+ .data-table tbody tr:last-child { border-bottom: none; }
574
+ .data-table tbody tr:hover { background: hsl(var(--gray-muted) / 0.5); }
575
+ .data-table tbody td {
576
+ padding: 12px 12px;
577
+ font-size: var(--font-size-base);
578
+ color: hsl(var(--gray-primary));
579
+ vertical-align: middle;
580
+ white-space: nowrap;
581
+ }
582
+ .data-table thead th:first-child,
583
+ .data-table tbody td:first-child { padding-left: 20px; }
584
+ .data-table thead th:last-child,
585
+ .data-table tbody td:last-child { padding-right: 20px; }
586
+ .endpoint-tag {
587
+ display: inline-flex; align-items: center;
588
+ padding: 2px 8px;
589
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
590
+ color: hsl(var(--primary));
591
+ background: hsl(var(--info-bg));
592
+ border: 1px solid hsl(var(--info-border));
593
+ border-radius: var(--radius-sm);
594
+ }
595
+ .network-tag {
596
+ display: inline-flex; align-items: center;
597
+ padding: 2px 8px;
598
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
599
+ border-radius: var(--radius-sm);
600
+ }
601
+ .network-tag.public {
602
+ color: hsl(var(--warning));
603
+ background: hsl(var(--warning-bg));
604
+ border: 1px solid hsl(var(--warning-border));
605
+ }
606
+ .mono {
607
+ font-family: var(--font-mono);
608
+ }
609
+ .ports-list {
610
+ display: flex; flex-direction: column; gap: 2px;
611
+ font-family: var(--font-mono);
612
+ font-size: var(--font-size-base);
613
+ color: hsl(var(--gray-secondary-foreground));
614
+ }
615
+
616
+ /* ===== Sonner ===== */
617
+ .toast {
618
+ position: fixed; top: 24px; left: 50%;
619
+ transform: translateX(-50%) translateY(-20px);
620
+ padding: 10px 20px;
621
+ background: hsl(var(--gray-primary));
622
+ color: hsl(var(--gray-white));
623
+ border-radius: var(--radius-md);
624
+ font-size: var(--font-size-base);
625
+ font-weight: var(--font-weight-medium);
626
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
627
+ z-index: 1000;
628
+ opacity: 0;
629
+ pointer-events: none;
630
+ transition: opacity var(--duration-normal), transform var(--duration-normal);
631
+ }
632
+ .toast.show {
633
+ opacity: 1;
634
+ transform: translateX(-50%) translateY(0);
635
+ }
636
+
637
+ /* ===== Responsive ===== */
638
+ @media (max-width: 1399px) {
639
+ .description-list { grid-template-columns: repeat(3, 1fr); }
640
+ }
641
+ @media (max-width: 1199px) {
642
+ .description-list { grid-template-columns: repeat(2, 1fr); }
643
+ }
644
+ </style>
645
+ </head>
646
+ <body>
647
+
648
+ <!-- ===== Sidebar:实例上下文 14 项菜单 ===== -->
649
+ <aside class="sidebar">
650
+ <div class="sidebar-header">
651
+ <div class="sidebar-logo" id="sidebarLogoArea">
652
+ <img src="./_assets/op-ai-gateway-logo.svg" alt="OP AI Gateway" />
653
+ <img class="collapsed-logo" src="./_assets/op-logo-collapsed.png" alt="OP" />
654
+ <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>
655
+ </div>
656
+ <button class="sidebar-collapse-btn" title="收起侧边栏">
657
+ <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>
658
+ </button>
659
+ </div>
660
+
661
+ <div class="sidebar-content">
662
+ <ul class="sidebar-menu">
663
+ <!-- 1. 概览(当前活跃) -->
664
+ <li><a class="sidebar-menu-item active" href="#">
665
+ <span class="item-icon">
666
+ <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>
667
+ </span>
668
+ 概览
669
+ </a></li>
670
+
671
+ <!-- 2. 模型API -->
672
+ <li><a class="sidebar-menu-item" href="#">
673
+ <span class="item-icon">
674
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5M2 12l10 5 10-5"/></svg>
675
+ </span>
676
+ 模型API
677
+ </a></li>
678
+
679
+ <!-- 3. MCP管理 -->
680
+ <li><a class="sidebar-menu-item" href="#">
681
+ <span class="item-icon">
682
+ <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="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h0a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
683
+ </span>
684
+ MCP管理
685
+ </a></li>
686
+
687
+ <!-- 4. AI服务 -->
688
+ <li><a class="sidebar-menu-item" href="#">
689
+ <span class="item-icon">
690
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><path d="M3.27 6.96L12 12.01l8.73-5.05M12 22.08V12"/></svg>
691
+ </span>
692
+ AI服务
693
+ </a></li>
694
+
695
+ <!-- 5. 服务 -->
696
+ <li><a class="sidebar-menu-item" href="#">
697
+ <span class="item-icon">
698
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
699
+ </span>
700
+ 服务
701
+ </a></li>
702
+
703
+ <!-- 6. 路由 -->
704
+ <li><a class="sidebar-menu-item" href="#">
705
+ <span class="item-icon">
706
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="6" cy="6" r="3"/><circle cx="18" cy="18" r="3"/><path d="M9 6h7a3 3 0 0 1 3 3v1M15 18H8a3 3 0 0 1-3-3v-1"/></svg>
707
+ </span>
708
+ 路由
709
+ </a></li>
710
+
711
+ <!-- 7. 消费者 -->
712
+ <li><a class="sidebar-menu-item" href="#">
713
+ <span class="item-icon">
714
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></svg>
715
+ </span>
716
+ 消费者
717
+ </a></li>
718
+
719
+ <!-- 8. 域名 -->
720
+ <li><a class="sidebar-menu-item" href="#">
721
+ <span class="item-icon">
722
+ <svg width="16" height="16" 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>
723
+ </span>
724
+ 域名
725
+ </a></li>
726
+
727
+ <!-- 9. 证书 -->
728
+ <li><a class="sidebar-menu-item" href="#">
729
+ <span class="item-icon">
730
+ <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 0 1 10 0v4"/></svg>
731
+ </span>
732
+ 证书
733
+ </a></li>
734
+
735
+ <!-- 10. 插件 -->
736
+ <li><a class="sidebar-menu-item" href="#">
737
+ <span class="item-icon">
738
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
739
+ </span>
740
+ 插件
741
+ </a></li>
742
+
743
+ <!-- 11. 观测分析(父菜单,默认展开) -->
744
+ <li>
745
+ <a class="sidebar-menu-item expanded" href="#" data-toggle="observability">
746
+ <span class="item-icon">
747
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>
748
+ </span>
749
+ 观测分析
750
+ <span class="expand-icon">
751
+ <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>
752
+ </span>
753
+ </a>
754
+ <ul class="sidebar-sub-menu show" id="observability">
755
+ <li><a class="sidebar-menu-item" href="#">模型监控</a></li>
756
+ <li><a class="sidebar-menu-item" href="#">MCP监控</a></li>
757
+ </ul>
758
+ <div class="sidebar-flyout">
759
+ <a class="sidebar-menu-item" href="#">模型监控</a>
760
+ <a class="sidebar-menu-item" href="#">MCP监控</a>
761
+ </div>
762
+ </li>
763
+
764
+ <!-- 12. 代理服务器 -->
765
+ <li><a class="sidebar-menu-item" href="#">
766
+ <span class="item-icon">
767
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
768
+ </span>
769
+ 代理服务器
770
+ </a></li>
771
+ </ul>
772
+ </div>
773
+
774
+ <div class="sidebar-divider"></div>
775
+ <div class="sidebar-footer">
776
+ <div class="sidebar-avatar">A</div>
777
+ <span class="sidebar-username">admin</span>
778
+ <button class="sidebar-more">
779
+ <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>
780
+ </button>
781
+ </div>
782
+ </aside>
783
+
784
+ <!-- ===== Main Content ===== -->
785
+ <main class="main-content">
786
+ <div class="page-container">
787
+ <div class="card">
788
+
789
+ <!-- PageHeader — 仅面包屑模式 -->
790
+ <div class="page-header">
791
+ <div class="page-header-left">
792
+ <nav class="breadcrumb">
793
+ <a href="#" id="backToList">i-bp1a4mka2u4rl7b12</a>
794
+ <span class="separator"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg></span>
795
+ <span class="current">概览</span>
796
+ <span class="gateway-type-tag">网关类型: AI网关</span>
797
+ </nav>
798
+ </div>
799
+ </div>
800
+
801
+ <!-- Tabs -->
802
+ <div class="tabs">
803
+ <ul class="tabs-list">
804
+ <li><button class="tab-item active" data-tab="basic">基本信息</button></li>
805
+ <li><button class="tab-item" data-tab="endpoint">接入点</button></li>
806
+ </ul>
807
+ </div>
808
+
809
+ <!-- Tab 1: 基本信息 -->
810
+ <div class="tab-content active" id="tab-basic">
811
+
812
+ <!-- 区块一:网关总览 -->
813
+ <div class="list-section">
814
+ <h3 class="list-section-title">网关总览</h3>
815
+ <div class="stat-grid">
816
+ <div class="stat-card stat-card-1" data-jump="mcp">
817
+ <svg class="stat-card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22v-5"/><path d="M9 8V2"/><path d="M15 8V2"/><path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/></svg>
818
+ <span class="stat-card-link">查看详情</span>
819
+ <div class="stat-card-label">MCP服务总数</div>
820
+ <div class="stat-card-value">3</div>
821
+ </div>
822
+ <div class="stat-card stat-card-2" data-jump="model-api">
823
+ <svg class="stat-card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="16" x="4" y="4" rx="2"/><rect width="6" height="6" x="9" y="9" rx="1"/><path d="M15 2v2"/><path d="M15 20v2"/><path d="M2 15h2"/><path d="M2 9h2"/><path d="M20 15h2"/><path d="M20 9h2"/><path d="M9 2v2"/><path d="M9 20v2"/></svg>
824
+ <span class="stat-card-link">查看详情</span>
825
+ <div class="stat-card-label">模型API总数</div>
826
+ <div class="stat-card-value">12</div>
827
+ </div>
828
+ <div class="stat-card stat-card-3" data-jump="ai-service">
829
+ <svg class="stat-card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg>
830
+ <span class="stat-card-link">查看详情</span>
831
+ <div class="stat-card-label">AI服务总数</div>
832
+ <div class="stat-card-value">5</div>
833
+ </div>
834
+ <div class="stat-card stat-card-4" data-jump="route">
835
+ <svg class="stat-card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><line x1="6" x2="6" y1="3" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>
836
+ <span class="stat-card-link">查看详情</span>
837
+ <div class="stat-card-label">路由总数</div>
838
+ <div class="stat-card-value">8</div>
839
+ </div>
840
+ <div class="stat-card stat-card-5" data-jump="consumer">
841
+ <svg class="stat-card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 1-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
842
+ <span class="stat-card-link">查看详情</span>
843
+ <div class="stat-card-label">消费者数</div>
844
+ <div class="stat-card-value">4</div>
845
+ </div>
846
+ <div class="stat-card stat-card-6" data-jump="service">
847
+ <svg class="stat-card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="8" x="2" y="2" rx="2" ry="2"/><rect width="20" height="8" x="2" y="14" rx="2" ry="2"/><line x1="6" x2="6.01" y1="6" y2="6"/><line x1="6" x2="6.01" y1="18" y2="18"/></svg>
848
+ <span class="stat-card-link">查看详情</span>
849
+ <div class="stat-card-label">服务总数</div>
850
+ <div class="stat-card-value">6</div>
851
+ </div>
852
+ <div class="stat-card stat-card-7" data-jump="plugin">
853
+ <svg class="stat-card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.705.707 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.23 8.77c.24-.24.581-.353.917-.303.515.077.877.528 1.073 1.01a2.5 2.5 0 1 0 3.259-3.259c-.482-.196-.933-.558-1.01-1.073-.05-.336.062-.676.303-.917l1.525-1.525A2.402 2.402 0 0 1 12 1.998c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.968a2.5 2.5 0 1 1 3.237 3.237c-.464.18-.894.527-.967 1.02Z"/></svg>
854
+ <span class="stat-card-link">查看详情</span>
855
+ <div class="stat-card-label">插件总数</div>
856
+ <div class="stat-card-value">15</div>
857
+ </div>
858
+ </div>
859
+ </div>
860
+
861
+ <!-- 区块二:基本信息 -->
862
+ <div class="list-section">
863
+ <h3 class="list-section-title">基本信息</h3>
864
+ <div class="description-list">
865
+ <div class="description-item">
866
+ <span class="description-label">实例ID</span>
867
+ <span class="description-value">
868
+ <span class="mono" id="instanceId">i-bp1a4mka2u4rl7b12</span>
869
+ <button class="copy-btn" data-copy="i-bp1a4mka2u4rl7b12" title="复制">
870
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
871
+ </button>
872
+ </span>
873
+ </div>
874
+ <div class="description-item">
875
+ <span class="description-label">实例名称</span>
876
+ <span class="description-value">production-gateway</span>
877
+ </div>
878
+ <div class="description-item">
879
+ <span class="description-label">状态</span>
880
+ <span class="description-value">
881
+ <span class="status-badge status-running">
882
+ <span class="status-dot"></span>
883
+ 运行中
884
+ </span>
885
+ </span>
886
+ </div>
887
+ <div class="description-item">
888
+ <span class="description-label">部署架构</span>
889
+ <span class="description-value">K8s</span>
890
+ </div>
891
+ <div class="description-item">
892
+ <span class="description-label">集群</span>
893
+ <span class="description-value">cluster-prod-01</span>
894
+ </div>
895
+ <div class="description-item">
896
+ <span class="description-label">命名空间</span>
897
+ <span class="description-value">higress-system</span>
898
+ </div>
899
+ <div class="description-item">
900
+ <span class="description-label">IngressClass</span>
901
+ <span class="description-value">higress</span>
902
+ </div>
903
+ <div class="description-item">
904
+ <span class="description-label">实例规格</span>
905
+ <span class="description-value">Standard</span>
906
+ </div>
907
+ <div class="description-item">
908
+ <span class="description-label">节点数</span>
909
+ <span class="description-value">3</span>
910
+ </div>
911
+ <div class="description-item">
912
+ <span class="description-label">创建时间</span>
913
+ <span class="description-value">2026年03月15日 14:30:22</span>
914
+ </div>
915
+ <div class="description-item">
916
+ <span class="description-label">修改时间</span>
917
+ <span class="description-value">2026年05月20日 09:15:38</span>
918
+ </div>
919
+ <div class="description-item">
920
+ <span class="description-label">引擎类型</span>
921
+ <span class="description-value">AI网关</span>
922
+ </div>
923
+ <div class="description-item">
924
+ <span class="description-label">引擎版本</span>
925
+ <span class="description-value mono">2.1.11</span>
926
+ </div>
927
+ <div class="description-item">
928
+ <span class="description-label">容器服务集群ID</span>
929
+ <span class="description-value mono" title="cf5b2b5e2a8c14d...">cf5b2b5e2a8c14d...</span>
930
+ </div>
931
+ <div class="description-item">
932
+ <span class="description-label">SLS日志服务</span>
933
+ <span class="description-value">已开启</span>
934
+ </div>
935
+ <div class="description-item">
936
+ <span class="description-label">Prometheus监控</span>
937
+ <span class="description-value">已开启</span>
938
+ </div>
939
+ </div>
940
+ </div>
941
+
942
+ </div>
943
+
944
+ <!-- Tab 2: 接入点 -->
945
+ <div class="tab-content" id="tab-endpoint">
946
+ <div class="list-section">
947
+ <h3 class="endpoint-section-title">接入点 (1)</h3>
948
+ <div class="data-table-wrapper">
949
+ <table class="data-table">
950
+ <thead>
951
+ <tr>
952
+ <th>类型</th>
953
+ <th>网络类型</th>
954
+ <th>ServiceName</th>
955
+ <th>External IPs</th>
956
+ <th>IP版本</th>
957
+ <th>Ports</th>
958
+ <th>ClusterIP</th>
959
+ </tr>
960
+ </thead>
961
+ <tbody>
962
+ <tr>
963
+ <td><span class="endpoint-tag">LoadBalancer</span></td>
964
+ <td><span class="network-tag public">公网</span></td>
965
+ <td class="mono">higress-gateway</td>
966
+ <td class="mono">47.108.232.137</td>
967
+ <td class="mono">ipv4</td>
968
+ <td>
969
+ <div class="ports-list">
970
+ <span>80:32423/TCP</span>
971
+ <span>443:30816/TCP</span>
972
+ <span>15001:31060/TCP</span>
973
+ </div>
974
+ </td>
975
+ <td class="mono">172.16.107.115</td>
976
+ </tr>
977
+ </tbody>
978
+ </table>
979
+ </div>
980
+ </div>
981
+ </div>
982
+
983
+ </div>
984
+ </div>
985
+ </main>
986
+
987
+ <!-- Sonner -->
988
+ <div class="toast" id="toast">已复制</div>
989
+
990
+ <script>
991
+ // Sidebar collapse
992
+ const sidebar = document.querySelector('.sidebar');
993
+ document.querySelector('.sidebar-collapse-btn').addEventListener('click', function() {
994
+ sidebar.classList.toggle('collapsed');
995
+ });
996
+ document.getElementById('sidebarLogoArea').addEventListener('click', function() {
997
+ if (sidebar.classList.contains('collapsed')) {
998
+ sidebar.classList.remove('collapsed');
999
+ }
1000
+ });
1001
+
1002
+ // Sidebar parent menu expand toggle
1003
+ document.querySelectorAll('.sidebar-menu-item[data-toggle]').forEach(item => {
1004
+ item.addEventListener('click', function(e) {
1005
+ e.preventDefault();
1006
+ this.classList.toggle('expanded');
1007
+ const targetId = this.getAttribute('data-toggle');
1008
+ const target = document.getElementById(targetId);
1009
+ if (target) target.classList.toggle('show');
1010
+ });
1011
+ });
1012
+
1013
+ // Tabs switching
1014
+ document.querySelectorAll('.tab-item').forEach(tab => {
1015
+ tab.addEventListener('click', function() {
1016
+ const target = this.getAttribute('data-tab');
1017
+ document.querySelectorAll('.tab-item').forEach(t => t.classList.remove('active'));
1018
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
1019
+ this.classList.add('active');
1020
+ const content = document.getElementById('tab-' + target);
1021
+ if (content) content.classList.add('active');
1022
+ });
1023
+ });
1024
+
1025
+ // Sonner
1026
+ const toast = document.getElementById('toast');
1027
+ let toastTimer = null;
1028
+ function showToast(msg) {
1029
+ toast.textContent = msg;
1030
+ toast.classList.add('show');
1031
+ if (toastTimer) clearTimeout(toastTimer);
1032
+ toastTimer = setTimeout(() => toast.classList.remove('show'), 1800);
1033
+ }
1034
+
1035
+ // Copy buttons
1036
+ document.querySelectorAll('.copy-btn').forEach(btn => {
1037
+ btn.addEventListener('click', function(e) {
1038
+ e.stopPropagation();
1039
+ const text = this.getAttribute('data-copy') || '';
1040
+ if (navigator.clipboard && navigator.clipboard.writeText) {
1041
+ navigator.clipboard.writeText(text).then(() => showToast('已复制'));
1042
+ } else {
1043
+ // Fallback
1044
+ const ta = document.createElement('textarea');
1045
+ ta.value = text; document.body.appendChild(ta);
1046
+ ta.select();
1047
+ try { document.execCommand('copy'); showToast('已复制'); } catch (err) {}
1048
+ document.body.removeChild(ta);
1049
+ }
1050
+ });
1051
+ });
1052
+
1053
+ // Stat card click jump (placeholder)
1054
+ document.querySelectorAll('.stat-card-value').forEach(v => {
1055
+ v.addEventListener('click', function() {
1056
+ const target = this.getAttribute('data-jump');
1057
+ console.log('跳转到', target);
1058
+ });
1059
+ });
1060
+
1061
+ // Breadcrumb back to instance list
1062
+ document.getElementById('backToList').addEventListener('click', function(e) {
1063
+ e.preventDefault();
1064
+ console.log('返回实例列表页');
1065
+ });
1066
+ </script>
1067
+
1068
+ </body>
1069
+ </html>