diff --git a/ui/console-src/modules/system/users/UserList.vue b/ui/console-src/modules/system/users/UserList.vue index 6e930ce2d..631493dba 100644 --- a/ui/console-src/modules/system/users/UserList.vue +++ b/ui/console-src/modules/system/users/UserList.vue @@ -24,6 +24,7 @@ import { } from "@halo-dev/components"; import { useQuery } from "@tanstack/vue-query"; import { useRouteQuery } from "@vueuse/router"; +import { chunk } from "lodash-es"; import { computed, onMounted, ref, watch } from "vue"; import { useI18n } from "vue-i18n"; import UserCreationModal from "./components/UserCreationModal.vue"; @@ -137,6 +138,71 @@ const handleDeleteInBatch = async () => { }); }; +const handleUserBatchOperation = async ({ + filterCondition, + apiMethod, + successMessageKey, + emptyMessageKey, +}) => { + const filteredUserNames = selectedUserNames.value.filter((name) => { + if (name === userStore.currentUser?.metadata.name) return false; + const user = users.value?.find((u) => u.user.metadata.name === name); + return user && filterCondition(user.user); + }); + + if (!filteredUserNames.length) { + Toast.info(t(emptyMessageKey)); + return; + } + + const chunks = chunk(filteredUserNames, 5); + for (const chunk of chunks) { + await Promise.all(chunk.map((name) => apiMethod(name))); + } + + await refetch(); + selectedUserNames.value.length = 0; + Toast.success(t(successMessageKey)); +}; + +const handleEnableInBatch = async () => { + Dialog.warning({ + title: t("core.user.operations.enable_in_batch.title"), + description: t("core.user.operations.enable_in_batch.description"), + confirmType: "primary", + confirmText: t("core.common.buttons.confirm"), + cancelText: t("core.common.buttons.cancel"), + onConfirm: async () => { + await handleUserBatchOperation({ + filterCondition: (user) => !!user.spec.disabled, + apiMethod: (name) => + consoleApiClient.user.enableUser({ username: name }), + successMessageKey: "core.common.toast.enable_success", + emptyMessageKey: "core.common.toast.no_users_to_enable", + }); + }, + }); +}; + +const handleDisableInBatch = async () => { + Dialog.warning({ + title: t("core.user.operations.disable_in_batch.title"), + description: t("core.user.operations.disable_in_batch.description"), + confirmType: "danger", + confirmText: t("core.common.buttons.confirm"), + cancelText: t("core.common.buttons.cancel"), + onConfirm: async () => { + await handleUserBatchOperation({ + filterCondition: (user) => !user.spec.disabled, + apiMethod: (name) => + consoleApiClient.user.disableUser({ username: name }), + successMessageKey: "core.common.toast.disable_success", + emptyMessageKey: "core.common.toast.no_users_to_disable", + }); + }, + }); +}; + watch(selectedUserNames, (newValue) => { checkedAll.value = newValue.length === @@ -242,6 +308,12 @@ function onCreationModalClose() {
+ + {{ $t("core.common.buttons.disable") }} + + + {{ $t("core.common.buttons.enable") }} + {{ $t("core.common.buttons.delete") }} diff --git a/ui/src/locales/en.yaml b/ui/src/locales/en.yaml index 05937d239..83dc27aad 100644 --- a/ui/src/locales/en.yaml +++ b/ui/src/locales/en.yaml @@ -1124,11 +1124,21 @@ core: enable: title: Enable description: Are you sure you want to enable this user? + enable_in_batch: + title: Enable + description: >- + Are you sure you want to enable the selected users? They will be able + to log in again after being enabled. disable: title: Disable description: >- Are you sure you want to disable this user? This user will not be able to log in after being disabled + disable_in_batch: + title: Disable + description: >- + Are you sure you want to disable the selected users? They will no longer + be able to log in after being disabled. filters: role: label: Role @@ -1951,6 +1961,8 @@ core: unknown_error: Unknown error disable_success: Disabled successfully enable_success: Enabled successfully + no_users_to_enable: All selected users are already enabled + no_users_to_disable: All selected users are already disabled dialog: titles: tip: Tip diff --git a/ui/src/locales/zh-CN.yaml b/ui/src/locales/zh-CN.yaml index b5453f761..120ffc53d 100644 --- a/ui/src/locales/zh-CN.yaml +++ b/ui/src/locales/zh-CN.yaml @@ -1055,9 +1055,15 @@ core: enable: title: 取消禁用 description: 确定取消禁用该用户吗? + enable_in_batch: + title: 启用 + description: 确定要启用所选用户吗?启用后该用户将可以重新登录系统 disable: title: 禁用 - description: 确定禁用该用户吗?禁用之后该用户将无法登录系统 + description: 确定禁用该用户吗?禁用后该用户将无法登录系统 + disable_in_batch: + title: 禁用 + description: 确定要禁用所选用户吗?禁用后这些用户将无法登录系统 filters: role: label: 角色 @@ -1815,7 +1821,9 @@ core: server_internal_error: 服务器内部错误 unknown_error: 未知错误 disable_success: 禁用成功 - enable_success: 啟用成功 + enable_success: 启用成功 + no_users_to_enable: 所有选中的用户已启用 + no_users_to_disable: 所有选中的用户已停用 dialog: titles: tip: 提示 diff --git a/ui/src/locales/zh-TW.yaml b/ui/src/locales/zh-TW.yaml index 4009f5a6e..7d7195e9b 100644 --- a/ui/src/locales/zh-TW.yaml +++ b/ui/src/locales/zh-TW.yaml @@ -1040,9 +1040,15 @@ core: enable: title: 取消停用 description: 確定要取消停用該用戶嗎? + enable_in_batch: + title: 启用 + description: 確定要启用所選用戶嗎?啟用後該用戶將可以重新登入系統 disable: title: 停用 description: 確定要停用該用戶嗎?停用後該用戶將無法登入系統 + disable_in_batch: + title: 停用 + description: 確定要停用所選用戶嗎?停用後這些用戶將無法登入系統 filters: role: label: 角色 @@ -1801,6 +1807,8 @@ core: unknown_error: 未知錯誤 disable_success: 禁用成功 enable_success: 啟用成功 + no_users_to_enable: 所有選中的用戶都已啟用 + no_users_to_disable: 所有選中的用戶都已停用 dialog: titles: tip: 提示