com-angel-authorization 1.0.0 → 1.0.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/README.md +87 -0
- package/dist/index.cjs +295 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +126 -1
- package/dist/index.d.ts +126 -1
- package/dist/index.js +280 -1
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +482 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +135 -1
- package/dist/react/index.d.ts +135 -1
- package/dist/react/index.js +488 -0
- package/dist/react/index.js.map +1 -1
- package/dist/vue/index.cjs +594 -0
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.d.cts +162 -1
- package/dist/vue/index.d.ts +162 -1
- package/dist/vue/index.js +602 -0
- package/dist/vue/index.js.map +1 -1
- package/package.json +6 -1
package/dist/react/index.cjs
CHANGED
|
@@ -24,7 +24,24 @@ __export(react_exports, {
|
|
|
24
24
|
Can: () => Can,
|
|
25
25
|
PermissionProvider: () => PermissionProvider,
|
|
26
26
|
PermissionStore: () => import_core2.PermissionStore,
|
|
27
|
+
RESOURCE_PRIVATE_OPTIONS: () => import_resources2.RESOURCE_PRIVATE_OPTIONS,
|
|
28
|
+
RESOURCE_STATUS_DISABLED: () => import_resources2.RESOURCE_STATUS_DISABLED,
|
|
29
|
+
RESOURCE_STATUS_ENABLED: () => import_resources2.RESOURCE_STATUS_ENABLED,
|
|
30
|
+
RESOURCE_STATUS_OPTIONS: () => import_resources2.RESOURCE_STATUS_OPTIONS,
|
|
31
|
+
RESOURCE_TYPE_API: () => import_resources2.RESOURCE_TYPE_API,
|
|
32
|
+
ResourceManager: () => ResourceManager,
|
|
33
|
+
appendQueryParam: () => import_resources2.appendQueryParam,
|
|
34
|
+
buildCreateBody: () => import_resources2.buildCreateBody,
|
|
35
|
+
buildUpdateBody: () => import_resources2.buildUpdateBody,
|
|
36
|
+
createAuthorizationResourceApi: () => import_resources2.createAuthorizationResourceApi,
|
|
37
|
+
createDefaultResourceRequest: () => import_resources2.createDefaultResourceRequest,
|
|
27
38
|
createPermissionStore: () => import_core2.createPermissionStore,
|
|
39
|
+
extractPagination: () => import_resources2.extractPagination,
|
|
40
|
+
extractRecords: () => import_resources2.extractRecords,
|
|
41
|
+
getAppClientId: () => import_snowflake.getAppClientId,
|
|
42
|
+
getDeviceWorkerId: () => import_snowflake.getDeviceWorkerId,
|
|
43
|
+
mapAuthorizationResource: () => import_resources2.mapAuthorizationResource,
|
|
44
|
+
snowyflake: () => import_snowflake.snowyflake,
|
|
28
45
|
useHasPermission: () => useHasPermission,
|
|
29
46
|
useHasRole: () => useHasRole,
|
|
30
47
|
usePermission: () => usePermission
|
|
@@ -141,14 +158,479 @@ function Can({
|
|
|
141
158
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: allowed ? children : fallback });
|
|
142
159
|
}
|
|
143
160
|
|
|
161
|
+
// src/react/ResourceManager.tsx
|
|
162
|
+
var import_react2 = require("react");
|
|
163
|
+
var import_resources = require("../resources");
|
|
164
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
165
|
+
var PAGE_SIZE_OPTIONS = ["10", "20", "50", "100"];
|
|
166
|
+
var emptyForm = () => ({
|
|
167
|
+
name: "",
|
|
168
|
+
identification: "",
|
|
169
|
+
status: import_resources.RESOURCE_STATUS_ENABLED,
|
|
170
|
+
private: false,
|
|
171
|
+
description: ""
|
|
172
|
+
});
|
|
173
|
+
function ResourceManager({
|
|
174
|
+
api,
|
|
175
|
+
title = "\u6743\u9650\u70B9\u7BA1\u7406",
|
|
176
|
+
pageSize: initialPageSize = "20",
|
|
177
|
+
toolbarExtra
|
|
178
|
+
}) {
|
|
179
|
+
const [records, setRecords] = (0, import_react2.useState)([]);
|
|
180
|
+
const [loading, setLoading] = (0, import_react2.useState)(false);
|
|
181
|
+
const [error, setError] = (0, import_react2.useState)("");
|
|
182
|
+
const [pageSize, setPageSize] = (0, import_react2.useState)(initialPageSize);
|
|
183
|
+
const [pageToken, setPageToken] = (0, import_react2.useState)("");
|
|
184
|
+
const [hasPreviousPage, setHasPreviousPage] = (0, import_react2.useState)(false);
|
|
185
|
+
const [hasNextPage, setHasNextPage] = (0, import_react2.useState)(false);
|
|
186
|
+
const [dialogOpen, setDialogOpen] = (0, import_react2.useState)(false);
|
|
187
|
+
const [editing, setEditing] = (0, import_react2.useState)(null);
|
|
188
|
+
const [form, setForm] = (0, import_react2.useState)(emptyForm);
|
|
189
|
+
const [saving, setSaving] = (0, import_react2.useState)(false);
|
|
190
|
+
const loadList = (0, import_react2.useCallback)(
|
|
191
|
+
async (direction = "current", token = pageToken) => {
|
|
192
|
+
setLoading(true);
|
|
193
|
+
setError("");
|
|
194
|
+
try {
|
|
195
|
+
const result = await api.list({
|
|
196
|
+
pagination: {
|
|
197
|
+
pageToken: token,
|
|
198
|
+
pageSize,
|
|
199
|
+
pageDirection: direction
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
setRecords(result.records);
|
|
203
|
+
setPageToken(result.pageToken);
|
|
204
|
+
setHasPreviousPage(result.hasPreviousPage);
|
|
205
|
+
setHasNextPage(result.hasNextPage);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25");
|
|
208
|
+
} finally {
|
|
209
|
+
setLoading(false);
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
[api, pageSize, pageToken]
|
|
213
|
+
);
|
|
214
|
+
(0, import_react2.useEffect)(() => {
|
|
215
|
+
void loadList("current", "");
|
|
216
|
+
}, [api, pageSize]);
|
|
217
|
+
const openCreate = () => {
|
|
218
|
+
setEditing(null);
|
|
219
|
+
setForm(emptyForm());
|
|
220
|
+
setDialogOpen(true);
|
|
221
|
+
};
|
|
222
|
+
const openEdit = (row) => {
|
|
223
|
+
setEditing(row);
|
|
224
|
+
setForm({
|
|
225
|
+
name: row.name,
|
|
226
|
+
identification: row.identification,
|
|
227
|
+
status: row.status,
|
|
228
|
+
private: row.private,
|
|
229
|
+
description: row.description
|
|
230
|
+
});
|
|
231
|
+
setDialogOpen(true);
|
|
232
|
+
};
|
|
233
|
+
const closeDialog = () => {
|
|
234
|
+
if (saving) return;
|
|
235
|
+
setDialogOpen(false);
|
|
236
|
+
};
|
|
237
|
+
const handleSubmit = async (event) => {
|
|
238
|
+
event.preventDefault();
|
|
239
|
+
if (!form.name.trim()) {
|
|
240
|
+
setError("\u8BF7\u586B\u5199\u6743\u9650\u540D\u79F0");
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!form.identification.trim()) {
|
|
244
|
+
setError("\u8BF7\u586B\u5199\u63A5\u53E3\u6807\u8BC6");
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
setSaving(true);
|
|
248
|
+
setError("");
|
|
249
|
+
try {
|
|
250
|
+
if (editing) {
|
|
251
|
+
await api.update(editing.resourceId, form);
|
|
252
|
+
} else {
|
|
253
|
+
await api.create(form);
|
|
254
|
+
}
|
|
255
|
+
setDialogOpen(false);
|
|
256
|
+
await loadList("current", "");
|
|
257
|
+
} catch (err) {
|
|
258
|
+
setError(err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25");
|
|
259
|
+
} finally {
|
|
260
|
+
setSaving(false);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
const handleDelete = async (row) => {
|
|
264
|
+
if (!window.confirm(`\u786E\u8BA4\u5220\u9664\u6743\u9650\u70B9\u300C${row.name}\u300D\uFF1F`)) return;
|
|
265
|
+
setError("");
|
|
266
|
+
try {
|
|
267
|
+
await api.remove(row.resourceId);
|
|
268
|
+
await loadList("current", "");
|
|
269
|
+
} catch (err) {
|
|
270
|
+
setError(err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25");
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
const statusLabel = (0, import_react2.useMemo)(
|
|
274
|
+
() => Object.fromEntries(import_resources.RESOURCE_STATUS_OPTIONS.map((o) => [o.value, o.label])),
|
|
275
|
+
[]
|
|
276
|
+
);
|
|
277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.root, children: [
|
|
278
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbar, children: [
|
|
279
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: styles.title, children: title }),
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbarRight, children: [
|
|
281
|
+
toolbarExtra,
|
|
282
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", style: styles.primaryBtn, onClick: openCreate, children: "\u65B0\u589E" })
|
|
283
|
+
] })
|
|
284
|
+
] }),
|
|
285
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.error, children: error }) : null,
|
|
286
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.tableWrap, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("table", { style: styles.table, children: [
|
|
287
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("tr", { children: [
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { style: styles.th, children: "\u6743\u9650\u540D\u79F0" }),
|
|
289
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { style: styles.th, children: "\u63A5\u53E3\u6807\u8BC6" }),
|
|
290
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { style: styles.th, children: "\u63CF\u8FF0" }),
|
|
291
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { style: { ...styles.th, width: 90 }, children: "\u72B6\u6001" }),
|
|
292
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { style: { ...styles.th, width: 140 }, children: "\u64CD\u4F5C" })
|
|
293
|
+
] }) }),
|
|
294
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 5, style: styles.empty, children: "\u52A0\u8F7D\u4E2D\u2026" }) }) : records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 5, style: styles.empty, children: "\u6682\u65E0\u6570\u636E" }) }) : records.map((row) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("tr", { children: [
|
|
295
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { style: styles.td, children: row.name }),
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { style: styles.td, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { style: styles.code, children: row.identification }) }),
|
|
297
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { style: styles.td, children: row.description || "\u2014" }),
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { style: styles.td, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
299
|
+
"span",
|
|
300
|
+
{
|
|
301
|
+
style: {
|
|
302
|
+
...styles.badge,
|
|
303
|
+
background: row.status === import_resources.RESOURCE_STATUS_ENABLED ? "#e8f7ef" : "#f4f4f5",
|
|
304
|
+
color: row.status === import_resources.RESOURCE_STATUS_ENABLED ? "#067647" : "#667085"
|
|
305
|
+
},
|
|
306
|
+
children: statusLabel[row.status] ?? row.status
|
|
307
|
+
}
|
|
308
|
+
) }),
|
|
309
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("td", { style: styles.td, children: [
|
|
310
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", style: styles.linkBtn, onClick: () => openEdit(row), children: "\u7F16\u8F91" }),
|
|
311
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
312
|
+
"button",
|
|
313
|
+
{
|
|
314
|
+
type: "button",
|
|
315
|
+
style: { ...styles.linkBtn, color: "#d92d20" },
|
|
316
|
+
onClick: () => void handleDelete(row),
|
|
317
|
+
children: "\u5220\u9664"
|
|
318
|
+
}
|
|
319
|
+
)
|
|
320
|
+
] })
|
|
321
|
+
] }, row.resourceId)) })
|
|
322
|
+
] }) }),
|
|
323
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.pagination, children: [
|
|
324
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: styles.pageSize, children: [
|
|
325
|
+
"\u6BCF\u9875",
|
|
326
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
327
|
+
"select",
|
|
328
|
+
{
|
|
329
|
+
value: pageSize,
|
|
330
|
+
onChange: (e) => {
|
|
331
|
+
setPageToken("");
|
|
332
|
+
setPageSize(e.target.value);
|
|
333
|
+
},
|
|
334
|
+
style: styles.select,
|
|
335
|
+
children: PAGE_SIZE_OPTIONS.map((size) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: size, children: size }, size))
|
|
336
|
+
}
|
|
337
|
+
)
|
|
338
|
+
] }),
|
|
339
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.pageBtns, children: [
|
|
340
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
341
|
+
"button",
|
|
342
|
+
{
|
|
343
|
+
type: "button",
|
|
344
|
+
style: styles.secondaryBtn,
|
|
345
|
+
disabled: !hasPreviousPage || loading,
|
|
346
|
+
onClick: () => void loadList("previous"),
|
|
347
|
+
children: "\u4E0A\u4E00\u9875"
|
|
348
|
+
}
|
|
349
|
+
),
|
|
350
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
351
|
+
"button",
|
|
352
|
+
{
|
|
353
|
+
type: "button",
|
|
354
|
+
style: styles.secondaryBtn,
|
|
355
|
+
disabled: !hasNextPage || loading,
|
|
356
|
+
onClick: () => void loadList("next"),
|
|
357
|
+
children: "\u4E0B\u4E00\u9875"
|
|
358
|
+
}
|
|
359
|
+
)
|
|
360
|
+
] })
|
|
361
|
+
] }),
|
|
362
|
+
dialogOpen ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.mask, onClick: closeDialog, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
363
|
+
"div",
|
|
364
|
+
{
|
|
365
|
+
style: styles.dialog,
|
|
366
|
+
onClick: (e) => e.stopPropagation(),
|
|
367
|
+
role: "dialog",
|
|
368
|
+
"aria-modal": "true",
|
|
369
|
+
children: [
|
|
370
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.dialogHeader, children: [
|
|
371
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { style: styles.dialogTitle, children: editing ? "\u7F16\u8F91\u6743\u9650\u70B9" : "\u65B0\u589E\u6743\u9650\u70B9" }),
|
|
372
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", style: styles.iconBtn, onClick: closeDialog, "aria-label": "\u5173\u95ED", children: "\xD7" })
|
|
373
|
+
] }),
|
|
374
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { style: styles.form, onSubmit: (e) => void handleSubmit(e), children: [
|
|
375
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: styles.field, children: [
|
|
376
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.label, children: "\u6743\u9650\u540D\u79F0" }),
|
|
377
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
378
|
+
"input",
|
|
379
|
+
{
|
|
380
|
+
style: styles.input,
|
|
381
|
+
value: form.name,
|
|
382
|
+
onChange: (e) => setForm((prev) => ({ ...prev, name: e.target.value })),
|
|
383
|
+
placeholder: "\u8BF7\u8F93\u5165\u6743\u9650\u540D\u79F0",
|
|
384
|
+
required: true
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
] }),
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: styles.field, children: [
|
|
389
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.label, children: "\u63A5\u53E3\u6807\u8BC6" }),
|
|
390
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
391
|
+
"input",
|
|
392
|
+
{
|
|
393
|
+
style: styles.input,
|
|
394
|
+
value: form.identification,
|
|
395
|
+
onChange: (e) => setForm((prev) => ({ ...prev, identification: e.target.value })),
|
|
396
|
+
placeholder: "\u5982 user:list",
|
|
397
|
+
required: true
|
|
398
|
+
}
|
|
399
|
+
)
|
|
400
|
+
] }),
|
|
401
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: styles.field, children: [
|
|
402
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.label, children: "\u72B6\u6001" }),
|
|
403
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
404
|
+
"select",
|
|
405
|
+
{
|
|
406
|
+
style: styles.input,
|
|
407
|
+
value: form.status,
|
|
408
|
+
onChange: (e) => setForm((prev) => ({
|
|
409
|
+
...prev,
|
|
410
|
+
status: Number(e.target.value)
|
|
411
|
+
})),
|
|
412
|
+
children: import_resources.RESOURCE_STATUS_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
|
|
413
|
+
}
|
|
414
|
+
)
|
|
415
|
+
] }),
|
|
416
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: styles.field, children: [
|
|
417
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.label, children: "\u79C1\u6709\u8D44\u6E90" }),
|
|
418
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
419
|
+
"select",
|
|
420
|
+
{
|
|
421
|
+
style: styles.input,
|
|
422
|
+
value: form.private ? "1" : "0",
|
|
423
|
+
onChange: (e) => setForm((prev) => ({ ...prev, private: e.target.value === "1" })),
|
|
424
|
+
children: import_resources.RESOURCE_PRIVATE_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: opt.value ? "1" : "0", children: opt.label }, String(opt.value)))
|
|
425
|
+
}
|
|
426
|
+
)
|
|
427
|
+
] }),
|
|
428
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: styles.field, children: [
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.label, children: "\u63CF\u8FF0" }),
|
|
430
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
431
|
+
"textarea",
|
|
432
|
+
{
|
|
433
|
+
style: { ...styles.input, minHeight: 88, resize: "vertical" },
|
|
434
|
+
value: form.description,
|
|
435
|
+
onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
|
|
436
|
+
placeholder: "\u8BF7\u8F93\u5165\u63CF\u8FF0"
|
|
437
|
+
}
|
|
438
|
+
)
|
|
439
|
+
] }),
|
|
440
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.dialogFooter, children: [
|
|
441
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", style: styles.secondaryBtn, onClick: closeDialog, children: "\u53D6\u6D88" }),
|
|
442
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "submit", style: styles.primaryBtn, disabled: saving, children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58" })
|
|
443
|
+
] })
|
|
444
|
+
] })
|
|
445
|
+
]
|
|
446
|
+
}
|
|
447
|
+
) }) : null
|
|
448
|
+
] });
|
|
449
|
+
}
|
|
450
|
+
var styles = {
|
|
451
|
+
root: {
|
|
452
|
+
display: "flex",
|
|
453
|
+
flexDirection: "column",
|
|
454
|
+
gap: 16,
|
|
455
|
+
padding: 16,
|
|
456
|
+
color: "#101828",
|
|
457
|
+
fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
|
|
458
|
+
},
|
|
459
|
+
toolbar: {
|
|
460
|
+
display: "flex",
|
|
461
|
+
alignItems: "center",
|
|
462
|
+
justifyContent: "space-between",
|
|
463
|
+
gap: 12
|
|
464
|
+
},
|
|
465
|
+
title: { margin: 0, fontSize: 18, fontWeight: 600 },
|
|
466
|
+
toolbarRight: { display: "flex", alignItems: "center", gap: 8 },
|
|
467
|
+
error: {
|
|
468
|
+
padding: "10px 12px",
|
|
469
|
+
borderRadius: 8,
|
|
470
|
+
background: "#fef3f2",
|
|
471
|
+
color: "#b42318",
|
|
472
|
+
fontSize: 13
|
|
473
|
+
},
|
|
474
|
+
tableWrap: {
|
|
475
|
+
overflow: "auto",
|
|
476
|
+
border: "1px solid #eaecf0",
|
|
477
|
+
borderRadius: 10,
|
|
478
|
+
background: "#fff"
|
|
479
|
+
},
|
|
480
|
+
table: { width: "100%", borderCollapse: "collapse", minWidth: 720 },
|
|
481
|
+
th: {
|
|
482
|
+
textAlign: "left",
|
|
483
|
+
padding: "12px 14px",
|
|
484
|
+
fontSize: 13,
|
|
485
|
+
fontWeight: 600,
|
|
486
|
+
color: "#475467",
|
|
487
|
+
background: "#f9fafb",
|
|
488
|
+
borderBottom: "1px solid #eaecf0"
|
|
489
|
+
},
|
|
490
|
+
td: {
|
|
491
|
+
padding: "12px 14px",
|
|
492
|
+
fontSize: 14,
|
|
493
|
+
borderBottom: "1px solid #f2f4f7",
|
|
494
|
+
verticalAlign: "middle"
|
|
495
|
+
},
|
|
496
|
+
empty: {
|
|
497
|
+
padding: 28,
|
|
498
|
+
textAlign: "center",
|
|
499
|
+
color: "#98a2b3",
|
|
500
|
+
fontSize: 14
|
|
501
|
+
},
|
|
502
|
+
code: {
|
|
503
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
504
|
+
fontSize: 13,
|
|
505
|
+
background: "#f2f4f7",
|
|
506
|
+
padding: "2px 6px",
|
|
507
|
+
borderRadius: 4
|
|
508
|
+
},
|
|
509
|
+
badge: {
|
|
510
|
+
display: "inline-block",
|
|
511
|
+
padding: "2px 8px",
|
|
512
|
+
borderRadius: 999,
|
|
513
|
+
fontSize: 12,
|
|
514
|
+
fontWeight: 500
|
|
515
|
+
},
|
|
516
|
+
linkBtn: {
|
|
517
|
+
border: "none",
|
|
518
|
+
background: "transparent",
|
|
519
|
+
color: "#049BAD",
|
|
520
|
+
cursor: "pointer",
|
|
521
|
+
padding: "0 8px 0 0",
|
|
522
|
+
fontSize: 13
|
|
523
|
+
},
|
|
524
|
+
pagination: {
|
|
525
|
+
display: "flex",
|
|
526
|
+
alignItems: "center",
|
|
527
|
+
justifyContent: "space-between",
|
|
528
|
+
gap: 12
|
|
529
|
+
},
|
|
530
|
+
pageSize: { display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "#475467" },
|
|
531
|
+
pageBtns: { display: "flex", gap: 8 },
|
|
532
|
+
primaryBtn: {
|
|
533
|
+
border: "none",
|
|
534
|
+
background: "#049BAD",
|
|
535
|
+
color: "#fff",
|
|
536
|
+
borderRadius: 8,
|
|
537
|
+
padding: "8px 14px",
|
|
538
|
+
cursor: "pointer",
|
|
539
|
+
fontSize: 14
|
|
540
|
+
},
|
|
541
|
+
secondaryBtn: {
|
|
542
|
+
border: "1px solid #d0d5dd",
|
|
543
|
+
background: "#fff",
|
|
544
|
+
color: "#344054",
|
|
545
|
+
borderRadius: 8,
|
|
546
|
+
padding: "8px 14px",
|
|
547
|
+
cursor: "pointer",
|
|
548
|
+
fontSize: 14
|
|
549
|
+
},
|
|
550
|
+
select: {
|
|
551
|
+
border: "1px solid #d0d5dd",
|
|
552
|
+
borderRadius: 6,
|
|
553
|
+
padding: "4px 8px",
|
|
554
|
+
fontSize: 13
|
|
555
|
+
},
|
|
556
|
+
mask: {
|
|
557
|
+
position: "fixed",
|
|
558
|
+
inset: 0,
|
|
559
|
+
background: "rgba(16, 24, 40, 0.45)",
|
|
560
|
+
display: "flex",
|
|
561
|
+
alignItems: "center",
|
|
562
|
+
justifyContent: "center",
|
|
563
|
+
zIndex: 1e3,
|
|
564
|
+
padding: 16
|
|
565
|
+
},
|
|
566
|
+
dialog: {
|
|
567
|
+
width: "100%",
|
|
568
|
+
maxWidth: 480,
|
|
569
|
+
background: "#fff",
|
|
570
|
+
borderRadius: 12,
|
|
571
|
+
boxShadow: "0 20px 40px rgba(16,24,40,0.18)"
|
|
572
|
+
},
|
|
573
|
+
dialogHeader: {
|
|
574
|
+
display: "flex",
|
|
575
|
+
alignItems: "center",
|
|
576
|
+
justifyContent: "space-between",
|
|
577
|
+
padding: "14px 16px",
|
|
578
|
+
borderBottom: "1px solid #eaecf0"
|
|
579
|
+
},
|
|
580
|
+
dialogTitle: { margin: 0, fontSize: 16, fontWeight: 600 },
|
|
581
|
+
iconBtn: {
|
|
582
|
+
border: "none",
|
|
583
|
+
background: "transparent",
|
|
584
|
+
fontSize: 22,
|
|
585
|
+
lineHeight: 1,
|
|
586
|
+
cursor: "pointer",
|
|
587
|
+
color: "#667085"
|
|
588
|
+
},
|
|
589
|
+
form: { display: "flex", flexDirection: "column", gap: 12, padding: 16 },
|
|
590
|
+
field: { display: "flex", flexDirection: "column", gap: 6 },
|
|
591
|
+
label: { fontSize: 13, color: "#344054", fontWeight: 500 },
|
|
592
|
+
input: {
|
|
593
|
+
border: "1px solid #d0d5dd",
|
|
594
|
+
borderRadius: 8,
|
|
595
|
+
padding: "8px 10px",
|
|
596
|
+
fontSize: 14,
|
|
597
|
+
outline: "none"
|
|
598
|
+
},
|
|
599
|
+
dialogFooter: {
|
|
600
|
+
display: "flex",
|
|
601
|
+
justifyContent: "flex-end",
|
|
602
|
+
gap: 8,
|
|
603
|
+
paddingTop: 4
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
|
|
144
607
|
// src/react/index.ts
|
|
145
608
|
var import_core2 = require("../core");
|
|
609
|
+
var import_snowflake = require("../utils/snowflake");
|
|
610
|
+
var import_resources2 = require("../resources");
|
|
146
611
|
// Annotate the CommonJS export names for ESM import in node:
|
|
147
612
|
0 && (module.exports = {
|
|
148
613
|
Can,
|
|
149
614
|
PermissionProvider,
|
|
150
615
|
PermissionStore,
|
|
616
|
+
RESOURCE_PRIVATE_OPTIONS,
|
|
617
|
+
RESOURCE_STATUS_DISABLED,
|
|
618
|
+
RESOURCE_STATUS_ENABLED,
|
|
619
|
+
RESOURCE_STATUS_OPTIONS,
|
|
620
|
+
RESOURCE_TYPE_API,
|
|
621
|
+
ResourceManager,
|
|
622
|
+
appendQueryParam,
|
|
623
|
+
buildCreateBody,
|
|
624
|
+
buildUpdateBody,
|
|
625
|
+
createAuthorizationResourceApi,
|
|
626
|
+
createDefaultResourceRequest,
|
|
151
627
|
createPermissionStore,
|
|
628
|
+
extractPagination,
|
|
629
|
+
extractRecords,
|
|
630
|
+
getAppClientId,
|
|
631
|
+
getDeviceWorkerId,
|
|
632
|
+
mapAuthorizationResource,
|
|
633
|
+
snowyflake,
|
|
152
634
|
useHasPermission,
|
|
153
635
|
useHasRole,
|
|
154
636
|
usePermission
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/index.ts","../../src/react/context.tsx","../../src/react/Can.tsx"],"sourcesContent":["export { PermissionProvider, usePermission, useHasPermission, useHasRole } from './context';\nexport type { PermissionProviderProps, UsePermissionResult } from './context';\n\nexport { Can } from './Can';\nexport type { CanProps } from './Can';\n\nexport type {\n CheckOptions,\n MatchMode,\n PermissionChecker,\n PermissionCode,\n PermissionListener,\n PermissionState,\n RoleCode,\n} from '../core';\n\nexport { PermissionStore, createPermissionStore } from '../core';\n","import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n createPermissionStore,\n type CheckOptions,\n type PermissionCode,\n type PermissionState,\n type PermissionStore,\n type RoleCode,\n} from '../core';\n\nconst PermissionContext = createContext<PermissionStore | null>(null);\n\nexport interface PermissionProviderProps {\n children: ReactNode;\n /** Pass an existing store to share across trees, or omit to create one. */\n store?: PermissionStore;\n /** Initial state when the provider creates its own store. */\n initialState?: Partial<PermissionState>;\n}\n\nexport function PermissionProvider({\n children,\n store: externalStore,\n initialState,\n}: PermissionProviderProps) {\n const store = useMemo(\n () => externalStore ?? createPermissionStore(initialState),\n // store identity is intentional; initialState only applies on first create\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [externalStore],\n );\n\n return createElement(PermissionContext.Provider, { value: store }, children);\n}\n\nfunction useStore(): PermissionStore {\n const store = useContext(PermissionContext);\n if (!store) {\n throw new Error(\n '[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>.',\n );\n }\n return store;\n}\n\nfunction usePermissionSnapshot(store: PermissionStore): PermissionState {\n const [state, setState] = useState(() => store.getState());\n\n useEffect(() => {\n setState(store.getState());\n return store.subscribe(setState);\n }, [store]);\n\n return state;\n}\n\nexport interface UsePermissionResult {\n permissions: PermissionCode[];\n roles: RoleCode[];\n isSuperAdmin: boolean;\n hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;\n can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n setPermissions: (permissions: PermissionCode[]) => void;\n setRoles: (roles: RoleCode[]) => void;\n setSuperAdmin: (isSuperAdmin: boolean) => void;\n hydrate: (payload: Partial<PermissionState>) => void;\n clear: () => void;\n store: PermissionStore;\n}\n\nexport function usePermission(): UsePermissionResult {\n const store = useStore();\n const state = usePermissionSnapshot(store);\n\n const hasPermission = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) =>\n store.hasPermission(codes, options),\n [store],\n );\n\n const hasRole = useCallback(\n (codes: RoleCode | RoleCode[], options?: CheckOptions) => store.hasRole(codes, options),\n [store],\n );\n\n const can = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => store.can(codes, options),\n [store],\n );\n\n return {\n permissions: state.permissions,\n roles: state.roles,\n isSuperAdmin: Boolean(state.isSuperAdmin),\n hasPermission,\n hasRole,\n can,\n setPermissions: store.setPermissions.bind(store),\n setRoles: store.setRoles.bind(store),\n setSuperAdmin: store.setSuperAdmin.bind(store),\n hydrate: store.hydrate.bind(store),\n clear: store.clear.bind(store),\n store,\n };\n}\n\n/** Returns whether the current user has the given permission(s). */\nexport function useHasPermission(\n codes: PermissionCode | PermissionCode[],\n options?: CheckOptions,\n): boolean {\n const { hasPermission, permissions, isSuperAdmin } = usePermission();\n // re-compute when permission list / super-admin changes\n void permissions;\n void isSuperAdmin;\n return hasPermission(codes, options);\n}\n\n/** Returns whether the current user has the given role(s). */\nexport function useHasRole(\n codes: RoleCode | RoleCode[],\n options?: CheckOptions,\n): boolean {\n const { hasRole, roles, isSuperAdmin } = usePermission();\n void roles;\n void isSuperAdmin;\n return hasRole(codes, options);\n}\n","import type { ReactNode } from 'react';\nimport type { CheckOptions, PermissionCode, RoleCode } from '../core';\nimport { usePermission } from './context';\n\nexport interface CanProps {\n /** Permission codes to check. */\n permission?: PermissionCode | PermissionCode[];\n /** Role codes to check. */\n role?: RoleCode | RoleCode[];\n /**\n * `any` — pass when at least one code matches (default)\n * `all` — pass only when every code matches\n */\n mode?: CheckOptions['mode'];\n /**\n * How permission and role conditions combine when both are provided.\n * Default: `and` (must satisfy both).\n */\n combine?: 'and' | 'or';\n children: ReactNode;\n /** Fallback when access is denied. */\n fallback?: ReactNode;\n}\n\nfunction evaluateAccess(\n hasPermission: (c: PermissionCode | PermissionCode[], o?: CheckOptions) => boolean,\n hasRole: (c: RoleCode | RoleCode[], o?: CheckOptions) => boolean,\n props: Pick<CanProps, 'permission' | 'role' | 'mode' | 'combine'>,\n): boolean {\n const { permission, role, mode, combine = 'and' } = props;\n const options: CheckOptions = { mode };\n\n const hasPermCheck = permission !== undefined;\n const hasRoleCheck = role !== undefined;\n\n if (!hasPermCheck && !hasRoleCheck) return true;\n\n const permOk = hasPermCheck ? hasPermission(permission!, options) : true;\n const roleOk = hasRoleCheck ? hasRole(role!, options) : true;\n\n if (hasPermCheck && hasRoleCheck) {\n return combine === 'or' ? permOk || roleOk : permOk && roleOk;\n }\n\n return hasPermCheck ? permOk : roleOk;\n}\n\n/**\n * Conditionally render children based on permission / role.\n *\n * @example\n * <Can permission=\"user:edit\">\n * <button>Edit</button>\n * </Can>\n *\n * <Can permission={['user:edit', 'user:delete']} mode=\"all\" fallback={null}>\n * <AdminPanel />\n * </Can>\n */\nexport function Can({\n permission,\n role,\n mode,\n combine,\n children,\n fallback = null,\n}: CanProps) {\n const { hasPermission, hasRole } = usePermission();\n const allowed = evaluateAccess(hasPermission, hasRole, {\n permission,\n role,\n mode,\n combine,\n });\n\n return <>{allowed ? children : fallback}</>;\n}\n"],"mappings":"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","names":["import_core"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/context.tsx","../../src/react/Can.tsx","../../src/react/ResourceManager.tsx"],"sourcesContent":["export { PermissionProvider, usePermission, useHasPermission, useHasRole } from './context';\nexport type { PermissionProviderProps, UsePermissionResult } from './context';\n\nexport { Can } from './Can';\nexport type { CanProps } from './Can';\n\nexport { ResourceManager } from './ResourceManager';\nexport type { ResourceManagerProps } from './ResourceManager';\n\nexport type {\n CheckOptions,\n MatchMode,\n PermissionChecker,\n PermissionCode,\n PermissionListener,\n PermissionState,\n RoleCode,\n} from '../core';\n\nexport { PermissionStore, createPermissionStore } from '../core';\n\nexport { getAppClientId, getDeviceWorkerId, snowyflake } from '../utils/snowflake';\n\nexport type {\n AuthorizationResource,\n AuthorizationResourceApi,\n AuthorizationResourceFormValues,\n AuthorizationResourceListResult,\n CreateAuthorizationResourceBody,\n CreateDefaultResourceRequestOptions,\n FetchAuthorizationResourcesParams,\n HttpMethod,\n ListPaginationParams,\n ListPaginationResult,\n PageDirection,\n ResourceHttpRequest,\n ResourceRequestOptions,\n ResourceStatus,\n UpdateAuthorizationResourceBody,\n} from '../resources';\n\nexport {\n RESOURCE_PRIVATE_OPTIONS,\n RESOURCE_STATUS_DISABLED,\n RESOURCE_STATUS_ENABLED,\n RESOURCE_STATUS_OPTIONS,\n RESOURCE_TYPE_API,\n appendQueryParam,\n buildCreateBody,\n buildUpdateBody,\n createAuthorizationResourceApi,\n createDefaultResourceRequest,\n extractPagination,\n extractRecords,\n mapAuthorizationResource,\n} from '../resources';\n","import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n createPermissionStore,\n type CheckOptions,\n type PermissionCode,\n type PermissionState,\n type PermissionStore,\n type RoleCode,\n} from '../core';\n\nconst PermissionContext = createContext<PermissionStore | null>(null);\n\nexport interface PermissionProviderProps {\n children: ReactNode;\n /** Pass an existing store to share across trees, or omit to create one. */\n store?: PermissionStore;\n /** Initial state when the provider creates its own store. */\n initialState?: Partial<PermissionState>;\n}\n\nexport function PermissionProvider({\n children,\n store: externalStore,\n initialState,\n}: PermissionProviderProps) {\n const store = useMemo(\n () => externalStore ?? createPermissionStore(initialState),\n // store identity is intentional; initialState only applies on first create\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [externalStore],\n );\n\n return createElement(PermissionContext.Provider, { value: store }, children);\n}\n\nfunction useStore(): PermissionStore {\n const store = useContext(PermissionContext);\n if (!store) {\n throw new Error(\n '[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>.',\n );\n }\n return store;\n}\n\nfunction usePermissionSnapshot(store: PermissionStore): PermissionState {\n const [state, setState] = useState(() => store.getState());\n\n useEffect(() => {\n setState(store.getState());\n return store.subscribe(setState);\n }, [store]);\n\n return state;\n}\n\nexport interface UsePermissionResult {\n permissions: PermissionCode[];\n roles: RoleCode[];\n isSuperAdmin: boolean;\n hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;\n can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n setPermissions: (permissions: PermissionCode[]) => void;\n setRoles: (roles: RoleCode[]) => void;\n setSuperAdmin: (isSuperAdmin: boolean) => void;\n hydrate: (payload: Partial<PermissionState>) => void;\n clear: () => void;\n store: PermissionStore;\n}\n\nexport function usePermission(): UsePermissionResult {\n const store = useStore();\n const state = usePermissionSnapshot(store);\n\n const hasPermission = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) =>\n store.hasPermission(codes, options),\n [store],\n );\n\n const hasRole = useCallback(\n (codes: RoleCode | RoleCode[], options?: CheckOptions) => store.hasRole(codes, options),\n [store],\n );\n\n const can = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => store.can(codes, options),\n [store],\n );\n\n return {\n permissions: state.permissions,\n roles: state.roles,\n isSuperAdmin: Boolean(state.isSuperAdmin),\n hasPermission,\n hasRole,\n can,\n setPermissions: store.setPermissions.bind(store),\n setRoles: store.setRoles.bind(store),\n setSuperAdmin: store.setSuperAdmin.bind(store),\n hydrate: store.hydrate.bind(store),\n clear: store.clear.bind(store),\n store,\n };\n}\n\n/** Returns whether the current user has the given permission(s). */\nexport function useHasPermission(\n codes: PermissionCode | PermissionCode[],\n options?: CheckOptions,\n): boolean {\n const { hasPermission, permissions, isSuperAdmin } = usePermission();\n // re-compute when permission list / super-admin changes\n void permissions;\n void isSuperAdmin;\n return hasPermission(codes, options);\n}\n\n/** Returns whether the current user has the given role(s). */\nexport function useHasRole(\n codes: RoleCode | RoleCode[],\n options?: CheckOptions,\n): boolean {\n const { hasRole, roles, isSuperAdmin } = usePermission();\n void roles;\n void isSuperAdmin;\n return hasRole(codes, options);\n}\n","import type { ReactNode } from 'react';\nimport type { CheckOptions, PermissionCode, RoleCode } from '../core';\nimport { usePermission } from './context';\n\nexport interface CanProps {\n /** Permission codes to check. */\n permission?: PermissionCode | PermissionCode[];\n /** Role codes to check. */\n role?: RoleCode | RoleCode[];\n /**\n * `any` — pass when at least one code matches (default)\n * `all` — pass only when every code matches\n */\n mode?: CheckOptions['mode'];\n /**\n * How permission and role conditions combine when both are provided.\n * Default: `and` (must satisfy both).\n */\n combine?: 'and' | 'or';\n children: ReactNode;\n /** Fallback when access is denied. */\n fallback?: ReactNode;\n}\n\nfunction evaluateAccess(\n hasPermission: (c: PermissionCode | PermissionCode[], o?: CheckOptions) => boolean,\n hasRole: (c: RoleCode | RoleCode[], o?: CheckOptions) => boolean,\n props: Pick<CanProps, 'permission' | 'role' | 'mode' | 'combine'>,\n): boolean {\n const { permission, role, mode, combine = 'and' } = props;\n const options: CheckOptions = { mode };\n\n const hasPermCheck = permission !== undefined;\n const hasRoleCheck = role !== undefined;\n\n if (!hasPermCheck && !hasRoleCheck) return true;\n\n const permOk = hasPermCheck ? hasPermission(permission!, options) : true;\n const roleOk = hasRoleCheck ? hasRole(role!, options) : true;\n\n if (hasPermCheck && hasRoleCheck) {\n return combine === 'or' ? permOk || roleOk : permOk && roleOk;\n }\n\n return hasPermCheck ? permOk : roleOk;\n}\n\n/**\n * Conditionally render children based on permission / role.\n *\n * @example\n * <Can permission=\"user:edit\">\n * <button>Edit</button>\n * </Can>\n *\n * <Can permission={['user:edit', 'user:delete']} mode=\"all\" fallback={null}>\n * <AdminPanel />\n * </Can>\n */\nexport function Can({\n permission,\n role,\n mode,\n combine,\n children,\n fallback = null,\n}: CanProps) {\n const { hasPermission, hasRole } = usePermission();\n const allowed = evaluateAccess(hasPermission, hasRole, {\n permission,\n role,\n mode,\n combine,\n });\n\n return <>{allowed ? children : fallback}</>;\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type CSSProperties,\n type FormEvent,\n type ReactNode,\n} from 'react';\nimport {\n RESOURCE_PRIVATE_OPTIONS,\n RESOURCE_STATUS_ENABLED,\n RESOURCE_STATUS_OPTIONS,\n type AuthorizationResource,\n type AuthorizationResourceApi,\n type AuthorizationResourceFormValues,\n type PageDirection,\n} from '../resources';\n\nconst PAGE_SIZE_OPTIONS = ['10', '20', '50', '100'];\n\nconst emptyForm = (): AuthorizationResourceFormValues => ({\n name: '',\n identification: '',\n status: RESOURCE_STATUS_ENABLED,\n private: false,\n description: '',\n});\n\nexport type ResourceManagerProps = {\n api: AuthorizationResourceApi;\n title?: string;\n pageSize?: string;\n /** 自定义顶部右侧操作区 */\n toolbarExtra?: ReactNode;\n};\n\nexport function ResourceManager({\n api,\n title = '权限点管理',\n pageSize: initialPageSize = '20',\n toolbarExtra,\n}: ResourceManagerProps) {\n const [records, setRecords] = useState<AuthorizationResource[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [pageSize, setPageSize] = useState(initialPageSize);\n const [pageToken, setPageToken] = useState('');\n const [hasPreviousPage, setHasPreviousPage] = useState(false);\n const [hasNextPage, setHasNextPage] = useState(false);\n\n const [dialogOpen, setDialogOpen] = useState(false);\n const [editing, setEditing] = useState<AuthorizationResource | null>(null);\n const [form, setForm] = useState<AuthorizationResourceFormValues>(emptyForm);\n const [saving, setSaving] = useState(false);\n\n const loadList = useCallback(\n async (direction: PageDirection = 'current', token = pageToken) => {\n setLoading(true);\n setError('');\n try {\n const result = await api.list({\n pagination: {\n pageToken: token,\n pageSize,\n pageDirection: direction,\n },\n });\n setRecords(result.records);\n setPageToken(result.pageToken);\n setHasPreviousPage(result.hasPreviousPage);\n setHasNextPage(result.hasNextPage);\n } catch (err) {\n setError(err instanceof Error ? err.message : '加载失败');\n } finally {\n setLoading(false);\n }\n },\n [api, pageSize, pageToken],\n );\n\n useEffect(() => {\n void loadList('current', '');\n // 仅 pageSize / api 变化时重置首页\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [api, pageSize]);\n\n const openCreate = () => {\n setEditing(null);\n setForm(emptyForm());\n setDialogOpen(true);\n };\n\n const openEdit = (row: AuthorizationResource) => {\n setEditing(row);\n setForm({\n name: row.name,\n identification: row.identification,\n status: row.status,\n private: row.private,\n description: row.description,\n });\n setDialogOpen(true);\n };\n\n const closeDialog = () => {\n if (saving) return;\n setDialogOpen(false);\n };\n\n const handleSubmit = async (event: FormEvent) => {\n event.preventDefault();\n if (!form.name.trim()) {\n setError('请填写权限名称');\n return;\n }\n if (!form.identification.trim()) {\n setError('请填写接口标识');\n return;\n }\n\n setSaving(true);\n setError('');\n try {\n if (editing) {\n await api.update(editing.resourceId, form);\n } else {\n await api.create(form);\n }\n setDialogOpen(false);\n await loadList('current', '');\n } catch (err) {\n setError(err instanceof Error ? err.message : '保存失败');\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async (row: AuthorizationResource) => {\n if (!window.confirm(`确认删除权限点「${row.name}」?`)) return;\n setError('');\n try {\n await api.remove(row.resourceId);\n await loadList('current', '');\n } catch (err) {\n setError(err instanceof Error ? err.message : '删除失败');\n }\n };\n\n const statusLabel = useMemo(\n () =>\n Object.fromEntries(RESOURCE_STATUS_OPTIONS.map((o) => [o.value, o.label])) as Record<\n number,\n string\n >,\n [],\n );\n\n return (\n <div style={styles.root}>\n <div style={styles.toolbar}>\n <h2 style={styles.title}>{title}</h2>\n <div style={styles.toolbarRight}>\n {toolbarExtra}\n <button type=\"button\" style={styles.primaryBtn} onClick={openCreate}>\n 新增\n </button>\n </div>\n </div>\n\n {error ? <div style={styles.error}>{error}</div> : null}\n\n <div style={styles.tableWrap}>\n <table style={styles.table}>\n <thead>\n <tr>\n <th style={styles.th}>权限名称</th>\n <th style={styles.th}>接口标识</th>\n <th style={styles.th}>描述</th>\n <th style={{ ...styles.th, width: 90 }}>状态</th>\n <th style={{ ...styles.th, width: 140 }}>操作</th>\n </tr>\n </thead>\n <tbody>\n {loading ? (\n <tr>\n <td colSpan={5} style={styles.empty}>\n 加载中…\n </td>\n </tr>\n ) : records.length === 0 ? (\n <tr>\n <td colSpan={5} style={styles.empty}>\n 暂无数据\n </td>\n </tr>\n ) : (\n records.map((row) => (\n <tr key={row.resourceId}>\n <td style={styles.td}>{row.name}</td>\n <td style={styles.td}>\n <code style={styles.code}>{row.identification}</code>\n </td>\n <td style={styles.td}>{row.description || '—'}</td>\n <td style={styles.td}>\n <span\n style={{\n ...styles.badge,\n background:\n row.status === RESOURCE_STATUS_ENABLED ? '#e8f7ef' : '#f4f4f5',\n color: row.status === RESOURCE_STATUS_ENABLED ? '#067647' : '#667085',\n }}\n >\n {statusLabel[row.status] ?? row.status}\n </span>\n </td>\n <td style={styles.td}>\n <button type=\"button\" style={styles.linkBtn} onClick={() => openEdit(row)}>\n 编辑\n </button>\n <button\n type=\"button\"\n style={{ ...styles.linkBtn, color: '#d92d20' }}\n onClick={() => void handleDelete(row)}\n >\n 删除\n </button>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n <div style={styles.pagination}>\n <label style={styles.pageSize}>\n 每页\n <select\n value={pageSize}\n onChange={(e) => {\n setPageToken('');\n setPageSize(e.target.value);\n }}\n style={styles.select}\n >\n {PAGE_SIZE_OPTIONS.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n </label>\n <div style={styles.pageBtns}>\n <button\n type=\"button\"\n style={styles.secondaryBtn}\n disabled={!hasPreviousPage || loading}\n onClick={() => void loadList('previous')}\n >\n 上一页\n </button>\n <button\n type=\"button\"\n style={styles.secondaryBtn}\n disabled={!hasNextPage || loading}\n onClick={() => void loadList('next')}\n >\n 下一页\n </button>\n </div>\n </div>\n\n {dialogOpen ? (\n <div style={styles.mask} onClick={closeDialog}>\n <div\n style={styles.dialog}\n onClick={(e) => e.stopPropagation()}\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <div style={styles.dialogHeader}>\n <h3 style={styles.dialogTitle}>{editing ? '编辑权限点' : '新增权限点'}</h3>\n <button type=\"button\" style={styles.iconBtn} onClick={closeDialog} aria-label=\"关闭\">\n ×\n </button>\n </div>\n <form style={styles.form} onSubmit={(e) => void handleSubmit(e)}>\n <label style={styles.field}>\n <span style={styles.label}>权限名称</span>\n <input\n style={styles.input}\n value={form.name}\n onChange={(e) => setForm((prev) => ({ ...prev, name: e.target.value }))}\n placeholder=\"请输入权限名称\"\n required\n />\n </label>\n <label style={styles.field}>\n <span style={styles.label}>接口标识</span>\n <input\n style={styles.input}\n value={form.identification}\n onChange={(e) =>\n setForm((prev) => ({ ...prev, identification: e.target.value }))\n }\n placeholder=\"如 user:list\"\n required\n />\n </label>\n <label style={styles.field}>\n <span style={styles.label}>状态</span>\n <select\n style={styles.input}\n value={form.status}\n onChange={(e) =>\n setForm((prev) => ({\n ...prev,\n status: Number(e.target.value) as 0 | 1,\n }))\n }\n >\n {RESOURCE_STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n <label style={styles.field}>\n <span style={styles.label}>私有资源</span>\n <select\n style={styles.input}\n value={form.private ? '1' : '0'}\n onChange={(e) =>\n setForm((prev) => ({ ...prev, private: e.target.value === '1' }))\n }\n >\n {RESOURCE_PRIVATE_OPTIONS.map((opt) => (\n <option key={String(opt.value)} value={opt.value ? '1' : '0'}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n <label style={styles.field}>\n <span style={styles.label}>描述</span>\n <textarea\n style={{ ...styles.input, minHeight: 88, resize: 'vertical' }}\n value={form.description}\n onChange={(e) =>\n setForm((prev) => ({ ...prev, description: e.target.value }))\n }\n placeholder=\"请输入描述\"\n />\n </label>\n <div style={styles.dialogFooter}>\n <button type=\"button\" style={styles.secondaryBtn} onClick={closeDialog}>\n 取消\n </button>\n <button type=\"submit\" style={styles.primaryBtn} disabled={saving}>\n {saving ? '保存中…' : '保存'}\n </button>\n </div>\n </form>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nconst styles: Record<string, CSSProperties> = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n gap: 16,\n padding: 16,\n color: '#101828',\n fontFamily:\n '\"PingFang SC\", \"Microsoft YaHei\", -apple-system, BlinkMacSystemFont, sans-serif',\n },\n toolbar: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n },\n title: { margin: 0, fontSize: 18, fontWeight: 600 },\n toolbarRight: { display: 'flex', alignItems: 'center', gap: 8 },\n error: {\n padding: '10px 12px',\n borderRadius: 8,\n background: '#fef3f2',\n color: '#b42318',\n fontSize: 13,\n },\n tableWrap: {\n overflow: 'auto',\n border: '1px solid #eaecf0',\n borderRadius: 10,\n background: '#fff',\n },\n table: { width: '100%', borderCollapse: 'collapse', minWidth: 720 },\n th: {\n textAlign: 'left',\n padding: '12px 14px',\n fontSize: 13,\n fontWeight: 600,\n color: '#475467',\n background: '#f9fafb',\n borderBottom: '1px solid #eaecf0',\n },\n td: {\n padding: '12px 14px',\n fontSize: 14,\n borderBottom: '1px solid #f2f4f7',\n verticalAlign: 'middle',\n },\n empty: {\n padding: 28,\n textAlign: 'center',\n color: '#98a2b3',\n fontSize: 14,\n },\n code: {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: 13,\n background: '#f2f4f7',\n padding: '2px 6px',\n borderRadius: 4,\n },\n badge: {\n display: 'inline-block',\n padding: '2px 8px',\n borderRadius: 999,\n fontSize: 12,\n fontWeight: 500,\n },\n linkBtn: {\n border: 'none',\n background: 'transparent',\n color: '#049BAD',\n cursor: 'pointer',\n padding: '0 8px 0 0',\n fontSize: 13,\n },\n pagination: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n },\n pageSize: { display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: '#475467' },\n pageBtns: { display: 'flex', gap: 8 },\n primaryBtn: {\n border: 'none',\n background: '#049BAD',\n color: '#fff',\n borderRadius: 8,\n padding: '8px 14px',\n cursor: 'pointer',\n fontSize: 14,\n },\n secondaryBtn: {\n border: '1px solid #d0d5dd',\n background: '#fff',\n color: '#344054',\n borderRadius: 8,\n padding: '8px 14px',\n cursor: 'pointer',\n fontSize: 14,\n },\n select: {\n border: '1px solid #d0d5dd',\n borderRadius: 6,\n padding: '4px 8px',\n fontSize: 13,\n },\n mask: {\n position: 'fixed',\n inset: 0,\n background: 'rgba(16, 24, 40, 0.45)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1000,\n padding: 16,\n },\n dialog: {\n width: '100%',\n maxWidth: 480,\n background: '#fff',\n borderRadius: 12,\n boxShadow: '0 20px 40px rgba(16,24,40,0.18)',\n },\n dialogHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '14px 16px',\n borderBottom: '1px solid #eaecf0',\n },\n dialogTitle: { margin: 0, fontSize: 16, fontWeight: 600 },\n iconBtn: {\n border: 'none',\n background: 'transparent',\n fontSize: 22,\n lineHeight: 1,\n cursor: 'pointer',\n color: '#667085',\n },\n form: { display: 'flex', flexDirection: 'column', gap: 12, padding: 16 },\n field: { display: 'flex', flexDirection: 'column', gap: 6 },\n label: { fontSize: 13, color: '#344054', fontWeight: 500 },\n input: {\n border: '1px solid #d0d5dd',\n borderRadius: 8,\n padding: '8px 10px',\n fontSize: 14,\n outline: 'none',\n },\n dialogFooter: {\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 8,\n paddingTop: 4,\n },\n};\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_core","import_resources"]}
|