- 添加银行卡管理页面和相关API - 实现银行卡列表展示、添加、编辑和删除功能 - 优化提现页面,支持选择银行卡进行提现 - 新增 FixedButton 组件用于底部固定按钮
146 lines
4.6 KiB
Markdown
146 lines
4.6 KiB
Markdown
# 用户信息缓存丢失问题修复说明
|
||
|
||
## 问题描述
|
||
用户更新头像和昵称后,缓存中的 `UserId` 和 `Phone` 等关键字段丢失,导致应用功能异常。
|
||
|
||
## 问题分析
|
||
|
||
### 根本原因
|
||
1. **API数据不完整**:`updateUserInfo` API 可能返回不完整的用户数据
|
||
2. **本地状态覆盖**:`updateUser` 方法使用本地状态合并数据,但本地状态可能已经过时
|
||
3. **保存逻辑缺陷**:`saveUserToStorage` 函数会无条件覆盖所有字段,包括空值
|
||
|
||
### 具体问题
|
||
1. **数据流程问题**:
|
||
```typescript
|
||
// 原来的流程
|
||
const updatedUser = { ...user, ...userData }; // 使用可能过时的本地状态
|
||
await updateUserInfo(updatedUser);
|
||
```
|
||
|
||
2. **保存逻辑问题**:
|
||
```typescript
|
||
// 原来的保存逻辑
|
||
Taro.setStorageSync('UserId', userInfo.userId); // 可能为空,覆盖现有值
|
||
Taro.setStorageSync('Phone', userInfo.phone); // 可能为空,覆盖现有值
|
||
```
|
||
|
||
## 修复方案
|
||
|
||
### 1. 优化 updateUser 方法
|
||
确保在更新前获取最新的完整用户信息:
|
||
|
||
```typescript
|
||
const updateUser = async (userData: Partial<User>) => {
|
||
if (!user) {
|
||
throw new Error('用户未登录');
|
||
}
|
||
|
||
try {
|
||
// 先获取最新的用户信息,确保我们有完整的数据
|
||
const latestUserInfo = await getUserInfo();
|
||
|
||
// 合并最新的用户信息和要更新的数据
|
||
const updatedUser = { ...latestUserInfo, ...userData };
|
||
|
||
// 调用API更新用户信息
|
||
await updateUserInfo(updatedUser);
|
||
|
||
// 更新本地状态和存储
|
||
setUser(updatedUser);
|
||
const token = Taro.getStorageSync('access_token');
|
||
if (token) {
|
||
saveUserToStorage(token, updatedUser);
|
||
}
|
||
|
||
return updatedUser;
|
||
} catch (error) {
|
||
// 错误处理
|
||
throw error;
|
||
}
|
||
};
|
||
```
|
||
|
||
### 2. 改进 saveUserToStorage 函数
|
||
只在字段有值时才保存,避免覆盖现有数据:
|
||
|
||
```typescript
|
||
const saveUserToStorage = (token: string, userInfo: User) => {
|
||
try {
|
||
Taro.setStorageSync('access_token', token);
|
||
Taro.setStorageSync('User', userInfo);
|
||
|
||
// 确保关键字段不为空时才保存,避免覆盖现有数据
|
||
if (userInfo.userId) {
|
||
Taro.setStorageSync('UserId', userInfo.userId);
|
||
}
|
||
if (userInfo.tenantId) {
|
||
Taro.setStorageSync('TenantId', userInfo.tenantId);
|
||
}
|
||
if (userInfo.phone) {
|
||
Taro.setStorageSync('Phone', userInfo.phone);
|
||
}
|
||
// 保存头像和昵称信息
|
||
if (userInfo.avatar) {
|
||
Taro.setStorageSync('Avatar', userInfo.avatar);
|
||
}
|
||
if (userInfo.nickname) {
|
||
Taro.setStorageSync('Nickname', userInfo.nickname);
|
||
}
|
||
} catch (error) {
|
||
console.error('保存用户数据失败:', error);
|
||
}
|
||
};
|
||
```
|
||
|
||
## 修复效果
|
||
|
||
### ✅ 数据完整性保障
|
||
- 更新前先获取最新的完整用户信息
|
||
- 确保合并的数据包含所有必要字段
|
||
- 避免使用过时的本地状态
|
||
|
||
### ✅ 安全的存储策略
|
||
- 只在字段有值时才保存到本地存储
|
||
- 避免空值覆盖现有的有效数据
|
||
- 保护关键字段如 `UserId`、`Phone` 等
|
||
|
||
### ✅ 用户体验改善
|
||
- 用户更新头像/昵称后,所有信息保持完整
|
||
- 避免因数据丢失导致的功能异常
|
||
- 确保应用状态的一致性
|
||
|
||
## 技术细节
|
||
|
||
### 数据流程优化
|
||
1. **获取最新数据** → `getUserInfo()` 获取服务器最新信息
|
||
2. **安全合并** → `{ ...latestUserInfo, ...userData }` 确保数据完整
|
||
3. **API更新** → `updateUserInfo(updatedUser)` 提交完整数据
|
||
4. **本地同步** → `saveUserToStorage()` 安全保存到本地
|
||
|
||
### 关键修改点
|
||
1. **useUser.ts 第178-185行**:在更新前获取最新用户信息
|
||
2. **useUser.ts 第95-118行**:改进保存逻辑,避免空值覆盖
|
||
|
||
### 防护机制
|
||
- **数据验证**:保存前检查字段是否有值
|
||
- **错误处理**:完善的异常捕获和处理
|
||
- **状态同步**:确保内存状态和本地存储一致
|
||
|
||
## 测试建议
|
||
|
||
### 测试场景
|
||
1. **头像更新**:验证更新头像后 `UserId`、`Phone` 等字段保持不变
|
||
2. **昵称更新**:验证更新昵称后其他字段完整性
|
||
3. **网络异常**:验证网络异常时的数据保护
|
||
4. **并发更新**:验证多次快速更新的数据一致性
|
||
|
||
### 验证步骤
|
||
1. 登录并检查初始缓存数据
|
||
2. 更新头像,检查缓存中的 `UserId`、`Phone` 是否保持
|
||
3. 更新昵称,再次检查数据完整性
|
||
4. 重启应用,验证数据持久化
|
||
|
||
## 总结
|
||
通过优化数据获取流程和改进存储策略,我们解决了用户信息缓存丢失问题,确保了数据的完整性和一致性,提升了应用的稳定性和用户体验。
|