com-angel-authorization 1.0.17 → 1.0.20

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.
@@ -45,15 +45,18 @@ __export(vue_exports, {
45
45
  SYSTEM_ADMIN_DEFAULT_KEY: () => SYSTEM_ADMIN_DEFAULT_KEY,
46
46
  SYSTEM_ADMIN_MENU: () => SYSTEM_ADMIN_MENU,
47
47
  SystemAdmin: () => SystemAdmin,
48
+ UserManager: () => UserManager,
48
49
  appendQueryParam: () => appendQueryParam,
49
50
  buildCreateBody: () => buildCreateBody,
50
51
  buildCreateMenuBody: () => buildCreateMenuBody,
51
52
  buildCreateRoleBody: () => buildCreateRoleBody,
53
+ buildCreateUserBody: () => buildCreateUserBody,
52
54
  buildPermissionTreeIndex: () => buildPermissionTreeIndex,
53
55
  buildSavePermissionsBody: () => buildSavePermissionsBody,
54
56
  buildUpdateBody: () => buildUpdateBody,
55
57
  buildUpdateMenuBody: () => buildUpdateMenuBody,
56
58
  buildUpdateRoleBody: () => buildUpdateRoleBody,
59
+ buildUpdateUserBody: () => buildUpdateUserBody,
57
60
  collectTreeResourceIds: () => collectTreeResourceIds,
58
61
  countCheckedDescendants: () => countCheckedDescendants,
59
62
  createAuthorizationResourceApi: () => createAuthorizationResourceApi,
@@ -62,6 +65,7 @@ __export(vue_exports, {
62
65
  createPermissionPlugin: () => createPermissionPlugin,
63
66
  createPermissionStore: () => createPermissionStore,
64
67
  createSystemRoleApi: () => createSystemRoleApi,
68
+ createSystemUserApi: () => createSystemUserApi,
65
69
  createVPermission: () => createVPermission,
66
70
  extractPagination: () => extractPagination,
67
71
  extractRecords: () => extractRecords,
@@ -74,13 +78,17 @@ __export(vue_exports, {
74
78
  mapMenuResource: () => mapMenuResource,
75
79
  mapPermissionTreeNode: () => mapPermissionTreeNode,
76
80
  mapRolePermissions: () => mapRolePermissions,
81
+ mapSystemGroupOption: () => mapSystemGroupOption,
77
82
  mapSystemRole: () => mapSystemRole,
83
+ mapSystemRoleOption: () => mapSystemRoleOption,
84
+ mapSystemUser: () => mapSystemUser,
78
85
  resolveMenuDepth: () => resolveMenuDepth,
79
86
  snowyflake: () => snowyflake,
80
87
  togglePermissionCheck: () => togglePermissionCheck,
81
88
  useHasPermission: () => useHasPermission,
82
89
  useHasRole: () => useHasRole,
83
- usePermission: () => usePermission
90
+ usePermission: () => usePermission,
91
+ validateUsername: () => validateUsername
84
92
  });
85
93
  module.exports = __toCommonJS(vue_exports);
86
94
 
@@ -572,7 +580,7 @@ function toStringArray(value) {
572
580
  }).filter(Boolean);
573
581
  }
574
582
  if (typeof value === "string" && value.trim()) {
575
- return value.split(",").map((s5) => s5.trim()).filter(Boolean);
583
+ return value.split(",").map((s6) => s6.trim()).filter(Boolean);
576
584
  }
577
585
  return [];
578
586
  }
@@ -3434,23 +3442,1152 @@ var RoleManager = (0, import_vue5.defineComponent)({
3434
3442
  }
3435
3443
  });
3436
3444
 
3445
+ // src/vue/UserManager.ts
3446
+ var import_vue6 = require("vue");
3447
+
3448
+ // src/users/index.ts
3449
+ function asIdList(value) {
3450
+ if (!Array.isArray(value)) return [];
3451
+ return value.map((item) => {
3452
+ if (item === void 0 || item === null || item === "") return "";
3453
+ if (typeof item === "object") {
3454
+ const row = item;
3455
+ const id = row.groupId ?? row.roleId ?? row.id;
3456
+ return id === void 0 || id === null ? "" : String(id);
3457
+ }
3458
+ return String(item);
3459
+ }).filter(Boolean);
3460
+ }
3461
+ function asNameList(value) {
3462
+ if (!Array.isArray(value)) return void 0;
3463
+ const names = value.map((item) => {
3464
+ if (item === void 0 || item === null) return "";
3465
+ if (typeof item === "object") {
3466
+ return String(item.name ?? "");
3467
+ }
3468
+ return String(item);
3469
+ }).filter(Boolean);
3470
+ return names.length ? names : void 0;
3471
+ }
3472
+ function mapSystemUser(item) {
3473
+ if (!item || typeof item !== "object") return null;
3474
+ const row = item;
3475
+ const userId = row.userId ?? row.user_id ?? row.id;
3476
+ if (userId === void 0 || userId === null || userId === "") return null;
3477
+ return {
3478
+ userId: String(userId),
3479
+ username: String(row.username ?? row.account ?? ""),
3480
+ name: String(row.name ?? ""),
3481
+ groupIds: asIdList(row.groupIds ?? row.group_ids ?? row.groups),
3482
+ roleIds: asIdList(row.roleIds ?? row.role_ids ?? row.roles),
3483
+ groupNames: asNameList(row.groupNames ?? row.group_names ?? row.groups),
3484
+ roleNames: asNameList(row.roleNames ?? row.role_names ?? row.roles),
3485
+ enabled: Boolean(row.enabled ?? row.enable ?? true)
3486
+ };
3487
+ }
3488
+ function mapSystemGroupOption(item) {
3489
+ if (!item || typeof item !== "object") return null;
3490
+ const row = item;
3491
+ const groupId = row.groupId ?? row.group_id ?? row.id;
3492
+ if (groupId === void 0 || groupId === null || groupId === "") return null;
3493
+ return {
3494
+ groupId: String(groupId),
3495
+ name: String(row.name ?? "")
3496
+ };
3497
+ }
3498
+ function mapSystemRoleOption(item) {
3499
+ if (!item || typeof item !== "object") return null;
3500
+ const row = item;
3501
+ const roleId = row.roleId ?? row.role_id ?? row.id;
3502
+ if (roleId === void 0 || roleId === null || roleId === "") return null;
3503
+ return {
3504
+ roleId: String(roleId),
3505
+ name: String(row.name ?? "")
3506
+ };
3507
+ }
3508
+ function validateUsername(username) {
3509
+ const value = username.trim();
3510
+ if (value.length < 6) return "\u8D26\u53F7\u957F\u5EA6\u4E0D\u5C11\u4E8E 6 \u4E2A\u5B57\u7B26";
3511
+ if (!/[A-Za-z]/.test(value) || !/[0-9]/.test(value)) {
3512
+ return "\u8D26\u53F7\u9700\u540C\u65F6\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57";
3513
+ }
3514
+ return null;
3515
+ }
3516
+ function buildListUrl3(params) {
3517
+ const parts = [];
3518
+ appendQueryParam(parts, "keyword", params?.keyword ?? "");
3519
+ if (params?.enabled !== void 0) {
3520
+ appendQueryParam(parts, "enabled", String(params.enabled));
3521
+ }
3522
+ appendQueryParam(parts, "page-token", params?.pagination?.pageToken ?? "");
3523
+ appendQueryParam(parts, "page-size", params?.pagination?.pageSize ?? "20");
3524
+ appendQueryParam(parts, "page-direction", params?.pagination?.pageDirection ?? "current");
3525
+ return parts.length ? `/system/users?${parts.join("&")}` : "/system/users";
3526
+ }
3527
+ function buildKeywordUrl(base, keyword) {
3528
+ const parts = [];
3529
+ appendQueryParam(parts, "keyword", keyword ?? "");
3530
+ return parts.length ? `${base}?${parts.join("&")}` : base;
3531
+ }
3532
+ function buildCreateUserBody(values) {
3533
+ return {
3534
+ username: values.username.trim(),
3535
+ name: values.name.trim(),
3536
+ password: values.password,
3537
+ groupIds: [...new Set(values.groupIds.map(String))],
3538
+ roleIds: [...new Set(values.roleIds.map(String))],
3539
+ enabled: Boolean(values.enabled)
3540
+ };
3541
+ }
3542
+ function buildUpdateUserBody(values) {
3543
+ const body = {
3544
+ username: values.username.trim(),
3545
+ name: values.name.trim(),
3546
+ groupIds: [...new Set(values.groupIds.map(String))],
3547
+ roleIds: [...new Set(values.roleIds.map(String))],
3548
+ enabled: Boolean(values.enabled)
3549
+ };
3550
+ if (values.password.trim()) {
3551
+ body.password = values.password;
3552
+ }
3553
+ return body;
3554
+ }
3555
+ function createSystemUserApi(request) {
3556
+ return {
3557
+ async list(params, signal) {
3558
+ const json = await request({
3559
+ method: "GET",
3560
+ url: buildListUrl3(params),
3561
+ signal
3562
+ });
3563
+ const records = extractRecords(json).map(mapSystemUser).filter((item) => item !== null);
3564
+ return {
3565
+ records,
3566
+ ...extractPagination(json)
3567
+ };
3568
+ },
3569
+ async create(values, signal) {
3570
+ return request({
3571
+ method: "POST",
3572
+ url: "/system/users",
3573
+ body: buildCreateUserBody(values),
3574
+ signal
3575
+ });
3576
+ },
3577
+ async update(userId, values, signal) {
3578
+ return request({
3579
+ method: "PATCH",
3580
+ url: `/system/users/${encodeURIComponent(userId)}`,
3581
+ body: buildUpdateUserBody(values),
3582
+ signal
3583
+ });
3584
+ },
3585
+ async remove(userId, signal) {
3586
+ return request({
3587
+ method: "DELETE",
3588
+ url: `/system/users/${encodeURIComponent(userId)}`,
3589
+ signal
3590
+ });
3591
+ },
3592
+ async listGroups(params, signal) {
3593
+ const json = await request({
3594
+ method: "GET",
3595
+ url: buildKeywordUrl("/system/groups", params?.keyword),
3596
+ signal
3597
+ });
3598
+ return extractRecords(json).map(mapSystemGroupOption).filter((item) => item !== null);
3599
+ },
3600
+ async listRoleOptions(params, signal) {
3601
+ const json = await request({
3602
+ method: "GET",
3603
+ url: buildKeywordUrl("/system/roles", params?.keyword),
3604
+ signal
3605
+ });
3606
+ return extractRecords(json).map(mapSystemRoleOption).filter((item) => item !== null);
3607
+ }
3608
+ };
3609
+ }
3610
+
3611
+ // src/vue/UserManager.ts
3612
+ var PAGE_SIZE_OPTIONS4 = ["10", "20", "50", "100"];
3613
+ function emptyForm4() {
3614
+ return {
3615
+ username: "",
3616
+ name: "",
3617
+ password: "",
3618
+ groupIds: [],
3619
+ roleIds: [],
3620
+ enabled: true
3621
+ };
3622
+ }
3623
+ var s4 = {
3624
+ root: {
3625
+ display: "flex",
3626
+ flexDirection: "column",
3627
+ gap: "16px",
3628
+ padding: "16px",
3629
+ color: "#101828",
3630
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
3631
+ },
3632
+ toolbar: {
3633
+ display: "flex",
3634
+ alignItems: "center",
3635
+ justifyContent: "space-between",
3636
+ gap: "12px"
3637
+ },
3638
+ title: { margin: "0", fontSize: "18px", fontWeight: "600" },
3639
+ toolbarRight: { display: "flex", alignItems: "center", gap: "8px" },
3640
+ searchBar: {
3641
+ display: "flex",
3642
+ alignItems: "center",
3643
+ gap: "8px",
3644
+ flexWrap: "wrap"
3645
+ },
3646
+ error: {
3647
+ padding: "10px 12px",
3648
+ borderRadius: "8px",
3649
+ background: "#fef3f2",
3650
+ color: "#b42318",
3651
+ fontSize: "13px"
3652
+ },
3653
+ tableWrap: {
3654
+ overflow: "auto",
3655
+ border: "1px solid #eaecf0",
3656
+ borderRadius: "10px",
3657
+ background: "#fff"
3658
+ },
3659
+ table: { width: "100%", borderCollapse: "collapse", minWidth: "720px" },
3660
+ th: {
3661
+ textAlign: "left",
3662
+ padding: "12px 14px",
3663
+ fontSize: "13px",
3664
+ fontWeight: "600",
3665
+ color: "#475467",
3666
+ background: "#f9fafb",
3667
+ borderBottom: "1px solid #eaecf0"
3668
+ },
3669
+ td: {
3670
+ padding: "12px 14px",
3671
+ fontSize: "14px",
3672
+ borderBottom: "1px solid #f2f4f7",
3673
+ verticalAlign: "middle"
3674
+ },
3675
+ empty: {
3676
+ padding: "28px",
3677
+ textAlign: "center",
3678
+ color: "#98a2b3",
3679
+ fontSize: "14px"
3680
+ },
3681
+ linkBtn: {
3682
+ border: "none",
3683
+ background: "transparent",
3684
+ color: "#049BAD",
3685
+ cursor: "pointer",
3686
+ padding: "0 8px 0 0",
3687
+ fontSize: "13px"
3688
+ },
3689
+ badge: {
3690
+ display: "inline-block",
3691
+ padding: "2px 8px",
3692
+ borderRadius: "999px",
3693
+ fontSize: "12px",
3694
+ fontWeight: "500"
3695
+ },
3696
+ badgeOn: { background: "#ecfdf3", color: "#027a48" },
3697
+ badgeOff: { background: "#f2f4f7", color: "#667085" },
3698
+ pagination: {
3699
+ display: "flex",
3700
+ alignItems: "center",
3701
+ justifyContent: "space-between",
3702
+ gap: "12px"
3703
+ },
3704
+ pageSize: {
3705
+ display: "flex",
3706
+ alignItems: "center",
3707
+ gap: "8px",
3708
+ fontSize: "13px",
3709
+ color: "#475467"
3710
+ },
3711
+ pageBtns: { display: "flex", gap: "8px" },
3712
+ primaryBtn: {
3713
+ border: "none",
3714
+ background: "#049BAD",
3715
+ color: "#fff",
3716
+ borderRadius: "8px",
3717
+ padding: "8px 14px",
3718
+ cursor: "pointer",
3719
+ fontSize: "14px"
3720
+ },
3721
+ secondaryBtn: {
3722
+ border: "1px solid #d0d5dd",
3723
+ background: "#fff",
3724
+ color: "#344054",
3725
+ borderRadius: "8px",
3726
+ padding: "8px 14px",
3727
+ cursor: "pointer",
3728
+ fontSize: "14px"
3729
+ },
3730
+ dangerBtn: {
3731
+ border: "none",
3732
+ background: "#d92d20",
3733
+ color: "#fff",
3734
+ borderRadius: "8px",
3735
+ padding: "8px 14px",
3736
+ cursor: "pointer",
3737
+ fontSize: "14px"
3738
+ },
3739
+ select: {
3740
+ border: "1px solid #d0d5dd",
3741
+ borderRadius: "6px",
3742
+ padding: "4px 8px",
3743
+ fontSize: "13px",
3744
+ backgroundColor: "#ffffff",
3745
+ color: "#101828"
3746
+ },
3747
+ mask: {
3748
+ position: "fixed",
3749
+ inset: "0",
3750
+ background: "rgba(16, 24, 40, 0.45)",
3751
+ display: "flex",
3752
+ alignItems: "center",
3753
+ justifyContent: "center",
3754
+ zIndex: "1000",
3755
+ padding: "16px"
3756
+ },
3757
+ dialog: {
3758
+ width: "100%",
3759
+ maxWidth: "480px",
3760
+ background: "#fff",
3761
+ borderRadius: "12px",
3762
+ boxShadow: "0 20px 40px rgba(16,24,40,0.18)",
3763
+ maxHeight: "90vh",
3764
+ overflow: "auto"
3765
+ },
3766
+ dialogHeader: {
3767
+ display: "flex",
3768
+ alignItems: "center",
3769
+ justifyContent: "space-between",
3770
+ padding: "14px 16px",
3771
+ borderBottom: "1px solid #eaecf0",
3772
+ position: "sticky",
3773
+ top: "0",
3774
+ background: "#fff",
3775
+ zIndex: "1"
3776
+ },
3777
+ dialogTitle: { margin: "0", fontSize: "16px", fontWeight: "600" },
3778
+ iconBtn: {
3779
+ border: "none",
3780
+ background: "transparent",
3781
+ fontSize: "22px",
3782
+ lineHeight: "1",
3783
+ cursor: "pointer",
3784
+ color: "#667085"
3785
+ },
3786
+ form: {
3787
+ display: "flex",
3788
+ flexDirection: "column",
3789
+ gap: "12px",
3790
+ padding: "16px"
3791
+ },
3792
+ confirmBody: {
3793
+ display: "flex",
3794
+ flexDirection: "column",
3795
+ gap: "16px",
3796
+ padding: "16px"
3797
+ },
3798
+ confirmText: {
3799
+ margin: "0",
3800
+ fontSize: "14px",
3801
+ color: "#344054",
3802
+ lineHeight: "1.6"
3803
+ },
3804
+ field: { display: "flex", flexDirection: "column", gap: "6px" },
3805
+ fieldset: {
3806
+ border: "1px solid #eaecf0",
3807
+ borderRadius: "8px",
3808
+ margin: "0",
3809
+ padding: "10px 12px 12px"
3810
+ },
3811
+ label: { fontSize: "13px", color: "#344054", fontWeight: "500" },
3812
+ input: {
3813
+ border: "1px solid #d0d5dd",
3814
+ borderRadius: "8px",
3815
+ padding: "8px 10px",
3816
+ fontSize: "14px",
3817
+ outline: "none",
3818
+ backgroundColor: "#ffffff",
3819
+ color: "#101828",
3820
+ boxSizing: "border-box",
3821
+ width: "100%"
3822
+ },
3823
+ multiSelect: {
3824
+ display: "flex",
3825
+ flexDirection: "column",
3826
+ gap: "6px",
3827
+ maxHeight: "160px",
3828
+ overflow: "auto",
3829
+ marginTop: "8px"
3830
+ },
3831
+ checkItem: {
3832
+ display: "flex",
3833
+ alignItems: "center",
3834
+ gap: "8px",
3835
+ fontSize: "14px",
3836
+ color: "#101828",
3837
+ cursor: "pointer"
3838
+ },
3839
+ control: {
3840
+ width: "16px",
3841
+ height: "16px",
3842
+ accentColor: "#049BAD",
3843
+ cursor: "pointer",
3844
+ colorScheme: "light",
3845
+ backgroundColor: "#ffffff"
3846
+ },
3847
+ hint: { fontSize: "13px", color: "#98a2b3", padding: "4px 0" },
3848
+ selectTrigger: {
3849
+ display: "flex",
3850
+ alignItems: "center",
3851
+ justifyContent: "space-between",
3852
+ gap: "8px",
3853
+ width: "100%",
3854
+ border: "1px solid #d0d5dd",
3855
+ borderRadius: "8px",
3856
+ padding: "8px 10px",
3857
+ background: "#fff",
3858
+ cursor: "pointer",
3859
+ fontSize: "14px",
3860
+ color: "#101828",
3861
+ boxSizing: "border-box",
3862
+ textAlign: "left"
3863
+ },
3864
+ selectTriggerText: {
3865
+ flex: "1",
3866
+ overflow: "hidden",
3867
+ textOverflow: "ellipsis",
3868
+ whiteSpace: "nowrap"
3869
+ },
3870
+ selectPlaceholder: { color: "#98a2b3" },
3871
+ selectChevron: { color: "#667085", fontSize: "10px", flexShrink: "0" },
3872
+ required: { color: "#d92d20", marginLeft: "2px" },
3873
+ switchRow: {
3874
+ display: "flex",
3875
+ alignItems: "center",
3876
+ justifyContent: "flex-start",
3877
+ gap: "12px"
3878
+ },
3879
+ switchTrack: {
3880
+ width: "44px",
3881
+ height: "24px",
3882
+ borderRadius: "999px",
3883
+ border: "none",
3884
+ padding: "2px",
3885
+ background: "#d0d5dd",
3886
+ cursor: "pointer",
3887
+ position: "relative",
3888
+ transition: "background 0.15s ease"
3889
+ },
3890
+ switchTrackOn: { background: "#049BAD" },
3891
+ switchThumb: {
3892
+ display: "block",
3893
+ width: "20px",
3894
+ height: "20px",
3895
+ borderRadius: "50%",
3896
+ background: "#fff",
3897
+ boxShadow: "0 1px 2px rgba(16,24,40,0.2)",
3898
+ transform: "translateX(0)",
3899
+ transition: "transform 0.15s ease"
3900
+ },
3901
+ switchThumbOn: { transform: "translateX(20px)" },
3902
+ dialogFooter: {
3903
+ display: "flex",
3904
+ justifyContent: "flex-end",
3905
+ gap: "8px",
3906
+ paddingTop: "4px"
3907
+ }
3908
+ };
3909
+ var UserManager = (0, import_vue6.defineComponent)({
3910
+ name: "UserManager",
3911
+ props: {
3912
+ api: {
3913
+ type: Object,
3914
+ required: true
3915
+ },
3916
+ title: {
3917
+ type: String,
3918
+ default: "\u7528\u6237\u7BA1\u7406"
3919
+ },
3920
+ pageSize: {
3921
+ type: String,
3922
+ default: "20"
3923
+ }
3924
+ },
3925
+ setup(props, { slots }) {
3926
+ const records = (0, import_vue6.ref)([]);
3927
+ const loading = (0, import_vue6.ref)(false);
3928
+ const error = (0, import_vue6.ref)("");
3929
+ const keyword = (0, import_vue6.ref)("");
3930
+ const keywordInput = (0, import_vue6.ref)("");
3931
+ const enabledFilter = (0, import_vue6.ref)("all");
3932
+ const pageSize = (0, import_vue6.ref)(props.pageSize);
3933
+ const pageToken = (0, import_vue6.ref)("");
3934
+ const hasPreviousPage = (0, import_vue6.ref)(false);
3935
+ const hasNextPage = (0, import_vue6.ref)(false);
3936
+ const dialogOpen = (0, import_vue6.ref)(false);
3937
+ const editing = (0, import_vue6.ref)(null);
3938
+ const form = (0, import_vue6.reactive)(emptyForm4());
3939
+ const formError = (0, import_vue6.ref)("");
3940
+ const saving = (0, import_vue6.ref)(false);
3941
+ const deletingRow = (0, import_vue6.ref)(null);
3942
+ const deleting = (0, import_vue6.ref)(false);
3943
+ const groups = (0, import_vue6.ref)([]);
3944
+ const roles = (0, import_vue6.ref)([]);
3945
+ const rolesLoading = (0, import_vue6.ref)(false);
3946
+ const groupsOpen = (0, import_vue6.ref)(false);
3947
+ const groupsLoading = (0, import_vue6.ref)(false);
3948
+ const groupsLoaded = (0, import_vue6.ref)(false);
3949
+ function enabledParam() {
3950
+ if (enabledFilter.value === "all") return void 0;
3951
+ return enabledFilter.value === "true";
3952
+ }
3953
+ async function loadList(direction = "current", token = pageToken.value) {
3954
+ loading.value = true;
3955
+ error.value = "";
3956
+ try {
3957
+ const result = await props.api.list({
3958
+ keyword: keyword.value,
3959
+ enabled: enabledParam(),
3960
+ pagination: {
3961
+ pageToken: token,
3962
+ pageSize: pageSize.value,
3963
+ pageDirection: direction
3964
+ }
3965
+ });
3966
+ records.value = result.records;
3967
+ pageToken.value = result.pageToken;
3968
+ hasPreviousPage.value = result.hasPreviousPage;
3969
+ hasNextPage.value = result.hasNextPage;
3970
+ } catch (err) {
3971
+ error.value = err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25";
3972
+ } finally {
3973
+ loading.value = false;
3974
+ }
3975
+ }
3976
+ async function loadRoles() {
3977
+ rolesLoading.value = true;
3978
+ try {
3979
+ roles.value = await props.api.listRoleOptions();
3980
+ } catch (err) {
3981
+ formError.value = err instanceof Error ? err.message : "\u52A0\u8F7D\u89D2\u8272\u5931\u8D25";
3982
+ } finally {
3983
+ rolesLoading.value = false;
3984
+ }
3985
+ }
3986
+ async function loadGroups() {
3987
+ if (groupsLoaded.value || groupsLoading.value) return;
3988
+ groupsLoading.value = true;
3989
+ try {
3990
+ groups.value = await props.api.listGroups();
3991
+ groupsLoaded.value = true;
3992
+ } catch (err) {
3993
+ formError.value = err instanceof Error ? err.message : "\u52A0\u8F7D\u90E8\u95E8\u5931\u8D25";
3994
+ } finally {
3995
+ groupsLoading.value = false;
3996
+ }
3997
+ }
3998
+ function handleSearch() {
3999
+ pageToken.value = "";
4000
+ keyword.value = keywordInput.value.trim();
4001
+ }
4002
+ function handleReset() {
4003
+ keywordInput.value = "";
4004
+ keyword.value = "";
4005
+ enabledFilter.value = "all";
4006
+ pageToken.value = "";
4007
+ }
4008
+ function resetGroupPanel() {
4009
+ groupsOpen.value = false;
4010
+ groups.value = [];
4011
+ groupsLoaded.value = false;
4012
+ }
4013
+ function openCreate() {
4014
+ editing.value = null;
4015
+ Object.assign(form, emptyForm4());
4016
+ formError.value = "";
4017
+ resetGroupPanel();
4018
+ dialogOpen.value = true;
4019
+ void loadRoles();
4020
+ }
4021
+ function openEdit(row) {
4022
+ editing.value = row;
4023
+ Object.assign(form, {
4024
+ username: row.username,
4025
+ name: row.name,
4026
+ password: "",
4027
+ groupIds: [...row.groupIds],
4028
+ roleIds: [...row.roleIds],
4029
+ enabled: row.enabled
4030
+ });
4031
+ formError.value = "";
4032
+ resetGroupPanel();
4033
+ dialogOpen.value = true;
4034
+ void loadRoles();
4035
+ }
4036
+ function closeDialog() {
4037
+ if (!saving.value) dialogOpen.value = false;
4038
+ }
4039
+ function toggleGroupsPanel() {
4040
+ groupsOpen.value = !groupsOpen.value;
4041
+ if (groupsOpen.value) void loadGroups();
4042
+ }
4043
+ function toggleId(field, id) {
4044
+ const exists = form[field].includes(id);
4045
+ form[field] = exists ? form[field].filter((x) => x !== id) : [...form[field], id];
4046
+ }
4047
+ async function handleSubmit(event) {
4048
+ event.preventDefault();
4049
+ const usernameError = validateUsername(form.username);
4050
+ if (usernameError) {
4051
+ formError.value = usernameError;
4052
+ return;
4053
+ }
4054
+ if (!form.name.trim()) {
4055
+ formError.value = "\u8BF7\u586B\u5199\u7528\u6237\u540D";
4056
+ return;
4057
+ }
4058
+ if (!editing.value && !form.password.trim()) {
4059
+ formError.value = "\u8BF7\u586B\u5199\u521D\u59CB\u5BC6\u7801";
4060
+ return;
4061
+ }
4062
+ if (!form.groupIds.length) {
4063
+ formError.value = "\u8BF7\u9009\u62E9\u5F52\u5C5E\u90E8\u95E8";
4064
+ return;
4065
+ }
4066
+ saving.value = true;
4067
+ formError.value = "";
4068
+ error.value = "";
4069
+ try {
4070
+ if (editing.value) {
4071
+ await props.api.update(editing.value.userId, { ...form });
4072
+ } else {
4073
+ await props.api.create({ ...form });
4074
+ }
4075
+ dialogOpen.value = false;
4076
+ await loadList("current", "");
4077
+ } catch (err) {
4078
+ formError.value = err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25";
4079
+ } finally {
4080
+ saving.value = false;
4081
+ }
4082
+ }
4083
+ function askDelete(row) {
4084
+ deletingRow.value = row;
4085
+ }
4086
+ function closeDeleteDialog() {
4087
+ if (!deleting.value) deletingRow.value = null;
4088
+ }
4089
+ async function confirmDelete() {
4090
+ if (!deletingRow.value) return;
4091
+ deleting.value = true;
4092
+ error.value = "";
4093
+ try {
4094
+ await props.api.remove(deletingRow.value.userId);
4095
+ deletingRow.value = null;
4096
+ await loadList("current", "");
4097
+ } catch (err) {
4098
+ error.value = err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25";
4099
+ } finally {
4100
+ deleting.value = false;
4101
+ }
4102
+ }
4103
+ function groupLabel(row) {
4104
+ if (row.groupNames?.length) return row.groupNames.join("\u3001");
4105
+ if (!row.groupIds.length) return "\u2014";
4106
+ return row.groupIds.join("\u3001");
4107
+ }
4108
+ function roleLabel(row) {
4109
+ if (row.roleNames?.length) return row.roleNames.join("\u3001");
4110
+ if (!row.roleIds.length) return "\u2014";
4111
+ const map = new Map(roles.value.map((r) => [r.roleId, r.name]));
4112
+ return row.roleIds.map((id) => map.get(id) || id).join("\u3001");
4113
+ }
4114
+ function selectedGroupSummary() {
4115
+ if (!form.groupIds.length) return "\u8BF7\u9009\u62E9\u5F52\u5C5E\u90E8\u95E8";
4116
+ if (groupsLoaded.value) {
4117
+ const map = new Map(groups.value.map((g) => [g.groupId, g.name]));
4118
+ return form.groupIds.map((id) => map.get(id) || id).join("\u3001");
4119
+ }
4120
+ if (editing.value?.groupNames?.length) {
4121
+ const map = new Map(
4122
+ editing.value.groupIds.map((id, i) => [
4123
+ id,
4124
+ editing.value?.groupNames?.[i] || id
4125
+ ])
4126
+ );
4127
+ return form.groupIds.map((id) => map.get(id) || id).join("\u3001");
4128
+ }
4129
+ return `\u5DF2\u9009 ${form.groupIds.length} \u4E2A\u90E8\u95E8`;
4130
+ }
4131
+ (0, import_vue6.onMounted)(() => {
4132
+ void loadList("current", "");
4133
+ void (async () => {
4134
+ try {
4135
+ roles.value = await props.api.listRoleOptions();
4136
+ } catch {
4137
+ }
4138
+ })();
4139
+ });
4140
+ (0, import_vue6.watch)(
4141
+ () => [
4142
+ props.api,
4143
+ pageSize.value,
4144
+ keyword.value,
4145
+ enabledFilter.value
4146
+ ],
4147
+ () => {
4148
+ pageToken.value = "";
4149
+ void loadList("current", "");
4150
+ }
4151
+ );
4152
+ return () => (0, import_vue6.h)("div", { style: s4.root }, [
4153
+ (0, import_vue6.h)("div", { style: s4.toolbar }, [
4154
+ (0, import_vue6.h)("h2", { style: s4.title }, props.title),
4155
+ (0, import_vue6.h)("div", { style: s4.toolbarRight }, [
4156
+ slots.toolbarExtra?.(),
4157
+ (0, import_vue6.h)(
4158
+ "button",
4159
+ { type: "button", style: s4.primaryBtn, onClick: openCreate },
4160
+ "\u65B0\u589E\u7528\u6237"
4161
+ )
4162
+ ])
4163
+ ]),
4164
+ (0, import_vue6.h)("div", { style: s4.searchBar }, [
4165
+ (0, import_vue6.h)("input", {
4166
+ style: { ...s4.input, maxWidth: "240px" },
4167
+ value: keywordInput.value,
4168
+ placeholder: "\u641C\u7D22\u8D26\u53F7 / \u7528\u6237\u540D",
4169
+ onInput: (e) => {
4170
+ keywordInput.value = e.target.value;
4171
+ },
4172
+ onKeydown: (e) => {
4173
+ if (e.key === "Enter") handleSearch();
4174
+ }
4175
+ }),
4176
+ (0, import_vue6.h)(
4177
+ "select",
4178
+ {
4179
+ style: s4.select,
4180
+ value: enabledFilter.value,
4181
+ onChange: (e) => {
4182
+ pageToken.value = "";
4183
+ enabledFilter.value = e.target.value;
4184
+ }
4185
+ },
4186
+ [
4187
+ (0, import_vue6.h)("option", { value: "all" }, "\u5168\u90E8\u72B6\u6001"),
4188
+ (0, import_vue6.h)("option", { value: "true" }, "\u5DF2\u542F\u7528"),
4189
+ (0, import_vue6.h)("option", { value: "false" }, "\u5DF2\u7981\u7528")
4190
+ ]
4191
+ ),
4192
+ (0, import_vue6.h)(
4193
+ "button",
4194
+ { type: "button", style: s4.secondaryBtn, onClick: handleSearch },
4195
+ "\u67E5\u8BE2"
4196
+ ),
4197
+ (0, import_vue6.h)(
4198
+ "button",
4199
+ { type: "button", style: s4.secondaryBtn, onClick: handleReset },
4200
+ "\u91CD\u7F6E"
4201
+ )
4202
+ ]),
4203
+ error.value ? (0, import_vue6.h)("div", { style: s4.error }, error.value) : null,
4204
+ (0, import_vue6.h)("div", { style: s4.tableWrap }, [
4205
+ (0, import_vue6.h)("table", { style: s4.table }, [
4206
+ (0, import_vue6.h)("thead", [
4207
+ (0, import_vue6.h)("tr", [
4208
+ (0, import_vue6.h)("th", { style: s4.th }, "\u8D26\u53F7"),
4209
+ (0, import_vue6.h)("th", { style: s4.th }, "\u7528\u6237\u540D"),
4210
+ (0, import_vue6.h)("th", { style: s4.th }, "\u5F52\u5C5E\u90E8\u95E8"),
4211
+ (0, import_vue6.h)("th", { style: s4.th }, "\u7528\u6237\u89D2\u8272"),
4212
+ (0, import_vue6.h)("th", { style: { ...s4.th, width: "90px" } }, "\u72B6\u6001"),
4213
+ (0, import_vue6.h)("th", { style: { ...s4.th, width: "140px" } }, "\u64CD\u4F5C")
4214
+ ])
4215
+ ]),
4216
+ (0, import_vue6.h)(
4217
+ "tbody",
4218
+ loading.value ? [
4219
+ (0, import_vue6.h)("tr", [
4220
+ (0, import_vue6.h)("td", { colspan: 6, style: s4.empty }, "\u52A0\u8F7D\u4E2D\u2026")
4221
+ ])
4222
+ ] : records.value.length === 0 ? [
4223
+ (0, import_vue6.h)("tr", [
4224
+ (0, import_vue6.h)("td", { colspan: 6, style: s4.empty }, "\u6682\u65E0\u6570\u636E")
4225
+ ])
4226
+ ] : records.value.map(
4227
+ (row) => (0, import_vue6.h)("tr", { key: row.userId }, [
4228
+ (0, import_vue6.h)("td", { style: s4.td }, row.username),
4229
+ (0, import_vue6.h)("td", { style: s4.td }, row.name),
4230
+ (0, import_vue6.h)("td", { style: s4.td }, groupLabel(row)),
4231
+ (0, import_vue6.h)("td", { style: s4.td }, roleLabel(row)),
4232
+ (0, import_vue6.h)("td", { style: s4.td }, [
4233
+ (0, import_vue6.h)(
4234
+ "span",
4235
+ {
4236
+ style: {
4237
+ ...s4.badge,
4238
+ ...row.enabled ? s4.badgeOn : s4.badgeOff
4239
+ }
4240
+ },
4241
+ row.enabled ? "\u542F\u7528" : "\u7981\u7528"
4242
+ )
4243
+ ]),
4244
+ (0, import_vue6.h)("td", { style: s4.td }, [
4245
+ (0, import_vue6.h)(
4246
+ "button",
4247
+ {
4248
+ type: "button",
4249
+ style: s4.linkBtn,
4250
+ onClick: () => openEdit(row)
4251
+ },
4252
+ "\u7F16\u8F91"
4253
+ ),
4254
+ (0, import_vue6.h)(
4255
+ "button",
4256
+ {
4257
+ type: "button",
4258
+ style: { ...s4.linkBtn, color: "#d92d20" },
4259
+ onClick: () => askDelete(row)
4260
+ },
4261
+ "\u5220\u9664"
4262
+ )
4263
+ ])
4264
+ ])
4265
+ )
4266
+ )
4267
+ ])
4268
+ ]),
4269
+ (0, import_vue6.h)("div", { style: s4.pagination }, [
4270
+ (0, import_vue6.h)("label", { style: s4.pageSize }, [
4271
+ "\u6BCF\u9875",
4272
+ (0, import_vue6.h)(
4273
+ "select",
4274
+ {
4275
+ style: s4.select,
4276
+ value: pageSize.value,
4277
+ onChange: (e) => {
4278
+ pageSize.value = e.target.value;
4279
+ }
4280
+ },
4281
+ PAGE_SIZE_OPTIONS4.map(
4282
+ (size) => (0, import_vue6.h)("option", { key: size, value: size }, size)
4283
+ )
4284
+ )
4285
+ ]),
4286
+ (0, import_vue6.h)("div", { style: s4.pageBtns }, [
4287
+ (0, import_vue6.h)(
4288
+ "button",
4289
+ {
4290
+ type: "button",
4291
+ style: s4.secondaryBtn,
4292
+ disabled: !hasPreviousPage.value || loading.value,
4293
+ onClick: () => void loadList("previous")
4294
+ },
4295
+ "\u4E0A\u4E00\u9875"
4296
+ ),
4297
+ (0, import_vue6.h)(
4298
+ "button",
4299
+ {
4300
+ type: "button",
4301
+ style: s4.secondaryBtn,
4302
+ disabled: !hasNextPage.value || loading.value,
4303
+ onClick: () => void loadList("next")
4304
+ },
4305
+ "\u4E0B\u4E00\u9875"
4306
+ )
4307
+ ])
4308
+ ]),
4309
+ dialogOpen.value ? (0, import_vue6.h)("div", { style: s4.mask, onClick: closeDialog }, [
4310
+ (0, import_vue6.h)(
4311
+ "div",
4312
+ {
4313
+ style: { ...s4.dialog, maxWidth: "560px" },
4314
+ role: "dialog",
4315
+ "aria-modal": "true",
4316
+ onClick: (e) => e.stopPropagation()
4317
+ },
4318
+ [
4319
+ (0, import_vue6.h)("div", { style: s4.dialogHeader }, [
4320
+ (0, import_vue6.h)(
4321
+ "h3",
4322
+ { style: s4.dialogTitle },
4323
+ editing.value ? "\u7F16\u8F91\u7528\u6237" : "\u65B0\u589E\u7528\u6237"
4324
+ ),
4325
+ (0, import_vue6.h)(
4326
+ "button",
4327
+ {
4328
+ type: "button",
4329
+ style: s4.iconBtn,
4330
+ "aria-label": "\u5173\u95ED",
4331
+ onClick: closeDialog
4332
+ },
4333
+ "\xD7"
4334
+ )
4335
+ ]),
4336
+ (0, import_vue6.h)(
4337
+ "form",
4338
+ {
4339
+ style: s4.form,
4340
+ onSubmit: (e) => void handleSubmit(e)
4341
+ },
4342
+ [
4343
+ formError.value ? (0, import_vue6.h)("div", { style: s4.error }, formError.value) : null,
4344
+ (0, import_vue6.h)("label", { style: s4.field }, [
4345
+ (0, import_vue6.h)("span", { style: s4.label }, "\u8D26\u53F7"),
4346
+ (0, import_vue6.h)("input", {
4347
+ style: s4.input,
4348
+ value: form.username,
4349
+ placeholder: "\u81F3\u5C116\u4F4D\uFF0C\u9700\u542B\u5B57\u6BCD\u548C\u6570\u5B57",
4350
+ required: true,
4351
+ onInput: (e) => {
4352
+ form.username = e.target.value;
4353
+ }
4354
+ })
4355
+ ]),
4356
+ (0, import_vue6.h)("label", { style: s4.field }, [
4357
+ (0, import_vue6.h)("span", { style: s4.label }, "\u7528\u6237\u540D"),
4358
+ (0, import_vue6.h)("input", {
4359
+ style: s4.input,
4360
+ value: form.name,
4361
+ placeholder: "\u8BF7\u8F93\u5165\u7528\u6237\u540D",
4362
+ required: true,
4363
+ onInput: (e) => {
4364
+ form.name = e.target.value;
4365
+ }
4366
+ })
4367
+ ]),
4368
+ (0, import_vue6.h)("label", { style: s4.field }, [
4369
+ (0, import_vue6.h)(
4370
+ "span",
4371
+ { style: s4.label },
4372
+ editing.value ? "\u5BC6\u7801\uFF08\u7559\u7A7A\u5219\u4E0D\u4FEE\u6539\uFF09" : "\u521D\u59CB\u5BC6\u7801"
4373
+ ),
4374
+ (0, import_vue6.h)("input", {
4375
+ style: s4.input,
4376
+ type: "password",
4377
+ value: form.password,
4378
+ placeholder: editing.value ? "\u7559\u7A7A\u8868\u793A\u4E0D\u4FEE\u6539\u5BC6\u7801" : "\u8BF7\u8F93\u5165\u521D\u59CB\u5BC6\u7801",
4379
+ required: !editing.value,
4380
+ autocomplete: "new-password",
4381
+ onInput: (e) => {
4382
+ form.password = e.target.value;
4383
+ }
4384
+ })
4385
+ ]),
4386
+ (0, import_vue6.h)("fieldset", { style: s4.fieldset }, [
4387
+ (0, import_vue6.h)("legend", { style: s4.label }, [
4388
+ "\u5F52\u5C5E\u90E8\u95E8 ",
4389
+ (0, import_vue6.h)("span", { style: s4.required }, "*")
4390
+ ]),
4391
+ (0, import_vue6.h)(
4392
+ "button",
4393
+ {
4394
+ type: "button",
4395
+ style: s4.selectTrigger,
4396
+ "aria-expanded": groupsOpen.value,
4397
+ onClick: toggleGroupsPanel
4398
+ },
4399
+ [
4400
+ (0, import_vue6.h)("span", {
4401
+ style: {
4402
+ ...s4.selectTriggerText,
4403
+ ...form.groupIds.length ? {} : s4.selectPlaceholder
4404
+ }
4405
+ }, selectedGroupSummary()),
4406
+ (0, import_vue6.h)(
4407
+ "span",
4408
+ { style: s4.selectChevron },
4409
+ groupsOpen.value ? "\u25B2" : "\u25BC"
4410
+ )
4411
+ ]
4412
+ ),
4413
+ groupsOpen.value ? (0, import_vue6.h)("div", { style: s4.multiSelect }, [
4414
+ groupsLoading.value ? (0, import_vue6.h)("div", { style: s4.hint }, "\u52A0\u8F7D\u4E2D\u2026") : groups.value.length === 0 ? (0, import_vue6.h)("div", { style: s4.hint }, "\u6682\u65E0\u90E8\u95E8\u6570\u636E") : groups.value.map(
4415
+ (g) => (0, import_vue6.h)(
4416
+ "label",
4417
+ {
4418
+ key: g.groupId,
4419
+ style: s4.checkItem
4420
+ },
4421
+ [
4422
+ (0, import_vue6.h)("input", {
4423
+ type: "checkbox",
4424
+ style: s4.control,
4425
+ checked: form.groupIds.includes(
4426
+ g.groupId
4427
+ ),
4428
+ onChange: () => toggleId("groupIds", g.groupId)
4429
+ }),
4430
+ (0, import_vue6.h)("span", g.name || g.groupId)
4431
+ ]
4432
+ )
4433
+ )
4434
+ ]) : null
4435
+ ]),
4436
+ (0, import_vue6.h)("fieldset", { style: s4.fieldset }, [
4437
+ (0, import_vue6.h)("legend", { style: s4.label }, "\u7528\u6237\u89D2\u8272"),
4438
+ (0, import_vue6.h)("div", { style: s4.multiSelect }, [
4439
+ rolesLoading.value ? (0, import_vue6.h)("div", { style: s4.hint }, "\u52A0\u8F7D\u4E2D\u2026") : roles.value.length === 0 ? (0, import_vue6.h)("div", { style: s4.hint }, "\u6682\u65E0\u89D2\u8272\u6570\u636E") : roles.value.map(
4440
+ (r) => (0, import_vue6.h)(
4441
+ "label",
4442
+ {
4443
+ key: r.roleId,
4444
+ style: s4.checkItem
4445
+ },
4446
+ [
4447
+ (0, import_vue6.h)("input", {
4448
+ type: "checkbox",
4449
+ style: s4.control,
4450
+ checked: form.roleIds.includes(
4451
+ r.roleId
4452
+ ),
4453
+ onChange: () => toggleId("roleIds", r.roleId)
4454
+ }),
4455
+ (0, import_vue6.h)("span", r.name || r.roleId)
4456
+ ]
4457
+ )
4458
+ )
4459
+ ])
4460
+ ]),
4461
+ (0, import_vue6.h)("div", { style: s4.switchRow }, [
4462
+ (0, import_vue6.h)("span", { style: s4.label }, "\u662F\u5426\u542F\u7528"),
4463
+ (0, import_vue6.h)(
4464
+ "button",
4465
+ {
4466
+ type: "button",
4467
+ role: "switch",
4468
+ "aria-checked": form.enabled,
4469
+ style: {
4470
+ ...s4.switchTrack,
4471
+ ...form.enabled ? s4.switchTrackOn : {}
4472
+ },
4473
+ onClick: () => {
4474
+ form.enabled = !form.enabled;
4475
+ }
4476
+ },
4477
+ [
4478
+ (0, import_vue6.h)("span", {
4479
+ style: {
4480
+ ...s4.switchThumb,
4481
+ ...form.enabled ? s4.switchThumbOn : {}
4482
+ }
4483
+ })
4484
+ ]
4485
+ )
4486
+ ]),
4487
+ (0, import_vue6.h)("div", { style: s4.dialogFooter }, [
4488
+ (0, import_vue6.h)(
4489
+ "button",
4490
+ {
4491
+ type: "button",
4492
+ style: s4.secondaryBtn,
4493
+ onClick: closeDialog
4494
+ },
4495
+ "\u53D6\u6D88"
4496
+ ),
4497
+ (0, import_vue6.h)(
4498
+ "button",
4499
+ {
4500
+ type: "submit",
4501
+ style: s4.primaryBtn,
4502
+ disabled: saving.value
4503
+ },
4504
+ saving.value ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58"
4505
+ )
4506
+ ])
4507
+ ]
4508
+ )
4509
+ ]
4510
+ )
4511
+ ]) : null,
4512
+ deletingRow.value ? (0, import_vue6.h)("div", { style: s4.mask, onClick: closeDeleteDialog }, [
4513
+ (0, import_vue6.h)(
4514
+ "div",
4515
+ {
4516
+ style: { ...s4.dialog, maxWidth: "420px" },
4517
+ role: "dialog",
4518
+ "aria-modal": "true",
4519
+ onClick: (e) => e.stopPropagation()
4520
+ },
4521
+ [
4522
+ (0, import_vue6.h)("div", { style: s4.dialogHeader }, [
4523
+ (0, import_vue6.h)("h3", { style: s4.dialogTitle }, "\u786E\u8BA4\u5220\u9664"),
4524
+ (0, import_vue6.h)(
4525
+ "button",
4526
+ {
4527
+ type: "button",
4528
+ style: s4.iconBtn,
4529
+ "aria-label": "\u5173\u95ED",
4530
+ onClick: closeDeleteDialog
4531
+ },
4532
+ "\xD7"
4533
+ )
4534
+ ]),
4535
+ (0, import_vue6.h)("div", { style: s4.confirmBody }, [
4536
+ (0, import_vue6.h)("p", { style: s4.confirmText }, [
4537
+ "\u786E\u8BA4\u5220\u9664\u7528\u6237\u300C",
4538
+ (0, import_vue6.h)("strong", deletingRow.value.name),
4539
+ "\u300D\uFF08",
4540
+ deletingRow.value.username,
4541
+ "\uFF09\u5417\uFF1F\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\u3002"
4542
+ ]),
4543
+ (0, import_vue6.h)("div", { style: s4.dialogFooter }, [
4544
+ (0, import_vue6.h)(
4545
+ "button",
4546
+ {
4547
+ type: "button",
4548
+ style: s4.secondaryBtn,
4549
+ disabled: deleting.value,
4550
+ onClick: closeDeleteDialog
4551
+ },
4552
+ "\u53D6\u6D88"
4553
+ ),
4554
+ (0, import_vue6.h)(
4555
+ "button",
4556
+ {
4557
+ type: "button",
4558
+ style: s4.dangerBtn,
4559
+ disabled: deleting.value,
4560
+ onClick: () => void confirmDelete()
4561
+ },
4562
+ deleting.value ? "\u5220\u9664\u4E2D\u2026" : "\u786E\u8BA4\u5220\u9664"
4563
+ )
4564
+ ])
4565
+ ])
4566
+ ]
4567
+ )
4568
+ ]) : null
4569
+ ]);
4570
+ }
4571
+ });
4572
+
3437
4573
  // src/vue/SystemAdmin.ts
3438
- var import_vue6 = require("vue");
4574
+ var import_vue7 = require("vue");
3439
4575
 
3440
4576
  // src/admin/menu.ts
3441
4577
  var SYSTEM_ADMIN_MENU = {
3442
4578
  key: "system",
3443
4579
  label: "\u7CFB\u7EDF\u7BA1\u7406",
3444
4580
  children: [
4581
+ { key: "user", label: "\u7528\u6237\u7BA1\u7406" },
4582
+ { key: "role", label: "\u89D2\u8272\u7BA1\u7406" },
3445
4583
  { key: "menu", label: "\u83DC\u5355\u7BA1\u7406" },
3446
- { key: "resource", label: "\u6743\u9650\u70B9\u7BA1\u7406" },
3447
- { key: "role", label: "\u89D2\u8272\u7BA1\u7406" }
4584
+ { key: "resource", label: "\u6743\u9650\u70B9\u7BA1\u7406" }
3448
4585
  ]
3449
4586
  };
3450
4587
  var SYSTEM_ADMIN_DEFAULT_KEY = "menu";
3451
4588
 
3452
4589
  // src/vue/SystemAdmin.ts
3453
- var s4 = {
4590
+ var s5 = {
3454
4591
  root: {
3455
4592
  display: "flex",
3456
4593
  minHeight: "560px",
@@ -3524,7 +4661,7 @@ var s4 = {
3524
4661
  overflow: "auto"
3525
4662
  }
3526
4663
  };
3527
- var SystemAdmin = (0, import_vue6.defineComponent)({
4664
+ var SystemAdmin = (0, import_vue7.defineComponent)({
3528
4665
  name: "SystemAdmin",
3529
4666
  props: {
3530
4667
  menuApi: {
@@ -3539,6 +4676,10 @@ var SystemAdmin = (0, import_vue6.defineComponent)({
3539
4676
  type: Object,
3540
4677
  required: true
3541
4678
  },
4679
+ userApi: {
4680
+ type: Object,
4681
+ required: true
4682
+ },
3542
4683
  defaultActiveKey: {
3543
4684
  type: String,
3544
4685
  default: SYSTEM_ADMIN_DEFAULT_KEY
@@ -3557,17 +4698,17 @@ var SystemAdmin = (0, import_vue6.defineComponent)({
3557
4698
  activeKeyChange: (_key) => true
3558
4699
  },
3559
4700
  setup(props, { emit, slots }) {
3560
- const innerKey = (0, import_vue6.ref)(props.defaultActiveKey);
3561
- (0, import_vue6.watch)(
4701
+ const innerKey = (0, import_vue7.ref)(props.defaultActiveKey);
4702
+ (0, import_vue7.watch)(
3562
4703
  () => props.defaultActiveKey,
3563
4704
  (value) => {
3564
4705
  if (props.activeKey === void 0) innerKey.value = value;
3565
4706
  }
3566
4707
  );
3567
- const activeKey = (0, import_vue6.computed)(
4708
+ const activeKey = (0, import_vue7.computed)(
3568
4709
  () => props.activeKey ?? innerKey.value
3569
4710
  );
3570
- const activeLabel = (0, import_vue6.computed)(
4711
+ const activeLabel = (0, import_vue7.computed)(
3571
4712
  () => SYSTEM_ADMIN_MENU.children.find((item) => item.key === activeKey.value)?.label ?? ""
3572
4713
  );
3573
4714
  function setActiveKey(key) {
@@ -3575,22 +4716,22 @@ var SystemAdmin = (0, import_vue6.defineComponent)({
3575
4716
  emit("update:activeKey", key);
3576
4717
  emit("activeKeyChange", key);
3577
4718
  }
3578
- return () => (0, import_vue6.h)("div", { style: s4.root }, [
3579
- (0, import_vue6.h)("aside", { style: s4.sidebar }, [
3580
- (0, import_vue6.h)("div", { style: s4.sidebarTitle }, props.title),
3581
- (0, import_vue6.h)(
4719
+ return () => (0, import_vue7.h)("div", { style: s5.root }, [
4720
+ (0, import_vue7.h)("aside", { style: s5.sidebar }, [
4721
+ (0, import_vue7.h)("div", { style: s5.sidebarTitle }, props.title),
4722
+ (0, import_vue7.h)(
3582
4723
  "nav",
3583
- { style: s4.nav },
4724
+ { style: s5.nav },
3584
4725
  SYSTEM_ADMIN_MENU.children.map((item) => {
3585
4726
  const active = item.key === activeKey.value;
3586
- return (0, import_vue6.h)(
4727
+ return (0, import_vue7.h)(
3587
4728
  "button",
3588
4729
  {
3589
4730
  key: item.key,
3590
4731
  type: "button",
3591
4732
  style: {
3592
- ...s4.navItem,
3593
- ...active ? s4.navItemActive : {}
4733
+ ...s5.navItem,
4734
+ ...active ? s5.navItemActive : {}
3594
4735
  },
3595
4736
  onClick: () => setActiveKey(item.key)
3596
4737
  },
@@ -3599,20 +4740,20 @@ var SystemAdmin = (0, import_vue6.defineComponent)({
3599
4740
  })
3600
4741
  )
3601
4742
  ]),
3602
- (0, import_vue6.h)("main", { style: s4.content }, [
3603
- (0, import_vue6.h)("div", { style: s4.contentHeader }, [
3604
- (0, import_vue6.h)("div", { style: s4.breadcrumb }, [
3605
- (0, import_vue6.h)("span", { style: s4.breadcrumbParent }, props.title),
3606
- (0, import_vue6.h)("span", { style: s4.breadcrumbSep }, "/"),
3607
- (0, import_vue6.h)("span", { style: s4.breadcrumbCurrent }, activeLabel.value)
4743
+ (0, import_vue7.h)("main", { style: s5.content }, [
4744
+ (0, import_vue7.h)("div", { style: s5.contentHeader }, [
4745
+ (0, import_vue7.h)("div", { style: s5.breadcrumb }, [
4746
+ (0, import_vue7.h)("span", { style: s5.breadcrumbParent }, props.title),
4747
+ (0, import_vue7.h)("span", { style: s5.breadcrumbSep }, "/"),
4748
+ (0, import_vue7.h)("span", { style: s5.breadcrumbCurrent }, activeLabel.value)
3608
4749
  ]),
3609
4750
  slots.toolbarExtra?.()
3610
4751
  ]),
3611
- (0, import_vue6.h)("div", { style: s4.panel }, [
3612
- activeKey.value === "menu" ? (0, import_vue6.h)(MenuManager, { api: props.menuApi, title: "\u83DC\u5355\u7BA1\u7406" }) : activeKey.value === "resource" ? (0, import_vue6.h)(ResourceManager, {
4752
+ (0, import_vue7.h)("div", { style: s5.panel }, [
4753
+ activeKey.value === "menu" ? (0, import_vue7.h)(MenuManager, { api: props.menuApi, title: "\u83DC\u5355\u7BA1\u7406" }) : activeKey.value === "resource" ? (0, import_vue7.h)(ResourceManager, {
3613
4754
  api: props.resourceApi,
3614
4755
  title: "\u6743\u9650\u70B9\u7BA1\u7406"
3615
- }) : (0, import_vue6.h)(RoleManager, { api: props.roleApi, title: "\u89D2\u8272\u7BA1\u7406" })
4756
+ }) : activeKey.value === "role" ? (0, import_vue7.h)(RoleManager, { api: props.roleApi, title: "\u89D2\u8272\u7BA1\u7406" }) : (0, import_vue7.h)(UserManager, { api: props.userApi, title: "\u7528\u6237\u7BA1\u7406" })
3616
4757
  ])
3617
4758
  ])
3618
4759
  ]);
@@ -3645,15 +4786,18 @@ var SystemAdmin = (0, import_vue6.defineComponent)({
3645
4786
  SYSTEM_ADMIN_DEFAULT_KEY,
3646
4787
  SYSTEM_ADMIN_MENU,
3647
4788
  SystemAdmin,
4789
+ UserManager,
3648
4790
  appendQueryParam,
3649
4791
  buildCreateBody,
3650
4792
  buildCreateMenuBody,
3651
4793
  buildCreateRoleBody,
4794
+ buildCreateUserBody,
3652
4795
  buildPermissionTreeIndex,
3653
4796
  buildSavePermissionsBody,
3654
4797
  buildUpdateBody,
3655
4798
  buildUpdateMenuBody,
3656
4799
  buildUpdateRoleBody,
4800
+ buildUpdateUserBody,
3657
4801
  collectTreeResourceIds,
3658
4802
  countCheckedDescendants,
3659
4803
  createAuthorizationResourceApi,
@@ -3662,6 +4806,7 @@ var SystemAdmin = (0, import_vue6.defineComponent)({
3662
4806
  createPermissionPlugin,
3663
4807
  createPermissionStore,
3664
4808
  createSystemRoleApi,
4809
+ createSystemUserApi,
3665
4810
  createVPermission,
3666
4811
  extractPagination,
3667
4812
  extractRecords,
@@ -3674,12 +4819,16 @@ var SystemAdmin = (0, import_vue6.defineComponent)({
3674
4819
  mapMenuResource,
3675
4820
  mapPermissionTreeNode,
3676
4821
  mapRolePermissions,
4822
+ mapSystemGroupOption,
3677
4823
  mapSystemRole,
4824
+ mapSystemRoleOption,
4825
+ mapSystemUser,
3678
4826
  resolveMenuDepth,
3679
4827
  snowyflake,
3680
4828
  togglePermissionCheck,
3681
4829
  useHasPermission,
3682
4830
  useHasRole,
3683
- usePermission
4831
+ usePermission,
4832
+ validateUsername
3684
4833
  });
3685
4834
  //# sourceMappingURL=index.cjs.map