You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
6.5 KiB
226 lines
6.5 KiB
<script setup lang="ts">
|
|
import type { BindItem } from '../types/bind';
|
|
import type { ProfileDto, UpdateProfileDto } from '../types/profile';
|
|
import type { UserInfo } from '../types/user';
|
|
|
|
import { computed, defineAsyncComponent, onMounted, ref } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
|
|
import { useVbenModal } from '@vben/common-ui';
|
|
import { $t } from '@vben/locales';
|
|
import { useUserStore } from '@vben/stores';
|
|
|
|
import { Card, Menu, message, Modal } from 'ant-design-vue';
|
|
|
|
import { useProfileApi } from '../api/useProfileApi';
|
|
|
|
interface MenuItem {
|
|
key: string;
|
|
label: string;
|
|
}
|
|
const props = defineProps<{
|
|
bindItems?: BindItem[];
|
|
disableAuthenticator?: boolean;
|
|
disableBind?: boolean;
|
|
disableNotice?: boolean;
|
|
disablePersonalData?: boolean;
|
|
disableSecurity?: boolean;
|
|
disableSession?: boolean;
|
|
}>();
|
|
const emits = defineEmits<{
|
|
(event: 'onBindInit'): void;
|
|
}>();
|
|
const AuthenticatorSettings = defineAsyncComponent(
|
|
() => import('./components/AuthenticatorSettings.vue'),
|
|
);
|
|
const BasicSettings = defineAsyncComponent(
|
|
() => import('./components/BasicSettings.vue'),
|
|
);
|
|
const BindSettings = defineAsyncComponent(
|
|
() => import('./components/BindSettings.vue'),
|
|
);
|
|
const NoticeSettings = defineAsyncComponent(
|
|
() => import('./components/NoticeSettings.vue'),
|
|
);
|
|
const SecuritySettings = defineAsyncComponent(
|
|
() => import('./components/SecuritySettings.vue'),
|
|
);
|
|
const SessionSettings = defineAsyncComponent(
|
|
() => import('./components/SessionSettings.vue'),
|
|
);
|
|
const PersonalDataSettings = defineAsyncComponent(
|
|
() => import('./components/PersonalDataSettings.vue'),
|
|
);
|
|
const { getApi, updateApi } = useProfileApi();
|
|
const userStore = useUserStore();
|
|
const { query } = useRoute();
|
|
|
|
const selectedMenuKeys = ref<string[]>(['basic']);
|
|
const myProfile = ref({} as ProfileDto);
|
|
const basicMenuItems: MenuItem[] = [
|
|
{
|
|
key: 'basic',
|
|
label: $t('abp.account.settings.basic.title'),
|
|
},
|
|
{
|
|
key: 'security',
|
|
label: $t('abp.account.settings.security.title'),
|
|
},
|
|
{
|
|
key: 'bind',
|
|
label: $t('abp.account.settings.bindSettings'),
|
|
},
|
|
{
|
|
key: 'session',
|
|
label: $t('abp.account.settings.sessionSettings'),
|
|
},
|
|
{
|
|
key: 'notice',
|
|
label: $t('abp.account.settings.noticeSettings'),
|
|
},
|
|
{
|
|
key: 'authenticator',
|
|
label: $t('abp.account.settings.authenticatorSettings'),
|
|
},
|
|
{
|
|
key: 'personal-data',
|
|
label: $t('abp.account.settings.personalDataSettings'),
|
|
},
|
|
];
|
|
const getEnabledMenus = computed(() => {
|
|
return basicMenuItems.filter((x) => {
|
|
if (x.key === 'basic') return true;
|
|
if (x.key === 'authenticator') return !props.disableAuthenticator;
|
|
if (x.key === 'bind') return !props.disableBind;
|
|
if (x.key === 'notice') return !props.disableNotice;
|
|
if (x.key === 'personal-data') return !props.disablePersonalData;
|
|
if (x.key === 'security') return !props.disableSecurity;
|
|
if (x.key === 'session') return !props.disableSession;
|
|
return true; // default case for any unexpected keys
|
|
});
|
|
});
|
|
const getUserInfo = computed((): null | UserInfo => {
|
|
if (!userStore.userInfo) {
|
|
return null;
|
|
}
|
|
return {
|
|
email: userStore.userInfo.email,
|
|
emailVerified: userStore.userInfo.emailVerified,
|
|
name: userStore.userInfo.name,
|
|
phoneNumber: userStore.userInfo.phoneNumber,
|
|
phoneNumberVerified: userStore.userInfo.phoneNumberVerified,
|
|
preferredUsername: userStore.userInfo.username,
|
|
role: userStore.userInfo.roles!,
|
|
sub: userStore.userInfo.userId,
|
|
uniqueName: userStore.userInfo.username,
|
|
};
|
|
});
|
|
const [EmailConfirmModal, emailConfirmModalApi] = useVbenModal({
|
|
connectedComponent: defineAsyncComponent(
|
|
() => import('./components/EmailConfirmModal.vue'),
|
|
),
|
|
});
|
|
const [ChangePasswordModal, changePasswordModalApi] = useVbenModal({
|
|
connectedComponent: defineAsyncComponent(
|
|
() => import('./components/ChangePasswordModal.vue'),
|
|
),
|
|
});
|
|
const [ChangePhoneNumberModal, changePhoneNumberModalApi] = useVbenModal({
|
|
connectedComponent: defineAsyncComponent(
|
|
() => import('./components/ChangePhoneNumberModal.vue'),
|
|
),
|
|
});
|
|
function onEmailConfirm() {
|
|
if (query?.confirmToken) {
|
|
setTimeout(() => {
|
|
emailConfirmModalApi.setData({
|
|
email: myProfile.value.email,
|
|
...query,
|
|
});
|
|
emailConfirmModalApi.open();
|
|
}, 300);
|
|
}
|
|
}
|
|
async function onGetProfile() {
|
|
const profile = await getApi();
|
|
myProfile.value = profile;
|
|
}
|
|
async function onPhoneNumberChange(phoneNumber: string) {
|
|
userStore.$patch((state) => {
|
|
state.userInfo && (state.userInfo.phoneNumber = phoneNumber);
|
|
});
|
|
}
|
|
async function onUpdateProfile(input: UpdateProfileDto) {
|
|
Modal.confirm({
|
|
centered: true,
|
|
content: $t('AbpAccount.PersonalSettingsSaved'),
|
|
onOk: async () => {
|
|
await updateApi(input);
|
|
message.success(
|
|
$t('AbpAccount.PersonalSettingsChangedConfirmationModalTitle'),
|
|
);
|
|
// 刷新页面重载用户信息
|
|
window.location.reload();
|
|
},
|
|
title: $t('AbpUi.AreYouSure'),
|
|
});
|
|
}
|
|
function onChangePassword() {
|
|
changePasswordModalApi.open();
|
|
}
|
|
function onChangePhoneNumber() {
|
|
changePhoneNumberModalApi.open();
|
|
}
|
|
onMounted(async () => {
|
|
await onGetProfile();
|
|
onEmailConfirm();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<Card>
|
|
<div class="flex">
|
|
<div class="basis-1/6">
|
|
<Menu
|
|
v-model:selected-keys="selectedMenuKeys"
|
|
:items="getEnabledMenus"
|
|
mode="inline"
|
|
/>
|
|
</div>
|
|
<div class="basis-5/6">
|
|
<BasicSettings
|
|
v-if="selectedMenuKeys[0] === 'basic'"
|
|
:profile="myProfile"
|
|
@submit="onUpdateProfile"
|
|
@picture-change="onGetProfile"
|
|
/>
|
|
<BindSettings
|
|
v-else-if="selectedMenuKeys[0] === 'bind'"
|
|
:items="bindItems"
|
|
@on-init="emits('onBindInit')"
|
|
/>
|
|
<SecuritySettings
|
|
v-else-if="selectedMenuKeys[0] === 'security'"
|
|
:user-info="getUserInfo"
|
|
@change-password="onChangePassword"
|
|
@change-phone-number="onChangePhoneNumber"
|
|
/>
|
|
<NoticeSettings v-else-if="selectedMenuKeys[0] === 'notice'" />
|
|
<AuthenticatorSettings
|
|
v-else-if="selectedMenuKeys[0] === 'authenticator'"
|
|
/>
|
|
<SessionSettings v-else-if="selectedMenuKeys[0] === 'session'" />
|
|
<PersonalDataSettings
|
|
v-else-if="selectedMenuKeys[0] === 'personal-data'"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
<EmailConfirmModal />
|
|
<ChangePasswordModal />
|
|
<ChangePhoneNumberModal @change="onPhoneNumberChange" />
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style>
|
|
|