com-angel-authorization 1.0.4 → 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.
@@ -21,6 +21,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var vue_exports = {};
22
22
  __export(vue_exports, {
23
23
  Can: () => Can,
24
+ MENU_LIST_TYPE_PARAM: () => MENU_LIST_TYPE_PARAM,
25
+ MENU_TYPE_BUTTON: () => MENU_TYPE_BUTTON,
26
+ MENU_TYPE_LABEL: () => MENU_TYPE_LABEL,
27
+ MENU_TYPE_MENU: () => MENU_TYPE_MENU,
28
+ MENU_TYPE_OPTIONS: () => MENU_TYPE_OPTIONS,
29
+ MENU_TYPE_PAGE: () => MENU_TYPE_PAGE,
30
+ MENU_VISIBILITY_OPTIONS: () => MENU_VISIBILITY_OPTIONS,
31
+ MenuManager: () => MenuManager,
24
32
  PERMISSION_STORE_KEY: () => PERMISSION_STORE_KEY,
25
33
  PermissionStore: () => PermissionStore,
26
34
  RESOURCE_PRIVATE_OPTIONS: () => RESOURCE_PRIVATE_OPTIONS,
@@ -28,12 +36,16 @@ __export(vue_exports, {
28
36
  RESOURCE_STATUS_ENABLED: () => RESOURCE_STATUS_ENABLED,
29
37
  RESOURCE_STATUS_OPTIONS: () => RESOURCE_STATUS_OPTIONS,
30
38
  RESOURCE_TYPE_API: () => RESOURCE_TYPE_API,
39
+ ROOT_PARENT_ID: () => ROOT_PARENT_ID,
31
40
  ResourceManager: () => ResourceManager,
32
41
  appendQueryParam: () => appendQueryParam,
33
42
  buildCreateBody: () => buildCreateBody,
43
+ buildCreateMenuBody: () => buildCreateMenuBody,
34
44
  buildUpdateBody: () => buildUpdateBody,
45
+ buildUpdateMenuBody: () => buildUpdateMenuBody,
35
46
  createAuthorizationResourceApi: () => createAuthorizationResourceApi,
36
47
  createDefaultResourceRequest: () => createDefaultResourceRequest,
48
+ createMenuResourceApi: () => createMenuResourceApi,
37
49
  createPermissionPlugin: () => createPermissionPlugin,
38
50
  createPermissionStore: () => createPermissionStore,
39
51
  createVPermission: () => createVPermission,
@@ -42,6 +54,7 @@ __export(vue_exports, {
42
54
  getAppClientId: () => getAppClientId,
43
55
  getDeviceWorkerId: () => getDeviceWorkerId,
44
56
  mapAuthorizationResource: () => mapAuthorizationResource,
57
+ mapMenuResource: () => mapMenuResource,
45
58
  snowyflake: () => snowyflake,
46
59
  useHasPermission: () => useHasPermission,
47
60
  useHasRole: () => useHasRole,
@@ -349,16 +362,35 @@ var import_vue3 = require("vue");
349
362
 
350
363
  // src/resources/types.ts
351
364
  var RESOURCE_TYPE_API = "api";
365
+ var MENU_TYPE_PAGE = "page";
366
+ var MENU_TYPE_MENU = "menu";
367
+ var MENU_TYPE_BUTTON = "button";
368
+ var MENU_LIST_TYPE_PARAM = "page,menu,button";
369
+ var ROOT_PARENT_ID = "0";
352
370
  var RESOURCE_STATUS_ENABLED = 1;
353
371
  var RESOURCE_STATUS_DISABLED = 0;
354
372
  var RESOURCE_STATUS_OPTIONS = [
355
373
  { label: "\u542F\u7528", value: RESOURCE_STATUS_ENABLED },
356
374
  { label: "\u7981\u7528", value: RESOURCE_STATUS_DISABLED }
357
375
  ];
376
+ var MENU_VISIBILITY_OPTIONS = [
377
+ { label: "\u663E\u793A", value: RESOURCE_STATUS_ENABLED },
378
+ { label: "\u9690\u85CF", value: RESOURCE_STATUS_DISABLED }
379
+ ];
358
380
  var RESOURCE_PRIVATE_OPTIONS = [
359
381
  { label: "\u662F", value: true },
360
382
  { label: "\u5426", value: false }
361
383
  ];
384
+ var MENU_TYPE_OPTIONS = [
385
+ { label: "\u76EE\u5F55", value: MENU_TYPE_PAGE },
386
+ { label: "\u83DC\u5355", value: MENU_TYPE_MENU },
387
+ { label: "\u6309\u94AE", value: MENU_TYPE_BUTTON }
388
+ ];
389
+ var MENU_TYPE_LABEL = {
390
+ page: "\u76EE\u5F55",
391
+ menu: "\u83DC\u5355",
392
+ button: "\u6309\u94AE"
393
+ };
362
394
 
363
395
  // src/utils/snowflake.ts
364
396
  var DEVICE_WORKER_ID_KEY = "hgams_device_worker_id";
@@ -503,6 +535,29 @@ function toBoolean(value) {
503
535
  }
504
536
  return false;
505
537
  }
538
+ function toStringArray(value) {
539
+ if (Array.isArray(value)) {
540
+ return value.map((item) => {
541
+ if (item && typeof item === "object") {
542
+ const row = item;
543
+ const id = row.resourceId ?? row.resource_id ?? row.id;
544
+ return id === void 0 || id === null ? "" : String(id);
545
+ }
546
+ return String(item ?? "");
547
+ }).filter(Boolean);
548
+ }
549
+ if (typeof value === "string" && value.trim()) {
550
+ return value.split(",").map((s3) => s3.trim()).filter(Boolean);
551
+ }
552
+ return [];
553
+ }
554
+ function toMenuType(value) {
555
+ const v = String(value ?? "").toLowerCase();
556
+ if (v === MENU_TYPE_PAGE || v === MENU_TYPE_MENU || v === MENU_TYPE_BUTTON) {
557
+ return v;
558
+ }
559
+ return MENU_TYPE_MENU;
560
+ }
506
561
  function mapAuthorizationResource(item) {
507
562
  if (!item || typeof item !== "object") return null;
508
563
  const row = item;
@@ -518,9 +573,31 @@ function mapAuthorizationResource(item) {
518
573
  description: String(row.description ?? row.desc ?? "")
519
574
  };
520
575
  }
521
- function buildListUrl(params) {
576
+ function mapMenuResource(item) {
577
+ if (!item || typeof item !== "object") return null;
578
+ const row = item;
579
+ const resourceId = row.resourceId ?? row.resource_id ?? row.id;
580
+ if (resourceId === void 0 || resourceId === null || resourceId === "") return null;
581
+ const permissionPointIds = toStringArray(
582
+ row.permissionPointIds ?? row.permission_point_ids ?? row.permissionPoints ?? row.permissions
583
+ );
584
+ const permissionNamesRaw = row.permissionPointNames ?? row.permission_point_names ?? row.permissionNames;
585
+ const permissionPointNames = Array.isArray(permissionNamesRaw) ? permissionNamesRaw.map((n) => String(n ?? "")).filter(Boolean) : void 0;
586
+ const parentId = row.parentId ?? row.parent_id ?? ROOT_PARENT_ID;
587
+ return {
588
+ resourceId: String(resourceId),
589
+ parentId: parentId === void 0 || parentId === null ? ROOT_PARENT_ID : String(parentId),
590
+ type: toMenuType(row.type),
591
+ name: String(row.name ?? ""),
592
+ identification: String(row.identification ?? row.identity ?? row.path ?? ""),
593
+ permissionPointIds,
594
+ permissionPointNames,
595
+ status: toResourceStatus(row.status)
596
+ };
597
+ }
598
+ function buildListUrl(type, params) {
522
599
  const parts = [];
523
- appendQueryParam(parts, "type", RESOURCE_TYPE_API);
600
+ appendQueryParam(parts, "type", type);
524
601
  appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
525
602
  appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
526
603
  appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
@@ -547,12 +624,33 @@ function buildUpdateBody(values) {
547
624
  description: values.description.trim()
548
625
  };
549
626
  }
627
+ function buildCreateMenuBody(values, resourceId = getAppClientId()) {
628
+ return {
629
+ resourceId,
630
+ parentId: values.parentId || ROOT_PARENT_ID,
631
+ type: values.type,
632
+ name: values.name.trim(),
633
+ identification: values.identification.trim(),
634
+ permissionPointIds: [...values.permissionPointIds],
635
+ status: values.status
636
+ };
637
+ }
638
+ function buildUpdateMenuBody(values) {
639
+ return {
640
+ parentId: values.parentId || ROOT_PARENT_ID,
641
+ type: values.type,
642
+ name: values.name.trim(),
643
+ identification: values.identification.trim(),
644
+ permissionPointIds: [...values.permissionPointIds],
645
+ status: values.status
646
+ };
647
+ }
550
648
  function createAuthorizationResourceApi(request) {
551
649
  return {
552
650
  async list(params, signal) {
553
651
  const json = await request({
554
652
  method: "GET",
555
- url: buildListUrl(params),
653
+ url: buildListUrl(RESOURCE_TYPE_API, params),
556
654
  signal
557
655
  });
558
656
  const records = extractRecords(json).map(mapAuthorizationResource).filter((item) => item !== null);
@@ -587,6 +685,50 @@ function createAuthorizationResourceApi(request) {
587
685
  }
588
686
  };
589
687
  }
688
+ function createMenuResourceApi(request) {
689
+ const permissionApi = createAuthorizationResourceApi(request);
690
+ return {
691
+ async list(params, signal) {
692
+ const json = await request({
693
+ method: "GET",
694
+ url: buildListUrl(MENU_LIST_TYPE_PARAM, params),
695
+ signal
696
+ });
697
+ const records = extractRecords(json).map(mapMenuResource).filter((item) => item !== null);
698
+ const pagination = extractPagination(json);
699
+ return {
700
+ records,
701
+ ...pagination
702
+ };
703
+ },
704
+ listPermissionPoints(params, signal) {
705
+ return permissionApi.list(params, signal);
706
+ },
707
+ async create(values, signal) {
708
+ return request({
709
+ method: "POST",
710
+ url: "/authorization-resources",
711
+ body: buildCreateMenuBody(values),
712
+ signal
713
+ });
714
+ },
715
+ async update(resourceId, values, signal) {
716
+ return request({
717
+ method: "PATCH",
718
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
719
+ body: buildUpdateMenuBody(values),
720
+ signal
721
+ });
722
+ },
723
+ async remove(resourceId, signal) {
724
+ return request({
725
+ method: "DELETE",
726
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
727
+ signal
728
+ });
729
+ }
730
+ };
731
+ }
590
732
  function createDefaultResourceRequest(options = {}) {
591
733
  const baseUrl = (options.baseUrl ?? "").replace(/\/+$/, "");
592
734
  const credentials = options.credentials ?? "include";
@@ -743,11 +885,22 @@ var s = {
743
885
  cursor: "pointer",
744
886
  fontSize: "14px"
745
887
  },
888
+ dangerBtn: {
889
+ border: "none",
890
+ background: "#d92d20",
891
+ color: "#fff",
892
+ borderRadius: "8px",
893
+ padding: "8px 14px",
894
+ cursor: "pointer",
895
+ fontSize: "14px"
896
+ },
746
897
  select: {
747
898
  border: "1px solid #d0d5dd",
748
899
  borderRadius: "6px",
749
900
  padding: "4px 8px",
750
- fontSize: "13px"
901
+ fontSize: "13px",
902
+ backgroundColor: "#ffffff",
903
+ color: "#101828"
751
904
  },
752
905
  mask: {
753
906
  position: "fixed",
@@ -783,6 +936,18 @@ var s = {
783
936
  color: "#667085"
784
937
  },
785
938
  form: { display: "flex", flexDirection: "column", gap: "12px", padding: "16px" },
939
+ confirmBody: {
940
+ display: "flex",
941
+ flexDirection: "column",
942
+ gap: "16px",
943
+ padding: "16px"
944
+ },
945
+ confirmText: {
946
+ margin: "0",
947
+ fontSize: "14px",
948
+ color: "#344054",
949
+ lineHeight: "1.6"
950
+ },
786
951
  field: { display: "flex", flexDirection: "column", gap: "6px" },
787
952
  label: { fontSize: "13px", color: "#344054", fontWeight: "500" },
788
953
  input: {
@@ -790,7 +955,11 @@ var s = {
790
955
  borderRadius: "8px",
791
956
  padding: "8px 10px",
792
957
  fontSize: "14px",
793
- outline: "none"
958
+ outline: "none",
959
+ backgroundColor: "#ffffff",
960
+ color: "#101828",
961
+ boxSizing: "border-box",
962
+ width: "100%"
794
963
  },
795
964
  dialogFooter: {
796
965
  display: "flex",
@@ -827,6 +996,8 @@ var ResourceManager = (0, import_vue3.defineComponent)({
827
996
  const editing = (0, import_vue3.ref)(null);
828
997
  const form = (0, import_vue3.reactive)(emptyForm());
829
998
  const saving = (0, import_vue3.ref)(false);
999
+ const deletingRow = (0, import_vue3.ref)(null);
1000
+ const deleting = (0, import_vue3.ref)(false);
830
1001
  const statusLabel = Object.fromEntries(
831
1002
  RESOURCE_STATUS_OPTIONS.map((o) => [o.value, o.label])
832
1003
  );
@@ -896,14 +1067,24 @@ var ResourceManager = (0, import_vue3.defineComponent)({
896
1067
  saving.value = false;
897
1068
  }
898
1069
  }
899
- async function handleDelete(row) {
900
- if (!window.confirm(`\u786E\u8BA4\u5220\u9664\u6743\u9650\u70B9\u300C${row.name}\u300D\uFF1F`)) return;
1070
+ function askDelete(row) {
1071
+ deletingRow.value = row;
1072
+ }
1073
+ function closeDeleteDialog() {
1074
+ if (!deleting.value) deletingRow.value = null;
1075
+ }
1076
+ async function confirmDelete() {
1077
+ if (!deletingRow.value) return;
1078
+ deleting.value = true;
901
1079
  error.value = "";
902
1080
  try {
903
- await props.api.remove(row.resourceId);
1081
+ await props.api.remove(deletingRow.value.resourceId);
1082
+ deletingRow.value = null;
904
1083
  await loadList("current", "");
905
1084
  } catch (err) {
906
1085
  error.value = err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25";
1086
+ } finally {
1087
+ deleting.value = false;
907
1088
  }
908
1089
  }
909
1090
  (0, import_vue3.onMounted)(() => {
@@ -985,7 +1166,7 @@ var ResourceManager = (0, import_vue3.defineComponent)({
985
1166
  {
986
1167
  type: "button",
987
1168
  style: { ...s.linkBtn, color: "#d92d20" },
988
- onClick: () => void handleDelete(row)
1169
+ onClick: () => askDelete(row)
989
1170
  },
990
1171
  "\u5220\u9664"
991
1172
  )
@@ -1177,6 +1358,862 @@ var ResourceManager = (0, import_vue3.defineComponent)({
1177
1358
  ]
1178
1359
  )
1179
1360
  ]
1361
+ ) : null,
1362
+ deletingRow.value ? (0, import_vue3.h)(
1363
+ "div",
1364
+ { style: s.mask, onClick: closeDeleteDialog },
1365
+ [
1366
+ (0, import_vue3.h)(
1367
+ "div",
1368
+ {
1369
+ style: { ...s.dialog, maxWidth: "420px" },
1370
+ role: "dialog",
1371
+ "aria-modal": "true",
1372
+ "aria-labelledby": "angel-auth-delete-title",
1373
+ onClick: (e) => e.stopPropagation()
1374
+ },
1375
+ [
1376
+ (0, import_vue3.h)("div", { style: s.dialogHeader }, [
1377
+ (0, import_vue3.h)(
1378
+ "h3",
1379
+ {
1380
+ id: "angel-auth-delete-title",
1381
+ style: s.dialogTitle
1382
+ },
1383
+ "\u786E\u8BA4\u5220\u9664"
1384
+ ),
1385
+ (0, import_vue3.h)(
1386
+ "button",
1387
+ {
1388
+ type: "button",
1389
+ style: s.iconBtn,
1390
+ "aria-label": "\u5173\u95ED",
1391
+ onClick: closeDeleteDialog
1392
+ },
1393
+ "\xD7"
1394
+ )
1395
+ ]),
1396
+ (0, import_vue3.h)("div", { style: s.confirmBody }, [
1397
+ (0, import_vue3.h)("p", { style: s.confirmText }, [
1398
+ "\u786E\u8BA4\u5220\u9664\u6743\u9650\u70B9\u300C",
1399
+ (0, import_vue3.h)("strong", deletingRow.value.name),
1400
+ "\u300D\u5417\uFF1F\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\u3002"
1401
+ ]),
1402
+ (0, import_vue3.h)("div", { style: s.dialogFooter }, [
1403
+ (0, import_vue3.h)(
1404
+ "button",
1405
+ {
1406
+ type: "button",
1407
+ style: s.secondaryBtn,
1408
+ disabled: deleting.value,
1409
+ onClick: closeDeleteDialog
1410
+ },
1411
+ "\u53D6\u6D88"
1412
+ ),
1413
+ (0, import_vue3.h)(
1414
+ "button",
1415
+ {
1416
+ type: "button",
1417
+ style: s.dangerBtn,
1418
+ disabled: deleting.value,
1419
+ onClick: () => void confirmDelete()
1420
+ },
1421
+ deleting.value ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u5220\u9664"
1422
+ )
1423
+ ])
1424
+ ])
1425
+ ]
1426
+ )
1427
+ ]
1428
+ ) : null
1429
+ ]);
1430
+ }
1431
+ });
1432
+
1433
+ // src/vue/MenuManager.ts
1434
+ var import_vue4 = require("vue");
1435
+ var PAGE_SIZE_OPTIONS2 = ["10", "20", "50", "100"];
1436
+ function emptyForm2() {
1437
+ return {
1438
+ parentId: ROOT_PARENT_ID,
1439
+ type: MENU_TYPE_MENU,
1440
+ name: "",
1441
+ identification: "",
1442
+ permissionPointIds: [],
1443
+ status: RESOURCE_STATUS_ENABLED
1444
+ };
1445
+ }
1446
+ var s2 = {
1447
+ root: {
1448
+ display: "flex",
1449
+ flexDirection: "column",
1450
+ gap: "16px",
1451
+ padding: "16px",
1452
+ color: "#101828",
1453
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
1454
+ },
1455
+ toolbar: {
1456
+ display: "flex",
1457
+ alignItems: "center",
1458
+ justifyContent: "space-between",
1459
+ gap: "12px"
1460
+ },
1461
+ title: { margin: "0", fontSize: "18px", fontWeight: "600" },
1462
+ toolbarRight: { display: "flex", alignItems: "center", gap: "8px" },
1463
+ error: {
1464
+ padding: "10px 12px",
1465
+ borderRadius: "8px",
1466
+ background: "#fef3f2",
1467
+ color: "#b42318",
1468
+ fontSize: "13px"
1469
+ },
1470
+ tableWrap: {
1471
+ overflow: "auto",
1472
+ border: "1px solid #eaecf0",
1473
+ borderRadius: "10px",
1474
+ background: "#fff"
1475
+ },
1476
+ table: { width: "100%", borderCollapse: "collapse", minWidth: "820px" },
1477
+ th: {
1478
+ textAlign: "left",
1479
+ padding: "12px 14px",
1480
+ fontSize: "13px",
1481
+ fontWeight: "600",
1482
+ color: "#475467",
1483
+ background: "#f9fafb",
1484
+ borderBottom: "1px solid #eaecf0"
1485
+ },
1486
+ td: {
1487
+ padding: "12px 14px",
1488
+ fontSize: "14px",
1489
+ borderBottom: "1px solid #f2f4f7",
1490
+ verticalAlign: "middle"
1491
+ },
1492
+ empty: {
1493
+ padding: "28px",
1494
+ textAlign: "center",
1495
+ color: "#98a2b3",
1496
+ fontSize: "14px"
1497
+ },
1498
+ code: {
1499
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
1500
+ fontSize: "13px",
1501
+ background: "#f2f4f7",
1502
+ padding: "2px 6px",
1503
+ borderRadius: "4px"
1504
+ },
1505
+ badge: {
1506
+ display: "inline-block",
1507
+ padding: "2px 8px",
1508
+ borderRadius: "999px",
1509
+ fontSize: "12px",
1510
+ fontWeight: "500"
1511
+ },
1512
+ linkBtn: {
1513
+ border: "none",
1514
+ background: "transparent",
1515
+ color: "#049BAD",
1516
+ cursor: "pointer",
1517
+ padding: "0 8px 0 0",
1518
+ fontSize: "13px"
1519
+ },
1520
+ pagination: {
1521
+ display: "flex",
1522
+ alignItems: "center",
1523
+ justifyContent: "space-between",
1524
+ gap: "12px"
1525
+ },
1526
+ pageSize: {
1527
+ display: "flex",
1528
+ alignItems: "center",
1529
+ gap: "8px",
1530
+ fontSize: "13px",
1531
+ color: "#475467"
1532
+ },
1533
+ pageBtns: { display: "flex", gap: "8px" },
1534
+ primaryBtn: {
1535
+ border: "none",
1536
+ background: "#049BAD",
1537
+ color: "#fff",
1538
+ borderRadius: "8px",
1539
+ padding: "8px 14px",
1540
+ cursor: "pointer",
1541
+ fontSize: "14px"
1542
+ },
1543
+ secondaryBtn: {
1544
+ border: "1px solid #d0d5dd",
1545
+ background: "#fff",
1546
+ color: "#344054",
1547
+ borderRadius: "8px",
1548
+ padding: "8px 14px",
1549
+ cursor: "pointer",
1550
+ fontSize: "14px"
1551
+ },
1552
+ dangerBtn: {
1553
+ border: "none",
1554
+ background: "#d92d20",
1555
+ color: "#fff",
1556
+ borderRadius: "8px",
1557
+ padding: "8px 14px",
1558
+ cursor: "pointer",
1559
+ fontSize: "14px"
1560
+ },
1561
+ select: {
1562
+ border: "1px solid #d0d5dd",
1563
+ borderRadius: "6px",
1564
+ padding: "4px 8px",
1565
+ fontSize: "13px",
1566
+ backgroundColor: "#ffffff",
1567
+ color: "#101828"
1568
+ },
1569
+ mask: {
1570
+ position: "fixed",
1571
+ inset: "0",
1572
+ background: "rgba(16, 24, 40, 0.45)",
1573
+ display: "flex",
1574
+ alignItems: "center",
1575
+ justifyContent: "center",
1576
+ zIndex: "1000",
1577
+ padding: "16px"
1578
+ },
1579
+ dialog: {
1580
+ width: "100%",
1581
+ maxWidth: "480px",
1582
+ background: "#fff",
1583
+ borderRadius: "12px",
1584
+ boxShadow: "0 20px 40px rgba(16,24,40,0.18)",
1585
+ maxHeight: "90vh",
1586
+ overflow: "auto"
1587
+ },
1588
+ dialogHeader: {
1589
+ display: "flex",
1590
+ alignItems: "center",
1591
+ justifyContent: "space-between",
1592
+ padding: "14px 16px",
1593
+ borderBottom: "1px solid #eaecf0",
1594
+ position: "sticky",
1595
+ top: "0",
1596
+ background: "#fff",
1597
+ zIndex: "1"
1598
+ },
1599
+ dialogTitle: { margin: "0", fontSize: "16px", fontWeight: "600" },
1600
+ iconBtn: {
1601
+ border: "none",
1602
+ background: "transparent",
1603
+ fontSize: "22px",
1604
+ lineHeight: "1",
1605
+ cursor: "pointer",
1606
+ color: "#667085"
1607
+ },
1608
+ form: { display: "flex", flexDirection: "column", gap: "12px", padding: "16px" },
1609
+ confirmBody: {
1610
+ display: "flex",
1611
+ flexDirection: "column",
1612
+ gap: "16px",
1613
+ padding: "16px"
1614
+ },
1615
+ confirmText: {
1616
+ margin: "0",
1617
+ fontSize: "14px",
1618
+ color: "#344054",
1619
+ lineHeight: "1.6"
1620
+ },
1621
+ field: { display: "flex", flexDirection: "column", gap: "6px" },
1622
+ fieldset: {
1623
+ margin: "0",
1624
+ padding: "0",
1625
+ border: "none",
1626
+ display: "flex",
1627
+ flexDirection: "column",
1628
+ gap: "8px"
1629
+ },
1630
+ label: { fontSize: "13px", color: "#344054", fontWeight: "500" },
1631
+ input: {
1632
+ border: "1px solid #d0d5dd",
1633
+ borderRadius: "8px",
1634
+ padding: "8px 10px",
1635
+ fontSize: "14px",
1636
+ outline: "none",
1637
+ backgroundColor: "#ffffff",
1638
+ color: "#101828",
1639
+ boxSizing: "border-box",
1640
+ width: "100%"
1641
+ },
1642
+ radioGroup: { display: "flex", flexWrap: "wrap", gap: "16px" },
1643
+ radioItem: {
1644
+ display: "flex",
1645
+ alignItems: "center",
1646
+ gap: "6px",
1647
+ fontSize: "14px",
1648
+ color: "#344054",
1649
+ cursor: "pointer"
1650
+ },
1651
+ multiSelect: {
1652
+ maxHeight: "160px",
1653
+ overflow: "auto",
1654
+ border: "1px solid #eaecf0",
1655
+ borderRadius: "8px",
1656
+ padding: "8px",
1657
+ background: "#f9fafb"
1658
+ },
1659
+ checkItem: {
1660
+ display: "flex",
1661
+ alignItems: "center",
1662
+ gap: "8px",
1663
+ padding: "6px 4px",
1664
+ fontSize: "13px",
1665
+ color: "#344054",
1666
+ cursor: "pointer"
1667
+ },
1668
+ hint: { fontSize: "13px", color: "#98a2b3", padding: "8px" },
1669
+ dialogFooter: {
1670
+ display: "flex",
1671
+ justifyContent: "flex-end",
1672
+ gap: "8px",
1673
+ paddingTop: "4px"
1674
+ }
1675
+ };
1676
+ var MenuManager = (0, import_vue4.defineComponent)({
1677
+ name: "MenuManager",
1678
+ props: {
1679
+ api: {
1680
+ type: Object,
1681
+ required: true
1682
+ },
1683
+ title: {
1684
+ type: String,
1685
+ default: "\u83DC\u5355\u7BA1\u7406"
1686
+ },
1687
+ pageSize: {
1688
+ type: String,
1689
+ default: "20"
1690
+ }
1691
+ },
1692
+ setup(props, { slots }) {
1693
+ const records = (0, import_vue4.ref)([]);
1694
+ const permissionPoints = (0, import_vue4.ref)([]);
1695
+ const loading = (0, import_vue4.ref)(false);
1696
+ const error = (0, import_vue4.ref)("");
1697
+ const pageSize = (0, import_vue4.ref)(props.pageSize);
1698
+ const pageToken = (0, import_vue4.ref)("");
1699
+ const hasPreviousPage = (0, import_vue4.ref)(false);
1700
+ const hasNextPage = (0, import_vue4.ref)(false);
1701
+ const dialogOpen = (0, import_vue4.ref)(false);
1702
+ const editing = (0, import_vue4.ref)(null);
1703
+ const form = (0, import_vue4.reactive)(emptyForm2());
1704
+ const saving = (0, import_vue4.ref)(false);
1705
+ const deletingRow = (0, import_vue4.ref)(null);
1706
+ const deleting = (0, import_vue4.ref)(false);
1707
+ const permissionNameMap = (0, import_vue4.computed)(() => {
1708
+ const map = /* @__PURE__ */ new Map();
1709
+ permissionPoints.value.forEach(
1710
+ (p) => map.set(p.resourceId, p.name || p.identification)
1711
+ );
1712
+ return map;
1713
+ });
1714
+ const parentOptions = (0, import_vue4.computed)(
1715
+ () => records.value.filter((row) => !editing.value || row.resourceId !== editing.value.resourceId).map((row) => ({
1716
+ value: row.resourceId,
1717
+ label: `${row.name}\uFF08${MENU_TYPE_LABEL[row.type]}\uFF09`
1718
+ }))
1719
+ );
1720
+ async function loadList(direction = "current", token = pageToken.value) {
1721
+ loading.value = true;
1722
+ error.value = "";
1723
+ try {
1724
+ const result = await props.api.list({
1725
+ pagination: {
1726
+ pageToken: token,
1727
+ pageSize: pageSize.value,
1728
+ pageDirection: direction
1729
+ }
1730
+ });
1731
+ records.value = result.records;
1732
+ pageToken.value = result.pageToken;
1733
+ hasPreviousPage.value = result.hasPreviousPage;
1734
+ hasNextPage.value = result.hasNextPage;
1735
+ } catch (err) {
1736
+ error.value = err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25";
1737
+ } finally {
1738
+ loading.value = false;
1739
+ }
1740
+ }
1741
+ async function loadPermissionPoints() {
1742
+ try {
1743
+ const result = await props.api.listPermissionPoints({
1744
+ pagination: { pageSize: "200", pageDirection: "current" }
1745
+ });
1746
+ permissionPoints.value = result.records;
1747
+ } catch {
1748
+ }
1749
+ }
1750
+ function openCreate() {
1751
+ editing.value = null;
1752
+ Object.assign(form, emptyForm2());
1753
+ dialogOpen.value = true;
1754
+ void loadPermissionPoints();
1755
+ }
1756
+ function openEdit(row) {
1757
+ editing.value = row;
1758
+ Object.assign(form, {
1759
+ parentId: row.parentId || ROOT_PARENT_ID,
1760
+ type: row.type,
1761
+ name: row.name,
1762
+ identification: row.identification,
1763
+ permissionPointIds: [...row.permissionPointIds],
1764
+ status: row.status
1765
+ });
1766
+ dialogOpen.value = true;
1767
+ void loadPermissionPoints();
1768
+ }
1769
+ function closeDialog() {
1770
+ if (!saving.value) dialogOpen.value = false;
1771
+ }
1772
+ async function handleSubmit(event) {
1773
+ event.preventDefault();
1774
+ if (!form.name.trim()) {
1775
+ error.value = "\u8BF7\u586B\u5199\u83DC\u5355\u540D\u79F0";
1776
+ return;
1777
+ }
1778
+ saving.value = true;
1779
+ error.value = "";
1780
+ try {
1781
+ if (editing.value) {
1782
+ await props.api.update(editing.value.resourceId, { ...form });
1783
+ } else {
1784
+ await props.api.create({ ...form });
1785
+ }
1786
+ dialogOpen.value = false;
1787
+ await loadList("current", "");
1788
+ } catch (err) {
1789
+ error.value = err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25";
1790
+ } finally {
1791
+ saving.value = false;
1792
+ }
1793
+ }
1794
+ function askDelete(row) {
1795
+ deletingRow.value = row;
1796
+ }
1797
+ function closeDeleteDialog() {
1798
+ if (!deleting.value) deletingRow.value = null;
1799
+ }
1800
+ async function confirmDelete() {
1801
+ if (!deletingRow.value) return;
1802
+ deleting.value = true;
1803
+ error.value = "";
1804
+ try {
1805
+ await props.api.remove(deletingRow.value.resourceId);
1806
+ deletingRow.value = null;
1807
+ await loadList("current", "");
1808
+ } catch (err) {
1809
+ error.value = err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25";
1810
+ } finally {
1811
+ deleting.value = false;
1812
+ }
1813
+ }
1814
+ function togglePermission(id) {
1815
+ const exists = form.permissionPointIds.includes(id);
1816
+ form.permissionPointIds = exists ? form.permissionPointIds.filter((x) => x !== id) : [...form.permissionPointIds, id];
1817
+ }
1818
+ function renderPermissionLabels(row) {
1819
+ if (row.permissionPointNames?.length) {
1820
+ return row.permissionPointNames.join("\u3001");
1821
+ }
1822
+ if (!row.permissionPointIds.length) return "\u2014";
1823
+ return row.permissionPointIds.map((id) => permissionNameMap.value.get(id) ?? id).join("\u3001");
1824
+ }
1825
+ (0, import_vue4.onMounted)(() => {
1826
+ void loadList("current", "");
1827
+ void loadPermissionPoints();
1828
+ });
1829
+ (0, import_vue4.watch)(
1830
+ () => [props.api, pageSize.value],
1831
+ () => {
1832
+ pageToken.value = "";
1833
+ void loadList("current", "");
1834
+ }
1835
+ );
1836
+ return () => (0, import_vue4.h)("div", { style: s2.root }, [
1837
+ (0, import_vue4.h)("div", { style: s2.toolbar }, [
1838
+ (0, import_vue4.h)("h2", { style: s2.title }, props.title),
1839
+ (0, import_vue4.h)("div", { style: s2.toolbarRight }, [
1840
+ slots.toolbarExtra?.(),
1841
+ (0, import_vue4.h)(
1842
+ "button",
1843
+ { type: "button", style: s2.primaryBtn, onClick: openCreate },
1844
+ "\u65B0\u589E"
1845
+ )
1846
+ ])
1847
+ ]),
1848
+ error.value ? (0, import_vue4.h)("div", { style: s2.error }, error.value) : null,
1849
+ (0, import_vue4.h)("div", { style: s2.tableWrap }, [
1850
+ (0, import_vue4.h)("table", { style: s2.table }, [
1851
+ (0, import_vue4.h)("thead", [
1852
+ (0, import_vue4.h)("tr", [
1853
+ (0, import_vue4.h)("th", { style: s2.th }, "\u83DC\u5355\u540D\u79F0"),
1854
+ (0, import_vue4.h)("th", { style: s2.th }, "\u8BF7\u6C42\u5730\u5740"),
1855
+ (0, import_vue4.h)("th", { style: { ...s2.th, width: "90px" } }, "\u7C7B\u578B"),
1856
+ (0, import_vue4.h)("th", { style: { ...s2.th, width: "80px" } }, "\u53EF\u89C1"),
1857
+ (0, import_vue4.h)("th", { style: s2.th }, "\u6743\u9650\u6807\u8BC6"),
1858
+ (0, import_vue4.h)("th", { style: { ...s2.th, width: "140px" } }, "\u64CD\u4F5C")
1859
+ ])
1860
+ ]),
1861
+ (0, import_vue4.h)(
1862
+ "tbody",
1863
+ loading.value ? [
1864
+ (0, import_vue4.h)("tr", [
1865
+ (0, import_vue4.h)("td", { colspan: 6, style: s2.empty }, "\u52A0\u8F7D\u4E2D\u2026")
1866
+ ])
1867
+ ] : records.value.length === 0 ? [
1868
+ (0, import_vue4.h)("tr", [
1869
+ (0, import_vue4.h)("td", { colspan: 6, style: s2.empty }, "\u6682\u65E0\u6570\u636E")
1870
+ ])
1871
+ ] : records.value.map(
1872
+ (row) => (0, import_vue4.h)("tr", { key: row.resourceId }, [
1873
+ (0, import_vue4.h)("td", { style: s2.td }, row.name),
1874
+ (0, import_vue4.h)("td", { style: s2.td }, [
1875
+ (0, import_vue4.h)(
1876
+ "code",
1877
+ { style: s2.code },
1878
+ row.identification || "\u2014"
1879
+ )
1880
+ ]),
1881
+ (0, import_vue4.h)("td", { style: s2.td }, MENU_TYPE_LABEL[row.type]),
1882
+ (0, import_vue4.h)("td", { style: s2.td }, [
1883
+ (0, import_vue4.h)(
1884
+ "span",
1885
+ {
1886
+ style: {
1887
+ ...s2.badge,
1888
+ background: row.status === RESOURCE_STATUS_ENABLED ? "#e8f7ef" : "#f4f4f5",
1889
+ color: row.status === RESOURCE_STATUS_ENABLED ? "#067647" : "#667085"
1890
+ }
1891
+ },
1892
+ row.status === RESOURCE_STATUS_ENABLED ? "\u663E\u793A" : "\u9690\u85CF"
1893
+ )
1894
+ ]),
1895
+ (0, import_vue4.h)("td", { style: s2.td }, renderPermissionLabels(row)),
1896
+ (0, import_vue4.h)("td", { style: s2.td }, [
1897
+ (0, import_vue4.h)(
1898
+ "button",
1899
+ {
1900
+ type: "button",
1901
+ style: s2.linkBtn,
1902
+ onClick: () => openEdit(row)
1903
+ },
1904
+ "\u7F16\u8F91"
1905
+ ),
1906
+ (0, import_vue4.h)(
1907
+ "button",
1908
+ {
1909
+ type: "button",
1910
+ style: { ...s2.linkBtn, color: "#d92d20" },
1911
+ onClick: () => askDelete(row)
1912
+ },
1913
+ "\u5220\u9664"
1914
+ )
1915
+ ])
1916
+ ])
1917
+ )
1918
+ )
1919
+ ])
1920
+ ]),
1921
+ (0, import_vue4.h)("div", { style: s2.pagination }, [
1922
+ (0, import_vue4.h)("label", { style: s2.pageSize }, [
1923
+ "\u6BCF\u9875",
1924
+ (0, import_vue4.h)(
1925
+ "select",
1926
+ {
1927
+ style: s2.select,
1928
+ value: pageSize.value,
1929
+ onChange: (e) => {
1930
+ pageSize.value = e.target.value;
1931
+ }
1932
+ },
1933
+ PAGE_SIZE_OPTIONS2.map(
1934
+ (size) => (0, import_vue4.h)("option", { key: size, value: size }, size)
1935
+ )
1936
+ )
1937
+ ]),
1938
+ (0, import_vue4.h)("div", { style: s2.pageBtns }, [
1939
+ (0, import_vue4.h)(
1940
+ "button",
1941
+ {
1942
+ type: "button",
1943
+ style: s2.secondaryBtn,
1944
+ disabled: !hasPreviousPage.value || loading.value,
1945
+ onClick: () => void loadList("previous")
1946
+ },
1947
+ "\u4E0A\u4E00\u9875"
1948
+ ),
1949
+ (0, import_vue4.h)(
1950
+ "button",
1951
+ {
1952
+ type: "button",
1953
+ style: s2.secondaryBtn,
1954
+ disabled: !hasNextPage.value || loading.value,
1955
+ onClick: () => void loadList("next")
1956
+ },
1957
+ "\u4E0B\u4E00\u9875"
1958
+ )
1959
+ ])
1960
+ ]),
1961
+ dialogOpen.value ? (0, import_vue4.h)(
1962
+ "div",
1963
+ { style: s2.mask, onClick: closeDialog },
1964
+ [
1965
+ (0, import_vue4.h)(
1966
+ "div",
1967
+ {
1968
+ style: { ...s2.dialog, maxWidth: "520px" },
1969
+ role: "dialog",
1970
+ "aria-modal": "true",
1971
+ onClick: (e) => e.stopPropagation()
1972
+ },
1973
+ [
1974
+ (0, import_vue4.h)("div", { style: s2.dialogHeader }, [
1975
+ (0, import_vue4.h)(
1976
+ "h3",
1977
+ { style: s2.dialogTitle },
1978
+ editing.value ? "\u7F16\u8F91\u83DC\u5355" : "\u65B0\u589E\u83DC\u5355"
1979
+ ),
1980
+ (0, import_vue4.h)(
1981
+ "button",
1982
+ {
1983
+ type: "button",
1984
+ style: s2.iconBtn,
1985
+ "aria-label": "\u5173\u95ED",
1986
+ onClick: closeDialog
1987
+ },
1988
+ "\xD7"
1989
+ )
1990
+ ]),
1991
+ (0, import_vue4.h)(
1992
+ "form",
1993
+ {
1994
+ style: s2.form,
1995
+ onSubmit: (e) => void handleSubmit(e)
1996
+ },
1997
+ [
1998
+ (0, import_vue4.h)("label", { style: s2.field }, [
1999
+ (0, import_vue4.h)("span", { style: s2.label }, "\u4E0A\u7EA7\u83DC\u5355"),
2000
+ (0, import_vue4.h)(
2001
+ "select",
2002
+ {
2003
+ style: s2.input,
2004
+ value: form.parentId,
2005
+ onChange: (e) => {
2006
+ form.parentId = e.target.value;
2007
+ }
2008
+ },
2009
+ [
2010
+ (0, import_vue4.h)("option", { value: ROOT_PARENT_ID }, "\u6839\u76EE\u5F55"),
2011
+ ...parentOptions.value.map(
2012
+ (opt) => (0, import_vue4.h)(
2013
+ "option",
2014
+ { key: opt.value, value: opt.value },
2015
+ opt.label
2016
+ )
2017
+ )
2018
+ ]
2019
+ )
2020
+ ]),
2021
+ (0, import_vue4.h)("fieldset", { style: s2.fieldset }, [
2022
+ (0, import_vue4.h)("legend", { style: s2.label }, "\u83DC\u5355\u7C7B\u578B"),
2023
+ (0, import_vue4.h)(
2024
+ "div",
2025
+ { style: s2.radioGroup },
2026
+ MENU_TYPE_OPTIONS.map(
2027
+ (opt) => (0, import_vue4.h)("label", { key: opt.value, style: s2.radioItem }, [
2028
+ (0, import_vue4.h)("input", {
2029
+ type: "radio",
2030
+ name: "menu-type",
2031
+ checked: form.type === opt.value,
2032
+ onChange: () => {
2033
+ form.type = opt.value;
2034
+ }
2035
+ }),
2036
+ opt.label
2037
+ ])
2038
+ )
2039
+ )
2040
+ ]),
2041
+ (0, import_vue4.h)("label", { style: s2.field }, [
2042
+ (0, import_vue4.h)("span", { style: s2.label }, "\u83DC\u5355\u540D\u79F0"),
2043
+ (0, import_vue4.h)("input", {
2044
+ style: s2.input,
2045
+ value: form.name,
2046
+ placeholder: "\u8BF7\u8F93\u5165\u83DC\u5355\u540D\u79F0",
2047
+ required: true,
2048
+ onInput: (e) => {
2049
+ form.name = e.target.value;
2050
+ }
2051
+ })
2052
+ ]),
2053
+ (0, import_vue4.h)("label", { style: s2.field }, [
2054
+ (0, import_vue4.h)("span", { style: s2.label }, "\u8BF7\u6C42\u5730\u5740"),
2055
+ (0, import_vue4.h)("input", {
2056
+ style: s2.input,
2057
+ value: form.identification,
2058
+ placeholder: "\u5982 /system/user",
2059
+ onInput: (e) => {
2060
+ form.identification = e.target.value;
2061
+ }
2062
+ })
2063
+ ]),
2064
+ (0, import_vue4.h)("fieldset", { style: s2.fieldset }, [
2065
+ (0, import_vue4.h)("legend", { style: s2.label }, "\u6743\u9650\u6807\u8BC6"),
2066
+ (0, import_vue4.h)(
2067
+ "div",
2068
+ { style: s2.multiSelect },
2069
+ permissionPoints.value.length === 0 ? [
2070
+ (0, import_vue4.h)(
2071
+ "div",
2072
+ { style: s2.hint },
2073
+ "\u6682\u65E0\u6743\u9650\u70B9\uFF0C\u8BF7\u5148\u5728\u6743\u9650\u70B9\u7BA1\u7406\u4E2D\u65B0\u589E"
2074
+ )
2075
+ ] : permissionPoints.value.map(
2076
+ (p) => (0, import_vue4.h)(
2077
+ "label",
2078
+ { key: p.resourceId, style: s2.checkItem },
2079
+ [
2080
+ (0, import_vue4.h)("input", {
2081
+ type: "checkbox",
2082
+ checked: form.permissionPointIds.includes(
2083
+ p.resourceId
2084
+ ),
2085
+ onChange: () => togglePermission(p.resourceId)
2086
+ }),
2087
+ (0, import_vue4.h)("span", [
2088
+ p.name,
2089
+ (0, import_vue4.h)(
2090
+ "code",
2091
+ {
2092
+ style: {
2093
+ ...s2.code,
2094
+ marginLeft: "6px"
2095
+ }
2096
+ },
2097
+ p.identification
2098
+ )
2099
+ ])
2100
+ ]
2101
+ )
2102
+ )
2103
+ )
2104
+ ]),
2105
+ (0, import_vue4.h)("fieldset", { style: s2.fieldset }, [
2106
+ (0, import_vue4.h)("legend", { style: s2.label }, "\u72B6\u6001"),
2107
+ (0, import_vue4.h)(
2108
+ "div",
2109
+ { style: s2.radioGroup },
2110
+ MENU_VISIBILITY_OPTIONS.map(
2111
+ (opt) => (0, import_vue4.h)("label", { key: opt.value, style: s2.radioItem }, [
2112
+ (0, import_vue4.h)("input", {
2113
+ type: "radio",
2114
+ name: "menu-status",
2115
+ checked: form.status === opt.value,
2116
+ onChange: () => {
2117
+ form.status = opt.value;
2118
+ }
2119
+ }),
2120
+ opt.label
2121
+ ])
2122
+ )
2123
+ )
2124
+ ]),
2125
+ (0, import_vue4.h)("div", { style: s2.dialogFooter }, [
2126
+ (0, import_vue4.h)(
2127
+ "button",
2128
+ {
2129
+ type: "button",
2130
+ style: s2.secondaryBtn,
2131
+ onClick: closeDialog
2132
+ },
2133
+ "\u53D6\u6D88"
2134
+ ),
2135
+ (0, import_vue4.h)(
2136
+ "button",
2137
+ {
2138
+ type: "submit",
2139
+ style: s2.primaryBtn,
2140
+ disabled: saving.value
2141
+ },
2142
+ saving.value ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58"
2143
+ )
2144
+ ])
2145
+ ]
2146
+ )
2147
+ ]
2148
+ )
2149
+ ]
2150
+ ) : null,
2151
+ deletingRow.value ? (0, import_vue4.h)(
2152
+ "div",
2153
+ { style: s2.mask, onClick: closeDeleteDialog },
2154
+ [
2155
+ (0, import_vue4.h)(
2156
+ "div",
2157
+ {
2158
+ style: { ...s2.dialog, maxWidth: "420px" },
2159
+ role: "dialog",
2160
+ "aria-modal": "true",
2161
+ "aria-labelledby": "angel-auth-menu-delete-title",
2162
+ onClick: (e) => e.stopPropagation()
2163
+ },
2164
+ [
2165
+ (0, import_vue4.h)("div", { style: s2.dialogHeader }, [
2166
+ (0, import_vue4.h)(
2167
+ "h3",
2168
+ {
2169
+ id: "angel-auth-menu-delete-title",
2170
+ style: s2.dialogTitle
2171
+ },
2172
+ "\u786E\u8BA4\u5220\u9664"
2173
+ ),
2174
+ (0, import_vue4.h)(
2175
+ "button",
2176
+ {
2177
+ type: "button",
2178
+ style: s2.iconBtn,
2179
+ "aria-label": "\u5173\u95ED",
2180
+ onClick: closeDeleteDialog
2181
+ },
2182
+ "\xD7"
2183
+ )
2184
+ ]),
2185
+ (0, import_vue4.h)("div", { style: s2.confirmBody }, [
2186
+ (0, import_vue4.h)("p", { style: s2.confirmText }, [
2187
+ "\u786E\u8BA4\u5220\u9664\u83DC\u5355\u300C",
2188
+ (0, import_vue4.h)("strong", deletingRow.value.name),
2189
+ "\u300D\u5417\uFF1F\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\u3002"
2190
+ ]),
2191
+ (0, import_vue4.h)("div", { style: s2.dialogFooter }, [
2192
+ (0, import_vue4.h)(
2193
+ "button",
2194
+ {
2195
+ type: "button",
2196
+ style: s2.secondaryBtn,
2197
+ disabled: deleting.value,
2198
+ onClick: closeDeleteDialog
2199
+ },
2200
+ "\u53D6\u6D88"
2201
+ ),
2202
+ (0, import_vue4.h)(
2203
+ "button",
2204
+ {
2205
+ type: "button",
2206
+ style: s2.dangerBtn,
2207
+ disabled: deleting.value,
2208
+ onClick: () => void confirmDelete()
2209
+ },
2210
+ deleting.value ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u5220\u9664"
2211
+ )
2212
+ ])
2213
+ ])
2214
+ ]
2215
+ )
2216
+ ]
1180
2217
  ) : null
1181
2218
  ]);
1182
2219
  }
@@ -1184,6 +2221,14 @@ var ResourceManager = (0, import_vue3.defineComponent)({
1184
2221
  // Annotate the CommonJS export names for ESM import in node:
1185
2222
  0 && (module.exports = {
1186
2223
  Can,
2224
+ MENU_LIST_TYPE_PARAM,
2225
+ MENU_TYPE_BUTTON,
2226
+ MENU_TYPE_LABEL,
2227
+ MENU_TYPE_MENU,
2228
+ MENU_TYPE_OPTIONS,
2229
+ MENU_TYPE_PAGE,
2230
+ MENU_VISIBILITY_OPTIONS,
2231
+ MenuManager,
1187
2232
  PERMISSION_STORE_KEY,
1188
2233
  PermissionStore,
1189
2234
  RESOURCE_PRIVATE_OPTIONS,
@@ -1191,12 +2236,16 @@ var ResourceManager = (0, import_vue3.defineComponent)({
1191
2236
  RESOURCE_STATUS_ENABLED,
1192
2237
  RESOURCE_STATUS_OPTIONS,
1193
2238
  RESOURCE_TYPE_API,
2239
+ ROOT_PARENT_ID,
1194
2240
  ResourceManager,
1195
2241
  appendQueryParam,
1196
2242
  buildCreateBody,
2243
+ buildCreateMenuBody,
1197
2244
  buildUpdateBody,
2245
+ buildUpdateMenuBody,
1198
2246
  createAuthorizationResourceApi,
1199
2247
  createDefaultResourceRequest,
2248
+ createMenuResourceApi,
1200
2249
  createPermissionPlugin,
1201
2250
  createPermissionStore,
1202
2251
  createVPermission,
@@ -1205,6 +2254,7 @@ var ResourceManager = (0, import_vue3.defineComponent)({
1205
2254
  getAppClientId,
1206
2255
  getDeviceWorkerId,
1207
2256
  mapAuthorizationResource,
2257
+ mapMenuResource,
1208
2258
  snowyflake,
1209
2259
  useHasPermission,
1210
2260
  useHasRole,