hookehuyr

fix(avatar): 修复头像上传功能并简化流程

- 修复 src/api/common.js 中 Taro 未定义的错误
- 改用 Taro.uploadFile 直接上传到服务器
- 添加图片审核支持和样式修复
- 更新 CHANGELOG.md

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
...@@ -50,6 +50,31 @@ ...@@ -50,6 +50,31 @@
50 50
51 --- 51 ---
52 52
53 +## [2026-02-03] - 修复头像上传功能
54 +
55 +### 修复
56 +- 修复 `src/api/common.js``Taro is not defined` 错误
57 + - 添加 `import Taro from '@tarojs/taro'` 导入语句
58 + - 影响:src/api/common.js
59 +- 简化头像上传流程,改用 `Taro.uploadFile` 直接上传到服务器
60 + - 移除七牛云上传流程,改用直接上传
61 + - 添加图片审核支持(image_audit=1)
62 + - 修复头像显示样式(object-fit: cover)
63 + - 影响:src/pages/avatar/index.vue
64 +
65 +---
66 +
67 +**详细信息**
68 +- **影响文件**: src/api/common.js, src/pages/avatar/index.vue
69 +- **技术栈**: Taro 4.x, Vue 3
70 +- **测试状态**: ✅ 已通过
71 +- **备注**:
72 + - 上传流程:选择图片 → Taro.uploadFile 直接上传到服务器 → 保存头像 URL
73 + - 支持图片大小限制(5MB)
74 + - 支持图片审核,审核不通过时提示用户
75 +
76 +---
77 +
53 ## [2026-02-03] - 新增头像修改页面接口记录 78 ## [2026-02-03] - 新增头像修改页面接口记录
54 79
55 ### 文档 80 ### 文档
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
5 * @FilePath: /tswj/src/api/common.js 5 * @FilePath: /tswj/src/api/common.js
6 * @Description: 通用接口 6 * @Description: 通用接口
7 */ 7 */
8 +import Taro from '@tarojs/taro'
8 import { fn, fetch, uploadFn } from '@/api/fn'; 9 import { fn, fetch, uploadFn } from '@/api/fn';
9 10
10 const Api = { 11 const Api = {
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 <view class="flex-1 flex flex-col items-center pt-[120rpx]"> 13 <view class="flex-1 flex flex-col items-center pt-[120rpx]">
14 <view class="relative mb-[60rpx]" @tap="onChangeAvatar"> 14 <view class="relative mb-[60rpx]" @tap="onChangeAvatar">
15 <nut-avatar size="large" class="!w-[240rpx] !h-[240rpx] shadow-lg border-4 border-gray-100"> 15 <nut-avatar size="large" class="!w-[240rpx] !h-[240rpx] shadow-lg border-4 border-gray-100">
16 - <img :src="avatarUrl" /> 16 + <img :src="avatarUrl" style="object-fit: cover; width: 100%; height: 100%;" />
17 </nut-avatar> 17 </nut-avatar>
18 <view class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-black/30 rounded-full p-[16rpx]"> 18 <view class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-black/30 rounded-full p-[16rpx]">
19 <IconFont name="photograph" color="#fff" size="24" /> 19 <IconFont name="photograph" color="#fff" size="24" />
...@@ -40,16 +40,15 @@ import IconFont from '@/components/IconFont.vue' ...@@ -40,16 +40,15 @@ import IconFont from '@/components/IconFont.vue'
40 import NavHeader from '@/components/NavHeader.vue' 40 import NavHeader from '@/components/NavHeader.vue'
41 import Taro from '@tarojs/taro' 41 import Taro from '@tarojs/taro'
42 import defaultAvatar from '@/assets/images/icon/avatar.svg' 42 import defaultAvatar from '@/assets/images/icon/avatar.svg'
43 -import { uploadImageToQiniuAPI } from '@/api/common'
44 import { updateProfileAPI } from '@/api/user' 43 import { updateProfileAPI } from '@/api/user'
44 +import BASE_URL from '@/utils/config'
45 45
46 const go = useGo() 46 const go = useGo()
47 const avatarUrl = ref(defaultAvatar) 47 const avatarUrl = ref(defaultAvatar)
48 const tempAvatarUrl = ref('') // 临时存储上传后的头像URL 48 const tempAvatarUrl = ref('') // 临时存储上传后的头像URL
49 -const uploading = ref(false) // 上传状态
50 49
51 /** 50 /**
52 - * @description 更换头像 51 + * @description 更换头像(参考老来赛项目,直接上传到服务器)
53 */ 52 */
54 const onChangeAvatar = () => { 53 const onChangeAvatar = () => {
55 Taro.chooseImage({ 54 Taro.chooseImage({
...@@ -70,40 +69,49 @@ const onChangeAvatar = () => { ...@@ -70,40 +69,49 @@ const onChangeAvatar = () => {
70 69
71 // 显示上传进度 70 // 显示上传进度
72 Taro.showLoading({ title: '上传中...', mask: true }) 71 Taro.showLoading({ title: '上传中...', mask: true })
73 - uploading.value = true
74 72
75 - try { 73 + // 参考老来赛:直接用 Taro.uploadFile 上传到服务器
76 - // 上传到七牛云 74 + Taro.uploadFile({
77 - const uploadRes = await uploadImageToQiniuAPI({ 75 + url: BASE_URL + '/admin/?m=srv&a=upload&image_audit=1',
78 - filePath: tempFile.path 76 + filePath: tempFile.path,
79 - }) 77 + name: 'file',
80 - 78 + success: (uploadRes) => {
81 - Taro.hideLoading() 79 + Taro.hideLoading()
82 - uploading.value = false 80 +
83 - 81 + const data = JSON.parse(uploadRes.data)
84 - if (uploadRes.code === 1) { 82 +
85 - // 上传成功,更新头像显示 83 + // 检查是否为审核不通过
86 - avatarUrl.value = uploadRes.data.src 84 + if (data.data && data.data.audit_code == -1) {
87 - tempAvatarUrl.value = uploadRes.data.src 85 + Taro.showModal({
88 - Taro.showToast({ 86 + title: '温馨提示',
89 - title: '上传成功', 87 + content: data.msg || '图片审核不通过',
90 - icon: 'success' 88 + showCancel: false
91 - }) 89 + })
92 - } else { 90 + return
91 + }
92 +
93 + if (data.code === 0) { // 注意:老来赛后端 code=0 表示成功
94 + avatarUrl.value = data.data.src
95 + tempAvatarUrl.value = data.data.src
96 + Taro.showToast({
97 + title: '上传成功',
98 + icon: 'success'
99 + })
100 + } else {
101 + Taro.showToast({
102 + title: data.msg || '上传失败',
103 + icon: 'none'
104 + })
105 + }
106 + },
107 + fail: () => {
108 + Taro.hideLoading()
93 Taro.showToast({ 109 Taro.showToast({
94 - title: uploadRes.msg || '上传失败', 110 + title: '上传失败,请稍后重试',
95 icon: 'none' 111 icon: 'none'
96 }) 112 })
97 } 113 }
98 - } catch (err) { 114 + })
99 - Taro.hideLoading()
100 - uploading.value = false
101 - console.error('上传头像失败:', err)
102 - Taro.showToast({
103 - title: '上传失败,请稍后重试',
104 - icon: 'none'
105 - })
106 - }
107 } 115 }
108 }) 116 })
109 } 117 }
......