# 小程序头像上传优化说明 ## 🔧 问题描述 **旧逻辑**: - 小程序换头像时直接保存微信临时图片路径 - 临时路径会过期,导致头像无法显示 - 数据库存储的是微信的临时URL **问题**: - ❌ 微信临时图片有效期有限(通常几天后失效) - ❌ 头像无法长期显示 - ❌ 用户体验差 --- ## ✅ 解决方案 **新逻辑**: 1. 用户选择头像后,先上传图片到自己的服务器 2. 服务器保存图片到 `public/assets/avatars/` 目录 3. 返回永久可访问的URL 4. 将永久URL保存到数据库 **优势**: - ✅ 图片永久保存在自己服务器 - ✅ 头像不会失效 - ✅ 完全可控 --- ## 🔧 修改的文件 ### 1. `miniprogram/pages/my/my.js` **修改函数**: `onChooseAvatar()` **旧逻辑**: ```javascript // 直接使用临时路径 const avatarUrl = e.detail.avatarUrl userInfo.avatar = avatarUrl // 保存临时路径到数据库 await app.request('/api/user/update', { data: { userId: userInfo.id, avatar: avatarUrl } }) ``` **新逻辑**: ```javascript // 1. 上传到服务器 const uploadRes = await wx.uploadFile({ url: app.globalData.baseUrl + '/api/upload', filePath: tempAvatarUrl, name: 'file', formData: { folder: 'avatars' } }) // 2. 获取永久URL const avatarUrl = app.globalData.baseUrl + uploadRes.data.url // 3. 保存永久URL到数据库 await app.request('/api/user/update', { data: { userId: userInfo.id, avatar: avatarUrl } }) ``` --- ### 2. `miniprogram/pages/settings/settings.js` **修改函数**: `getWechatAvatar()` **功能**: 使用 `wx.getUserProfile` 获取微信头像 **修改内容**: 与 `my.js` 相同,先上传图片再保存URL --- ## 📁 服务器存储路径 ### 图片保存位置 ``` public/assets/avatars/ ├── 1738756123456_abc123.jpg ├── 1738756234567_def456.png └── ... ``` ### 访问URL格式 ``` https://soul.quwanzhi.com/assets/avatars/1738756123456_abc123.jpg ``` ### 数据库存储 ```javascript // users 表 { id: "user_123", avatar: "https://soul.quwanzhi.com/assets/avatars/1738756123456_abc123.jpg" } ``` --- ## 🔄 上传流程 ### 完整流程图 ``` 用户点击更换头像 ↓ 微信弹出头像选择器(chooseAvatar / getUserProfile) ↓ 获取临时图片路径(tempAvatarUrl) ↓ 调用 wx.uploadFile 上传到服务器 ↓ 服务器保存图片到 public/assets/avatars/ ↓ 服务器返回永久URL ↓ 更新本地 userInfo(app.globalData / storage) ↓ 调用 /api/user/update 保存到数据库 ↓ 完成! ``` ### 代码实现 ```javascript // 1. 获取临时头像 const tempAvatarUrl = e.detail.avatarUrl // 2. 上传到服务器 const uploadRes = await new Promise((resolve, reject) => { wx.uploadFile({ url: app.globalData.baseUrl + '/api/upload', filePath: tempAvatarUrl, name: 'file', formData: { folder: 'avatars' // 保存到 avatars 文件夹 }, success: (res) => { const data = JSON.parse(res.data) if (data.success) { resolve(data) // { success: true, data: { url: '/assets/avatars/xxx.jpg' } } } else { reject(new Error(data.error)) } }, fail: reject }) }) // 3. 拼接完整URL const avatarUrl = app.globalData.baseUrl + uploadRes.data.url // 结果: https://soul.quwanzhi.com/assets/avatars/xxx.jpg // 4. 保存到数据库 await app.request('/api/user/update', { method: 'POST', data: { userId: userInfo.id, avatar: avatarUrl } }) ``` --- ## 🔍 错误处理 ### 1. 上传失败 ```javascript try { // ... 上传逻辑 } catch (e) { wx.showToast({ title: e.message || '上传失败,请重试', icon: 'none' }) } ``` ### 2. 网络错误 - 自动重试机制(可选) - 清晰的错误提示 ### 3. 文件格式错误 - 服务器会验证文件类型 - 只允许 JPG、PNG、GIF、WebP、SVG - 文件大小限制 5MB --- ## 📊 服务器API ### `/api/upload` - 图片上传接口 **请求方式**: POST (multipart/form-data) **参数**: - `file`: 图片文件 - `folder`: 保存文件夹(如 'avatars') **返回**: ```json { "success": true, "data": { "url": "/assets/avatars/1738756123456_abc123.jpg", "fileName": "1738756123456_abc123.jpg", "size": 45678, "type": "image/jpeg" } } ``` **文件命名规则**: ```javascript const timestamp = Date.now() const randomStr = Math.random().toString(36).substring(2, 8) const fileName = `${timestamp}_${randomStr}.${ext}` // 例如: 1738756123456_abc123.jpg ``` --- ## ✅ 测试清单 ### 功能测试 - [ ] 在"我的"页面点击头像,选择图片后成功上传 - [ ] 上传后头像立即显示 - [ ] 刷新页面后头像依然正常显示 - [ ] 在设置页面使用"获取微信头像"功能正常 - [ ] 后台管理页面能正确显示用户头像 ### 数据验证 - [ ] 数据库 `users.avatar` 字段保存的是完整URL - [ ] URL格式: `https://soul.quwanzhi.com/assets/avatars/xxx.jpg` - [ ] 不是微信临时路径(不包含 `weixin` 或 `tmp`) ### 文件验证 - [ ] 服务器 `public/assets/avatars/` 目录存在 - [ ] 上传的图片文件正常保存 - [ ] 文件可通过浏览器直接访问 --- ## 🚀 部署步骤 ### 1. 确保目录存在 ```bash # 在服务器上创建目录 mkdir -p /www/wwwroot/soul.quwanzhi.com/public/assets/avatars chmod 755 /www/wwwroot/soul.quwanzhi.com/public/assets/avatars ``` ### 2. 部署代码 ```bash # 本地构建 pnpm build # 部署到服务器 python devlop.py # 重启PM2 pm2 restart soul ``` ### 3. 小程序代码上传 - 在微信开发者工具中上传代码 - 提交审核 - 发布新版本 --- ## 📝 注意事项 ### 1. 兼容性 - 旧版本用户的头像可能还是微信临时路径 - 建议提示用户重新上传头像 ### 2. 存储空间 - 每个头像约 50-200KB - 10000个用户约 0.5-2GB - 定期清理无用头像(可选) ### 3. CDN优化(可选) - 如果用户量大,考虑使用CDN加速 - 将 `public/assets/avatars/` 目录同步到CDN ### 4. 图片压缩(可选) - 可以在上传时自动压缩图片 - 减少存储空间和加载时间 --- ## 🔄 数据迁移(可选) 如果需要迁移旧数据(微信临时路径 → 永久URL): ### 方案1: 提示用户重新上传 ```javascript // 在小程序中检查头像URL if (userInfo.avatar && userInfo.avatar.includes('weixin')) { // 提示用户重新上传头像 wx.showModal({ title: '头像过期', content: '请重新上传您的头像', confirmText: '立即上传' }) } ``` ### 方案2: 自动下载并上传(服务器端) ```javascript // 在服务器端批量处理 // 1. 查询所有微信临时路径的头像 // 2. 下载图片 // 3. 上传到自己服务器 // 4. 更新数据库 // (需要开发专门的迁移脚本) ``` --- ## ✅ 完成状态 - ✅ 修改 `my.js` 的 `onChooseAvatar()` 函数 - ✅ 修改 `settings.js` 的 `getWechatAvatar()` 函数 - ✅ 使用现有的 `/api/upload` 接口 - ✅ 添加错误处理和日志 - ✅ 创建说明文档 --- ## 📚 相关文档 - `后台订单显示优化说明.md` - 后台显示头像相关 - `/api/upload` 接口文档 --- **优化完成!小程序头像将永久保存在自己的服务器上,不会再失效!**