@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,941 @@
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 (resource-detail)
9
+ ─────────────────────────────────────────────────────────────
10
+ 布局:TWO_COL(实例级 Sidebar + ContentCard 单例容器)
11
+ Sidebar:14 项实例上下文菜单(12 L1 + 1 父菜单含 2 L2 子项)
12
+ 内容区模式:PageHeader(面包屑)+ InfoCard(嵌入模式B) + Tabs(基本信息 / 接入点 / Token配额)
13
+ ─────────────────────────────────────────────────────────────
14
+ 组件清单:
15
+ • PageHeader — 面包屑模式
16
+ • InfoCard — 嵌入模式B(padding + border-bottom)
17
+ • Tabs — 页内分段
18
+ • DescriptionList — 4 列布局
19
+ • StatusBadge — 状态徽章
20
+ • CopyableText — 可复制字段
21
+ • DataTable — 接入点表格
22
+ ─────────────────────────────────────────────────────────────
23
+ 规范:page-rule-system v7.8.4 / Tokens v4.1 (TrekClaw)
24
+ 验证:无硬编码色值 / 无brand-scale / ContentCard border:none + shadow-sm
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
+ --primary-glow: 226.9 100% 68.6%;
36
+
37
+ /* ===== Gray Scale (v7.4) ===== */
38
+ --gray-primary: 220 9% 7%;
39
+ --gray-primary-foreground: 210 33% 99%;
40
+ --gray-secondary-foreground: 216 4% 26%;
41
+ --muted-foreground: 216 2% 45%;
42
+ --gray-disabled: 210 3% 63%;
43
+ --gray-line: 210 9% 91%;
44
+ --gray-sidebar-accent: 210 12% 93%;
45
+ --gray-muted: 220 18% 97%;
46
+ --gray-white: 0 0% 100%;
47
+
48
+ /* Legacy aliases */
49
+ --gray-title: 220 9% 7%;
50
+ --gray-secondary: 216 4% 26%;
51
+
52
+ /* ===== Semantic ===== */
53
+ --success: 142 76% 36%;
54
+ --success-bg: 152 82% 96%;
55
+ --destructive: 0 72% 51%;
56
+ --destructive-bg: 0 86% 97%;
57
+ --warning: 40 88% 48%;
58
+ --warning-bg: 43 100% 94%;
59
+ --warning-border: 40 92% 68%;
60
+ --info: 221 83% 53%;
61
+ --info-bg: 214 100% 97%;
62
+ --info-border: 213 94% 82.5%;
63
+
64
+ /* ===== Surface ===== */
65
+ --background: 220 18% 97%;
66
+ --card: 0 0% 100%;
67
+ --card-foreground: 220 9% 7%;
68
+ --border: 210 9% 91%;
69
+ --ring: 218.6 100% 46.7%;
70
+
71
+ /* ===== Sidebar ===== */
72
+ --sidebar: 220 18% 97%;
73
+ --sidebar-foreground: 220 9% 7%;
74
+ --sidebar-active: 210 12% 93%;
75
+ --sidebar-active-foreground: 220 9% 7%;
76
+ --sidebar-hover: 220 18% 97%;
77
+ --sidebar-group: 216 2% 45%;
78
+ --sidebar-item: 220 9% 7%;
79
+ --sidebar-item-muted: 216 4% 26%;
80
+ --sidebar-border: 210 9% 91%;
81
+
82
+ /* ===== Geometry ===== */
83
+ --radius-sm: 4px;
84
+ --radius-md: 8px;
85
+ --radius-lg: 12px;
86
+
87
+ /* ===== Spacing (v7.5) ===== */
88
+ --gap-xs: 4px;
89
+ --btn-padding-x: 16px;
90
+ --btn-padding-x-sm: 12px;
91
+ --button-gap: 8px;
92
+ --tabs-gap: 24px;
93
+ --card-gap: 16px;
94
+ --page-container-padding: 16px;
95
+ --page-container-padding-left: 0px;
96
+ --card-padding-x: 20px;
97
+
98
+ /* ===== Shadow (v7.6) ===== */
99
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
100
+
101
+ /* ===== Typography ===== */
102
+ --font-size-base: 12px;
103
+ --font-size-lg: 14px;
104
+ --font-size-xl: 16px;
105
+ --font-size-2xl: 18px;
106
+ --font-size-page-header: 18px;
107
+ --font-sans: 'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
108
+ --font-mono: 'SF Mono', Monaco, 'Courier New', monospace;
109
+ --font-weight-normal: 400;
110
+ --font-weight-medium: 500;
111
+ --font-weight-black: 900;
112
+
113
+ /* ===== Input ===== */
114
+ --input-height: 32px;
115
+
116
+ /* ===== Layout ===== */
117
+ --layout-sidebar-width: 240px;
118
+
119
+ /* ===== Motion ===== */
120
+ --duration-fast: 150ms;
121
+ --duration-normal: 200ms;
122
+ }
123
+
124
+ body {
125
+ font-family: var(--font-sans);
126
+ font-size: var(--font-size-base);
127
+ color: hsl(var(--gray-primary));
128
+ background: hsl(var(--background));
129
+ min-height: 100vh;
130
+ min-width: 1280px;
131
+ }
132
+
133
+ /* ===== Sidebar ===== */
134
+ .sidebar {
135
+ position: fixed; top: 0; left: 0; bottom: 0;
136
+ width: var(--layout-sidebar-width);
137
+ background: hsl(var(--sidebar));
138
+ z-index: 100;
139
+ display: flex; flex-direction: column;
140
+ overflow: hidden;
141
+ transition: width 0.2s ease;
142
+ }
143
+ .sidebar-header {
144
+ height: 56px; padding: 0 16px;
145
+ display: flex; align-items: center; gap: var(--gap-xs);
146
+ flex-shrink: 0;
147
+ }
148
+ .sidebar-logo {
149
+ height: 28px; flex-shrink: 0;
150
+ display: flex; align-items: center;
151
+ overflow: hidden;
152
+ }
153
+ .sidebar-logo img { height: 28px; width: auto; display: block; }
154
+ .sidebar-logo .collapsed-logo { display: none; width: 30px; height: 30px; }
155
+ .sidebar-logo .expand-logo { display: none; width: 18px; height: 18px; color: hsl(var(--muted-foreground)); }
156
+ .sidebar-collapse-btn {
157
+ margin-left: auto; width: 18px; height: 18px;
158
+ background: none; border: none; padding: 0; cursor: pointer;
159
+ display: flex; align-items: center; justify-content: center;
160
+ color: hsl(var(--muted-foreground)); flex-shrink: 0;
161
+ }
162
+ .sidebar-collapse-btn svg { width: 18px; height: 18px; }
163
+
164
+ /* Sidebar Collapsed */
165
+ .sidebar.collapsed { width: 68px; overflow: visible; }
166
+ .sidebar.collapsed .sidebar-header { padding: 0 12px; justify-content: center; }
167
+ .sidebar.collapsed .sidebar-logo { cursor: pointer; }
168
+ .sidebar.collapsed .sidebar-logo img { display: none; }
169
+ .sidebar.collapsed .sidebar-logo .collapsed-logo { display: block; }
170
+ .sidebar.collapsed .sidebar-logo:hover .collapsed-logo { display: none; }
171
+ .sidebar.collapsed .sidebar-logo:hover .expand-logo { display: block; }
172
+ .sidebar.collapsed .sidebar-collapse-btn { display: none; }
173
+ .sidebar.collapsed .sidebar-content { padding: 12px 0; overflow-y: auto; overflow-x: hidden; }
174
+ .sidebar.collapsed .sidebar-menu { padding: 0; }
175
+ .sidebar.collapsed .sidebar-menu > li { display: flex; justify-content: center; }
176
+ .sidebar.collapsed .sidebar-menu > li > a.sidebar-menu-item {
177
+ justify-content: center; padding: 0; width: 40px; height: 40px;
178
+ border-radius: var(--radius-md); position: relative; flex-shrink: 0; gap: 0;
179
+ }
180
+ .sidebar.collapsed .sidebar-menu > li > a.sidebar-menu-item .item-icon { margin: 0; }
181
+ .sidebar.collapsed .sidebar-menu > li > a > span:not(.item-icon),
182
+ .sidebar.collapsed .sidebar-menu > li > a > .expand-icon { display: none; }
183
+ .sidebar.collapsed .sidebar-menu > li > a { font-size: 0; }
184
+ .sidebar.collapsed .sidebar-menu > li > a > .item-icon { font-size: var(--font-size-lg); }
185
+ .sidebar.collapsed .sidebar-sub-menu { display: none !important; }
186
+ .sidebar.collapsed .sidebar-divider { margin: 0 14px; }
187
+ .sidebar.collapsed .sidebar-footer { padding: 12px 10px 16px; justify-content: center; }
188
+ .sidebar.collapsed .sidebar-username,
189
+ .sidebar.collapsed .sidebar-more { display: none; }
190
+
191
+ /* Sidebar Flyout */
192
+ .sidebar.collapsed .sidebar-menu > li { position: relative; }
193
+ .sidebar.collapsed .sidebar-menu > li:hover > .sidebar-flyout { display: block; }
194
+ .sidebar-flyout {
195
+ display: none;
196
+ position: absolute; left: 100%; top: 0;
197
+ min-width: 160px; padding: 4px;
198
+ background: hsl(var(--card));
199
+ border: 1px solid hsl(var(--gray-line));
200
+ border-radius: var(--radius-md);
201
+ box-shadow: 0 4px 12px rgba(0,0,0,0.08);
202
+ z-index: 200;
203
+ }
204
+ .sidebar-flyout .sidebar-menu-item {
205
+ height: 36px; padding: 0 12px;
206
+ font-size: var(--font-size-base) !important;
207
+ font-weight: var(--font-weight-normal);
208
+ color: hsl(var(--gray-primary));
209
+ border-radius: var(--radius-sm);
210
+ white-space: nowrap;
211
+ }
212
+ .sidebar-flyout .sidebar-menu-item:hover { background: hsl(var(--gray-muted)); }
213
+
214
+ /* ===== Main Layout ===== */
215
+ .main-content {
216
+ margin-left: var(--layout-sidebar-width);
217
+ min-height: 100vh;
218
+ transition: margin-left 0.2s ease;
219
+ }
220
+ .sidebar.collapsed ~ .main-content { margin-left: 68px; }
221
+ .sidebar-content { flex: 1; overflow-y: auto; padding: 12px 0; }
222
+ .sidebar-menu { list-style: none; padding: 0 8px; display: flex; flex-direction: column; gap: 2px; }
223
+ .sidebar-menu-item {
224
+ display: flex; align-items: center; gap: var(--button-gap);
225
+ padding: 0 12px; height: 40px;
226
+ border-radius: var(--radius-md);
227
+ font-size: var(--font-size-lg); font-weight: var(--font-weight-medium);
228
+ color: hsl(var(--sidebar-item-muted));
229
+ text-decoration: none; cursor: pointer;
230
+ transition: background var(--duration-fast), color var(--duration-fast);
231
+ white-space: nowrap;
232
+ }
233
+ .sidebar-menu-item:hover {
234
+ background: hsl(var(--sidebar-hover));
235
+ color: hsl(var(--sidebar-item));
236
+ }
237
+ .sidebar-menu-item.active {
238
+ background: hsl(var(--sidebar-active));
239
+ color: hsl(var(--sidebar-active-foreground));
240
+ }
241
+ .sidebar-menu-item .item-icon {
242
+ width: 16px; height: 16px; flex-shrink: 0;
243
+ display: flex; align-items: center; justify-content: center;
244
+ }
245
+ .sidebar-menu-item .expand-icon {
246
+ margin-left: auto; width: 16px; height: 16px;
247
+ transition: transform var(--duration-fast);
248
+ }
249
+ .sidebar-menu-item.expanded .expand-icon { transform: rotate(90deg); }
250
+ .sidebar-sub-menu { list-style: none; padding: 0; display: none; }
251
+ .sidebar-sub-menu.show { display: block; }
252
+ .sidebar-sub-menu .sidebar-menu-item {
253
+ height: 36px; font-size: var(--font-size-base); font-weight: var(--font-weight-normal);
254
+ padding-left: 36px;
255
+ }
256
+ .sidebar-divider {
257
+ height: 1px; background: hsl(var(--sidebar-border));
258
+ margin: 0 12px; flex-shrink: 0;
259
+ }
260
+ .sidebar-footer {
261
+ flex-shrink: 0; display: flex; align-items: center;
262
+ gap: var(--button-gap); padding: 12px 12px 16px 24px;
263
+ }
264
+ .sidebar-avatar {
265
+ width: 28px; height: 28px; border-radius: 50%;
266
+ background: hsl(var(--sidebar-active));
267
+ display: flex; align-items: center; justify-content: center;
268
+ font-size: var(--font-size-base); font-weight: 600;
269
+ color: hsl(var(--gray-primary)); flex-shrink: 0;
270
+ }
271
+ .sidebar-username {
272
+ flex: 1; font-size: var(--font-size-lg); font-weight: var(--font-weight-medium);
273
+ color: hsl(var(--sidebar-item)); overflow: hidden;
274
+ text-overflow: ellipsis; white-space: nowrap;
275
+ }
276
+ .sidebar-more {
277
+ width: 28px; height: 28px; border-radius: var(--radius-sm);
278
+ border: none; background: transparent; cursor: pointer;
279
+ display: flex; align-items: center; justify-content: center;
280
+ color: hsl(var(--muted-foreground));
281
+ }
282
+ .sidebar-more:hover { background: hsl(var(--sidebar-hover)); color: hsl(var(--gray-primary)); }
283
+
284
+ /* ===== Page Container ===== */
285
+ .page-container {
286
+ padding: var(--page-container-padding) var(--page-container-padding) var(--page-container-padding) var(--page-container-padding-left);
287
+ }
288
+ .card {
289
+ background: hsl(var(--card));
290
+ border-radius: var(--radius-lg);
291
+ border: none;
292
+ box-shadow: var(--shadow-sm);
293
+ overflow: hidden;
294
+ display: flex; flex-direction: column;
295
+ min-height: calc(100vh - 32px);
296
+ padding: 0 var(--card-padding-x);
297
+ }
298
+
299
+ /* ===== PageHeader — Breadcrumb Mode ===== */
300
+ .page-header {
301
+ height: 64px; padding: 0;
302
+ display: flex; align-items: center; justify-content: space-between;
303
+ background: transparent; border: none; box-shadow: none;
304
+ flex-shrink: 0;
305
+ }
306
+ .page-header-left { display: flex; align-items: center; }
307
+ .breadcrumb {
308
+ display: flex; align-items: center; gap: 4px;
309
+ font-size: var(--font-size-page-header); font-weight: var(--font-weight-medium);
310
+ color: hsl(var(--gray-secondary-foreground));
311
+ }
312
+ .breadcrumb a { color: hsl(var(--gray-secondary-foreground)); text-decoration: none; cursor: pointer; }
313
+ .breadcrumb a:hover { color: hsl(var(--gray-primary)); }
314
+ .breadcrumb .separator { color: hsl(var(--muted-foreground)); display: flex; align-items: center; }
315
+ .breadcrumb .separator svg { width: 20px; height: 20px; }
316
+ .breadcrumb .current { color: hsl(var(--gray-primary)); }
317
+ .page-header-actions { display: flex; align-items: center; gap: var(--button-gap); }
318
+
319
+ /* ===== Buttons ===== */
320
+ .btn {
321
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--gap-xs);
322
+ height: var(--input-height); padding: 0 var(--btn-padding-x);
323
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
324
+ border-radius: var(--radius-md); cursor: pointer;
325
+ transition: background var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast);
326
+ border: 1px solid hsl(var(--gray-line));
327
+ background: hsl(var(--card)); color: hsl(var(--gray-primary));
328
+ white-space: nowrap;
329
+ }
330
+ .btn:hover { background: hsl(var(--gray-muted)); border-color: hsl(var(--gray-line)); }
331
+ .btn-primary {
332
+ background: hsl(var(--primary)); color: hsl(var(--primary-foreground));
333
+ border-color: hsl(var(--primary));
334
+ }
335
+ .btn-primary:hover { background: hsl(var(--primary-hover)); border-color: hsl(var(--primary-hover)); }
336
+ .btn-ghost { border: none; background: transparent; }
337
+ .btn-ghost:hover { background: hsl(var(--gray-muted)); }
338
+ .btn-icon {
339
+ width: var(--input-height); padding: 0;
340
+ display: inline-flex; align-items: center; justify-content: center;
341
+ }
342
+ .btn svg { width: 14px; height: 14px; }
343
+
344
+ /* ===== InfoCard — 嵌入模式B ===== */
345
+ .info-card {
346
+ padding: 16px 0;
347
+ border-bottom: 1px solid hsl(var(--gray-line));
348
+ }
349
+ .info-card-grid {
350
+ display: flex; align-items: center; gap: 32px;
351
+ flex-wrap: wrap;
352
+ }
353
+ .info-card-item {
354
+ display: flex; align-items: center; gap: 8px;
355
+ }
356
+ .info-card-label {
357
+ font-size: var(--font-size-base);
358
+ color: hsl(var(--muted-foreground));
359
+ }
360
+ .info-card-value {
361
+ font-size: var(--font-size-base);
362
+ color: hsl(var(--gray-primary));
363
+ font-weight: var(--font-weight-normal);
364
+ }
365
+
366
+ /* ===== Tabs ===== */
367
+ .tabs { border-bottom: 1px solid hsl(var(--gray-line)); }
368
+ .tabs-list { display: flex; gap: var(--tabs-gap); list-style: none; }
369
+ .tab-item {
370
+ padding: 10px 0; font-size: var(--font-size-lg);
371
+ color: hsl(var(--gray-secondary-foreground)); cursor: pointer;
372
+ border-bottom: 2px solid transparent;
373
+ transition: color var(--duration-fast), border-color var(--duration-fast);
374
+ font-weight: var(--font-weight-normal);
375
+ background: transparent; border-left: none; border-right: none; border-top: none;
376
+ }
377
+ .tab-item:hover { color: hsl(var(--gray-primary)); }
378
+ .tab-item.active {
379
+ color: hsl(var(--primary));
380
+ border-bottom-color: hsl(var(--primary));
381
+ font-weight: var(--font-weight-medium);
382
+ }
383
+ .tab-content { display: none; padding: 20px 0; }
384
+ .tab-content.active { display: block; }
385
+
386
+ /* ===== Section ===== */
387
+ .list-section { padding-top: 24px; }
388
+ .list-section:first-child { padding-top: 0; }
389
+ .list-section-title {
390
+ font-size: var(--font-size-lg); font-weight: 600;
391
+ color: hsl(var(--gray-primary)); margin-bottom: 12px;
392
+ }
393
+
394
+ /* ===== DescriptionList — 4 cols ===== */
395
+ .description-list {
396
+ display: grid;
397
+ grid-template-columns: repeat(4, 1fr);
398
+ gap: 0 24px;
399
+ }
400
+ .description-item {
401
+ display: flex; align-items: center;
402
+ height: 36px; padding: 8px 0;
403
+ gap: 12px; min-width: 0;
404
+ }
405
+ .description-label {
406
+ min-width: 96px;
407
+ font-size: var(--font-size-base);
408
+ color: hsl(var(--muted-foreground));
409
+ font-weight: var(--font-weight-normal);
410
+ flex-shrink: 0;
411
+ }
412
+ .description-value {
413
+ font-size: var(--font-size-base);
414
+ color: hsl(var(--gray-primary));
415
+ font-weight: var(--font-weight-normal);
416
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
417
+ display: flex; align-items: center; gap: 4px;
418
+ flex: 1; min-width: 0;
419
+ }
420
+ .description-value .copy-btn {
421
+ width: 16px; height: 16px; padding: 0;
422
+ background: transparent; border: none; cursor: pointer;
423
+ color: hsl(var(--muted-foreground));
424
+ display: inline-flex; align-items: center; justify-content: center;
425
+ opacity: 0;
426
+ transition: opacity var(--duration-fast), color var(--duration-fast);
427
+ flex-shrink: 0;
428
+ }
429
+ .description-item:hover .copy-btn { opacity: 1; }
430
+ .copy-btn:hover { color: hsl(var(--primary)); }
431
+
432
+ /* ===== StatusBadge ===== */
433
+ .status-badge { display: inline-flex; align-items: center; gap: 6px; font-size: var(--font-size-base); }
434
+ .status-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
435
+ .status-running .status-dot { background: hsl(var(--success)); }
436
+ .status-running { color: hsl(var(--success)); }
437
+ .status-stopped .status-dot { background: hsl(var(--gray-disabled)); }
438
+ .status-stopped { color: hsl(var(--gray-disabled)); }
439
+ @keyframes pulse { 0%,100%{opacity:1}50%{opacity:0.5} }
440
+
441
+ /* ===== DataTable ===== */
442
+ .data-table-wrapper { width: 100%; overflow-x: auto; }
443
+ .data-table { width: 100%; border-collapse: collapse; background: hsl(var(--card)); }
444
+ .data-table thead th {
445
+ padding: 12px 12px; text-align: left;
446
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
447
+ color: hsl(var(--muted-foreground));
448
+ background: hsl(var(--gray-muted));
449
+ border-bottom: 1px solid hsl(var(--gray-line));
450
+ white-space: nowrap;
451
+ }
452
+ .data-table tbody tr {
453
+ border-bottom: 1px solid hsl(var(--gray-line));
454
+ transition: background var(--duration-fast);
455
+ }
456
+ .data-table tbody tr:last-child { border-bottom: none; }
457
+ .data-table tbody tr:hover { background: hsl(var(--gray-muted) / 0.5); }
458
+ .data-table tbody td {
459
+ padding: 12px 12px;
460
+ font-size: var(--font-size-base);
461
+ color: hsl(var(--gray-primary));
462
+ vertical-align: middle;
463
+ white-space: nowrap;
464
+ }
465
+ .data-table thead th:first-child,
466
+ .data-table tbody td:first-child { padding-left: 20px; }
467
+ .data-table thead th:last-child,
468
+ .data-table tbody td:last-child { padding-right: 20px; }
469
+
470
+ /* ===== Tags ===== */
471
+ .endpoint-tag {
472
+ display: inline-flex; align-items: center;
473
+ padding: 2px 8px;
474
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
475
+ color: hsl(var(--primary));
476
+ background: hsl(var(--info-bg));
477
+ border: 1px solid hsl(var(--info-border));
478
+ border-radius: var(--radius-sm);
479
+ }
480
+ .network-tag {
481
+ display: inline-flex; align-items: center;
482
+ padding: 2px 8px;
483
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
484
+ border-radius: var(--radius-sm);
485
+ }
486
+ .network-tag.public {
487
+ color: hsl(var(--warning));
488
+ background: hsl(var(--warning-bg));
489
+ border: 1px solid hsl(var(--warning-border));
490
+ }
491
+
492
+ /* ===== Utility ===== */
493
+ .mono { font-family: var(--font-mono); }
494
+ .link { color: hsl(var(--primary)); cursor: pointer; text-decoration: none; }
495
+ .link:hover { text-decoration: underline; }
496
+ .ports-list {
497
+ display: flex; flex-direction: column; gap: 2px;
498
+ font-family: var(--font-mono);
499
+ font-size: var(--font-size-base);
500
+ color: hsl(var(--gray-secondary-foreground));
501
+ }
502
+
503
+ /* ===== Sonner ===== */
504
+ .toast {
505
+ position: fixed; top: 24px; left: 50%;
506
+ transform: translateX(-50%) translateY(-20px);
507
+ padding: 10px 20px;
508
+ background: hsl(var(--gray-primary));
509
+ color: hsl(var(--gray-white));
510
+ border-radius: var(--radius-md);
511
+ font-size: var(--font-size-base); font-weight: var(--font-weight-medium);
512
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
513
+ z-index: 1000; opacity: 0; pointer-events: none;
514
+ transition: opacity var(--duration-normal), transform var(--duration-normal);
515
+ }
516
+ .toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
517
+
518
+ /* ===== Responsive ===== */
519
+ @media (max-width: 1399px) { .description-list { grid-template-columns: repeat(3, 1fr); } }
520
+ @media (max-width: 1199px) { .description-list { grid-template-columns: repeat(2, 1fr); } }
521
+ </style>
522
+ </head>
523
+ <body>
524
+
525
+ <!-- ===== Sidebar:实例上下文菜单 ===== -->
526
+ <aside class="sidebar">
527
+ <div class="sidebar-header">
528
+ <div class="sidebar-logo" id="sidebarLogoArea">
529
+ <img src="./_assets/op-ai-gateway-logo.svg" alt="OP AI Gateway" />
530
+ <img class="collapsed-logo" src="./_assets/op-logo-collapsed.png" alt="OP" />
531
+ <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>
532
+ </div>
533
+ <button class="sidebar-collapse-btn" title="收起侧边栏">
534
+ <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>
535
+ </button>
536
+ </div>
537
+
538
+ <div class="sidebar-content">
539
+ <ul class="sidebar-menu">
540
+ <li><a class="sidebar-menu-item active" href="#">
541
+ <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>
542
+ 概览
543
+ </a></li>
544
+ <li><a class="sidebar-menu-item" href="#">
545
+ <span class="item-icon"><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></span>
546
+ 模型API
547
+ </a></li>
548
+ <li><a class="sidebar-menu-item" href="#">
549
+ <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="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></span>
550
+ MCP管理
551
+ </a></li>
552
+ <li><a class="sidebar-menu-item" href="#">
553
+ <span class="item-icon"><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></span>
554
+ AI服务
555
+ </a></li>
556
+ <li><a class="sidebar-menu-item" href="#">
557
+ <span class="item-icon"><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></span>
558
+ 服务
559
+ </a></li>
560
+ <li><a class="sidebar-menu-item" href="#">
561
+ <span class="item-icon"><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></span>
562
+ 路由
563
+ </a></li>
564
+ <li><a class="sidebar-menu-item" href="#">
565
+ <span class="item-icon"><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></span>
566
+ 消费者
567
+ </a></li>
568
+ <li><a class="sidebar-menu-item" href="#">
569
+ <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="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></span>
570
+ 域名
571
+ </a></li>
572
+ <li><a class="sidebar-menu-item" href="#">
573
+ <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 0 1 10 0v4"/></svg></span>
574
+ 证书
575
+ </a></li>
576
+ <li><a class="sidebar-menu-item" href="#">
577
+ <span class="item-icon"><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></span>
578
+ 插件
579
+ </a></li>
580
+ <li>
581
+ <a class="sidebar-menu-item expanded" href="#" data-toggle="observability">
582
+ <span class="item-icon"><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></span>
583
+ 观测分析
584
+ <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>
585
+ </a>
586
+ <ul class="sidebar-sub-menu show" id="observability">
587
+ <li><a class="sidebar-menu-item" href="#">模型监控</a></li>
588
+ <li><a class="sidebar-menu-item" href="#">MCP监控</a></li>
589
+ </ul>
590
+ <div class="sidebar-flyout">
591
+ <a class="sidebar-menu-item" href="#">模型监控</a>
592
+ <a class="sidebar-menu-item" href="#">MCP监控</a>
593
+ </div>
594
+ </li>
595
+ <li><a class="sidebar-menu-item" href="#">
596
+ <span class="item-icon"><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></span>
597
+ 代理服务器
598
+ </a></li>
599
+ </ul>
600
+ </div>
601
+
602
+ <div class="sidebar-divider"></div>
603
+ <div class="sidebar-footer">
604
+ <div class="sidebar-avatar">A</div>
605
+ <span class="sidebar-username">admin</span>
606
+ <button class="sidebar-more">
607
+ <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>
608
+ </button>
609
+ </div>
610
+ </aside>
611
+
612
+ <!-- ===== Main Content ===== -->
613
+ <main class="main-content">
614
+ <div class="page-container">
615
+ <div class="card">
616
+
617
+ <!-- PageHeader — 面包屑模式 -->
618
+ <div class="page-header">
619
+ <div class="page-header-left">
620
+ <nav class="breadcrumb">
621
+ <a href="#" id="backToList">AI网关实例</a>
622
+ <span class="separator"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></span>
623
+ <span class="current">production-gateway</span>
624
+ </nav>
625
+ </div>
626
+ <div class="page-header-actions">
627
+ <button class="btn btn-primary">
628
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
629
+ 编辑
630
+ </button>
631
+ <button class="btn">更多操作</button>
632
+ <button class="btn btn-icon btn-ghost" title="关闭">
633
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
634
+ </button>
635
+ </div>
636
+ </div>
637
+
638
+ <!-- InfoCard — 嵌入模式B -->
639
+ <div class="info-card">
640
+ <div class="info-card-grid">
641
+ <div class="info-card-item">
642
+ <span class="info-card-label">状态</span>
643
+ <span class="status-badge status-running"><span class="status-dot"></span>运行中</span>
644
+ </div>
645
+ <div class="info-card-item">
646
+ <span class="info-card-label">网关类型</span>
647
+ <span class="info-card-value">AI网关</span>
648
+ </div>
649
+ <div class="info-card-item">
650
+ <span class="info-card-label">部署架构</span>
651
+ <span class="info-card-value">K8s</span>
652
+ </div>
653
+ <div class="info-card-item">
654
+ <span class="info-card-label">实例规格</span>
655
+ <span class="info-card-value">Standard · 3 节点</span>
656
+ </div>
657
+ <div class="info-card-item">
658
+ <span class="info-card-label">创建时间</span>
659
+ <span class="info-card-value">2026-03-15 14:30</span>
660
+ </div>
661
+ </div>
662
+ </div>
663
+
664
+ <!-- Tabs -->
665
+ <div class="tabs">
666
+ <ul class="tabs-list">
667
+ <li><button class="tab-item active" data-tab="basic">基本信息</button></li>
668
+ <li><button class="tab-item" data-tab="endpoint">接入点</button></li>
669
+ <li><button class="tab-item" data-tab="quota">Token配额</button></li>
670
+ </ul>
671
+ </div>
672
+
673
+ <!-- Tab 1: 基本信息 -->
674
+ <div class="tab-content active" id="tab-basic">
675
+ <div class="list-section">
676
+ <h3 class="list-section-title">基本信息</h3>
677
+ <div class="description-list">
678
+ <div class="description-item">
679
+ <span class="description-label">实例ID</span>
680
+ <span class="description-value">
681
+ <span class="mono">i-bp1a4mka2u4rl7b12</span>
682
+ <button class="copy-btn" data-copy="i-bp1a4mka2u4rl7b12" title="复制"><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></button>
683
+ </span>
684
+ </div>
685
+ <div class="description-item">
686
+ <span class="description-label">实例名称</span>
687
+ <span class="description-value">production-gateway</span>
688
+ </div>
689
+ <div class="description-item">
690
+ <span class="description-label">状态</span>
691
+ <span class="description-value"><span class="status-badge status-running"><span class="status-dot"></span>运行中</span></span>
692
+ </div>
693
+ <div class="description-item">
694
+ <span class="description-label">引擎类型</span>
695
+ <span class="description-value">AI网关</span>
696
+ </div>
697
+ <div class="description-item">
698
+ <span class="description-label">集群</span>
699
+ <span class="description-value">cluster-prod-01</span>
700
+ </div>
701
+ <div class="description-item">
702
+ <span class="description-label">命名空间</span>
703
+ <span class="description-value">higress-system</span>
704
+ </div>
705
+ <div class="description-item">
706
+ <span class="description-label">IngressClass</span>
707
+ <span class="description-value">higress</span>
708
+ </div>
709
+ <div class="description-item">
710
+ <span class="description-label">引擎版本</span>
711
+ <span class="description-value mono">2.1.11</span>
712
+ </div>
713
+ <div class="description-item">
714
+ <span class="description-label">节点数</span>
715
+ <span class="description-value">3</span>
716
+ </div>
717
+ <div class="description-item">
718
+ <span class="description-label">创建时间</span>
719
+ <span class="description-value">2026-03-15 14:30:22</span>
720
+ </div>
721
+ <div class="description-item">
722
+ <span class="description-label">修改时间</span>
723
+ <span class="description-value">2026-05-20 09:15:38</span>
724
+ </div>
725
+ <div class="description-item">
726
+ <span class="description-label">容器服务集群ID</span>
727
+ <span class="description-value mono" title="cf5b2b5e2a8c14d7e9f3b2a1">cf5b2b5e2a8c14d...</span>
728
+ </div>
729
+ </div>
730
+ </div>
731
+
732
+ <div class="list-section">
733
+ <h3 class="list-section-title">能力配置</h3>
734
+ <div class="description-list">
735
+ <div class="description-item">
736
+ <span class="description-label">SLS日志服务</span>
737
+ <span class="description-value">已开启</span>
738
+ </div>
739
+ <div class="description-item">
740
+ <span class="description-label">Prometheus监控</span>
741
+ <span class="description-value">已开启</span>
742
+ </div>
743
+ <div class="description-item">
744
+ <span class="description-label">AI缓存</span>
745
+ <span class="description-value">已开启</span>
746
+ </div>
747
+ <div class="description-item">
748
+ <span class="description-label">内容安全</span>
749
+ <span class="description-value">未开启</span>
750
+ </div>
751
+ </div>
752
+ </div>
753
+ </div>
754
+
755
+ <!-- Tab 2: 接入点 -->
756
+ <div class="tab-content" id="tab-endpoint">
757
+ <div class="list-section">
758
+ <h3 class="list-section-title">接入点 (1)</h3>
759
+ <div class="data-table-wrapper">
760
+ <table class="data-table">
761
+ <thead>
762
+ <tr>
763
+ <th>类型</th>
764
+ <th>网络类型</th>
765
+ <th>ServiceName</th>
766
+ <th>External IPs</th>
767
+ <th>IP版本</th>
768
+ <th>Ports</th>
769
+ <th>ClusterIP</th>
770
+ </tr>
771
+ </thead>
772
+ <tbody>
773
+ <tr>
774
+ <td><span class="endpoint-tag">LoadBalancer</span></td>
775
+ <td><span class="network-tag public">公网</span></td>
776
+ <td class="mono">higress-gateway</td>
777
+ <td class="mono">47.108.232.137</td>
778
+ <td class="mono">ipv4</td>
779
+ <td>
780
+ <div class="ports-list">
781
+ <span>80:32423/TCP</span>
782
+ <span>443:30816/TCP</span>
783
+ </div>
784
+ </td>
785
+ <td class="mono">172.16.107.115</td>
786
+ </tr>
787
+ </tbody>
788
+ </table>
789
+ </div>
790
+ </div>
791
+ </div>
792
+
793
+ <!-- Tab 3: Token配额 -->
794
+ <div class="tab-content" id="tab-quota">
795
+ <div class="list-section">
796
+ <h3 class="list-section-title">Token 配额概览</h3>
797
+ <div class="description-list">
798
+ <div class="description-item">
799
+ <span class="description-label">配额策略</span>
800
+ <span class="description-value">按消费者分配</span>
801
+ </div>
802
+ <div class="description-item">
803
+ <span class="description-label">全局限额</span>
804
+ <span class="description-value">1,000,000 tokens/天</span>
805
+ </div>
806
+ <div class="description-item">
807
+ <span class="description-label">已用量</span>
808
+ <span class="description-value">356,780 tokens</span>
809
+ </div>
810
+ <div class="description-item">
811
+ <span class="description-label">剩余额度</span>
812
+ <span class="description-value">643,220 tokens</span>
813
+ </div>
814
+ </div>
815
+ </div>
816
+ <div class="list-section">
817
+ <h3 class="list-section-title">消费者配额分配</h3>
818
+ <div class="data-table-wrapper">
819
+ <table class="data-table">
820
+ <thead>
821
+ <tr>
822
+ <th>消费者</th>
823
+ <th>日限额</th>
824
+ <th>今日已用</th>
825
+ <th>使用率</th>
826
+ <th>状态</th>
827
+ </tr>
828
+ </thead>
829
+ <tbody>
830
+ <tr>
831
+ <td>frontend-app</td>
832
+ <td>300,000</td>
833
+ <td>156,200</td>
834
+ <td>52.1%</td>
835
+ <td><span class="status-badge status-running"><span class="status-dot"></span>正常</span></td>
836
+ </tr>
837
+ <tr>
838
+ <td>backend-service</td>
839
+ <td>500,000</td>
840
+ <td>178,580</td>
841
+ <td>35.7%</td>
842
+ <td><span class="status-badge status-running"><span class="status-dot"></span>正常</span></td>
843
+ </tr>
844
+ <tr>
845
+ <td>data-pipeline</td>
846
+ <td>200,000</td>
847
+ <td>22,000</td>
848
+ <td>11.0%</td>
849
+ <td><span class="status-badge status-running"><span class="status-dot"></span>正常</span></td>
850
+ </tr>
851
+ </tbody>
852
+ </table>
853
+ </div>
854
+ </div>
855
+ </div>
856
+
857
+ </div>
858
+ </div>
859
+ </main>
860
+
861
+ <!-- Sonner -->
862
+ <div class="toast" id="toast">已复制</div>
863
+
864
+ <script>
865
+ // Sidebar collapse
866
+ const sidebar = document.querySelector('.sidebar');
867
+ document.querySelector('.sidebar-collapse-btn').addEventListener('click', () => {
868
+ sidebar.classList.toggle('collapsed');
869
+ });
870
+ document.getElementById('sidebarLogoArea').addEventListener('click', () => {
871
+ if (sidebar.classList.contains('collapsed')) sidebar.classList.remove('collapsed');
872
+ });
873
+
874
+ // Sidebar parent menu toggle
875
+ document.querySelectorAll('.sidebar-menu-item[data-toggle]').forEach(item => {
876
+ item.addEventListener('click', function(e) {
877
+ e.preventDefault();
878
+ this.classList.toggle('expanded');
879
+ const target = document.getElementById(this.getAttribute('data-toggle'));
880
+ if (target) target.classList.toggle('show');
881
+ });
882
+ });
883
+
884
+ // Tabs switching
885
+ document.querySelectorAll('.tab-item').forEach(tab => {
886
+ tab.addEventListener('click', function() {
887
+ const target = this.getAttribute('data-tab');
888
+ document.querySelectorAll('.tab-item').forEach(t => t.classList.remove('active'));
889
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
890
+ this.classList.add('active');
891
+ const content = document.getElementById('tab-' + target);
892
+ if (content) content.classList.add('active');
893
+ // URL hash sync
894
+ history.replaceState(null, '', '#' + target);
895
+ });
896
+ });
897
+
898
+ // Restore tab from hash
899
+ (function() {
900
+ const hash = location.hash.replace('#', '');
901
+ if (hash) {
902
+ const tabBtn = document.querySelector(`.tab-item[data-tab="${hash}"]`);
903
+ if (tabBtn) tabBtn.click();
904
+ }
905
+ })();
906
+
907
+ // Sonner
908
+ const toast = document.getElementById('toast');
909
+ let toastTimer = null;
910
+ function showToast(msg) {
911
+ toast.textContent = msg;
912
+ toast.classList.add('show');
913
+ if (toastTimer) clearTimeout(toastTimer);
914
+ toastTimer = setTimeout(() => toast.classList.remove('show'), 1800);
915
+ }
916
+
917
+ // Copy buttons
918
+ document.querySelectorAll('.copy-btn').forEach(btn => {
919
+ btn.addEventListener('click', function(e) {
920
+ e.stopPropagation();
921
+ const text = this.getAttribute('data-copy') || '';
922
+ if (navigator.clipboard && navigator.clipboard.writeText) {
923
+ navigator.clipboard.writeText(text).then(() => showToast('已复制'));
924
+ } else {
925
+ const ta = document.createElement('textarea');
926
+ ta.value = text; document.body.appendChild(ta); ta.select();
927
+ try { document.execCommand('copy'); showToast('已复制'); } catch(err) {}
928
+ document.body.removeChild(ta);
929
+ }
930
+ });
931
+ });
932
+
933
+ // Breadcrumb back
934
+ document.getElementById('backToList').addEventListener('click', function(e) {
935
+ e.preventDefault();
936
+ console.log('返回实例列表页');
937
+ });
938
+ </script>
939
+
940
+ </body>
941
+ </html>