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
|