Browse Source

feat: 实现租户登录

pull/1152/head
colin 11 months ago
parent
commit
b1eb0bec6b
  1. 2
      apps/vben5/apps/app-antd/src/adapter/component/index.ts
  2. 2
      apps/vben5/packages/@abp/saas/package.json
  3. 1
      apps/vben5/packages/@abp/saas/src/api/index.ts
  4. 31
      apps/vben5/packages/@abp/saas/src/api/useMultiTenancyApi.ts
  5. 1
      apps/vben5/packages/@abp/saas/src/components/index.ts
  6. 58
      apps/vben5/packages/@abp/saas/src/components/tenants/TenantSelect.vue
  7. 98
      apps/vben5/packages/@abp/saas/src/components/tenants/TenantSelectModal.vue
  8. 1
      apps/vben5/packages/@abp/saas/src/types/index.ts
  9. 9
      apps/vben5/packages/@abp/saas/src/types/multiTenancys.ts
  10. 1
      apps/vben5/pnpm-workspace.yaml

2
apps/vben5/apps/app-antd/src/adapter/component/index.ts

@ -14,6 +14,7 @@ import { $t } from '@vben/locales';
import { FeatureStateCheck, GlobalFeatureStateCheck } from '@abp/features';
import { PermissionStateCheck } from '@abp/permissions';
import { TenantSelect } from '@abp/saas';
import {
AutoComplete,
Button,
@ -158,6 +159,7 @@ async function initComponentAdapter() {
FeatureStateCheck,
GlobalFeatureStateCheck,
PermissionStateCheck,
TenantSelect,
};
// 将组件注册到全局共享状态中

2
apps/vben5/packages/@abp/saas/package.json

@ -31,9 +31,11 @@
"@vben/hooks": "workspace:*",
"@vben/icons": "workspace:*",
"@vben/locales": "workspace:*",
"@vueuse/integrations": "catalog:",
"ant-design-vue": "catalog:",
"dayjs": "catalog:",
"lodash.debounce": "catalog:",
"universal-cookie": "catalog:",
"vue": "catalog:*",
"vxe-table": "catalog:"
},

1
apps/vben5/packages/@abp/saas/src/api/index.ts

@ -1,2 +1,3 @@
export { useEditionsApi } from './useEditionsApi';
export { useMultiTenancyApi } from './useMultiTenancyApi';
export { useTenantsApi } from './useTenantsApi';

31
apps/vben5/packages/@abp/saas/src/api/useMultiTenancyApi.ts

@ -0,0 +1,31 @@
import type { FindTenantResultDto } from '../types/multiTenancys';
import { useRequest } from '@abp/request';
export function useMultiTenancyApi() {
const { cancel, request } = useRequest();
function findTenantByNameApi(name: string): Promise<FindTenantResultDto> {
return request<FindTenantResultDto>(
`/api/abp/multi-tenancy/tenants/by-name/${name}`,
{
method: 'GET',
},
);
}
function findTenantByIdApi(id: string): Promise<FindTenantResultDto> {
return request<FindTenantResultDto>(
`/api/abp/multi-tenancy/tenants/by-id/${id}`,
{
method: 'GET',
},
);
}
return {
cancel,
findTenantByIdApi,
findTenantByNameApi,
};
}

1
apps/vben5/packages/@abp/saas/src/components/index.ts

@ -1,2 +1,3 @@
export { default as EditionTable } from './editions/EditionTable.vue';
export { default as TenantSelect } from './tenants/TenantSelect.vue';
export { default as TenantTable } from './tenants/TenantTable.vue';

58
apps/vben5/packages/@abp/saas/src/components/tenants/TenantSelect.vue

@ -0,0 +1,58 @@
<script setup lang="ts">
import { computed, defineAsyncComponent } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { useAbpStore } from '@abp/core';
import { Button, InputSearch } from 'ant-design-vue';
defineOptions({
name: 'TenantSelect',
});
const emits = defineEmits<{
(event: 'change', data?: { id?: string; name?: string }): void;
}>();
const abpStore = useAbpStore();
const getCurrentTenant = computed(() => {
return abpStore.application?.currentTenant;
});
const [Modal, modapApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./TenantSelectModal.vue'),
),
});
function onSwitchClick() {
modapApi.setData({
name: getCurrentTenant.value?.name,
});
modapApi.open();
}
function onChange(tenant?: { id?: string; name?: string }) {
emits('change', tenant);
}
</script>
<template>
<div class="w-full">
<InputSearch
readonly
:value="getCurrentTenant?.name"
:placeholder="$t('AbpUiMultiTenancy.NotSelected')"
>
<template #enterButton>
<Button @click="onSwitchClick">
({{ $t('AbpUiMultiTenancy.Switch') }})
</Button>
</template>
</InputSearch>
<Modal @change="onChange" />
</div>
</template>
<style scoped></style>

98
apps/vben5/packages/@abp/saas/src/components/tenants/TenantSelectModal.vue

@ -0,0 +1,98 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { useCookies } from '@vueuse/integrations/useCookies';
import { message } from 'ant-design-vue';
import { useMultiTenancyApi } from '../../api/useMultiTenancyApi';
interface Tenant {
id?: string;
name?: string;
}
const emits = defineEmits<{
(event: 'change', data?: Tenant): void;
}>();
const tenant = ref<Tenant>();
const cookies = useCookies();
const { findTenantByNameApi } = useMultiTenancyApi();
const [Form, formApi] = useVbenForm({
handleSubmit: onSubmit,
schema: [
{
component: 'Input',
componentProps: {
allowClear: true,
placeholder: $t('AbpUiMultiTenancy.SwitchTenantHint'),
},
fieldName: 'name',
label: $t('AbpUiMultiTenancy.Name'),
},
],
showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
onCancel() {
emits('change', tenant.value);
},
async onConfirm() {
await formApi.validateAndSubmitForm();
},
onOpenChange(isOpen) {
if (isOpen) {
const { name } = modalApi.getData<Tenant>();
formApi.setFieldValue('name', name);
}
},
});
async function onSubmit(values: Record<string, any>) {
modalApi.setState({ submitting: true });
try {
tenant.value = undefined;
cookies.remove('__tenant', {
path: '/',
});
// localStorage.removeItem('__tenant');
if (values.name) {
const result = await findTenantByNameApi(values.name);
if (!result.success) {
message.warning(
$t('AbpUiMultiTenancy.GivenTenantIsNotExist', [values.name]),
);
return;
}
if (!result.isActive) {
message.warning(
$t('AbpUiMultiTenancy.GivenTenantIsNotAvailable', [values.name]),
);
return;
}
tenant.value = { id: result.tenantId, name: result.normalizedName };
if (result.tenantId) {
// localStorage.setItem('__tenant', result.tenantId);
cookies.set('__tenant', result.tenantId, {
path: '/',
});
}
}
emits('change', tenant.value);
modalApi.close();
} finally {
modalApi.setState({ submitting: false });
}
}
</script>
<template>
<Modal :title="$t('AbpUiMultiTenancy.SwitchTenant')">
<Form />
</Modal>
</template>
<style scoped></style>

1
apps/vben5/packages/@abp/saas/src/types/index.ts

@ -1,2 +1,3 @@
export * from './editions';
export * from './multiTenancys';
export * from './tenants';

9
apps/vben5/packages/@abp/saas/src/types/multiTenancys.ts

@ -0,0 +1,9 @@
interface FindTenantResultDto {
isActive: boolean;
name?: string;
normalizedName?: string;
success: boolean;
tenantId?: string;
}
export type { FindTenantResultDto };

1
apps/vben5/pnpm-workspace.yaml

@ -174,6 +174,7 @@ catalog:
turbo: ^2.4.0
typescript: ^5.7.3
unbuild: ^3.3.1
universal-cookie: ^7
unplugin-element-plus: ^0.9.0
vee-validate: ^4.15.0
vditor: ^3.10.9

Loading…
Cancel
Save