feat(user): 添加用户信息实时同步和刷新功能

- 在个人中心页面添加用户信息实时刷新机制
- 实现用户头像和昵称修改后的同步更新
- 新增 reloadUserInfo 方法用于重新加载用户数据
- 添加本地存储同步机制保持用户信息一致性
- 优化登录状态管理和用户数据显示逻辑
- 整合微信 OpenID 获取流程到用户信息刷新过程
This commit is contained in:
2026-02-25 17:19:20 +08:00
parent 63d0d64a1f
commit 3d94125c5e
2 changed files with 53 additions and 25 deletions

View File

@@ -17,7 +17,7 @@ import { saveStorageByLoginUser } from '@/utils/server'
const UserCard = forwardRef<any, any>((_, ref) => {
const {data, refresh} = useUserData()
const {getDisplayName, isAdmin} = useUser();
const {loadUserFromStorage} = useUser();
const [IsLogin, setIsLogin] = useState<boolean>(false)
const [userInfo, setUserInfo] = useState<User>()
const [ticketTotal, setTicketTotal] = useState<number>(0)
@@ -25,9 +25,14 @@ const UserCard = forwardRef<any, any>((_, ref) => {
const themeStyles = useThemeStyles();
const canShowScanButton = (() => {
const v: any = (userInfo as any)?.isAdmin
return isAdmin() || v === true || v === 1 || v === '1'
return v === true || v === 1 || v === '1'
})()
const getDisplayName = () => {
if (!userInfo) return IsLogin ? '用户' : '点击登录'
return userInfo.nickname || (userInfo as any).realName || (userInfo as any).username || (IsLogin ? '用户' : '点击登录')
}
// 角色名称:优先取用户 roles 数组的第一个角色名称
const getRoleName = () => {
return userInfo?.roles?.[0]?.roleName || userInfo?.roleName || '注册用户'
@@ -45,10 +50,46 @@ const UserCard = forwardRef<any, any>((_, ref) => {
}
}
const syncUserToStorage = (u: User) => {
// Keep storage up-to-date for other places that read user info synchronously.
Taro.setStorageSync('User', u)
if (u?.userId) Taro.setStorageSync('UserId', u.userId)
if (u?.nickname) Taro.setStorageSync('WxNickName', u.nickname)
}
const reloadUserInfo = async () => {
try {
const u = await getUserInfo()
if (u) {
setUserInfo(u)
setIsLogin(true)
syncUserToStorage(u)
// Refresh this hook instance's state from storage (defensive).
await loadUserFromStorage()
// 获取openId不阻塞 UI 刷新)
if (!u.openid) {
Taro.login({
success: (res) => {
getWxOpenId({code: res.code}).catch(() => {})
}
})
}
}
} catch (e) {
// Not logged in / token expired: keep UI in "not login" state.
// Other error handling is done in request interceptor / callers.
}
}
// 暴露方法给父组件
useImperativeHandle(ref, () => ({
handleRefresh: () => reloadStats(true),
reloadStats
handleRefresh: async () => {
await reloadUserInfo()
await reloadStats(true)
},
reloadStats,
reloadUserInfo
}))
useEffect(() => {
@@ -97,30 +138,15 @@ const UserCard = forwardRef<any, any>((_, ref) => {
nickname: res.userInfo.nickName,
sexName: res.userInfo.gender == 1 ? '男' : '女'
})
getUserInfo().then((data) => {
if (data) {
setUserInfo(data)
setIsLogin(true);
// Keep local storage user info in sync so other hooks (e.g. unified scan) can read admin flags.
Taro.setStorageSync('User', data)
Taro.setStorageSync('UserId', data.userId)
reloadUserInfo()
.then(() => {
// 登录态已就绪后刷新卡片统计(余额/积分/券/水票)
refresh().then()
reloadTicketTotal()
// 获取openId
if (!data.openid) {
Taro.login({
success: (res) => {
getWxOpenId({code: res.code}).then(() => {
})
}
})
}
}
}).catch(() => {
console.log('未登录')
});
})
.catch(() => {
console.log('未登录')
})
}
});
};

View File

@@ -28,6 +28,8 @@ function User() {
// 每次进入/切回个人中心都刷新一次统计(包含水票数量)
useDidShow(() => {
userCardRef.current?.reloadStats?.()
// 个人资料(头像/昵称)可能在其它页面被修改,这里确保返回时立刻刷新
userCardRef.current?.reloadUserInfo?.()
})
return (