feat(头像设置): 实现七牛云头像上传功能并添加MD5校验
- 新增七牛云上传相关API调用和MD5文件校验功能 - 优化头像上传流程,先检查文件是否已存在 - 使用vant组件显示上传状态提示 - 根据协议自动选择七牛云上传地址 - 添加文件信息保存逻辑
Showing
1 changed file
with
93 additions
and
10 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-03-24 13:04:21 | 2 | * @Date: 2025-03-24 13:04:21 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-03-26 13:27:45 | 4 | + * @LastEditTime: 2025-06-06 11:22:30 |
| 5 | * @FilePath: /mlaj/src/views/profile/settings/AvatarSettingPage.vue | 5 | * @FilePath: /mlaj/src/views/profile/settings/AvatarSettingPage.vue |
| 6 | * @Description: 修改头像页面 | 6 | * @Description: 修改头像页面 |
| 7 | --> | 7 | --> |
| ... | @@ -55,10 +55,14 @@ import { ref, onMounted } from "vue"; | ... | @@ -55,10 +55,14 @@ import { ref, onMounted } from "vue"; |
| 55 | import AppLayout from "@/components/layout/AppLayout.vue"; | 55 | import AppLayout from "@/components/layout/AppLayout.vue"; |
| 56 | import FrostedGlass from "@/components/ui/FrostedGlass.vue"; | 56 | import FrostedGlass from "@/components/ui/FrostedGlass.vue"; |
| 57 | import { getUserInfoAPI, updateUserInfoAPI } from "@/api/users"; | 57 | import { getUserInfoAPI, updateUserInfoAPI } from "@/api/users"; |
| 58 | - | 58 | +import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common'; |
| 59 | +import { showToast, showLoadingToast } from 'vant'; | ||
| 60 | +import BMF from 'browser-md5-file'; | ||
| 59 | import { useTitle } from '@vueuse/core'; | 61 | import { useTitle } from '@vueuse/core'; |
| 62 | +import { useAuth } from '@/contexts/auth'; | ||
| 60 | 63 | ||
| 61 | const $route = useRoute(); | 64 | const $route = useRoute(); |
| 65 | +const { currentUser } = useAuth(); | ||
| 62 | useTitle($route.meta.title); | 66 | useTitle($route.meta.title); |
| 63 | 67 | ||
| 64 | 68 | ||
| ... | @@ -77,20 +81,99 @@ onMounted(async () => { | ... | @@ -77,20 +81,99 @@ onMounted(async () => { |
| 77 | } | 81 | } |
| 78 | }); | 82 | }); |
| 79 | 83 | ||
| 84 | +// 获取文件MD5 | ||
| 85 | +const getFileMD5 = (file) => { | ||
| 86 | + return new Promise((resolve, reject) => { | ||
| 87 | + const bmf = new BMF() | ||
| 88 | + bmf.md5(file, (err, md5) => { | ||
| 89 | + if (err) { | ||
| 90 | + reject(err) | ||
| 91 | + return | ||
| 92 | + } | ||
| 93 | + resolve(md5) | ||
| 94 | + }) | ||
| 95 | + }) | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +// 上传到七牛云 | ||
| 99 | +const uploadToQiniu = async (file, token, fileName) => { | ||
| 100 | + const formData = new FormData() | ||
| 101 | + formData.append('file', file) | ||
| 102 | + formData.append('token', token) | ||
| 103 | + formData.append('key', fileName) | ||
| 104 | + | ||
| 105 | + const config = { | ||
| 106 | + headers: { 'Content-Type': 'multipart/form-data' } | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + // 根据协议选择上传地址 | ||
| 110 | + const qiniuUploadUrl = window.location.protocol === 'https:' | ||
| 111 | + ? 'https://up.qbox.me' | ||
| 112 | + : 'http://upload.qiniu.com' | ||
| 113 | + | ||
| 114 | + return await qiniuUploadAPI(qiniuUploadUrl, formData, config) | ||
| 115 | +} | ||
| 116 | + | ||
| 80 | // 处理头像上传 | 117 | // 处理头像上传 |
| 81 | const handleAvatarChange = async (file) => { | 118 | const handleAvatarChange = async (file) => { |
| 119 | + // const toast = showLoadingToast({ | ||
| 120 | + // message: '上传中...', | ||
| 121 | + // forbidClick: true, | ||
| 122 | + // }); | ||
| 123 | + | ||
| 82 | try { | 124 | try { |
| 83 | - const formData = new FormData(); | 125 | + // 获取MD5值 |
| 84 | - formData.append("avatar", file); | 126 | + const md5 = await getFileMD5(file.file) |
| 85 | 127 | ||
| 86 | - const response = await updateUserInfoAPI(formData); | 128 | + // 获取七牛token |
| 87 | - if (response.data) { | 129 | + const tokenResult = await qiniuTokenAPI({ |
| 88 | - userAvatar.value = response.data.url; | 130 | + name: file.file.name, |
| 89 | - alert("头像上传成功"); | 131 | + hash: md5 |
| 132 | + }) | ||
| 133 | + | ||
| 134 | + // 文件已存在,直接使用 | ||
| 135 | + if (tokenResult.data) { | ||
| 136 | + userAvatar.value = tokenResult.data.src; | ||
| 137 | + // 更新用户信息 | ||
| 138 | + await updateUserInfoAPI({ avatar: tokenResult.data.src }); | ||
| 139 | + showToast('头像上传成功'); | ||
| 140 | + return; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + // 新文件上传 | ||
| 144 | + if (tokenResult.token) { | ||
| 145 | + const suffix = /.[^.]+$/.exec(file.file.name) || '' | ||
| 146 | + const fileName = `mlaj/upload/avatar/${currentUser.value.mobile}/${md5}${suffix}` | ||
| 147 | + | ||
| 148 | + const { filekey, image_info } = await uploadToQiniu( | ||
| 149 | + file.file, | ||
| 150 | + tokenResult.token, | ||
| 151 | + fileName | ||
| 152 | + ) | ||
| 153 | + | ||
| 154 | + if (filekey) { | ||
| 155 | + // 保存文件信息 | ||
| 156 | + const { data } = await saveFileAPI({ | ||
| 157 | + name: file.file.name, | ||
| 158 | + filekey, | ||
| 159 | + hash: md5, | ||
| 160 | + height: image_info?.height, | ||
| 161 | + width: image_info?.width | ||
| 162 | + }) | ||
| 163 | + | ||
| 164 | + if (data) { | ||
| 165 | + userAvatar.value = data.src; | ||
| 166 | + // 更新用户信息 | ||
| 167 | + await updateUserInfoAPI({ avatar: data.src }); | ||
| 168 | + showToast('头像上传成功'); | ||
| 169 | + } | ||
| 170 | + } | ||
| 90 | } | 171 | } |
| 91 | } catch (error) { | 172 | } catch (error) { |
| 92 | - console.error("头像上传失败:", error); | 173 | + console.error('头像上传失败:', error) |
| 93 | - alert("头像上传失败,请重试"); | 174 | + showToast('头像上传失败,请重试') |
| 175 | + } finally { | ||
| 176 | + // toast.close(); | ||
| 94 | } | 177 | } |
| 95 | }; | 178 | }; |
| 96 | </script> | 179 | </script> | ... | ... |
-
Please register or login to post a comment