feat(dealer/customer): 实现客户列表的无限滚动和搜索功能- 在客户列表页面添加 InfiniteLoading 组件,实现无限滚动加载- 添加搜索功能,支持按关键词搜索客户
- 优化数据加载逻辑,解决重复请求问题 - 在 Header 组件中增加用户登录状态和信息的检查
This commit is contained in:
@@ -231,7 +231,7 @@ const CustomerIndex = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="p-4" style={{
|
<View className="p-4" style={{
|
||||||
height: '75vh',
|
height: '90vh',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
overflowX: 'hidden'
|
overflowX: 'hidden'
|
||||||
}}>
|
}}>
|
||||||
@@ -257,7 +257,7 @@ const CustomerIndex = () => {
|
|||||||
description={loading ? "加载中..." : "暂无客户数据"}
|
description={loading ? "加载中..." : "暂无客户数据"}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<View className={'h-12 flex items-center justify-center'}>
|
<View className={'h-3 flex items-center justify-center'}>
|
||||||
<Text className="text-gray-500 text-sm">没有更多了</Text>
|
<Text className="text-gray-500 text-sm">没有更多了</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -94,9 +94,17 @@ export const useUser = () => {
|
|||||||
try {
|
try {
|
||||||
Taro.setStorageSync('access_token', token);
|
Taro.setStorageSync('access_token', token);
|
||||||
Taro.setStorageSync('User', userInfo);
|
Taro.setStorageSync('User', userInfo);
|
||||||
Taro.setStorageSync('UserId', userInfo.userId);
|
|
||||||
Taro.setStorageSync('TenantId', userInfo.tenantId);
|
// 确保关键字段不为空时才保存,避免覆盖现有数据
|
||||||
Taro.setStorageSync('Phone', userInfo.phone);
|
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) {
|
if (userInfo.avatar) {
|
||||||
Taro.setStorageSync('Avatar', userInfo.avatar);
|
Taro.setStorageSync('Avatar', userInfo.avatar);
|
||||||
@@ -172,9 +180,16 @@ export const useUser = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const updatedUser = { ...user, ...userData };
|
// 先获取最新的用户信息,确保我们有完整的数据
|
||||||
|
const latestUserInfo = await getUserInfo();
|
||||||
|
|
||||||
|
// 合并最新的用户信息和要更新的数据
|
||||||
|
const updatedUser = { ...latestUserInfo, ...userData };
|
||||||
|
|
||||||
|
// 调用API更新用户信息
|
||||||
await updateUserInfo(updatedUser);
|
await updateUserInfo(updatedUser);
|
||||||
|
|
||||||
|
// 更新本地状态
|
||||||
setUser(updatedUser);
|
setUser(updatedUser);
|
||||||
|
|
||||||
// 更新本地存储
|
// 更新本地存储
|
||||||
|
|||||||
132
头像昵称同步问题修复说明.md
Normal file
132
头像昵称同步问题修复说明.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# 头像昵称同步问题修复说明
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
用户更新了头像和昵称后,首页仍然提示"您还没有上传头像和昵称",导致用户体验不佳。
|
||||||
|
|
||||||
|
## 问题分析
|
||||||
|
|
||||||
|
### 根本原因
|
||||||
|
1. **检查逻辑错误**:`Header.tsx` 中检查的是 `Taro.getStorageSync('Avatar')`,但这个字段从未被设置过
|
||||||
|
2. **数据同步缺失**:`useUser` hook 中的 `saveUserToStorage` 函数没有保存头像和昵称到本地存储
|
||||||
|
3. **状态不一致**:用户信息更新后,本地存储和 `useUser` hook 状态不同步
|
||||||
|
|
||||||
|
### 具体问题
|
||||||
|
1. **Header.tsx 第42行**:
|
||||||
|
```typescript
|
||||||
|
if(!Taro.getStorageSync('Avatar')){
|
||||||
|
// 提示用户上传头像和昵称
|
||||||
|
}
|
||||||
|
```
|
||||||
|
这里检查的 `Avatar` 字段从未被保存到本地存储
|
||||||
|
|
||||||
|
2. **useUser.ts saveUserToStorage 函数**:
|
||||||
|
```typescript
|
||||||
|
const saveUserToStorage = (token: string, userInfo: User) => {
|
||||||
|
Taro.setStorageSync('access_token', token);
|
||||||
|
Taro.setStorageSync('User', userInfo);
|
||||||
|
Taro.setStorageSync('UserId', userInfo.userId);
|
||||||
|
Taro.setStorageSync('TenantId', userInfo.tenantId);
|
||||||
|
Taro.setStorageSync('Phone', userInfo.phone);
|
||||||
|
// 缺少头像和昵称的保存
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 修复方案
|
||||||
|
|
||||||
|
### 1. 修复 saveUserToStorage 函数
|
||||||
|
在 `src/hooks/useUser.ts` 中添加头像和昵称的保存:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const saveUserToStorage = (token: string, userInfo: User) => {
|
||||||
|
try {
|
||||||
|
Taro.setStorageSync('access_token', token);
|
||||||
|
Taro.setStorageSync('User', userInfo);
|
||||||
|
Taro.setStorageSync('UserId', userInfo.userId);
|
||||||
|
Taro.setStorageSync('TenantId', userInfo.tenantId);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 优化 Header.tsx 检查逻辑
|
||||||
|
在 `src/pages/index/Header.tsx` 中改进检查逻辑:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 检查用户是否已登录并且有头像和昵称
|
||||||
|
if (isLoggedIn) {
|
||||||
|
const hasAvatar = user?.avatar || Taro.getStorageSync('Avatar');
|
||||||
|
const hasNickname = user?.nickname || Taro.getStorageSync('Nickname');
|
||||||
|
|
||||||
|
if (!hasAvatar || !hasNickname) {
|
||||||
|
Taro.showToast({
|
||||||
|
title: '您还没有上传头像和昵称',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: '/user/profile/profile'
|
||||||
|
})
|
||||||
|
}, 3000)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 修复效果
|
||||||
|
|
||||||
|
### ✅ 数据同步
|
||||||
|
- 用户更新头像/昵称后,信息会同时保存到 `useUser` hook 状态和本地存储
|
||||||
|
- 确保数据的一致性和持久化
|
||||||
|
|
||||||
|
### ✅ 检查逻辑优化
|
||||||
|
- 同时检查 `useUser` hook 中的用户信息和本地存储
|
||||||
|
- 提供双重保障,确保检查的准确性
|
||||||
|
|
||||||
|
### ✅ 用户体验改善
|
||||||
|
- 用户更新头像/昵称后不再收到错误提示
|
||||||
|
- 信息更新立即生效,无需重新登录
|
||||||
|
|
||||||
|
## 技术细节
|
||||||
|
|
||||||
|
### 数据流程
|
||||||
|
1. **用户更新信息** → `profile.tsx` 调用 `updateUser()`
|
||||||
|
2. **updateUser()** → 调用 API 更新服务器数据
|
||||||
|
3. **更新成功** → 调用 `saveUserToStorage()` 保存到本地
|
||||||
|
4. **本地存储** → 同时更新 `useUser` 状态和 Taro 存储
|
||||||
|
5. **Header 检查** → 检查两个数据源确保准确性
|
||||||
|
|
||||||
|
### 关键修改点
|
||||||
|
1. **useUser.ts 第99-106行**:添加头像和昵称的本地存储
|
||||||
|
2. **Header.tsx 第41-58行**:优化检查逻辑,支持双重验证
|
||||||
|
|
||||||
|
### 兼容性
|
||||||
|
- 向后兼容:旧的检查逻辑仍然有效
|
||||||
|
- 渐进增强:新的检查逻辑提供更好的准确性
|
||||||
|
- 数据迁移:现有用户的数据会在下次更新时自动同步
|
||||||
|
|
||||||
|
## 测试建议
|
||||||
|
|
||||||
|
### 测试场景
|
||||||
|
1. **新用户注册**:验证首次上传头像/昵称后不再提示
|
||||||
|
2. **现有用户更新**:验证更新头像/昵称后立即生效
|
||||||
|
3. **应用重启**:验证重启应用后信息仍然正确
|
||||||
|
4. **网络异常**:验证网络异常时的降级处理
|
||||||
|
|
||||||
|
### 验证步骤
|
||||||
|
1. 清除应用数据
|
||||||
|
2. 登录并上传头像/昵称
|
||||||
|
3. 返回首页检查是否还有提示
|
||||||
|
4. 重启应用再次检查
|
||||||
|
5. 修改头像/昵称并验证同步
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
通过修复 `saveUserToStorage` 函数和优化 `Header.tsx` 的检查逻辑,我们解决了头像昵称同步问题,确保用户更新信息后能够立即生效,提升了用户体验。
|
||||||
145
用户信息缓存丢失问题修复说明.md
Normal file
145
用户信息缓存丢失问题修复说明.md
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# 用户信息缓存丢失问题修复说明
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
用户更新头像和昵称后,缓存中的 `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. 重启应用,验证数据持久化
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
通过优化数据获取流程和改进存储策略,我们解决了用户信息缓存丢失问题,确保了数据的完整性和一致性,提升了应用的稳定性和用户体验。
|
||||||
Reference in New Issue
Block a user