com-angel-authorization 1.0.9 → 1.0.11

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.
@@ -228,6 +228,10 @@ type MenuResource = {
228
228
  * 菜单层级:无上级(根)为 1,其余为上级 depth + 1
229
229
  */
230
230
  depth: number;
231
+ /**
232
+ * 是否叶子节点:`1` 表示无下级菜单,不可再展开
233
+ */
234
+ leaf: number;
231
235
  type: MenuResourceType;
232
236
  name: string;
233
237
  identification: string;
@@ -252,6 +256,8 @@ type CreateMenuResourceBody = MenuResourceFormValues & {
252
256
  };
253
257
  type UpdateMenuResourceBody = Partial<MenuResourceFormValues>;
254
258
  type FetchMenuResourcesParams = {
259
+ /** 列表默认传 1,只拉根层 */
260
+ depth?: number;
255
261
  pagination?: ListPaginationParams;
256
262
  };
257
263
  type MenuResourceListResult = {
@@ -260,6 +266,9 @@ type MenuResourceListResult = {
260
266
  hasPreviousPage: boolean;
261
267
  hasNextPage: boolean;
262
268
  };
269
+ /** leaf === 1 表示无下级 */
270
+ declare const MENU_LEAF_YES = 1;
271
+ declare const MENU_LEAF_NO = 0;
263
272
  declare const RESOURCE_TYPE_API: ApiResourceType;
264
273
  declare const MENU_TYPE_PAGE: MenuResourceType;
265
274
  declare const MENU_TYPE_MENU: MenuResourceType;
@@ -313,6 +322,8 @@ type AuthorizationResourceApi = {
313
322
  };
314
323
  type MenuResourceApi = {
315
324
  list: (params?: FetchMenuResourcesParams, signal?: AbortSignal) => Promise<MenuResourceListResult>;
325
+ /** 展开下级:GET /authorization-resources/{resource-id}/sub-resources */
326
+ listSubResources: (resourceId: string, signal?: AbortSignal) => Promise<MenuResource[]>;
316
327
  /** 拉取权限点(type=api),供菜单表单多选 */
317
328
  listPermissionPoints: (params?: FetchAuthorizationResourcesParams, signal?: AbortSignal) => Promise<AuthorizationResourceListResult>;
318
329
  create: (values: MenuResourceFormValues, signal?: AbortSignal) => Promise<unknown>;
@@ -321,6 +332,10 @@ type MenuResourceApi = {
321
332
  };
322
333
  declare function mapAuthorizationResource(item: unknown): AuthorizationResource | null;
323
334
  declare function mapMenuResource(item: unknown): MenuResource | null;
335
+ /**
336
+ * leaf === 1 表示无下级菜单。
337
+ */
338
+ declare function isMenuLeaf(row: Pick<MenuResource, 'leaf'>): boolean;
324
339
  /**
325
340
  * 根据上级菜单计算 depth:无上级为 1,否则为上级 depth + 1。
326
341
  */
@@ -523,4 +538,4 @@ declare const snowyflake: ConfigurableSnowflake;
523
538
  declare function getAppClientId(): string;
524
539
  declare function getDeviceWorkerId(): string;
525
540
 
526
- export { type ApiResourceType, type AuthorizationResource, type AuthorizationResourceApi, type AuthorizationResourceFormValues, type AuthorizationResourceListResult, Can, type CheckOptions, type CreateAuthorizationResourceBody, type CreateDefaultResourceRequestOptions, type CreateMenuResourceBody, type FetchAuthorizationResourcesParams, type FetchMenuResourcesParams, type HttpMethod, type ListPaginationParams, type ListPaginationResult, MENU_LIST_TYPE_PARAM, MENU_TYPE_BUTTON, MENU_TYPE_LABEL, MENU_TYPE_MENU, MENU_TYPE_OPTIONS, MENU_TYPE_PAGE, MENU_VISIBILITY_OPTIONS, type MatchMode, MenuManager, type MenuResource, type MenuResourceApi, type MenuResourceFormValues, type MenuResourceListResult, type MenuResourceType, PERMISSION_STORE_KEY, type PageDirection, type PermissionChecker, type PermissionCode, type PermissionDirectiveValue, type PermissionListener, type PermissionPluginOptions, type PermissionState, PermissionStore, RESOURCE_PRIVATE_OPTIONS, RESOURCE_STATUS_DISABLED, RESOURCE_STATUS_ENABLED, RESOURCE_STATUS_OPTIONS, RESOURCE_TYPE_API, ROOT_MENU_DEPTH, ROOT_PARENT_ID, type ResourceHttpRequest, ResourceManager, type ResourceRequestOptions, type ResourceStatus, type ResourceType, type RoleCode, SYSTEM_ADMIN_DEFAULT_KEY, SYSTEM_ADMIN_MENU, SystemAdmin, type SystemAdminMenuGroup, type SystemAdminMenuKey, type SystemAdminSubMenu, type UpdateAuthorizationResourceBody, type UpdateMenuResourceBody, type UsePermissionResult, appendQueryParam, buildCreateBody, buildCreateMenuBody, buildUpdateBody, buildUpdateMenuBody, createAuthorizationResourceApi, createDefaultResourceRequest, createMenuResourceApi, createPermissionPlugin, createPermissionStore, createVPermission, extractPagination, extractRecords, getAppClientId, getDeviceWorkerId, mapAuthorizationResource, mapMenuResource, resolveMenuDepth, snowyflake, useHasPermission, useHasRole, usePermission };
541
+ export { type ApiResourceType, type AuthorizationResource, type AuthorizationResourceApi, type AuthorizationResourceFormValues, type AuthorizationResourceListResult, Can, type CheckOptions, type CreateAuthorizationResourceBody, type CreateDefaultResourceRequestOptions, type CreateMenuResourceBody, type FetchAuthorizationResourcesParams, type FetchMenuResourcesParams, type HttpMethod, type ListPaginationParams, type ListPaginationResult, MENU_LEAF_NO, MENU_LEAF_YES, MENU_LIST_TYPE_PARAM, MENU_TYPE_BUTTON, MENU_TYPE_LABEL, MENU_TYPE_MENU, MENU_TYPE_OPTIONS, MENU_TYPE_PAGE, MENU_VISIBILITY_OPTIONS, type MatchMode, MenuManager, type MenuResource, type MenuResourceApi, type MenuResourceFormValues, type MenuResourceListResult, type MenuResourceType, PERMISSION_STORE_KEY, type PageDirection, type PermissionChecker, type PermissionCode, type PermissionDirectiveValue, type PermissionListener, type PermissionPluginOptions, type PermissionState, PermissionStore, RESOURCE_PRIVATE_OPTIONS, RESOURCE_STATUS_DISABLED, RESOURCE_STATUS_ENABLED, RESOURCE_STATUS_OPTIONS, RESOURCE_TYPE_API, ROOT_MENU_DEPTH, ROOT_PARENT_ID, type ResourceHttpRequest, ResourceManager, type ResourceRequestOptions, type ResourceStatus, type ResourceType, type RoleCode, SYSTEM_ADMIN_DEFAULT_KEY, SYSTEM_ADMIN_MENU, SystemAdmin, type SystemAdminMenuGroup, type SystemAdminMenuKey, type SystemAdminSubMenu, type UpdateAuthorizationResourceBody, type UpdateMenuResourceBody, type UsePermissionResult, appendQueryParam, buildCreateBody, buildCreateMenuBody, buildUpdateBody, buildUpdateMenuBody, createAuthorizationResourceApi, createDefaultResourceRequest, createMenuResourceApi, createPermissionPlugin, createPermissionStore, createVPermission, extractPagination, extractRecords, getAppClientId, getDeviceWorkerId, isMenuLeaf, mapAuthorizationResource, mapMenuResource, resolveMenuDepth, snowyflake, useHasPermission, useHasRole, usePermission };
@@ -228,6 +228,10 @@ type MenuResource = {
228
228
  * 菜单层级:无上级(根)为 1,其余为上级 depth + 1
229
229
  */
230
230
  depth: number;
231
+ /**
232
+ * 是否叶子节点:`1` 表示无下级菜单,不可再展开
233
+ */
234
+ leaf: number;
231
235
  type: MenuResourceType;
232
236
  name: string;
233
237
  identification: string;
@@ -252,6 +256,8 @@ type CreateMenuResourceBody = MenuResourceFormValues & {
252
256
  };
253
257
  type UpdateMenuResourceBody = Partial<MenuResourceFormValues>;
254
258
  type FetchMenuResourcesParams = {
259
+ /** 列表默认传 1,只拉根层 */
260
+ depth?: number;
255
261
  pagination?: ListPaginationParams;
256
262
  };
257
263
  type MenuResourceListResult = {
@@ -260,6 +266,9 @@ type MenuResourceListResult = {
260
266
  hasPreviousPage: boolean;
261
267
  hasNextPage: boolean;
262
268
  };
269
+ /** leaf === 1 表示无下级 */
270
+ declare const MENU_LEAF_YES = 1;
271
+ declare const MENU_LEAF_NO = 0;
263
272
  declare const RESOURCE_TYPE_API: ApiResourceType;
264
273
  declare const MENU_TYPE_PAGE: MenuResourceType;
265
274
  declare const MENU_TYPE_MENU: MenuResourceType;
@@ -313,6 +322,8 @@ type AuthorizationResourceApi = {
313
322
  };
314
323
  type MenuResourceApi = {
315
324
  list: (params?: FetchMenuResourcesParams, signal?: AbortSignal) => Promise<MenuResourceListResult>;
325
+ /** 展开下级:GET /authorization-resources/{resource-id}/sub-resources */
326
+ listSubResources: (resourceId: string, signal?: AbortSignal) => Promise<MenuResource[]>;
316
327
  /** 拉取权限点(type=api),供菜单表单多选 */
317
328
  listPermissionPoints: (params?: FetchAuthorizationResourcesParams, signal?: AbortSignal) => Promise<AuthorizationResourceListResult>;
318
329
  create: (values: MenuResourceFormValues, signal?: AbortSignal) => Promise<unknown>;
@@ -321,6 +332,10 @@ type MenuResourceApi = {
321
332
  };
322
333
  declare function mapAuthorizationResource(item: unknown): AuthorizationResource | null;
323
334
  declare function mapMenuResource(item: unknown): MenuResource | null;
335
+ /**
336
+ * leaf === 1 表示无下级菜单。
337
+ */
338
+ declare function isMenuLeaf(row: Pick<MenuResource, 'leaf'>): boolean;
324
339
  /**
325
340
  * 根据上级菜单计算 depth:无上级为 1,否则为上级 depth + 1。
326
341
  */
@@ -523,4 +538,4 @@ declare const snowyflake: ConfigurableSnowflake;
523
538
  declare function getAppClientId(): string;
524
539
  declare function getDeviceWorkerId(): string;
525
540
 
526
- export { type ApiResourceType, type AuthorizationResource, type AuthorizationResourceApi, type AuthorizationResourceFormValues, type AuthorizationResourceListResult, Can, type CheckOptions, type CreateAuthorizationResourceBody, type CreateDefaultResourceRequestOptions, type CreateMenuResourceBody, type FetchAuthorizationResourcesParams, type FetchMenuResourcesParams, type HttpMethod, type ListPaginationParams, type ListPaginationResult, MENU_LIST_TYPE_PARAM, MENU_TYPE_BUTTON, MENU_TYPE_LABEL, MENU_TYPE_MENU, MENU_TYPE_OPTIONS, MENU_TYPE_PAGE, MENU_VISIBILITY_OPTIONS, type MatchMode, MenuManager, type MenuResource, type MenuResourceApi, type MenuResourceFormValues, type MenuResourceListResult, type MenuResourceType, PERMISSION_STORE_KEY, type PageDirection, type PermissionChecker, type PermissionCode, type PermissionDirectiveValue, type PermissionListener, type PermissionPluginOptions, type PermissionState, PermissionStore, RESOURCE_PRIVATE_OPTIONS, RESOURCE_STATUS_DISABLED, RESOURCE_STATUS_ENABLED, RESOURCE_STATUS_OPTIONS, RESOURCE_TYPE_API, ROOT_MENU_DEPTH, ROOT_PARENT_ID, type ResourceHttpRequest, ResourceManager, type ResourceRequestOptions, type ResourceStatus, type ResourceType, type RoleCode, SYSTEM_ADMIN_DEFAULT_KEY, SYSTEM_ADMIN_MENU, SystemAdmin, type SystemAdminMenuGroup, type SystemAdminMenuKey, type SystemAdminSubMenu, type UpdateAuthorizationResourceBody, type UpdateMenuResourceBody, type UsePermissionResult, appendQueryParam, buildCreateBody, buildCreateMenuBody, buildUpdateBody, buildUpdateMenuBody, createAuthorizationResourceApi, createDefaultResourceRequest, createMenuResourceApi, createPermissionPlugin, createPermissionStore, createVPermission, extractPagination, extractRecords, getAppClientId, getDeviceWorkerId, mapAuthorizationResource, mapMenuResource, resolveMenuDepth, snowyflake, useHasPermission, useHasRole, usePermission };
541
+ export { type ApiResourceType, type AuthorizationResource, type AuthorizationResourceApi, type AuthorizationResourceFormValues, type AuthorizationResourceListResult, Can, type CheckOptions, type CreateAuthorizationResourceBody, type CreateDefaultResourceRequestOptions, type CreateMenuResourceBody, type FetchAuthorizationResourcesParams, type FetchMenuResourcesParams, type HttpMethod, type ListPaginationParams, type ListPaginationResult, MENU_LEAF_NO, MENU_LEAF_YES, MENU_LIST_TYPE_PARAM, MENU_TYPE_BUTTON, MENU_TYPE_LABEL, MENU_TYPE_MENU, MENU_TYPE_OPTIONS, MENU_TYPE_PAGE, MENU_VISIBILITY_OPTIONS, type MatchMode, MenuManager, type MenuResource, type MenuResourceApi, type MenuResourceFormValues, type MenuResourceListResult, type MenuResourceType, PERMISSION_STORE_KEY, type PageDirection, type PermissionChecker, type PermissionCode, type PermissionDirectiveValue, type PermissionListener, type PermissionPluginOptions, type PermissionState, PermissionStore, RESOURCE_PRIVATE_OPTIONS, RESOURCE_STATUS_DISABLED, RESOURCE_STATUS_ENABLED, RESOURCE_STATUS_OPTIONS, RESOURCE_TYPE_API, ROOT_MENU_DEPTH, ROOT_PARENT_ID, type ResourceHttpRequest, ResourceManager, type ResourceRequestOptions, type ResourceStatus, type ResourceType, type RoleCode, SYSTEM_ADMIN_DEFAULT_KEY, SYSTEM_ADMIN_MENU, SystemAdmin, type SystemAdminMenuGroup, type SystemAdminMenuKey, type SystemAdminSubMenu, type UpdateAuthorizationResourceBody, type UpdateMenuResourceBody, type UsePermissionResult, appendQueryParam, buildCreateBody, buildCreateMenuBody, buildUpdateBody, buildUpdateMenuBody, createAuthorizationResourceApi, createDefaultResourceRequest, createMenuResourceApi, createPermissionPlugin, createPermissionStore, createVPermission, extractPagination, extractRecords, getAppClientId, getDeviceWorkerId, isMenuLeaf, mapAuthorizationResource, mapMenuResource, resolveMenuDepth, snowyflake, useHasPermission, useHasRole, usePermission };
package/dist/vue/index.js CHANGED
@@ -309,6 +309,8 @@ import {
309
309
  } from "vue";
310
310
 
311
311
  // src/resources/types.ts
312
+ var MENU_LEAF_YES = 1;
313
+ var MENU_LEAF_NO = 0;
312
314
  var RESOURCE_TYPE_API = "api";
313
315
  var MENU_TYPE_PAGE = "page";
314
316
  var MENU_TYPE_MENU = "menu";
@@ -537,10 +539,13 @@ function mapMenuResource(item) {
537
539
  const rawDepth = row.depth;
538
540
  const parsedDepth = Number(rawDepth);
539
541
  const depth = Number.isFinite(parsedDepth) && parsedDepth > 0 ? Math.floor(parsedDepth) : parentId ? ROOT_MENU_DEPTH + 1 : ROOT_MENU_DEPTH;
542
+ const rawLeaf = row.leaf;
543
+ const leaf = rawLeaf === true || rawLeaf === 1 || rawLeaf === "1" || String(rawLeaf).toLowerCase() === "true" ? MENU_LEAF_YES : Number(rawLeaf) === MENU_LEAF_YES ? MENU_LEAF_YES : 0;
540
544
  return {
541
545
  resourceId: String(resourceId),
542
546
  parentId,
543
547
  depth,
548
+ leaf,
544
549
  type: toMenuType(row.type),
545
550
  name: String(row.name ?? ""),
546
551
  identification: String(row.identification ?? row.identity ?? row.path ?? ""),
@@ -549,6 +554,9 @@ function mapMenuResource(item) {
549
554
  status: toResourceStatus(row.status)
550
555
  };
551
556
  }
557
+ function isMenuLeaf(row) {
558
+ return Number(row.leaf) === MENU_LEAF_YES;
559
+ }
552
560
  function resolveMenuDepth(parentId, menus) {
553
561
  if (!parentId) return ROOT_MENU_DEPTH;
554
562
  const parent = menus.find((item) => item.resourceId === parentId);
@@ -558,6 +566,9 @@ function resolveMenuDepth(parentId, menus) {
558
566
  function buildListUrl(type, params) {
559
567
  const parts = [];
560
568
  appendQueryParam(parts, "type", type);
569
+ if (params?.depth !== void 0 && params?.depth !== null && String(params.depth) !== "") {
570
+ appendQueryParam(parts, "depth", String(params.depth));
571
+ }
561
572
  appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
562
573
  appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
563
574
  appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
@@ -655,7 +666,10 @@ function createMenuResourceApi(request) {
655
666
  async list(params, signal) {
656
667
  const json = await request({
657
668
  method: "GET",
658
- url: buildListUrl(MENU_LIST_TYPE_PARAM, params),
669
+ url: buildListUrl(MENU_LIST_TYPE_PARAM, {
670
+ pagination: params?.pagination,
671
+ depth: params?.depth ?? ROOT_MENU_DEPTH
672
+ }),
659
673
  signal
660
674
  });
661
675
  const records = extractRecords(json).map(mapMenuResource).filter((item) => item !== null);
@@ -665,6 +679,14 @@ function createMenuResourceApi(request) {
665
679
  ...pagination
666
680
  };
667
681
  },
682
+ async listSubResources(resourceId, signal) {
683
+ const json = await request({
684
+ method: "GET",
685
+ url: `/authorization-resources/${encodeURIComponent(resourceId)}/sub-resources`,
686
+ signal
687
+ });
688
+ return extractRecords(json).map(mapMenuResource).filter((item) => item !== null);
689
+ },
668
690
  listPermissionPoints(params, signal) {
669
691
  return permissionApi.list(params, signal);
670
692
  },
@@ -1462,6 +1484,30 @@ var s2 = {
1462
1484
  borderBottom: "1px solid #f2f4f7",
1463
1485
  verticalAlign: "middle"
1464
1486
  },
1487
+ treeCell: {
1488
+ display: "flex",
1489
+ alignItems: "center",
1490
+ gap: "6px"
1491
+ },
1492
+ treeToggle: {
1493
+ width: "22px",
1494
+ height: "22px",
1495
+ border: "1px solid #d0d5dd",
1496
+ borderRadius: "4px",
1497
+ background: "#fff",
1498
+ color: "#475467",
1499
+ cursor: "pointer",
1500
+ fontSize: "10px",
1501
+ lineHeight: "20px",
1502
+ padding: "0",
1503
+ flexShrink: "0"
1504
+ },
1505
+ treeSpacer: {
1506
+ width: "22px",
1507
+ height: "22px",
1508
+ flexShrink: "0",
1509
+ display: "inline-block"
1510
+ },
1465
1511
  empty: {
1466
1512
  padding: "28px",
1467
1513
  textAlign: "center",
@@ -1598,7 +1644,9 @@ var s2 = {
1598
1644
  border: "none",
1599
1645
  display: "flex",
1600
1646
  flexDirection: "column",
1601
- gap: "8px"
1647
+ gap: "8px",
1648
+ backgroundColor: "transparent",
1649
+ color: "#101828"
1602
1650
  },
1603
1651
  label: { fontSize: "13px", color: "#344054", fontWeight: "500" },
1604
1652
  input: {
@@ -1612,14 +1660,29 @@ var s2 = {
1612
1660
  boxSizing: "border-box",
1613
1661
  width: "100%"
1614
1662
  },
1615
- radioGroup: { display: "flex", flexWrap: "wrap", gap: "16px" },
1663
+ control: {
1664
+ width: "16px",
1665
+ height: "16px",
1666
+ margin: "0",
1667
+ flexShrink: "0",
1668
+ accentColor: "#049BAD",
1669
+ backgroundColor: "#ffffff",
1670
+ colorScheme: "light"
1671
+ },
1672
+ radioGroup: {
1673
+ display: "flex",
1674
+ flexWrap: "wrap",
1675
+ gap: "16px",
1676
+ backgroundColor: "transparent"
1677
+ },
1616
1678
  radioItem: {
1617
1679
  display: "flex",
1618
1680
  alignItems: "center",
1619
1681
  gap: "6px",
1620
1682
  fontSize: "14px",
1621
1683
  color: "#344054",
1622
- cursor: "pointer"
1684
+ cursor: "pointer",
1685
+ backgroundColor: "transparent"
1623
1686
  },
1624
1687
  multiSelect: {
1625
1688
  maxHeight: "160px",
@@ -1627,7 +1690,8 @@ var s2 = {
1627
1690
  border: "1px solid #eaecf0",
1628
1691
  borderRadius: "8px",
1629
1692
  padding: "8px",
1630
- background: "#f9fafb"
1693
+ backgroundColor: "#ffffff",
1694
+ color: "#101828"
1631
1695
  },
1632
1696
  checkItem: {
1633
1697
  display: "flex",
@@ -1636,7 +1700,8 @@ var s2 = {
1636
1700
  padding: "6px 4px",
1637
1701
  fontSize: "13px",
1638
1702
  color: "#344054",
1639
- cursor: "pointer"
1703
+ cursor: "pointer",
1704
+ backgroundColor: "transparent"
1640
1705
  },
1641
1706
  hint: { fontSize: "13px", color: "#98a2b3", padding: "8px" },
1642
1707
  dialogFooter: {
@@ -1664,6 +1729,9 @@ var MenuManager = defineComponent3({
1664
1729
  },
1665
1730
  setup(props, { slots }) {
1666
1731
  const records = ref2([]);
1732
+ const childrenMap = ref2({});
1733
+ const expandedIds = ref2({});
1734
+ const expandingIds = ref2({});
1667
1735
  const permissionPoints = ref2([]);
1668
1736
  const loading = ref2(false);
1669
1737
  const error = ref2("");
@@ -1684,17 +1752,39 @@ var MenuManager = defineComponent3({
1684
1752
  );
1685
1753
  return map;
1686
1754
  });
1755
+ const allKnownMenus = computed3(() => {
1756
+ const map = /* @__PURE__ */ new Map();
1757
+ records.value.forEach((row) => map.set(row.resourceId, row));
1758
+ Object.values(childrenMap.value).forEach((list) => {
1759
+ list.forEach((row) => map.set(row.resourceId, row));
1760
+ });
1761
+ return Array.from(map.values());
1762
+ });
1687
1763
  const parentOptions = computed3(
1688
- () => records.value.filter((row) => !editing.value || row.resourceId !== editing.value.resourceId).map((row) => ({
1764
+ () => allKnownMenus.value.filter((row) => !editing.value || row.resourceId !== editing.value.resourceId).map((row) => ({
1689
1765
  value: row.resourceId,
1690
1766
  label: `${row.name}\uFF08${MENU_TYPE_LABEL[row.type]}\uFF09`
1691
1767
  }))
1692
1768
  );
1769
+ const flatRows = computed3(() => {
1770
+ const rows = [];
1771
+ const walk = (list) => {
1772
+ list.forEach((row) => {
1773
+ rows.push(row);
1774
+ if (expandedIds.value[row.resourceId] && childrenMap.value[row.resourceId]?.length) {
1775
+ walk(childrenMap.value[row.resourceId]);
1776
+ }
1777
+ });
1778
+ };
1779
+ walk(records.value);
1780
+ return rows;
1781
+ });
1693
1782
  async function loadList(direction = "current", token = pageToken.value) {
1694
1783
  loading.value = true;
1695
1784
  error.value = "";
1696
1785
  try {
1697
1786
  const result = await props.api.list({
1787
+ depth: ROOT_MENU_DEPTH,
1698
1788
  pagination: {
1699
1789
  pageToken: token,
1700
1790
  pageSize: pageSize.value,
@@ -1702,6 +1792,9 @@ var MenuManager = defineComponent3({
1702
1792
  }
1703
1793
  });
1704
1794
  records.value = result.records;
1795
+ childrenMap.value = {};
1796
+ expandedIds.value = {};
1797
+ expandingIds.value = {};
1705
1798
  pageToken.value = result.pageToken;
1706
1799
  hasPreviousPage.value = result.hasPreviousPage;
1707
1800
  hasNextPage.value = result.hasNextPage;
@@ -1720,6 +1813,29 @@ var MenuManager = defineComponent3({
1720
1813
  } catch {
1721
1814
  }
1722
1815
  }
1816
+ async function toggleExpand(row) {
1817
+ if (isMenuLeaf(row)) return;
1818
+ const id = row.resourceId;
1819
+ if (expandedIds.value[id]) {
1820
+ expandedIds.value = { ...expandedIds.value, [id]: false };
1821
+ return;
1822
+ }
1823
+ if (!childrenMap.value[id]) {
1824
+ expandingIds.value = { ...expandingIds.value, [id]: true };
1825
+ error.value = "";
1826
+ try {
1827
+ const children = await props.api.listSubResources(id);
1828
+ childrenMap.value = { ...childrenMap.value, [id]: children };
1829
+ expandedIds.value = { ...expandedIds.value, [id]: true };
1830
+ } catch (err) {
1831
+ error.value = err instanceof Error ? err.message : "\u52A0\u8F7D\u4E0B\u7EA7\u83DC\u5355\u5931\u8D25";
1832
+ } finally {
1833
+ expandingIds.value = { ...expandingIds.value, [id]: false };
1834
+ }
1835
+ return;
1836
+ }
1837
+ expandedIds.value = { ...expandedIds.value, [id]: true };
1838
+ }
1723
1839
  function openCreate() {
1724
1840
  editing.value = null;
1725
1841
  Object.assign(form, emptyForm2());
@@ -1730,7 +1846,7 @@ var MenuManager = defineComponent3({
1730
1846
  editing.value = row;
1731
1847
  Object.assign(form, {
1732
1848
  parentId: row.parentId ?? null,
1733
- depth: resolveMenuDepth(row.parentId ?? null, records.value),
1849
+ depth: resolveMenuDepth(row.parentId ?? null, allKnownMenus.value),
1734
1850
  type: row.type,
1735
1851
  name: row.name,
1736
1852
  identification: row.identification,
@@ -1838,13 +1954,41 @@ var MenuManager = defineComponent3({
1838
1954
  h2("tr", [
1839
1955
  h2("td", { colspan: 6, style: s2.empty }, "\u52A0\u8F7D\u4E2D\u2026")
1840
1956
  ])
1841
- ] : records.value.length === 0 ? [
1957
+ ] : flatRows.value.length === 0 ? [
1842
1958
  h2("tr", [
1843
1959
  h2("td", { colspan: 6, style: s2.empty }, "\u6682\u65E0\u6570\u636E")
1844
1960
  ])
1845
- ] : records.value.map(
1846
- (row) => h2("tr", { key: row.resourceId }, [
1847
- h2("td", { style: s2.td }, row.name),
1961
+ ] : flatRows.value.map((row) => {
1962
+ const leaf = isMenuLeaf(row);
1963
+ const expanded = Boolean(expandedIds.value[row.resourceId]);
1964
+ const expanding = Boolean(expandingIds.value[row.resourceId]);
1965
+ const indent = Math.max(0, (row.depth || 1) - 1) * 18;
1966
+ return h2("tr", { key: row.resourceId }, [
1967
+ h2("td", { style: s2.td }, [
1968
+ h2(
1969
+ "div",
1970
+ {
1971
+ style: {
1972
+ ...s2.treeCell,
1973
+ paddingLeft: `${indent}px`
1974
+ }
1975
+ },
1976
+ [
1977
+ leaf ? h2("span", { style: s2.treeSpacer }) : h2(
1978
+ "button",
1979
+ {
1980
+ type: "button",
1981
+ style: s2.treeToggle,
1982
+ disabled: expanding,
1983
+ "aria-label": expanded ? "\u6536\u8D77" : "\u5C55\u5F00",
1984
+ onClick: () => void toggleExpand(row)
1985
+ },
1986
+ expanding ? "\u2026" : expanded ? "\u25BC" : "\u25B6"
1987
+ ),
1988
+ h2("span", row.name)
1989
+ ]
1990
+ )
1991
+ ]),
1848
1992
  h2("td", { style: s2.td }, [
1849
1993
  h2(
1850
1994
  "code",
@@ -1887,8 +2031,8 @@ var MenuManager = defineComponent3({
1887
2031
  "\u5220\u9664"
1888
2032
  )
1889
2033
  ])
1890
- ])
1891
- )
2034
+ ]);
2035
+ })
1892
2036
  )
1893
2037
  ])
1894
2038
  ]),
@@ -1980,7 +2124,7 @@ var MenuManager = defineComponent3({
1980
2124
  const value = e.target.value;
1981
2125
  const parentId = value ? value : null;
1982
2126
  form.parentId = parentId;
1983
- form.depth = resolveMenuDepth(parentId, records.value);
2127
+ form.depth = resolveMenuDepth(parentId, allKnownMenus.value);
1984
2128
  }
1985
2129
  },
1986
2130
  [
@@ -1995,14 +2139,6 @@ var MenuManager = defineComponent3({
1995
2139
  ]
1996
2140
  )
1997
2141
  ]),
1998
- h2("div", { style: s2.field }, [
1999
- h2("span", { style: s2.label }, "\u83DC\u5355\u5C42\u7EA7\uFF08depth\uFF09"),
2000
- h2("input", {
2001
- style: s2.input,
2002
- value: form.depth,
2003
- readOnly: true
2004
- })
2005
- ]),
2006
2142
  h2("fieldset", { style: s2.fieldset }, [
2007
2143
  h2("legend", { style: s2.label }, "\u83DC\u5355\u7C7B\u578B"),
2008
2144
  h2(
@@ -2013,6 +2149,7 @@ var MenuManager = defineComponent3({
2013
2149
  h2("input", {
2014
2150
  type: "radio",
2015
2151
  name: "menu-type",
2152
+ style: s2.control,
2016
2153
  checked: form.type === opt.value,
2017
2154
  onChange: () => {
2018
2155
  form.type = opt.value;
@@ -2064,6 +2201,7 @@ var MenuManager = defineComponent3({
2064
2201
  [
2065
2202
  h2("input", {
2066
2203
  type: "checkbox",
2204
+ style: s2.control,
2067
2205
  checked: form.permissionPointIds.includes(
2068
2206
  p.resourceId
2069
2207
  ),
@@ -2097,6 +2235,7 @@ var MenuManager = defineComponent3({
2097
2235
  h2("input", {
2098
2236
  type: "radio",
2099
2237
  name: "menu-status",
2238
+ style: s2.control,
2100
2239
  checked: form.status === opt.value,
2101
2240
  onChange: () => {
2102
2241
  form.status = opt.value;
@@ -2385,6 +2524,8 @@ var SystemAdmin = defineComponent4({
2385
2524
  });
2386
2525
  export {
2387
2526
  Can,
2527
+ MENU_LEAF_NO,
2528
+ MENU_LEAF_YES,
2388
2529
  MENU_LIST_TYPE_PARAM,
2389
2530
  MENU_TYPE_BUTTON,
2390
2531
  MENU_TYPE_LABEL,
@@ -2421,6 +2562,7 @@ export {
2421
2562
  extractRecords,
2422
2563
  getAppClientId,
2423
2564
  getDeviceWorkerId,
2565
+ isMenuLeaf,
2424
2566
  mapAuthorizationResource,
2425
2567
  mapMenuResource,
2426
2568
  resolveMenuDepth,