Files
cpzs-frontend/头像上传功能实现说明.md

5.7 KiB
Raw Permalink Blame History

头像上传功能实现说明

完成时间

2026-01-27

功能概述

将Profile页面的头像上传功能从Base64编码改为调用后端文件上传接口获取云存储URL。

实现细节

1. API接口配置

lottery-app/src/api/index.js 中已添加文件上传接口:

// 上传文件
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

响应格式:

{
  "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 中添加了上传状态标志:

data() {
  return {
    // ... 其他属性
    uploadingAvatar: false,  // 新增:头像上传状态
    // ...
  }
}

3. 头像上传方法实现

修改了 handleAvatarChange 方法:

主要改动:

  • 从读取文件为Base64改为调用 lotteryApi.uploadFile(file) 接口
  • 添加上传状态管理 (uploadingAvatar)
  • 从响应中获取 fileUrl 并设置到 editForm.userAvatar
  • 添加完整的错误处理和用户提示
  • 清空文件输入框,允许重新选择同一文件

代码实现:

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 头像预览区域

添加了上传中的遮罩层和加载动画:

<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 上传按钮

添加了禁用状态和文字变化:

<button class="upload-btn" @click="triggerFileUpload" :disabled="uploadingAvatar">
  <svg viewBox="0 0 24 24" class="camera-icon">
    <!-- SVG路径 -->
  </svg>
  {{ uploadingAvatar ? '上传中...' : '更换头像' }}
</button>

4.3 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. 建议在生产环境中添加图片压缩功能