com-angel-authorization 1.0.8 → 1.0.10

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.
@@ -224,6 +224,14 @@ type MenuResource = {
224
224
  resourceId: string;
225
225
  /** 上级菜单 ID;无上级时为 null */
226
226
  parentId: string | null;
227
+ /**
228
+ * 菜单层级:无上级(根)为 1,其余为上级 depth + 1
229
+ */
230
+ depth: number;
231
+ /**
232
+ * 是否叶子节点:`1` 表示无下级菜单,不可再展开
233
+ */
234
+ leaf: number;
227
235
  type: MenuResourceType;
228
236
  name: string;
229
237
  identification: string;
@@ -235,6 +243,8 @@ type MenuResource = {
235
243
  type MenuResourceFormValues = {
236
244
  /** 上级菜单 ID;选择「无」时为 null */
237
245
  parentId: string | null;
246
+ /** 由 parentId 自动计算:无为 1,否则上级 depth + 1 */
247
+ depth: number;
238
248
  type: MenuResourceType;
239
249
  name: string;
240
250
  identification: string;
@@ -246,6 +256,8 @@ type CreateMenuResourceBody = MenuResourceFormValues & {
246
256
  };
247
257
  type UpdateMenuResourceBody = Partial<MenuResourceFormValues>;
248
258
  type FetchMenuResourcesParams = {
259
+ /** 列表默认传 1,只拉根层 */
260
+ depth?: number;
249
261
  pagination?: ListPaginationParams;
250
262
  };
251
263
  type MenuResourceListResult = {
@@ -254,6 +266,9 @@ type MenuResourceListResult = {
254
266
  hasPreviousPage: boolean;
255
267
  hasNextPage: boolean;
256
268
  };
269
+ /** leaf === 1 表示无下级 */
270
+ declare const MENU_LEAF_YES = 1;
271
+ declare const MENU_LEAF_NO = 0;
257
272
  declare const RESOURCE_TYPE_API: ApiResourceType;
258
273
  declare const MENU_TYPE_PAGE: MenuResourceType;
259
274
  declare const MENU_TYPE_MENU: MenuResourceType;
@@ -265,6 +280,8 @@ declare const MENU_LIST_TYPE_PARAM = "page,menu,button";
265
280
  * 提交接口时会转换为 parentId: null。
266
281
  */
267
282
  declare const ROOT_PARENT_ID = "";
283
+ /** 无上级时的菜单层级 */
284
+ declare const ROOT_MENU_DEPTH = 1;
268
285
  declare const RESOURCE_STATUS_ENABLED: ResourceStatus;
269
286
  declare const RESOURCE_STATUS_DISABLED: ResourceStatus;
270
287
  declare const RESOURCE_STATUS_OPTIONS: {
@@ -305,6 +322,8 @@ type AuthorizationResourceApi = {
305
322
  };
306
323
  type MenuResourceApi = {
307
324
  list: (params?: FetchMenuResourcesParams, signal?: AbortSignal) => Promise<MenuResourceListResult>;
325
+ /** 展开下级:GET /authorization-resources/{resource-id}/sub-resources */
326
+ listSubResources: (resourceId: string, signal?: AbortSignal) => Promise<MenuResource[]>;
308
327
  /** 拉取权限点(type=api),供菜单表单多选 */
309
328
  listPermissionPoints: (params?: FetchAuthorizationResourcesParams, signal?: AbortSignal) => Promise<AuthorizationResourceListResult>;
310
329
  create: (values: MenuResourceFormValues, signal?: AbortSignal) => Promise<unknown>;
@@ -313,6 +332,14 @@ type MenuResourceApi = {
313
332
  };
314
333
  declare function mapAuthorizationResource(item: unknown): AuthorizationResource | null;
315
334
  declare function mapMenuResource(item: unknown): MenuResource | null;
335
+ /**
336
+ * leaf === 1 表示无下级菜单。
337
+ */
338
+ declare function isMenuLeaf(row: Pick<MenuResource, 'leaf'>): boolean;
339
+ /**
340
+ * 根据上级菜单计算 depth:无上级为 1,否则为上级 depth + 1。
341
+ */
342
+ declare function resolveMenuDepth(parentId: string | null | undefined, menus: Array<Pick<MenuResource, 'resourceId' | 'depth'>>): number;
316
343
  declare function buildCreateBody(values: AuthorizationResourceFormValues, resourceId?: string): CreateAuthorizationResourceBody;
317
344
  declare function buildUpdateBody(values: AuthorizationResourceFormValues): UpdateAuthorizationResourceBody;
318
345
  declare function buildCreateMenuBody(values: MenuResourceFormValues, resourceId?: string): CreateMenuResourceBody;
@@ -511,4 +538,4 @@ declare const snowyflake: ConfigurableSnowflake;
511
538
  declare function getAppClientId(): string;
512
539
  declare function getDeviceWorkerId(): string;
513
540
 
514
- 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_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, 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 };
@@ -224,6 +224,14 @@ type MenuResource = {
224
224
  resourceId: string;
225
225
  /** 上级菜单 ID;无上级时为 null */
226
226
  parentId: string | null;
227
+ /**
228
+ * 菜单层级:无上级(根)为 1,其余为上级 depth + 1
229
+ */
230
+ depth: number;
231
+ /**
232
+ * 是否叶子节点:`1` 表示无下级菜单,不可再展开
233
+ */
234
+ leaf: number;
227
235
  type: MenuResourceType;
228
236
  name: string;
229
237
  identification: string;
@@ -235,6 +243,8 @@ type MenuResource = {
235
243
  type MenuResourceFormValues = {
236
244
  /** 上级菜单 ID;选择「无」时为 null */
237
245
  parentId: string | null;
246
+ /** 由 parentId 自动计算:无为 1,否则上级 depth + 1 */
247
+ depth: number;
238
248
  type: MenuResourceType;
239
249
  name: string;
240
250
  identification: string;
@@ -246,6 +256,8 @@ type CreateMenuResourceBody = MenuResourceFormValues & {
246
256
  };
247
257
  type UpdateMenuResourceBody = Partial<MenuResourceFormValues>;
248
258
  type FetchMenuResourcesParams = {
259
+ /** 列表默认传 1,只拉根层 */
260
+ depth?: number;
249
261
  pagination?: ListPaginationParams;
250
262
  };
251
263
  type MenuResourceListResult = {
@@ -254,6 +266,9 @@ type MenuResourceListResult = {
254
266
  hasPreviousPage: boolean;
255
267
  hasNextPage: boolean;
256
268
  };
269
+ /** leaf === 1 表示无下级 */
270
+ declare const MENU_LEAF_YES = 1;
271
+ declare const MENU_LEAF_NO = 0;
257
272
  declare const RESOURCE_TYPE_API: ApiResourceType;
258
273
  declare const MENU_TYPE_PAGE: MenuResourceType;
259
274
  declare const MENU_TYPE_MENU: MenuResourceType;
@@ -265,6 +280,8 @@ declare const MENU_LIST_TYPE_PARAM = "page,menu,button";
265
280
  * 提交接口时会转换为 parentId: null。
266
281
  */
267
282
  declare const ROOT_PARENT_ID = "";
283
+ /** 无上级时的菜单层级 */
284
+ declare const ROOT_MENU_DEPTH = 1;
268
285
  declare const RESOURCE_STATUS_ENABLED: ResourceStatus;
269
286
  declare const RESOURCE_STATUS_DISABLED: ResourceStatus;
270
287
  declare const RESOURCE_STATUS_OPTIONS: {
@@ -305,6 +322,8 @@ type AuthorizationResourceApi = {
305
322
  };
306
323
  type MenuResourceApi = {
307
324
  list: (params?: FetchMenuResourcesParams, signal?: AbortSignal) => Promise<MenuResourceListResult>;
325
+ /** 展开下级:GET /authorization-resources/{resource-id}/sub-resources */
326
+ listSubResources: (resourceId: string, signal?: AbortSignal) => Promise<MenuResource[]>;
308
327
  /** 拉取权限点(type=api),供菜单表单多选 */
309
328
  listPermissionPoints: (params?: FetchAuthorizationResourcesParams, signal?: AbortSignal) => Promise<AuthorizationResourceListResult>;
310
329
  create: (values: MenuResourceFormValues, signal?: AbortSignal) => Promise<unknown>;
@@ -313,6 +332,14 @@ type MenuResourceApi = {
313
332
  };
314
333
  declare function mapAuthorizationResource(item: unknown): AuthorizationResource | null;
315
334
  declare function mapMenuResource(item: unknown): MenuResource | null;
335
+ /**
336
+ * leaf === 1 表示无下级菜单。
337
+ */
338
+ declare function isMenuLeaf(row: Pick<MenuResource, 'leaf'>): boolean;
339
+ /**
340
+ * 根据上级菜单计算 depth:无上级为 1,否则为上级 depth + 1。
341
+ */
342
+ declare function resolveMenuDepth(parentId: string | null | undefined, menus: Array<Pick<MenuResource, 'resourceId' | 'depth'>>): number;
316
343
  declare function buildCreateBody(values: AuthorizationResourceFormValues, resourceId?: string): CreateAuthorizationResourceBody;
317
344
  declare function buildUpdateBody(values: AuthorizationResourceFormValues): UpdateAuthorizationResourceBody;
318
345
  declare function buildCreateMenuBody(values: MenuResourceFormValues, resourceId?: string): CreateMenuResourceBody;
@@ -511,4 +538,4 @@ declare const snowyflake: ConfigurableSnowflake;
511
538
  declare function getAppClientId(): string;
512
539
  declare function getDeviceWorkerId(): string;
513
540
 
514
- 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_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, 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,12 +309,15 @@ 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";
315
317
  var MENU_TYPE_BUTTON = "button";
316
318
  var MENU_LIST_TYPE_PARAM = "page,menu,button";
317
319
  var ROOT_PARENT_ID = "";
320
+ var ROOT_MENU_DEPTH = 1;
318
321
  var RESOURCE_STATUS_ENABLED = 1;
319
322
  var RESOURCE_STATUS_DISABLED = 0;
320
323
  var RESOURCE_STATUS_OPTIONS = [
@@ -533,9 +536,16 @@ function mapMenuResource(item) {
533
536
  const permissionPointNames = Array.isArray(permissionNamesRaw) ? permissionNamesRaw.map((n) => String(n ?? "")).filter(Boolean) : void 0;
534
537
  const rawParentId = row.parentId ?? row.parent_id;
535
538
  const parentId = rawParentId === void 0 || rawParentId === null || rawParentId === "" || String(rawParentId) === "0" ? null : String(rawParentId);
539
+ const rawDepth = row.depth;
540
+ const parsedDepth = Number(rawDepth);
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;
536
544
  return {
537
545
  resourceId: String(resourceId),
538
546
  parentId,
547
+ depth,
548
+ leaf,
539
549
  type: toMenuType(row.type),
540
550
  name: String(row.name ?? ""),
541
551
  identification: String(row.identification ?? row.identity ?? row.path ?? ""),
@@ -544,9 +554,21 @@ function mapMenuResource(item) {
544
554
  status: toResourceStatus(row.status)
545
555
  };
546
556
  }
557
+ function isMenuLeaf(row) {
558
+ return Number(row.leaf) === MENU_LEAF_YES;
559
+ }
560
+ function resolveMenuDepth(parentId, menus) {
561
+ if (!parentId) return ROOT_MENU_DEPTH;
562
+ const parent = menus.find((item) => item.resourceId === parentId);
563
+ const parentDepth = parent && Number.isFinite(parent.depth) && parent.depth > 0 ? Math.floor(parent.depth) : ROOT_MENU_DEPTH;
564
+ return parentDepth + 1;
565
+ }
547
566
  function buildListUrl(type, params) {
548
567
  const parts = [];
549
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
+ }
550
572
  appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
551
573
  appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
552
574
  appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
@@ -574,9 +596,11 @@ function buildUpdateBody(values) {
574
596
  };
575
597
  }
576
598
  function buildCreateMenuBody(values, resourceId = getAppClientId()) {
599
+ const parentId = values.parentId ? values.parentId : null;
577
600
  return {
578
601
  resourceId,
579
- parentId: values.parentId ? values.parentId : null,
602
+ parentId,
603
+ depth: values.depth > 0 ? Math.floor(values.depth) : parentId ? ROOT_MENU_DEPTH + 1 : ROOT_MENU_DEPTH,
580
604
  type: values.type,
581
605
  name: values.name.trim(),
582
606
  identification: values.identification.trim(),
@@ -585,8 +609,10 @@ function buildCreateMenuBody(values, resourceId = getAppClientId()) {
585
609
  };
586
610
  }
587
611
  function buildUpdateMenuBody(values) {
612
+ const parentId = values.parentId ? values.parentId : null;
588
613
  return {
589
- parentId: values.parentId ? values.parentId : null,
614
+ parentId,
615
+ depth: values.depth > 0 ? Math.floor(values.depth) : parentId ? ROOT_MENU_DEPTH + 1 : ROOT_MENU_DEPTH,
590
616
  type: values.type,
591
617
  name: values.name.trim(),
592
618
  identification: values.identification.trim(),
@@ -640,7 +666,10 @@ function createMenuResourceApi(request) {
640
666
  async list(params, signal) {
641
667
  const json = await request({
642
668
  method: "GET",
643
- 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
+ }),
644
673
  signal
645
674
  });
646
675
  const records = extractRecords(json).map(mapMenuResource).filter((item) => item !== null);
@@ -650,6 +679,14 @@ function createMenuResourceApi(request) {
650
679
  ...pagination
651
680
  };
652
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
+ },
653
690
  listPermissionPoints(params, signal) {
654
691
  return permissionApi.list(params, signal);
655
692
  },
@@ -1393,6 +1430,7 @@ var PAGE_SIZE_OPTIONS2 = ["10", "20", "50", "100"];
1393
1430
  function emptyForm2() {
1394
1431
  return {
1395
1432
  parentId: null,
1433
+ depth: ROOT_MENU_DEPTH,
1396
1434
  type: MENU_TYPE_MENU,
1397
1435
  name: "",
1398
1436
  identification: "",
@@ -1446,6 +1484,30 @@ var s2 = {
1446
1484
  borderBottom: "1px solid #f2f4f7",
1447
1485
  verticalAlign: "middle"
1448
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
+ },
1449
1511
  empty: {
1450
1512
  padding: "28px",
1451
1513
  textAlign: "center",
@@ -1648,6 +1710,9 @@ var MenuManager = defineComponent3({
1648
1710
  },
1649
1711
  setup(props, { slots }) {
1650
1712
  const records = ref2([]);
1713
+ const childrenMap = ref2({});
1714
+ const expandedIds = ref2({});
1715
+ const expandingIds = ref2({});
1651
1716
  const permissionPoints = ref2([]);
1652
1717
  const loading = ref2(false);
1653
1718
  const error = ref2("");
@@ -1668,17 +1733,39 @@ var MenuManager = defineComponent3({
1668
1733
  );
1669
1734
  return map;
1670
1735
  });
1736
+ const allKnownMenus = computed3(() => {
1737
+ const map = /* @__PURE__ */ new Map();
1738
+ records.value.forEach((row) => map.set(row.resourceId, row));
1739
+ Object.values(childrenMap.value).forEach((list) => {
1740
+ list.forEach((row) => map.set(row.resourceId, row));
1741
+ });
1742
+ return Array.from(map.values());
1743
+ });
1671
1744
  const parentOptions = computed3(
1672
- () => records.value.filter((row) => !editing.value || row.resourceId !== editing.value.resourceId).map((row) => ({
1745
+ () => allKnownMenus.value.filter((row) => !editing.value || row.resourceId !== editing.value.resourceId).map((row) => ({
1673
1746
  value: row.resourceId,
1674
1747
  label: `${row.name}\uFF08${MENU_TYPE_LABEL[row.type]}\uFF09`
1675
1748
  }))
1676
1749
  );
1750
+ const flatRows = computed3(() => {
1751
+ const rows = [];
1752
+ const walk = (list) => {
1753
+ list.forEach((row) => {
1754
+ rows.push(row);
1755
+ if (expandedIds.value[row.resourceId] && childrenMap.value[row.resourceId]?.length) {
1756
+ walk(childrenMap.value[row.resourceId]);
1757
+ }
1758
+ });
1759
+ };
1760
+ walk(records.value);
1761
+ return rows;
1762
+ });
1677
1763
  async function loadList(direction = "current", token = pageToken.value) {
1678
1764
  loading.value = true;
1679
1765
  error.value = "";
1680
1766
  try {
1681
1767
  const result = await props.api.list({
1768
+ depth: ROOT_MENU_DEPTH,
1682
1769
  pagination: {
1683
1770
  pageToken: token,
1684
1771
  pageSize: pageSize.value,
@@ -1686,6 +1773,9 @@ var MenuManager = defineComponent3({
1686
1773
  }
1687
1774
  });
1688
1775
  records.value = result.records;
1776
+ childrenMap.value = {};
1777
+ expandedIds.value = {};
1778
+ expandingIds.value = {};
1689
1779
  pageToken.value = result.pageToken;
1690
1780
  hasPreviousPage.value = result.hasPreviousPage;
1691
1781
  hasNextPage.value = result.hasNextPage;
@@ -1704,6 +1794,29 @@ var MenuManager = defineComponent3({
1704
1794
  } catch {
1705
1795
  }
1706
1796
  }
1797
+ async function toggleExpand(row) {
1798
+ if (isMenuLeaf(row)) return;
1799
+ const id = row.resourceId;
1800
+ if (expandedIds.value[id]) {
1801
+ expandedIds.value = { ...expandedIds.value, [id]: false };
1802
+ return;
1803
+ }
1804
+ if (!childrenMap.value[id]) {
1805
+ expandingIds.value = { ...expandingIds.value, [id]: true };
1806
+ error.value = "";
1807
+ try {
1808
+ const children = await props.api.listSubResources(id);
1809
+ childrenMap.value = { ...childrenMap.value, [id]: children };
1810
+ expandedIds.value = { ...expandedIds.value, [id]: true };
1811
+ } catch (err) {
1812
+ error.value = err instanceof Error ? err.message : "\u52A0\u8F7D\u4E0B\u7EA7\u83DC\u5355\u5931\u8D25";
1813
+ } finally {
1814
+ expandingIds.value = { ...expandingIds.value, [id]: false };
1815
+ }
1816
+ return;
1817
+ }
1818
+ expandedIds.value = { ...expandedIds.value, [id]: true };
1819
+ }
1707
1820
  function openCreate() {
1708
1821
  editing.value = null;
1709
1822
  Object.assign(form, emptyForm2());
@@ -1714,6 +1827,7 @@ var MenuManager = defineComponent3({
1714
1827
  editing.value = row;
1715
1828
  Object.assign(form, {
1716
1829
  parentId: row.parentId ?? null,
1830
+ depth: resolveMenuDepth(row.parentId ?? null, allKnownMenus.value),
1717
1831
  type: row.type,
1718
1832
  name: row.name,
1719
1833
  identification: row.identification,
@@ -1821,13 +1935,41 @@ var MenuManager = defineComponent3({
1821
1935
  h2("tr", [
1822
1936
  h2("td", { colspan: 6, style: s2.empty }, "\u52A0\u8F7D\u4E2D\u2026")
1823
1937
  ])
1824
- ] : records.value.length === 0 ? [
1938
+ ] : flatRows.value.length === 0 ? [
1825
1939
  h2("tr", [
1826
1940
  h2("td", { colspan: 6, style: s2.empty }, "\u6682\u65E0\u6570\u636E")
1827
1941
  ])
1828
- ] : records.value.map(
1829
- (row) => h2("tr", { key: row.resourceId }, [
1830
- h2("td", { style: s2.td }, row.name),
1942
+ ] : flatRows.value.map((row) => {
1943
+ const leaf = isMenuLeaf(row);
1944
+ const expanded = Boolean(expandedIds.value[row.resourceId]);
1945
+ const expanding = Boolean(expandingIds.value[row.resourceId]);
1946
+ const indent = Math.max(0, (row.depth || 1) - 1) * 18;
1947
+ return h2("tr", { key: row.resourceId }, [
1948
+ h2("td", { style: s2.td }, [
1949
+ h2(
1950
+ "div",
1951
+ {
1952
+ style: {
1953
+ ...s2.treeCell,
1954
+ paddingLeft: `${indent}px`
1955
+ }
1956
+ },
1957
+ [
1958
+ leaf ? h2("span", { style: s2.treeSpacer }) : h2(
1959
+ "button",
1960
+ {
1961
+ type: "button",
1962
+ style: s2.treeToggle,
1963
+ disabled: expanding,
1964
+ "aria-label": expanded ? "\u6536\u8D77" : "\u5C55\u5F00",
1965
+ onClick: () => void toggleExpand(row)
1966
+ },
1967
+ expanding ? "\u2026" : expanded ? "\u25BC" : "\u25B6"
1968
+ ),
1969
+ h2("span", row.name)
1970
+ ]
1971
+ )
1972
+ ]),
1831
1973
  h2("td", { style: s2.td }, [
1832
1974
  h2(
1833
1975
  "code",
@@ -1870,8 +2012,8 @@ var MenuManager = defineComponent3({
1870
2012
  "\u5220\u9664"
1871
2013
  )
1872
2014
  ])
1873
- ])
1874
- )
2015
+ ]);
2016
+ })
1875
2017
  )
1876
2018
  ])
1877
2019
  ]),
@@ -1961,7 +2103,9 @@ var MenuManager = defineComponent3({
1961
2103
  value: form.parentId ?? ROOT_PARENT_ID,
1962
2104
  onChange: (e) => {
1963
2105
  const value = e.target.value;
1964
- form.parentId = value ? value : null;
2106
+ const parentId = value ? value : null;
2107
+ form.parentId = parentId;
2108
+ form.depth = resolveMenuDepth(parentId, allKnownMenus.value);
1965
2109
  }
1966
2110
  },
1967
2111
  [
@@ -1976,6 +2120,14 @@ var MenuManager = defineComponent3({
1976
2120
  ]
1977
2121
  )
1978
2122
  ]),
2123
+ h2("div", { style: s2.field }, [
2124
+ h2("span", { style: s2.label }, "\u83DC\u5355\u5C42\u7EA7\uFF08depth\uFF09"),
2125
+ h2("input", {
2126
+ style: s2.input,
2127
+ value: form.depth,
2128
+ readOnly: true
2129
+ })
2130
+ ]),
1979
2131
  h2("fieldset", { style: s2.fieldset }, [
1980
2132
  h2("legend", { style: s2.label }, "\u83DC\u5355\u7C7B\u578B"),
1981
2133
  h2(
@@ -2358,6 +2510,8 @@ var SystemAdmin = defineComponent4({
2358
2510
  });
2359
2511
  export {
2360
2512
  Can,
2513
+ MENU_LEAF_NO,
2514
+ MENU_LEAF_YES,
2361
2515
  MENU_LIST_TYPE_PARAM,
2362
2516
  MENU_TYPE_BUTTON,
2363
2517
  MENU_TYPE_LABEL,
@@ -2373,6 +2527,7 @@ export {
2373
2527
  RESOURCE_STATUS_ENABLED,
2374
2528
  RESOURCE_STATUS_OPTIONS,
2375
2529
  RESOURCE_TYPE_API,
2530
+ ROOT_MENU_DEPTH,
2376
2531
  ROOT_PARENT_ID,
2377
2532
  ResourceManager,
2378
2533
  SYSTEM_ADMIN_DEFAULT_KEY,
@@ -2393,8 +2548,10 @@ export {
2393
2548
  extractRecords,
2394
2549
  getAppClientId,
2395
2550
  getDeviceWorkerId,
2551
+ isMenuLeaf,
2396
2552
  mapAuthorizationResource,
2397
2553
  mapMenuResource,
2554
+ resolveMenuDepth,
2398
2555
  snowyflake,
2399
2556
  useHasPermission,
2400
2557
  useHasRole,