feat: add grant permission and user deletion features to user detail page (#6963)

What type of PR is this?

/area ui
/kind improvement
/milestone 2.20.x

What this PR does / why we need it:

期望支持在用户详情页面支持变更用户角色及删除用户 。

Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/6944

Special notes for your reviewer:

Does this PR introduce a user-facing change?
```release-note
支持在用户详情页面支持变更用户角色及删除用户 。
```
pull/6972/head^2
Nancy 2024-10-30 12:50:39 +08:00 committed by GitHub
parent 77548ec5a7
commit 2c4e85f40b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 4 deletions

View File

@ -3,8 +3,11 @@ import UserAvatar from "@/components/user-avatar/UserAvatar.vue";
import { usePluginModuleStore } from "@/stores/plugin"; import { usePluginModuleStore } from "@/stores/plugin";
import { useUserStore } from "@/stores/user"; import { useUserStore } from "@/stores/user";
import { usePermission } from "@/utils/permission"; import { usePermission } from "@/utils/permission";
import { consoleApiClient } from "@halo-dev/api-client"; import type { User } from "@halo-dev/api-client";
import { consoleApiClient, coreApiClient } from "@halo-dev/api-client";
import { import {
Dialog,
Toast,
VButton, VButton,
VDropdown, VDropdown,
VDropdownItem, VDropdownItem,
@ -23,7 +26,8 @@ import {
type Ref, type Ref,
} from "vue"; } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useRoute } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import GrantPermissionModal from "./components/GrantPermissionModal.vue";
import UserEditingModal from "./components/UserEditingModal.vue"; import UserEditingModal from "./components/UserEditingModal.vue";
import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue"; import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue";
import DetailTab from "./tabs/Detail.vue"; import DetailTab from "./tabs/Detail.vue";
@ -34,9 +38,9 @@ const { currentUser } = useUserStore();
const editingModal = ref(false); const editingModal = ref(false);
const passwordChangeModal = ref(false); const passwordChangeModal = ref(false);
const grantPermissionModal = ref<boolean>(false);
const { params } = useRoute(); const { params } = useRoute();
const router = useRouter();
const { const {
data: user, data: user,
isLoading, isLoading,
@ -97,6 +101,27 @@ const tabbarItems = computed(() => {
})); }));
}); });
const handleDelete = async (userToDelete: User) => {
Dialog.warning({
title: t("core.user.operations.delete.title"),
description: t("core.common.dialog.descriptions.cannot_be_recovered"),
confirmType: "danger",
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
try {
await coreApiClient.user.deleteUser({
name: userToDelete.metadata.name,
});
Toast.success(t("core.common.toast.delete_success"));
router.push({ name: "Users" });
} catch (e) {
console.error("Failed to delete user", e);
}
},
});
};
function handleRouteToUC() { function handleRouteToUC() {
window.location.href = "/uc"; window.location.href = "/uc";
} }
@ -105,6 +130,10 @@ function onPasswordChangeModalClose() {
passwordChangeModal.value = false; passwordChangeModal.value = false;
refetch(); refetch();
} }
function onGrantPermissionModalClose() {
grantPermissionModal.value = false;
refetch();
}
</script> </script>
<template> <template>
<UserEditingModal <UserEditingModal
@ -119,6 +148,12 @@ function onPasswordChangeModalClose() {
@close="onPasswordChangeModalClose" @close="onPasswordChangeModalClose"
/> />
<GrantPermissionModal
v-if="grantPermissionModal"
:user="user?.user"
@close="onGrantPermissionModalClose"
/>
<header class="bg-white"> <header class="bg-white">
<div class="p-4"> <div class="p-4">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
@ -154,6 +189,16 @@ function onPasswordChangeModalClose() {
<VDropdownItem @click="passwordChangeModal = true"> <VDropdownItem @click="passwordChangeModal = true">
{{ $t("core.user.detail.actions.change_password.title") }} {{ $t("core.user.detail.actions.change_password.title") }}
</VDropdownItem> </VDropdownItem>
<VDropdownItem @click="grantPermissionModal = true">
{{ $t("core.user.detail.actions.grant_permission.title") }}
</VDropdownItem>
<VDropdownItem
v-if="user?.user"
type="danger"
@click="handleDelete(user.user)"
>
{{ $t("core.common.buttons.delete") }}
</VDropdownItem>
</template> </template>
</VDropdown> </VDropdown>
</div> </div>

View File

@ -1068,6 +1068,8 @@ core:
title: Update profile title: Update profile
change_password: change_password:
title: Change password title: Change password
grant_permission:
title: Grant permission
profile: profile:
title: Profile title: Profile
fields: fields:

View File

@ -998,6 +998,8 @@ core:
title: 修改资料 title: 修改资料
change_password: change_password:
title: 修改密码 title: 修改密码
grant_permission:
title: 分配角色
profile: profile:
title: 个人中心 title: 个人中心
fields: fields:

View File

@ -975,6 +975,8 @@ core:
title: 修改資料 title: 修改資料
change_password: change_password:
title: 修改密碼 title: 修改密碼
grant_permission:
title: 分配角色
profile: profile:
title: 個人中心 title: 個人中心
fields: fields: