com-angel-authorization 1.0.5 → 1.0.6

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.
@@ -22,6 +22,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  var react_exports = {};
23
23
  __export(react_exports, {
24
24
  Can: () => Can,
25
+ MENU_LIST_TYPE_PARAM: () => MENU_LIST_TYPE_PARAM,
26
+ MENU_TYPE_BUTTON: () => MENU_TYPE_BUTTON,
27
+ MENU_TYPE_LABEL: () => MENU_TYPE_LABEL,
28
+ MENU_TYPE_MENU: () => MENU_TYPE_MENU,
29
+ MENU_TYPE_OPTIONS: () => MENU_TYPE_OPTIONS,
30
+ MENU_TYPE_PAGE: () => MENU_TYPE_PAGE,
31
+ MENU_VISIBILITY_OPTIONS: () => MENU_VISIBILITY_OPTIONS,
32
+ MenuManager: () => MenuManager,
25
33
  PermissionProvider: () => PermissionProvider,
26
34
  PermissionStore: () => PermissionStore,
27
35
  RESOURCE_PRIVATE_OPTIONS: () => RESOURCE_PRIVATE_OPTIONS,
@@ -29,18 +37,23 @@ __export(react_exports, {
29
37
  RESOURCE_STATUS_ENABLED: () => RESOURCE_STATUS_ENABLED,
30
38
  RESOURCE_STATUS_OPTIONS: () => RESOURCE_STATUS_OPTIONS,
31
39
  RESOURCE_TYPE_API: () => RESOURCE_TYPE_API,
40
+ ROOT_PARENT_ID: () => ROOT_PARENT_ID,
32
41
  ResourceManager: () => ResourceManager,
33
42
  appendQueryParam: () => appendQueryParam,
34
43
  buildCreateBody: () => buildCreateBody,
44
+ buildCreateMenuBody: () => buildCreateMenuBody,
35
45
  buildUpdateBody: () => buildUpdateBody,
46
+ buildUpdateMenuBody: () => buildUpdateMenuBody,
36
47
  createAuthorizationResourceApi: () => createAuthorizationResourceApi,
37
48
  createDefaultResourceRequest: () => createDefaultResourceRequest,
49
+ createMenuResourceApi: () => createMenuResourceApi,
38
50
  createPermissionStore: () => createPermissionStore,
39
51
  extractPagination: () => extractPagination,
40
52
  extractRecords: () => extractRecords,
41
53
  getAppClientId: () => getAppClientId,
42
54
  getDeviceWorkerId: () => getDeviceWorkerId,
43
55
  mapAuthorizationResource: () => mapAuthorizationResource,
56
+ mapMenuResource: () => mapMenuResource,
44
57
  snowyflake: () => snowyflake,
45
58
  useHasPermission: () => useHasPermission,
46
59
  useHasRole: () => useHasRole,
@@ -268,16 +281,35 @@ var import_react2 = require("react");
268
281
 
269
282
  // src/resources/types.ts
270
283
  var RESOURCE_TYPE_API = "api";
284
+ var MENU_TYPE_PAGE = "page";
285
+ var MENU_TYPE_MENU = "menu";
286
+ var MENU_TYPE_BUTTON = "button";
287
+ var MENU_LIST_TYPE_PARAM = "page,menu,button";
288
+ var ROOT_PARENT_ID = "0";
271
289
  var RESOURCE_STATUS_ENABLED = 1;
272
290
  var RESOURCE_STATUS_DISABLED = 0;
273
291
  var RESOURCE_STATUS_OPTIONS = [
274
292
  { label: "\u542F\u7528", value: RESOURCE_STATUS_ENABLED },
275
293
  { label: "\u7981\u7528", value: RESOURCE_STATUS_DISABLED }
276
294
  ];
295
+ var MENU_VISIBILITY_OPTIONS = [
296
+ { label: "\u663E\u793A", value: RESOURCE_STATUS_ENABLED },
297
+ { label: "\u9690\u85CF", value: RESOURCE_STATUS_DISABLED }
298
+ ];
277
299
  var RESOURCE_PRIVATE_OPTIONS = [
278
300
  { label: "\u662F", value: true },
279
301
  { label: "\u5426", value: false }
280
302
  ];
303
+ var MENU_TYPE_OPTIONS = [
304
+ { label: "\u76EE\u5F55", value: MENU_TYPE_PAGE },
305
+ { label: "\u83DC\u5355", value: MENU_TYPE_MENU },
306
+ { label: "\u6309\u94AE", value: MENU_TYPE_BUTTON }
307
+ ];
308
+ var MENU_TYPE_LABEL = {
309
+ page: "\u76EE\u5F55",
310
+ menu: "\u83DC\u5355",
311
+ button: "\u6309\u94AE"
312
+ };
281
313
 
282
314
  // src/utils/snowflake.ts
283
315
  var DEVICE_WORKER_ID_KEY = "hgams_device_worker_id";
@@ -422,6 +454,29 @@ function toBoolean(value) {
422
454
  }
423
455
  return false;
424
456
  }
457
+ function toStringArray(value) {
458
+ if (Array.isArray(value)) {
459
+ return value.map((item) => {
460
+ if (item && typeof item === "object") {
461
+ const row = item;
462
+ const id = row.resourceId ?? row.resource_id ?? row.id;
463
+ return id === void 0 || id === null ? "" : String(id);
464
+ }
465
+ return String(item ?? "");
466
+ }).filter(Boolean);
467
+ }
468
+ if (typeof value === "string" && value.trim()) {
469
+ return value.split(",").map((s) => s.trim()).filter(Boolean);
470
+ }
471
+ return [];
472
+ }
473
+ function toMenuType(value) {
474
+ const v = String(value ?? "").toLowerCase();
475
+ if (v === MENU_TYPE_PAGE || v === MENU_TYPE_MENU || v === MENU_TYPE_BUTTON) {
476
+ return v;
477
+ }
478
+ return MENU_TYPE_MENU;
479
+ }
425
480
  function mapAuthorizationResource(item) {
426
481
  if (!item || typeof item !== "object") return null;
427
482
  const row = item;
@@ -437,9 +492,31 @@ function mapAuthorizationResource(item) {
437
492
  description: String(row.description ?? row.desc ?? "")
438
493
  };
439
494
  }
440
- function buildListUrl(params) {
495
+ function mapMenuResource(item) {
496
+ if (!item || typeof item !== "object") return null;
497
+ const row = item;
498
+ const resourceId = row.resourceId ?? row.resource_id ?? row.id;
499
+ if (resourceId === void 0 || resourceId === null || resourceId === "") return null;
500
+ const permissionPointIds = toStringArray(
501
+ row.permissionPointIds ?? row.permission_point_ids ?? row.permissionPoints ?? row.permissions
502
+ );
503
+ const permissionNamesRaw = row.permissionPointNames ?? row.permission_point_names ?? row.permissionNames;
504
+ const permissionPointNames = Array.isArray(permissionNamesRaw) ? permissionNamesRaw.map((n) => String(n ?? "")).filter(Boolean) : void 0;
505
+ const parentId = row.parentId ?? row.parent_id ?? ROOT_PARENT_ID;
506
+ return {
507
+ resourceId: String(resourceId),
508
+ parentId: parentId === void 0 || parentId === null ? ROOT_PARENT_ID : String(parentId),
509
+ type: toMenuType(row.type),
510
+ name: String(row.name ?? ""),
511
+ identification: String(row.identification ?? row.identity ?? row.path ?? ""),
512
+ permissionPointIds,
513
+ permissionPointNames,
514
+ status: toResourceStatus(row.status)
515
+ };
516
+ }
517
+ function buildListUrl(type, params) {
441
518
  const parts = [];
442
- appendQueryParam(parts, "type", RESOURCE_TYPE_API);
519
+ appendQueryParam(parts, "type", type);
443
520
  appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
444
521
  appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
445
522
  appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
@@ -466,12 +543,33 @@ function buildUpdateBody(values) {
466
543
  description: values.description.trim()
467
544
  };
468
545
  }
546
+ function buildCreateMenuBody(values, resourceId = getAppClientId()) {
547
+ return {
548
+ resourceId,
549
+ parentId: values.parentId || ROOT_PARENT_ID,
550
+ type: values.type,
551
+ name: values.name.trim(),
552
+ identification: values.identification.trim(),
553
+ permissionPointIds: [...values.permissionPointIds],
554
+ status: values.status
555
+ };
556
+ }
557
+ function buildUpdateMenuBody(values) {
558
+ return {
559
+ parentId: values.parentId || ROOT_PARENT_ID,
560
+ type: values.type,
561
+ name: values.name.trim(),
562
+ identification: values.identification.trim(),
563
+ permissionPointIds: [...values.permissionPointIds],
564
+ status: values.status
565
+ };
566
+ }
469
567
  function createAuthorizationResourceApi(request) {
470
568
  return {
471
569
  async list(params, signal) {
472
570
  const json = await request({
473
571
  method: "GET",
474
- url: buildListUrl(params),
572
+ url: buildListUrl(RESOURCE_TYPE_API, params),
475
573
  signal
476
574
  });
477
575
  const records = extractRecords(json).map(mapAuthorizationResource).filter((item) => item !== null);
@@ -506,6 +604,50 @@ function createAuthorizationResourceApi(request) {
506
604
  }
507
605
  };
508
606
  }
607
+ function createMenuResourceApi(request) {
608
+ const permissionApi = createAuthorizationResourceApi(request);
609
+ return {
610
+ async list(params, signal) {
611
+ const json = await request({
612
+ method: "GET",
613
+ url: buildListUrl(MENU_LIST_TYPE_PARAM, params),
614
+ signal
615
+ });
616
+ const records = extractRecords(json).map(mapMenuResource).filter((item) => item !== null);
617
+ const pagination = extractPagination(json);
618
+ return {
619
+ records,
620
+ ...pagination
621
+ };
622
+ },
623
+ listPermissionPoints(params, signal) {
624
+ return permissionApi.list(params, signal);
625
+ },
626
+ async create(values, signal) {
627
+ return request({
628
+ method: "POST",
629
+ url: "/authorization-resources",
630
+ body: buildCreateMenuBody(values),
631
+ signal
632
+ });
633
+ },
634
+ async update(resourceId, values, signal) {
635
+ return request({
636
+ method: "PATCH",
637
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
638
+ body: buildUpdateMenuBody(values),
639
+ signal
640
+ });
641
+ },
642
+ async remove(resourceId, signal) {
643
+ return request({
644
+ method: "DELETE",
645
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
646
+ signal
647
+ });
648
+ }
649
+ };
650
+ }
509
651
  function createDefaultResourceRequest(options = {}) {
510
652
  const baseUrl = (options.baseUrl ?? "").replace(/\/+$/, "");
511
653
  const credentials = options.credentials ?? "include";
@@ -1072,9 +1214,639 @@ var styles = {
1072
1214
  paddingTop: 4
1073
1215
  }
1074
1216
  };
1217
+
1218
+ // src/react/MenuManager.tsx
1219
+ var import_react3 = require("react");
1220
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1221
+ var PAGE_SIZE_OPTIONS2 = ["10", "20", "50", "100"];
1222
+ var emptyForm2 = () => ({
1223
+ parentId: ROOT_PARENT_ID,
1224
+ type: MENU_TYPE_MENU,
1225
+ name: "",
1226
+ identification: "",
1227
+ permissionPointIds: [],
1228
+ status: RESOURCE_STATUS_ENABLED
1229
+ });
1230
+ function MenuManager({
1231
+ api,
1232
+ title = "\u83DC\u5355\u7BA1\u7406",
1233
+ pageSize: initialPageSize = "20",
1234
+ toolbarExtra
1235
+ }) {
1236
+ const [records, setRecords] = (0, import_react3.useState)([]);
1237
+ const [permissionPoints, setPermissionPoints] = (0, import_react3.useState)([]);
1238
+ const [loading, setLoading] = (0, import_react3.useState)(false);
1239
+ const [error, setError] = (0, import_react3.useState)("");
1240
+ const [pageSize, setPageSize] = (0, import_react3.useState)(initialPageSize);
1241
+ const [pageToken, setPageToken] = (0, import_react3.useState)("");
1242
+ const [hasPreviousPage, setHasPreviousPage] = (0, import_react3.useState)(false);
1243
+ const [hasNextPage, setHasNextPage] = (0, import_react3.useState)(false);
1244
+ const [dialogOpen, setDialogOpen] = (0, import_react3.useState)(false);
1245
+ const [editing, setEditing] = (0, import_react3.useState)(null);
1246
+ const [form, setForm] = (0, import_react3.useState)(emptyForm2);
1247
+ const [saving, setSaving] = (0, import_react3.useState)(false);
1248
+ const [deletingRow, setDeletingRow] = (0, import_react3.useState)(null);
1249
+ const [deleting, setDeleting] = (0, import_react3.useState)(false);
1250
+ const permissionNameMap = (0, import_react3.useMemo)(() => {
1251
+ const map = /* @__PURE__ */ new Map();
1252
+ permissionPoints.forEach((p) => map.set(p.resourceId, p.name || p.identification));
1253
+ return map;
1254
+ }, [permissionPoints]);
1255
+ const parentOptions = (0, import_react3.useMemo)(() => {
1256
+ return records.filter((row) => !editing || row.resourceId !== editing.resourceId).map((row) => ({
1257
+ value: row.resourceId,
1258
+ label: `${row.name}\uFF08${MENU_TYPE_LABEL[row.type]}\uFF09`
1259
+ }));
1260
+ }, [records, editing]);
1261
+ const loadList = (0, import_react3.useCallback)(
1262
+ async (direction = "current", token = pageToken) => {
1263
+ setLoading(true);
1264
+ setError("");
1265
+ try {
1266
+ const result = await api.list({
1267
+ pagination: {
1268
+ pageToken: token,
1269
+ pageSize,
1270
+ pageDirection: direction
1271
+ }
1272
+ });
1273
+ setRecords(result.records);
1274
+ setPageToken(result.pageToken);
1275
+ setHasPreviousPage(result.hasPreviousPage);
1276
+ setHasNextPage(result.hasNextPage);
1277
+ } catch (err) {
1278
+ setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25");
1279
+ } finally {
1280
+ setLoading(false);
1281
+ }
1282
+ },
1283
+ [api, pageSize, pageToken]
1284
+ );
1285
+ const loadPermissionPoints = (0, import_react3.useCallback)(async () => {
1286
+ try {
1287
+ const result = await api.listPermissionPoints({
1288
+ pagination: { pageSize: "200", pageDirection: "current" }
1289
+ });
1290
+ setPermissionPoints(result.records);
1291
+ } catch {
1292
+ }
1293
+ }, [api]);
1294
+ (0, import_react3.useEffect)(() => {
1295
+ void loadList("current", "");
1296
+ void loadPermissionPoints();
1297
+ }, [api, pageSize]);
1298
+ const openCreate = () => {
1299
+ setEditing(null);
1300
+ setForm(emptyForm2());
1301
+ setDialogOpen(true);
1302
+ void loadPermissionPoints();
1303
+ };
1304
+ const openEdit = (row) => {
1305
+ setEditing(row);
1306
+ setForm({
1307
+ parentId: row.parentId || ROOT_PARENT_ID,
1308
+ type: row.type,
1309
+ name: row.name,
1310
+ identification: row.identification,
1311
+ permissionPointIds: [...row.permissionPointIds],
1312
+ status: row.status
1313
+ });
1314
+ setDialogOpen(true);
1315
+ void loadPermissionPoints();
1316
+ };
1317
+ const closeDialog = () => {
1318
+ if (saving) return;
1319
+ setDialogOpen(false);
1320
+ };
1321
+ const handleSubmit = async (event) => {
1322
+ event.preventDefault();
1323
+ if (!form.name.trim()) {
1324
+ setError("\u8BF7\u586B\u5199\u83DC\u5355\u540D\u79F0");
1325
+ return;
1326
+ }
1327
+ setSaving(true);
1328
+ setError("");
1329
+ try {
1330
+ if (editing) {
1331
+ await api.update(editing.resourceId, form);
1332
+ } else {
1333
+ await api.create(form);
1334
+ }
1335
+ setDialogOpen(false);
1336
+ await loadList("current", "");
1337
+ } catch (err) {
1338
+ setError(err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25");
1339
+ } finally {
1340
+ setSaving(false);
1341
+ }
1342
+ };
1343
+ const askDelete = (row) => setDeletingRow(row);
1344
+ const closeDeleteDialog = () => {
1345
+ if (!deleting) setDeletingRow(null);
1346
+ };
1347
+ const confirmDelete = async () => {
1348
+ if (!deletingRow) return;
1349
+ setDeleting(true);
1350
+ setError("");
1351
+ try {
1352
+ await api.remove(deletingRow.resourceId);
1353
+ setDeletingRow(null);
1354
+ await loadList("current", "");
1355
+ } catch (err) {
1356
+ setError(err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25");
1357
+ } finally {
1358
+ setDeleting(false);
1359
+ }
1360
+ };
1361
+ const togglePermission = (id) => {
1362
+ setForm((prev) => {
1363
+ const exists = prev.permissionPointIds.includes(id);
1364
+ return {
1365
+ ...prev,
1366
+ permissionPointIds: exists ? prev.permissionPointIds.filter((x) => x !== id) : [...prev.permissionPointIds, id]
1367
+ };
1368
+ });
1369
+ };
1370
+ const renderPermissionLabels = (row) => {
1371
+ if (row.permissionPointNames?.length) {
1372
+ return row.permissionPointNames.join("\u3001");
1373
+ }
1374
+ if (!row.permissionPointIds.length) return "\u2014";
1375
+ return row.permissionPointIds.map((id) => permissionNameMap.get(id) ?? id).join("\u3001");
1376
+ };
1377
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.root, children: [
1378
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.toolbar, children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { style: styles2.title, children: title }),
1380
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.toolbarRight, children: [
1381
+ toolbarExtra,
1382
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: styles2.primaryBtn, onClick: openCreate, children: "\u65B0\u589E" })
1383
+ ] })
1384
+ ] }),
1385
+ error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.error, children: error }) : null,
1386
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.tableWrap, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("table", { style: styles2.table, children: [
1387
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("tr", { children: [
1388
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("th", { style: styles2.th, children: "\u83DC\u5355\u540D\u79F0" }),
1389
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("th", { style: styles2.th, children: "\u8BF7\u6C42\u5730\u5740" }),
1390
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("th", { style: { ...styles2.th, width: 90 }, children: "\u7C7B\u578B" }),
1391
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("th", { style: { ...styles2.th, width: 80 }, children: "\u53EF\u89C1" }),
1392
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("th", { style: styles2.th, children: "\u6743\u9650\u6807\u8BC6" }),
1393
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("th", { style: { ...styles2.th, width: 140 }, children: "\u64CD\u4F5C" })
1394
+ ] }) }),
1395
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("tbody", { children: loading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { colSpan: 6, style: styles2.empty, children: "\u52A0\u8F7D\u4E2D\u2026" }) }) : records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { colSpan: 6, style: styles2.empty, children: "\u6682\u65E0\u6570\u636E" }) }) : records.map((row) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("tr", { children: [
1396
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { style: styles2.td, children: row.name }),
1397
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { style: styles2.td, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { style: styles2.code, children: row.identification || "\u2014" }) }),
1398
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { style: styles2.td, children: MENU_TYPE_LABEL[row.type] }),
1399
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { style: styles2.td, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1400
+ "span",
1401
+ {
1402
+ style: {
1403
+ ...styles2.badge,
1404
+ background: row.status === RESOURCE_STATUS_ENABLED ? "#e8f7ef" : "#f4f4f5",
1405
+ color: row.status === RESOURCE_STATUS_ENABLED ? "#067647" : "#667085"
1406
+ },
1407
+ children: row.status === RESOURCE_STATUS_ENABLED ? "\u663E\u793A" : "\u9690\u85CF"
1408
+ }
1409
+ ) }),
1410
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("td", { style: styles2.td, children: renderPermissionLabels(row) }),
1411
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("td", { style: styles2.td, children: [
1412
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: styles2.linkBtn, onClick: () => openEdit(row), children: "\u7F16\u8F91" }),
1413
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1414
+ "button",
1415
+ {
1416
+ type: "button",
1417
+ style: { ...styles2.linkBtn, color: "#d92d20" },
1418
+ onClick: () => askDelete(row),
1419
+ children: "\u5220\u9664"
1420
+ }
1421
+ )
1422
+ ] })
1423
+ ] }, row.resourceId)) })
1424
+ ] }) }),
1425
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.pagination, children: [
1426
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles2.pageSize, children: [
1427
+ "\u6BCF\u9875",
1428
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1429
+ "select",
1430
+ {
1431
+ value: pageSize,
1432
+ onChange: (e) => {
1433
+ setPageToken("");
1434
+ setPageSize(e.target.value);
1435
+ },
1436
+ style: styles2.select,
1437
+ children: PAGE_SIZE_OPTIONS2.map((size) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: size, children: size }, size))
1438
+ }
1439
+ )
1440
+ ] }),
1441
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.pageBtns, children: [
1442
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1443
+ "button",
1444
+ {
1445
+ type: "button",
1446
+ style: styles2.secondaryBtn,
1447
+ disabled: !hasPreviousPage || loading,
1448
+ onClick: () => void loadList("previous"),
1449
+ children: "\u4E0A\u4E00\u9875"
1450
+ }
1451
+ ),
1452
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1453
+ "button",
1454
+ {
1455
+ type: "button",
1456
+ style: styles2.secondaryBtn,
1457
+ disabled: !hasNextPage || loading,
1458
+ onClick: () => void loadList("next"),
1459
+ children: "\u4E0B\u4E00\u9875"
1460
+ }
1461
+ )
1462
+ ] })
1463
+ ] }),
1464
+ dialogOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.mask, onClick: closeDialog, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1465
+ "div",
1466
+ {
1467
+ style: { ...styles2.dialog, maxWidth: 520 },
1468
+ onClick: (e) => e.stopPropagation(),
1469
+ role: "dialog",
1470
+ "aria-modal": "true",
1471
+ children: [
1472
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.dialogHeader, children: [
1473
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: styles2.dialogTitle, children: editing ? "\u7F16\u8F91\u83DC\u5355" : "\u65B0\u589E\u83DC\u5355" }),
1474
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: styles2.iconBtn, onClick: closeDialog, "aria-label": "\u5173\u95ED", children: "\xD7" })
1475
+ ] }),
1476
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { style: styles2.form, onSubmit: (e) => void handleSubmit(e), children: [
1477
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles2.field, children: [
1478
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: styles2.label, children: "\u4E0A\u7EA7\u83DC\u5355" }),
1479
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1480
+ "select",
1481
+ {
1482
+ style: styles2.input,
1483
+ value: form.parentId,
1484
+ onChange: (e) => setForm((prev) => ({ ...prev, parentId: e.target.value })),
1485
+ children: [
1486
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: ROOT_PARENT_ID, children: "\u6839\u76EE\u5F55" }),
1487
+ parentOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1488
+ ]
1489
+ }
1490
+ )
1491
+ ] }),
1492
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("fieldset", { style: styles2.fieldset, children: [
1493
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("legend", { style: styles2.label, children: "\u83DC\u5355\u7C7B\u578B" }),
1494
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.radioGroup, children: MENU_TYPE_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles2.radioItem, children: [
1495
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1496
+ "input",
1497
+ {
1498
+ type: "radio",
1499
+ name: "menu-type",
1500
+ checked: form.type === opt.value,
1501
+ onChange: () => setForm((prev) => ({
1502
+ ...prev,
1503
+ type: opt.value
1504
+ }))
1505
+ }
1506
+ ),
1507
+ opt.label
1508
+ ] }, opt.value)) })
1509
+ ] }),
1510
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles2.field, children: [
1511
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: styles2.label, children: "\u83DC\u5355\u540D\u79F0" }),
1512
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1513
+ "input",
1514
+ {
1515
+ style: styles2.input,
1516
+ value: form.name,
1517
+ onChange: (e) => setForm((prev) => ({ ...prev, name: e.target.value })),
1518
+ placeholder: "\u8BF7\u8F93\u5165\u83DC\u5355\u540D\u79F0",
1519
+ required: true
1520
+ }
1521
+ )
1522
+ ] }),
1523
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles2.field, children: [
1524
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: styles2.label, children: "\u8BF7\u6C42\u5730\u5740" }),
1525
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1526
+ "input",
1527
+ {
1528
+ style: styles2.input,
1529
+ value: form.identification,
1530
+ onChange: (e) => setForm((prev) => ({ ...prev, identification: e.target.value })),
1531
+ placeholder: "\u5982 /system/user"
1532
+ }
1533
+ )
1534
+ ] }),
1535
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("fieldset", { style: styles2.fieldset, children: [
1536
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("legend", { style: styles2.label, children: "\u6743\u9650\u6807\u8BC6" }),
1537
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.multiSelect, children: permissionPoints.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.hint, children: "\u6682\u65E0\u6743\u9650\u70B9\uFF0C\u8BF7\u5148\u5728\u6743\u9650\u70B9\u7BA1\u7406\u4E2D\u65B0\u589E" }) : permissionPoints.map((p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles2.checkItem, children: [
1538
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1539
+ "input",
1540
+ {
1541
+ type: "checkbox",
1542
+ checked: form.permissionPointIds.includes(p.resourceId),
1543
+ onChange: () => togglePermission(p.resourceId)
1544
+ }
1545
+ ),
1546
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
1547
+ p.name,
1548
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { style: { ...styles2.code, marginLeft: 6 }, children: p.identification })
1549
+ ] })
1550
+ ] }, p.resourceId)) })
1551
+ ] }),
1552
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("fieldset", { style: styles2.fieldset, children: [
1553
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("legend", { style: styles2.label, children: "\u72B6\u6001" }),
1554
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.radioGroup, children: MENU_VISIBILITY_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: styles2.radioItem, children: [
1555
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1556
+ "input",
1557
+ {
1558
+ type: "radio",
1559
+ name: "menu-status",
1560
+ checked: form.status === opt.value,
1561
+ onChange: () => setForm((prev) => ({ ...prev, status: opt.value }))
1562
+ }
1563
+ ),
1564
+ opt.label
1565
+ ] }, opt.value)) })
1566
+ ] }),
1567
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.dialogFooter, children: [
1568
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: styles2.secondaryBtn, onClick: closeDialog, children: "\u53D6\u6D88" }),
1569
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", style: styles2.primaryBtn, disabled: saving, children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58" })
1570
+ ] })
1571
+ ] })
1572
+ ]
1573
+ }
1574
+ ) }) : null,
1575
+ deletingRow ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: styles2.mask, onClick: closeDeleteDialog, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1576
+ "div",
1577
+ {
1578
+ style: { ...styles2.dialog, maxWidth: 420 },
1579
+ onClick: (e) => e.stopPropagation(),
1580
+ role: "dialog",
1581
+ "aria-modal": "true",
1582
+ children: [
1583
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.dialogHeader, children: [
1584
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: styles2.dialogTitle, children: "\u786E\u8BA4\u5220\u9664" }),
1585
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1586
+ "button",
1587
+ {
1588
+ type: "button",
1589
+ style: styles2.iconBtn,
1590
+ onClick: closeDeleteDialog,
1591
+ "aria-label": "\u5173\u95ED",
1592
+ children: "\xD7"
1593
+ }
1594
+ )
1595
+ ] }),
1596
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.confirmBody, children: [
1597
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { style: styles2.confirmText, children: [
1598
+ "\u786E\u8BA4\u5220\u9664\u83DC\u5355\u300C",
1599
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: deletingRow.name }),
1600
+ "\u300D\u5417\uFF1F\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\u3002"
1601
+ ] }),
1602
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: styles2.dialogFooter, children: [
1603
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1604
+ "button",
1605
+ {
1606
+ type: "button",
1607
+ style: styles2.secondaryBtn,
1608
+ onClick: closeDeleteDialog,
1609
+ disabled: deleting,
1610
+ children: "\u53D6\u6D88"
1611
+ }
1612
+ ),
1613
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1614
+ "button",
1615
+ {
1616
+ type: "button",
1617
+ style: styles2.dangerBtn,
1618
+ onClick: () => void confirmDelete(),
1619
+ disabled: deleting,
1620
+ children: deleting ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u5220\u9664"
1621
+ }
1622
+ )
1623
+ ] })
1624
+ ] })
1625
+ ]
1626
+ }
1627
+ ) }) : null
1628
+ ] });
1629
+ }
1630
+ var styles2 = {
1631
+ root: {
1632
+ display: "flex",
1633
+ flexDirection: "column",
1634
+ gap: 16,
1635
+ padding: 16,
1636
+ color: "#101828",
1637
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
1638
+ },
1639
+ toolbar: {
1640
+ display: "flex",
1641
+ alignItems: "center",
1642
+ justifyContent: "space-between",
1643
+ gap: 12
1644
+ },
1645
+ title: { margin: 0, fontSize: 18, fontWeight: 600 },
1646
+ toolbarRight: { display: "flex", alignItems: "center", gap: 8 },
1647
+ error: {
1648
+ padding: "10px 12px",
1649
+ borderRadius: 8,
1650
+ background: "#fef3f2",
1651
+ color: "#b42318",
1652
+ fontSize: 13
1653
+ },
1654
+ tableWrap: {
1655
+ overflow: "auto",
1656
+ border: "1px solid #eaecf0",
1657
+ borderRadius: 10,
1658
+ background: "#fff"
1659
+ },
1660
+ table: { width: "100%", borderCollapse: "collapse", minWidth: 820 },
1661
+ th: {
1662
+ textAlign: "left",
1663
+ padding: "12px 14px",
1664
+ fontSize: 13,
1665
+ fontWeight: 600,
1666
+ color: "#475467",
1667
+ background: "#f9fafb",
1668
+ borderBottom: "1px solid #eaecf0"
1669
+ },
1670
+ td: {
1671
+ padding: "12px 14px",
1672
+ fontSize: 14,
1673
+ borderBottom: "1px solid #f2f4f7",
1674
+ verticalAlign: "middle"
1675
+ },
1676
+ empty: { padding: 28, textAlign: "center", color: "#98a2b3", fontSize: 14 },
1677
+ code: {
1678
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
1679
+ fontSize: 13,
1680
+ background: "#f2f4f7",
1681
+ padding: "2px 6px",
1682
+ borderRadius: 4
1683
+ },
1684
+ badge: {
1685
+ display: "inline-block",
1686
+ padding: "2px 8px",
1687
+ borderRadius: 999,
1688
+ fontSize: 12,
1689
+ fontWeight: 500
1690
+ },
1691
+ linkBtn: {
1692
+ border: "none",
1693
+ background: "transparent",
1694
+ color: "#049BAD",
1695
+ cursor: "pointer",
1696
+ padding: "0 8px 0 0",
1697
+ fontSize: 13
1698
+ },
1699
+ pagination: {
1700
+ display: "flex",
1701
+ alignItems: "center",
1702
+ justifyContent: "space-between",
1703
+ gap: 12
1704
+ },
1705
+ pageSize: { display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "#475467" },
1706
+ pageBtns: { display: "flex", gap: 8 },
1707
+ primaryBtn: {
1708
+ border: "none",
1709
+ background: "#049BAD",
1710
+ color: "#fff",
1711
+ borderRadius: 8,
1712
+ padding: "8px 14px",
1713
+ cursor: "pointer",
1714
+ fontSize: 14
1715
+ },
1716
+ secondaryBtn: {
1717
+ border: "1px solid #d0d5dd",
1718
+ background: "#fff",
1719
+ color: "#344054",
1720
+ borderRadius: 8,
1721
+ padding: "8px 14px",
1722
+ cursor: "pointer",
1723
+ fontSize: 14
1724
+ },
1725
+ dangerBtn: {
1726
+ border: "none",
1727
+ background: "#d92d20",
1728
+ color: "#fff",
1729
+ borderRadius: 8,
1730
+ padding: "8px 14px",
1731
+ cursor: "pointer",
1732
+ fontSize: 14
1733
+ },
1734
+ select: {
1735
+ border: "1px solid #d0d5dd",
1736
+ borderRadius: 6,
1737
+ padding: "4px 8px",
1738
+ fontSize: 13,
1739
+ backgroundColor: "#ffffff",
1740
+ color: "#101828"
1741
+ },
1742
+ mask: {
1743
+ position: "fixed",
1744
+ inset: 0,
1745
+ background: "rgba(16, 24, 40, 0.45)",
1746
+ display: "flex",
1747
+ alignItems: "center",
1748
+ justifyContent: "center",
1749
+ zIndex: 1e3,
1750
+ padding: 16
1751
+ },
1752
+ dialog: {
1753
+ width: "100%",
1754
+ maxWidth: 480,
1755
+ background: "#fff",
1756
+ borderRadius: 12,
1757
+ boxShadow: "0 20px 40px rgba(16,24,40,0.18)",
1758
+ maxHeight: "90vh",
1759
+ overflow: "auto"
1760
+ },
1761
+ dialogHeader: {
1762
+ display: "flex",
1763
+ alignItems: "center",
1764
+ justifyContent: "space-between",
1765
+ padding: "14px 16px",
1766
+ borderBottom: "1px solid #eaecf0",
1767
+ position: "sticky",
1768
+ top: 0,
1769
+ background: "#fff",
1770
+ zIndex: 1
1771
+ },
1772
+ dialogTitle: { margin: 0, fontSize: 16, fontWeight: 600 },
1773
+ iconBtn: {
1774
+ border: "none",
1775
+ background: "transparent",
1776
+ fontSize: 22,
1777
+ lineHeight: 1,
1778
+ cursor: "pointer",
1779
+ color: "#667085"
1780
+ },
1781
+ form: { display: "flex", flexDirection: "column", gap: 12, padding: 16 },
1782
+ confirmBody: { display: "flex", flexDirection: "column", gap: 16, padding: 16 },
1783
+ confirmText: { margin: 0, fontSize: 14, color: "#344054", lineHeight: 1.6 },
1784
+ field: { display: "flex", flexDirection: "column", gap: 6 },
1785
+ fieldset: {
1786
+ margin: 0,
1787
+ padding: 0,
1788
+ border: "none",
1789
+ display: "flex",
1790
+ flexDirection: "column",
1791
+ gap: 8
1792
+ },
1793
+ label: { fontSize: 13, color: "#344054", fontWeight: 500 },
1794
+ input: {
1795
+ border: "1px solid #d0d5dd",
1796
+ borderRadius: 8,
1797
+ padding: "8px 10px",
1798
+ fontSize: 14,
1799
+ outline: "none",
1800
+ backgroundColor: "#ffffff",
1801
+ color: "#101828",
1802
+ boxSizing: "border-box",
1803
+ width: "100%"
1804
+ },
1805
+ radioGroup: { display: "flex", flexWrap: "wrap", gap: 16 },
1806
+ radioItem: {
1807
+ display: "flex",
1808
+ alignItems: "center",
1809
+ gap: 6,
1810
+ fontSize: 14,
1811
+ color: "#344054",
1812
+ cursor: "pointer"
1813
+ },
1814
+ multiSelect: {
1815
+ maxHeight: 160,
1816
+ overflow: "auto",
1817
+ border: "1px solid #eaecf0",
1818
+ borderRadius: 8,
1819
+ padding: 8,
1820
+ background: "#f9fafb"
1821
+ },
1822
+ checkItem: {
1823
+ display: "flex",
1824
+ alignItems: "center",
1825
+ gap: 8,
1826
+ padding: "6px 4px",
1827
+ fontSize: 13,
1828
+ color: "#344054",
1829
+ cursor: "pointer"
1830
+ },
1831
+ hint: { fontSize: 13, color: "#98a2b3", padding: 8 },
1832
+ dialogFooter: {
1833
+ display: "flex",
1834
+ justifyContent: "flex-end",
1835
+ gap: 8,
1836
+ paddingTop: 4
1837
+ }
1838
+ };
1075
1839
  // Annotate the CommonJS export names for ESM import in node:
1076
1840
  0 && (module.exports = {
1077
1841
  Can,
1842
+ MENU_LIST_TYPE_PARAM,
1843
+ MENU_TYPE_BUTTON,
1844
+ MENU_TYPE_LABEL,
1845
+ MENU_TYPE_MENU,
1846
+ MENU_TYPE_OPTIONS,
1847
+ MENU_TYPE_PAGE,
1848
+ MENU_VISIBILITY_OPTIONS,
1849
+ MenuManager,
1078
1850
  PermissionProvider,
1079
1851
  PermissionStore,
1080
1852
  RESOURCE_PRIVATE_OPTIONS,
@@ -1082,18 +1854,23 @@ var styles = {
1082
1854
  RESOURCE_STATUS_ENABLED,
1083
1855
  RESOURCE_STATUS_OPTIONS,
1084
1856
  RESOURCE_TYPE_API,
1857
+ ROOT_PARENT_ID,
1085
1858
  ResourceManager,
1086
1859
  appendQueryParam,
1087
1860
  buildCreateBody,
1861
+ buildCreateMenuBody,
1088
1862
  buildUpdateBody,
1863
+ buildUpdateMenuBody,
1089
1864
  createAuthorizationResourceApi,
1090
1865
  createDefaultResourceRequest,
1866
+ createMenuResourceApi,
1091
1867
  createPermissionStore,
1092
1868
  extractPagination,
1093
1869
  extractRecords,
1094
1870
  getAppClientId,
1095
1871
  getDeviceWorkerId,
1096
1872
  mapAuthorizationResource,
1873
+ mapMenuResource,
1097
1874
  snowyflake,
1098
1875
  useHasPermission,
1099
1876
  useHasRole,