perf: tenant-dropdown
parent
56b4751be1
commit
5b4846e93d
|
@ -1,11 +1,13 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { NotificationItem } from '@vben/layouts';
|
import type { NotificationItem } from '@vben/layouts';
|
||||||
|
|
||||||
|
import type { SystemTenantApi } from '#/api/system/tenant';
|
||||||
|
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
import { computed, onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { AuthenticationLoginExpiredModal, useVbenModal } from '@vben/common-ui';
|
import { AuthenticationLoginExpiredModal, useVbenModal } from '@vben/common-ui';
|
||||||
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
||||||
import { useWatermark } from '@vben/hooks';
|
import { useTabs, useWatermark } from '@vben/hooks';
|
||||||
import {
|
import {
|
||||||
AntdProfileOutlined,
|
AntdProfileOutlined,
|
||||||
BookOpenText,
|
BookOpenText,
|
||||||
|
@ -16,30 +18,37 @@ import {
|
||||||
BasicLayout,
|
BasicLayout,
|
||||||
LockScreen,
|
LockScreen,
|
||||||
Notification,
|
Notification,
|
||||||
|
TenantDropdown,
|
||||||
UserDropdown,
|
UserDropdown,
|
||||||
} from '@vben/layouts';
|
} from '@vben/layouts';
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||||
import { formatDateTime, openWindow } from '@vben/utils';
|
import { formatDateTime, openWindow } from '@vben/utils';
|
||||||
|
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getUnreadNotifyMessageCount,
|
getUnreadNotifyMessageCount,
|
||||||
getUnreadNotifyMessageList,
|
getUnreadNotifyMessageList,
|
||||||
updateAllNotifyMessageRead,
|
updateAllNotifyMessageRead,
|
||||||
updateNotifyMessageRead,
|
updateNotifyMessageRead,
|
||||||
} from '#/api/system/notify/message';
|
} from '#/api/system/notify/message';
|
||||||
|
import { getSimpleTenantList } from '#/api/system/tenant';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
import { router } from '#/router';
|
import { router } from '#/router';
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
import LoginForm from '#/views/_core/authentication/login.vue';
|
import LoginForm from '#/views/_core/authentication/login.vue';
|
||||||
|
|
||||||
import Help from './components/help.vue';
|
import Help from './components/help.vue';
|
||||||
import TenantDropdown from './components/tenant-dropdown.vue';
|
|
||||||
|
// 租户列表
|
||||||
|
const tenants = ref<SystemTenantApi.Tenant[]>([]);
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
const { destroyWatermark, updateWatermark } = useWatermark();
|
const { destroyWatermark, updateWatermark } = useWatermark();
|
||||||
|
const { closeOtherTabs, refreshTab } = useTabs();
|
||||||
|
|
||||||
const notifications = ref<NotificationItem[]>([]);
|
const notifications = ref<NotificationItem[]>([]);
|
||||||
const unreadCount = ref(0);
|
const unreadCount = ref(0);
|
||||||
|
@ -148,10 +157,33 @@ function handleNotificationOpen(open: boolean) {
|
||||||
handleNotificationGetUnreadCount();
|
handleNotificationGetUnreadCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取租户列表 */
|
||||||
|
async function handleGetTenantList() {
|
||||||
|
tenants.value = await getSimpleTenantList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理租户切换 */
|
||||||
|
async function handleTenantChange(tenant: SystemTenantApi.Tenant) {
|
||||||
|
if (!tenant || !tenant.id) {
|
||||||
|
message.error('切换租户失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置访问租户 ID
|
||||||
|
accessStore.setVisitTenantId(tenant.id as number);
|
||||||
|
// 关闭其他标签页,只保留当前页
|
||||||
|
await closeOtherTabs();
|
||||||
|
// 刷新当前页面
|
||||||
|
await refreshTab();
|
||||||
|
// 提示切换成功
|
||||||
|
message.success(`切换当前租户为: ${tenant.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
// ========== 初始化 ==========
|
// ========== 初始化 ==========
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 首次加载未读数量
|
// 首次加载未读数量
|
||||||
handleNotificationGetUnreadCount();
|
handleNotificationGetUnreadCount();
|
||||||
|
// 获取租户列表
|
||||||
|
handleGetTenantList();
|
||||||
// 轮询刷新未读数量
|
// 轮询刷新未读数量
|
||||||
setInterval(
|
setInterval(
|
||||||
() => {
|
() => {
|
||||||
|
@ -204,7 +236,14 @@ watch(
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #header-right-1>
|
<template #header-right-1>
|
||||||
<TenantDropdown class="mr-2 w-44" />
|
<div v-access:code="['system:tenant:visit']">
|
||||||
|
<TenantDropdown
|
||||||
|
class="mr-2"
|
||||||
|
:tenant-list="tenants"
|
||||||
|
:visit-tenant-id="accessStore.visitTenantId"
|
||||||
|
@success="handleTenantChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<AuthenticationLoginExpiredModal
|
<AuthenticationLoginExpiredModal
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import type { SelectValue } from 'ant-design-vue/es/select';
|
|
||||||
|
|
||||||
import type { SystemTenantApi } from '#/api/system/tenant';
|
|
||||||
|
|
||||||
import { onMounted, ref } from 'vue';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
import { isTenantEnable, useTabs } from '@vben/hooks';
|
|
||||||
import { useAccessStore } from '@vben/stores';
|
|
||||||
|
|
||||||
import { message, Select } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { getSimpleTenantList } from '#/api/system/tenant';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const { closeOtherTabs, refreshTab } = useTabs();
|
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
const accessStore = useAccessStore();
|
|
||||||
|
|
||||||
const tenantEnable = isTenantEnable();
|
|
||||||
|
|
||||||
// 当前访问的租户 ID
|
|
||||||
const value = ref<number | undefined>(accessStore.visitTenantId ?? undefined);
|
|
||||||
// 租户列表
|
|
||||||
const tenants = ref<SystemTenantApi.Tenant[]>([]);
|
|
||||||
|
|
||||||
async function handleChange(id: SelectValue) {
|
|
||||||
// 设置访问租户 ID
|
|
||||||
accessStore.setVisitTenantId(id as number);
|
|
||||||
// 关闭其他标签页,只保留当前页
|
|
||||||
await closeOtherTabs();
|
|
||||||
// 刷新当前页面
|
|
||||||
await refreshTab();
|
|
||||||
// 提示切换成功
|
|
||||||
const tenant = tenants.value.find((item) => item.id === id);
|
|
||||||
if (tenant) {
|
|
||||||
message.success(`切换当前租户为: ${tenant.name}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
if (!tenantEnable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tenants.value = await getSimpleTenantList();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div v-if="tenantEnable && hasAccessByCodes(['system:tenant:visit'])">
|
|
||||||
<Select
|
|
||||||
v-model:value="value"
|
|
||||||
:field-names="{ label: 'name', value: 'id' }"
|
|
||||||
:options="tenants"
|
|
||||||
:placeholder="$t('page.tenant.placeholder')"
|
|
||||||
:dropdown-style="{ position: 'fixed', zIndex: 1666 }"
|
|
||||||
allow-clear
|
|
||||||
class="w-40"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -7,5 +7,6 @@ export { default as AuthenticationLayoutToggle } from './layout-toggle.vue';
|
||||||
export * from './lock-screen';
|
export * from './lock-screen';
|
||||||
export * from './notification';
|
export * from './notification';
|
||||||
export * from './preferences';
|
export * from './preferences';
|
||||||
|
export * from './tenant-dropdown';
|
||||||
export * from './theme-toggle';
|
export * from './theme-toggle';
|
||||||
export * from './user-dropdown';
|
export * from './user-dropdown';
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as TenantDropdown } from './tenant-dropdown.vue';
|
|
@ -0,0 +1,76 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { isTenantEnable } from '@vben/hooks';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
|
interface Tenant {
|
||||||
|
id?: number;
|
||||||
|
name: string;
|
||||||
|
packageId: number;
|
||||||
|
contactName: string;
|
||||||
|
contactMobile: string;
|
||||||
|
accountCount: number;
|
||||||
|
expireTime: Date;
|
||||||
|
website: string;
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'TenantDropdown',
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
tenantList?: Tenant[];
|
||||||
|
visitTenantId?: null | number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
|
const tenantEnable = isTenantEnable();
|
||||||
|
|
||||||
|
// 租户列表
|
||||||
|
const tenants = computed(() => props.tenantList ?? []);
|
||||||
|
|
||||||
|
async function handleChange(id: number | undefined) {
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tenant = tenants.value.find((item) => item.id === id);
|
||||||
|
|
||||||
|
emit('success', tenant);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<DropdownMenu v-if="tenantEnable">
|
||||||
|
<DropdownMenuTrigger as-child>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
class="hover:bg-accent ml-1 mr-2 h-8 w-24 cursor-pointer rounded-full p-1.5"
|
||||||
|
>
|
||||||
|
{{ tenants.find((item) => item.id === visitTenantId)?.name }}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent class="w-56 p-0 pb-1">
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuItem
|
||||||
|
v-for="tenant in tenants"
|
||||||
|
:key="tenant.id"
|
||||||
|
:disabled="tenant.id === visitTenantId"
|
||||||
|
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
|
||||||
|
@click="handleChange(tenant.id)"
|
||||||
|
>
|
||||||
|
{{ tenant.name }}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</template>
|
Loading…
Reference in New Issue