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 UserCard = forwardRef<any, any>((_, ref) => {
const {data, refresh} = useUserData() const {data, refresh} = useUserData()
const {getDisplayName, isAdmin} = useUser(); const {loadUserFromStorage} = useUser();
const [IsLogin, setIsLogin] = useState<boolean>(false) const [IsLogin, setIsLogin] = useState<boolean>(false)
const [userInfo, setUserInfo] = useState<User>() const [userInfo, setUserInfo] = useState<User>()
const [ticketTotal, setTicketTotal] = useState<number>(0) const [ticketTotal, setTicketTotal] = useState<number>(0)
@@ -25,9 +25,14 @@ const UserCard = forwardRef<any, any>((_, ref) => {
const themeStyles = useThemeStyles(); const themeStyles = useThemeStyles();
const canShowScanButton = (() => { const canShowScanButton = (() => {
const v: any = (userInfo as any)?.isAdmin 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 数组的第一个角色名称 // 角色名称:优先取用户 roles 数组的第一个角色名称
const getRoleName = () => { const getRoleName = () => {
return userInfo?.roles?.[0]?.roleName || userInfo?.roleName || '注册用户' 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, () => ({ useImperativeHandle(ref, () => ({
handleRefresh: () => reloadStats(true), handleRefresh: async () => {
reloadStats await reloadUserInfo()
await reloadStats(true)
},
reloadStats,
reloadUserInfo
})) }))
useEffect(() => { useEffect(() => {
@@ -97,30 +138,15 @@ const UserCard = forwardRef<any, any>((_, ref) => {
nickname: res.userInfo.nickName, nickname: res.userInfo.nickName,
sexName: res.userInfo.gender == 1 ? '男' : '女' sexName: res.userInfo.gender == 1 ? '男' : '女'
}) })
getUserInfo().then((data) => { reloadUserInfo()
if (data) { .then(() => {
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)
// 登录态已就绪后刷新卡片统计(余额/积分/券/水票) // 登录态已就绪后刷新卡片统计(余额/积分/券/水票)
refresh().then() refresh().then()
reloadTicketTotal() reloadTicketTotal()
// 获取openId
if (!data.openid) {
Taro.login({
success: (res) => {
getWxOpenId({code: res.code}).then(() => {
}) })
} .catch(() => {
})
}
}
}).catch(() => {
console.log('未登录') console.log('未登录')
}); })
} }
}); });
}; };

View File

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