diff --git a/ui/console-src/modules/system/users/UserDetail.vue b/ui/console-src/modules/system/users/UserDetail.vue index 2355ac07f..5cdd44883 100644 --- a/ui/console-src/modules/system/users/UserDetail.vue +++ b/ui/console-src/modules/system/users/UserDetail.vue @@ -2,40 +2,36 @@ import { apiClient } from "@/utils/api-client"; import { VButton, - VTabbar, VDropdown, VDropdownItem, + VTabbar, } from "@halo-dev/components"; -import { computed, provide, ref, type Ref } from "vue"; +import { + computed, + markRaw, + onMounted, + provide, + type Ref, + ref, + toRaw, +} from "vue"; import { useRoute } from "vue-router"; -import type { DetailedUser } from "@halo-dev/api-client"; import UserEditingModal from "./components/UserEditingModal.vue"; import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue"; import { usePermission } from "@/utils/permission"; import { useQuery } from "@tanstack/vue-query"; import { useI18n } from "vue-i18n"; import UserAvatar from "@/components/user-avatar/UserAvatar.vue"; -import type { Raw } from "vue"; -import type { Component } from "vue"; -import { markRaw } from "vue"; import DetailTab from "./tabs/Detail.vue"; import { useRouteQuery } from "@vueuse/router"; import { useUserStore } from "@/stores/user"; +import { usePluginModuleStore } from "@/stores/plugin"; +import type { PluginModule, UserTab } from "@halo-dev/console-shared"; const { currentUserHasPermission } = usePermission(); const { t } = useI18n(); const { currentUser } = useUserStore(); -interface UserTab { - id: string; - label: string; - component: Raw; - props?: Record; - permissions?: string[]; - priority: number; - hidden?: boolean; -} - const editingModal = ref(false); const passwordChangeModal = ref(false); @@ -56,25 +52,44 @@ const { enabled: computed(() => !!params.name), }); -provide>("user", user); - -const tabs: UserTab[] = [ +const tabs = ref([ { id: "detail", label: t("core.user.detail.tabs.detail"), component: markRaw(DetailTab), priority: 10, }, -]; +]); -const activeTab = useRouteQuery("tab", tabs[0].id, { +// Collect user:detail:tabs:create extension points +onMounted(() => { + const { pluginModules } = usePluginModuleStore(); + + pluginModules.forEach((pluginModule: PluginModule) => { + const { extensionPoints } = pluginModule; + if (!extensionPoints?.["user:detail:tabs:create"]) { + return; + } + + const providers = extensionPoints["user:detail:tabs:create"]() as UserTab[]; + + tabs.value.push(...providers); + }); +}); + +const activeTab = useRouteQuery("tab", tabs.value[0].id, { mode: "push", }); provide>("activeTab", activeTab); const tabbarItems = computed(() => { - return tabs.map((tab) => ({ id: tab.id, label: tab.label })); + return toRaw(tabs) + .value.sort((a, b) => a.priority - b.priority) + .map((tab) => ({ + id: tab.id, + label: tab.label, + })); }); function handleRouteToUC() { @@ -142,7 +157,8 @@ function handleRouteToUC() { diff --git a/ui/console-src/modules/system/users/tabs/Detail.vue b/ui/console-src/modules/system/users/tabs/Detail.vue index 8fd1a2f9d..cad29bc0e 100644 --- a/ui/console-src/modules/system/users/tabs/Detail.vue +++ b/ui/console-src/modules/system/users/tabs/Detail.vue @@ -5,13 +5,13 @@ import { VDescriptionItem, VTag, } from "@halo-dev/components"; -import type { Ref } from "vue"; -import { inject } from "vue"; import type { DetailedUser } from "@halo-dev/api-client"; import { rbacAnnotations } from "@/constants/annotations"; import { formatDatetime } from "@/utils/date"; -const user = inject>("user"); +withDefaults(defineProps<{ user?: DetailedUser }>(), { + user: undefined, +});