From 7d8f6c0f9d3ce152d5d89bee48bbc2091a6e27ba Mon Sep 17 00:00:00 2001 From: sunlei Date: Sun, 7 Jun 2026 20:09:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E5=A4=B4=E5=83=8F=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antdv-next/src/api/core/index.ts | 1 + apps/web-antdv-next/src/api/core/upload.ts | 41 ++++ apps/web-antdv-next/src/api/core/user.ts | 15 ++ apps/web-antdv-next/src/layouts/basic.vue | 2 +- .../src/views/_core/profile/base-setting.vue | 77 ++++--- .../src/views/_core/profile/index.vue | 211 ++++++++++++++++-- .../common-ui/src/ui/profile/profile.vue | 43 +++- .../effects/common-ui/src/ui/profile/types.ts | 1 + 8 files changed, 325 insertions(+), 66 deletions(-) create mode 100644 apps/web-antdv-next/src/api/core/upload.ts diff --git a/apps/web-antdv-next/src/api/core/index.ts b/apps/web-antdv-next/src/api/core/index.ts index ba64a03..14c6521 100644 --- a/apps/web-antdv-next/src/api/core/index.ts +++ b/apps/web-antdv-next/src/api/core/index.ts @@ -2,4 +2,5 @@ export * from './auth'; export * from './dict'; export * from './menu'; export * from './timezone'; +export * from './upload'; export * from './user'; diff --git a/apps/web-antdv-next/src/api/core/upload.ts b/apps/web-antdv-next/src/api/core/upload.ts new file mode 100644 index 0000000..4318757 --- /dev/null +++ b/apps/web-antdv-next/src/api/core/upload.ts @@ -0,0 +1,41 @@ +import { requestClient } from '#/api/request'; + +export interface UploadFileOptions { + bucketName?: string; + objectName?: string; +} + +export interface UploadFileResult { + bucketName: string; + etag: string; + mimeType: string; + objectName: string; + size: number; + url: string; +} + +/** + * 统一文件上传入口,业务侧只传文件和可选对象名。 + */ +export async function uploadFileApi( + file: Blob | File, + options: UploadFileOptions = {}, +) { + return requestClient.upload('/minio/upload', { + ...options, + file, + }); +} + +export function createUploadedFileDownloadUrl(file: UploadFileResult) { + const baseUrl = requestClient.getBaseUrl() || ''; + const params = new URLSearchParams({ + objectName: file.objectName, + }); + + if (file.bucketName) { + params.set('bucketName', file.bucketName); + } + + return `${baseUrl.replace(/\/$/, '')}/minio/download?${params.toString()}`; +} diff --git a/apps/web-antdv-next/src/api/core/user.ts b/apps/web-antdv-next/src/api/core/user.ts index 7e28ea8..2713b8e 100644 --- a/apps/web-antdv-next/src/api/core/user.ts +++ b/apps/web-antdv-next/src/api/core/user.ts @@ -2,9 +2,24 @@ import type { UserInfo } from '@vben/types'; import { requestClient } from '#/api/request'; +export interface CurrentUserProfileInput { + avatar?: string; + homePath?: string; + realName?: string; +} + /** * 获取用户信息 */ export async function getUserInfoApi() { return requestClient.get('/user/info'); } + +/** + * 更新当前用户基础资料 + */ +export async function updateCurrentUserProfileApi( + data: CurrentUserProfileInput, +) { + return requestClient.put('/user/profile', data); +} diff --git a/apps/web-antdv-next/src/layouts/basic.vue b/apps/web-antdv-next/src/layouts/basic.vue index 74b0854..4cb7d6d 100644 --- a/apps/web-antdv-next/src/layouts/basic.vue +++ b/apps/web-antdv-next/src/layouts/basic.vue @@ -32,7 +32,7 @@ const router = useRouter(); const { destroyWatermark, updateWatermark } = useWatermark(); const avatar = computed(() => { - return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar; + return userStore.userInfo?.avatar || preferences.app.defaultAvatar; }); const userDropdownMenus = computed(() => [ diff --git a/apps/web-antdv-next/src/views/_core/profile/base-setting.vue b/apps/web-antdv-next/src/views/_core/profile/base-setting.vue index aa8a4c2..4713ed2 100644 --- a/apps/web-antdv-next/src/views/_core/profile/base-setting.vue +++ b/apps/web-antdv-next/src/views/_core/profile/base-setting.vue @@ -1,65 +1,70 @@ diff --git a/apps/web-antdv-next/src/views/_core/profile/index.vue b/apps/web-antdv-next/src/views/_core/profile/index.vue index 8740894..31e4e2d 100644 --- a/apps/web-antdv-next/src/views/_core/profile/index.vue +++ b/apps/web-antdv-next/src/views/_core/profile/index.vue @@ -1,49 +1,220 @@ diff --git a/packages/effects/common-ui/src/ui/profile/profile.vue b/packages/effects/common-ui/src/ui/profile/profile.vue index 5ab39e6..3afe2cd 100644 --- a/packages/effects/common-ui/src/ui/profile/profile.vue +++ b/packages/effects/common-ui/src/ui/profile/profile.vue @@ -10,6 +10,7 @@ import { TabsTrigger, VbenAvatar, } from '@vben-core/shadcn-ui'; +import { cn } from '@vben-core/shared/utils'; import { Page } from '../../components'; @@ -17,34 +18,58 @@ defineOptions({ name: 'ProfileUI', }); -withDefaults(defineProps(), { +const props = withDefaults(defineProps(), { + avatarEditable: false, title: '关于项目', tabs: () => [], }); +const emit = defineEmits<{ + avatarClick: []; +}>(); + const tabsValue = defineModel('modelValue'); + +function handleAvatarClick() { + if (props.avatarEditable) { + emit('avatarClick'); + } +}