@yuku123/z-team-component 0.2.38 → 0.2.40

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.
@@ -1,1664 +0,0 @@
1
- import { jsx as e, jsxs as s } from "react/jsx-runtime";
2
- import { useNavigate as Ae, useLocation as Te, Navigate as S } from "react-router-dom";
3
- import { useState as p, useEffect as G, useRef as F, useMemo as le } from "react";
4
- import { Spin as Re, Row as Ne, Col as W, Card as M, Statistic as j, Space as x, Tag as I, Button as w, Alert as X, Table as $e, Badge as ve, Popconfirm as U, message as v, Select as we, Drawer as ze, Tabs as Ee, Form as L, Modal as Le, Input as te, InputNumber as ne } from "antd";
5
- import { DashboardOutlined as q, ClusterOutlined as H, CloudServerOutlined as A, ContainerOutlined as Se, ReloadOutlined as re, LockOutlined as Ge, UnlockOutlined as De, PlayCircleOutlined as He, PauseCircleOutlined as qe, ClearOutlined as Ce, SendOutlined as xe, EyeOutlined as Be, DeleteOutlined as Ie, PlusOutlined as Fe, EditOutlined as Me, DownOutlined as Ke, RightOutlined as Ue, BranchesOutlined as ie, RocketOutlined as We, AlertOutlined as je, FileTextOutlined as ae, DatabaseOutlined as V, CloudOutlined as Ve, DeploymentUnitOutlined as de, UnorderedListOutlined as J, HistoryOutlined as Je, ExperimentOutlined as Ze, SettingOutlined as pe, KeyOutlined as Z, AppstoreOutlined as se, SafetyCertificateOutlined as Qe, TeamOutlined as Ye, ProfileOutlined as me, ApiOutlined as ue, HddOutlined as ce, ApartmentOutlined as he, InboxOutlined as ye, NodeIndexOutlined as Xe, TableOutlined as ge, SearchOutlined as be, ConsoleSqlOutlined as et, BookOutlined as Q, FundOutlined as tt, CloudUploadOutlined as nt, TagsOutlined as at, CodeOutlined as st } from "@ant-design/icons";
6
- import { ConfigApp as ct } from "@yuku123/z-config-component";
7
- import { MistApp as ot } from "@yuku123/z-mist-component";
8
- import { MetaApp as rt } from "@yuku123/z-meta-component";
9
- import { MsgApp as lt } from "@yuku123/z-msg-component";
10
- import { RpcApp as it } from "@yuku123/z-rpc-component";
11
- import { VectorApp as dt } from "@yuku123/z-vector-component";
12
- import { GraphApp as pt } from "@yuku123/z-graph-component";
13
- import { GwApp as mt } from "@yuku123/z-gw-component";
14
- import { CacheApp as ut } from "@yuku123/z-cache-component";
15
- import { MqApp as ht } from "@yuku123/z-mq-component";
16
- import { OssApp as yt } from "@yuku123/z-oss-component";
17
- import { ZkbApp as gt } from "@yuku123/z-kb-component";
18
- import { ScriptProductizationPage as K } from "@yuku123/z-agent-component";
19
- import { ListTable as Oe } from "@yuku123/z-frontend-common/ui";
20
- const bt = "_shell_19t4h_6", kt = "_sidebar_19t4h_14", ft = "_menuList_19t4h_36", vt = "_menuGroup_19t4h_42", wt = "_menuGroupHeader_19t4h_46", St = "_menuGroupIcon_19t4h_64", Ct = "_menuGroupLabel_19t4h_69", xt = "_menuGroupArrow_19t4h_73", It = "_menuSubList_19t4h_79", Ot = "_menuSubItem_19t4h_85", _t = "_menuSubItemActive_19t4h_102", Pt = "_menuSubItemIcon_19t4h_109", At = "_menuSubItemLabel_19t4h_114", Tt = "_menuSubItemWrap_19t4h_118", Rt = "_main_19t4h_122", Nt = "_empty_19t4h_129", $t = "_emptyIcon_19t4h_139", zt = "_emptyText_19t4h_144", f = {
21
- shell: bt,
22
- sidebar: kt,
23
- menuList: ft,
24
- menuGroup: vt,
25
- menuGroupHeader: wt,
26
- menuGroupIcon: St,
27
- menuGroupLabel: Ct,
28
- menuGroupArrow: xt,
29
- menuSubList: It,
30
- menuSubItem: Ot,
31
- menuSubItemActive: _t,
32
- menuSubItemIcon: Pt,
33
- menuSubItemLabel: At,
34
- menuSubItemWrap: Tt,
35
- main: Rt,
36
- empty: Nt,
37
- emptyIcon: $t,
38
- emptyText: zt
39
- }, Et = "/z-team/ops/k8s";
40
- async function _e(t, c) {
41
- const i = `${Et}${t}`, d = await fetch(i, {
42
- headers: { "Content-Type": "application/json" },
43
- ...c
44
- }), m = d.headers && d.headers.get("content-type") || "";
45
- if (!/json/i.test(m))
46
- throw new Error(`数据源不可达:GET ${i} 返回 ${d.status} ${m || "(无 content-type)"},不是 JSON —— 该前缀没有进到后端接口(K8s 管理 API 在 z-ops 仓,z-opc 宿主未注册)`);
47
- const u = await d.json();
48
- if (u && u.success === !1)
49
- throw new Error(`后端 ${i} 返回 success=false:${u.message || "(无 message)"}`);
50
- return u;
51
- }
52
- async function z(t, c) {
53
- return _e(t, c);
54
- }
55
- async function Lt() {
56
- return z("/cluster/info");
57
- }
58
- async function Gt() {
59
- return z("/nodes");
60
- }
61
- async function Dt(t) {
62
- return z("/nodes/cordon", {
63
- method: "POST",
64
- body: JSON.stringify({ name: t })
65
- });
66
- }
67
- async function Ht(t) {
68
- return z("/nodes/uncordon", {
69
- method: "POST",
70
- body: JSON.stringify({ name: t })
71
- });
72
- }
73
- async function qt(t = "*") {
74
- return z(`/workloads/pods?namespace=${t}`);
75
- }
76
- async function Bt(t, c, i = 200) {
77
- return z(`/workloads/pods/${t}/${c}/logs?tailLines=${i}`);
78
- }
79
- async function Ft(t, c) {
80
- return z(`/workloads/pods/${t}/${c}/restart`, { method: "POST" });
81
- }
82
- async function Mt(t, c) {
83
- return z(`/workloads/pods/${t}/${c}`, { method: "DELETE" });
84
- }
85
- async function Kt() {
86
- return z("/namespaces");
87
- }
88
- const ke = () => {
89
- var u, y;
90
- const [t, c] = p(null), [i, d] = p(!0);
91
- G(() => {
92
- m();
93
- const h = setInterval(m, 1e4);
94
- return () => clearInterval(h);
95
- }, []);
96
- const m = async () => {
97
- try {
98
- const h = await Lt();
99
- h.success && c(h.data);
100
- } catch (h) {
101
- console.error("Failed to load cluster info", h);
102
- } finally {
103
- d(!1);
104
- }
105
- };
106
- return i ? /* @__PURE__ */ e(Re, { size: "large" }) : /* @__PURE__ */ s("div", { style: { padding: 16 }, children: [
107
- /* @__PURE__ */ s("h2", { style: { marginBottom: 24 }, children: [
108
- /* @__PURE__ */ e(q, {}),
109
- " 运维总览"
110
- ] }),
111
- /* @__PURE__ */ s(Ne, { gutter: [16, 16], children: [
112
- /* @__PURE__ */ e(W, { xs: 24, sm: 12, lg: 6, children: /* @__PURE__ */ s(M, { children: [
113
- /* @__PURE__ */ e(
114
- j,
115
- {
116
- title: /* @__PURE__ */ s(x, { children: [
117
- /* @__PURE__ */ e(H, {}),
118
- " K8s 节点"
119
- ] }),
120
- value: (t == null ? void 0 : t.readyNodes) ?? 0,
121
- suffix: /* @__PURE__ */ s("span", { style: { color: "#999" }, children: [
122
- " / ",
123
- (t == null ? void 0 : t.nodeCount) ?? 0
124
- ] })
125
- }
126
- ),
127
- /* @__PURE__ */ e(I, { color: (t == null ? void 0 : t.status) === "Healthy" ? "success" : "warning", children: (t == null ? void 0 : t.status) ?? "Unknown" })
128
- ] }) }),
129
- /* @__PURE__ */ e(W, { xs: 24, sm: 12, lg: 6, children: /* @__PURE__ */ s(M, { children: [
130
- /* @__PURE__ */ e(
131
- j,
132
- {
133
- title: /* @__PURE__ */ s(x, { children: [
134
- /* @__PURE__ */ e(A, {}),
135
- " CPU"
136
- ] }),
137
- value: ((u = t == null ? void 0 : t.usedCpu) == null ? void 0 : u.toFixed(1)) ?? "0",
138
- suffix: /* @__PURE__ */ s("span", { style: { color: "#999" }, children: [
139
- " / ",
140
- (t == null ? void 0 : t.totalCpu) ?? 0,
141
- " cores"
142
- ] }),
143
- precision: 1
144
- }
145
- ),
146
- /* @__PURE__ */ s(I, { color: ((t == null ? void 0 : t.usedCpu) ?? 0) / ((t == null ? void 0 : t.totalCpu) ?? 1) > 0.8 ? "error" : "success", children: [
147
- (((t == null ? void 0 : t.usedCpu) ?? 0) / ((t == null ? void 0 : t.totalCpu) ?? 1) * 100).toFixed(0),
148
- "%"
149
- ] })
150
- ] }) }),
151
- /* @__PURE__ */ e(W, { xs: 24, sm: 12, lg: 6, children: /* @__PURE__ */ s(M, { children: [
152
- /* @__PURE__ */ e(
153
- j,
154
- {
155
- title: /* @__PURE__ */ s(x, { children: [
156
- /* @__PURE__ */ e(q, {}),
157
- " 内存"
158
- ] }),
159
- value: ((y = t == null ? void 0 : t.usedMemory) == null ? void 0 : y.toFixed(1)) ?? "0",
160
- suffix: /* @__PURE__ */ s("span", { style: { color: "#999" }, children: [
161
- " / ",
162
- (t == null ? void 0 : t.totalMemory) ?? 0,
163
- " GB"
164
- ] }),
165
- precision: 1
166
- }
167
- ),
168
- /* @__PURE__ */ s(I, { color: ((t == null ? void 0 : t.usedMemory) ?? 0) / ((t == null ? void 0 : t.totalMemory) ?? 1) > 0.8 ? "error" : "success", children: [
169
- (((t == null ? void 0 : t.usedMemory) ?? 0) / ((t == null ? void 0 : t.totalMemory) ?? 1) * 100).toFixed(0),
170
- "%"
171
- ] })
172
- ] }) }),
173
- /* @__PURE__ */ e(W, { xs: 24, sm: 12, lg: 6, children: /* @__PURE__ */ s(M, { children: [
174
- /* @__PURE__ */ e(
175
- j,
176
- {
177
- title: /* @__PURE__ */ s(x, { children: [
178
- /* @__PURE__ */ e(Se, {}),
179
- " Pods"
180
- ] }),
181
- value: (t == null ? void 0 : t.runningPods) ?? 0,
182
- suffix: /* @__PURE__ */ s("span", { style: { color: "#999" }, children: [
183
- " / ",
184
- (t == null ? void 0 : t.totalPods) ?? 0
185
- ] })
186
- }
187
- ),
188
- /* @__PURE__ */ s(I, { color: "success", children: [
189
- (t == null ? void 0 : t.namespaceCount) ?? 0,
190
- " namespaces"
191
- ] })
192
- ] }) })
193
- ] }),
194
- /* @__PURE__ */ e(M, { title: "集群信息", style: { marginTop: 16 }, children: /* @__PURE__ */ s(x, { orientation: "vertical", children: [
195
- /* @__PURE__ */ s("div", { children: [
196
- /* @__PURE__ */ e("strong", { children: "K8s 版本:" }),
197
- " ",
198
- (t == null ? void 0 : t.version) ?? "Unknown"
199
- ] }),
200
- /* @__PURE__ */ s("div", { children: [
201
- /* @__PURE__ */ e("strong", { children: "集群状态:" }),
202
- " ",
203
- /* @__PURE__ */ e(I, { color: "success", children: t == null ? void 0 : t.status })
204
- ] }),
205
- /* @__PURE__ */ s("div", { children: [
206
- /* @__PURE__ */ e("strong", { children: "节点数:" }),
207
- " ",
208
- t == null ? void 0 : t.nodeCount,
209
- " (Ready: ",
210
- t == null ? void 0 : t.readyNodes,
211
- ")"
212
- ] }),
213
- /* @__PURE__ */ s("div", { children: [
214
- /* @__PURE__ */ e("strong", { children: "CPU 使用率:" }),
215
- " ",
216
- (((t == null ? void 0 : t.usedCpu) ?? 0) / ((t == null ? void 0 : t.totalCpu) ?? 1) * 100).toFixed(1),
217
- "%"
218
- ] }),
219
- /* @__PURE__ */ s("div", { children: [
220
- /* @__PURE__ */ e("strong", { children: "内存使用率:" }),
221
- " ",
222
- (((t == null ? void 0 : t.usedMemory) ?? 0) / ((t == null ? void 0 : t.totalMemory) ?? 1) * 100).toFixed(1),
223
- "%"
224
- ] })
225
- ] }) })
226
- ] });
227
- }, Ut = () => {
228
- const [t, c] = p([]), [i, d] = p(!1), [m, u] = p("");
229
- G(() => {
230
- y();
231
- }, []);
232
- const y = async () => {
233
- d(!0), u("");
234
- try {
235
- const a = await Gt();
236
- c(Array.isArray(a.data) ? a.data : []);
237
- } catch (a) {
238
- c([]), u(String((a == null ? void 0 : a.message) || a));
239
- } finally {
240
- d(!1);
241
- }
242
- }, h = async (a) => {
243
- try {
244
- await Dt(a), v.success(`${a} 已封锁(停止调度)`), y();
245
- } catch {
246
- v.error("封锁失败");
247
- }
248
- }, C = async (a) => {
249
- try {
250
- await Ht(a), v.success(`${a} 已解封`), y();
251
- } catch {
252
- v.error("解封失败");
253
- }
254
- };
255
- return /* @__PURE__ */ s("div", { children: [
256
- /* @__PURE__ */ e(x, { style: { marginBottom: 16 }, children: /* @__PURE__ */ e(w, { icon: /* @__PURE__ */ e(re, {}), onClick: y, loading: i, children: "刷新" }) }),
257
- m && /* @__PURE__ */ e(
258
- X,
259
- {
260
- type: "error",
261
- showIcon: !0,
262
- style: { marginBottom: 12 },
263
- message: "节点列表读取失败",
264
- description: m
265
- }
266
- ),
267
- /* @__PURE__ */ e(
268
- $e,
269
- {
270
- columns: [
271
- {
272
- title: "名称",
273
- dataIndex: "name",
274
- key: "name",
275
- render: (a) => /* @__PURE__ */ e("strong", { children: a })
276
- },
277
- {
278
- title: "IP",
279
- dataIndex: "ip",
280
- key: "ip",
281
- render: (a) => /* @__PURE__ */ e("code", { children: a })
282
- },
283
- {
284
- title: "状态",
285
- dataIndex: "status",
286
- key: "status",
287
- render: (a) => /* @__PURE__ */ e(ve, { status: a === "Ready" ? "success" : "error", text: a })
288
- },
289
- {
290
- title: "角色",
291
- dataIndex: "roles",
292
- key: "roles",
293
- render: (a) => a ? /* @__PURE__ */ e(I, { color: "blue", children: a }) : /* @__PURE__ */ e(I, { children: "worker" })
294
- },
295
- {
296
- title: "CPU",
297
- key: "cpu",
298
- render: (a, o) => {
299
- var O, _;
300
- const r = o.cpuCapacity > 0 ? (o.cpuAllocatable - o.cpuCapacity + o.cpuCapacity) / o.cpuCapacity * 100 : 0;
301
- return /* @__PURE__ */ s("span", { children: [
302
- ((O = o.cpuAllocatable) == null ? void 0 : O.toFixed(1)) ?? 0,
303
- " / ",
304
- ((_ = o.cpuCapacity) == null ? void 0 : _.toFixed(0)) ?? 0,
305
- " cores",
306
- /* @__PURE__ */ s(I, { color: r > 80 ? "error" : "success", style: { marginLeft: 4 }, children: [
307
- r.toFixed(0),
308
- "%"
309
- ] })
310
- ] });
311
- }
312
- },
313
- {
314
- title: "内存",
315
- key: "mem",
316
- render: (a, o) => {
317
- var _;
318
- const r = o.memCapacity - o.memAllocatable, O = o.memCapacity > 0 ? r / o.memCapacity * 100 : 0;
319
- return /* @__PURE__ */ s("span", { children: [
320
- (r == null ? void 0 : r.toFixed(1)) ?? 0,
321
- " / ",
322
- ((_ = o.memCapacity) == null ? void 0 : _.toFixed(0)) ?? 0,
323
- " GB",
324
- /* @__PURE__ */ s(I, { color: O > 80 ? "error" : "success", style: { marginLeft: 4 }, children: [
325
- O.toFixed(0),
326
- "%"
327
- ] })
328
- ] });
329
- }
330
- },
331
- { title: "OS", dataIndex: "osImage", key: "osImage", ellipsis: !0, width: 200 },
332
- { title: "运行时", dataIndex: "containerRuntime", key: "containerRuntime", width: 160 },
333
- { title: "存活", dataIndex: "age", key: "age", width: 80 },
334
- {
335
- title: "操作",
336
- key: "action",
337
- width: 150,
338
- render: (a, o) => /* @__PURE__ */ s(x, { children: [
339
- /* @__PURE__ */ e(U, { title: `封锁 ${o.name}?`, onConfirm: () => h(o.name), children: /* @__PURE__ */ e(w, { size: "small", icon: /* @__PURE__ */ e(Ge, {}), children: "Cordon" }) }),
340
- /* @__PURE__ */ e(U, { title: `解封 ${o.name}?`, onConfirm: () => C(o.name), children: /* @__PURE__ */ e(w, { size: "small", icon: /* @__PURE__ */ e(De, {}), children: "Uncordon" }) })
341
- ] })
342
- }
343
- ],
344
- dataSource: t,
345
- rowKey: "name",
346
- loading: i,
347
- pagination: !1,
348
- scroll: { x: 1400 },
349
- size: "middle"
350
- }
351
- )
352
- ] });
353
- }, Wt = ({
354
- namespace: t,
355
- podName: c,
356
- tailLines: i = 200
357
- }) => {
358
- const [d, m] = p([]), [u, y] = p(!1), [h, C] = p(!1), k = F(null), a = F(null), o = F(!1);
359
- G(() => (r(), () => {
360
- var g;
361
- (g = k.current) == null || g.close();
362
- }), [t, c]), G(() => {
363
- var g;
364
- h || (g = a.current) == null || g.scrollIntoView({ behavior: "smooth" });
365
- }, [d, h]);
366
- const r = () => {
367
- const g = window.location.protocol === "https:" ? "wss:" : "ws:", n = window.location.host, b = `${g}//${n}/z-team/ops/k8s/ws/logs?namespace=${t}&name=${c}&tailLines=${i}`, P = new WebSocket(b);
368
- k.current = P, P.onopen = () => {
369
- y(!0), v.success("日志流已连接");
370
- }, P.onmessage = (T) => {
371
- o.current || m(($) => [...$.slice(-1e3), T.data]);
372
- }, P.onclose = () => {
373
- y(!1);
374
- }, P.onerror = () => {
375
- y(!1), v.error("WebSocket 连接错误");
376
- };
377
- };
378
- return /* @__PURE__ */ s("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
379
- /* @__PURE__ */ s(x, { style: { marginBottom: 8 }, children: [
380
- /* @__PURE__ */ e(I, { color: u ? "success" : "error", children: u ? "● 已连接" : "● 已断开" }),
381
- /* @__PURE__ */ e(
382
- w,
383
- {
384
- size: "small",
385
- icon: h ? /* @__PURE__ */ e(He, {}) : /* @__PURE__ */ e(qe, {}),
386
- onClick: () => {
387
- o.current = !o.current, C(o.current);
388
- },
389
- children: h ? "继续" : "暂停"
390
- }
391
- ),
392
- /* @__PURE__ */ e(w, { size: "small", icon: /* @__PURE__ */ e(Ce, {}), onClick: () => {
393
- m([]);
394
- }, children: "清空" }),
395
- /* @__PURE__ */ e(w, { size: "small", onClick: () => {
396
- var g;
397
- (g = k.current) == null || g.close(), m([]), r();
398
- }, children: "重连" })
399
- ] }),
400
- /* @__PURE__ */ s("div", { style: {
401
- flex: 1,
402
- background: "#1e1e1e",
403
- borderRadius: 8,
404
- padding: 12,
405
- overflow: "auto",
406
- fontFamily: 'Menlo, Monaco, "Courier New", monospace',
407
- fontSize: 12,
408
- lineHeight: 1.5,
409
- color: "#d4d4d4"
410
- }, children: [
411
- d.map((g, n) => /* @__PURE__ */ e("div", { style: {
412
- color: g.includes("ERROR") ? "#f44336" : g.includes("WARN") ? "#ff9800" : g.includes("INFO") ? "#4caf50" : "#d4d4d4",
413
- whiteSpace: "pre-wrap",
414
- wordBreak: "break-all"
415
- }, children: g }, n)),
416
- /* @__PURE__ */ e("div", { ref: a })
417
- ] })
418
- ] });
419
- }, jt = ({
420
- namespace: t,
421
- podName: c
422
- }) => {
423
- const [i, d] = p(!1), [m, u] = p(""), [y, h] = p("sh"), [C, k] = p([]), a = F(null), o = F(null), r = F(null);
424
- G(() => (t && c && O(), () => {
425
- var n;
426
- return (n = a.current) == null ? void 0 : n.close();
427
- }), [t, c]);
428
- const O = () => {
429
- const n = window.location.protocol === "https:" ? "wss:" : "ws:", b = window.location.host, P = `${n}//${b}/z-team/ops/k8s/ws/exec?namespace=${t}&name=${c}&command=${y}`, T = new WebSocket(P);
430
- a.current = T, T.onopen = () => {
431
- d(!0), k(($) => [...$, `Connected to ${t}/${c} (${y})`]), v.success("终端已连接");
432
- }, T.onmessage = ($) => {
433
- k((ee) => [...ee.slice(-500), $.data]), setTimeout(() => {
434
- o.current && (o.current.scrollTop = o.current.scrollHeight);
435
- }, 50);
436
- }, T.onclose = () => {
437
- d(!1), k(($) => [...$, `
438
- --- 连接已关闭 ---`]);
439
- }, T.onerror = () => {
440
- d(!1), v.error("WebSocket 连接错误");
441
- };
442
- }, _ = () => {
443
- !m.trim() || !a.current || (a.current.readyState === WebSocket.OPEN ? (a.current.send(m), k((n) => [...n, `$ ${m}`]), u("")) : v.warning("WebSocket 未连接"));
444
- }, D = (n) => {
445
- var b;
446
- n.key === "Enter" && _(), n.key === "Tab" && (n.preventDefault(), ((b = a.current) == null ? void 0 : b.readyState) === WebSocket.OPEN && a.current.send(" "));
447
- }, g = () => k([]);
448
- return /* @__PURE__ */ s("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
449
- /* @__PURE__ */ s(x, { style: { marginBottom: 8 }, children: [
450
- /* @__PURE__ */ e(I, { color: i ? "success" : "error", children: i ? "● 已连接" : "● 已断开" }),
451
- /* @__PURE__ */ e(
452
- we,
453
- {
454
- value: y,
455
- onChange: h,
456
- size: "small",
457
- style: { width: 100 },
458
- options: ["sh", "bash", "/bin/sh", "/bin/bash"].map((n) => ({ label: n, value: n }))
459
- }
460
- ),
461
- /* @__PURE__ */ e(w, { size: "small", onClick: g, icon: /* @__PURE__ */ e(Ce, {}), children: "清空" }),
462
- /* @__PURE__ */ e(w, { size: "small", onClick: () => {
463
- var n;
464
- (n = a.current) == null || n.close(), setTimeout(O, 200);
465
- }, children: "重连" })
466
- ] }),
467
- /* @__PURE__ */ s(
468
- "div",
469
- {
470
- ref: o,
471
- style: {
472
- flex: 1,
473
- background: "#1a1a2e",
474
- borderRadius: 8,
475
- padding: 12,
476
- overflow: "auto",
477
- fontFamily: '"JetBrains Mono", "Fira Code", Menlo, Monaco, "Courier New", monospace',
478
- fontSize: 13,
479
- lineHeight: 1.6,
480
- color: "#00ff88",
481
- marginBottom: 8,
482
- minHeight: 300,
483
- border: "1px solid #333"
484
- },
485
- children: [
486
- C.map((n, b) => /* @__PURE__ */ e("div", { style: {
487
- whiteSpace: "pre-wrap",
488
- wordBreak: "break-all",
489
- color: n.startsWith("$ ") ? "#00bfff" : n.startsWith("---") ? "#666" : n.includes("Error") || n.includes("error") ? "#ff4444" : "#00ff88"
490
- }, children: n }, b)),
491
- /* @__PURE__ */ e("span", { ref: r, style: {
492
- display: "inline-block",
493
- width: 8,
494
- height: 16,
495
- background: "#00ff88",
496
- animation: "blink 1s step-end infinite",
497
- verticalAlign: "middle"
498
- } })
499
- ]
500
- }
501
- ),
502
- /* @__PURE__ */ s(x.Compact, { style: { width: "100%" }, children: [
503
- /* @__PURE__ */ s("span", { style: {
504
- background: "#333",
505
- color: "#00ff88",
506
- padding: "4px 10px",
507
- borderRadius: "8px 0 0 8px",
508
- fontFamily: "monospace",
509
- fontSize: 13,
510
- lineHeight: "22px",
511
- borderRight: "1px solid #555"
512
- }, children: [
513
- "$ ",
514
- t,
515
- "/",
516
- c
517
- ] }),
518
- /* @__PURE__ */ e(
519
- "input",
520
- {
521
- value: m,
522
- onChange: (n) => u(n.target.value),
523
- onKeyDown: D,
524
- placeholder: "输入命令后按 Enter...",
525
- disabled: !i,
526
- style: {
527
- flex: 1,
528
- background: "#1a1a2e",
529
- color: "#00ff88",
530
- border: "1px solid #555",
531
- borderLeft: "none",
532
- borderRight: "none",
533
- padding: "4px 10px",
534
- fontFamily: "monospace",
535
- fontSize: 13,
536
- outline: "none"
537
- }
538
- }
539
- ),
540
- /* @__PURE__ */ e(
541
- w,
542
- {
543
- type: "primary",
544
- icon: /* @__PURE__ */ e(xe, {}),
545
- onClick: _,
546
- disabled: !i,
547
- children: "发送"
548
- }
549
- )
550
- ] })
551
- ] });
552
- }, Vt = (t) => {
553
- switch (t) {
554
- case "Running":
555
- return "success";
556
- case "Pending":
557
- return "warning";
558
- case "Succeeded":
559
- return "default";
560
- case "Failed":
561
- return "error";
562
- default:
563
- return "default";
564
- }
565
- }, Jt = () => {
566
- const [t, c] = p([]), [i, d] = p(!1), [m, u] = p(""), [y, h] = p("*"), [C, k] = p([]), [a, o] = p(!1), [r, O] = p(null), [_, D] = p("logs"), [g, n] = p("");
567
- G(() => {
568
- b();
569
- }, []), G(() => {
570
- P();
571
- }, [y]);
572
- const b = async () => {
573
- try {
574
- const l = await Kt();
575
- k(Array.isArray(l.data) ? ["*", ...l.data] : ["*"]);
576
- } catch {
577
- k(["*"]);
578
- }
579
- }, P = async () => {
580
- d(!0), u("");
581
- try {
582
- const l = await qt(y);
583
- c(Array.isArray(l.data) ? l.data : []);
584
- } catch (l) {
585
- c([]), u(String((l == null ? void 0 : l.message) || l));
586
- } finally {
587
- d(!1);
588
- }
589
- }, T = async (l) => {
590
- var R;
591
- O(l), D("logs"), o(!0);
592
- try {
593
- const E = await Bt(l.namespace, l.name, 200);
594
- n(((R = E == null ? void 0 : E.data) == null ? void 0 : R.logs) ?? "");
595
- } catch (E) {
596
- n(`加载日志失败:${String((E == null ? void 0 : E.message) || E)}`);
597
- }
598
- }, $ = async (l) => {
599
- try {
600
- await Ft(l.namespace, l.name), v.success(`${l.name} 已重启`), P();
601
- } catch {
602
- v.error("重启失败");
603
- }
604
- }, ee = async (l) => {
605
- try {
606
- await Mt(l.namespace, l.name), v.success(`${l.name} 已删除`), P();
607
- } catch {
608
- v.error("删除失败");
609
- }
610
- }, Pe = [
611
- {
612
- title: "名称",
613
- dataIndex: "name",
614
- key: "name",
615
- render: (l, R) => /* @__PURE__ */ e("a", { onClick: () => T(R), children: l })
616
- },
617
- { title: "命名空间", dataIndex: "namespace", key: "namespace", width: 120 },
618
- { title: "节点", dataIndex: "nodeName", key: "nodeName", width: 130 },
619
- { title: "IP", dataIndex: "ip", key: "ip", width: 120 },
620
- {
621
- title: "状态",
622
- dataIndex: "status",
623
- key: "status",
624
- width: 100,
625
- render: (l) => /* @__PURE__ */ e(ve, { status: Vt(l), text: l })
626
- },
627
- {
628
- title: "就绪",
629
- dataIndex: "ready",
630
- key: "ready",
631
- width: 70,
632
- render: (l) => l ? /* @__PURE__ */ e(I, { color: "success", children: "✓" }) : /* @__PURE__ */ e(I, { color: "error", children: "✗" })
633
- },
634
- { title: "重启", dataIndex: "restartCount", key: "restartCount", width: 70 },
635
- { title: "存活", dataIndex: "age", key: "age", width: 80 },
636
- {
637
- title: "操作",
638
- key: "action",
639
- width: 200,
640
- render: (l, R) => /* @__PURE__ */ s(x, { children: [
641
- /* @__PURE__ */ e(w, { size: "small", icon: /* @__PURE__ */ e(Be, {}), onClick: () => T(R), children: "日志" }),
642
- /* @__PURE__ */ e(U, { title: "确认重启此 Pod?", onConfirm: () => $(R), children: /* @__PURE__ */ e(w, { size: "small", type: "primary", ghost: !0, children: "重启" }) }),
643
- /* @__PURE__ */ e(U, { title: "确认删除此 Pod?", onConfirm: () => ee(R), children: /* @__PURE__ */ e(w, { size: "small", danger: !0, icon: /* @__PURE__ */ e(Ie, {}), children: "删除" }) })
644
- ] })
645
- }
646
- ];
647
- return /* @__PURE__ */ s("div", { children: [
648
- /* @__PURE__ */ s(x, { style: { marginBottom: 16 }, children: [
649
- /* @__PURE__ */ e("span", { children: "命名空间:" }),
650
- /* @__PURE__ */ e(
651
- we,
652
- {
653
- value: y,
654
- onChange: h,
655
- style: { width: 200 },
656
- options: C.map((l) => ({ label: l, value: l }))
657
- }
658
- ),
659
- /* @__PURE__ */ e(w, { icon: /* @__PURE__ */ e(re, {}), onClick: P, loading: i, children: "刷新" })
660
- ] }),
661
- m && /* @__PURE__ */ e(
662
- X,
663
- {
664
- type: "error",
665
- showIcon: !0,
666
- style: { marginBottom: 12 },
667
- message: "Pod 列表读取失败",
668
- description: m
669
- }
670
- ),
671
- /* @__PURE__ */ e(
672
- Oe,
673
- {
674
- rows: t,
675
- columns: Pe,
676
- rowKey: "name",
677
- loading: i,
678
- scroll: { x: 1e3 },
679
- searchKeys: ["name", "namespace", "nodeName"],
680
- searchPlaceholder: "按 Pod 名 / 命名空间 / 节点过滤",
681
- emptyTitle: "暂无 Pod",
682
- emptyDescription: "该命名空间下还没有 Pod。",
683
- tableProps: { size: "middle" }
684
- }
685
- ),
686
- /* @__PURE__ */ e(
687
- ze,
688
- {
689
- title: r ? `${r.name} (${r.namespace})` : "",
690
- placement: "right",
691
- size: "large",
692
- open: a,
693
- onClose: () => o(!1),
694
- children: /* @__PURE__ */ e(
695
- Ee,
696
- {
697
- activeKey: _,
698
- onChange: D,
699
- items: [
700
- {
701
- key: "logs",
702
- label: "实时日志",
703
- children: r ? /* @__PURE__ */ e(
704
- Wt,
705
- {
706
- namespace: r.namespace,
707
- podName: r.name
708
- }
709
- ) : null
710
- },
711
- {
712
- key: "exec",
713
- label: "终端",
714
- children: /* @__PURE__ */ e("div", { style: { padding: 20 }, children: /* @__PURE__ */ e(
715
- jt,
716
- {
717
- namespace: (r == null ? void 0 : r.namespace) ?? "",
718
- podName: (r == null ? void 0 : r.name) ?? ""
719
- }
720
- ) })
721
- }
722
- ]
723
- }
724
- )
725
- }
726
- )
727
- ] });
728
- };
729
- async function Y(t, c) {
730
- return _e(`/hpa${t}`, c);
731
- }
732
- const Zt = () => {
733
- const [t, c] = p([]), [i, d] = p(!1), [m, u] = p(""), [y, h] = p(!1), [C, k] = p(!1), [a] = L.useForm();
734
- G(() => {
735
- o();
736
- }, []);
737
- const o = async () => {
738
- d(!0), u("");
739
- try {
740
- const n = await Y("/list?namespace=*");
741
- c(Array.isArray(n.data) ? n.data : []);
742
- } catch (n) {
743
- c([]), u(String((n == null ? void 0 : n.message) || n));
744
- } finally {
745
- d(!1);
746
- }
747
- }, r = () => {
748
- k(!1), a.resetFields(), a.setFieldsValue({ minReplicas: 1, maxReplicas: 10, cpuTarget: 80 }), h(!0);
749
- }, O = (n) => {
750
- k(!0), a.setFieldsValue({
751
- name: n.name,
752
- namespace: n.namespace,
753
- deploymentName: n.scaleTargetRef,
754
- minReplicas: n.minReplicas,
755
- maxReplicas: n.maxReplicas,
756
- cpuTarget: n.cpuTarget
757
- }), h(!0);
758
- }, _ = async () => {
759
- try {
760
- const n = await a.validateFields();
761
- C ? (await Y("/update", {
762
- method: "POST",
763
- body: JSON.stringify({
764
- namespace: n.namespace,
765
- name: n.name,
766
- minReplicas: n.minReplicas,
767
- maxReplicas: n.maxReplicas
768
- })
769
- }), v.success("HPA 更新成功")) : (await Y("/create", {
770
- method: "POST",
771
- body: JSON.stringify(n)
772
- }), v.success("HPA 创建成功")), h(!1), o();
773
- } catch {
774
- v.error("操作失败");
775
- }
776
- }, D = async (n) => {
777
- try {
778
- await Y(`/delete/${n.namespace}/${n.name}`, { method: "DELETE" }), v.success("HPA 已删除"), o();
779
- } catch {
780
- v.error("删除失败");
781
- }
782
- };
783
- return /* @__PURE__ */ s("div", { children: [
784
- /* @__PURE__ */ s(x, { style: { marginBottom: 16 }, children: [
785
- /* @__PURE__ */ e(w, { type: "primary", icon: /* @__PURE__ */ e(Fe, {}), onClick: r, children: "新建 HPA" }),
786
- /* @__PURE__ */ e(w, { icon: /* @__PURE__ */ e(re, {}), onClick: o, loading: i, children: "刷新" })
787
- ] }),
788
- m && /* @__PURE__ */ e(
789
- X,
790
- {
791
- type: "error",
792
- showIcon: !0,
793
- style: { marginBottom: 12 },
794
- message: "HPA 列表读取失败",
795
- description: m
796
- }
797
- ),
798
- /* @__PURE__ */ e(
799
- Oe,
800
- {
801
- rows: t,
802
- columns: [
803
- { title: "名称", dataIndex: "name", key: "name", render: (n) => /* @__PURE__ */ e("strong", { children: n }) },
804
- { title: "命名空间", dataIndex: "namespace", key: "namespace" },
805
- { title: "目标 Deployment", dataIndex: "scaleTargetRef", key: "target" },
806
- {
807
- title: "副本范围",
808
- key: "replicas",
809
- render: (n, b) => /* @__PURE__ */ s("span", { children: [
810
- b.minReplicas,
811
- " ~ ",
812
- b.maxReplicas,
813
- " (当前: ",
814
- b.currentReplicas ?? "-",
815
- ")"
816
- ] })
817
- },
818
- {
819
- title: "CPU 目标",
820
- dataIndex: "cpuTarget",
821
- key: "cpuTarget",
822
- render: (n) => n ? /* @__PURE__ */ s(I, { color: "blue", children: [
823
- n,
824
- "%"
825
- ] }) : "-"
826
- },
827
- {
828
- title: "期望副本",
829
- dataIndex: "desiredReplicas",
830
- key: "desired",
831
- render: (n) => n ? /* @__PURE__ */ e(I, { color: "green", children: n }) : "-"
832
- },
833
- { title: "存活", dataIndex: "age", key: "age" },
834
- {
835
- title: "操作",
836
- key: "action",
837
- width: 150,
838
- render: (n, b) => /* @__PURE__ */ s(x, { children: [
839
- /* @__PURE__ */ e(w, { size: "small", icon: /* @__PURE__ */ e(Me, {}), onClick: () => O(b), children: "编辑" }),
840
- /* @__PURE__ */ e(U, { title: `删除 HPA ${b.name}?`, onConfirm: () => D(b), children: /* @__PURE__ */ e(w, { size: "small", danger: !0, icon: /* @__PURE__ */ e(Ie, {}), children: "删除" }) })
841
- ] })
842
- }
843
- ],
844
- rowKey: "name",
845
- loading: i,
846
- searchKeys: ["name", "namespace", "scaleTargetRef"],
847
- searchPlaceholder: "按 HPA 名 / 命名空间 / 目标 Deployment 过滤",
848
- emptyTitle: "暂无 HPA",
849
- emptyDescription: "该集群还没有配置水平弹性伸缩,HPA 会自动扩缩容目标 Deployment。",
850
- tableProps: { size: "middle" }
851
- }
852
- ),
853
- /* @__PURE__ */ e(
854
- Le,
855
- {
856
- title: C ? "编辑 HPA" : "新建 HPA",
857
- open: y,
858
- onOk: _,
859
- onCancel: () => h(!1),
860
- children: /* @__PURE__ */ s(L, { form: a, layout: "vertical", children: [
861
- /* @__PURE__ */ e(L.Item, { name: "namespace", label: "命名空间", rules: [{ required: !0 }], children: /* @__PURE__ */ e(te, { disabled: C }) }),
862
- /* @__PURE__ */ e(L.Item, { name: "name", label: "HPA 名称", rules: [{ required: !0 }], children: /* @__PURE__ */ e(te, { disabled: C }) }),
863
- /* @__PURE__ */ e(L.Item, { name: "deploymentName", label: "目标 Deployment", rules: [{ required: !0 }], children: /* @__PURE__ */ e(te, { disabled: C, placeholder: "namespace/deploymentName" }) }),
864
- /* @__PURE__ */ s(x, { children: [
865
- /* @__PURE__ */ e(L.Item, { name: "minReplicas", label: "最小副本", rules: [{ required: !0 }], children: /* @__PURE__ */ e(ne, { min: 0, max: 100 }) }),
866
- /* @__PURE__ */ e(L.Item, { name: "maxReplicas", label: "最大副本", rules: [{ required: !0 }], children: /* @__PURE__ */ e(ne, { min: 1, max: 100 }) })
867
- ] }),
868
- /* @__PURE__ */ e(L.Item, { name: "cpuTarget", label: "CPU 目标 (%)", children: /* @__PURE__ */ e(ne, { min: 1, max: 100 }) })
869
- ] })
870
- }
871
- )
872
- ] });
873
- }, oe = [
874
- {
875
- title: "DevOps 运维",
876
- icon: /* @__PURE__ */ e(H, {}),
877
- items: [
878
- {
879
- key: "devops-dashboard",
880
- label: "运维总览",
881
- icon: /* @__PURE__ */ e(q, {}),
882
- path: "/ops/devops/dashboard",
883
- desc: "集群概览与资源统计"
884
- },
885
- {
886
- key: "devops-nodes",
887
- label: "节点管理",
888
- icon: /* @__PURE__ */ e(H, {}),
889
- path: "/ops/devops/nodes",
890
- desc: "K8s 节点列表与状态"
891
- },
892
- {
893
- key: "devops-pods",
894
- label: "Pod 管理",
895
- icon: /* @__PURE__ */ e(Se, {}),
896
- path: "/ops/devops/pods",
897
- desc: "Pod 列表、日志、终端"
898
- },
899
- {
900
- key: "devops-hpa",
901
- label: "弹性伸缩",
902
- icon: /* @__PURE__ */ e(A, {}),
903
- path: "/ops/devops/hpa",
904
- desc: "HPA 自动扩缩容策略"
905
- },
906
- {
907
- key: "devops-registry",
908
- label: "镜像仓库",
909
- icon: /* @__PURE__ */ e(A, {}),
910
- path: "/ops/devops/registry",
911
- desc: "容器镜像统一管理"
912
- },
913
- {
914
- key: "devops-pipeline",
915
- label: "流水线",
916
- icon: /* @__PURE__ */ e(ie, {}),
917
- path: "/ops/devops/pipeline",
918
- desc: "CI/CD 流水线编排"
919
- },
920
- {
921
- key: "devops-release",
922
- label: "发布管理",
923
- icon: /* @__PURE__ */ e(We, {}),
924
- path: "/ops/devops/release",
925
- desc: "应用发布与回滚"
926
- },
927
- {
928
- key: "devops-monitor",
929
- label: "监控告警",
930
- icon: /* @__PURE__ */ e(je, {}),
931
- path: "/ops/devops/monitor",
932
- desc: "Prometheus/Grafana 监控"
933
- },
934
- {
935
- key: "devops-logs",
936
- label: "日志管理",
937
- icon: /* @__PURE__ */ e(ae, {}),
938
- path: "/ops/devops/logs",
939
- desc: "Loki 集中日志查询"
940
- },
941
- {
942
- key: "devops-dba",
943
- label: "DBA 工单",
944
- icon: /* @__PURE__ */ e(V, {}),
945
- path: "/ops/devops/dba",
946
- desc: "数据库运维工单"
947
- }
948
- ]
949
- },
950
- {
951
- title: "基础设施",
952
- icon: /* @__PURE__ */ e(H, {}),
953
- items: [
954
- {
955
- key: "ops-channel",
956
- label: "渠道管理",
957
- icon: /* @__PURE__ */ e(Ve, {}),
958
- path: "/ops/channel",
959
- desc: "部署渠道配置与管理"
960
- },
961
- {
962
- key: "ops-env",
963
- label: "环境管理",
964
- icon: /* @__PURE__ */ e(A, {}),
965
- path: "/ops/delivery",
966
- desc: "运行环境配置与管理"
967
- },
968
- {
969
- key: "ops-deploy",
970
- label: "部署管理",
971
- icon: /* @__PURE__ */ e(de, {}),
972
- path: "/ops/deployment",
973
- desc: "应用部署与发布管理"
974
- },
975
- {
976
- key: "ops-repo",
977
- label: "仓库管理",
978
- icon: /* @__PURE__ */ e(V, {}),
979
- path: "/ops/repo-mgmt",
980
- desc: "代码仓库与镜像管理"
981
- }
982
- ]
983
- },
984
- {
985
- title: "配置中心",
986
- icon: /* @__PURE__ */ e(pe, {}),
987
- items: [
988
- {
989
- key: "config-list",
990
- label: "配置列表",
991
- icon: /* @__PURE__ */ e(J, {}),
992
- path: "/config/list",
993
- desc: "集中配置项的查询、编辑与发布"
994
- },
995
- {
996
- key: "config-history",
997
- label: "变更历史",
998
- icon: /* @__PURE__ */ e(Je, {}),
999
- path: "/config/history",
1000
- desc: "配置变更记录与版本回溯"
1001
- },
1002
- {
1003
- key: "config-service",
1004
- label: "服务列表",
1005
- icon: /* @__PURE__ */ e(H, {}),
1006
- path: "/config/service",
1007
- desc: "接入配置的客户端服务管理"
1008
- },
1009
- {
1010
- key: "config-cluster",
1011
- label: "集群概览",
1012
- icon: /* @__PURE__ */ e(q, {}),
1013
- path: "/config/cluster",
1014
- desc: "配置中心集群节点与状态总览"
1015
- },
1016
- {
1017
- key: "config-namespace",
1018
- label: "命名空间 / 灰度",
1019
- icon: /* @__PURE__ */ e(Ze, {}),
1020
- path: "/config/namespace",
1021
- desc: "命名空间与灰度发布(孵化中)"
1022
- }
1023
- ]
1024
- },
1025
- {
1026
- title: "密钥中心",
1027
- icon: /* @__PURE__ */ e(Z, {}),
1028
- items: [
1029
- {
1030
- key: "mist-secret",
1031
- label: "密钥管理",
1032
- icon: /* @__PURE__ */ e(Z, {}),
1033
- path: "/mist/secret",
1034
- desc: "z-mist 密钥台账(只读孵化)"
1035
- },
1036
- {
1037
- key: "mist-app",
1038
- label: "应用接入",
1039
- icon: /* @__PURE__ */ e(se, {}),
1040
- path: "/mist/app",
1041
- desc: "接入应用与 appSecret 台账"
1042
- },
1043
- {
1044
- key: "mist-acl",
1045
- label: "密钥授权",
1046
- icon: /* @__PURE__ */ e(Qe, {}),
1047
- path: "/mist/acl",
1048
- desc: "哪个应用能读哪个密钥 + 在线校验"
1049
- }
1050
- ]
1051
- },
1052
- {
1053
- title: "元数据中心",
1054
- icon: /* @__PURE__ */ e(he, {}),
1055
- items: [
1056
- {
1057
- key: "meta-app",
1058
- label: "应用元数据",
1059
- icon: /* @__PURE__ */ e(se, {}),
1060
- path: "/meta/app",
1061
- desc: "z-meta 应用台账"
1062
- },
1063
- {
1064
- key: "meta-tenant",
1065
- label: "租户管理",
1066
- icon: /* @__PURE__ */ e(Ye, {}),
1067
- path: "/meta/tenant",
1068
- desc: "z-meta 租户台账"
1069
- },
1070
- {
1071
- key: "meta-dict",
1072
- label: "数据字典",
1073
- icon: /* @__PURE__ */ e(me, {}),
1074
- path: "/meta/dict",
1075
- desc: "字典类型与字典项"
1076
- },
1077
- {
1078
- key: "meta-interface",
1079
- label: "接口台账",
1080
- icon: /* @__PURE__ */ e(ue, {}),
1081
- path: "/meta/interface",
1082
- desc: "登记在册的业务接口"
1083
- },
1084
- {
1085
- key: "meta-private-config",
1086
- label: "私有配置",
1087
- icon: /* @__PURE__ */ e(pe, {}),
1088
- path: "/meta/private-config",
1089
- desc: "应用私有键值配置"
1090
- },
1091
- {
1092
- key: "meta-models",
1093
- label: "业务模型",
1094
- icon: /* @__PURE__ */ e(ce, {}),
1095
- path: "/meta/models",
1096
- desc: "结构化业务模型与字段"
1097
- }
1098
- ]
1099
- },
1100
- {
1101
- title: "消息中心",
1102
- icon: /* @__PURE__ */ e(xe, {}),
1103
- items: [
1104
- {
1105
- key: "msg-inbox",
1106
- label: "站内信",
1107
- icon: /* @__PURE__ */ e(ye, {}),
1108
- path: "/msg/inbox",
1109
- desc: "当前用户的收件箱"
1110
- },
1111
- {
1112
- key: "msg-template",
1113
- label: "消息模板",
1114
- icon: /* @__PURE__ */ e(me, {}),
1115
- path: "/msg/template",
1116
- desc: "按渠道/业务类型维护模板"
1117
- },
1118
- {
1119
- key: "msg-delivery",
1120
- label: "投递日志",
1121
- icon: /* @__PURE__ */ e(ae, {}),
1122
- path: "/msg/delivery",
1123
- desc: "投递结果、失败原因与统计"
1124
- },
1125
- {
1126
- key: "msg-batch",
1127
- label: "批量任务",
1128
- icon: /* @__PURE__ */ e(J, {}),
1129
- path: "/msg/batch",
1130
- desc: "批量发送进度与成败"
1131
- }
1132
- ]
1133
- },
1134
- {
1135
- title: "服务注册",
1136
- icon: /* @__PURE__ */ e(Xe, {}),
1137
- items: [
1138
- {
1139
- key: "rpc-service",
1140
- label: "服务列表",
1141
- icon: /* @__PURE__ */ e(H, {}),
1142
- path: "/rpc/service",
1143
- desc: "RPC 注册表(z-rpc 视角 / z-config naming 数据源)"
1144
- },
1145
- {
1146
- key: "rpc-instance",
1147
- label: "服务实例",
1148
- icon: /* @__PURE__ */ e(A, {}),
1149
- path: "/rpc/instance",
1150
- desc: "按服务名展开实例与健康状态"
1151
- }
1152
- ]
1153
- },
1154
- {
1155
- title: "向量检索",
1156
- icon: /* @__PURE__ */ e(V, {}),
1157
- items: [
1158
- {
1159
- key: "vector-collection",
1160
- label: "向量集合",
1161
- icon: /* @__PURE__ */ e(ge, {}),
1162
- path: "/vector/collections",
1163
- desc: "z-vector 集合台账:维度 / 度量 / 索引 / 向量数"
1164
- },
1165
- {
1166
- key: "vector-search",
1167
- label: "向量检索",
1168
- icon: /* @__PURE__ */ e(be, {}),
1169
- path: "/vector/search",
1170
- desc: "top-k ANN 查询,渲染后端给的命中距离"
1171
- },
1172
- {
1173
- key: "vector-instance",
1174
- label: "实例与端口",
1175
- icon: /* @__PURE__ */ e(A, {}),
1176
- path: "/vector/instance",
1177
- desc: "内嵌 Qdrant REST 服务的 bind 状态(区分「没起」和「没数据」)"
1178
- }
1179
- ]
1180
- },
1181
- {
1182
- title: "图数据库",
1183
- icon: /* @__PURE__ */ e(he, {}),
1184
- items: [
1185
- {
1186
- key: "graph-schema",
1187
- label: "图 Schema",
1188
- icon: /* @__PURE__ */ e(ge, {}),
1189
- path: "/graph/schema",
1190
- desc: "z-graph 点类型 / 边类型 / 属性索引(/api/graph/meta/schema)"
1191
- },
1192
- {
1193
- key: "graph-query",
1194
- label: "图查询",
1195
- icon: /* @__PURE__ */ e(et, {}),
1196
- path: "/graph/query",
1197
- desc: "Cypher 执行 + 执行计划,写语句二次确认(/api/graph/query)"
1198
- },
1199
- {
1200
- key: "graph-branches",
1201
- label: "分支与提交",
1202
- icon: /* @__PURE__ */ e(ie, {}),
1203
- path: "/graph/branches",
1204
- desc: "Git 式版本面:分支 head 与全量 commit 图(/api/graph/meta/{branches,commits})"
1205
- },
1206
- {
1207
- key: "graph-instance",
1208
- label: "实例与端口",
1209
- icon: /* @__PURE__ */ e(A, {}),
1210
- path: "/graph/instance",
1211
- desc: "内嵌 GraphControlServer 的 bind 状态 + 外来监听者判定(区分「没起」和「没数据」)"
1212
- }
1213
- ]
1214
- },
1215
- {
1216
- title: "网关",
1217
- icon: /* @__PURE__ */ e(ue, {}),
1218
- items: [
1219
- {
1220
- key: "gw-routes",
1221
- label: "网关路由",
1222
- icon: /* @__PURE__ */ e(J, {}),
1223
- path: "/gw/routes",
1224
- desc: "z-gw 在线路由表:谓词 / 过滤器 / order / 启停"
1225
- },
1226
- {
1227
- key: "gw-metrics",
1228
- label: "网关指标",
1229
- icon: /* @__PURE__ */ e(q, {}),
1230
- path: "/gw/metrics",
1231
- desc: "zgw.* 请求计数与平均 RT(附 micrometer 桥自证)"
1232
- },
1233
- {
1234
- key: "gw-instance",
1235
- label: "实例与面",
1236
- icon: /* @__PURE__ */ e(A, {}),
1237
- path: "/gw/instance",
1238
- desc: "admin 面接没接通 / Netty 9090 通不通 / 指标桥看不看得见"
1239
- }
1240
- ]
1241
- },
1242
- {
1243
- title: "缓存",
1244
- icon: /* @__PURE__ */ e(V, {}),
1245
- items: [
1246
- {
1247
- key: "cache-overview",
1248
- label: "缓存总览",
1249
- icon: /* @__PURE__ */ e(se, {}),
1250
- path: "/cache/overview",
1251
- desc: "z-cache 双路对账:进程内 MemoryStore ∥ zCacheClient,分歧即警报"
1252
- },
1253
- {
1254
- key: "cache-keys",
1255
- label: "键浏览",
1256
- icon: /* @__PURE__ */ e(be, {}),
1257
- path: "/cache/keys",
1258
- desc: "只读 SCAN/KEYS + TTL;命令名不接受外部输入(无 FLUSHALL 类按钮)"
1259
- },
1260
- {
1261
- key: "cache-stats",
1262
- label: "命中率与热键",
1263
- icon: /* @__PURE__ */ e(q, {}),
1264
- path: "/cache/stats",
1265
- desc: "hits/misses/evictions + accessCount/lfuCounter 热键视图"
1266
- },
1267
- {
1268
- key: "cache-instance",
1269
- label: "实例与端口",
1270
- icon: /* @__PURE__ */ e(A, {}),
1271
- path: "/cache/instance",
1272
- desc: "内嵌 RedisServer bind 上了没 / 6379 上应答的是谁"
1273
- }
1274
- ]
1275
- },
1276
- {
1277
- title: "消息队列",
1278
- icon: /* @__PURE__ */ e(ye, {}),
1279
- items: [
1280
- {
1281
- key: "mq-instance",
1282
- label: "实例与端口",
1283
- icon: /* @__PURE__ */ e(A, {}),
1284
- path: "/mq/instance",
1285
- desc: "子进程活着 ≠ 端口归它:z-mq 内嵌是 spawn,归属按子进程 PID 判"
1286
- },
1287
- {
1288
- key: "mq-cluster",
1289
- label: "集群与 Broker",
1290
- icon: /* @__PURE__ */ e(H, {}),
1291
- path: "/mq/cluster",
1292
- desc: "NameServer 码 4 brokerAddrTable(记的是「谁发过心跳」,不是「谁在跑」)"
1293
- },
1294
- {
1295
- key: "mq-topics",
1296
- label: "Topic 列表",
1297
- icon: /* @__PURE__ */ e(J, {}),
1298
- path: "/mq/topics",
1299
- desc: "NameServer 码 8 ∥ Broker 码 8 并排 + 按需码 3 路由详情"
1300
- },
1301
- {
1302
- key: "mq-broker",
1303
- label: "Broker 元数据",
1304
- icon: /* @__PURE__ */ e(de, {}),
1305
- path: "/mq/broker",
1306
- desc: "码 320/321/322/323/324;上游 MVP 恒空的那几格挂原文不挂假表"
1307
- }
1308
- ]
1309
- },
1310
- {
1311
- title: "知识库",
1312
- icon: /* @__PURE__ */ e(Q, {}),
1313
- items: [
1314
- {
1315
- key: "kb-workspace",
1316
- label: "工作空间",
1317
- icon: /* @__PURE__ */ e(Q, {}),
1318
- path: "/kb/workspaces",
1319
- desc: "知识库工作空间管理"
1320
- },
1321
- {
1322
- key: "kb-documents",
1323
- label: "文档管理",
1324
- icon: /* @__PURE__ */ e(Q, {}),
1325
- path: "/kb/documents",
1326
- desc: "知识库文档列表与管理"
1327
- },
1328
- {
1329
- key: "kb-search",
1330
- label: "知识搜索",
1331
- icon: /* @__PURE__ */ e(Q, {}),
1332
- path: "/kb/search",
1333
- desc: "统一知识搜索"
1334
- }
1335
- ]
1336
- },
1337
- {
1338
- title: "对象存储",
1339
- icon: /* @__PURE__ */ e(ce, {}),
1340
- items: [
1341
- {
1342
- key: "oss-buckets",
1343
- label: "Bucket 列表",
1344
- icon: /* @__PURE__ */ e(ce, {}),
1345
- path: "/oss/buckets",
1346
- desc: "GET /api/oss-admin/buckets · z-oss IOssBucketService#listUserBuckets(只读)"
1347
- },
1348
- {
1349
- key: "oss-objects",
1350
- label: "对象浏览",
1351
- icon: /* @__PURE__ */ e(ae, {}),
1352
- path: "/oss/objects",
1353
- desc: "对象数/总大小来自 IOssObjectService,physicalExists 来自 IOssBucketService,两栏分开显示"
1354
- },
1355
- {
1356
- key: "oss-account",
1357
- label: "访问身份",
1358
- icon: /* @__PURE__ */ e(Z, {}),
1359
- path: "/oss/account",
1360
- desc: "平台账号 → z_oss_user 映射;未开户显式报 409,不退化成空表"
1361
- }
1362
- ]
1363
- },
1364
- {
1365
- title: "脚本中心",
1366
- icon: /* @__PURE__ */ e(st, {}),
1367
- items: [
1368
- {
1369
- key: "script-keys",
1370
- label: "API Key 台账",
1371
- icon: /* @__PURE__ */ e(Z, {}),
1372
- path: "/script/keys",
1373
- desc: "GET /api/script/api-key/page · 刻意不渲染 api_key / api_secret_hash 两列(见 TASK-20260925-031)"
1374
- },
1375
- {
1376
- key: "script-monitor",
1377
- label: "调用监控",
1378
- icon: /* @__PURE__ */ e(q, {}),
1379
- path: "/script/monitor",
1380
- desc: "GET /api/script/invoke-log/page + /stats/trend · 实测 124 行日志 / 7 天趋势"
1381
- },
1382
- {
1383
- key: "script-quota",
1384
- label: "配额与用量",
1385
- icon: /* @__PURE__ */ e(tt, {}),
1386
- path: "/script/quota",
1387
- desc: "GET /api/script/quota/by-api-key/{id} · 日用量进度条(配额值是字符串,已 Number())"
1388
- },
1389
- {
1390
- key: "script-version",
1391
- label: "脚本版本",
1392
- icon: /* @__PURE__ */ e(nt, {}),
1393
- path: "/script/version",
1394
- desc: "GET /api/script/version/list/{scriptId} · 按脚本主表 ID 查,状态是字符串枚举"
1395
- },
1396
- {
1397
- key: "script-tag",
1398
- label: "标签治理",
1399
- icon: /* @__PURE__ */ e(at, {}),
1400
- path: "/script/tag",
1401
- desc: "GET /api/script/tag/list · 3 条标签,颜色取 tag_color(回退 color)"
1402
- }
1403
- ]
1404
- },
1405
- {
1406
- title: "资源管理",
1407
- icon: /* @__PURE__ */ e(A, {}),
1408
- items: [
1409
- {
1410
- key: "resource",
1411
- label: "资源管理",
1412
- icon: /* @__PURE__ */ e(A, {}),
1413
- path: "/resource/domain",
1414
- desc: "域名、ECS、RDS、OSS 管理"
1415
- }
1416
- ]
1417
- }
1418
- ];
1419
- function Qt() {
1420
- return /* @__PURE__ */ s("div", { className: f.empty, children: [
1421
- /* @__PURE__ */ e("div", { className: f.emptyIcon, children: "⚙️" }),
1422
- /* @__PURE__ */ e("div", { className: f.emptyText, children: "请从左侧菜单选择运维模块" })
1423
- ] });
1424
- }
1425
- function B({ label: t }) {
1426
- return /* @__PURE__ */ s("div", { style: { padding: 40, textAlign: "center", color: "#999" }, children: [
1427
- /* @__PURE__ */ s("h2", { children: [
1428
- "🚧 ",
1429
- t
1430
- ] }),
1431
- /* @__PURE__ */ e("p", { children: "功能开发中..." })
1432
- ] });
1433
- }
1434
- function Yt({ label: t, reason: c }) {
1435
- return /* @__PURE__ */ s("div", { style: { padding: 40, textAlign: "center", color: "#999" }, children: [
1436
- /* @__PURE__ */ s("h2", { children: [
1437
- "🧪 ",
1438
- t
1439
- ] }),
1440
- /* @__PURE__ */ e("p", { style: { maxWidth: 760, margin: "0 auto", textAlign: "left", lineHeight: 1.7 }, children: c || "功能孵化中..." })
1441
- ] });
1442
- }
1443
- function Xt({ label: t, reason: c, message: i = "该页面未孵化,因为后端接口尚不可用" }) {
1444
- return /* @__PURE__ */ s("div", { style: { padding: 40, maxWidth: 720, margin: "0 auto" }, children: [
1445
- /* @__PURE__ */ s("h2", { style: { textAlign: "center" }, children: [
1446
- "🧪 ",
1447
- t
1448
- ] }),
1449
- /* @__PURE__ */ e(
1450
- X,
1451
- {
1452
- type: "warning",
1453
- showIcon: !0,
1454
- message: i,
1455
- description: c
1456
- }
1457
- )
1458
- ] });
1459
- }
1460
- function N({ label: t }) {
1461
- return /* @__PURE__ */ e(
1462
- Xt,
1463
- {
1464
- label: t,
1465
- message: "该页面未孵化,因为组件从来不在本仓",
1466
- reason: "组件从未迁进本仓:z-opc 的 src 目录下没有这个组件,历史上也没有任何提交 import 过它(OPS_ROUTES 里留着一个解析不到的标识符)。要恢复这一页,得先把组件从 z-ops 迁进来并接上它自己的后端;在那之前这里刻意不放假表格。"
1467
- }
1468
- );
1469
- }
1470
- const fe = [
1471
- // ─── 运维中心 ───
1472
- // ⚠ 这一族路由的组件从来没有从 z-ops 迁进来(见 UnmigratedPage 注释)。原先直接写
1473
- // <ChannelPage/> 之类会在**模块求值期**抛 ReferenceError 并白屏整个前端,不是只坏这一页。
1474
- { path: "/ops", element: /* @__PURE__ */ e(S, { to: "/ops/devops", replace: !0 }) },
1475
- { path: "/ops/channel", element: /* @__PURE__ */ e(N, { label: "渠道管理" }) },
1476
- { path: "/ops/delivery", element: /* @__PURE__ */ e(N, { label: "环境管理" }) },
1477
- { path: "/ops/deployment", element: /* @__PURE__ */ e(N, { label: "部署管理" }) },
1478
- { path: "/ops/deployment/:id", element: /* @__PURE__ */ e(N, { label: "部署管理" }) },
1479
- { path: "/ops/repo-mgmt", element: /* @__PURE__ */ e(N, { label: "仓库管理" }) },
1480
- { path: "/ops/git-platform", element: /* @__PURE__ */ e(N, { label: "仓库管理" }) },
1481
- // ─── DevOps 子路由 (从 OpsK8s 直接渲染) ───
1482
- { path: "/ops/devops", element: /* @__PURE__ */ e(ke, {}) },
1483
- { path: "/ops/devops/dashboard", element: /* @__PURE__ */ e(ke, {}) },
1484
- { path: "/ops/devops/nodes", element: /* @__PURE__ */ e(Ut, {}) },
1485
- { path: "/ops/devops/pods", element: /* @__PURE__ */ e(Jt, {}) },
1486
- { path: "/ops/devops/hpa", element: /* @__PURE__ */ e(Zt, {}) },
1487
- { path: "/ops/devops/registry", element: /* @__PURE__ */ e(B, { label: "镜像仓库" }) },
1488
- { path: "/ops/devops/pipeline", element: /* @__PURE__ */ e(B, { label: "流水线" }) },
1489
- { path: "/ops/devops/release", element: /* @__PURE__ */ e(B, { label: "发布管理" }) },
1490
- { path: "/ops/devops/monitor", element: /* @__PURE__ */ e(B, { label: "监控告警" }) },
1491
- { path: "/ops/devops/logs", element: /* @__PURE__ */ e(B, { label: "日志管理" }) },
1492
- { path: "/ops/devops/dba", element: /* @__PURE__ */ e(B, { label: "DBA 工单" }) },
1493
- // ─── 配置中心 ───
1494
- // 精确条目在前 (菜单点击的精确 path, 优先命中以避免被通配覆盖)
1495
- { path: "/config", element: /* @__PURE__ */ e(S, { to: "/config/list", replace: !0 }) },
1496
- // 配置中心 — 命名空间: 占位,但**理由是量出来的**(2026-10-22 复测,见 TASK-20260925-036):
1497
- // ⚠️ 2026-10-22 之前这一格写的是"缺表 / 缺数据源",**那一版理由已作废**(实测反了),现况如下:
1498
- // ① 数据源**已经有了**:GET /api/namespace/list 实测 200 ⇒ 1 行(namespace_id=DEFAULT_NAMESPACE);
1499
- // 共享 oc 库里 z_namespace 等 8 张表 + z_config_info.encrypted_data_key 列都在
1500
- // (z_namespace 的 information_schema create_time = 2026-10-03 23:02:14;
1501
- // 2026-10-22 本卡把升级脚本的种子行也补齐了,见 TASK-20260925-036)。
1502
- // ② 现在缺的不是数据,是**路由**:真正的命名空间页在 component 的 /z-config/namespace
1503
- // (z-config-component/src/pages/namespace/NamespaceList.jsx);
1504
- // 而 /config/* 这条链走的是 ConfigApp(z-config-component/src/pages/ConfigApp.jsx),
1505
- // 它的 <Routes> 里**没有 namespace 这一条** ⇒ 这里只能占位。
1506
- // 把占位换成真页面 = 给 ConfigApp 加一条 namespace 路由(z-config component 的路由改动,
1507
- // 不在本卡授权范围,见该卡「交接」);另外那一页的列名还是 camelCase(namespaceId),
1508
- // 而实测响应是 snake_case(namespace_id)⇒ 接真页面前要先修列名,否则又是一个恒空的假绿列。
1509
- // ③ 灰度发布这一半仍然没有落点:L3 里灰度是 ZConfigTagRelation 那一族,
1510
- // 而它就在「从未进制品」的那 9 个 controller 里。
1511
- {
1512
- path: "/config/namespace",
1513
- element: /* @__PURE__ */ e(
1514
- Yt,
1515
- {
1516
- label: "命名空间 / 灰度",
1517
- reason: "缺的不是数据,是路由:命名空间的数据源已经有了 —— GET /api/namespace/list 实测 200 且有 1 行(共享 oc 库的 z_namespace 等 8 张表与 z_config_info.encrypted_data_key 列都在,z_namespace 的information_schema create_time = 2026-10-03 23:02:14;2026-10-22 又把升级脚本的种子行补齐,见 TASK-20260925-036)。真正的命名空间页在 component 的 /z-config/namespace,而 /config/* 走 ConfigApp(z-config-component/src/pages/ConfigApp.jsx),它的路由表里没有 namespace 这一条 ⇒ 这里只能占位;接真页面 = 给 ConfigApp 加一条 namespace 路由,详见 TASK-20260925-036。灰度发布这一半仍无落点:L3 里灰度是 ZConfigTagRelation 那一族,它就在「从未进制品」的那 9 个 controller 里。"
1518
- }
1519
- )
1520
- },
1521
- // 通配兜底: 其余 /config/* (list / history / service / cluster / edit / dashboard 等) 全部交给 ConfigApp 内部路由
1522
- { path: "/config/*", element: /* @__PURE__ */ e(ct, {}) },
1523
- // ─── 密钥中心 ───
1524
- { path: "/mist", element: /* @__PURE__ */ e(S, { to: "/mist/secret", replace: !0 }) },
1525
- { path: "/mist/*", element: /* @__PURE__ */ e(ot, {}) },
1526
- // ─── 元数据中心 (z-meta) ───
1527
- // 子模块自带相对路由 <Routes>, 由 /meta/* 通配把剩余路径交给它
1528
- { path: "/meta", element: /* @__PURE__ */ e(S, { to: "/meta/app", replace: !0 }) },
1529
- { path: "/meta/*", element: /* @__PURE__ */ e(rt, {}) },
1530
- // ─── 消息中心 (z-msg) ───
1531
- { path: "/msg", element: /* @__PURE__ */ e(S, { to: "/msg/inbox", replace: !0 }) },
1532
- { path: "/msg/*", element: /* @__PURE__ */ e(lt, {}) },
1533
- // ─── 服务注册 (z-rpc, 数据源是 z-config 的 naming) ───
1534
- { path: "/rpc", element: /* @__PURE__ */ e(S, { to: "/rpc/service", replace: !0 }) },
1535
- { path: "/rpc/*", element: /* @__PURE__ */ e(it, {}) },
1536
- // ─── 向量检索 (z-vector) ───
1537
- // REST 面是内嵌 QdrantRestServer(非 Spring MVC),经 z-opc 的 /api/vector/** 代理出去
1538
- { path: "/vector", element: /* @__PURE__ */ e(S, { to: "/vector/collections", replace: !0 }) },
1539
- { path: "/vector/*", element: /* @__PURE__ */ e(dt, {}) },
1540
- // ─── 图数据库 (z-graph) ───
1541
- // REST 面是内嵌 GraphControlServer(JDK HttpServer,非 Spring MVC),经 z-opc 的 /api/graph/** 代理出去
1542
- // ⚠ 内嵌端口是 8091 不是 8090:8090 归一个外部进程,且被 BizKnowledgeGraphService 当业务依赖在用
1543
- { path: "/graph", element: /* @__PURE__ */ e(S, { to: "/graph/schema", replace: !0 }) },
1544
- { path: "/graph/*", element: /* @__PURE__ */ e(pt, {}) },
1545
- // ─── 网关 (z-gw) ───
1546
- // admin 面是 z-gw-admin 的原生 Spring MVC(pom 加 io.github.yuku123:z-gw-admin 后挂 /gw/admin/**,12 条 handler);
1547
- // 页面不直连裸 /gw/admin(不在 sso.intercept-paths 内),一律走 z-opc 自己的环回代理 GET /api/gw/**
1548
- { path: "/gw", element: /* @__PURE__ */ e(S, { to: "/gw/routes", replace: !0 }) },
1549
- { path: "/gw/*", element: /* @__PURE__ */ e(mt, {}) },
1550
- // ─── 缓存 (z-cache) ───
1551
- // z-cache 只有 RESP over TCP(:6379),没有 HTTP 管理面 ⇒ /api/cache/** 不是转发器,
1552
- // 是 CacheProxyController 在 JVM 内读 MemoryStore + 用现成 zCacheClient 发只读命令拼出来的结构化 JSON。
1553
- { path: "/cache", element: /* @__PURE__ */ e(S, { to: "/cache/overview", replace: !0 }) },
1554
- { path: "/cache/*", element: /* @__PURE__ */ e(ut, {}) },
1555
- // ─── 消息队列 (z-mq) ───
1556
- // :9877/:10912 是 z-mq-remoting 的 Netty 私有二进制协议(端口从 9876/10911 挪开,那两个被旧世代孤儿 JVM 占着)
1557
- // ⇒ /api/mq/** 是「固定只读请求码 → JSON」的协议适配器,端点穷举,未列出的子路径一律 404 并回显可用清单
1558
- { path: "/mq", element: /* @__PURE__ */ e(S, { to: "/mq/instance", replace: !0 }) },
1559
- { path: "/mq/*", element: /* @__PURE__ */ e(ht, {}) },
1560
- // ─── 知识库 (z-kb) — 主机侧确定性装配,接口真通(2026-09-25 实测) ───
1561
- // 09-25 早先"页面在、/api/kb/** 全 404"的判断已被推翻:404 的根因是 z-kb 的自动装配清单错位
1562
- // (4 条 .imports 路径不存在 + 2 份无 key 的 spring.factories + z-kb-web 压根没有登记),
1563
- // 而不是"前端把 404 读成空列表"——src/kb/services/api.js 有自己的 fetch 包装,!res.ok 直接 throw,
1564
- // 三个页面都渲染"接口错误:{message}"。
1565
- // 现由 KbAssemblyConfig 在 host 侧 @Import 五个 AutoConfiguration + @ComponentScan controller,
1566
- // 并用一个 BFPP 把 z-kb 的 @Bean 产物改名(避让别的模块按 @Resource 字段名注入到同名 bean 上)。
1567
- // 实测:/kb/workspaces 1 行(314 篇/8746 实体/60479 关系)、/kb/documents 服务端分页 20 条 × 16 页、
1568
- // /kb/search FUSION 10 命中 + GRAPH 4 命中;向量召回恒 0 是 L3 读写两侧集合名不一致(见 SearchPage 的告警条)。
1569
- { path: "/kb", element: /* @__PURE__ */ e(S, { to: "/kb/workspaces", replace: !0 }) },
1570
- { path: "/kb/*", element: /* @__PURE__ */ e(gt, {}) },
1571
- // ─── 对象存储 (z-oss) — TASK-003: 走 z-opc 侧 /api/oss-admin/**,不再需要 AK/SK 下发 ───
1572
- // z-oss 原生 /api/v1/** 的 AuthenticationInterceptor 要 X-Zoss-Access-Key/Secret-Key(实测带平台会话仍 401),
1573
- // 浏览器侧没有凭证下发通道;OssAdminController 改为在同一 JVM 内直接调 IOssBucketService/IOssObjectService,
1574
- // 鉴权用平台 SSO + username→z_oss_user 映射,且只有 @GetMapping(无写入口)。
1575
- // 刻意不接 E2EAliasController 的 /api/oss/list(异常吞成空列表)与 /api/oss/{bucket}(硬编码 stub 零值)。
1576
- { path: "/oss", element: /* @__PURE__ */ e(S, { to: "/oss/buckets", replace: !0 }) },
1577
- { path: "/oss/*", element: /* @__PURE__ */ e(yt, {}) },
1578
- // ─── 脚本中心 (z-script) ───
1579
- // 组件自带 5 个 Tab,这里按"一个能力一条菜单"把 Tab 键透传成 initialTab,
1580
- // 而不是给每个 Tab 复刻一份页面组件。
1581
- // ⚠️ 只挂这 5 个 Tab:脚本清单页(System 面的 /script/manage)刻意不接进运维面 ——
1582
- // 它的数据源 /api/script/list 在部署制品里被 z-script 自己的 ApiKeyAuthInterceptor 拦着,
1583
- // 带平台会话也是 401,而共用 axios 拦截器把任何 401 当会话过期 ⇒ 一点进来就被踢到 /login。
1584
- // 在那条链修好之前(TASK-20260925-032),把它放进菜单等于在运维面埋一个登出陷阱。
1585
- { path: "/script", element: /* @__PURE__ */ e(S, { to: "/script/monitor", replace: !0 }) },
1586
- { path: "/script/keys", element: /* @__PURE__ */ e(K, { initialTab: "apikey" }) },
1587
- { path: "/script/monitor", element: /* @__PURE__ */ e(K, { initialTab: "monitor" }) },
1588
- { path: "/script/quota", element: /* @__PURE__ */ e(K, { initialTab: "quota" }) },
1589
- { path: "/script/version", element: /* @__PURE__ */ e(K, { initialTab: "version" }) },
1590
- { path: "/script/tag", element: /* @__PURE__ */ e(K, { initialTab: "tag" }) },
1591
- { path: "/script/*", element: /* @__PURE__ */ e(S, { to: "/script/monitor", replace: !0 }) },
1592
- // ─── 资源管理 ───
1593
- { path: "/resource", element: /* @__PURE__ */ e(S, { to: "/resource/domain", replace: !0 }) },
1594
- { path: "/resource/domain", element: /* @__PURE__ */ e(N, { label: "域名管理" }) },
1595
- { path: "/resource/ecs", element: /* @__PURE__ */ e(N, { label: "ECS 管理" }) },
1596
- { path: "/resource/rds", element: /* @__PURE__ */ e(N, { label: "RDS 管理" }) },
1597
- { path: "/resource/oss", element: /* @__PURE__ */ e(N, { label: "OSS 管理" }) }
1598
- ];
1599
- function en(t) {
1600
- for (const c of fe)
1601
- if (c.path === t) return c.element;
1602
- for (const c of fe)
1603
- if (c.path.includes("*") || c.path.includes(":")) {
1604
- const i = "^" + c.path.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, "[^/]+") + "$";
1605
- if (new RegExp(i).test(t)) return c.element;
1606
- }
1607
- return /* @__PURE__ */ e(Qt, {});
1608
- }
1609
- function wn({
1610
- activePathOverride: t,
1611
- menuOnly: c = !1
1612
- } = {}) {
1613
- const i = Ae(), { pathname: d } = Te(), [m, u] = p(
1614
- new Set(oe.map((a) => a.title))
1615
- ), y = le(() => {
1616
- const a = t ?? d;
1617
- for (const o of oe)
1618
- for (const r of o.items)
1619
- if (r.path === a) return r.key;
1620
- return null;
1621
- }, [t, d]), h = (a) => {
1622
- u((o) => {
1623
- const r = new Set(o);
1624
- return r.has(a) ? r.delete(a) : r.add(a), r;
1625
- });
1626
- }, C = (a) => {
1627
- i(`${a.path}?mode=ops`);
1628
- }, k = le(() => en(d), [d]);
1629
- return /* @__PURE__ */ s("div", { className: f.shell, children: [
1630
- /* @__PURE__ */ e("aside", { className: f.sidebar, children: /* @__PURE__ */ e("nav", { className: f.menuList, children: oe.map((a) => {
1631
- const o = m.has(a.title);
1632
- return /* @__PURE__ */ s("div", { className: f.menuGroup, children: [
1633
- /* @__PURE__ */ s(
1634
- "div",
1635
- {
1636
- className: f.menuGroupHeader,
1637
- onClick: () => h(a.title),
1638
- children: [
1639
- /* @__PURE__ */ e("span", { className: f.menuGroupIcon, children: a.icon }),
1640
- /* @__PURE__ */ e("span", { className: f.menuGroupLabel, children: a.title }),
1641
- /* @__PURE__ */ e("span", { className: f.menuGroupArrow, children: o ? /* @__PURE__ */ e(Ke, {}) : /* @__PURE__ */ e(Ue, {}) })
1642
- ]
1643
- }
1644
- ),
1645
- o && /* @__PURE__ */ e("ul", { className: f.menuSubList, children: a.items.map((r) => /* @__PURE__ */ s(
1646
- "li",
1647
- {
1648
- className: `${f.menuSubItemWrap} ${f.menuSubItem} ${y === r.key ? f.menuSubItemActive : ""}`,
1649
- onClick: () => C(r),
1650
- children: [
1651
- /* @__PURE__ */ e("span", { className: f.menuSubItemIcon, children: r.icon }),
1652
- /* @__PURE__ */ e("span", { className: f.menuSubItemLabel, children: r.label })
1653
- ]
1654
- },
1655
- r.key
1656
- )) })
1657
- ] }, a.title);
1658
- }) }) }),
1659
- c ? null : /* @__PURE__ */ e("main", { className: f.main, children: k })
1660
- ] });
1661
- }
1662
- export {
1663
- wn as default
1664
- };