616 lines
14 KiB
Vue
616 lines
14 KiB
Vue
<template>
|
||
<view class="team-page">
|
||
<!-- 团队概览 -->
|
||
<view class="overview-card gradient-bg">
|
||
<view class="card-title">我的团队</view>
|
||
<view class="stats-grid">
|
||
<view class="stat-item">
|
||
<text class="stat-value">{{ teamStats.memberCount }}</text>
|
||
<text class="stat-label">团队成员</text>
|
||
</view>
|
||
<view class="stat-item">
|
||
<text class="stat-value">¥{{ teamStats.totalSales }}</text>
|
||
<text class="stat-label">团队业绩</text>
|
||
</view>
|
||
<view class="stat-item">
|
||
<text class="stat-value">¥{{ teamStats.totalCommission }}</text>
|
||
<text class="stat-label">团队佣金</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 邀请新成员 -->
|
||
<view class="invite-section">
|
||
<view class="invite-card">
|
||
<view class="invite-content">
|
||
<text class="invite-title">邀请好友加入团队</text>
|
||
<text class="invite-desc">好友成功注册并推广,您可获得二级佣金</text>
|
||
</view>
|
||
<button class="invite-btn" @click="inviteMember">
|
||
<text class="btn-icon"></text>
|
||
<text>立即邀请</text>
|
||
</button>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 团队成员列表 -->
|
||
<view class="member-section">
|
||
<view class="section-header">
|
||
<text class="section-title">团队成员</text>
|
||
<picker mode="selector" :range="sortOptions" @change="onSortChange">
|
||
<view class="sort-picker">
|
||
<text>{{ selectedSort }}</text>
|
||
<text class="arrow">▼</text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
|
||
<view class="member-list">
|
||
<view class="member-item" v-for="member in memberList" :key="member.id" @click="viewMemberDetail(member)">
|
||
<image class="member-avatar" :src="member.avatar" mode="aspectFill"></image>
|
||
<view class="member-info">
|
||
<view class="member-name-row">
|
||
<text class="member-name">{{ member.name }}</text>
|
||
<text class="member-level" :class="'level-' + member.level">{{ getLevelText(member.level) }}</text>
|
||
</view>
|
||
<text class="member-time">加入时间:{{ member.joinTime }}</text>
|
||
<view class="member-stats">
|
||
<text class="stat-text">推广客户:{{ member.customerCount }}人</text>
|
||
<text class="stat-text">成交订单:{{ member.orderCount }}单</text>
|
||
</view>
|
||
</view>
|
||
<view class="member-performance">
|
||
<text class="performance-label">业绩</text>
|
||
<text class="performance-value">¥{{ member.totalSales }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view class="empty-state" v-if="memberList.length === 0">
|
||
<text class="empty-icon"></text>
|
||
<text class="empty-text">暂无团队成员</text>
|
||
<text class="empty-hint">快去邀请好友加入吧</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 团队排行榜 -->
|
||
<view class="rank-section">
|
||
<view class="section-header">
|
||
<text class="section-title">本月排行榜</text>
|
||
</view>
|
||
|
||
<view class="rank-list">
|
||
<view class="rank-item" v-for="(item, index) in rankList" :key="item.id">
|
||
<view class="rank-number" :class="'rank-' + (index + 1)">
|
||
{{ index + 1 }}
|
||
</view>
|
||
<image class="rank-avatar" :src="item.avatar" mode="aspectFill"></image>
|
||
<view class="rank-info">
|
||
<text class="rank-name">{{ item.name }}</text>
|
||
<text class="rank-sales">业绩:¥{{ item.sales }}</text>
|
||
</view>
|
||
<view class="rank-badge" v-if="index < 3">
|
||
<text>{{ ['', '', ''][index] }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
teamStats: {
|
||
memberCount: 0,
|
||
totalSales: 0,
|
||
totalCommission: 0
|
||
},
|
||
selectedSort: '按加入时间',
|
||
sortOptions: ['按加入时间', '按业绩排序', '按客户数排序'],
|
||
memberList: [],
|
||
rankList: []
|
||
}
|
||
},
|
||
|
||
onLoad() {
|
||
this.loadTeamStats()
|
||
this.loadMemberList()
|
||
this.loadRankList()
|
||
},
|
||
|
||
methods: {
|
||
async loadTeamStats() {
|
||
try {
|
||
// TODO: 调用API获取团队统计
|
||
this.teamStats = {
|
||
memberCount: 8,
|
||
totalSales: 15680.00,
|
||
totalCommission: 1568.00
|
||
}
|
||
} catch (error) {
|
||
console.error('加载团队统计失败:', error)
|
||
}
|
||
},
|
||
|
||
async loadMemberList() {
|
||
try {
|
||
// 调用API获取团队成员列表
|
||
const token = uni.getStorageSync('token')
|
||
const res = await uni.request({
|
||
url: 'http://localhost:8089/api/distributor/team/members',
|
||
method: 'GET',
|
||
header: {
|
||
'Authorization': 'Bearer ' + token
|
||
},
|
||
data: {
|
||
page: 1,
|
||
size: 100
|
||
}
|
||
})
|
||
|
||
if (res.data && res.data.code === 200) {
|
||
const records = res.data.data.records || []
|
||
|
||
// 处理团队成员数据,保留所有详细信息
|
||
this.memberList = records.map(member => {
|
||
// 处理孩子信息
|
||
let children = []
|
||
if (member.studentInfo) {
|
||
children = [{
|
||
studentName: member.studentInfo.studentName,
|
||
gender: member.studentInfo.gender,
|
||
age: member.studentInfo.age,
|
||
grade: member.studentInfo.grade,
|
||
school: member.studentInfo.school,
|
||
hobbies: member.studentInfo.hobbies,
|
||
specialties: member.studentInfo.specialties
|
||
}]
|
||
}
|
||
|
||
return {
|
||
id: member.id,
|
||
name: member.name || member.nickname,
|
||
realName: member.realName, // ✅ 保存真实姓名
|
||
phone: member.phone, // ✅ 保存电话
|
||
avatar: member.avatar || '/static/images/default-avatar.png',
|
||
level: member.level || 1,
|
||
joinTime: member.joinTime ? member.joinTime.substring(0, 10) : '',
|
||
customerCount: member.customerCount || 0,
|
||
orderCount: member.orderCount || 0,
|
||
totalSales: member.totalSales || 0,
|
||
residenceAddress: member.residenceAddress, // ✅ 保存所在区域
|
||
customerRequirement: member.customerRequirement, // ✅ 保存客户需求
|
||
children: children // ✅ 保存孩子信息
|
||
}
|
||
})
|
||
|
||
console.log('团队成员列表加载成功:', this.memberList)
|
||
} else {
|
||
console.error('加载团队成员失败:', res.data)
|
||
uni.showToast({
|
||
title: '加载失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} catch (error) {
|
||
console.error('加载团队成员失败:', error)
|
||
uni.showToast({
|
||
title: '网络错误',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
},
|
||
|
||
async loadRankList() {
|
||
try {
|
||
// TODO: 调用API获取排行榜
|
||
this.rankList = [
|
||
{
|
||
id: 1,
|
||
name: '张小明',
|
||
avatar: '/static/images/avatar1.jpg',
|
||
sales: 5680.00
|
||
},
|
||
{
|
||
id: 2,
|
||
name: '李红',
|
||
avatar: '/static/images/avatar2.jpg',
|
||
sales: 3200.00
|
||
},
|
||
{
|
||
id: 3,
|
||
name: '王芳',
|
||
avatar: '/static/images/avatar3.jpg',
|
||
sales: 2800.00
|
||
}
|
||
]
|
||
} catch (error) {
|
||
console.error('加载排行榜失败:', error)
|
||
}
|
||
},
|
||
|
||
onSortChange(e) {
|
||
this.selectedSort = this.sortOptions[e.detail.value]
|
||
this.loadMemberList()
|
||
},
|
||
|
||
getLevelText(level) {
|
||
const levelMap = {
|
||
1: '一级',
|
||
2: '二级'
|
||
}
|
||
return levelMap[level] || '未知'
|
||
},
|
||
|
||
inviteMember() {
|
||
uni.navigateTo({
|
||
url: '/distributor-package/pages/distributor/promotion-code'
|
||
})
|
||
},
|
||
|
||
viewMemberDetail(member) {
|
||
// 构建详细信息内容(竖向排列,增加空行)
|
||
let content = ''
|
||
|
||
// 1. 电话
|
||
content += `电话:${member.phone || '未提供'}\n\n`
|
||
|
||
// 2. 姓名
|
||
content += `姓名:${member.realName || member.name || '未知'}\n\n`
|
||
|
||
// 3. 孩子基本情况
|
||
content += `孩子基本情况:`
|
||
if (member.children && member.children.length > 0) {
|
||
content += `\n`
|
||
member.children.forEach((child, index) => {
|
||
const childName = child.studentName || '未知'
|
||
const gender = child.gender === 1 ? '男' : child.gender === 2 ? '女' : '未知'
|
||
const age = child.age ? `${child.age}岁` : ''
|
||
const grade = child.grade || ''
|
||
|
||
content += `${childName} (${gender}) ${age} ${grade}\n`
|
||
})
|
||
content += `\n`
|
||
} else {
|
||
content += `暂无\n\n`
|
||
}
|
||
|
||
// 4. 所在区域
|
||
content += `所在区域:${member.residenceAddress || '未提供'}\n\n`
|
||
|
||
// 5. 客户需求
|
||
content += `客户需求:${member.customerRequirement || '暂无'}`
|
||
|
||
uni.showModal({
|
||
title: '团队成员详情',
|
||
content: content,
|
||
showCancel: false,
|
||
confirmText: '关闭'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.team-page {
|
||
min-height: 100vh;
|
||
background: #f0f9f7;
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.gradient-bg {
|
||
background: linear-gradient(135deg, #7dd3c0 0%, #5fb8a8 100%);
|
||
}
|
||
|
||
.overview-card {
|
||
border-radius: 20rpx;
|
||
padding: 40rpx;
|
||
margin-bottom: 20rpx;
|
||
box-shadow: 0 8rpx 24rpx rgba(125, 211, 192, 0.3);
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #ffffff;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.stats-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.stat-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 24rpx;
|
||
color: rgba(255, 255, 255, 0.9);
|
||
}
|
||
|
||
.invite-section {
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.invite-card {
|
||
background: #ffffff;
|
||
border-radius: 20rpx;
|
||
padding: 30rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.invite-content {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.invite-title {
|
||
font-size: 30rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.invite-desc {
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.invite-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
padding: 20rpx 30rpx;
|
||
background: linear-gradient(135deg, #7dd3c0 0%, #5fb8a8 100%);
|
||
color: #ffffff;
|
||
border-radius: 50rpx;
|
||
font-size: 28rpx;
|
||
border: none;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.btn-icon {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.member-section, .rank-section {
|
||
background: #ffffff;
|
||
border-radius: 20rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.sort-picker {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
padding: 12rpx 20rpx;
|
||
background: #f0f9f7;
|
||
border-radius: 8rpx;
|
||
font-size: 26rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
.arrow {
|
||
font-size: 20rpx;
|
||
}
|
||
|
||
.member-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.member-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
padding: 30rpx;
|
||
background: #f0f9f7;
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
.member-avatar {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 50%;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.member-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.member-name-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15rpx;
|
||
}
|
||
|
||
.member-name {
|
||
font-size: 30rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.member-level {
|
||
padding: 6rpx 12rpx;
|
||
font-size: 22rpx;
|
||
border-radius: 8rpx;
|
||
|
||
&.level-1 {
|
||
background: #fff3e0;
|
||
color: #ff9800;
|
||
}
|
||
|
||
&.level-2 {
|
||
background: #e3f2fd;
|
||
color: #2196f3;
|
||
}
|
||
}
|
||
|
||
.member-time {
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.member-stats {
|
||
display: flex;
|
||
gap: 30rpx;
|
||
}
|
||
|
||
.stat-text {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
.member-performance {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.performance-label {
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.performance-value {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #ff6b6b;
|
||
}
|
||
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 100rpx 0;
|
||
}
|
||
|
||
.empty-icon {
|
||
font-size: 100rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: 28rpx;
|
||
color: #999999;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.empty-hint {
|
||
font-size: 24rpx;
|
||
color: #cccccc;
|
||
}
|
||
|
||
.rank-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.rank-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
padding: 20rpx;
|
||
background: #f0f9f7;
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
.rank-number {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
line-height: 60rpx;
|
||
text-align: center;
|
||
background: #e0e0e0;
|
||
color: #666666;
|
||
border-radius: 50%;
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
flex-shrink: 0;
|
||
|
||
&.rank-1 {
|
||
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
&.rank-2 {
|
||
background: linear-gradient(135deg, #c0c0c0 0%, #e8e8e8 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
&.rank-3 {
|
||
background: linear-gradient(135deg, #cd7f32 0%, #e8a87c 100%);
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
|
||
.rank-avatar {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 50%;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.rank-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.rank-name {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.rank-sales {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
.rank-badge {
|
||
font-size: 48rpx;
|
||
}
|
||
</style>
|