Browse Source

feat(vben5): 保存前检查租户连接字符串

pull/1169/head
colin 12 months ago
parent
commit
5e7b538528
  1. 15
      apps/vben5/packages/@abp/saas/src/api/useTenantsApi.ts
  2. 39
      apps/vben5/packages/@abp/saas/src/components/tenants/ConnectionStringModal.vue
  3. 6
      apps/vben5/packages/@abp/saas/src/components/tenants/ConnectionStringTable.vue
  4. 5
      apps/vben5/packages/@abp/saas/src/components/tenants/ConnectionStringsModal.vue
  5. 25
      apps/vben5/packages/@abp/saas/src/components/tenants/TenantModal.vue
  6. 14
      apps/vben5/packages/@abp/saas/src/components/tenants/TenantTable.vue
  7. 7
      apps/vben5/packages/@abp/saas/src/types/tenants.ts

15
apps/vben5/packages/@abp/saas/src/api/useTenantsApi.ts

@ -2,6 +2,7 @@ import type { ListResultDto, PagedResultDto } from '@abp/core';
import type { import type {
GetTenantPagedListInput, GetTenantPagedListInput,
TenantConnectionStringCheckInput,
TenantConnectionStringDto, TenantConnectionStringDto,
TenantConnectionStringSetInput, TenantConnectionStringSetInput,
TenantCreateDto, TenantCreateDto,
@ -139,8 +140,22 @@ export function useTenantsApi() {
}); });
} }
/**
*
* @param input
*/
function checkConnectionString(
input: TenantConnectionStringCheckInput,
): Promise<void> {
return request(`/api/saas/tenants/connection-string/check`, {
data: input,
method: 'POST',
});
}
return { return {
cancel, cancel,
checkConnectionString,
createApi, createApi,
deleteApi, deleteApi,
deleteConnectionStringApi, deleteConnectionStringApi,

39
apps/vben5/packages/@abp/saas/src/components/tenants/ConnectionStringModal.vue

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import type { NameValue } from '@abp/core';
import type { FormExpose } from 'ant-design-vue/es/form/Form'; import type { FormExpose } from 'ant-design-vue/es/form/Form';
import type { TenantConnectionStringDto } from '../../types'; import type { TenantConnectionStringDto } from '../../types';
@ -8,17 +9,31 @@ import { ref, toValue, useTemplateRef } from 'vue';
import { useVbenModal } from '@vben/common-ui'; import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { Form, Input, Textarea } from 'ant-design-vue'; import { Form, Input, Select, Textarea } from 'ant-design-vue';
import { useTenantsApi } from '../../api/useTenantsApi';
const props = defineProps<{ const props = defineProps<{
dataBaseOptions: { label: string; value: string }[];
submit?: (data: TenantConnectionStringDto) => Promise<void>; submit?: (data: TenantConnectionStringDto) => Promise<void>;
}>(); }>();
const FormItem = Form.Item; const FormItem = Form.Item;
interface TenantConnectionString extends NameValue<string> {
provider: string;
}
const isEditModal = ref(false); const isEditModal = ref(false);
const form = useTemplateRef<FormExpose>('form'); const form = useTemplateRef<FormExpose>('form');
const formModel = ref({} as TenantConnectionStringDto); const formModel = ref<TenantConnectionString>({
name: '',
provider: 'MySql',
value: '',
});
const { checkConnectionString } = useTenantsApi();
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({
async onConfirm() { async onConfirm() {
await form.value?.validate(); await form.value?.validate();
@ -30,7 +45,10 @@ const [Modal, modalApi] = useVbenModal({
if (isOpen) { if (isOpen) {
form.value?.resetFields(); form.value?.resetFields();
const dto = modalApi.getData<TenantConnectionStringDto>(); const dto = modalApi.getData<TenantConnectionStringDto>();
formModel.value = { ...dto }; formModel.value = {
provider: formModel.value.provider,
...dto,
};
if (dto.name) { if (dto.name) {
isEditModal.value = true; isEditModal.value = true;
title = `${$t('AbpSaas.ConnectionStrings')} - ${dto.name}`; title = `${$t('AbpSaas.ConnectionStrings')} - ${dto.name}`;
@ -43,7 +61,13 @@ const [Modal, modalApi] = useVbenModal({
async function onSubmit() { async function onSubmit() {
modalApi.setState({ submitting: true }); modalApi.setState({ submitting: true });
try { try {
props.submit && (await props.submit(toValue(formModel))); const input = toValue(formModel);
await checkConnectionString({
connectionString: input.value,
name: input.name,
provider: input.provider,
});
props.submit && (await props.submit(input));
modalApi.close(); modalApi.close();
} finally { } finally {
modalApi.setState({ submitting: false }); modalApi.setState({ submitting: false });
@ -59,6 +83,13 @@ async function onSubmit() {
:wapper-col="{ span: 20 }" :wapper-col="{ span: 20 }"
:model="formModel" :model="formModel"
> >
<FormItem
required
name="provider"
:label="$t('AbpSaas.DisplayName:DataBaseProvider')"
>
<Select :options="dataBaseOptions" v-model:value="formModel.provider" />
</FormItem>
<FormItem required name="name" :label="$t('AbpSaas.DisplayName:Name')"> <FormItem required name="name" :label="$t('AbpSaas.DisplayName:Name')">
<Input <Input
:disabled="isEditModal" :disabled="isEditModal"

6
apps/vben5/packages/@abp/saas/src/components/tenants/ConnectionStringTable.vue

@ -14,6 +14,7 @@ import { VxeGrid } from 'vxe-table';
const props = defineProps<{ const props = defineProps<{
connectionStrings: TenantConnectionStringDto[]; connectionStrings: TenantConnectionStringDto[];
dataBaseOptions: { label: string; value: string }[];
delete?: (data: TenantConnectionStringDto) => Promise<void>; delete?: (data: TenantConnectionStringDto) => Promise<void>;
submit?: (data: TenantConnectionStringDto) => Promise<void>; submit?: (data: TenantConnectionStringDto) => Promise<void>;
}>(); }>();
@ -107,7 +108,10 @@ async function onDelete(row: TenantConnectionStringDto) {
</div> </div>
</template> </template>
</VxeGrid> </VxeGrid>
<ConnectionStringModal :submit="submit" /> <ConnectionStringModal
:data-base-options="dataBaseOptions"
:submit="submit"
/>
</div> </div>
</template> </template>

5
apps/vben5/packages/@abp/saas/src/components/tenants/ConnectionStringsModal.vue

@ -11,6 +11,10 @@ import { message } from 'ant-design-vue';
import { useTenantsApi } from '../../api/useTenantsApi'; import { useTenantsApi } from '../../api/useTenantsApi';
import ConnectionStringTable from './ConnectionStringTable.vue'; import ConnectionStringTable from './ConnectionStringTable.vue';
defineProps<{
dataBaseOptions: { label: string; value: string }[];
}>();
const connectionStrings = ref<TenantConnectionStringDto[]>([]); const connectionStrings = ref<TenantConnectionStringDto[]>([]);
const { const {
@ -61,6 +65,7 @@ async function onDelete(data: TenantConnectionStringDto) {
<template> <template>
<Modal :title="$t('AbpSaas.ConnectionStrings')"> <Modal :title="$t('AbpSaas.ConnectionStrings')">
<ConnectionStringTable <ConnectionStringTable
:data-base-options="dataBaseOptions"
:connection-strings="connectionStrings" :connection-strings="connectionStrings"
:delete="onDelete" :delete="onDelete"
:submit="onChange" :submit="onChange"

25
apps/vben5/packages/@abp/saas/src/components/tenants/TenantModal.vue

@ -32,10 +32,12 @@ import { useEditionsApi } from '../../api/useEditionsApi';
import { useTenantsApi } from '../../api/useTenantsApi'; import { useTenantsApi } from '../../api/useTenantsApi';
import ConnectionStringTable from './ConnectionStringTable.vue'; import ConnectionStringTable from './ConnectionStringTable.vue';
defineProps<{
dataBaseOptions: { label: string; value: string }[];
}>();
const emits = defineEmits<{ const emits = defineEmits<{
(event: 'change', val: TenantDto): void; (event: 'change', val: TenantDto): void;
}>(); }>();
const FormItem = Form.Item; const FormItem = Form.Item;
const defaultModel = { const defaultModel = {
@ -79,6 +81,11 @@ const getFormRules = computed(() => {
prefix: 'DisplayName', prefix: 'DisplayName',
resourceName: 'AbpSaas', resourceName: 'AbpSaas',
}), }),
provider: fieldRequired({
name: 'DataBaseProvider',
prefix: 'DisplayName',
resourceName: 'AbpSaas',
}),
}; };
}); });
/** 启用时间不可晚于禁用时间 */ /** 启用时间不可晚于禁用时间 */
@ -99,7 +106,8 @@ const getDisabledDisableTime = (current: dayjs.Dayjs) => {
return current && current < dayjs(tenant.value.enableTime).endOf('day'); return current && current < dayjs(tenant.value.enableTime).endOf('day');
}; };
const { cancel, createApi, getApi, updateApi } = useTenantsApi(); const { cancel, checkConnectionString, createApi, getApi, updateApi } =
useTenantsApi();
const { getPagedListApi: getEditions } = useEditionsApi(); const { getPagedListApi: getEditions } = useEditionsApi();
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({
@ -140,6 +148,12 @@ async function onGet() {
async function onSubmit() { async function onSubmit() {
try { try {
modalApi.setState({ submitting: true }); modalApi.setState({ submitting: true });
if (!tenant.value.useSharedDatabase) {
await checkConnectionString({
connectionString: tenant.value.defaultConnectionString,
provider: tenant.value.provider,
});
}
const api = tenant.value.id const api = tenant.value.id
? updateApi(tenant.value.id, tenant.value as TenantUpdateDto) ? updateApi(tenant.value.id, tenant.value as TenantUpdateDto)
: createApi(tenant.value as unknown as TenantCreateDto); : createApi(tenant.value as unknown as TenantCreateDto);
@ -284,6 +298,12 @@ onMounted(onSearchEditions);
</Checkbox> </Checkbox>
</FormItem> </FormItem>
<template v-if="!tenant.id && !tenant.useSharedDatabase"> <template v-if="!tenant.id && !tenant.useSharedDatabase">
<FormItem
name="provider"
:label="$t('AbpSaas.DisplayName:DataBaseProvider')"
>
<Select :options="dataBaseOptions" v-model:value="tenant.provider" />
</FormItem>
<FormItem <FormItem
name="defaultConnectionString" name="defaultConnectionString"
:label="$t('AbpSaas.DisplayName:DefaultConnectionString')" :label="$t('AbpSaas.DisplayName:DefaultConnectionString')"
@ -294,6 +314,7 @@ onMounted(onSearchEditions);
/> />
</FormItem> </FormItem>
<ConnectionStringTable <ConnectionStringTable
:data-base-options="dataBaseOptions"
:connection-strings="tenant.connectionStrings" :connection-strings="tenant.connectionStrings"
:submit="onConnectionChange" :submit="onConnectionChange"
:delete="onConnectionDelete" :delete="onConnectionDelete"

14
apps/vben5/packages/@abp/saas/src/components/tenants/TenantTable.vue

@ -6,7 +6,7 @@ import type { VbenFormProps } from '@vben/common-ui';
import type { TenantDto } from '../../types/tenants'; import type { TenantDto } from '../../types/tenants';
import { defineAsyncComponent, h } from 'vue'; import { defineAsyncComponent, h, reactive } from 'vue';
import { useAccess } from '@vben/access'; import { useAccess } from '@vben/access';
import { useVbenDrawer, useVbenModal } from '@vben/common-ui'; import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
@ -42,6 +42,14 @@ const { isEnabled } = useFeatures();
const { hasAccessByCodes } = useAccess(); const { hasAccessByCodes } = useAccess();
const { cancel, deleteApi, getPagedListApi } = useTenantsApi(); const { cancel, deleteApi, getPagedListApi } = useTenantsApi();
const dataBaseOptions = reactive([
{ label: 'MySql', value: 'MySql' },
{ label: 'Oracle', value: 'Oracle' },
{ label: 'Postgres', value: 'Postgres' },
{ label: 'Sqlite', value: 'Sqlite' },
{ label: 'SqlServer', value: 'SqlServer' },
]);
const formOptions: VbenFormProps = { const formOptions: VbenFormProps = {
// //
collapsed: false, collapsed: false,
@ -272,8 +280,8 @@ const onMenuClick = (row: TenantDto, info: MenuInfo) => {
</div> </div>
</template> </template>
</Grid> </Grid>
<TenantModal @change="() => query()" /> <TenantModal :data-base-options="dataBaseOptions" @change="() => query()" />
<TenantConnectionStringsModal /> <TenantConnectionStringsModal :data-base-options="dataBaseOptions" />
<TenantFeatureModal /> <TenantFeatureModal />
<TenantChangeDrawer /> <TenantChangeDrawer />
</template> </template>

7
apps/vben5/packages/@abp/saas/src/types/tenants.ts

@ -54,12 +54,19 @@ interface TenantCreateDto extends TenantCreateOrUpdateBase {
useSharedDatabase: boolean; useSharedDatabase: boolean;
} }
interface TenantConnectionStringCheckInput {
connectionString: string;
name?: string;
provider: string;
}
interface TenantUpdateDto interface TenantUpdateDto
extends IHasConcurrencyStamp, extends IHasConcurrencyStamp,
TenantCreateOrUpdateBase {} TenantCreateOrUpdateBase {}
export type { export type {
GetTenantPagedListInput, GetTenantPagedListInput,
TenantConnectionStringCheckInput,
TenantConnectionStringDto, TenantConnectionStringDto,
TenantConnectionStringSetInput, TenantConnectionStringSetInput,
TenantCreateDto, TenantCreateDto,

Loading…
Cancel
Save