262 lines
5.9 KiB
Markdown
262 lines
5.9 KiB
Markdown
# 个人资料功能开发方案
|
||
|
||
## 📋 功能清单
|
||
|
||
### 1. 头像上传功能 ✅
|
||
- 点击头像选择图片
|
||
- 上传到服务器
|
||
- 更新用户头像
|
||
|
||
### 2. 生日选择 ✅
|
||
- 日期选择器
|
||
- 保存生日信息
|
||
|
||
### 3. 所在地区选择 ✅
|
||
- 省市区三级联动
|
||
- 保存地区信息
|
||
|
||
### 4. 实名认证 ⚠️
|
||
- 需要后端接口支持
|
||
- 暂时显示"功能开发中"
|
||
|
||
### 5. 保存修改 ✅
|
||
- 调用后端API保存所有修改
|
||
|
||
## 🔧 后端API状态
|
||
|
||
### 已有接口
|
||
|
||
**1. 获取个人资料**
|
||
```
|
||
GET /api/user/profile
|
||
Response: {
|
||
id, nickname, phone, gender, birthday,
|
||
region, avatar, createTime, role
|
||
}
|
||
```
|
||
|
||
**2. 更新个人资料**
|
||
```
|
||
PUT /api/user/profile
|
||
Body: {
|
||
nickname, gender, birthday, avatar, region
|
||
}
|
||
```
|
||
|
||
### 需要添加的接口
|
||
|
||
**1. 头像上传**
|
||
```java
|
||
@PostMapping("/upload-avatar")
|
||
public Result<String> uploadAvatar(@CurrentUser Long userId,
|
||
@RequestParam("file") MultipartFile file) {
|
||
// 1. 验证文件类型(jpg, png, jpeg)
|
||
// 2. 验证文件大小(< 5MB)
|
||
// 3. 生成唯一文件名
|
||
// 4. 保存到服务器或OSS
|
||
// 5. 返回文件URL
|
||
return Result.success(fileUrl);
|
||
}
|
||
```
|
||
|
||
**2. 实名认证**
|
||
```java
|
||
@PostMapping("/real-name-auth")
|
||
public Result<?> realNameAuth(@CurrentUser Long userId,
|
||
@RequestBody RealNameDTO dto) {
|
||
// dto包含:realName, idCard, idCardFront, idCardBack
|
||
// 1. 验证身份证号格式
|
||
// 2. 调用第三方实名认证API
|
||
// 3. 更新用户实名状态
|
||
return Result.success();
|
||
}
|
||
```
|
||
|
||
## 📱 前端实现
|
||
|
||
### 修改文件
|
||
`peidu/uniapp/src/user-package/pages/user/profile.vue`
|
||
|
||
### 关键功能实现
|
||
|
||
#### 1. 生日选择器
|
||
```javascript
|
||
selectBirthday() {
|
||
uni.showModal({
|
||
title: '选择生日',
|
||
editable: false,
|
||
content: '请使用日期选择器',
|
||
showCancel: false
|
||
})
|
||
|
||
// 使用uni-app的picker组件
|
||
// mode="date"
|
||
}
|
||
```
|
||
|
||
#### 2. 地区选择器
|
||
```javascript
|
||
selectRegion() {
|
||
uni.chooseLocation({
|
||
success: (res) => {
|
||
this.userInfo.region = res.address
|
||
}
|
||
})
|
||
|
||
// 或使用省市区三级联动组件
|
||
}
|
||
```
|
||
|
||
#### 3. 头像上传
|
||
```javascript
|
||
async changeAvatar() {
|
||
uni.chooseImage({
|
||
count: 1,
|
||
sizeType: ['compressed'],
|
||
sourceType: ['album', 'camera'],
|
||
success: async (res) => {
|
||
const tempFilePath = res.tempFilePaths[0]
|
||
await this.uploadAvatar(tempFilePath)
|
||
}
|
||
})
|
||
}
|
||
|
||
async uploadAvatar(filePath) {
|
||
uni.showLoading({ title: '上传中...' })
|
||
|
||
try {
|
||
// 方案1:使用uni.uploadFile
|
||
const uploadRes = await uni.uploadFile({
|
||
url: 'http://your-server/api/user/upload-avatar',
|
||
filePath: filePath,
|
||
name: 'file',
|
||
header: {
|
||
'Authorization': 'Bearer ' + uni.getStorageSync('token')
|
||
}
|
||
})
|
||
|
||
const data = JSON.parse(uploadRes.data)
|
||
if (data.code === 200) {
|
||
this.userInfo.avatar = data.data
|
||
uni.showToast({ title: '上传成功', icon: 'success' })
|
||
}
|
||
} catch (error) {
|
||
uni.showToast({ title: '上传失败', icon: 'none' })
|
||
} finally {
|
||
uni.hideLoading()
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 4. 保存修改
|
||
```javascript
|
||
async saveProfile() {
|
||
try {
|
||
uni.showLoading({ title: '保存中...' })
|
||
|
||
const res = await userApi.updateUserInfo({
|
||
nickname: this.userInfo.nickname,
|
||
gender: this.userInfo.gender,
|
||
birthday: this.userInfo.birthday,
|
||
region: this.userInfo.region,
|
||
avatar: this.userInfo.avatar
|
||
})
|
||
|
||
if (res && res.code === 200) {
|
||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||
// 更新本地存储
|
||
uni.setStorageSync('userInfo', this.userInfo)
|
||
// 1秒后返回
|
||
setTimeout(() => {
|
||
uni.navigateBack()
|
||
}, 1000)
|
||
}
|
||
} catch (e) {
|
||
uni.showToast({ title: '保存失败', icon: 'none' })
|
||
} finally {
|
||
uni.hideLoading()
|
||
}
|
||
}
|
||
```
|
||
|
||
## 🚀 实施步骤
|
||
|
||
### 第1步:添加后端头像上传接口
|
||
|
||
在 `UserController.java` 中添加:
|
||
|
||
```java
|
||
@Autowired
|
||
private FileService fileService; // 需要创建文件服务
|
||
|
||
@ApiOperation("上传头像")
|
||
@PostMapping("/upload-avatar")
|
||
public Result<String> uploadAvatar(@CurrentUser Long userId,
|
||
@RequestParam("file") MultipartFile file) {
|
||
try {
|
||
// 验证文件
|
||
if (file.isEmpty()) {
|
||
return Result.error("文件不能为空");
|
||
}
|
||
|
||
String contentType = file.getContentType();
|
||
if (!contentType.startsWith("image/")) {
|
||
return Result.error("只能上传图片文件");
|
||
}
|
||
|
||
if (file.getSize() > 5 * 1024 * 1024) {
|
||
return Result.error("文件大小不能超过5MB");
|
||
}
|
||
|
||
// 上传文件
|
||
String fileUrl = fileService.uploadFile(file, "avatar");
|
||
|
||
// 更新用户头像
|
||
User user = new User();
|
||
user.setId(userId);
|
||
user.setAvatar(fileUrl);
|
||
userService.updateById(user);
|
||
|
||
return Result.success(fileUrl);
|
||
} catch (Exception e) {
|
||
log.error("上传头像失败", e);
|
||
return Result.error("上传失败:" + e.getMessage());
|
||
}
|
||
}
|
||
```
|
||
|
||
### 第2步:修改前端profile.vue
|
||
|
||
完整的修改内容较多,关键修改点:
|
||
|
||
1. **添加生日选择器**
|
||
2. **添加地区选择器**
|
||
3. **完善头像上传**
|
||
4. **完善保存功能**
|
||
|
||
### 第3步:测试
|
||
|
||
1. 测试头像上传
|
||
2. 测试生日选择
|
||
3. 测试地区选择
|
||
4. 测试保存功能
|
||
|
||
## 📝 注意事项
|
||
|
||
1. **头像上传**需要后端支持文件上传和存储
|
||
2. **实名认证**需要对接第三方API(如阿里云实人认证)
|
||
3. **地区选择**可以使用uni-app的`uni.chooseLocation`或自定义省市区组件
|
||
4. **生日选择**使用`picker`组件,`mode="date"`
|
||
|
||
## 🎯 优先级
|
||
|
||
1. **高优先级**:生日选择、保存修改
|
||
2. **中优先级**:头像上传
|
||
3. **低优先级**:地区选择、实名认证
|
||
|
||
## 📅 创建时间
|
||
2026-01-28
|
||
|
||
## 👤 创建人员
|
||
Kiro AI Assistant
|