Refactor user batch enable/disable logic and update i18n (#7647)

pull/7650/head v2.21.4
Ryan Wang 2025-07-31 22:04:50 +08:00 committed by GitHub
parent 4119e36cd8
commit 87cb00a2f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 88 deletions

View File

@ -138,70 +138,56 @@ const handleDeleteInBatch = async () => {
}); });
}; };
const handleUserBatchOperation = async ({ function handleEnableOrDisableInBatch(operation: "enable" | "disable") {
filterCondition, const operations = {
apiMethod, enable: {
successMessageKey, title: t("core.user.operations.enable_in_batch.title"),
emptyMessageKey, description: t("core.user.operations.enable_in_batch.description"),
}) => { request: (name: string) =>
const filteredUserNames = selectedUserNames.value.filter((name) => { consoleApiClient.user.enableUser({ username: name }),
if (name === userStore.currentUser?.metadata.name) return false; condition: (user: User) => user.spec.disabled,
const user = users.value?.find((u) => u.user.metadata.name === name); message: t("core.common.toast.enable_success"),
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",
});
}, },
}); disable: {
}; title: t("core.user.operations.disable_in_batch.title"),
description: t("core.user.operations.disable_in_batch.description"),
request: (name: string) =>
consoleApiClient.user.disableUser({ username: name }),
condition: (user: User) => !user.spec.disabled,
message: t("core.common.toast.disable_success"),
},
};
const operationConfig = operations[operation];
const handleDisableInBatch = async () => {
Dialog.warning({ Dialog.warning({
title: t("core.user.operations.disable_in_batch.title"), title: operationConfig.title,
description: t("core.user.operations.disable_in_batch.description"), description: operationConfig.description,
confirmType: "danger", confirmType: "danger",
confirmText: t("core.common.buttons.confirm"), confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"), cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => { onConfirm: async () => {
await handleUserBatchOperation({ const filteredUserNames = selectedUserNames.value.filter((name) => {
filterCondition: (user) => !user.spec.disabled, if (name === userStore.currentUser?.metadata.name) return false;
apiMethod: (name) => const user = users.value?.find((u) => u.user.metadata.name === name);
consoleApiClient.user.disableUser({ username: name }), return user && operationConfig.condition(user.user);
successMessageKey: "core.common.toast.disable_success",
emptyMessageKey: "core.common.toast.no_users_to_disable",
}); });
const chunks = chunk(filteredUserNames, 5);
for (const chunk of chunks) {
await Promise.all(chunk.map((name) => operationConfig.request(name)));
}
await refetch();
selectedUserNames.value.length = 0;
checkedAll.value = false;
Toast.success(operationConfig.message);
}, },
}); });
}; }
watch(selectedUserNames, (newValue) => { watch(selectedUserNames, (newValue) => {
checkedAll.value = checkedAll.value =
@ -308,10 +294,10 @@ function onCreationModalClose() {
<div class="flex w-full flex-1 items-center sm:w-auto"> <div class="flex w-full flex-1 items-center sm:w-auto">
<SearchInput v-if="!selectedUserNames.length" v-model="keyword" /> <SearchInput v-if="!selectedUserNames.length" v-model="keyword" />
<VSpace v-else> <VSpace v-else>
<VButton type="secondary" @click="handleDisableInBatch"> <VButton @click="handleEnableOrDisableInBatch('disable')">
{{ $t("core.common.buttons.disable") }} {{ $t("core.common.buttons.disable") }}
</VButton> </VButton>
<VButton type="secondary" @click="handleEnableInBatch"> <VButton @click="handleEnableOrDisableInBatch('enable')">
{{ $t("core.common.buttons.enable") }} {{ $t("core.common.buttons.enable") }}
</VButton> </VButton>
<VButton type="danger" @click="handleDeleteInBatch"> <VButton type="danger" @click="handleDeleteInBatch">

View File

@ -64,12 +64,16 @@ export function useUserEnableDisable() {
enable: { enable: {
title: t("core.user.operations.enable.title"), title: t("core.user.operations.enable.title"),
description: t("core.user.operations.enable.description"), description: t("core.user.operations.enable.description"),
value: false, request: (name: string) =>
consoleApiClient.user.enableUser({ username: name }),
message: t("core.common.toast.enable_success"),
}, },
disable: { disable: {
title: t("core.user.operations.disable.title"), title: t("core.user.operations.disable.title"),
description: t("core.user.operations.disable.description"), description: t("core.user.operations.disable.description"),
value: true, request: (name: string) =>
consoleApiClient.user.disableUser({ username: name }),
message: t("core.common.toast.disable_success"),
}, },
}; };
@ -83,17 +87,9 @@ export function useUserEnableDisable() {
cancelText: t("core.common.buttons.cancel"), cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => { onConfirm: async () => {
try { try {
if (operation == "enable") { await operationConfig.request(name);
await consoleApiClient.user.enableUser({
username: name,
});
} else {
await consoleApiClient.user.disableUser({
username: name,
});
}
Toast.success(t("core.common.toast.operation_success")); Toast.success(operationConfig.message);
onSuccess?.(); onSuccess?.();
} catch (e) { } catch (e) {
console.error("Failed to enable or disable user", e); console.error("Failed to enable or disable user", e);

View File

@ -1142,22 +1142,20 @@ core:
title: Grant permission title: Grant permission
enable: enable:
title: Enable title: Enable
description: Are you sure you want to enable this user? description: >-
Are you sure you want to enable this user? Once enabled, the user will be able to log back into the system.
enable_in_batch: enable_in_batch:
title: Enable title: Enable
description: >- description: >-
Are you sure you want to enable the selected users? They will be able Are you sure you want to enable the selected users? Once enabled, these users will be able to log back into the system.
to log in again after being enabled.
disable: disable:
title: Disable title: Disable
description: >- description: >-
Are you sure you want to disable this user? This user will not be able Are you sure you want to disable this user? Once disabled, the user will no longer be able to log in.
to log in after being disabled
disable_in_batch: disable_in_batch:
title: Disable title: Disable
description: >- description: >-
Are you sure you want to disable the selected users? They will no longer Are you sure you want to disable the selected users? Once disabled, these users will no longer be able to log in.
be able to log in after being disabled.
filters: filters:
role: role:
label: Role label: Role
@ -1981,8 +1979,6 @@ core:
unknown_error: Unknown error unknown_error: Unknown error
disable_success: Disabled successfully disable_success: Disabled successfully
enable_success: Enabled 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: dialog:
titles: titles:
tip: Tip tip: Tip

View File

@ -1070,14 +1070,14 @@ core:
grant_permission: grant_permission:
title: 分配角色 title: 分配角色
enable: enable:
title: 取消禁 title:
description: 确定取消禁用该用户吗? description: 确定要启用该用户吗?启用之后该用户将可以重新登录系统
enable_in_batch: enable_in_batch:
title: 启用 title: 启用
description: 确定要启用所选用户吗?启用后用户将可以重新登录系统 description: 确定要启用所选用户吗?启用后这些用户将可以重新登录系统
disable: disable:
title: 禁用 title: 禁用
description: 确定禁用该用户吗?禁用后该用户将无法登录系统 description: 确定禁用该用户吗?禁用后该用户将无法登录系统
disable_in_batch: disable_in_batch:
title: 禁用 title: 禁用
description: 确定要禁用所选用户吗?禁用后这些用户将无法登录系统 description: 确定要禁用所选用户吗?禁用后这些用户将无法登录系统
@ -1840,8 +1840,6 @@ core:
unknown_error: 未知错误 unknown_error: 未知错误
disable_success: 禁用成功 disable_success: 禁用成功
enable_success: 启用成功 enable_success: 启用成功
no_users_to_enable: 所有选中的用户已启用
no_users_to_disable: 所有选中的用户已停用
dialog: dialog:
titles: titles:
tip: 提示 tip: 提示

View File

@ -1055,11 +1055,11 @@ core:
grant_permission: grant_permission:
title: 分配角色 title: 分配角色
enable: enable:
title: 取消停 title:
description: 確定要取消停用該用戶嗎? description: 確定要啟用該用戶嗎?啟用後該用戶將可以重新登入系統
enable_in_batch: enable_in_batch:
title: 启用 title: 启用
description: 確定要启用所選用戶嗎?啟用後該用戶將可以重新登入系統 description: 確定要啟用所選用戶嗎?啟用後這些用戶將可以重新登入系統
disable: disable:
title: 停用 title: 停用
description: 確定要停用該用戶嗎?停用後該用戶將無法登入系統 description: 確定要停用該用戶嗎?停用後該用戶將無法登入系統
@ -1825,8 +1825,6 @@ core:
unknown_error: 未知錯誤 unknown_error: 未知錯誤
disable_success: 禁用成功 disable_success: 禁用成功
enable_success: 啟用成功 enable_success: 啟用成功
no_users_to_enable: 所有選中的用戶都已啟用
no_users_to_disable: 所有選中的用戶都已停用
dialog: dialog:
titles: titles:
tip: 提示 tip: 提示