65 lines
2.1 KiB
Vue
65 lines
2.1 KiB
Vue
<template>
|
||
<el-dropdown v-if="permissionStore.isSuper" trigger="click" @command="onCommand">
|
||
<button class="ty-tenant-switch" type="button" title="切换租户">
|
||
<icon type="iconify" icon="mdi:domain" />
|
||
</button>
|
||
<template #dropdown>
|
||
<el-dropdown-menu>
|
||
<el-dropdown-item v-for="t in tenants" :key="t.code" :command="t.code" :disabled="t.code === currentTenantCode">
|
||
{{ t.name }}({{ t.code }})
|
||
</el-dropdown-item>
|
||
</el-dropdown-menu>
|
||
</template>
|
||
</el-dropdown>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed, onMounted, ref } from 'vue'
|
||
import { useAuthStore } from '@/stores/modules/auth'
|
||
import { usePermissionStore } from '@/stores/modules/permission'
|
||
import { listTenants, type Tenant } from '@/api/tenant'
|
||
|
||
defineOptions({ name: 'TyTenantSwitch' })
|
||
|
||
const auth = useAuthStore()
|
||
const permissionStore = usePermissionStore()
|
||
const tenants = ref<Tenant[]>([])
|
||
|
||
const currentTenantCode = computed(() => decodeTenantCode(auth.accessToken))
|
||
|
||
function decodeTenantCode(token: string | null): string {
|
||
if (!token) return ''
|
||
try {
|
||
const payload = token.split('.')[1]
|
||
const base64 = payload.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(payload.length / 4) * 4, '=')
|
||
const bytes = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0))
|
||
const json = JSON.parse(new TextDecoder().decode(bytes))
|
||
return (json.tenantCode as string) ?? ''
|
||
} catch {
|
||
return ''
|
||
}
|
||
}
|
||
|
||
async function onCommand(tenantCode: string): Promise<void> {
|
||
if (!tenantCode || tenantCode === currentTenantCode.value) return
|
||
await auth.switchTenant(tenantCode)
|
||
window.location.reload()
|
||
}
|
||
|
||
onMounted(async () => {
|
||
const res = await listTenants({ page: 1, pageSize: 200 })
|
||
tenants.value = res.list
|
||
})
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.ty-tenant-switch {
|
||
@apply inline-flex items-center justify-center w-[34px] h-[34px] border-none rounded-base bg-transparent text-[18px] text-text-regular cursor-pointer transition-colors duration-200;
|
||
|
||
&:hover {
|
||
@apply bg-bg-page;
|
||
color: var(--el-color-primary);
|
||
}
|
||
}
|
||
</style>
|