补分销中心页面

This commit is contained in:
2025-08-10 01:38:17 +08:00
parent 44fd815fe7
commit afe54770a8
20 changed files with 2499 additions and 4 deletions

176
src/dealer/team/index.scss Normal file
View File

@@ -0,0 +1,176 @@
.my-team-page {
min-height: 100vh;
background-color: #f5f5f5;
.loading-container {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
}
.team-stats {
background: white;
margin: 16px;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.stats-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
.stat-item {
text-align: center;
.stat-value {
font-size: 20px; // 对应 text-xl
font-weight: bold;
color: #1f2937;
margin-bottom: 4px;
}
.stat-label {
font-size: 16px; // 对应 text-base
color: #6b7280;
}
}
}
}
.level-stats {
background: white;
margin: 0 16px 16px;
border-radius: 12px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.level-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
&:not(:last-child) {
border-bottom: 1px solid #f3f4f6;
}
.level-info {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.level-title {
font-size: 20px; // 对应 text-xl
color: #1f2937;
}
.level-count {
font-size: 20px; // 对应 text-xl
font-weight: bold;
color: #3b82f6;
}
}
}
}
.members-container {
margin: 0 16px;
.empty-container {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
}
.members-list {
margin-top: 16px;
.member-item {
background: white;
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
cursor: pointer;
transition: all 0.2s ease;
&:active {
transform: scale(0.98);
background-color: #f9f9f9;
}
.member-info {
flex: 1;
margin-left: 12px;
.member-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
.member-name {
font-size: 20px; // 对应 text-xl成员名称是重要信息
font-weight: 500;
color: #1f2937;
}
.member-level {
font-size: 14px; // 对应 text-sm
padding: 4px 10px;
border-radius: 12px;
color: white;
&.level-1 {
background-color: #3b82f6;
}
&.level-2 {
background-color: #10b981;
}
}
}
.member-stats {
display: flex;
gap: 16px;
margin-bottom: 6px;
.stat {
font-size: 16px; // 对应 text-base
color: #6b7280;
}
}
.member-time {
font-size: 14px; // 对应 text-sm
color: #9ca3af;
}
}
.member-status {
font-size: 14px; // 对应 text-sm
padding: 6px 10px;
border-radius: 12px;
margin-left: 12px;
&.active {
background-color: #d1fae5;
color: #10b981;
}
&.inactive {
background-color: #fee2e2;
color: #ef4444;
}
}
}
}
}
}

244
src/dealer/team/index.tsx Normal file
View File

@@ -0,0 +1,244 @@
import { useState, useEffect } from 'react'
import { View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { Avatar, Empty, Tabs, TabPane } from '@nutui/nutui-react-taro'
import './index.scss'
interface TeamMember {
id: string
nickname: string
avatar: string
joinTime: string
level: number
orderCount: number
totalCommission: number
status: 'active' | 'inactive'
}
interface TeamStats {
totalMembers: number
activeMembers: number
level1Members: number
level2Members: number
totalCommission: number
monthCommission: number
}
function MyTeam() {
const [activeTab, setActiveTab] = useState('0')
const [members, setMembers] = useState<TeamMember[]>([])
const [stats, setStats] = useState<TeamStats>({
totalMembers: 0,
activeMembers: 0,
level1Members: 0,
level2Members: 0,
totalCommission: 0,
monthCommission: 0
})
const [loading, setLoading] = useState(true)
useEffect(() => {
Taro.setNavigationBarTitle({
title: '我的团队'
})
loadTeamData()
}, [])
const loadTeamData = async () => {
try {
setLoading(true)
// 模拟数据
const mockMembers: TeamMember[] = [
{
id: '1',
nickname: '张小明',
avatar: 'https://img12.360buyimg.com/imagetools/jfs/t1/143702/31/16654/116794/5fc6f541Edebf8a57/4138097748889987.png',
joinTime: '2024-01-15',
level: 1,
orderCount: 15,
totalCommission: 150.50,
status: 'active'
},
{
id: '2',
nickname: '李小红',
avatar: 'https://img12.360buyimg.com/imagetools/jfs/t1/143702/31/16654/116794/5fc6f541Edebf8a57/4138097748889987.png',
joinTime: '2024-01-10',
level: 1,
orderCount: 8,
totalCommission: 89.20,
status: 'active'
},
{
id: '3',
nickname: '王小华',
avatar: 'https://img12.360buyimg.com/imagetools/jfs/t1/143702/31/16654/116794/5fc6f541Edebf8a57/4138097748889987.png',
joinTime: '2024-01-08',
level: 2,
orderCount: 3,
totalCommission: 25.80,
status: 'inactive'
},
{
id: '4',
nickname: '赵小刚',
avatar: 'https://img12.360buyimg.com/imagetools/jfs/t1/143702/31/16654/116794/5fc6f541Edebf8a57/4138097748889987.png',
joinTime: '2024-01-05',
level: 2,
orderCount: 12,
totalCommission: 98.60,
status: 'active'
}
]
// 计算统计数据
const totalMembers = mockMembers.length
const activeMembers = mockMembers.filter(m => m.status === 'active').length
const level1Members = mockMembers.filter(m => m.level === 1).length
const level2Members = mockMembers.filter(m => m.level === 2).length
const totalCommission = mockMembers.reduce((sum, m) => sum + m.totalCommission, 0)
setTimeout(() => {
setMembers(mockMembers)
setStats({
totalMembers,
activeMembers,
level1Members,
level2Members,
totalCommission,
monthCommission: totalCommission * 0.3 // 模拟本月佣金
})
setLoading(false)
}, 1000)
} catch (error) {
console.error('加载团队数据失败:', error)
setLoading(false)
}
}
const getFilteredMembers = () => {
switch (activeTab) {
case '1':
return members.filter(member => member.level === 1)
case '2':
return members.filter(member => member.level === 2)
case '3':
return members.filter(member => member.status === 'active')
default:
return members
}
}
const handleMemberClick = (member: TeamMember) => {
Taro.showModal({
title: '成员详情',
content: `
昵称:${member.nickname}
加入时间:${member.joinTime}
等级:${member.level}级下线
订单数量:${member.orderCount}
累计佣金:¥${member.totalCommission.toFixed(2)}
状态:${member.status === 'active' ? '活跃' : '不活跃'}
`.trim(),
showCancel: false
})
}
if (loading) {
return (
<View className="my-team-page">
<View className="loading-container">
<View className="text-center text-gray-500">...</View>
</View>
</View>
)
}
return (
<View className="my-team-page">
{/* 团队统计 */}
<View className="team-stats">
<View className="stats-grid">
<View className="stat-item">
<View className="stat-value">{stats.totalMembers}</View>
<View className="stat-label"></View>
</View>
<View className="stat-item">
<View className="stat-value">{stats.activeMembers}</View>
<View className="stat-label"></View>
</View>
<View className="stat-item">
<View className="stat-value">¥{stats.totalCommission.toFixed(2)}</View>
<View className="stat-label"></View>
</View>
<View className="stat-item">
<View className="stat-value">¥{stats.monthCommission.toFixed(2)}</View>
<View className="stat-label"></View>
</View>
</View>
</View>
{/* 等级统计 */}
<View className="level-stats">
<View className="level-item">
<View className="level-info">
<View className="level-title">线</View>
<View className="level-count">{stats.level1Members}</View>
</View>
</View>
<View className="level-item">
<View className="level-info">
<View className="level-title">线</View>
<View className="level-count">{stats.level2Members}</View>
</View>
</View>
</View>
{/* 成员列表 */}
<View className="members-container">
<Tabs value={activeTab} onChange={(value) => setActiveTab(value)}>
<TabPane title="全部" />
<TabPane title="一级" />
<TabPane title="二级" />
<TabPane title="活跃" />
</Tabs>
<View className="members-list">
{getFilteredMembers().length === 0 ? (
<View className="empty-container">
<Empty description="暂无团队成员" />
</View>
) : (
getFilteredMembers().map((member) => (
<View
key={member.id}
className="member-item"
onClick={() => handleMemberClick(member)}
>
<Avatar size="50" src={member.avatar} shape="round" />
<View className="member-info">
<View className="member-header">
<View className="member-name">{member.nickname}</View>
<View className={`member-level level-${member.level}`}>
{member.level}
</View>
</View>
<View className="member-stats">
<View className="stat">{member.orderCount}</View>
<View className="stat">¥{member.totalCommission.toFixed(2)}</View>
</View>
<View className="member-time">{member.joinTime}</View>
</View>
<View className={`member-status ${member.status}`}>
{member.status === 'active' ? '活跃' : '不活跃'}
</View>
</View>
))
)}
</View>
</View>
</View>
)
}
export default MyTeam