更新项目代码:新增彩种模块、组件优化、管理后台功能完善
This commit is contained in:
241
头像上传功能实现说明.md
Normal file
241
头像上传功能实现说明.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# 头像上传功能实现说明
|
||||
|
||||
## 完成时间
|
||||
2026-01-27
|
||||
|
||||
## 功能概述
|
||||
将Profile页面的头像上传功能从Base64编码改为调用后端文件上传接口,获取云存储URL。
|
||||
|
||||
## 实现细节
|
||||
|
||||
### 1. API接口配置
|
||||
在 `lottery-app/src/api/index.js` 中已添加文件上传接口:
|
||||
|
||||
```javascript
|
||||
// 上传文件
|
||||
uploadFile(file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return api.post('/file/upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
**接口地址**: `POST /api/file/upload`
|
||||
|
||||
**请求格式**: `multipart/form-data`
|
||||
|
||||
**响应格式**:
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"fileName": "a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpg",
|
||||
"fileUrl": "https://yicaishuzhi-1326058838.cos.ap-beijing.myqcloud.com/a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpg",
|
||||
"originalFilename": "avatar.jpg"
|
||||
},
|
||||
"message": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 数据状态管理
|
||||
在 `lottery-app/src/views/Profile.vue` 的 data 中添加了上传状态标志:
|
||||
|
||||
```javascript
|
||||
data() {
|
||||
return {
|
||||
// ... 其他属性
|
||||
uploadingAvatar: false, // 新增:头像上传状态
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 头像上传方法实现
|
||||
修改了 `handleAvatarChange` 方法:
|
||||
|
||||
**主要改动**:
|
||||
- 从读取文件为Base64改为调用 `lotteryApi.uploadFile(file)` 接口
|
||||
- 添加上传状态管理 (`uploadingAvatar`)
|
||||
- 从响应中获取 `fileUrl` 并设置到 `editForm.userAvatar`
|
||||
- 添加完整的错误处理和用户提示
|
||||
- 清空文件输入框,允许重新选择同一文件
|
||||
|
||||
**代码实现**:
|
||||
```javascript
|
||||
async handleAvatarChange(event) {
|
||||
const file = event.target.files[0]
|
||||
if (!file) return
|
||||
|
||||
// 验证文件类型
|
||||
if (!file.type.startsWith('image/')) {
|
||||
this.$toast.error('请选择图片文件')
|
||||
return
|
||||
}
|
||||
|
||||
// 验证文件大小(限制2MB)
|
||||
if (file.size > 2 * 1024 * 1024) {
|
||||
this.$toast.error('图片大小不能超过2MB')
|
||||
return
|
||||
}
|
||||
|
||||
this.uploadingAvatar = true
|
||||
try {
|
||||
// 显示上传提示
|
||||
this.$toast.info('正在上传头像...')
|
||||
|
||||
// 调用上传接口
|
||||
const response = await lotteryApi.uploadFile(file)
|
||||
|
||||
if (response.code === 0 && response.data && response.data.fileUrl) {
|
||||
// 上传成功,设置头像URL
|
||||
this.editForm.userAvatar = response.data.fileUrl
|
||||
this.$toast.success('头像上传成功!')
|
||||
} else {
|
||||
this.$toast.error(response.message || '头像上传失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('头像上传失败:', error)
|
||||
this.$toast.error('头像上传失败,请稍后重试')
|
||||
} finally {
|
||||
this.uploadingAvatar = false
|
||||
// 清空文件输入框,允许重新选择同一文件
|
||||
event.target.value = ''
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. UI交互优化
|
||||
|
||||
#### 4.1 头像预览区域
|
||||
添加了上传中的遮罩层和加载动画:
|
||||
|
||||
```vue
|
||||
<div class="avatar-preview" :class="{ 'uploading': uploadingAvatar }">
|
||||
<img v-if="editForm.userAvatar" :src="editForm.userAvatar" alt="头像" />
|
||||
<div v-else class="avatar-placeholder">{{ editForm.userName ? editForm.userName.charAt(0) : 'U' }}</div>
|
||||
<div v-if="uploadingAvatar" class="upload-overlay">
|
||||
<div class="upload-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 4.2 上传按钮
|
||||
添加了禁用状态和文字变化:
|
||||
|
||||
```vue
|
||||
<button class="upload-btn" @click="triggerFileUpload" :disabled="uploadingAvatar">
|
||||
<svg viewBox="0 0 24 24" class="camera-icon">
|
||||
<!-- SVG路径 -->
|
||||
</svg>
|
||||
{{ uploadingAvatar ? '上传中...' : '更换头像' }}
|
||||
</button>
|
||||
```
|
||||
|
||||
#### 4.3 CSS样式
|
||||
添加了以下样式:
|
||||
|
||||
```css
|
||||
/* 禁用状态 */
|
||||
.upload-btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
background: #f5f5f5;
|
||||
border-color: #e0e6ed;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 上传遮罩层 */
|
||||
.upload-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* 加载动画 */
|
||||
.upload-spinner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.3);
|
||||
border-top-color: white;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
```
|
||||
|
||||
## 功能特性
|
||||
|
||||
### ✅ 已实现
|
||||
1. **文件验证**
|
||||
- 验证文件类型(仅允许图片)
|
||||
- 验证文件大小(限制2MB)
|
||||
|
||||
2. **上传流程**
|
||||
- 调用后端上传接口
|
||||
- 获取云存储URL
|
||||
- 更新头像预览
|
||||
|
||||
3. **用户反馈**
|
||||
- 上传中提示
|
||||
- 上传成功提示
|
||||
- 上传失败提示
|
||||
- 按钮禁用状态
|
||||
- 加载动画
|
||||
|
||||
4. **错误处理**
|
||||
- 网络错误处理
|
||||
- 接口错误处理
|
||||
- 文件验证错误处理
|
||||
|
||||
5. **用户体验**
|
||||
- 上传中显示遮罩和加载动画
|
||||
- 按钮文字动态变化
|
||||
- 清空文件输入框,允许重新选择
|
||||
|
||||
## 测试建议
|
||||
|
||||
### 1. 功能测试
|
||||
- [ ] 选择图片文件,验证上传成功
|
||||
- [ ] 选择非图片文件,验证错误提示
|
||||
- [ ] 选择超过2MB的图片,验证错误提示
|
||||
- [ ] 上传过程中验证按钮禁用
|
||||
- [ ] 上传成功后验证头像更新
|
||||
- [ ] 保存用户信息后验证头像持久化
|
||||
|
||||
### 2. UI测试
|
||||
- [ ] 验证上传中的遮罩层显示
|
||||
- [ ] 验证加载动画正常运行
|
||||
- [ ] 验证按钮文字变化
|
||||
- [ ] 验证按钮禁用样式
|
||||
|
||||
### 3. 错误场景测试
|
||||
- [ ] 网络断开时上传
|
||||
- [ ] 后端接口返回错误
|
||||
- [ ] 上传超时处理
|
||||
|
||||
## 相关文件
|
||||
- `lottery-app/src/views/Profile.vue` - 主要实现文件
|
||||
- `lottery-app/src/api/index.js` - API接口定义
|
||||
|
||||
## 开发服务器
|
||||
当前运行在: http://localhost:5174/
|
||||
|
||||
## 注意事项
|
||||
1. 确保后端 `/api/file/upload` 接口正常运行
|
||||
2. 确保云存储服务配置正确
|
||||
3. 上传的图片URL需要支持跨域访问
|
||||
4. 建议在生产环境中添加图片压缩功能
|
||||
Reference in New Issue
Block a user