com-angel-authorization 1.0.16 → 1.0.18

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.
package/README.md CHANGED
@@ -427,13 +427,59 @@ export function Page() {
427
427
 
428
428
  列表支持 `keyword` 搜索与 page-token 分页。表头:角色名称、描述、操作(编辑 / 授权 / 删除)。
429
429
 
430
- 点击「授权」打开树形勾选弹窗:勾选父节点会级联子节点;保存调用 `POST /system/roles/{role-id}/permissions`。
430
+ 点击「授权」打开树形勾选弹窗(父子联动:勾选父节点级联子节点;子节点全选/取消会回写父节点;部分勾选为半选态)。保存调用 `POST /system/roles/{role-id}/permissions`。
431
+
432
+ ---
433
+
434
+ ## 用户管理(CRUD)
435
+
436
+ 对接后端 `/system/users`。
437
+
438
+ | 操作 | 方法 | 地址 |
439
+ |------|------|------|
440
+ | 列表 | GET | `/system/users?keyword=&enabled=&page-token=&page-size=&page-direction=` |
441
+ | 新增 | POST | `/system/users` |
442
+ | 修改 | PATCH | `/system/users/{user-id}` |
443
+ | 删除 | DELETE | `/system/users/{user-id}` |
444
+ | 部门下拉 | GET | `/system/groups?keyword=` |
445
+ | 角色下拉 | GET | `/system/roles?keyword=` |
446
+
447
+ ### React
448
+
449
+ ```tsx
450
+ import {
451
+ UserManager,
452
+ createSystemUserApi,
453
+ createDefaultResourceRequest,
454
+ } from 'com-angel-authorization/react';
455
+
456
+ const api = createSystemUserApi(
457
+ createDefaultResourceRequest({ baseUrl: '/api' }),
458
+ );
459
+
460
+ export function Page() {
461
+ return <UserManager api={api} />;
462
+ }
463
+ ```
464
+
465
+ ### 表单字段
466
+
467
+ | 字段 | 说明 |
468
+ |------|------|
469
+ | username | 账号:不少于 6 位,且同时包含字母与数字 |
470
+ | name | 用户名 |
471
+ | password | 初始密码(编辑时可留空表示不修改) |
472
+ | groupIds | 归属部门,多选(`/system/groups`) |
473
+ | roleIds | 用户角色,多选(`/system/roles`) |
474
+ | enabled | 是否启用(boolean,Switch) |
475
+
476
+ 列表支持 `keyword`、`enabled` 过滤与 page-token 分页。
431
477
 
432
478
  ---
433
479
 
434
480
  ## 系统管理(含子菜单)
435
481
 
436
- 将「菜单管理」「权限点管理」「角色管理」作为「系统管理」的子菜单展示:
482
+ 将「菜单管理」「权限点管理」「角色管理」「用户管理」作为「系统管理」的子菜单展示:
437
483
 
438
484
  ```tsx
439
485
  import {
@@ -441,6 +487,7 @@ import {
441
487
  createMenuResourceApi,
442
488
  createAuthorizationResourceApi,
443
489
  createSystemRoleApi,
490
+ createSystemUserApi,
444
491
  createDefaultResourceRequest,
445
492
  SYSTEM_ADMIN_MENU,
446
493
  } from 'com-angel-authorization/react';
@@ -449,9 +496,15 @@ const request = createDefaultResourceRequest({ baseUrl: '/api' });
449
496
  const menuApi = createMenuResourceApi(request);
450
497
  const resourceApi = createAuthorizationResourceApi(request);
451
498
  const roleApi = createSystemRoleApi(request);
499
+ const userApi = createSystemUserApi(request);
452
500
 
453
- // 侧栏:系统管理 → 菜单管理 / 权限点管理 / 角色管理
454
- <SystemAdmin menuApi={menuApi} resourceApi={resourceApi} roleApi={roleApi} />
501
+ // 侧栏:系统管理 → 菜单 / 权限点 / 角色 / 用户管理
502
+ <SystemAdmin
503
+ menuApi={menuApi}
504
+ resourceApi={resourceApi}
505
+ roleApi={roleApi}
506
+ userApi={userApi}
507
+ />
455
508
 
456
509
  // 也可把菜单结构接到自有路由
457
510
  console.log(SYSTEM_ADMIN_MENU);
@@ -459,6 +512,7 @@ console.log(SYSTEM_ADMIN_MENU);
459
512
  // { key: 'menu', label: '菜单管理' },
460
513
  // { key: 'resource', label: '权限点管理' },
461
514
  // { key: 'role', label: '角色管理' },
515
+ // { key: 'user', label: '用户管理' },
462
516
  // ]}
463
517
  ```
464
518
 
package/dist/index.cjs CHANGED
@@ -188,7 +188,8 @@ var SYSTEM_ADMIN_MENU = {
188
188
  children: [
189
189
  { key: "menu", label: "\u83DC\u5355\u7BA1\u7406" },
190
190
  { key: "resource", label: "\u6743\u9650\u70B9\u7BA1\u7406" },
191
- { key: "role", label: "\u89D2\u8272\u7BA1\u7406" }
191
+ { key: "role", label: "\u89D2\u8272\u7BA1\u7406" },
192
+ { key: "user", label: "\u7528\u6237\u7BA1\u7406" }
192
193
  ]
193
194
  };
194
195
  var SYSTEM_ADMIN_DEFAULT_KEY = "menu";
@@ -602,6 +603,72 @@ function mapRolePermissions(payload) {
602
603
  function collectTreeResourceIds(node) {
603
604
  return [node.resourceId, ...node.children.flatMap(collectTreeResourceIds)];
604
605
  }
606
+ function buildPermissionTreeIndex(tree) {
607
+ const parentMap = /* @__PURE__ */ new Map();
608
+ const nodeMap = /* @__PURE__ */ new Map();
609
+ const walk = (nodes, parentId) => {
610
+ for (const node of nodes) {
611
+ parentMap.set(node.resourceId, parentId);
612
+ nodeMap.set(node.resourceId, node);
613
+ if (node.children.length > 0) {
614
+ walk(node.children, node.resourceId);
615
+ }
616
+ }
617
+ };
618
+ walk(tree, null);
619
+ return { parentMap, nodeMap };
620
+ }
621
+ function togglePermissionCheck(tree, checked, node) {
622
+ const next = new Set(checked);
623
+ const ids = collectTreeResourceIds(node);
624
+ const shouldCheck = !checked.has(node.resourceId);
625
+ if (shouldCheck) {
626
+ ids.forEach((id) => next.add(id));
627
+ } else {
628
+ ids.forEach((id) => next.delete(id));
629
+ }
630
+ const { parentMap, nodeMap } = buildPermissionTreeIndex(tree);
631
+ let parentId = parentMap.get(node.resourceId) ?? null;
632
+ while (parentId) {
633
+ const parent = nodeMap.get(parentId);
634
+ if (!parent) break;
635
+ const allChildrenChecked = parent.children.every(
636
+ (child) => next.has(child.resourceId)
637
+ );
638
+ if (allChildrenChecked && parent.children.length > 0) {
639
+ next.add(parentId);
640
+ } else {
641
+ next.delete(parentId);
642
+ }
643
+ parentId = parentMap.get(parentId) ?? null;
644
+ }
645
+ return next;
646
+ }
647
+ function countCheckedDescendants(node, checked) {
648
+ let total = 0;
649
+ let checkedCount = 0;
650
+ const walk = (n) => {
651
+ for (const child of n.children) {
652
+ total += 1;
653
+ if (checked.has(child.resourceId)) checkedCount += 1;
654
+ walk(child);
655
+ }
656
+ };
657
+ walk(node);
658
+ return { total, checkedCount };
659
+ }
660
+ function hasCheckedDescendant(node, checked) {
661
+ for (const child of node.children) {
662
+ if (checked.has(child.resourceId) || hasCheckedDescendant(child, checked)) {
663
+ return true;
664
+ }
665
+ }
666
+ return false;
667
+ }
668
+ function isPermissionNodeIndeterminate(node, checked) {
669
+ if (checked.has(node.resourceId) || node.children.length === 0) return false;
670
+ return hasCheckedDescendant(node, checked);
671
+ }
605
672
  function buildListUrl2(params) {
606
673
  const parts = [];
607
674
  appendQueryParam(parts, "keyword", params?.keyword ?? "");
@@ -683,6 +750,169 @@ function createSystemRoleApi(request) {
683
750
  };
684
751
  }
685
752
 
753
+ // src/users/index.ts
754
+ function asIdList(value) {
755
+ if (!Array.isArray(value)) return [];
756
+ return value.map((item) => {
757
+ if (item === void 0 || item === null || item === "") return "";
758
+ if (typeof item === "object") {
759
+ const row = item;
760
+ const id = row.groupId ?? row.roleId ?? row.id;
761
+ return id === void 0 || id === null ? "" : String(id);
762
+ }
763
+ return String(item);
764
+ }).filter(Boolean);
765
+ }
766
+ function asNameList(value) {
767
+ if (!Array.isArray(value)) return void 0;
768
+ const names = value.map((item) => {
769
+ if (item === void 0 || item === null) return "";
770
+ if (typeof item === "object") {
771
+ return String(item.name ?? "");
772
+ }
773
+ return String(item);
774
+ }).filter(Boolean);
775
+ return names.length ? names : void 0;
776
+ }
777
+ function mapSystemUser(item) {
778
+ if (!item || typeof item !== "object") return null;
779
+ const row = item;
780
+ const userId = row.userId ?? row.user_id ?? row.id;
781
+ if (userId === void 0 || userId === null || userId === "") return null;
782
+ return {
783
+ userId: String(userId),
784
+ username: String(row.username ?? row.account ?? ""),
785
+ name: String(row.name ?? ""),
786
+ groupIds: asIdList(row.groupIds ?? row.group_ids ?? row.groups),
787
+ roleIds: asIdList(row.roleIds ?? row.role_ids ?? row.roles),
788
+ groupNames: asNameList(row.groupNames ?? row.group_names ?? row.groups),
789
+ roleNames: asNameList(row.roleNames ?? row.role_names ?? row.roles),
790
+ enabled: Boolean(row.enabled ?? row.enable ?? true)
791
+ };
792
+ }
793
+ function mapSystemGroupOption(item) {
794
+ if (!item || typeof item !== "object") return null;
795
+ const row = item;
796
+ const groupId = row.groupId ?? row.group_id ?? row.id;
797
+ if (groupId === void 0 || groupId === null || groupId === "") return null;
798
+ return {
799
+ groupId: String(groupId),
800
+ name: String(row.name ?? "")
801
+ };
802
+ }
803
+ function mapSystemRoleOption(item) {
804
+ if (!item || typeof item !== "object") return null;
805
+ const row = item;
806
+ const roleId = row.roleId ?? row.role_id ?? row.id;
807
+ if (roleId === void 0 || roleId === null || roleId === "") return null;
808
+ return {
809
+ roleId: String(roleId),
810
+ name: String(row.name ?? "")
811
+ };
812
+ }
813
+ function validateUsername(username) {
814
+ const value = username.trim();
815
+ if (value.length < 6) return "\u8D26\u53F7\u957F\u5EA6\u4E0D\u5C11\u4E8E 6 \u4E2A\u5B57\u7B26";
816
+ if (!/[A-Za-z]/.test(value) || !/[0-9]/.test(value)) {
817
+ return "\u8D26\u53F7\u9700\u540C\u65F6\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57";
818
+ }
819
+ return null;
820
+ }
821
+ function buildListUrl3(params) {
822
+ const parts = [];
823
+ appendQueryParam(parts, "keyword", params?.keyword ?? "");
824
+ if (params?.enabled !== void 0) {
825
+ appendQueryParam(parts, "enabled", String(params.enabled));
826
+ }
827
+ appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
828
+ appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
829
+ appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
830
+ return parts.length ? `/system/users?${parts.join("&")}` : "/system/users";
831
+ }
832
+ function buildKeywordUrl(base, keyword) {
833
+ const parts = [];
834
+ appendQueryParam(parts, "keyword", keyword ?? "");
835
+ return parts.length ? `${base}?${parts.join("&")}` : base;
836
+ }
837
+ function buildCreateUserBody(values) {
838
+ return {
839
+ username: values.username.trim(),
840
+ name: values.name.trim(),
841
+ password: values.password,
842
+ groupIds: [...new Set(values.groupIds.map(String))],
843
+ roleIds: [...new Set(values.roleIds.map(String))],
844
+ enabled: Boolean(values.enabled)
845
+ };
846
+ }
847
+ function buildUpdateUserBody(values) {
848
+ const body = {
849
+ username: values.username.trim(),
850
+ name: values.name.trim(),
851
+ groupIds: [...new Set(values.groupIds.map(String))],
852
+ roleIds: [...new Set(values.roleIds.map(String))],
853
+ enabled: Boolean(values.enabled)
854
+ };
855
+ if (values.password.trim()) {
856
+ body.password = values.password;
857
+ }
858
+ return body;
859
+ }
860
+ function createSystemUserApi(request) {
861
+ return {
862
+ async list(params, signal) {
863
+ const json = await request({
864
+ method: "GET",
865
+ url: buildListUrl3(params),
866
+ signal
867
+ });
868
+ const records = extractRecords(json).map(mapSystemUser).filter((item) => item !== null);
869
+ return {
870
+ records,
871
+ ...extractPagination(json)
872
+ };
873
+ },
874
+ async create(values, signal) {
875
+ return request({
876
+ method: "POST",
877
+ url: "/system/users",
878
+ body: buildCreateUserBody(values),
879
+ signal
880
+ });
881
+ },
882
+ async update(userId, values, signal) {
883
+ return request({
884
+ method: "PATCH",
885
+ url: `/system/users/${encodeURIComponent(userId)}`,
886
+ body: buildUpdateUserBody(values),
887
+ signal
888
+ });
889
+ },
890
+ async remove(userId, signal) {
891
+ return request({
892
+ method: "DELETE",
893
+ url: `/system/users/${encodeURIComponent(userId)}`,
894
+ signal
895
+ });
896
+ },
897
+ async listGroups(params, signal) {
898
+ const json = await request({
899
+ method: "GET",
900
+ url: buildKeywordUrl("/system/groups", params?.keyword),
901
+ signal
902
+ });
903
+ return extractRecords(json).map(mapSystemGroupOption).filter((item) => item !== null);
904
+ },
905
+ async listRoleOptions(params, signal) {
906
+ const json = await request({
907
+ method: "GET",
908
+ url: buildKeywordUrl("/system/roles", params?.keyword),
909
+ signal
910
+ });
911
+ return extractRecords(json).map(mapSystemRoleOption).filter((item) => item !== null);
912
+ }
913
+ };
914
+ }
915
+
686
916
  exports.MENU_LEAF_NO = MENU_LEAF_NO;
687
917
  exports.MENU_LEAF_YES = MENU_LEAF_YES;
688
918
  exports.MENU_LIST_TYPE_PARAM = MENU_LIST_TYPE_PARAM;
@@ -706,27 +936,39 @@ exports.appendQueryParam = appendQueryParam;
706
936
  exports.buildCreateBody = buildCreateBody;
707
937
  exports.buildCreateMenuBody = buildCreateMenuBody;
708
938
  exports.buildCreateRoleBody = buildCreateRoleBody;
939
+ exports.buildCreateUserBody = buildCreateUserBody;
940
+ exports.buildPermissionTreeIndex = buildPermissionTreeIndex;
709
941
  exports.buildSavePermissionsBody = buildSavePermissionsBody;
710
942
  exports.buildUpdateBody = buildUpdateBody;
711
943
  exports.buildUpdateMenuBody = buildUpdateMenuBody;
712
944
  exports.buildUpdateRoleBody = buildUpdateRoleBody;
945
+ exports.buildUpdateUserBody = buildUpdateUserBody;
713
946
  exports.collectTreeResourceIds = collectTreeResourceIds;
947
+ exports.countCheckedDescendants = countCheckedDescendants;
714
948
  exports.createAuthorizationResourceApi = createAuthorizationResourceApi;
715
949
  exports.createDefaultResourceRequest = createDefaultResourceRequest;
716
950
  exports.createMenuResourceApi = createMenuResourceApi;
717
951
  exports.createPermissionStore = createPermissionStore;
718
952
  exports.createSystemRoleApi = createSystemRoleApi;
953
+ exports.createSystemUserApi = createSystemUserApi;
719
954
  exports.extractPagination = extractPagination;
720
955
  exports.extractRecords = extractRecords;
721
956
  exports.getAppClientId = getAppClientId;
722
957
  exports.getDeviceWorkerId = getDeviceWorkerId;
958
+ exports.hasCheckedDescendant = hasCheckedDescendant;
723
959
  exports.isMenuLeaf = isMenuLeaf;
960
+ exports.isPermissionNodeIndeterminate = isPermissionNodeIndeterminate;
724
961
  exports.mapAuthorizationResource = mapAuthorizationResource;
725
962
  exports.mapMenuResource = mapMenuResource;
726
963
  exports.mapPermissionTreeNode = mapPermissionTreeNode;
727
964
  exports.mapRolePermissions = mapRolePermissions;
965
+ exports.mapSystemGroupOption = mapSystemGroupOption;
728
966
  exports.mapSystemRole = mapSystemRole;
967
+ exports.mapSystemRoleOption = mapSystemRoleOption;
968
+ exports.mapSystemUser = mapSystemUser;
729
969
  exports.resolveMenuDepth = resolveMenuDepth;
730
970
  exports.snowyflake = snowyflake;
971
+ exports.togglePermissionCheck = togglePermissionCheck;
972
+ exports.validateUsername = validateUsername;
731
973
  //# sourceMappingURL=index.cjs.map
732
974
  //# sourceMappingURL=index.cjs.map