Browse Source

feat: 增加头像管理

pull/1131/head
colin 1 year ago
parent
commit
9b6c321aaa
  1. 15
      apps/vben5/apps/app-antd/src/store/auth.ts
  2. 28
      apps/vben5/packages/@abp/account/src/api/useProfileApi.ts
  3. 45
      apps/vben5/packages/@abp/account/src/components/components/BasicSettings.vue
  4. 5
      apps/vben5/packages/@abp/account/src/types/profile.ts

15
apps/vben5/apps/app-antd/src/store/auth.ts

@ -8,7 +8,12 @@ import { useRouter } from 'vue-router';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores'; import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { useQrCodeLoginApi, useTokenApi, useUserInfoApi } from '@abp/account'; import {
useProfileApi,
useQrCodeLoginApi,
useTokenApi,
useUserInfoApi,
} from '@abp/account';
import { Events, useAbpStore, useEventBus } from '@abp/core'; import { Events, useAbpStore, useEventBus } from '@abp/core';
import { notification } from 'ant-design-vue'; import { notification } from 'ant-design-vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
@ -22,6 +27,7 @@ export const useAuthStore = defineStore('auth', () => {
const { loginApi: qrcodeLoginApi } = useQrCodeLoginApi(); const { loginApi: qrcodeLoginApi } = useQrCodeLoginApi();
const { getUserInfoApi } = useUserInfoApi(); const { getUserInfoApi } = useUserInfoApi();
const { getConfigApi } = useAbpConfigApi(); const { getConfigApi } = useAbpConfigApi();
const { getPictureApi } = useProfileApi();
const accessStore = useAccessStore(); const accessStore = useAccessStore();
const userStore = useUserStore(); const userStore = useUserStore();
const abpStore = useAbpStore(); const abpStore = useAbpStore();
@ -76,6 +82,7 @@ export const useAuthStore = defineStore('auth', () => {
let userInfo: null | (UserInfo & { [key: string]: any }) = null; let userInfo: null | (UserInfo & { [key: string]: any }) = null;
const userInfoRes = await getUserInfoApi(); const userInfoRes = await getUserInfoApi();
const abpConfig = await getConfigApi(); const abpConfig = await getConfigApi();
const picture = await getPictureApi();
userInfo = { userInfo = {
userId: userInfoRes.sub ?? abpConfig.currentUser.id, userId: userInfoRes.sub ?? abpConfig.currentUser.id,
username: userInfoRes.uniqueName ?? abpConfig.currentUser.userName, username: userInfoRes.uniqueName ?? abpConfig.currentUser.userName,
@ -83,7 +90,7 @@ export const useAuthStore = defineStore('auth', () => {
userInfoRes.name ?? userInfoRes.name ??
abpConfig.currentUser.name ?? abpConfig.currentUser.name ??
abpConfig.currentUser.userName, abpConfig.currentUser.userName,
avatar: userInfoRes.avatarUrl ?? userInfoRes.picture ?? '', avatar: URL.createObjectURL(picture) ?? '',
desc: userInfoRes.uniqueName ?? userInfoRes.name, desc: userInfoRes.uniqueName ?? userInfoRes.name,
email: userInfoRes.email ?? userInfoRes.email, email: userInfoRes.email ?? userInfoRes.email,
emailVerified: emailVerified:
@ -148,6 +155,10 @@ export const useAuthStore = defineStore('auth', () => {
} }
function $reset() { function $reset() {
const userInfo = userStore.userInfo;
if (userInfo?.avatar) {
URL.revokeObjectURL(userInfo?.avatar);
}
loginLoading.value = false; loginLoading.value = false;
} }

28
apps/vben5/packages/@abp/account/src/api/useProfileApi.ts

@ -2,6 +2,7 @@ import type {
AuthenticatorDto, AuthenticatorDto,
AuthenticatorRecoveryCodeDto, AuthenticatorRecoveryCodeDto,
ChangePasswordInput, ChangePasswordInput,
ChangePictureInput,
ConfirmEmailInput, ConfirmEmailInput,
ProfileDto, ProfileDto,
SendEmailConfirmCodeDto, SendEmailConfirmCodeDto,
@ -48,6 +49,31 @@ export function useProfileApi() {
}); });
} }
/**
*
* @param input
*/
function changePictureApi(input: ChangePictureInput): Promise<void> {
return request('/api/account/my-profile/picture', {
data: input,
headers: {
'Content-Type': 'multipart/form-data',
},
method: 'POST',
});
}
/**
*
* @returns
*/
function getPictureApi(): Promise<Blob> {
return request('/api/account/my-profile/picture', {
method: 'GET',
responseType: 'blob',
});
}
/** /**
* *
*/ */
@ -132,10 +158,12 @@ export function useProfileApi() {
return { return {
cancel, cancel,
changePasswordApi, changePasswordApi,
changePictureApi,
changeTwoFactorEnabledApi, changeTwoFactorEnabledApi,
confirmEmailApi, confirmEmailApi,
getApi, getApi,
getAuthenticatorApi, getAuthenticatorApi,
getPictureApi,
getTwoFactorEnabledApi, getTwoFactorEnabledApi,
resetAuthenticatorApi, resetAuthenticatorApi,
sendEmailConfirmLinkApi, sendEmailConfirmLinkApi,

45
apps/vben5/packages/@abp/account/src/components/components/BasicSettings.vue

@ -12,7 +12,17 @@ import { useUserStore } from '@vben/stores';
import { useSettings } from '@abp/core'; import { useSettings } from '@abp/core';
import { UploadOutlined } from '@ant-design/icons-vue'; import { UploadOutlined } from '@ant-design/icons-vue';
import { Avatar, Button, Card, Form, Input, Upload } from 'ant-design-vue'; import {
Avatar,
Button,
Card,
Form,
Input,
message,
Upload,
} from 'ant-design-vue';
import { useProfileApi } from '../../api/useProfileApi';
const props = defineProps<{ const props = defineProps<{
profile: ProfileDto; profile: ProfileDto;
@ -23,19 +33,40 @@ const emits = defineEmits<{
const FormItem = Form.Item; const FormItem = Form.Item;
const formModel = ref({} as ProfileDto); const formModel = ref({} as ProfileDto);
const pictureState = ref<{
file?: any;
uploading: boolean;
}>({
uploading: false,
});
const userStore = useUserStore(); const userStore = useUserStore();
const { isTrue } = useSettings(); const { isTrue } = useSettings();
const { changePictureApi, getPictureApi } = useProfileApi();
const avatar = computed(() => { const avatar = computed(() => {
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar; return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
}); });
function onAvatarChange(_param: UploadChangeParam) { async function onAvatarChange(_param: UploadChangeParam) {
// TODO: oss pictureState.value.uploading = true;
console.warn('等待oss模块集成完成...'); try {
await changePictureApi({
file: pictureState.value.file,
});
if (userStore.userInfo?.avatar) {
URL.revokeObjectURL(userStore.userInfo.avatar);
}
const picture = await getPictureApi();
userStore.$patch((state) => {
state.userInfo && (state.userInfo.avatar = URL.createObjectURL(picture));
});
message.success($t('AbpUi.SavedSuccessfully'));
} finally {
pictureState.value.uploading = false;
}
} }
function onBeforeUpload(_file: FileType) { function onBeforeUpload(file: FileType) {
console.warn('等待oss模块集成完成...'); pictureState.value.file = file;
return false; return false;
} }
function onSubmit() { function onSubmit() {
@ -110,7 +141,7 @@ watchEffect(() => {
name="file" name="file"
@change="onAvatarChange" @change="onAvatarChange"
> >
<Button class="mt-4"> <Button class="mt-4" :loading="pictureState.uploading">
<UploadOutlined /> <UploadOutlined />
{{ $t('abp.account.settings.changeAvatar') }} {{ $t('abp.account.settings.changeAvatar') }}
</Button> </Button>

5
apps/vben5/packages/@abp/account/src/types/profile.ts

@ -36,6 +36,10 @@ interface ChangePasswordInput {
newPassword: string; newPassword: string;
} }
interface ChangePictureInput {
file: File;
}
interface TwoFactorEnabledDto { interface TwoFactorEnabledDto {
/** 是否启用二次认证 */ /** 是否启用二次认证 */
enabled: boolean; enabled: boolean;
@ -69,6 +73,7 @@ export type {
AuthenticatorDto, AuthenticatorDto,
AuthenticatorRecoveryCodeDto, AuthenticatorRecoveryCodeDto,
ChangePasswordInput, ChangePasswordInput,
ChangePictureInput,
ConfirmEmailInput, ConfirmEmailInput,
ProfileDto, ProfileDto,
SendEmailConfirmCodeDto, SendEmailConfirmCodeDto,

Loading…
Cancel
Save