1+ <template >
2+ <div class =" profile-avatar relative w-[120px] h-[120px] rounded-full overflow-hidden cursor-pointer group" >
3+ <img
4+ v-if =" modelValue"
5+ class =" w-full h-full object-cover"
6+ :src =" getUrl(modelValue)"
7+ alt =" 头像"
8+ />
9+ <div
10+ v-else
11+ class =" w-full h-full flex flex-col items-center justify-center bg-gray-100 dark:bg-slate-700"
12+ >
13+ <el-icon class =" text-2xl text-gray-400" >
14+ <avatar />
15+ </el-icon >
16+ <span class =" mt-2 text-sm text-gray-400" >点击上传</span >
17+ </div >
18+
19+ <div
20+ class =" absolute inset-0 bg-black/30 opacity-0 group-hover:opacity-100 flex items-center justify-center transition-all duration-300"
21+ @click =" chooseFile"
22+ >
23+ <div class =" text-center text-white" >
24+ <el-icon class =" text-2xl" ><camera-filled /></el-icon >
25+ <div class =" text-xs mt-1" >更换头像</div >
26+ </div >
27+ </div >
28+
29+ <input
30+ ref =" fileInput"
31+ type =" file"
32+ class =" hidden"
33+ accept =" image/*"
34+ @change =" handleFileChange"
35+ />
36+ </div >
37+ </template >
38+
39+ <script setup>
40+ import { ref } from ' vue'
41+ import { ElMessage } from ' element-plus'
42+ import { getUrl } from ' @/utils/image'
43+ import service from ' @/utils/request'
44+
45+ defineOptions ({
46+ name: ' ProfileAvatar'
47+ })
48+
49+ const { modelValue } = defineProps ({
50+ modelValue: {
51+ type: String ,
52+ default: ' '
53+ }
54+ })
55+
56+ const emit = defineEmits ([' update:modelValue' ])
57+
58+ const fileInput = ref (null )
59+
60+ const chooseFile = () => {
61+ fileInput .value .click ()
62+ }
63+
64+ const handleFileChange = async (e ) => {
65+ const file = e .target .files [0 ]
66+ if (! file) return
67+
68+ // 验证文件类型
69+ if (! file .type .includes (' image/' )) {
70+ ElMessage .error (' 请选择图片文件' )
71+ return
72+ }
73+
74+ // 验证文件大小(限制为2MB)
75+ if (file .size > 2 * 1024 * 1024 ) {
76+ ElMessage .error (' 图片大小不能超过2MB' )
77+ return
78+ }
79+
80+ try {
81+ const formData = new FormData ()
82+ formData .append (' file' , file)
83+
84+ const res = await service ({
85+ url: ' /fileUploadAndDownload/upload' ,
86+ method: ' post' ,
87+ data: formData,
88+ headers: {
89+ ' Content-Type' : ' multipart/form-data'
90+ }
91+ })
92+
93+ if (res .code === 0 && res .data ? .file ? .url ) {
94+ emit (' update:modelValue' , res .data .file .url )
95+ ElMessage .success (' 头像上传成功' )
96+ } else {
97+ ElMessage .error (res .msg || ' 上传失败' )
98+ }
99+ } catch {
100+ ElMessage .error (' 头像上传失败,请重试' )
101+ } finally {
102+ // 清空input,确保可以重复选择同一文件
103+ e .target .value = ' '
104+ }
105+ }
106+ < / script>
107+
108+ < style lang= " scss" scoped>
109+ .profile - avatar {
110+ img {
111+ @apply transition- transform duration- 300 ;
112+ }
113+
114+ & : hover {
115+ img {
116+ @apply scale- 110 ;
117+ }
118+ }
119+ }
120+ < / style>
0 commit comments