|
@@ -8,98 +8,204 @@
|
|
|
<div class="title">我的团队</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 用户信息卡片 -->
|
|
|
- <div class="header-info">
|
|
|
- <div class="user-info">
|
|
|
- <div class="avatar">
|
|
|
- <img src="@/assets/hongqi.png" alt="红旗">
|
|
|
+ <!-- 主要内容 -->
|
|
|
+ <div class="content">
|
|
|
+ <!-- 顶部邀请码区域 -->
|
|
|
+ <div class="invite-section">
|
|
|
+ <!-- 二维码区域 -->
|
|
|
+ <div class="qr-section">
|
|
|
+ <img v-if="qrCodeUrl" :src="qrCodeUrl" alt="邀请二维码" class="qr-code" />
|
|
|
+ <div class="qr-label">分享二维码给好友</div>
|
|
|
</div>
|
|
|
- <div class="account-info">
|
|
|
- <div>账号:{{ userInfo.mobile }}</div>
|
|
|
- <div class="invite-code">
|
|
|
- <span>邀请码:{{ userInfo.salt }}</span>
|
|
|
- <button class="copy-btn" @click="copyInviteCode">复制</button>
|
|
|
+
|
|
|
+ <!-- 邀请码信息 -->
|
|
|
+ <div class="invite-info">
|
|
|
+ <div class="invite-code-label">我的邀请码:</div>
|
|
|
+ <div class="invite-actions">
|
|
|
+ <button class="copy-btn" @click="copyInviteCode">复制邀请码</button>
|
|
|
+ <button class="share-btn" @click="shareInviteLink">复制邀请链接</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="title-text">我的团队</div>
|
|
|
-
|
|
|
- <!-- 团队数据 -->
|
|
|
- <div class="team-stats">
|
|
|
+ <!-- 统计数据卡片 -->
|
|
|
+ <div class="stats-card">
|
|
|
<div class="stat-item">
|
|
|
- <div class="stat-num">{{ userInfo.totleone || 0 }}</div>
|
|
|
- <div class="stat-label">一级人数</div>
|
|
|
+ <div class="stat-number">{{ userInfo.totleone || 0 }}</div>
|
|
|
+ <div class="stat-label">直推人数</div>
|
|
|
</div>
|
|
|
<div class="stat-item">
|
|
|
- <div class="stat-num">{{ userInfo.totletwo || 0 }}</div>
|
|
|
- <div class="stat-label">二级人数</div>
|
|
|
+ <div class="stat-number">{{ (userInfo.totleone || 0) + (userInfo.totletwo || 0) + (userInfo.totlethree || 0) }}</div>
|
|
|
+ <div class="stat-label">团队总人数</div>
|
|
|
</div>
|
|
|
<div class="stat-item">
|
|
|
- <div class="stat-num">{{ userInfo.totlethree || 0 }}</div>
|
|
|
- <div class="stat-label">三级人数</div>
|
|
|
+ <div class="stat-number">{{ getRealNameCount() }}</div>
|
|
|
+ <div class="stat-label">已实名人数</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 功能列表 -->
|
|
|
- <div class="function-list">
|
|
|
- <div class="function-item" @click="$router.push('/share')">
|
|
|
- <span>邀请好友</span>
|
|
|
- </div>
|
|
|
- <div class="function-item" @click="$router.push('/team-detail')">
|
|
|
- <span>团队明细</span>
|
|
|
- </div>
|
|
|
- <div class="function-item" @click="$router.push('/asset-center')">
|
|
|
- <span>收益记录</span>
|
|
|
+ <!-- 会员分类标签 -->
|
|
|
+ <div class="member-tabs">
|
|
|
+ <div
|
|
|
+ class="member-tab"
|
|
|
+ :class="{ active: currentLevel === 1 }"
|
|
|
+ @click="switchLevel(1)"
|
|
|
+ >一级会员</div>
|
|
|
+ <div
|
|
|
+ class="member-tab"
|
|
|
+ :class="{ active: currentLevel === 2 }"
|
|
|
+ @click="switchLevel(2)"
|
|
|
+ >二级会员</div>
|
|
|
+ <div
|
|
|
+ class="member-tab"
|
|
|
+ :class="{ active: currentLevel === 3 }"
|
|
|
+ @click="switchLevel(3)"
|
|
|
+ >三级会员</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 会员详情卡片 -->
|
|
|
+ <div v-if="teamList.length > 0" class="member-list">
|
|
|
+ <div v-for="member in teamList" :key="member.id" class="member-card">
|
|
|
+ <div class="member-row">
|
|
|
+ <span class="member-label">姓名:</span>
|
|
|
+ <span class="member-value">{{ member.cardname || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="member-row">
|
|
|
+ <span class="member-label">账号:</span>
|
|
|
+ <span class="member-value">{{ member.mobile || '18888888888' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="member-row">
|
|
|
+ <span class="member-label">注册时间:</span>
|
|
|
+ <span class="member-value">{{ member.createtime || '' }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- Toast 提示 -->
|
|
|
+ <Toast ref="toast" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { getUserInfo } from '@/api/home';
|
|
|
-import { getBankInfo } from '@/api/profile';
|
|
|
+import { getMyTeam } from '@/api/profile';
|
|
|
+import QRCode from 'qrcode';
|
|
|
+import Toast from '@/components/Toast.vue';
|
|
|
|
|
|
export default {
|
|
|
name: 'Member',
|
|
|
+ components: {
|
|
|
+ Toast
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
userInfo: {},
|
|
|
- bankInfo: {}
|
|
|
+ qrCodeUrl: '',
|
|
|
+ currentLevel: 1,
|
|
|
+ teamList: [],
|
|
|
+ teamStats: {
|
|
|
+ level1: { yxuser: 0 },
|
|
|
+ level2: { yxuser: 0 },
|
|
|
+ level3: { yxuser: 0 }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ inviteLink() {
|
|
|
+ return this.userInfo.inviteLink || '';
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
this.getUserInfo();
|
|
|
- // this.getBankInfo();
|
|
|
+ this.getTeamData();
|
|
|
+ this.getAllTeamStats();
|
|
|
},
|
|
|
methods: {
|
|
|
async getUserInfo() {
|
|
|
try {
|
|
|
const res = await getUserInfo();
|
|
|
this.userInfo = res.data;
|
|
|
+ await this.generateQRCode();
|
|
|
} catch (error) {
|
|
|
console.error('获取用户信息失败:', error);
|
|
|
}
|
|
|
},
|
|
|
- async getBankInfo() {
|
|
|
+ async generateQRCode() {
|
|
|
+ try {
|
|
|
+ if (!this.inviteLink) return;
|
|
|
+ const qrOptions = {
|
|
|
+ errorCorrectionLevel: 'H',
|
|
|
+ type: 'image/png',
|
|
|
+ quality: 0.92,
|
|
|
+ margin: 1,
|
|
|
+ color: {
|
|
|
+ dark: '#000000',
|
|
|
+ light: '#FFFFFF'
|
|
|
+ }
|
|
|
+ };
|
|
|
+ this.qrCodeUrl = await QRCode.toDataURL(this.inviteLink, qrOptions);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('生成二维码失败:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async getTeamData() {
|
|
|
try {
|
|
|
- const res = await getBankInfo();
|
|
|
- this.bankInfo = res.data;
|
|
|
+ const res = await getMyTeam(this.currentLevel);
|
|
|
+ if (res && res.data) {
|
|
|
+ this.teamList = res.data.list || [];
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
- console.error('获取银行卡信息失败:', error);
|
|
|
+ console.error('获取团队数据失败:', error);
|
|
|
+ this.teamList = [];
|
|
|
}
|
|
|
},
|
|
|
+ switchLevel(level) {
|
|
|
+ this.currentLevel = level;
|
|
|
+ this.getTeamData();
|
|
|
+ },
|
|
|
copyInviteCode() {
|
|
|
if (this.userInfo.salt) {
|
|
|
navigator.clipboard.writeText(this.userInfo.salt)
|
|
|
.then(() => {
|
|
|
- alert('邀请码已复制');
|
|
|
+ this.$refs.toast.show('邀请码已复制', 'success');
|
|
|
})
|
|
|
.catch(() => {
|
|
|
- alert('复制失败,请手动复制');
|
|
|
+ this.$refs.toast.show('复制失败,请手动复制', 'error');
|
|
|
});
|
|
|
}
|
|
|
+ },
|
|
|
+ shareInviteLink() {
|
|
|
+ if (this.inviteLink) {
|
|
|
+ navigator.clipboard.writeText(this.inviteLink)
|
|
|
+ .then(() => {
|
|
|
+ this.$refs.toast.show('邀请链接已复制', 'success');
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ this.$refs.toast.show('复制失败,请手动复制', 'error');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async getAllTeamStats() {
|
|
|
+ // 获取所有级别的团队统计数据,用于计算已实名人数
|
|
|
+ for (let level = 1; level <= 3; level++) {
|
|
|
+ try {
|
|
|
+ const res = await getMyTeam(level);
|
|
|
+ if (res && res.data) {
|
|
|
+ this.teamStats[`level${level}`] = {
|
|
|
+ yxuser: res.data.yxuser || 0
|
|
|
+ };
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`获取${level}级团队统计失败:`, error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ getRealNameCount() {
|
|
|
+ // 计算所有级别的已实名人数总和
|
|
|
+ return (this.teamStats.level1.yxuser || 0) +
|
|
|
+ (this.teamStats.level2.yxuser || 0) +
|
|
|
+ (this.teamStats.level3.yxuser || 0);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -108,10 +214,7 @@ export default {
|
|
|
<style scoped>
|
|
|
.container {
|
|
|
min-height: 100vh;
|
|
|
- /* background: url('../assets/dabag.png') no-repeat; */
|
|
|
background-color: #b43a39;
|
|
|
- background-size: cover;
|
|
|
- background-position: center;
|
|
|
}
|
|
|
|
|
|
.nav-bar {
|
|
@@ -148,81 +251,92 @@ export default {
|
|
|
font-weight: 500;
|
|
|
}
|
|
|
|
|
|
-.header-info {
|
|
|
+.content {
|
|
|
padding: 20px;
|
|
|
- color: #fff;
|
|
|
}
|
|
|
|
|
|
-.user-info {
|
|
|
+/* 邀请码区域 */
|
|
|
+.invite-section {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 20px;
|
|
|
+ margin-bottom: 20px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- margin-bottom: 30px;
|
|
|
+ justify-content: space-between;
|
|
|
}
|
|
|
|
|
|
-.avatar {
|
|
|
- width: 60px;
|
|
|
- height: 60px;
|
|
|
- background: #fff;
|
|
|
- border-radius: 50%;
|
|
|
+.qr-section {
|
|
|
display: flex;
|
|
|
+ flex-direction: column;
|
|
|
align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-right: 15px;
|
|
|
}
|
|
|
|
|
|
-.avatar img {
|
|
|
- width: 40px;
|
|
|
- height: 40px;
|
|
|
- object-fit: contain;
|
|
|
+.qr-code {
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ border-radius: 8px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.qr-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
}
|
|
|
|
|
|
-.account-info {
|
|
|
+.invite-info {
|
|
|
flex: 1;
|
|
|
- font-size: 14px;
|
|
|
+ margin-left: 20px;
|
|
|
}
|
|
|
|
|
|
-.invite-code {
|
|
|
+.invite-code-label {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+.invite-actions {
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
- margin-top: 10px;
|
|
|
- justify-content: space-between;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
}
|
|
|
|
|
|
-.copy-btn {
|
|
|
- margin-left: 15px;
|
|
|
- padding: 2px 15px;
|
|
|
- background: #fff;
|
|
|
+.copy-btn, .share-btn {
|
|
|
+ padding: 8px 16px;
|
|
|
border: none;
|
|
|
- font-size: 12px;
|
|
|
+ border-radius: 6px;
|
|
|
+ font-size: 14px;
|
|
|
cursor: pointer;
|
|
|
- color: #bb2d5c;
|
|
|
- font-weight: bold;
|
|
|
}
|
|
|
|
|
|
-.title-text {
|
|
|
- font-size: 20px;
|
|
|
- font-weight: bold;
|
|
|
- text-align: center;
|
|
|
- margin: 30px 0;
|
|
|
+.copy-btn {
|
|
|
+ background: #ffb3b3;
|
|
|
+ color: #d91d42;
|
|
|
}
|
|
|
|
|
|
-.team-stats {
|
|
|
- background: #fff;
|
|
|
- border-radius: 8px;
|
|
|
- display: flex;
|
|
|
+.share-btn {
|
|
|
+ background: #ffb3b3;
|
|
|
+ color: #d91d42;
|
|
|
+}
|
|
|
+
|
|
|
+/* 统计卡片 */
|
|
|
+.stats-card {
|
|
|
+ background: #ffcccc;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 20px;
|
|
|
margin-bottom: 20px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
}
|
|
|
|
|
|
.stat-item {
|
|
|
- flex: 1;
|
|
|
text-align: center;
|
|
|
- padding: 15px 0;
|
|
|
- color: #333;
|
|
|
}
|
|
|
|
|
|
-.stat-num {
|
|
|
- font-size: 20px;
|
|
|
+.stat-number {
|
|
|
+ font-size: 24px;
|
|
|
font-weight: bold;
|
|
|
+ color: #333;
|
|
|
margin-bottom: 5px;
|
|
|
}
|
|
|
|
|
@@ -231,19 +345,54 @@ export default {
|
|
|
color: #666;
|
|
|
}
|
|
|
|
|
|
-.function-list {
|
|
|
+/* 会员分类标签 */
|
|
|
+.member-tabs {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.member-tab {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 8px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.member-tab.active {
|
|
|
+ border-bottom: 2px solid #fff;
|
|
|
+}
|
|
|
+
|
|
|
+/* 会员列表 */
|
|
|
+.member-list {
|
|
|
+ /* 容器样式 */
|
|
|
+}
|
|
|
+
|
|
|
+.member-card {
|
|
|
background: #fff;
|
|
|
- border-radius: 8px;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 20px;
|
|
|
+ margin-bottom: 12px;
|
|
|
}
|
|
|
|
|
|
-.function-item {
|
|
|
- padding: 15px;
|
|
|
- border-bottom: 1px solid #eee;
|
|
|
- color: #333;
|
|
|
+.member-card:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.member-row {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 8px;
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
|
|
|
-.function-item:last-child {
|
|
|
- border-bottom: none;
|
|
|
+.member-label {
|
|
|
+ color: #666;
|
|
|
+ width: 80px;
|
|
|
+}
|
|
|
+
|
|
|
+.member-value {
|
|
|
+ color: #333;
|
|
|
+ font-weight: 500;
|
|
|
}
|
|
|
</style>
|