com-angel-authorization 1.0.5 → 1.0.7

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,19 @@ __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,
41
+ SYSTEM_ADMIN_DEFAULT_KEY: () => SYSTEM_ADMIN_DEFAULT_KEY,
42
+ SYSTEM_ADMIN_MENU: () => SYSTEM_ADMIN_MENU,
43
+ SystemAdmin: () => SystemAdmin,
32
44
  appendQueryParam: () => appendQueryParam,
33
45
  buildCreateBody: () => buildCreateBody,
46
+ buildCreateMenuBody: () => buildCreateMenuBody,
34
47
  buildUpdateBody: () => buildUpdateBody,
48
+ buildUpdateMenuBody: () => buildUpdateMenuBody,
35
49
  createAuthorizationResourceApi: () => createAuthorizationResourceApi,
36
50
  createDefaultResourceRequest: () => createDefaultResourceRequest,
51
+ createMenuResourceApi: () => createMenuResourceApi,
37
52
  createPermissionPlugin: () => createPermissionPlugin,
38
53
  createPermissionStore: () => createPermissionStore,
39
54
  createVPermission: () => createVPermission,
@@ -42,6 +57,7 @@ __export(vue_exports, {
42
57
  getAppClientId: () => getAppClientId,
43
58
  getDeviceWorkerId: () => getDeviceWorkerId,
44
59
  mapAuthorizationResource: () => mapAuthorizationResource,
60
+ mapMenuResource: () => mapMenuResource,
45
61
  snowyflake: () => snowyflake,
46
62
  useHasPermission: () => useHasPermission,
47
63
  useHasRole: () => useHasRole,
@@ -349,16 +365,35 @@ var import_vue3 = require("vue");
349
365
 
350
366
  // src/resources/types.ts
351
367
  var RESOURCE_TYPE_API = "api";
368
+ var MENU_TYPE_PAGE = "page";
369
+ var MENU_TYPE_MENU = "menu";
370
+ var MENU_TYPE_BUTTON = "button";
371
+ var MENU_LIST_TYPE_PARAM = "page,menu,button";
372
+ var ROOT_PARENT_ID = "0";
352
373
  var RESOURCE_STATUS_ENABLED = 1;
353
374
  var RESOURCE_STATUS_DISABLED = 0;
354
375
  var RESOURCE_STATUS_OPTIONS = [
355
376
  { label: "\u542F\u7528", value: RESOURCE_STATUS_ENABLED },
356
377
  { label: "\u7981\u7528", value: RESOURCE_STATUS_DISABLED }
357
378
  ];
379
+ var MENU_VISIBILITY_OPTIONS = [
380
+ { label: "\u663E\u793A", value: RESOURCE_STATUS_ENABLED },
381
+ { label: "\u9690\u85CF", value: RESOURCE_STATUS_DISABLED }
382
+ ];
358
383
  var RESOURCE_PRIVATE_OPTIONS = [
359
384
  { label: "\u662F", value: true },
360
385
  { label: "\u5426", value: false }
361
386
  ];
387
+ var MENU_TYPE_OPTIONS = [
388
+ { label: "\u76EE\u5F55", value: MENU_TYPE_PAGE },
389
+ { label: "\u83DC\u5355", value: MENU_TYPE_MENU },
390
+ { label: "\u6309\u94AE", value: MENU_TYPE_BUTTON }
391
+ ];
392
+ var MENU_TYPE_LABEL = {
393
+ page: "\u76EE\u5F55",
394
+ menu: "\u83DC\u5355",
395
+ button: "\u6309\u94AE"
396
+ };
362
397
 
363
398
  // src/utils/snowflake.ts
364
399
  var DEVICE_WORKER_ID_KEY = "hgams_device_worker_id";
@@ -503,6 +538,29 @@ function toBoolean(value) {
503
538
  }
504
539
  return false;
505
540
  }
541
+ function toStringArray(value) {
542
+ if (Array.isArray(value)) {
543
+ return value.map((item) => {
544
+ if (item && typeof item === "object") {
545
+ const row = item;
546
+ const id = row.resourceId ?? row.resource_id ?? row.id;
547
+ return id === void 0 || id === null ? "" : String(id);
548
+ }
549
+ return String(item ?? "");
550
+ }).filter(Boolean);
551
+ }
552
+ if (typeof value === "string" && value.trim()) {
553
+ return value.split(",").map((s4) => s4.trim()).filter(Boolean);
554
+ }
555
+ return [];
556
+ }
557
+ function toMenuType(value) {
558
+ const v = String(value ?? "").toLowerCase();
559
+ if (v === MENU_TYPE_PAGE || v === MENU_TYPE_MENU || v === MENU_TYPE_BUTTON) {
560
+ return v;
561
+ }
562
+ return MENU_TYPE_MENU;
563
+ }
506
564
  function mapAuthorizationResource(item) {
507
565
  if (!item || typeof item !== "object") return null;
508
566
  const row = item;
@@ -518,9 +576,31 @@ function mapAuthorizationResource(item) {
518
576
  description: String(row.description ?? row.desc ?? "")
519
577
  };
520
578
  }
521
- function buildListUrl(params) {
579
+ function mapMenuResource(item) {
580
+ if (!item || typeof item !== "object") return null;
581
+ const row = item;
582
+ const resourceId = row.resourceId ?? row.resource_id ?? row.id;
583
+ if (resourceId === void 0 || resourceId === null || resourceId === "") return null;
584
+ const permissionPointIds = toStringArray(
585
+ row.permissionPointIds ?? row.permission_point_ids ?? row.permissionPoints ?? row.permissions
586
+ );
587
+ const permissionNamesRaw = row.permissionPointNames ?? row.permission_point_names ?? row.permissionNames;
588
+ const permissionPointNames = Array.isArray(permissionNamesRaw) ? permissionNamesRaw.map((n) => String(n ?? "")).filter(Boolean) : void 0;
589
+ const parentId = row.parentId ?? row.parent_id ?? ROOT_PARENT_ID;
590
+ return {
591
+ resourceId: String(resourceId),
592
+ parentId: parentId === void 0 || parentId === null ? ROOT_PARENT_ID : String(parentId),
593
+ type: toMenuType(row.type),
594
+ name: String(row.name ?? ""),
595
+ identification: String(row.identification ?? row.identity ?? row.path ?? ""),
596
+ permissionPointIds,
597
+ permissionPointNames,
598
+ status: toResourceStatus(row.status)
599
+ };
600
+ }
601
+ function buildListUrl(type, params) {
522
602
  const parts = [];
523
- appendQueryParam(parts, "type", RESOURCE_TYPE_API);
603
+ appendQueryParam(parts, "type", type);
524
604
  appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
525
605
  appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
526
606
  appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
@@ -547,12 +627,33 @@ function buildUpdateBody(values) {
547
627
  description: values.description.trim()
548
628
  };
549
629
  }
630
+ function buildCreateMenuBody(values, resourceId = getAppClientId()) {
631
+ return {
632
+ resourceId,
633
+ parentId: values.parentId || ROOT_PARENT_ID,
634
+ type: values.type,
635
+ name: values.name.trim(),
636
+ identification: values.identification.trim(),
637
+ permissionPointIds: [...values.permissionPointIds],
638
+ status: values.status
639
+ };
640
+ }
641
+ function buildUpdateMenuBody(values) {
642
+ return {
643
+ parentId: values.parentId || ROOT_PARENT_ID,
644
+ type: values.type,
645
+ name: values.name.trim(),
646
+ identification: values.identification.trim(),
647
+ permissionPointIds: [...values.permissionPointIds],
648
+ status: values.status
649
+ };
650
+ }
550
651
  function createAuthorizationResourceApi(request) {
551
652
  return {
552
653
  async list(params, signal) {
553
654
  const json = await request({
554
655
  method: "GET",
555
- url: buildListUrl(params),
656
+ url: buildListUrl(RESOURCE_TYPE_API, params),
556
657
  signal
557
658
  });
558
659
  const records = extractRecords(json).map(mapAuthorizationResource).filter((item) => item !== null);
@@ -587,6 +688,50 @@ function createAuthorizationResourceApi(request) {
587
688
  }
588
689
  };
589
690
  }
691
+ function createMenuResourceApi(request) {
692
+ const permissionApi = createAuthorizationResourceApi(request);
693
+ return {
694
+ async list(params, signal) {
695
+ const json = await request({
696
+ method: "GET",
697
+ url: buildListUrl(MENU_LIST_TYPE_PARAM, params),
698
+ signal
699
+ });
700
+ const records = extractRecords(json).map(mapMenuResource).filter((item) => item !== null);
701
+ const pagination = extractPagination(json);
702
+ return {
703
+ records,
704
+ ...pagination
705
+ };
706
+ },
707
+ listPermissionPoints(params, signal) {
708
+ return permissionApi.list(params, signal);
709
+ },
710
+ async create(values, signal) {
711
+ return request({
712
+ method: "POST",
713
+ url: "/authorization-resources",
714
+ body: buildCreateMenuBody(values),
715
+ signal
716
+ });
717
+ },
718
+ async update(resourceId, values, signal) {
719
+ return request({
720
+ method: "PATCH",
721
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
722
+ body: buildUpdateMenuBody(values),
723
+ signal
724
+ });
725
+ },
726
+ async remove(resourceId, signal) {
727
+ return request({
728
+ method: "DELETE",
729
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}`,
730
+ signal
731
+ });
732
+ }
733
+ };
734
+ }
590
735
  function createDefaultResourceRequest(options = {}) {
591
736
  const baseUrl = (options.baseUrl ?? "").replace(/\/+$/, "");
592
737
  const credentials = options.credentials ?? "include";
@@ -1287,9 +1432,986 @@ var ResourceManager = (0, import_vue3.defineComponent)({
1287
1432
  ]);
1288
1433
  }
1289
1434
  });
1435
+
1436
+ // src/vue/MenuManager.ts
1437
+ var import_vue4 = require("vue");
1438
+ var PAGE_SIZE_OPTIONS2 = ["10", "20", "50", "100"];
1439
+ function emptyForm2() {
1440
+ return {
1441
+ parentId: ROOT_PARENT_ID,
1442
+ type: MENU_TYPE_MENU,
1443
+ name: "",
1444
+ identification: "",
1445
+ permissionPointIds: [],
1446
+ status: RESOURCE_STATUS_ENABLED
1447
+ };
1448
+ }
1449
+ var s2 = {
1450
+ root: {
1451
+ display: "flex",
1452
+ flexDirection: "column",
1453
+ gap: "16px",
1454
+ padding: "16px",
1455
+ color: "#101828",
1456
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
1457
+ },
1458
+ toolbar: {
1459
+ display: "flex",
1460
+ alignItems: "center",
1461
+ justifyContent: "space-between",
1462
+ gap: "12px"
1463
+ },
1464
+ title: { margin: "0", fontSize: "18px", fontWeight: "600" },
1465
+ toolbarRight: { display: "flex", alignItems: "center", gap: "8px" },
1466
+ error: {
1467
+ padding: "10px 12px",
1468
+ borderRadius: "8px",
1469
+ background: "#fef3f2",
1470
+ color: "#b42318",
1471
+ fontSize: "13px"
1472
+ },
1473
+ tableWrap: {
1474
+ overflow: "auto",
1475
+ border: "1px solid #eaecf0",
1476
+ borderRadius: "10px",
1477
+ background: "#fff"
1478
+ },
1479
+ table: { width: "100%", borderCollapse: "collapse", minWidth: "820px" },
1480
+ th: {
1481
+ textAlign: "left",
1482
+ padding: "12px 14px",
1483
+ fontSize: "13px",
1484
+ fontWeight: "600",
1485
+ color: "#475467",
1486
+ background: "#f9fafb",
1487
+ borderBottom: "1px solid #eaecf0"
1488
+ },
1489
+ td: {
1490
+ padding: "12px 14px",
1491
+ fontSize: "14px",
1492
+ borderBottom: "1px solid #f2f4f7",
1493
+ verticalAlign: "middle"
1494
+ },
1495
+ empty: {
1496
+ padding: "28px",
1497
+ textAlign: "center",
1498
+ color: "#98a2b3",
1499
+ fontSize: "14px"
1500
+ },
1501
+ code: {
1502
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
1503
+ fontSize: "13px",
1504
+ background: "#f2f4f7",
1505
+ padding: "2px 6px",
1506
+ borderRadius: "4px"
1507
+ },
1508
+ badge: {
1509
+ display: "inline-block",
1510
+ padding: "2px 8px",
1511
+ borderRadius: "999px",
1512
+ fontSize: "12px",
1513
+ fontWeight: "500"
1514
+ },
1515
+ linkBtn: {
1516
+ border: "none",
1517
+ background: "transparent",
1518
+ color: "#049BAD",
1519
+ cursor: "pointer",
1520
+ padding: "0 8px 0 0",
1521
+ fontSize: "13px"
1522
+ },
1523
+ pagination: {
1524
+ display: "flex",
1525
+ alignItems: "center",
1526
+ justifyContent: "space-between",
1527
+ gap: "12px"
1528
+ },
1529
+ pageSize: {
1530
+ display: "flex",
1531
+ alignItems: "center",
1532
+ gap: "8px",
1533
+ fontSize: "13px",
1534
+ color: "#475467"
1535
+ },
1536
+ pageBtns: { display: "flex", gap: "8px" },
1537
+ primaryBtn: {
1538
+ border: "none",
1539
+ background: "#049BAD",
1540
+ color: "#fff",
1541
+ borderRadius: "8px",
1542
+ padding: "8px 14px",
1543
+ cursor: "pointer",
1544
+ fontSize: "14px"
1545
+ },
1546
+ secondaryBtn: {
1547
+ border: "1px solid #d0d5dd",
1548
+ background: "#fff",
1549
+ color: "#344054",
1550
+ borderRadius: "8px",
1551
+ padding: "8px 14px",
1552
+ cursor: "pointer",
1553
+ fontSize: "14px"
1554
+ },
1555
+ dangerBtn: {
1556
+ border: "none",
1557
+ background: "#d92d20",
1558
+ color: "#fff",
1559
+ borderRadius: "8px",
1560
+ padding: "8px 14px",
1561
+ cursor: "pointer",
1562
+ fontSize: "14px"
1563
+ },
1564
+ select: {
1565
+ border: "1px solid #d0d5dd",
1566
+ borderRadius: "6px",
1567
+ padding: "4px 8px",
1568
+ fontSize: "13px",
1569
+ backgroundColor: "#ffffff",
1570
+ color: "#101828"
1571
+ },
1572
+ mask: {
1573
+ position: "fixed",
1574
+ inset: "0",
1575
+ background: "rgba(16, 24, 40, 0.45)",
1576
+ display: "flex",
1577
+ alignItems: "center",
1578
+ justifyContent: "center",
1579
+ zIndex: "1000",
1580
+ padding: "16px"
1581
+ },
1582
+ dialog: {
1583
+ width: "100%",
1584
+ maxWidth: "480px",
1585
+ background: "#fff",
1586
+ borderRadius: "12px",
1587
+ boxShadow: "0 20px 40px rgba(16,24,40,0.18)",
1588
+ maxHeight: "90vh",
1589
+ overflow: "auto"
1590
+ },
1591
+ dialogHeader: {
1592
+ display: "flex",
1593
+ alignItems: "center",
1594
+ justifyContent: "space-between",
1595
+ padding: "14px 16px",
1596
+ borderBottom: "1px solid #eaecf0",
1597
+ position: "sticky",
1598
+ top: "0",
1599
+ background: "#fff",
1600
+ zIndex: "1"
1601
+ },
1602
+ dialogTitle: { margin: "0", fontSize: "16px", fontWeight: "600" },
1603
+ iconBtn: {
1604
+ border: "none",
1605
+ background: "transparent",
1606
+ fontSize: "22px",
1607
+ lineHeight: "1",
1608
+ cursor: "pointer",
1609
+ color: "#667085"
1610
+ },
1611
+ form: { display: "flex", flexDirection: "column", gap: "12px", padding: "16px" },
1612
+ confirmBody: {
1613
+ display: "flex",
1614
+ flexDirection: "column",
1615
+ gap: "16px",
1616
+ padding: "16px"
1617
+ },
1618
+ confirmText: {
1619
+ margin: "0",
1620
+ fontSize: "14px",
1621
+ color: "#344054",
1622
+ lineHeight: "1.6"
1623
+ },
1624
+ field: { display: "flex", flexDirection: "column", gap: "6px" },
1625
+ fieldset: {
1626
+ margin: "0",
1627
+ padding: "0",
1628
+ border: "none",
1629
+ display: "flex",
1630
+ flexDirection: "column",
1631
+ gap: "8px"
1632
+ },
1633
+ label: { fontSize: "13px", color: "#344054", fontWeight: "500" },
1634
+ input: {
1635
+ border: "1px solid #d0d5dd",
1636
+ borderRadius: "8px",
1637
+ padding: "8px 10px",
1638
+ fontSize: "14px",
1639
+ outline: "none",
1640
+ backgroundColor: "#ffffff",
1641
+ color: "#101828",
1642
+ boxSizing: "border-box",
1643
+ width: "100%"
1644
+ },
1645
+ radioGroup: { display: "flex", flexWrap: "wrap", gap: "16px" },
1646
+ radioItem: {
1647
+ display: "flex",
1648
+ alignItems: "center",
1649
+ gap: "6px",
1650
+ fontSize: "14px",
1651
+ color: "#344054",
1652
+ cursor: "pointer"
1653
+ },
1654
+ multiSelect: {
1655
+ maxHeight: "160px",
1656
+ overflow: "auto",
1657
+ border: "1px solid #eaecf0",
1658
+ borderRadius: "8px",
1659
+ padding: "8px",
1660
+ background: "#f9fafb"
1661
+ },
1662
+ checkItem: {
1663
+ display: "flex",
1664
+ alignItems: "center",
1665
+ gap: "8px",
1666
+ padding: "6px 4px",
1667
+ fontSize: "13px",
1668
+ color: "#344054",
1669
+ cursor: "pointer"
1670
+ },
1671
+ hint: { fontSize: "13px", color: "#98a2b3", padding: "8px" },
1672
+ dialogFooter: {
1673
+ display: "flex",
1674
+ justifyContent: "flex-end",
1675
+ gap: "8px",
1676
+ paddingTop: "4px"
1677
+ }
1678
+ };
1679
+ var MenuManager = (0, import_vue4.defineComponent)({
1680
+ name: "MenuManager",
1681
+ props: {
1682
+ api: {
1683
+ type: Object,
1684
+ required: true
1685
+ },
1686
+ title: {
1687
+ type: String,
1688
+ default: "\u83DC\u5355\u7BA1\u7406"
1689
+ },
1690
+ pageSize: {
1691
+ type: String,
1692
+ default: "20"
1693
+ }
1694
+ },
1695
+ setup(props, { slots }) {
1696
+ const records = (0, import_vue4.ref)([]);
1697
+ const permissionPoints = (0, import_vue4.ref)([]);
1698
+ const loading = (0, import_vue4.ref)(false);
1699
+ const error = (0, import_vue4.ref)("");
1700
+ const pageSize = (0, import_vue4.ref)(props.pageSize);
1701
+ const pageToken = (0, import_vue4.ref)("");
1702
+ const hasPreviousPage = (0, import_vue4.ref)(false);
1703
+ const hasNextPage = (0, import_vue4.ref)(false);
1704
+ const dialogOpen = (0, import_vue4.ref)(false);
1705
+ const editing = (0, import_vue4.ref)(null);
1706
+ const form = (0, import_vue4.reactive)(emptyForm2());
1707
+ const saving = (0, import_vue4.ref)(false);
1708
+ const deletingRow = (0, import_vue4.ref)(null);
1709
+ const deleting = (0, import_vue4.ref)(false);
1710
+ const permissionNameMap = (0, import_vue4.computed)(() => {
1711
+ const map = /* @__PURE__ */ new Map();
1712
+ permissionPoints.value.forEach(
1713
+ (p) => map.set(p.resourceId, p.name || p.identification)
1714
+ );
1715
+ return map;
1716
+ });
1717
+ const parentOptions = (0, import_vue4.computed)(
1718
+ () => records.value.filter((row) => !editing.value || row.resourceId !== editing.value.resourceId).map((row) => ({
1719
+ value: row.resourceId,
1720
+ label: `${row.name}\uFF08${MENU_TYPE_LABEL[row.type]}\uFF09`
1721
+ }))
1722
+ );
1723
+ async function loadList(direction = "current", token = pageToken.value) {
1724
+ loading.value = true;
1725
+ error.value = "";
1726
+ try {
1727
+ const result = await props.api.list({
1728
+ pagination: {
1729
+ pageToken: token,
1730
+ pageSize: pageSize.value,
1731
+ pageDirection: direction
1732
+ }
1733
+ });
1734
+ records.value = result.records;
1735
+ pageToken.value = result.pageToken;
1736
+ hasPreviousPage.value = result.hasPreviousPage;
1737
+ hasNextPage.value = result.hasNextPage;
1738
+ } catch (err) {
1739
+ error.value = err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25";
1740
+ } finally {
1741
+ loading.value = false;
1742
+ }
1743
+ }
1744
+ async function loadPermissionPoints() {
1745
+ try {
1746
+ const result = await props.api.listPermissionPoints({
1747
+ pagination: { pageSize: "200", pageDirection: "current" }
1748
+ });
1749
+ permissionPoints.value = result.records;
1750
+ } catch {
1751
+ }
1752
+ }
1753
+ function openCreate() {
1754
+ editing.value = null;
1755
+ Object.assign(form, emptyForm2());
1756
+ dialogOpen.value = true;
1757
+ void loadPermissionPoints();
1758
+ }
1759
+ function openEdit(row) {
1760
+ editing.value = row;
1761
+ Object.assign(form, {
1762
+ parentId: row.parentId || ROOT_PARENT_ID,
1763
+ type: row.type,
1764
+ name: row.name,
1765
+ identification: row.identification,
1766
+ permissionPointIds: [...row.permissionPointIds],
1767
+ status: row.status
1768
+ });
1769
+ dialogOpen.value = true;
1770
+ void loadPermissionPoints();
1771
+ }
1772
+ function closeDialog() {
1773
+ if (!saving.value) dialogOpen.value = false;
1774
+ }
1775
+ async function handleSubmit(event) {
1776
+ event.preventDefault();
1777
+ if (!form.name.trim()) {
1778
+ error.value = "\u8BF7\u586B\u5199\u83DC\u5355\u540D\u79F0";
1779
+ return;
1780
+ }
1781
+ saving.value = true;
1782
+ error.value = "";
1783
+ try {
1784
+ if (editing.value) {
1785
+ await props.api.update(editing.value.resourceId, { ...form });
1786
+ } else {
1787
+ await props.api.create({ ...form });
1788
+ }
1789
+ dialogOpen.value = false;
1790
+ await loadList("current", "");
1791
+ } catch (err) {
1792
+ error.value = err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25";
1793
+ } finally {
1794
+ saving.value = false;
1795
+ }
1796
+ }
1797
+ function askDelete(row) {
1798
+ deletingRow.value = row;
1799
+ }
1800
+ function closeDeleteDialog() {
1801
+ if (!deleting.value) deletingRow.value = null;
1802
+ }
1803
+ async function confirmDelete() {
1804
+ if (!deletingRow.value) return;
1805
+ deleting.value = true;
1806
+ error.value = "";
1807
+ try {
1808
+ await props.api.remove(deletingRow.value.resourceId);
1809
+ deletingRow.value = null;
1810
+ await loadList("current", "");
1811
+ } catch (err) {
1812
+ error.value = err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25";
1813
+ } finally {
1814
+ deleting.value = false;
1815
+ }
1816
+ }
1817
+ function togglePermission(id) {
1818
+ const exists = form.permissionPointIds.includes(id);
1819
+ form.permissionPointIds = exists ? form.permissionPointIds.filter((x) => x !== id) : [...form.permissionPointIds, id];
1820
+ }
1821
+ function renderPermissionLabels(row) {
1822
+ if (row.permissionPointNames?.length) {
1823
+ return row.permissionPointNames.join("\u3001");
1824
+ }
1825
+ if (!row.permissionPointIds.length) return "\u2014";
1826
+ return row.permissionPointIds.map((id) => permissionNameMap.value.get(id) ?? id).join("\u3001");
1827
+ }
1828
+ (0, import_vue4.onMounted)(() => {
1829
+ void loadList("current", "");
1830
+ void loadPermissionPoints();
1831
+ });
1832
+ (0, import_vue4.watch)(
1833
+ () => [props.api, pageSize.value],
1834
+ () => {
1835
+ pageToken.value = "";
1836
+ void loadList("current", "");
1837
+ }
1838
+ );
1839
+ return () => (0, import_vue4.h)("div", { style: s2.root }, [
1840
+ (0, import_vue4.h)("div", { style: s2.toolbar }, [
1841
+ (0, import_vue4.h)("h2", { style: s2.title }, props.title),
1842
+ (0, import_vue4.h)("div", { style: s2.toolbarRight }, [
1843
+ slots.toolbarExtra?.(),
1844
+ (0, import_vue4.h)(
1845
+ "button",
1846
+ { type: "button", style: s2.primaryBtn, onClick: openCreate },
1847
+ "\u65B0\u589E"
1848
+ )
1849
+ ])
1850
+ ]),
1851
+ error.value ? (0, import_vue4.h)("div", { style: s2.error }, error.value) : null,
1852
+ (0, import_vue4.h)("div", { style: s2.tableWrap }, [
1853
+ (0, import_vue4.h)("table", { style: s2.table }, [
1854
+ (0, import_vue4.h)("thead", [
1855
+ (0, import_vue4.h)("tr", [
1856
+ (0, import_vue4.h)("th", { style: s2.th }, "\u83DC\u5355\u540D\u79F0"),
1857
+ (0, import_vue4.h)("th", { style: s2.th }, "\u8BF7\u6C42\u5730\u5740"),
1858
+ (0, import_vue4.h)("th", { style: { ...s2.th, width: "90px" } }, "\u7C7B\u578B"),
1859
+ (0, import_vue4.h)("th", { style: { ...s2.th, width: "80px" } }, "\u53EF\u89C1"),
1860
+ (0, import_vue4.h)("th", { style: s2.th }, "\u6743\u9650\u6807\u8BC6"),
1861
+ (0, import_vue4.h)("th", { style: { ...s2.th, width: "140px" } }, "\u64CD\u4F5C")
1862
+ ])
1863
+ ]),
1864
+ (0, import_vue4.h)(
1865
+ "tbody",
1866
+ loading.value ? [
1867
+ (0, import_vue4.h)("tr", [
1868
+ (0, import_vue4.h)("td", { colspan: 6, style: s2.empty }, "\u52A0\u8F7D\u4E2D\u2026")
1869
+ ])
1870
+ ] : records.value.length === 0 ? [
1871
+ (0, import_vue4.h)("tr", [
1872
+ (0, import_vue4.h)("td", { colspan: 6, style: s2.empty }, "\u6682\u65E0\u6570\u636E")
1873
+ ])
1874
+ ] : records.value.map(
1875
+ (row) => (0, import_vue4.h)("tr", { key: row.resourceId }, [
1876
+ (0, import_vue4.h)("td", { style: s2.td }, row.name),
1877
+ (0, import_vue4.h)("td", { style: s2.td }, [
1878
+ (0, import_vue4.h)(
1879
+ "code",
1880
+ { style: s2.code },
1881
+ row.identification || "\u2014"
1882
+ )
1883
+ ]),
1884
+ (0, import_vue4.h)("td", { style: s2.td }, MENU_TYPE_LABEL[row.type]),
1885
+ (0, import_vue4.h)("td", { style: s2.td }, [
1886
+ (0, import_vue4.h)(
1887
+ "span",
1888
+ {
1889
+ style: {
1890
+ ...s2.badge,
1891
+ background: row.status === RESOURCE_STATUS_ENABLED ? "#e8f7ef" : "#f4f4f5",
1892
+ color: row.status === RESOURCE_STATUS_ENABLED ? "#067647" : "#667085"
1893
+ }
1894
+ },
1895
+ row.status === RESOURCE_STATUS_ENABLED ? "\u663E\u793A" : "\u9690\u85CF"
1896
+ )
1897
+ ]),
1898
+ (0, import_vue4.h)("td", { style: s2.td }, renderPermissionLabels(row)),
1899
+ (0, import_vue4.h)("td", { style: s2.td }, [
1900
+ (0, import_vue4.h)(
1901
+ "button",
1902
+ {
1903
+ type: "button",
1904
+ style: s2.linkBtn,
1905
+ onClick: () => openEdit(row)
1906
+ },
1907
+ "\u7F16\u8F91"
1908
+ ),
1909
+ (0, import_vue4.h)(
1910
+ "button",
1911
+ {
1912
+ type: "button",
1913
+ style: { ...s2.linkBtn, color: "#d92d20" },
1914
+ onClick: () => askDelete(row)
1915
+ },
1916
+ "\u5220\u9664"
1917
+ )
1918
+ ])
1919
+ ])
1920
+ )
1921
+ )
1922
+ ])
1923
+ ]),
1924
+ (0, import_vue4.h)("div", { style: s2.pagination }, [
1925
+ (0, import_vue4.h)("label", { style: s2.pageSize }, [
1926
+ "\u6BCF\u9875",
1927
+ (0, import_vue4.h)(
1928
+ "select",
1929
+ {
1930
+ style: s2.select,
1931
+ value: pageSize.value,
1932
+ onChange: (e) => {
1933
+ pageSize.value = e.target.value;
1934
+ }
1935
+ },
1936
+ PAGE_SIZE_OPTIONS2.map(
1937
+ (size) => (0, import_vue4.h)("option", { key: size, value: size }, size)
1938
+ )
1939
+ )
1940
+ ]),
1941
+ (0, import_vue4.h)("div", { style: s2.pageBtns }, [
1942
+ (0, import_vue4.h)(
1943
+ "button",
1944
+ {
1945
+ type: "button",
1946
+ style: s2.secondaryBtn,
1947
+ disabled: !hasPreviousPage.value || loading.value,
1948
+ onClick: () => void loadList("previous")
1949
+ },
1950
+ "\u4E0A\u4E00\u9875"
1951
+ ),
1952
+ (0, import_vue4.h)(
1953
+ "button",
1954
+ {
1955
+ type: "button",
1956
+ style: s2.secondaryBtn,
1957
+ disabled: !hasNextPage.value || loading.value,
1958
+ onClick: () => void loadList("next")
1959
+ },
1960
+ "\u4E0B\u4E00\u9875"
1961
+ )
1962
+ ])
1963
+ ]),
1964
+ dialogOpen.value ? (0, import_vue4.h)(
1965
+ "div",
1966
+ { style: s2.mask, onClick: closeDialog },
1967
+ [
1968
+ (0, import_vue4.h)(
1969
+ "div",
1970
+ {
1971
+ style: { ...s2.dialog, maxWidth: "520px" },
1972
+ role: "dialog",
1973
+ "aria-modal": "true",
1974
+ onClick: (e) => e.stopPropagation()
1975
+ },
1976
+ [
1977
+ (0, import_vue4.h)("div", { style: s2.dialogHeader }, [
1978
+ (0, import_vue4.h)(
1979
+ "h3",
1980
+ { style: s2.dialogTitle },
1981
+ editing.value ? "\u7F16\u8F91\u83DC\u5355" : "\u65B0\u589E\u83DC\u5355"
1982
+ ),
1983
+ (0, import_vue4.h)(
1984
+ "button",
1985
+ {
1986
+ type: "button",
1987
+ style: s2.iconBtn,
1988
+ "aria-label": "\u5173\u95ED",
1989
+ onClick: closeDialog
1990
+ },
1991
+ "\xD7"
1992
+ )
1993
+ ]),
1994
+ (0, import_vue4.h)(
1995
+ "form",
1996
+ {
1997
+ style: s2.form,
1998
+ onSubmit: (e) => void handleSubmit(e)
1999
+ },
2000
+ [
2001
+ (0, import_vue4.h)("label", { style: s2.field }, [
2002
+ (0, import_vue4.h)("span", { style: s2.label }, "\u4E0A\u7EA7\u83DC\u5355"),
2003
+ (0, import_vue4.h)(
2004
+ "select",
2005
+ {
2006
+ style: s2.input,
2007
+ value: form.parentId,
2008
+ onChange: (e) => {
2009
+ form.parentId = e.target.value;
2010
+ }
2011
+ },
2012
+ [
2013
+ (0, import_vue4.h)("option", { value: ROOT_PARENT_ID }, "\u6839\u76EE\u5F55"),
2014
+ ...parentOptions.value.map(
2015
+ (opt) => (0, import_vue4.h)(
2016
+ "option",
2017
+ { key: opt.value, value: opt.value },
2018
+ opt.label
2019
+ )
2020
+ )
2021
+ ]
2022
+ )
2023
+ ]),
2024
+ (0, import_vue4.h)("fieldset", { style: s2.fieldset }, [
2025
+ (0, import_vue4.h)("legend", { style: s2.label }, "\u83DC\u5355\u7C7B\u578B"),
2026
+ (0, import_vue4.h)(
2027
+ "div",
2028
+ { style: s2.radioGroup },
2029
+ MENU_TYPE_OPTIONS.map(
2030
+ (opt) => (0, import_vue4.h)("label", { key: opt.value, style: s2.radioItem }, [
2031
+ (0, import_vue4.h)("input", {
2032
+ type: "radio",
2033
+ name: "menu-type",
2034
+ checked: form.type === opt.value,
2035
+ onChange: () => {
2036
+ form.type = opt.value;
2037
+ }
2038
+ }),
2039
+ opt.label
2040
+ ])
2041
+ )
2042
+ )
2043
+ ]),
2044
+ (0, import_vue4.h)("label", { style: s2.field }, [
2045
+ (0, import_vue4.h)("span", { style: s2.label }, "\u83DC\u5355\u540D\u79F0"),
2046
+ (0, import_vue4.h)("input", {
2047
+ style: s2.input,
2048
+ value: form.name,
2049
+ placeholder: "\u8BF7\u8F93\u5165\u83DC\u5355\u540D\u79F0",
2050
+ required: true,
2051
+ onInput: (e) => {
2052
+ form.name = e.target.value;
2053
+ }
2054
+ })
2055
+ ]),
2056
+ (0, import_vue4.h)("label", { style: s2.field }, [
2057
+ (0, import_vue4.h)("span", { style: s2.label }, "\u8BF7\u6C42\u5730\u5740"),
2058
+ (0, import_vue4.h)("input", {
2059
+ style: s2.input,
2060
+ value: form.identification,
2061
+ placeholder: "\u5982 /system/user",
2062
+ onInput: (e) => {
2063
+ form.identification = e.target.value;
2064
+ }
2065
+ })
2066
+ ]),
2067
+ (0, import_vue4.h)("fieldset", { style: s2.fieldset }, [
2068
+ (0, import_vue4.h)("legend", { style: s2.label }, "\u6743\u9650\u6807\u8BC6"),
2069
+ (0, import_vue4.h)(
2070
+ "div",
2071
+ { style: s2.multiSelect },
2072
+ permissionPoints.value.length === 0 ? [
2073
+ (0, import_vue4.h)(
2074
+ "div",
2075
+ { style: s2.hint },
2076
+ "\u6682\u65E0\u6743\u9650\u70B9\uFF0C\u8BF7\u5148\u5728\u6743\u9650\u70B9\u7BA1\u7406\u4E2D\u65B0\u589E"
2077
+ )
2078
+ ] : permissionPoints.value.map(
2079
+ (p) => (0, import_vue4.h)(
2080
+ "label",
2081
+ { key: p.resourceId, style: s2.checkItem },
2082
+ [
2083
+ (0, import_vue4.h)("input", {
2084
+ type: "checkbox",
2085
+ checked: form.permissionPointIds.includes(
2086
+ p.resourceId
2087
+ ),
2088
+ onChange: () => togglePermission(p.resourceId)
2089
+ }),
2090
+ (0, import_vue4.h)("span", [
2091
+ p.name,
2092
+ (0, import_vue4.h)(
2093
+ "code",
2094
+ {
2095
+ style: {
2096
+ ...s2.code,
2097
+ marginLeft: "6px"
2098
+ }
2099
+ },
2100
+ p.identification
2101
+ )
2102
+ ])
2103
+ ]
2104
+ )
2105
+ )
2106
+ )
2107
+ ]),
2108
+ (0, import_vue4.h)("fieldset", { style: s2.fieldset }, [
2109
+ (0, import_vue4.h)("legend", { style: s2.label }, "\u72B6\u6001"),
2110
+ (0, import_vue4.h)(
2111
+ "div",
2112
+ { style: s2.radioGroup },
2113
+ MENU_VISIBILITY_OPTIONS.map(
2114
+ (opt) => (0, import_vue4.h)("label", { key: opt.value, style: s2.radioItem }, [
2115
+ (0, import_vue4.h)("input", {
2116
+ type: "radio",
2117
+ name: "menu-status",
2118
+ checked: form.status === opt.value,
2119
+ onChange: () => {
2120
+ form.status = opt.value;
2121
+ }
2122
+ }),
2123
+ opt.label
2124
+ ])
2125
+ )
2126
+ )
2127
+ ]),
2128
+ (0, import_vue4.h)("div", { style: s2.dialogFooter }, [
2129
+ (0, import_vue4.h)(
2130
+ "button",
2131
+ {
2132
+ type: "button",
2133
+ style: s2.secondaryBtn,
2134
+ onClick: closeDialog
2135
+ },
2136
+ "\u53D6\u6D88"
2137
+ ),
2138
+ (0, import_vue4.h)(
2139
+ "button",
2140
+ {
2141
+ type: "submit",
2142
+ style: s2.primaryBtn,
2143
+ disabled: saving.value
2144
+ },
2145
+ saving.value ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58"
2146
+ )
2147
+ ])
2148
+ ]
2149
+ )
2150
+ ]
2151
+ )
2152
+ ]
2153
+ ) : null,
2154
+ deletingRow.value ? (0, import_vue4.h)(
2155
+ "div",
2156
+ { style: s2.mask, onClick: closeDeleteDialog },
2157
+ [
2158
+ (0, import_vue4.h)(
2159
+ "div",
2160
+ {
2161
+ style: { ...s2.dialog, maxWidth: "420px" },
2162
+ role: "dialog",
2163
+ "aria-modal": "true",
2164
+ "aria-labelledby": "angel-auth-menu-delete-title",
2165
+ onClick: (e) => e.stopPropagation()
2166
+ },
2167
+ [
2168
+ (0, import_vue4.h)("div", { style: s2.dialogHeader }, [
2169
+ (0, import_vue4.h)(
2170
+ "h3",
2171
+ {
2172
+ id: "angel-auth-menu-delete-title",
2173
+ style: s2.dialogTitle
2174
+ },
2175
+ "\u786E\u8BA4\u5220\u9664"
2176
+ ),
2177
+ (0, import_vue4.h)(
2178
+ "button",
2179
+ {
2180
+ type: "button",
2181
+ style: s2.iconBtn,
2182
+ "aria-label": "\u5173\u95ED",
2183
+ onClick: closeDeleteDialog
2184
+ },
2185
+ "\xD7"
2186
+ )
2187
+ ]),
2188
+ (0, import_vue4.h)("div", { style: s2.confirmBody }, [
2189
+ (0, import_vue4.h)("p", { style: s2.confirmText }, [
2190
+ "\u786E\u8BA4\u5220\u9664\u83DC\u5355\u300C",
2191
+ (0, import_vue4.h)("strong", deletingRow.value.name),
2192
+ "\u300D\u5417\uFF1F\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\u3002"
2193
+ ]),
2194
+ (0, import_vue4.h)("div", { style: s2.dialogFooter }, [
2195
+ (0, import_vue4.h)(
2196
+ "button",
2197
+ {
2198
+ type: "button",
2199
+ style: s2.secondaryBtn,
2200
+ disabled: deleting.value,
2201
+ onClick: closeDeleteDialog
2202
+ },
2203
+ "\u53D6\u6D88"
2204
+ ),
2205
+ (0, import_vue4.h)(
2206
+ "button",
2207
+ {
2208
+ type: "button",
2209
+ style: s2.dangerBtn,
2210
+ disabled: deleting.value,
2211
+ onClick: () => void confirmDelete()
2212
+ },
2213
+ deleting.value ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u5220\u9664"
2214
+ )
2215
+ ])
2216
+ ])
2217
+ ]
2218
+ )
2219
+ ]
2220
+ ) : null
2221
+ ]);
2222
+ }
2223
+ });
2224
+
2225
+ // src/vue/SystemAdmin.ts
2226
+ var import_vue5 = require("vue");
2227
+
2228
+ // src/admin/menu.ts
2229
+ var SYSTEM_ADMIN_MENU = {
2230
+ key: "system",
2231
+ label: "\u7CFB\u7EDF\u7BA1\u7406",
2232
+ children: [
2233
+ { key: "menu", label: "\u83DC\u5355\u7BA1\u7406" },
2234
+ { key: "resource", label: "\u6743\u9650\u70B9\u7BA1\u7406" }
2235
+ ]
2236
+ };
2237
+ var SYSTEM_ADMIN_DEFAULT_KEY = "menu";
2238
+
2239
+ // src/vue/SystemAdmin.ts
2240
+ var s3 = {
2241
+ root: {
2242
+ display: "flex",
2243
+ minHeight: "560px",
2244
+ border: "1px solid #eaecf0",
2245
+ borderRadius: "12px",
2246
+ overflow: "hidden",
2247
+ background: "#fff",
2248
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif',
2249
+ color: "#101828"
2250
+ },
2251
+ sidebar: {
2252
+ width: "200px",
2253
+ flexShrink: "0",
2254
+ borderRight: "1px solid #eaecf0",
2255
+ background: "#f9fafb",
2256
+ padding: "16px 12px"
2257
+ },
2258
+ sidebarTitle: {
2259
+ fontSize: "14px",
2260
+ fontWeight: "600",
2261
+ color: "#344054",
2262
+ padding: "4px 10px 12px"
2263
+ },
2264
+ nav: {
2265
+ display: "flex",
2266
+ flexDirection: "column",
2267
+ gap: "4px"
2268
+ },
2269
+ navItem: {
2270
+ border: "none",
2271
+ background: "transparent",
2272
+ textAlign: "left",
2273
+ padding: "10px 12px",
2274
+ borderRadius: "8px",
2275
+ fontSize: "14px",
2276
+ color: "#475467",
2277
+ cursor: "pointer"
2278
+ },
2279
+ navItemActive: {
2280
+ background: "#e6f7f9",
2281
+ color: "#049BAD",
2282
+ fontWeight: "600"
2283
+ },
2284
+ content: {
2285
+ flex: "1",
2286
+ minWidth: "0",
2287
+ display: "flex",
2288
+ flexDirection: "column",
2289
+ background: "#fff"
2290
+ },
2291
+ contentHeader: {
2292
+ display: "flex",
2293
+ alignItems: "center",
2294
+ justifyContent: "space-between",
2295
+ gap: "12px",
2296
+ padding: "12px 16px",
2297
+ borderBottom: "1px solid #f2f4f7"
2298
+ },
2299
+ breadcrumb: {
2300
+ display: "flex",
2301
+ alignItems: "center",
2302
+ gap: "8px",
2303
+ fontSize: "13px"
2304
+ },
2305
+ breadcrumbParent: { color: "#98a2b3" },
2306
+ breadcrumbSep: { color: "#d0d5dd" },
2307
+ breadcrumbCurrent: { color: "#344054", fontWeight: "600" },
2308
+ panel: {
2309
+ flex: "1",
2310
+ minHeight: "0",
2311
+ overflow: "auto"
2312
+ }
2313
+ };
2314
+ var SystemAdmin = (0, import_vue5.defineComponent)({
2315
+ name: "SystemAdmin",
2316
+ props: {
2317
+ menuApi: {
2318
+ type: Object,
2319
+ required: true
2320
+ },
2321
+ resourceApi: {
2322
+ type: Object,
2323
+ required: true
2324
+ },
2325
+ defaultActiveKey: {
2326
+ type: String,
2327
+ default: SYSTEM_ADMIN_DEFAULT_KEY
2328
+ },
2329
+ activeKey: {
2330
+ type: String,
2331
+ default: void 0
2332
+ },
2333
+ title: {
2334
+ type: String,
2335
+ default: SYSTEM_ADMIN_MENU.label
2336
+ }
2337
+ },
2338
+ emits: {
2339
+ "update:activeKey": (_key) => true,
2340
+ activeKeyChange: (_key) => true
2341
+ },
2342
+ setup(props, { emit, slots }) {
2343
+ const innerKey = (0, import_vue5.ref)(props.defaultActiveKey);
2344
+ (0, import_vue5.watch)(
2345
+ () => props.defaultActiveKey,
2346
+ (value) => {
2347
+ if (props.activeKey === void 0) innerKey.value = value;
2348
+ }
2349
+ );
2350
+ const activeKey = (0, import_vue5.computed)(
2351
+ () => props.activeKey ?? innerKey.value
2352
+ );
2353
+ const activeLabel = (0, import_vue5.computed)(
2354
+ () => SYSTEM_ADMIN_MENU.children.find((item) => item.key === activeKey.value)?.label ?? ""
2355
+ );
2356
+ function setActiveKey(key) {
2357
+ if (props.activeKey === void 0) innerKey.value = key;
2358
+ emit("update:activeKey", key);
2359
+ emit("activeKeyChange", key);
2360
+ }
2361
+ return () => (0, import_vue5.h)("div", { style: s3.root }, [
2362
+ (0, import_vue5.h)("aside", { style: s3.sidebar }, [
2363
+ (0, import_vue5.h)("div", { style: s3.sidebarTitle }, props.title),
2364
+ (0, import_vue5.h)(
2365
+ "nav",
2366
+ { style: s3.nav },
2367
+ SYSTEM_ADMIN_MENU.children.map((item) => {
2368
+ const active = item.key === activeKey.value;
2369
+ return (0, import_vue5.h)(
2370
+ "button",
2371
+ {
2372
+ key: item.key,
2373
+ type: "button",
2374
+ style: {
2375
+ ...s3.navItem,
2376
+ ...active ? s3.navItemActive : {}
2377
+ },
2378
+ onClick: () => setActiveKey(item.key)
2379
+ },
2380
+ item.label
2381
+ );
2382
+ })
2383
+ )
2384
+ ]),
2385
+ (0, import_vue5.h)("main", { style: s3.content }, [
2386
+ (0, import_vue5.h)("div", { style: s3.contentHeader }, [
2387
+ (0, import_vue5.h)("div", { style: s3.breadcrumb }, [
2388
+ (0, import_vue5.h)("span", { style: s3.breadcrumbParent }, props.title),
2389
+ (0, import_vue5.h)("span", { style: s3.breadcrumbSep }, "/"),
2390
+ (0, import_vue5.h)("span", { style: s3.breadcrumbCurrent }, activeLabel.value)
2391
+ ]),
2392
+ slots.toolbarExtra?.()
2393
+ ]),
2394
+ (0, import_vue5.h)("div", { style: s3.panel }, [
2395
+ activeKey.value === "menu" ? (0, import_vue5.h)(MenuManager, { api: props.menuApi, title: "\u83DC\u5355\u7BA1\u7406" }) : (0, import_vue5.h)(ResourceManager, {
2396
+ api: props.resourceApi,
2397
+ title: "\u6743\u9650\u70B9\u7BA1\u7406"
2398
+ })
2399
+ ])
2400
+ ])
2401
+ ]);
2402
+ }
2403
+ });
1290
2404
  // Annotate the CommonJS export names for ESM import in node:
1291
2405
  0 && (module.exports = {
1292
2406
  Can,
2407
+ MENU_LIST_TYPE_PARAM,
2408
+ MENU_TYPE_BUTTON,
2409
+ MENU_TYPE_LABEL,
2410
+ MENU_TYPE_MENU,
2411
+ MENU_TYPE_OPTIONS,
2412
+ MENU_TYPE_PAGE,
2413
+ MENU_VISIBILITY_OPTIONS,
2414
+ MenuManager,
1293
2415
  PERMISSION_STORE_KEY,
1294
2416
  PermissionStore,
1295
2417
  RESOURCE_PRIVATE_OPTIONS,
@@ -1297,12 +2419,19 @@ var ResourceManager = (0, import_vue3.defineComponent)({
1297
2419
  RESOURCE_STATUS_ENABLED,
1298
2420
  RESOURCE_STATUS_OPTIONS,
1299
2421
  RESOURCE_TYPE_API,
2422
+ ROOT_PARENT_ID,
1300
2423
  ResourceManager,
2424
+ SYSTEM_ADMIN_DEFAULT_KEY,
2425
+ SYSTEM_ADMIN_MENU,
2426
+ SystemAdmin,
1301
2427
  appendQueryParam,
1302
2428
  buildCreateBody,
2429
+ buildCreateMenuBody,
1303
2430
  buildUpdateBody,
2431
+ buildUpdateMenuBody,
1304
2432
  createAuthorizationResourceApi,
1305
2433
  createDefaultResourceRequest,
2434
+ createMenuResourceApi,
1306
2435
  createPermissionPlugin,
1307
2436
  createPermissionStore,
1308
2437
  createVPermission,
@@ -1311,6 +2440,7 @@ var ResourceManager = (0, import_vue3.defineComponent)({
1311
2440
  getAppClientId,
1312
2441
  getDeviceWorkerId,
1313
2442
  mapAuthorizationResource,
2443
+ mapMenuResource,
1314
2444
  snowyflake,
1315
2445
  useHasPermission,
1316
2446
  useHasRole,