Browse Source

feat(settings): Improve setting manager.

pull/1061/head
colin 1 year ago
parent
commit
c0b55406bb
  1. 1
      apps/vben5/packages/@abp/settings/package.json
  2. 13
      apps/vben5/packages/@abp/settings/src/api/settings.ts
  3. 211
      apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue
  4. 85
      apps/vben5/packages/@abp/settings/src/components/settings/SystemSetting.vue
  5. 22
      apps/vben5/packages/@abp/settings/src/components/settings/UserSetting.vue
  6. 4
      apps/vben5/packages/@abp/settings/src/types/settings.ts

1
apps/vben5/packages/@abp/settings/package.json

@ -31,6 +31,7 @@
"@vben/layouts": "workspace:*", "@vben/layouts": "workspace:*",
"@vben/locales": "workspace:*", "@vben/locales": "workspace:*",
"ant-design-vue": "catalog:", "ant-design-vue": "catalog:",
"dayjs": "catalog:",
"vue": "catalog:*" "vue": "catalog:*"
} }
} }

13
apps/vben5/packages/@abp/settings/src/api/settings.ts

@ -69,3 +69,16 @@ export function setUserSettingsApi(input: SettingsUpdateInput): Promise<void> {
input, input,
); );
} }
/**
*
* @param emailAddress
*/
export const sendTestEmailApi = (emailAddress: string) => {
return requestClient.post(
`/api/setting-management/settings/send-test-email`,
{
emailAddress,
},
);
};

211
apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue

@ -1,7 +1,214 @@
<script setup lang="ts"></script> <script setup lang="ts">
import type {
SettingDetail,
SettingGroup,
SettingsUpdateInput,
} from '../../types';
import { computed, onMounted, ref, toValue } from 'vue';
import { $t } from '@vben/locales';
import { formatToDate } from '@abp/core';
import {
Button,
Card,
Checkbox,
Collapse,
DatePicker,
Form,
Input,
InputNumber,
InputPassword,
message,
Select,
Tabs,
} from 'ant-design-vue';
import dayjs from 'dayjs';
import { ValueType } from '../../types';
defineOptions({
name: 'SettingForm',
});
const props = defineProps<{
getApi: () => Promise<SettingGroup[]>;
submitApi: (input: SettingsUpdateInput) => Promise<void>;
}>();
const emits = defineEmits<{
(event: 'change', data: SettingsUpdateInput): void;
}>();
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
const CollapsePanel = Collapse.Panel;
const SelectOption = Select.Option;
const defaultModel: SettingsUpdateInput = {
settings: [],
};
const activeTab = ref(0);
const submiting = ref(false);
const settingGroups = ref<SettingGroup[]>([]);
const settingsUpdateInput = ref<SettingsUpdateInput>({ ...defaultModel });
const getExpandedCollapseKeys = computed(() => {
return (group: SettingGroup) => {
const keys = group.settings.map((group) => {
return group.displayName;
});
return keys;
};
});
async function onGet() {
settingGroups.value = await props.getApi();
}
async function onSubmit() {
try {
submiting.value = true;
const input = toValue(settingsUpdateInput);
await props.submitApi(input);
emits('change', input);
message.success($t('AbpSettingManagement.SuccessfullySaved'));
} finally {
submiting.value = false;
}
}
function onCheckChange(setting: SettingDetail) {
setting.value = setting.value === 'true' ? 'false' : 'true';
onValueChange(setting);
}
function onDateChange(e: any, setting: SettingDetail) {
setting.value = dayjs.isDayjs(e) ? formatToDate(e) : '';
onValueChange(setting);
}
function onValueChange(setting: SettingDetail) {
const index = settingsUpdateInput.value.settings.findIndex(
(s) => s.name === setting.name,
);
if (index === -1) {
settingsUpdateInput.value.settings.push({
name: setting.name,
value: String(setting.value),
});
} else {
settingsUpdateInput.value.settings[index]!.value = String(setting.value);
}
}
onMounted(onGet);
</script>
<template> <template>
<div></div> <Card :title="$t('AbpSettingManagement.Settings')">
<template #extra>
<Button
v-if="settingsUpdateInput.settings.length > 0"
:loading="submiting"
class="w-[100px]"
post-icon="ant-design:setting-outlined"
type="primary"
@click="onSubmit"
>
{{ $t('AbpUi.Submit') }}
</Button>
</template>
<Form :label-col="{ span: 5 }" :wrapper-col="{ span: 15 }">
<Tabs v-model="activeTab">
<TabPane
v-for="(group, index) in settingGroups"
:key="index"
:tab="group.displayName"
>
<Collapse :default-active-key="getExpandedCollapseKeys(group)">
<CollapsePanel
v-for="setting in group.settings"
:key="setting.displayName"
:header="setting.displayName"
>
<template v-for="detail in setting.details" :key="detail.name">
<slot
v-if="detail.slot"
:change="
detail.valueType === ValueType.Boolean
? onCheckChange(detail)
: onValueChange(detail)
"
:detail="detail"
:name="detail.slot"
></slot>
<FormItem
v-else
:extra="detail.description"
:label="detail.displayName"
>
<template v-if="detail.valueType === ValueType.String">
<InputPassword
v-if="detail.isEncrypted"
v-model:value="detail.value"
:placeholder="detail.description"
@change="onValueChange(detail)"
/>
<Input
v-else
v-model:value="detail.value"
:placeholder="detail.description"
type="text"
@change="onValueChange(detail)"
/>
</template>
<InputNumber
v-else-if="
detail.valueType === ValueType.Number &&
!detail.isEncrypted
"
v-model:value="detail.value"
:placeholder="detail.description"
class="w-full"
@change="onValueChange(detail)"
/>
<DatePicker
v-else-if="detail.valueType === ValueType.Date"
:placeholder="detail.description"
:value="
detail.value ? dayjs(detail.value, 'YYYY-MM-DD') : ''
"
style="width: 100%"
@change="onDateChange($event, detail)"
/>
<Select
v-if="detail.valueType === ValueType.Option"
v-model:value="detail.value"
@change="onValueChange(detail)"
>
<SelectOption
v-for="option in detail.options"
:key="option.value"
:disabled="option.value === detail.value"
>
{{ option.name }}
</SelectOption>
</Select>
<Checkbox
v-if="detail.valueType === ValueType.Boolean"
:checked="detail.value === 'true'"
@change="onCheckChange(detail)"
>
{{ detail.displayName }}
</Checkbox>
</FormItem>
</template>
</CollapsePanel>
</Collapse>
</TabPane>
</Tabs>
</Form>
</Card>
</template> </template>
<style scoped></style> <style scoped></style>

85
apps/vben5/packages/@abp/settings/src/components/settings/SystemSetting.vue

@ -1,10 +1,91 @@
<script setup lang="ts"> <script setup lang="ts">
import { Page } from '@vben/common-ui'; import type { SettingsUpdateInput } from '../../types';
import { ref } from 'vue';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { isEmail, useAbpStore } from '@abp/core';
import { Button, Form, InputSearch, message, Modal } from 'ant-design-vue';
import {
getGlobalSettingsApi,
getTenantSettingsApi,
sendTestEmailApi,
setGlobalSettingsApi,
setTenantSettingsApi,
} from '../../api/settings';
import SettingForm from './SettingForm.vue';
defineOptions({
name: 'SystemSettingForm',
});
const FormItem = Form.Item;
const abpStore = useAbpStore();
const sending = ref(false);
async function onGet() {
const api = abpStore.application?.currentTenant.isAvailable
? getTenantSettingsApi
: getGlobalSettingsApi;
const { items } = await api();
return items;
}
async function onSubmit(input: SettingsUpdateInput) {
const api = abpStore.application?.currentTenant.isAvailable
? setTenantSettingsApi
: setGlobalSettingsApi;
await api(input);
}
async function onSendMail(email: string) {
if (!isEmail(email)) {
Modal.warn({
centered: true,
content: $t('AbpValidation.The {0} field is not a valid e-mail address', [
$t('AbpSettingManagement.TargetEmailAddress'),
]),
title: $t('AbpValidation.ThisFieldIsNotValid'),
});
return;
}
try {
sending.value = true;
await sendTestEmailApi(email);
message.success($t('AbpSettingManagement.SuccessfullySent'));
} finally {
sending.value = false;
}
}
</script> </script>
<template> <template>
<Page :title="$t('AbpSettingManagement.Settings')" /> <SettingForm :get-api="onGet" :submit-api="onSubmit">
<template #send-test-email="{ detail }">
<FormItem
:extra="detail.description"
:label="detail.displayName"
name="testEmail"
>
<InputSearch
v-model:value="detail.value"
:loading="sending"
:placeholder="$t('AbpSettingManagement.TargetEmailAddress')"
@search="onSendMail"
>
<template #enterButton>
<Button :loading="sending" type="primary">
{{ $t('AbpSettingManagement.Send') }}
</Button>
</template>
</InputSearch>
</FormItem>
</template>
</SettingForm>
</template> </template>
<style scoped></style> <style scoped></style>

22
apps/vben5/packages/@abp/settings/src/components/settings/UserSetting.vue

@ -1,7 +1,25 @@
<script setup lang="ts"></script> <script setup lang="ts">
import type { SettingsUpdateInput } from '../../types';
import { getUserSettingsApi, setUserSettingsApi } from '../../api/settings';
import SettingForm from './SettingForm.vue';
defineOptions({
name: 'UserSettingForm',
});
async function onGet() {
const { items } = await getUserSettingsApi();
return items;
}
async function onSubmit(input: SettingsUpdateInput) {
await setUserSettingsApi(input);
}
</script>
<template> <template>
<div></div> <SettingForm :get-api="onGet" :submit-api="onSubmit" />
</template> </template>
<style scoped></style> <style scoped></style>

4
apps/vben5/packages/@abp/settings/src/types/settings.ts

@ -2,7 +2,7 @@ interface SettingBase {
/** 名称 */ /** 名称 */
name: string; name: string;
/** 当前设置值 */ /** 当前设置值 */
value: any; value: string;
} }
/** 配置变更对象 */ /** 配置变更对象 */
@ -53,4 +53,4 @@ interface SettingGroup {
settings: Setting[]; settings: Setting[];
} }
export type { SettingGroup, SettingsUpdateInput }; export type { Setting, SettingDetail, SettingGroup, SettingsUpdateInput };

Loading…
Cancel
Save