Files
template-10584/src/dealer/team/index.tsx
赵忠林 ab2260ec3e feat(dealer/team): 点击团队成员加载下级用户数据- 在团队成员列表中添加点击事件,实现加载下级用户数据的功能
- 新增 getNextUser函数用于切换当前用户并重新获取数据
- 优化 fetchTeamData 函数,支持根据 dealerId 或 dealerUser.userId 获取数据
2025-08-27 23:41:54 +08:00

195 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, {useState, useEffect, useCallback} from 'react'
import {View, Text} from '@tarojs/components'
import {Space, Avatar, Loading} from '@nutui/nutui-react-taro'
import {User} from '@nutui/icons-react-taro'
import Taro from '@tarojs/taro'
import {useDealerUser} from '@/hooks/useDealerUser'
import {listShopDealerReferee} from '@/api/shop/shopDealerReferee'
import {pageShopDealerOrder} from '@/api/shop/shopDealerOrder'
import type {ShopDealerReferee} from '@/api/shop/shopDealerReferee/model'
import type {ShopDealerUser} from "@/api/shop/shopDealerUser/model";
interface TeamMemberWithStats extends ShopDealerReferee {
name?: string
avatar?: string
orderCount?: number
commission?: string
status?: 'active' | 'inactive'
subMembers?: number
joinTime?: string
}
const DealerTeam: React.FC = () => {
const [teamMembers, setTeamMembers] = useState<TeamMemberWithStats[]>([])
const {dealerUser} = useDealerUser()
const [dealerId, setDealerId] = useState<number>()
// 获取团队数据
const fetchTeamData = useCallback(async () => {
if (!dealerUser?.userId && !dealerId) return
try {
console.log(dealerId, 'dealerId>>>>>>>>>')
// 获取团队成员关系
const refereeResult = await listShopDealerReferee({
dealerId: dealerId ? dealerId : dealerUser.userId
})
if (refereeResult) {
// 处理团队成员数据
const processedMembers: TeamMemberWithStats[] = refereeResult.map(member => ({
...member,
name: `用户${member.userId}`,
avatar: '',
orderCount: 0,
commission: '0.00',
status: 'active' as const,
subMembers: 0,
joinTime: member.createTime
}))
// 并行获取每个成员的订单统计
const memberStats = await Promise.all(
processedMembers.map(async (member) => {
try {
const orderResult = await pageShopDealerOrder({
page: 1,
limit: 100,
userId: member.userId
})
if (orderResult?.list) {
const orders = orderResult.list
const orderCount = orders.length
const commission = orders.reduce((sum, order) => {
const levelCommission = member.level === 1 ? order.firstMoney :
member.level === 2 ? order.secondMoney :
order.thirdMoney
return sum + parseFloat(levelCommission || '0')
}, 0).toFixed(2)
// 判断活跃状态30天内有订单为活跃
const thirtyDaysAgo = new Date()
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30)
const hasRecentOrder = orders.some(order =>
new Date(order.createTime || '') > thirtyDaysAgo
)
return {
...member,
orderCount,
commission,
status: hasRecentOrder ? 'active' as const : 'inactive' as const
}
}
return member
} catch (error) {
console.error(`获取成员${member.userId}订单失败:`, error)
return member
}
})
)
setTeamMembers(memberStats)
}
} catch (error) {
console.error('获取团队数据失败:', error)
Taro.showToast({
title: '获取团队数据失败',
icon: 'error'
})
}
}, [dealerUser?.userId])
const getNextUser = (item: ShopDealerUser) => {
setDealerId(item.userId)
fetchTeamData().then()
}
// 初始化加载数据
useEffect(() => {
if (dealerUser?.userId) {
fetchTeamData().then()
}
}, [fetchTeamData])
const renderMemberItem = (member: TeamMemberWithStats) => (
<View key={member.id} className="bg-white rounded-lg p-4 mb-3 shadow-sm" onClick={() => getNextUser(member)}>
<View className="flex items-center mb-3">
<Avatar
size="40"
src={member.avatar}
icon={<User/>}
className="mr-3"
/>
<View className="flex-1">
<View className="flex items-center mb-1">
<Text className="font-semibold text-gray-800 mr-2">
{member.name}
</Text>
{/*{getLevelIcon(Number(member.level))}*/}
{/*<Text className="text-xs text-gray-500 ml-1">*/}
{/* {member.level}级*/}
{/*</Text>*/}
</View>
<Text className="text-xs text-gray-500">
{member.joinTime}
</Text>
</View>
{/*<View className="text-right">*/}
{/* <Tag*/}
{/* type={member.status === 'active' ? 'success' : 'default'}*/}
{/* >*/}
{/* {member.status === 'active' ? '活跃' : '沉默'}*/}
{/* </Tag>*/}
{/*</View>*/}
</View>
<View className="grid grid-cols-3 gap-4 text-center">
<Space>
<Text className="text-xs text-gray-500"></Text>
<Text className="text-sm font-semibold text-blue-600">
{member.orderCount}
</Text>
</Space>
<Space>
<Text className="text-xs text-gray-500"></Text>
<Text className="text-sm font-semibold text-green-600">
¥{member.commission}
</Text>
</Space>
<Space>
<Text className="text-xs text-gray-500"></Text>
<Text className="text-sm font-semibold text-purple-600">
{member.subMembers}
</Text>
</Space>
</View>
</View>
)
const renderOverview = () => (
<View className="rounded-xl p-4">
{teamMembers.slice(0, 3).map(renderMemberItem)}
</View>
)
if (!dealerUser) {
return (
<View className="bg-gray-50 min-h-screen flex items-center justify-center">
<Loading/>
<Text className="text-gray-500 mt-2">...</Text>
</View>
)
}
return (
<View className="min-h-screen">
{renderOverview()}
</View>
)
}
export default DealerTeam