import React, { useEffect, useState } from 'react' import { View, Text, Image, ScrollView } from '@tarojs/components' import Taro, { useDidShow } from '@tarojs/taro' import { useUser } from '@/hooks/useUser' import { useScrollHeight } from '@/hooks/useScrollHeight' import { useRequest } from '@/hooks/useRequest' import { getUserCardStats, getUserOrderStats } from '@/api/shop/shopUserCard' import { getMyClerk } from '@/api/shop/shopStoreUser' import { listUserRole } from '@/api/system/userRole' import type { UserRole } from '@/api/system/userRole/model' import { checkAndCacheVipStatus } from '@/utils/vip' import MemberBadge from '@/components/business/MemberBadge' const UserPage: React.FC = () => { const scrollHeight = useScrollHeight() const { user, isLoggedIn, loading: userLoading, refreshUser, syncFromStorage } = useUser() // 查询门店关联信息 const [storeInfo, setStoreInfo] = useState(null) // 用户角色列表 const [userRoles, setUserRoles] = useState([]) // 获取用户卡片统计(余额/积分/优惠券/礼品卡) // stale-while-revalidate: 缓存命中即时展示 + 后台静默刷新 // localStorage 持久化: 冷启动先读 storage 即时展示,避免骨架屏 const { data: cardStats, run: runCardStats, loading: cardStatsLoading, mutate: mutateCardStats } = useRequest(getUserCardStats, { manual: true, cacheKey: 'user_card_stats', cacheTime: 30 * 1000, onSuccess: (data) => { // 请求成功后持久化到本地存储,下次冷启动可直接展示 Taro.setStorageSync('user_card_stats_v2', data) }, }) // 获取用户订单统计(同上 stale-while-revalidate + localStorage 持久化) const { data: orderStats, run: runOrderStats, loading: orderStatsLoading, mutate: mutateOrderStats } = useRequest(getUserOrderStats, { manual: true, cacheKey: 'user_order_stats', cacheTime: 30 * 1000, onSuccess: (data) => { Taro.setStorageSync('user_order_stats_v2', data) }, }) // 登录后加载数据 useEffect(() => { if (isLoggedIn) { // 冷启动优化:先从 localStorage 读取缓存即时展示,消除骨架屏 const cachedCardStats = Taro.getStorageSync('user_card_stats_v2') if (cachedCardStats) mutateCardStats(cachedCardStats) const cachedOrderStats = Taro.getStorageSync('user_order_stats_v2') if (cachedOrderStats) mutateOrderStats(cachedOrderStats) // 然后发起网络请求(stale-while-revalidate 后台刷新) runCardStats() runOrderStats() // 查询门店关联 getMyClerk().then(data => setStoreInfo(data)).catch(() => setStoreInfo(null)) // 查询用户角色 listUserRole({ userId: user?.userId }).then(data => setUserRoles(data || [])).catch(() => setUserRoles([])) // 检查并缓存 VIP 状态 checkAndCacheVipStatus((user as any)?.userId || (user as any)?.id) } else { setStoreInfo(null) setUserRoles([]) } }, [isLoggedIn]) // 每次页面重新显示时(从登录页返回、从其他页面返回)检查登录状态并刷新数据 useDidShow(() => { // 先从 storage 快速同步,立即更新 UI(无网络延迟) const hasUser = syncFromStorage() if (hasUser) { // 冷启动优化:先从 localStorage 读取上次缓存的数据即时展示,消除骨架屏 const cachedCardStats = Taro.getStorageSync('user_card_stats_v2') if (cachedCardStats) { mutateCardStats(cachedCardStats) } const cachedOrderStats = Taro.getStorageSync('user_order_stats_v2') if (cachedOrderStats) { mutateOrderStats(cachedOrderStats) } // 然后发起网络请求(stale-while-revalidate 自动在后台刷新) runCardStats() runOrderStats() // 刷新门店关联 getMyClerk().then(data => setStoreInfo(data)).catch(() => setStoreInfo(null)) // 刷新用户角色 const userId = Taro.getStorageSync('UserId') if (userId) { listUserRole({ userId }).then(data => setUserRoles(data || [])).catch(() => {}) // 刷新 VIP 状态缓存 checkAndCacheVipStatus(userId) } } }) const menuItems = [ // 升级VIP会员 - 醒目样式 { icon: '👑', label: '升级VIP会员', url: '/pages/user/vip-upgrade/index', highlight: true }, // 门店中心:仅门店店员/店长显示(通过 /shop/shop-store-user/my 判断) ...(storeInfo ? [{ icon: '🏪', label: '门店中心', url: '/pages/store/center/index' }] : []), { icon: '💰', label: '我的钱包', url: '/pages/user/wallet' }, { icon: '📍', label: '收货地址', url: '/pages/user/address-list' }, // { icon: '⭐', label: '积分明细', url: '/pages/user/points-record' }, { icon: '❤️', label: '我的收藏', url: '/pages/user/favorite-list/index' }, // { icon: '🕐', label: '浏览历史', url: '/pages/user/history-list/index' }, { icon: '❓', label: '帮助中心', url: '/pages/user/help-center/index' }, // { icon: '🔔', label: '消息通知', url: '/pages/index/notification' }, // 门店管理:仅门店经理/店员显示 // ...(storeInfo ? [{ icon: '🏪', label: '门店管理', url: '/pages/store/list/index' }] : []), { icon: '⚙️', label: '设置', url: '/pages/user/setting' }, ] const handleAvatarClick = () => { if (!isLoggedIn) { Taro.navigateTo({ url: '/passport/login' }) } else { Taro.navigateTo({ url: '/pages/user/profile' }) } } const loading = cardStatsLoading || orderStatsLoading // 是否有可用数据(缓存或请求结果),用于判断是否需要骨架屏 const hasCardData = !!cardStats const hasOrderData = !!orderStats // 下拉刷新状态 const [refreshing, setRefreshing] = useState(false) // 下拉刷新:同时刷新用户信息、卡片统计、订单统计、角色 const onRefresh = async () => { if (!isLoggedIn) { setRefreshing(false); return } setRefreshing(true) try { await Promise.all([refreshUser(), runCardStats(), runOrderStats()]) // 刷新角色 const uid = user?.userId if (uid) { listUserRole({ userId: uid }).then(data => setUserRoles(data || [])).catch(() => {}) // 刷新 VIP 状态 checkAndCacheVipStatus(uid) } } finally { setRefreshing(false) } } return ( {/* 用户信息卡片 */} {/* 装饰性光晕 */} {isLoggedIn && user?.avatar ? ( ) : ( 👤 )} {isLoggedIn ? (user?.nickname || user?.phone || '用户') : '点击登录'} {/*{isLoggedIn && (*/} {/* */} {/* {(user as any)?.memberLevelName || '普通用户'}*/} {/* */} {/*)}*/} {userRoles.map(role => ( {role.roleName} ))} {isLoggedIn && {'>'}} {/* 数据概览 */} {isLoggedIn && ( Taro.navigateTo({ url: '/pages/user/wallet' })}> {!hasCardData ? ( ) : ( {cardStats?.balance || '0.00'} )} 余额 Taro.navigateTo({ url: '/pages/user/points-record' })}> {!hasCardData ? ( ) : ( {cardStats?.points || (user as any)?.points || 0} )} 积分 Taro.navigateTo({ url: '/pages/user/coupon-list' })}> {!hasCardData ? ( ) : ( {cardStats?.coupons || 0} )} 优惠券 )} {/* 我的订单快捷入口 */} 我的订单 Taro.switchTab({ url: '/pages/order/list' })}> 全部订单 {'>'} {[ { icon: '💳', label: '待付款', status: 0, count: orderStats?.pending }, { icon: '📦', label: '待发货', status: 1, count: orderStats?.paid }, { icon: '🚚', label: '待收货', status: 2, count: orderStats?.shipped }, { icon: '✅', label: '已完成', status: 3, count: orderStats?.completed }, ].map(item => ( { Taro.setStorageSync('order_tab', item.status); Taro.switchTab({ url: '/pages/order/list' }) }} > {item.icon} {item.label} {/* 数量角标 */} {item.count && item.count > 0 && ( {item.count > 99 ? '99+' : item.count} )} ))} {/* 功能菜单 */} {menuItems.map((item, idx) => ( Taro.navigateTo({ url: item.url })} > {(item as any).highlight ? '' : item.icon}{(item as any).highlight ? item.icon : ''} {item.label} {(item as any).highlight && ( 推荐 )} {'>'} ))} ) } export default UserPage