@yuku123/z-mist-component 0.1.1 → 0.1.2
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.
- package/dist/ComponentDoc-MZ2exfz_.js +966 -0
- package/dist/index.js +5 -4
- package/dist/pages.js +460 -452
- package/package.json +1 -1
- package/dist/MistApp-BPKuQySt.js +0 -973
|
@@ -0,0 +1,966 @@
|
|
|
1
|
+
import { useNavigate as we, Routes as ke, Route as H, Navigate as be } from "react-router-dom";
|
|
2
|
+
import Re, { useState as i, useEffect as te } from "react";
|
|
3
|
+
import { Space as F, Input as _, Button as j, message as y, Modal as L, Tag as U, Select as q, Form as w, Switch as Oe } from "antd";
|
|
4
|
+
import { EyeInvisibleOutlined as Se, EyeOutlined as je, CopyOutlined as _e, ReloadOutlined as ne, PlusOutlined as re, EditOutlined as se, DeleteOutlined as ae, ExclamationCircleOutlined as Ce, KeyOutlined as Pe, SafetyOutlined as Ie } from "@ant-design/icons";
|
|
5
|
+
import { ListTable as oe, SearchInput as ye, ErrorState as ge, TableToolbar as ze, ComponentDoc as Ae } from "@yuku123/z-frontend-common/ui";
|
|
6
|
+
import { request as C } from "@yuku123/z-frontend-common";
|
|
7
|
+
var X = { exports: {} }, J = {};
|
|
8
|
+
/**
|
|
9
|
+
* @license React
|
|
10
|
+
* react-jsx-runtime.production.js
|
|
11
|
+
*
|
|
12
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
13
|
+
*
|
|
14
|
+
* This source code is licensed under the MIT license found in the
|
|
15
|
+
* LICENSE file in the root directory of this source tree.
|
|
16
|
+
*/
|
|
17
|
+
var me;
|
|
18
|
+
function De() {
|
|
19
|
+
if (me) return J;
|
|
20
|
+
me = 1;
|
|
21
|
+
var m = Symbol.for("react.transitional.element"), O = Symbol.for("react.fragment");
|
|
22
|
+
function b(T, u, c) {
|
|
23
|
+
var g = null;
|
|
24
|
+
if (c !== void 0 && (g = "" + c), u.key !== void 0 && (g = "" + u.key), "key" in u) {
|
|
25
|
+
c = {};
|
|
26
|
+
for (var S in u)
|
|
27
|
+
S !== "key" && (c[S] = u[S]);
|
|
28
|
+
} else c = u;
|
|
29
|
+
return u = c.ref, {
|
|
30
|
+
$$typeof: m,
|
|
31
|
+
type: T,
|
|
32
|
+
key: g,
|
|
33
|
+
ref: u !== void 0 ? u : null,
|
|
34
|
+
props: c
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return J.Fragment = O, J.jsx = b, J.jsxs = b, J;
|
|
38
|
+
}
|
|
39
|
+
var B = {};
|
|
40
|
+
/**
|
|
41
|
+
* @license React
|
|
42
|
+
* react-jsx-runtime.development.js
|
|
43
|
+
*
|
|
44
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
45
|
+
*
|
|
46
|
+
* This source code is licensed under the MIT license found in the
|
|
47
|
+
* LICENSE file in the root directory of this source tree.
|
|
48
|
+
*/
|
|
49
|
+
var xe;
|
|
50
|
+
function Le() {
|
|
51
|
+
return xe || (xe = 1, process.env.NODE_ENV !== "production" && (function() {
|
|
52
|
+
function m(t) {
|
|
53
|
+
if (t == null) return null;
|
|
54
|
+
if (typeof t == "function")
|
|
55
|
+
return t.$$typeof === ve ? null : t.displayName || t.name || null;
|
|
56
|
+
if (typeof t == "string") return t;
|
|
57
|
+
switch (t) {
|
|
58
|
+
case o:
|
|
59
|
+
return "Fragment";
|
|
60
|
+
case x:
|
|
61
|
+
return "Profiler";
|
|
62
|
+
case v:
|
|
63
|
+
return "StrictMode";
|
|
64
|
+
case V:
|
|
65
|
+
return "Suspense";
|
|
66
|
+
case K:
|
|
67
|
+
return "SuspenseList";
|
|
68
|
+
case l:
|
|
69
|
+
return "Activity";
|
|
70
|
+
case W:
|
|
71
|
+
return "ViewTransition";
|
|
72
|
+
}
|
|
73
|
+
if (typeof t == "object")
|
|
74
|
+
switch (typeof t.tag == "number" && console.error(
|
|
75
|
+
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
|
|
76
|
+
), t.$$typeof) {
|
|
77
|
+
case a:
|
|
78
|
+
return "Portal";
|
|
79
|
+
case G:
|
|
80
|
+
return t.displayName || "Context";
|
|
81
|
+
case E:
|
|
82
|
+
return (t._context.displayName || "Context") + ".Consumer";
|
|
83
|
+
case Y:
|
|
84
|
+
var s = t.render;
|
|
85
|
+
return t = t.displayName, t || (t = s.displayName || s.name || "", t = t !== "" ? "ForwardRef(" + t + ")" : "ForwardRef"), t;
|
|
86
|
+
case r:
|
|
87
|
+
return s = t.displayName || null, s !== null ? s : m(t.type) || "Memo";
|
|
88
|
+
case n:
|
|
89
|
+
s = t._payload, t = t._init;
|
|
90
|
+
try {
|
|
91
|
+
return m(t(s));
|
|
92
|
+
} catch {
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function O(t) {
|
|
98
|
+
return "" + t;
|
|
99
|
+
}
|
|
100
|
+
function b(t) {
|
|
101
|
+
try {
|
|
102
|
+
O(t);
|
|
103
|
+
var s = !1;
|
|
104
|
+
} catch {
|
|
105
|
+
s = !0;
|
|
106
|
+
}
|
|
107
|
+
if (s) {
|
|
108
|
+
s = console;
|
|
109
|
+
var d = s.error, h = typeof Symbol == "function" && Symbol.toStringTag && t[Symbol.toStringTag] || t.constructor.name || "Object";
|
|
110
|
+
return d.call(
|
|
111
|
+
s,
|
|
112
|
+
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
|
|
113
|
+
h
|
|
114
|
+
), O(t);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function T(t) {
|
|
118
|
+
if (t === o) return "<>";
|
|
119
|
+
if (typeof t == "object" && t !== null && t.$$typeof === n)
|
|
120
|
+
return "<...>";
|
|
121
|
+
try {
|
|
122
|
+
var s = m(t);
|
|
123
|
+
return s ? "<" + s + ">" : "<...>";
|
|
124
|
+
} catch {
|
|
125
|
+
return "<...>";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function u() {
|
|
129
|
+
var t = Q.A;
|
|
130
|
+
return t === null ? null : t.getOwner();
|
|
131
|
+
}
|
|
132
|
+
function c() {
|
|
133
|
+
return Error("react-stack-top-frame");
|
|
134
|
+
}
|
|
135
|
+
function g(t) {
|
|
136
|
+
if (ie.call(t, "key")) {
|
|
137
|
+
var s = Object.getOwnPropertyDescriptor(t, "key").get;
|
|
138
|
+
if (s && s.isReactWarning) return !1;
|
|
139
|
+
}
|
|
140
|
+
return t.key !== void 0;
|
|
141
|
+
}
|
|
142
|
+
function S(t, s) {
|
|
143
|
+
function d() {
|
|
144
|
+
le || (le = !0, console.error(
|
|
145
|
+
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
|
|
146
|
+
s
|
|
147
|
+
));
|
|
148
|
+
}
|
|
149
|
+
d.isReactWarning = !0, Object.defineProperty(t, "key", {
|
|
150
|
+
get: d,
|
|
151
|
+
configurable: !0
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function P() {
|
|
155
|
+
var t = m(this.type);
|
|
156
|
+
return ce[t] || (ce[t] = !0, console.error(
|
|
157
|
+
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
|
|
158
|
+
)), t = this.props.ref, t !== void 0 ? t : null;
|
|
159
|
+
}
|
|
160
|
+
function I(t, s, d, h, $, D) {
|
|
161
|
+
var f = d.ref;
|
|
162
|
+
return t = {
|
|
163
|
+
$$typeof: N,
|
|
164
|
+
type: t,
|
|
165
|
+
key: s,
|
|
166
|
+
props: d,
|
|
167
|
+
_owner: h
|
|
168
|
+
}, (f !== void 0 ? f : null) !== null ? Object.defineProperty(t, "ref", {
|
|
169
|
+
enumerable: !1,
|
|
170
|
+
get: P
|
|
171
|
+
}) : Object.defineProperty(t, "ref", { enumerable: !1, value: null }), t._store = {}, Object.defineProperty(t._store, "validated", {
|
|
172
|
+
configurable: !1,
|
|
173
|
+
enumerable: !1,
|
|
174
|
+
writable: !0,
|
|
175
|
+
value: 0
|
|
176
|
+
}), Object.defineProperty(t, "_debugInfo", {
|
|
177
|
+
configurable: !1,
|
|
178
|
+
enumerable: !1,
|
|
179
|
+
writable: !0,
|
|
180
|
+
value: null
|
|
181
|
+
}), Object.defineProperty(t, "_debugStack", {
|
|
182
|
+
configurable: !1,
|
|
183
|
+
enumerable: !1,
|
|
184
|
+
writable: !0,
|
|
185
|
+
value: $
|
|
186
|
+
}), Object.defineProperty(t, "_debugTask", {
|
|
187
|
+
configurable: !1,
|
|
188
|
+
enumerable: !1,
|
|
189
|
+
writable: !0,
|
|
190
|
+
value: D
|
|
191
|
+
}), Object.freeze && (Object.freeze(t.props), Object.freeze(t)), t;
|
|
192
|
+
}
|
|
193
|
+
function A(t, s, d, h, $, D) {
|
|
194
|
+
var f = s.children;
|
|
195
|
+
if (f !== void 0)
|
|
196
|
+
if (h)
|
|
197
|
+
if (Ee(f)) {
|
|
198
|
+
for (h = 0; h < f.length; h++)
|
|
199
|
+
R(f[h]);
|
|
200
|
+
Object.freeze && Object.freeze(f);
|
|
201
|
+
} else
|
|
202
|
+
console.error(
|
|
203
|
+
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
|
|
204
|
+
);
|
|
205
|
+
else R(f);
|
|
206
|
+
if (ie.call(s, "key")) {
|
|
207
|
+
f = m(t);
|
|
208
|
+
var M = Object.keys(s).filter(function(Te) {
|
|
209
|
+
return Te !== "key";
|
|
210
|
+
});
|
|
211
|
+
h = 0 < M.length ? "{key: someKey, " + M.join(": ..., ") + ": ...}" : "{key: someKey}", pe[f + h] || (M = 0 < M.length ? "{" + M.join(": ..., ") + ": ...}" : "{}", console.error(
|
|
212
|
+
`A props object containing a "key" prop is being spread into JSX:
|
|
213
|
+
let props = %s;
|
|
214
|
+
<%s {...props} />
|
|
215
|
+
React keys must be passed directly to JSX without using spread:
|
|
216
|
+
let props = %s;
|
|
217
|
+
<%s key={someKey} {...props} />`,
|
|
218
|
+
h,
|
|
219
|
+
f,
|
|
220
|
+
M,
|
|
221
|
+
f
|
|
222
|
+
), pe[f + h] = !0);
|
|
223
|
+
}
|
|
224
|
+
if (f = null, d !== void 0 && (b(d), f = "" + d), g(s) && (b(s.key), f = "" + s.key), "key" in s) {
|
|
225
|
+
d = {};
|
|
226
|
+
for (var ee in s)
|
|
227
|
+
ee !== "key" && (d[ee] = s[ee]);
|
|
228
|
+
} else d = s;
|
|
229
|
+
return f && S(
|
|
230
|
+
d,
|
|
231
|
+
typeof t == "function" ? t.displayName || t.name || "Unknown" : t
|
|
232
|
+
), I(
|
|
233
|
+
t,
|
|
234
|
+
f,
|
|
235
|
+
d,
|
|
236
|
+
u(),
|
|
237
|
+
$,
|
|
238
|
+
D
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
function R(t) {
|
|
242
|
+
p(t) ? t._store && (t._store.validated = 1) : typeof t == "object" && t !== null && t.$$typeof === n && (t._payload.status === "fulfilled" ? p(t._payload.value) && t._payload.value._store && (t._payload.value._store.validated = 1) : t._store && (t._store.validated = 1));
|
|
243
|
+
}
|
|
244
|
+
function p(t) {
|
|
245
|
+
return typeof t == "object" && t !== null && t.$$typeof === N;
|
|
246
|
+
}
|
|
247
|
+
var k = Re, N = Symbol.for("react.transitional.element"), a = Symbol.for("react.portal"), o = Symbol.for("react.fragment"), v = Symbol.for("react.strict_mode"), x = Symbol.for("react.profiler"), E = Symbol.for("react.consumer"), G = Symbol.for("react.context"), Y = Symbol.for("react.forward_ref"), V = Symbol.for("react.suspense"), K = Symbol.for("react.suspense_list"), r = Symbol.for("react.memo"), n = Symbol.for("react.lazy"), l = Symbol.for("react.activity"), W = Symbol.for("react.view_transition"), ve = Symbol.for("react.client.reference"), Q = k.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, ie = Object.prototype.hasOwnProperty, Ee = Array.isArray, Z = console.createTask ? console.createTask : function() {
|
|
248
|
+
return null;
|
|
249
|
+
};
|
|
250
|
+
k = {
|
|
251
|
+
react_stack_bottom_frame: function(t) {
|
|
252
|
+
return t();
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
var le, ce = {}, de = k.react_stack_bottom_frame.bind(
|
|
256
|
+
k,
|
|
257
|
+
c
|
|
258
|
+
)(), ue = Z(T(c)), pe = {};
|
|
259
|
+
B.Fragment = o, B.jsx = function(t, s, d) {
|
|
260
|
+
var h = 1e4 > Q.recentlyCreatedOwnerStacks++;
|
|
261
|
+
if (h) {
|
|
262
|
+
var $ = Error.stackTraceLimit;
|
|
263
|
+
Error.stackTraceLimit = 10;
|
|
264
|
+
var D = Error("react-stack-top-frame");
|
|
265
|
+
Error.stackTraceLimit = $;
|
|
266
|
+
} else D = de;
|
|
267
|
+
return A(
|
|
268
|
+
t,
|
|
269
|
+
s,
|
|
270
|
+
d,
|
|
271
|
+
!1,
|
|
272
|
+
D,
|
|
273
|
+
h ? Z(T(t)) : ue
|
|
274
|
+
);
|
|
275
|
+
}, B.jsxs = function(t, s, d) {
|
|
276
|
+
var h = 1e4 > Q.recentlyCreatedOwnerStacks++;
|
|
277
|
+
if (h) {
|
|
278
|
+
var $ = Error.stackTraceLimit;
|
|
279
|
+
Error.stackTraceLimit = 10;
|
|
280
|
+
var D = Error("react-stack-top-frame");
|
|
281
|
+
Error.stackTraceLimit = $;
|
|
282
|
+
} else D = de;
|
|
283
|
+
return A(
|
|
284
|
+
t,
|
|
285
|
+
s,
|
|
286
|
+
d,
|
|
287
|
+
!0,
|
|
288
|
+
D,
|
|
289
|
+
h ? Z(T(t)) : ue
|
|
290
|
+
);
|
|
291
|
+
};
|
|
292
|
+
})()), B;
|
|
293
|
+
}
|
|
294
|
+
var he;
|
|
295
|
+
function Ne() {
|
|
296
|
+
return he || (he = 1, process.env.NODE_ENV === "production" ? X.exports = De() : X.exports = Le()), X.exports;
|
|
297
|
+
}
|
|
298
|
+
var e = Ne();
|
|
299
|
+
function $e({ value: m, displayValue: O = "••••••", copyable: b = !0 }) {
|
|
300
|
+
const [T, u] = i(!1), c = () => {
|
|
301
|
+
m && (navigator.clipboard.writeText(m), y.success("已复制到剪贴板"));
|
|
302
|
+
};
|
|
303
|
+
return /* @__PURE__ */ e.jsxs(F, { children: [
|
|
304
|
+
/* @__PURE__ */ e.jsx(
|
|
305
|
+
_,
|
|
306
|
+
{
|
|
307
|
+
value: T ? m : O,
|
|
308
|
+
readOnly: !0,
|
|
309
|
+
style: { width: 200 }
|
|
310
|
+
}
|
|
311
|
+
),
|
|
312
|
+
/* @__PURE__ */ e.jsx(
|
|
313
|
+
j,
|
|
314
|
+
{
|
|
315
|
+
size: "small",
|
|
316
|
+
icon: T ? /* @__PURE__ */ e.jsx(Se, {}) : /* @__PURE__ */ e.jsx(je, {}),
|
|
317
|
+
onClick: () => u(!T)
|
|
318
|
+
}
|
|
319
|
+
),
|
|
320
|
+
b && /* @__PURE__ */ e.jsx(
|
|
321
|
+
j,
|
|
322
|
+
{
|
|
323
|
+
size: "small",
|
|
324
|
+
icon: /* @__PURE__ */ e.jsx(_e, {}),
|
|
325
|
+
onClick: c
|
|
326
|
+
}
|
|
327
|
+
)
|
|
328
|
+
] });
|
|
329
|
+
}
|
|
330
|
+
function Ue() {
|
|
331
|
+
const m = we(), [O, b] = i([]), [T, u] = i(!1), [c, g] = i(""), [S, P] = i(!1), [I, A] = i(null), R = async (a) => {
|
|
332
|
+
u(!0);
|
|
333
|
+
try {
|
|
334
|
+
const o = a ? `/secret/search?keyword=${encodeURIComponent(a)}` : "/secret/list", v = await C.get(o);
|
|
335
|
+
v.success && b(v.data || []);
|
|
336
|
+
} catch {
|
|
337
|
+
y.error("获取密钥列表失败");
|
|
338
|
+
} finally {
|
|
339
|
+
u(!1);
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
te(() => {
|
|
343
|
+
R();
|
|
344
|
+
}, []);
|
|
345
|
+
const p = (a) => {
|
|
346
|
+
L.confirm({
|
|
347
|
+
title: "确认删除",
|
|
348
|
+
icon: /* @__PURE__ */ e.jsx(Ce, {}),
|
|
349
|
+
content: `确定要删除密钥 "${a.secretName}" 吗?`,
|
|
350
|
+
onOk: async () => {
|
|
351
|
+
try {
|
|
352
|
+
const o = await C.delete(
|
|
353
|
+
`/secret?secretKey=${encodeURIComponent(a.secretKey)}&group=${encodeURIComponent(a.group || "DEFAULT_GROUP")}&namespace=${encodeURIComponent(a.namespace || "")}`
|
|
354
|
+
);
|
|
355
|
+
o.success ? (y.success("删除成功"), R(c)) : y.error(o.message || "删除失败");
|
|
356
|
+
} catch {
|
|
357
|
+
y.error("删除失败");
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
}, k = (a) => {
|
|
362
|
+
L.confirm({
|
|
363
|
+
title: "立即轮换密钥?",
|
|
364
|
+
content: `将重新生成 "${a.secretKey}" 的值并自增版本`,
|
|
365
|
+
onOk: async () => {
|
|
366
|
+
const o = await C.post(
|
|
367
|
+
`/secret/rotate?secretKey=${encodeURIComponent(a.secretKey)}&group=${encodeURIComponent(a.group || "DEFAULT_GROUP")}&namespace=${encodeURIComponent(a.namespace || "")}&newValueLength=32`
|
|
368
|
+
);
|
|
369
|
+
o.success ? (y.success("轮换成功"), R(c)) : y.error(o.message || "轮换失败");
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
}, N = [
|
|
373
|
+
{
|
|
374
|
+
title: "密钥名称",
|
|
375
|
+
dataIndex: "secretName",
|
|
376
|
+
key: "secretName"
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
title: "密钥标识",
|
|
380
|
+
dataIndex: "secretKey",
|
|
381
|
+
key: "secretKey"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
title: "分组",
|
|
385
|
+
dataIndex: "group",
|
|
386
|
+
key: "group",
|
|
387
|
+
width: 120
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
title: "命名空间",
|
|
391
|
+
dataIndex: "namespace",
|
|
392
|
+
key: "namespace",
|
|
393
|
+
width: 110
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
title: "密钥类型",
|
|
397
|
+
dataIndex: "secretType",
|
|
398
|
+
key: "secretType",
|
|
399
|
+
width: 110,
|
|
400
|
+
render: (a) => {
|
|
401
|
+
const o = {
|
|
402
|
+
text: "blue",
|
|
403
|
+
password: "red",
|
|
404
|
+
cert: "green",
|
|
405
|
+
key: "purple",
|
|
406
|
+
api_key: "orange"
|
|
407
|
+
};
|
|
408
|
+
return /* @__PURE__ */ e.jsx(U, { color: o[a] || "default", children: a });
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
title: "版本",
|
|
413
|
+
dataIndex: "keyVersion",
|
|
414
|
+
key: "keyVersion",
|
|
415
|
+
width: 80
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
title: "过期",
|
|
419
|
+
dataIndex: "expireTime",
|
|
420
|
+
key: "expireTime",
|
|
421
|
+
width: 170,
|
|
422
|
+
render: (a) => {
|
|
423
|
+
if (!a) return /* @__PURE__ */ e.jsx("span", { style: { color: "#999" }, children: "-" });
|
|
424
|
+
const o = new Date(a), v = Math.floor((o - /* @__PURE__ */ new Date()) / (1e3 * 60 * 60 * 24));
|
|
425
|
+
let x = "default";
|
|
426
|
+
return v < 0 ? x = "red" : v < 7 ? x = "orange" : v < 30 ? x = "gold" : x = "green", /* @__PURE__ */ e.jsxs(U, { color: x, children: [
|
|
427
|
+
o.toLocaleDateString(),
|
|
428
|
+
v >= 0 && ` (${v}d)`
|
|
429
|
+
] });
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
title: "创建时间",
|
|
434
|
+
dataIndex: "gmtCreate",
|
|
435
|
+
key: "gmtCreate",
|
|
436
|
+
width: 170,
|
|
437
|
+
render: (a) => a ? new Date(a).toLocaleString() : "-"
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
title: "操作",
|
|
441
|
+
key: "action",
|
|
442
|
+
width: 320,
|
|
443
|
+
fixed: "right",
|
|
444
|
+
render: (a, o) => /* @__PURE__ */ e.jsxs(F, { size: "small", children: [
|
|
445
|
+
/* @__PURE__ */ e.jsx(
|
|
446
|
+
j,
|
|
447
|
+
{
|
|
448
|
+
type: "link",
|
|
449
|
+
icon: /* @__PURE__ */ e.jsx(je, {}),
|
|
450
|
+
onClick: () => m(`/z-mist/secret/detail/${o.id}`),
|
|
451
|
+
children: "详情"
|
|
452
|
+
}
|
|
453
|
+
),
|
|
454
|
+
/* @__PURE__ */ e.jsx(
|
|
455
|
+
j,
|
|
456
|
+
{
|
|
457
|
+
type: "link",
|
|
458
|
+
icon: /* @__PURE__ */ e.jsx(se, {}),
|
|
459
|
+
onClick: () => m(`/z-mist/secret/edit/${o.id}`),
|
|
460
|
+
children: "编辑"
|
|
461
|
+
}
|
|
462
|
+
),
|
|
463
|
+
/* @__PURE__ */ e.jsx(
|
|
464
|
+
j,
|
|
465
|
+
{
|
|
466
|
+
type: "link",
|
|
467
|
+
onClick: () => k(o),
|
|
468
|
+
children: "轮换"
|
|
469
|
+
}
|
|
470
|
+
),
|
|
471
|
+
/* @__PURE__ */ e.jsx(
|
|
472
|
+
j,
|
|
473
|
+
{
|
|
474
|
+
type: "link",
|
|
475
|
+
danger: !0,
|
|
476
|
+
icon: /* @__PURE__ */ e.jsx(ae, {}),
|
|
477
|
+
onClick: () => p(o),
|
|
478
|
+
children: "删除"
|
|
479
|
+
}
|
|
480
|
+
)
|
|
481
|
+
] })
|
|
482
|
+
}
|
|
483
|
+
];
|
|
484
|
+
return /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
|
|
485
|
+
/* @__PURE__ */ e.jsx("div", { style: { marginBottom: 16, display: "flex", justifyContent: "space-between" }, children: /* @__PURE__ */ e.jsx("h2", { children: "密钥管理" }) }),
|
|
486
|
+
/* @__PURE__ */ e.jsx(
|
|
487
|
+
oe,
|
|
488
|
+
{
|
|
489
|
+
rows: O,
|
|
490
|
+
columns: N,
|
|
491
|
+
rowKey: "id",
|
|
492
|
+
loading: T,
|
|
493
|
+
scroll: { x: 1200 },
|
|
494
|
+
emptyTitle: "暂无密钥",
|
|
495
|
+
emptyDescription: "点右上角「新增密钥」创建第一个",
|
|
496
|
+
cardExtra: /* @__PURE__ */ e.jsxs(F, { children: [
|
|
497
|
+
/* @__PURE__ */ e.jsx(
|
|
498
|
+
ye,
|
|
499
|
+
{
|
|
500
|
+
placeholder: "搜索密钥标识/名称/描述/应用",
|
|
501
|
+
value: c,
|
|
502
|
+
onChange: g,
|
|
503
|
+
onSearch: (a) => {
|
|
504
|
+
g(a), R(a);
|
|
505
|
+
},
|
|
506
|
+
width: 320
|
|
507
|
+
}
|
|
508
|
+
),
|
|
509
|
+
/* @__PURE__ */ e.jsx(j, { icon: /* @__PURE__ */ e.jsx(ne, {}), onClick: () => {
|
|
510
|
+
g(""), R("");
|
|
511
|
+
}, children: "重置" }),
|
|
512
|
+
/* @__PURE__ */ e.jsx(
|
|
513
|
+
j,
|
|
514
|
+
{
|
|
515
|
+
type: "primary",
|
|
516
|
+
icon: /* @__PURE__ */ e.jsx(re, {}),
|
|
517
|
+
onClick: () => m("/z-mist/secret/add"),
|
|
518
|
+
children: "新增密钥"
|
|
519
|
+
}
|
|
520
|
+
)
|
|
521
|
+
] })
|
|
522
|
+
}
|
|
523
|
+
),
|
|
524
|
+
/* @__PURE__ */ e.jsx(
|
|
525
|
+
L,
|
|
526
|
+
{
|
|
527
|
+
title: "密钥详情 - " + ((I == null ? void 0 : I.secretName) || ""),
|
|
528
|
+
open: S,
|
|
529
|
+
onCancel: () => P(!1),
|
|
530
|
+
footer: null,
|
|
531
|
+
width: 500,
|
|
532
|
+
children: I && /* @__PURE__ */ e.jsx(
|
|
533
|
+
$e,
|
|
534
|
+
{
|
|
535
|
+
value: I.secretValue,
|
|
536
|
+
displayValue: "••••••••"
|
|
537
|
+
}
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
)
|
|
541
|
+
] });
|
|
542
|
+
}
|
|
543
|
+
const { Option: fe } = q;
|
|
544
|
+
function Fe() {
|
|
545
|
+
const [m, O] = i([]), [b, T] = i(0), [u, c] = i(!1), [g, S] = i(1), [P, I] = i(20), [A, R] = i(""), [p, k] = i(null), [N, a] = i(!1), [o, v] = i(null), [x] = w.useForm();
|
|
546
|
+
te(() => {
|
|
547
|
+
E();
|
|
548
|
+
}, [g, P]);
|
|
549
|
+
const E = async (n) => {
|
|
550
|
+
c(!0);
|
|
551
|
+
try {
|
|
552
|
+
const l = typeof n == "string" ? n : A, W = await C.get(`/app/page?current=${g}&size=${P}&appName=${encodeURIComponent(l)}`);
|
|
553
|
+
W.success && (O(W.data || []), T(W.total || 0)), k(null);
|
|
554
|
+
} catch (l) {
|
|
555
|
+
k(l);
|
|
556
|
+
} finally {
|
|
557
|
+
c(!1);
|
|
558
|
+
}
|
|
559
|
+
}, G = () => {
|
|
560
|
+
v(null), x.resetFields(), x.setFieldsValue({ appType: "server", enabled: 1, namespace: "" }), a(!0);
|
|
561
|
+
}, Y = (n) => {
|
|
562
|
+
v(n), x.setFieldsValue(n), a(!0);
|
|
563
|
+
}, V = (n) => {
|
|
564
|
+
L.confirm({
|
|
565
|
+
title: "确认删除",
|
|
566
|
+
content: `确定要删除应用 "${n.appName}" 吗?`,
|
|
567
|
+
onOk: async () => {
|
|
568
|
+
const l = await C.delete(`/app/${n.id}`);
|
|
569
|
+
l.success ? (y.success("删除成功"), E()) : y.error(l.message || "删除失败");
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
}, K = (n) => {
|
|
573
|
+
L.confirm({
|
|
574
|
+
title: "重置 appSecret",
|
|
575
|
+
content: `将重新生成 "${n.appName}" 的 appSecret,旧密钥立即失效`,
|
|
576
|
+
onOk: async () => {
|
|
577
|
+
const l = await C.post(`/app/${n.id}/reset-secret`);
|
|
578
|
+
l.success ? (L.info({
|
|
579
|
+
title: "新密钥生成成功",
|
|
580
|
+
content: /* @__PURE__ */ e.jsxs("div", { children: [
|
|
581
|
+
/* @__PURE__ */ e.jsxs("p", { children: [
|
|
582
|
+
"应用: ",
|
|
583
|
+
l.data.appName
|
|
584
|
+
] }),
|
|
585
|
+
/* @__PURE__ */ e.jsx("p", { children: "新 appSecret (仅显示一次,请妥善保存):" }),
|
|
586
|
+
/* @__PURE__ */ e.jsx(_.TextArea, { rows: 3, value: l.data.newSecret, readOnly: !0 })
|
|
587
|
+
] })
|
|
588
|
+
}), E()) : y.error(l.message || "重置失败");
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
}, r = async () => {
|
|
592
|
+
const n = await x.validateFields();
|
|
593
|
+
try {
|
|
594
|
+
const l = o ? await C.put(`/app/${o.id}`, n) : await C.post("/app", n);
|
|
595
|
+
l.success ? (y.success(o ? "更新成功" : "创建成功"), a(!1), E()) : y.error(l.message || "操作失败");
|
|
596
|
+
} catch {
|
|
597
|
+
y.error("操作失败");
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
return /* @__PURE__ */ e.jsxs("div", { children: [
|
|
601
|
+
p && /* @__PURE__ */ e.jsx("div", { style: { marginBottom: 16 }, children: /* @__PURE__ */ e.jsx(ge, { error: p, title: "获取应用列表失败", onRetry: () => E() }) }),
|
|
602
|
+
/* @__PURE__ */ e.jsx(
|
|
603
|
+
oe,
|
|
604
|
+
{
|
|
605
|
+
rows: m,
|
|
606
|
+
columns: [
|
|
607
|
+
{ title: "ID", dataIndex: "id", width: 60 },
|
|
608
|
+
{ title: "应用名", dataIndex: "appName" },
|
|
609
|
+
{
|
|
610
|
+
title: "appSecret 指纹",
|
|
611
|
+
dataIndex: "appSecret",
|
|
612
|
+
ellipsis: !0,
|
|
613
|
+
render: (n) => n ? /* @__PURE__ */ e.jsxs("code", { children: [
|
|
614
|
+
n.substring(0, 8),
|
|
615
|
+
"...",
|
|
616
|
+
n.substring(n.length - 4)
|
|
617
|
+
] }) : "-"
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
title: "类型",
|
|
621
|
+
dataIndex: "appType",
|
|
622
|
+
width: 80,
|
|
623
|
+
render: (n) => /* @__PURE__ */ e.jsx(U, { color: n === "server" ? "blue" : "green", children: n })
|
|
624
|
+
},
|
|
625
|
+
{ title: "命名空间", dataIndex: "namespace", width: 120 },
|
|
626
|
+
{
|
|
627
|
+
title: "启用",
|
|
628
|
+
dataIndex: "enabled",
|
|
629
|
+
width: 80,
|
|
630
|
+
render: (n) => /* @__PURE__ */ e.jsx(U, { color: n === 1 ? "green" : "red", children: n === 1 ? "是" : "否" })
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
title: "创建时间",
|
|
634
|
+
dataIndex: "gmtCreate",
|
|
635
|
+
width: 170,
|
|
636
|
+
render: (n) => n ? new Date(n).toLocaleString() : "-"
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
title: "操作",
|
|
640
|
+
width: 280,
|
|
641
|
+
fixed: "right",
|
|
642
|
+
render: (n, l) => /* @__PURE__ */ e.jsxs(F, { size: "small", children: [
|
|
643
|
+
/* @__PURE__ */ e.jsx(
|
|
644
|
+
j,
|
|
645
|
+
{
|
|
646
|
+
type: "link",
|
|
647
|
+
icon: /* @__PURE__ */ e.jsx(se, {}),
|
|
648
|
+
onClick: () => Y(l),
|
|
649
|
+
children: "编辑"
|
|
650
|
+
}
|
|
651
|
+
),
|
|
652
|
+
/* @__PURE__ */ e.jsx(
|
|
653
|
+
j,
|
|
654
|
+
{
|
|
655
|
+
type: "link",
|
|
656
|
+
icon: /* @__PURE__ */ e.jsx(Pe, {}),
|
|
657
|
+
onClick: () => K(l),
|
|
658
|
+
children: "重置密钥"
|
|
659
|
+
}
|
|
660
|
+
),
|
|
661
|
+
/* @__PURE__ */ e.jsx(
|
|
662
|
+
j,
|
|
663
|
+
{
|
|
664
|
+
type: "link",
|
|
665
|
+
danger: !0,
|
|
666
|
+
icon: /* @__PURE__ */ e.jsx(ae, {}),
|
|
667
|
+
onClick: () => V(l),
|
|
668
|
+
children: "删除"
|
|
669
|
+
}
|
|
670
|
+
)
|
|
671
|
+
] })
|
|
672
|
+
}
|
|
673
|
+
],
|
|
674
|
+
rowKey: "id",
|
|
675
|
+
loading: u,
|
|
676
|
+
pagination: {
|
|
677
|
+
current: g,
|
|
678
|
+
pageSize: P,
|
|
679
|
+
total: b,
|
|
680
|
+
showSizeChanger: !0,
|
|
681
|
+
onChange: (n, l) => {
|
|
682
|
+
S(n), I(l);
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
emptyTitle: "暂无应用",
|
|
686
|
+
emptyDescription: "点「新建应用」注册第一个调用方",
|
|
687
|
+
cardExtra: /* @__PURE__ */ e.jsxs(F, { children: [
|
|
688
|
+
/* @__PURE__ */ e.jsx(
|
|
689
|
+
ye,
|
|
690
|
+
{
|
|
691
|
+
placeholder: "搜索应用名",
|
|
692
|
+
value: A,
|
|
693
|
+
onChange: R,
|
|
694
|
+
onSearch: (n) => E(n),
|
|
695
|
+
width: 240
|
|
696
|
+
}
|
|
697
|
+
),
|
|
698
|
+
/* @__PURE__ */ e.jsx(j, { icon: /* @__PURE__ */ e.jsx(ne, {}), onClick: () => E(), children: "刷新" }),
|
|
699
|
+
/* @__PURE__ */ e.jsx(j, { type: "primary", icon: /* @__PURE__ */ e.jsx(re, {}), onClick: G, children: "新建应用" })
|
|
700
|
+
] })
|
|
701
|
+
}
|
|
702
|
+
),
|
|
703
|
+
/* @__PURE__ */ e.jsx(
|
|
704
|
+
L,
|
|
705
|
+
{
|
|
706
|
+
title: o ? "编辑应用" : "新建应用",
|
|
707
|
+
open: N,
|
|
708
|
+
onCancel: () => a(!1),
|
|
709
|
+
onOk: r,
|
|
710
|
+
width: 500,
|
|
711
|
+
destroyOnClose: !0,
|
|
712
|
+
children: /* @__PURE__ */ e.jsxs(w, { form: x, layout: "vertical", children: [
|
|
713
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "appName", label: "应用名", rules: [{ required: !0 }], children: /* @__PURE__ */ e.jsx(_, { placeholder: "如: z-trade-biz" }) }),
|
|
714
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "appType", label: "应用类型", children: /* @__PURE__ */ e.jsxs(q, { children: [
|
|
715
|
+
/* @__PURE__ */ e.jsx(fe, { value: "server", children: "server (服务端)" }),
|
|
716
|
+
/* @__PURE__ */ e.jsx(fe, { value: "client", children: "client (客户端)" })
|
|
717
|
+
] }) }),
|
|
718
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "namespace", label: "命名空间", children: /* @__PURE__ */ e.jsx(_, { placeholder: "如: prod/dev" }) }),
|
|
719
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "enabled", label: "启用", valuePropName: "checked", children: /* @__PURE__ */ e.jsx(Oe, {}) }),
|
|
720
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "description", label: "描述", children: /* @__PURE__ */ e.jsx(_.TextArea, { rows: 2 }) })
|
|
721
|
+
] })
|
|
722
|
+
}
|
|
723
|
+
)
|
|
724
|
+
] });
|
|
725
|
+
}
|
|
726
|
+
const { Option: z } = q;
|
|
727
|
+
function Me() {
|
|
728
|
+
const [m, O] = i([]), [b, T] = i(0), [u, c] = i(!1), [g, S] = i(1), [P, I] = i(20), [A, R] = i(null), [p, k] = i({ secretKey: "", authorizedApp: "", authorizedEnv: "", namespace: "" }), [N, a] = i(!1), [o, v] = i(null), [x] = w.useForm();
|
|
729
|
+
te(() => {
|
|
730
|
+
E();
|
|
731
|
+
}, [g, P]);
|
|
732
|
+
const E = async () => {
|
|
733
|
+
c(!0);
|
|
734
|
+
try {
|
|
735
|
+
const r = new URLSearchParams({
|
|
736
|
+
current: g,
|
|
737
|
+
size: P,
|
|
738
|
+
secretKey: p.secretKey,
|
|
739
|
+
authorizedApp: p.authorizedApp,
|
|
740
|
+
authorizedEnv: p.authorizedEnv,
|
|
741
|
+
namespace: p.namespace
|
|
742
|
+
}), n = await C.get(`/acl/page?${r}`);
|
|
743
|
+
n.success && (O(n.data || []), T(n.total || 0)), R(null);
|
|
744
|
+
} catch (r) {
|
|
745
|
+
R(r);
|
|
746
|
+
} finally {
|
|
747
|
+
c(!1);
|
|
748
|
+
}
|
|
749
|
+
}, G = () => {
|
|
750
|
+
v(null), x.resetFields(), x.setFieldsValue({
|
|
751
|
+
permissionLevel: "read",
|
|
752
|
+
group: "DEFAULT_GROUP",
|
|
753
|
+
namespace: "",
|
|
754
|
+
authorizedEnv: "prod"
|
|
755
|
+
}), a(!0);
|
|
756
|
+
}, Y = (r) => {
|
|
757
|
+
v(r), x.setFieldsValue(r), a(!0);
|
|
758
|
+
}, V = (r) => {
|
|
759
|
+
L.confirm({
|
|
760
|
+
title: "确认删除授权",
|
|
761
|
+
content: `将撤销 ${r.authorizedApp} 对 ${r.secretKey} 的访问权限`,
|
|
762
|
+
onOk: async () => {
|
|
763
|
+
const n = await C.delete(`/acl/${r.id}`);
|
|
764
|
+
n.success ? (y.success("删除成功"), E()) : y.error(n.message || "删除失败");
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
}, K = async () => {
|
|
768
|
+
const r = await x.validateFields();
|
|
769
|
+
try {
|
|
770
|
+
const n = o ? await C.put(`/acl/${o.id}`, r) : await C.post("/acl", r);
|
|
771
|
+
n.success ? (y.success(o ? "更新成功" : "创建成功"), a(!1), E()) : y.error(n.message || "操作失败");
|
|
772
|
+
} catch {
|
|
773
|
+
y.error("操作失败");
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
return /* @__PURE__ */ e.jsxs("div", { children: [
|
|
777
|
+
A && /* @__PURE__ */ e.jsx("div", { style: { marginBottom: 16 }, children: /* @__PURE__ */ e.jsx(ge, { error: A, title: "获取授权列表失败", onRetry: () => E() }) }),
|
|
778
|
+
/* @__PURE__ */ e.jsx(
|
|
779
|
+
ze,
|
|
780
|
+
{
|
|
781
|
+
left: /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
|
|
782
|
+
/* @__PURE__ */ e.jsx(
|
|
783
|
+
_,
|
|
784
|
+
{
|
|
785
|
+
placeholder: "密钥标识",
|
|
786
|
+
allowClear: !0,
|
|
787
|
+
value: p.secretKey,
|
|
788
|
+
onChange: (r) => k({ ...p, secretKey: r.target.value }),
|
|
789
|
+
style: { width: 180 }
|
|
790
|
+
}
|
|
791
|
+
),
|
|
792
|
+
/* @__PURE__ */ e.jsx(
|
|
793
|
+
_,
|
|
794
|
+
{
|
|
795
|
+
placeholder: "授权应用",
|
|
796
|
+
allowClear: !0,
|
|
797
|
+
value: p.authorizedApp,
|
|
798
|
+
onChange: (r) => k({ ...p, authorizedApp: r.target.value }),
|
|
799
|
+
style: { width: 180 }
|
|
800
|
+
}
|
|
801
|
+
),
|
|
802
|
+
/* @__PURE__ */ e.jsxs(
|
|
803
|
+
q,
|
|
804
|
+
{
|
|
805
|
+
placeholder: "环境",
|
|
806
|
+
allowClear: !0,
|
|
807
|
+
value: p.authorizedEnv || void 0,
|
|
808
|
+
onChange: (r) => k({ ...p, authorizedEnv: r || "" }),
|
|
809
|
+
style: { width: 120 },
|
|
810
|
+
children: [
|
|
811
|
+
/* @__PURE__ */ e.jsx(z, { value: "dev", children: "dev" }),
|
|
812
|
+
/* @__PURE__ */ e.jsx(z, { value: "test", children: "test" }),
|
|
813
|
+
/* @__PURE__ */ e.jsx(z, { value: "pre", children: "pre" }),
|
|
814
|
+
/* @__PURE__ */ e.jsx(z, { value: "prod", children: "prod" })
|
|
815
|
+
]
|
|
816
|
+
}
|
|
817
|
+
),
|
|
818
|
+
/* @__PURE__ */ e.jsx(
|
|
819
|
+
_,
|
|
820
|
+
{
|
|
821
|
+
placeholder: "命名空间",
|
|
822
|
+
allowClear: !0,
|
|
823
|
+
value: p.namespace,
|
|
824
|
+
onChange: (r) => k({ ...p, namespace: r.target.value }),
|
|
825
|
+
style: { width: 140 }
|
|
826
|
+
}
|
|
827
|
+
)
|
|
828
|
+
] })
|
|
829
|
+
}
|
|
830
|
+
),
|
|
831
|
+
/* @__PURE__ */ e.jsx(
|
|
832
|
+
oe,
|
|
833
|
+
{
|
|
834
|
+
rows: m,
|
|
835
|
+
columns: [
|
|
836
|
+
{ title: "ID", dataIndex: "id", width: 60 },
|
|
837
|
+
{ title: "密钥", dataIndex: "secretKey", ellipsis: !0 },
|
|
838
|
+
{ title: "分组", dataIndex: "group", width: 110 },
|
|
839
|
+
{ title: "命名空间", dataIndex: "namespace", width: 110 },
|
|
840
|
+
{
|
|
841
|
+
title: "授权应用",
|
|
842
|
+
dataIndex: "authorizedApp",
|
|
843
|
+
render: (r) => /* @__PURE__ */ e.jsx(U, { color: "blue", children: r })
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
title: "环境",
|
|
847
|
+
dataIndex: "authorizedEnv",
|
|
848
|
+
width: 80,
|
|
849
|
+
render: (r) => r ? /* @__PURE__ */ e.jsx(U, { children: r }) : /* @__PURE__ */ e.jsx(U, { color: "default", children: "ALL" })
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
title: "权限级别",
|
|
853
|
+
dataIndex: "permissionLevel",
|
|
854
|
+
width: 100,
|
|
855
|
+
render: (r) => /* @__PURE__ */ e.jsx(U, { color: r === "decrypt" ? "orange" : "green", children: r })
|
|
856
|
+
},
|
|
857
|
+
{
|
|
858
|
+
title: "过期时间",
|
|
859
|
+
dataIndex: "expireTime",
|
|
860
|
+
width: 170,
|
|
861
|
+
render: (r) => r ? new Date(r).toLocaleString() : "永久"
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
title: "创建时间",
|
|
865
|
+
dataIndex: "gmtCreate",
|
|
866
|
+
width: 170,
|
|
867
|
+
render: (r) => r ? new Date(r).toLocaleString() : "-"
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
title: "操作",
|
|
871
|
+
width: 150,
|
|
872
|
+
fixed: "right",
|
|
873
|
+
render: (r, n) => /* @__PURE__ */ e.jsxs(F, { size: "small", children: [
|
|
874
|
+
/* @__PURE__ */ e.jsx(
|
|
875
|
+
j,
|
|
876
|
+
{
|
|
877
|
+
type: "link",
|
|
878
|
+
icon: /* @__PURE__ */ e.jsx(se, {}),
|
|
879
|
+
onClick: () => Y(n),
|
|
880
|
+
children: "编辑"
|
|
881
|
+
}
|
|
882
|
+
),
|
|
883
|
+
/* @__PURE__ */ e.jsx(
|
|
884
|
+
j,
|
|
885
|
+
{
|
|
886
|
+
type: "link",
|
|
887
|
+
danger: !0,
|
|
888
|
+
icon: /* @__PURE__ */ e.jsx(ae, {}),
|
|
889
|
+
onClick: () => V(n),
|
|
890
|
+
children: "删除"
|
|
891
|
+
}
|
|
892
|
+
)
|
|
893
|
+
] })
|
|
894
|
+
}
|
|
895
|
+
],
|
|
896
|
+
rowKey: "id",
|
|
897
|
+
loading: u,
|
|
898
|
+
pagination: {
|
|
899
|
+
current: g,
|
|
900
|
+
pageSize: P,
|
|
901
|
+
total: b,
|
|
902
|
+
showSizeChanger: !0,
|
|
903
|
+
onChange: (r, n) => {
|
|
904
|
+
S(r), I(n);
|
|
905
|
+
}
|
|
906
|
+
},
|
|
907
|
+
emptyTitle: "暂无授权",
|
|
908
|
+
emptyDescription: "点「新建授权」给应用开一把钥匙",
|
|
909
|
+
cardExtra: /* @__PURE__ */ e.jsxs(F, { children: [
|
|
910
|
+
/* @__PURE__ */ e.jsx(j, { type: "primary", icon: /* @__PURE__ */ e.jsx(Ie, {}), onClick: () => {
|
|
911
|
+
S(1), E();
|
|
912
|
+
}, children: "查询" }),
|
|
913
|
+
/* @__PURE__ */ e.jsx(j, { icon: /* @__PURE__ */ e.jsx(ne, {}), onClick: E, children: "刷新" }),
|
|
914
|
+
/* @__PURE__ */ e.jsx(j, { type: "primary", icon: /* @__PURE__ */ e.jsx(re, {}), onClick: G, children: "新建授权" })
|
|
915
|
+
] })
|
|
916
|
+
}
|
|
917
|
+
),
|
|
918
|
+
/* @__PURE__ */ e.jsx(
|
|
919
|
+
L,
|
|
920
|
+
{
|
|
921
|
+
title: o ? "编辑授权" : "新建授权",
|
|
922
|
+
open: N,
|
|
923
|
+
onCancel: () => a(!1),
|
|
924
|
+
onOk: K,
|
|
925
|
+
width: 500,
|
|
926
|
+
destroyOnClose: !0,
|
|
927
|
+
children: /* @__PURE__ */ e.jsxs(w, { form: x, layout: "vertical", children: [
|
|
928
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "secretKey", label: "密钥标识", rules: [{ required: !0 }], children: /* @__PURE__ */ e.jsx(_, { placeholder: "如: db_password" }) }),
|
|
929
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "group", label: "分组", children: /* @__PURE__ */ e.jsx(_, { placeholder: "DEFAULT_GROUP" }) }),
|
|
930
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "namespace", label: "命名空间", children: /* @__PURE__ */ e.jsx(_, { placeholder: "prod/test/dev" }) }),
|
|
931
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "authorizedApp", label: "授权应用名", rules: [{ required: !0 }], children: /* @__PURE__ */ e.jsx(_, { placeholder: "如: z-trade-biz" }) }),
|
|
932
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "authorizedEnv", label: "授权环境", children: /* @__PURE__ */ e.jsxs(q, { children: [
|
|
933
|
+
/* @__PURE__ */ e.jsx(z, { value: "dev", children: "dev" }),
|
|
934
|
+
/* @__PURE__ */ e.jsx(z, { value: "test", children: "test" }),
|
|
935
|
+
/* @__PURE__ */ e.jsx(z, { value: "pre", children: "pre" }),
|
|
936
|
+
/* @__PURE__ */ e.jsx(z, { value: "prod", children: "prod" })
|
|
937
|
+
] }) }),
|
|
938
|
+
/* @__PURE__ */ e.jsx(w.Item, { name: "permissionLevel", label: "权限级别", children: /* @__PURE__ */ e.jsxs(q, { children: [
|
|
939
|
+
/* @__PURE__ */ e.jsx(z, { value: "read", children: "read (仅读取密文)" }),
|
|
940
|
+
/* @__PURE__ */ e.jsx(z, { value: "decrypt", children: "decrypt (读取并解密)" })
|
|
941
|
+
] }) })
|
|
942
|
+
] })
|
|
943
|
+
}
|
|
944
|
+
)
|
|
945
|
+
] });
|
|
946
|
+
}
|
|
947
|
+
function Be() {
|
|
948
|
+
return /* @__PURE__ */ e.jsxs(ke, { children: [
|
|
949
|
+
/* @__PURE__ */ e.jsx(H, { index: !0, element: /* @__PURE__ */ e.jsx(be, { to: "secret", replace: !0 }) }),
|
|
950
|
+
/* @__PURE__ */ e.jsx(H, { path: "secret", element: /* @__PURE__ */ e.jsx(Ue, {}) }),
|
|
951
|
+
/* @__PURE__ */ e.jsx(H, { path: "app", element: /* @__PURE__ */ e.jsx(Fe, {}) }),
|
|
952
|
+
/* @__PURE__ */ e.jsx(H, { path: "acl", element: /* @__PURE__ */ e.jsx(Me, {}) })
|
|
953
|
+
] });
|
|
954
|
+
}
|
|
955
|
+
const qe = "# z-mist-component\n\nz-mist(密钥管理)跨仓唯一前端面:把「密钥台账 / 加密即服务 / 轮换策略 / 授权管理 / 应用管理 /\n访问日志 / 数据看板」这一整套密钥管理页面收敛成一个可复用的 React 组件包。\n\n- **npm 包名**:`@yuku123/z-mist-component`\n- **宿主接入**:`@yuku123/z-mist-component/pages`(manifest + 页面),主壳可只取 `ComponentDocPage`\n- **后端**:z-mist 的密钥管理接口,基座请求实例 `baseURL='/api'`\n- **技术栈**:React 19 + antd 6 + react-router-dom 7 + vite(library mode,双入口 `.` / `./pages`)\n\n---\n\n## 一、能力概览\n\n路由前缀 `/z-mist`,菜单与路由在 `src/pages-manifest.jsx` 里声明。\n\n| 页面 | 路由(相对 `/z-mist/*`) | 源文件 | 能力 |\n|------|--------------------------|--------|------|\n| 登录 | `login` | `pages/login/Login.jsx` | 用户名密码登录(`POST /auth/login`) |\n| 首页 | `home` | `pages/HomePage.jsx` | 入口卡片页 |\n| 数据看板 | `dashboard` | `pages/dashboard/Dashboard.jsx` | 密钥总数、今日操作次数、Top 密钥、即将过期密钥、近 7 天趋势 |\n| 密钥管理 | `secret` | `pages/secret/SecretList.jsx` | 密钥台账列表,支持关键词搜索 |\n| 新建 / 编辑密钥 | `secret/add`、`secret/edit/:id` | `pages/secret/SecretEdit.jsx` | 密钥元信息编辑与保存 |\n| 密钥详情 | `secret/detail/:id` | `pages/secret/SecretDetail.jsx` | 密钥详情 + 密文值展示 + 版本回滚 |\n| 加密即服务 | `eaas` | `pages/eaas/EaasConsole.jsx` | 明文加密 / 解密控制台 + 信封加密说明 |\n| 轮换策略 | `rotation` | `pages/rotation/RotationPolicy.jsx` | 轮换策略增删改查 + 手动触发 + 轮换历史 |\n| 授权管理 | `acl` | `pages/acl/AclManage.jsx` | 授权记录增删改查 |\n| 应用管理 | `app` | `pages/app/AppManage.jsx` | 应用增删改查 + 重置密钥 |\n| 访问日志 | `log` | `pages/log/AccessLog.jsx` | 访问日志分页查询 |\n| 组件文档 | `docs` | `pages/ComponentDoc.jsx` | 本文件渲染页(左侧 240px TOC + 右侧正文) |\n\n`src/pages/MistApp.jsx` 是子路由挂载点(`secret` / `app` / `acl`),被 `routes` 里的\n`/z-mist/:rest*` 承接,同时从包根具名导出。\n\n## 二、导出面\n\n```js\n// 主入口(. 桶)\nimport {request, MistApp, ComponentDocPage} from '@yuku123/z-mist-component'\n\n// 宿主组装面(./pages 桶)\nimport {menuItems, routes, HomePage, LoginPage, Dashboard} from '@yuku123/z-mist-component/pages'\n```\n\n`./pages` 桶是 `export * from './pages-manifest.jsx'` 的整份转发。\n\n## 三、API 端点\n\n请求实例是基座的 `request`(`createRequest()`,`baseURL='/api'`,token 键 `token`)。\n下表是页面里**实际调用**的路径。\n\n| 方法 | 路径 | 说明 |\n|---|---|---|\n| POST | `/auth/login` | 登录 |\n| GET | `/secret/list` | 密钥列表(详情页 / 编辑页也用它取列表) |\n| GET | `/secret/search?keyword=` | 密钥搜索(有关键词时走这个) |\n| POST | `/secret` | 新建密钥 |\n| PUT | `/secret` | 修改密钥 |\n| POST | `/secret/rollback?historyId=` | 回滚到历史版本 |\n| POST | `/eaas/encrypt` | 加密即服务:明文加密 |\n| POST | `/eaas/decrypt` | 加密即服务:解密 |\n| GET | `/rotation/policy/page?current=&size=` | 轮换策略分页 |\n| POST | `/rotation/policy` | 新建轮换策略 |\n| PUT | `/rotation/policy/{id}` | 修改轮换策略 |\n| DELETE | `/rotation/policy/{id}` | 删除轮换策略 |\n| POST | `/rotation/policy/{id}/trigger` | 手动触发轮换 |\n| GET | `/rotation/history/page?current=&size=` | 轮换历史 |\n| GET | `/acl/page?...` | 授权记录分页 |\n| POST | `/acl` | 新建授权 |\n| PUT | `/acl/{id}` | 修改授权 |\n| DELETE | `/acl/{id}` | 删除授权 |\n| GET | `/app/page?current=&size=&appName=` | 应用分页(按名搜索) |\n| POST | `/app` | 新建应用 |\n| PUT | `/app/{id}` | 修改应用 |\n| DELETE | `/app/{id}` | 删除应用 |\n| POST | `/app/{id}/reset-secret` | 重置应用密钥 |\n| GET | `/log/page?...` | 访问日志分页 |\n| GET | `/stats/overview` | 密钥总览统计 |\n| GET | `/stats/daily?days=7` | 近 N 天操作趋势 |\n| GET | `/stats/top-secrets?limit=10` | Top 密钥 |\n| GET | `/stats/expiring` | 即将过期的密钥 |\n\n## 四、页面说明\n\n### 4.1 数据看板\n\n并行拉四个统计端点(`/stats/overview`、`/stats/daily?days=7`、`/stats/top-secrets?limit=10`、\n`/stats/expiring`),渲染密钥总数、今日操作次数等卡片。加载失败走基座 `ErrorState` + 重试。\n\n### 4.2 密钥管理(列表)\n\n密钥台账。**有关键词走 `/secret/search?keyword=`,没有走 `/secret/list`** —— 两条路径要一起改,\n只改一条会出现「搜索能搜到、列表却空」。\n\n### 4.3 新建 / 编辑密钥\n\n同一组件承担新建与编辑两种模式(`/secret/add` 与 `/secret/edit/:id`):编辑时先取列表定位当前密钥,\n保存时 `POST /secret`(新建)或 `PUT /secret`(修改)。加载失败用基座 `ErrorState`(标题「获取密钥详情失败」)。\n\n### 4.4 密钥详情\n\n展示密钥元信息 + 密文值(`pages/secret/SecretValueDisplay.jsx` 负责展示),并支持按 `historyId` 回滚。\n密钥不存在时展示「该密钥可能已被删除,返回列表重新选择」。\n\n### 4.5 加密即服务\n\n明文加密 / 解密控制台:选算法 → 输入明文 → 得 Base64 密文,可反向解密。\n页面同时说明信封加密(Envelope Encryption)的用法:业务方把敏感数据加密后存 MySQL/Redis,\n后续解密反查,**密钥值不落库**。\n\n### 4.6 轮换策略\n\n策略列表 + 新建 / 编辑 / 删除 + 手动触发轮换,下方展示轮换历史(默认取 50 条)。\n策略列表固定 `current=1&size=100`,历史固定 `current=1&size=50`。\n\n### 4.7 授权管理\n\n授权记录的分页查询与增删改查。\n\n### 4.8 应用管理\n\n应用分页(支持按 `appName` 搜索)+ 增删改查 + **重置密钥**(`POST /app/{id}/reset-secret`)。\n\n### 4.9 访问日志\n\n访问日志分页查询。\n\n### 4.10 组件文档\n\n本文件。内容以 `?raw` 在编译期内联,零额外请求;左侧 240px TOC 随滚动联动。\n\n## 五、配置\n\n| 配置项 | 默认值 | 说明 |\n|---|---|---|\n| 请求实例 | 基座 `request` | `baseURL='/api'`,token 键 `token`,401 跳转与业务码判定由基座统一处理 |\n| `mistErr(e)` | — | 从 500 响应体里取真因(如 `Table 'oc.z_mist_secret_tag' doesn't exist`),避免被 axios 压成「没有数据」 |\n| 轮换策略列表条数 | `size=100` | 固定值,未开放配置 |\n| 轮换历史条数 | `size=50` | 固定值,未开放配置 |\n\n## 六、已知限制\n\n- ⚠ **密钥明文/密文值属于敏感信息**:页面只做展示与回滚,没有任何「导出密钥」入口;\n 后续加功能时不要顺手加批量导出。\n- `services/api.js` 用的是**默认导入**(桶对象)当 axios 用(`import request from '@yuku123/z-frontend-common'`)。\n 基座的桶在 1.1.x 上补了 HTTP 动词转发才让这种写法能跑;**新写代码请用具名导入**\n `import { request } from '@yuku123/z-frontend-common'`。\n- `services/request.js` 重新导出了一份 `request`,与 `services/api.js` 的默认导出**是同一个实例**\n (都来自基座),但两个文件各写一份导出,容易让人以为有两个实例。\n- 密钥列表的搜索路径与列表路径是**两条不同的端点**(`/secret/search` vs `/secret/list`),\n 改返回结构时两条都要改。\n- 轮换策略 / 轮换历史的分页参数是**写死的**(`current=1`),没有翻页控件。\n- 页面里 `request.get('/secret/list')` 拿的是**全量列表**再在本地定位,没有按 id 取单个密钥的端点 ——\n 密钥量大时详情页会变慢。\n- 组件包必须 external 基座;`vite.config.js` 的 `external` 是精确字符串匹配,\n `@yuku123/z-frontend-common/ui` 与 `/ui/echarts` 两个子路径必须逐个列出,漏了基座会被复制进 dist。\n\n## 七、变更记录\n\n| 版本 | 变更 |\n|---|---|\n| 0.1.1 | 新增组件文档页 `ComponentDocPage`(lead 008 §7):`src/DOC.md` + 基座 `ComponentDoc` 薄包装 |\n| 0.1.0 | 首版:密钥管理页面集 + manifest + 自洽 request |\n";
|
|
956
|
+
function He() {
|
|
957
|
+
return /* @__PURE__ */ e.jsx(Ae, { markdown: qe, title: "组件文档 — z-mist" });
|
|
958
|
+
}
|
|
959
|
+
export {
|
|
960
|
+
Me as A,
|
|
961
|
+
He as C,
|
|
962
|
+
Be as M,
|
|
963
|
+
Ue as S,
|
|
964
|
+
Fe as a,
|
|
965
|
+
e as j
|
|
966
|
+
};
|