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