feat(user): 添加用户卡片统计数据接口和优化性能

- 新增 UserCardStats 接口定义余额/积分/优惠券/礼品卡数据结构
- 实现 getUserCardStats 函数聚合返回用户卡片统计数据
- 替换原有多个独立请求为单一聚合接口提升性能
- 修改 useUserData Hook 使用新聚合接口并调整数据类型
- 移除废弃的 pageShopOrder 和相关 API 导入
- 优化用户登录后自动刷新卡片统计数据逻辑
This commit is contained in:
2026-01-20 12:47:22 +08:00
parent 0542b93dc7
commit 415e05cc4e
5 changed files with 45 additions and 35 deletions

View File

@@ -43,6 +43,15 @@ export interface UserOrderStats {
total: number
}
// 用户卡片统计(个人中心头部:余额/积分/优惠券/礼品卡)
export interface UserCardStats {
balance: string
points: number
coupons: number
giftCards: number
lastUpdateTime?: string
}
// 用户完整数据
export interface UserDashboard {
balance: UserBalance
@@ -108,6 +117,17 @@ export async function getUserOrderStats() {
return Promise.reject(new Error(res.message))
}
/**
* 获取用户卡片统计(一次性返回余额/积分/可用优惠券/未使用礼品卡数量)
*/
export async function getUserCardStats() {
const res = await request.get<ApiResult<UserCardStats>>('/user/card/stats')
if (res.code === 0 && res.data) {
return res.data
}
return Promise.reject(new Error(res.message))
}
/**
* 获取用户完整仪表板数据(一次性获取所有数据)
*/

View File

@@ -1,7 +1,6 @@
import { useState, useEffect, useCallback } from 'react';
import { UserOrderStats } from '@/api/user';
import { getUserOrderStats, UserOrderStats } from '@/api/user';
import Taro from '@tarojs/taro';
import {pageShopOrder} from "@/api/shop/shopOrder";
/**
* 订单统计Hook
@@ -31,20 +30,17 @@ export const useOrderStats = () => {
if(!Taro.getStorageSync('UserId')){
return false;
}
// TODO 读取订单数量
const pending = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 0})
const paid = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 1})
const shipped = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 3})
const completed = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 5})
const refund = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 6})
const total = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId')})
// 聚合接口:一次请求返回各状态数量(后台按用户做了缓存)
const stats = await getUserOrderStats();
setOrderStats({
pending: pending?.count || 0,
paid: paid?.count || 0,
shipped: shipped?.count || 0,
completed: completed?.count || 0,
refund: refund?.count || 0,
total: total?.count || 0
pending: stats?.pending || 0,
paid: stats?.paid || 0,
shipped: stats?.shipped || 0,
completed: stats?.completed || 0,
refund: stats?.refund || 0,
total: stats?.total || 0
})
if (showToast) {

View File

@@ -1,12 +1,10 @@
import { useState, useEffect, useCallback } from 'react'
import {pageShopUserCoupon} from "@/api/shop/shopUserCoupon";
import {pageShopGift} from "@/api/shop/shopGift";
import {useUser} from "@/hooks/useUser";
import Taro from '@tarojs/taro'
import {getUserInfo} from "@/api/layout";
import { getUserCardStats } from '@/api/user'
interface UserData {
balance: number
balance: string
points: number
coupons: number
giftCards: number
@@ -24,7 +22,7 @@ interface UseUserDataReturn {
loading: boolean
error: string | null
refresh: () => Promise<void>
updateBalance: (newBalance: number) => void
updateBalance: (newBalance: string) => void
updatePoints: (newPoints: number) => void
}
@@ -43,18 +41,14 @@ export const useUserData = (): UseUserDataReturn => {
return;
}
// 并发请求所有数据
const [userDataRes, couponsRes, giftCardsRes] = await Promise.all([
getUserInfo(),
pageShopUserCoupon({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), status: 0}),
pageShopGift({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), status: 0})
])
// 聚合接口:一次请求返回余额/积分/优惠券/礼品卡统计(后端可按用户做缓存)
const stats = await getUserCardStats()
const newData: UserData = {
balance: userDataRes?.balance || 0.00,
points: userDataRes?.points || 0,
coupons: couponsRes?.count || 0,
giftCards: giftCardsRes?.count || 0,
balance: stats?.balance || '0.00',
points: stats?.points || 0,
coupons: stats?.coupons || 0,
giftCards: stats?.giftCards || 0,
orders: {
pending: 0,
paid: 0,
@@ -78,7 +72,7 @@ export const useUserData = (): UseUserDataReturn => {
}, [fetchUserData])
// 更新余额(本地更新,避免频繁请求)
const updateBalance = useCallback((newBalance: number) => {
const updateBalance = useCallback((newBalance: string) => {
setData(prev => prev ? { ...prev, balance: newBalance } : null)
}, [])

View File

@@ -65,6 +65,8 @@ const UserCard = forwardRef<any, any>((_, ref) => {
setUserInfo(data)
setIsLogin(true);
Taro.setStorageSync('UserId', data.userId)
// 登录态已就绪后刷新卡片统计(余额/积分/券/礼品卡)
refresh().then()
// 获取openId
if (!data.openid) {
@@ -162,6 +164,8 @@ const UserCard = forwardRef<any, any>((_, ref) => {
Taro.setStorageSync('UserId', res.data.data.user.userId)
setUserInfo(res.data.data.user)
setIsLogin(true)
// 登录态已就绪后刷新卡片统计(余额/积分/券/礼品卡)
refresh().then()
}
})
} else {

View File

@@ -3,7 +3,6 @@ import {PullToRefresh} from '@nutui/nutui-react-taro'
import UserCard from "./components/UserCard";
import UserOrder from "./components/UserOrder";
import UserFooter from "./components/UserFooter";
import {useUserData} from "@/hooks/useUserData";
import {View} from '@tarojs/components';
import './user.scss'
import IsDealer from "./components/IsDealer";
@@ -12,14 +11,11 @@ import UserGrid from "@/pages/user/components/UserGrid";
function User() {
const {refresh} = useUserData()
const userCardRef = useRef<any>()
const themeStyles = useThemeStyles();
// 下拉刷新处理
const handleRefresh = async () => {
await refresh()
// 如果 UserCard 组件有自己的刷新方法,也可以调用
if (userCardRef.current?.handleRefresh) {
await userCardRef.current.handleRefresh()
}