2025-11-13 22:53:09 +08:00

936 lines
18 KiB
Vue
Raw Permalink 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.

<template>
<view class="distribution-page">
<view class="header-card">
<view class="header-top flex justify-between">
<view class="title-wrap">
<view class="title-row flex items-center">
<text class="iconfont icon-yonghu title-icon"></text>
<text class="title-text">分销中心</text>
</view>
<view class="role-row flex items-center">
<view class="role-tag">{{ userInfo.role }}</view>
<text class="team-size">团队 {{ userInfo.teamSize }} </text>
</view>
</view>
<button class="invite-btn" @click="handleInvite">
<text class="iconfont icon-zhifeiji1"></text>
邀请
</button>
</view>
<view class="commission-panel">
<view class="panel-label">累计佣金</view>
<view class="panel-value">¥{{ commission.total }}</view>
<view class="progress-bar">
<view class="progress-inner" :style="{ width: commission.progress + '%' }"></view>
</view>
<view class="progress-text">
升级进度 {{ commission.progress }}%
</view>
</view>
</view>
<view class="content-wrap">
<view class="overview-card shadow" v-if="activeTab === 0">
<view class="card-title flex items-center">
<text class="iconfont icon-tubiaoshangshengqushi"></text>
数据概览
</view>
<view class="overview-grid">
<view class="overview-item highlight">
<view class="item-label">今日佣金</view>
<view class="item-value">¥{{ overview.today.amount }}</view>
<view class="item-desc success">+{{ overview.today.growth }}%</view>
</view>
<view class="overview-item">
<view class="item-label">团队人数</view>
<view class="item-value">{{ overview.team.total }}</view>
<view class="item-desc">活跃 {{ overview.team.active }}</view>
</view>
<view class="overview-item">
<view class="item-label">本月订单</view>
<view class="item-value">{{ overview.orders }}</view>
</view>
<view class="overview-item">
<view class="item-label">月度营收</view>
<view class="item-value">¥{{ overview.revenue }}</view>
</view>
<view class="overview-item span-2">
<view class="item-label">转化率</view>
<view class="item-value purple">{{ overview.conversion.rate }}%</view>
<view class="item-desc muted">{{ overview.conversion.remark }}</view>
</view>
</view>
</view>
<view class="tabs-row">
<view
v-for="(tab, index) in tabs"
:key="tab"
class="tab-item"
:class="{ active: activeTab === index }"
@click="changeTab(index)"
>
{{ tab }}
</view>
</view>
<view class="team-card shadow" v-if="activeTab === 1">
<view class="card-title flex items-center justify-between">
<view class="title-left flex items-center">
<text class="iconfont icon-yonghu"></text>
团队成员
</view>
<view class="team-count">{{ teamMembers.length }} </view>
</view>
<view
class="team-item"
v-for="member in teamMembers"
:key="member.id"
>
<image class="avatar" :src="member.avatar" mode="aspectFill"></image>
<view class="member-info">
<view class="member-header flex items-center">
<view class="member-name">{{ member.name }}</view>
<view class="member-role">{{ member.role }}</view>
</view>
<view class="member-stats">
<view class="stat">
<view class="stat-label">订单</view>
<view class="stat-value">{{ member.orders }}</view>
</view>
<view class="stat">
<view class="stat-label">佣金</view>
<view class="stat-value">¥{{ member.commission }}</view>
</view>
</view>
</view>
<view class="member-right">
<view class="growth">{{ member.growth > 0 ? '+' : '' }}{{ member.growth }}%</view>
<view class="arrow">></view>
</view>
</view>
</view>
<view class="achievement-card shadow" v-if="activeTab === 0">
<view class="card-title flex items-center">
<text class="iconfont icon-lihe"></text>
成就进度
</view>
<view
class="achievement-item"
v-for="achievement in achievements"
:key="achievement.id"
>
<view class="achievement-icon">
<text class="iconfont" :class="achievement.icon"></text>
</view>
<view class="achievement-content">
<view class="achievement-header flex justify-between items-center">
<view class="achievement-title">{{ achievement.title }}</view>
<view class="achievement-percent">{{ achievement.percent }}%</view>
</view>
<view class="achievement-desc">
{{ achievement.description }}
</view>
<view class="achievement-progress">
<view class="progress-track">
<view class="progress-chunk" :style="{ width: achievement.percent + '%' }"></view>
</view>
<view class="progress-meta">
{{ achievement.current }} / {{ achievement.goal }}
</view>
</view>
<view class="achievement-reward flex items-center">
<text class="reward-badge">解锁奖励</text>
<text class="reward-text">{{ achievement.reward }}</text>
</view>
</view>
</view>
</view>
<view class="settlement-card shadow" v-if="activeTab === 2">
<view class="card-title flex items-center">
<text class="info-icon">i</text>
佣金结算说明
</view>
<view class="settlement-list">
<view
class="settlement-item"
v-for="rule in settlementRules"
:key="rule.id"
:class="rule.tone"
>
<view class="rule-icon">
<text v-if="rule.iconType === 'font'" class="iconfont" :class="rule.icon"></text>
<text v-else>{{ rule.icon }}</text>
</view>
<view class="rule-content">
<view class="rule-title">{{ rule.title }}</view>
<view class="rule-desc">{{ rule.description }}</view>
</view>
</view>
</view>
</view>
<view class="detail-card shadow" v-if="activeTab === 2">
<view class="card-title flex items-center">
<text class="iconfont icon-tubiaoshangshengqushi"></text>
佣金明细
</view>
<view
class="detail-item"
v-for="detail in commissionDetails"
:key="detail.id"
>
<view class="detail-info">
<view class="detail-header flex items-center">
<view class="detail-tag" :class="detail.type">{{ detail.typeLabel }}</view>
<view class="detail-title">{{ detail.product }}</view>
</view>
<view class="detail-meta">来自: {{ detail.customer }}</view>
<view class="detail-time">{{ detail.time }}</view>
</view>
<view class="detail-amount">+¥{{ detail.amount }}</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
userInfo: {
role: '品鉴分销员',
teamSize: 23
},
commission: {
total: '2580.50',
progress: 65
},
overview: {
today: {
amount: '156',
growth: 12.5
},
team: {
total: 23,
active: 18
},
orders: 45,
revenue: '8.9K',
conversion: {
rate: 8.3,
remark: '行业领先'
}
},
tabs: ['概览', '团队', '收益'],
activeTab: 0,
achievements: [
{
id: 'invite',
title: '邀请3位好友',
description: '成功邀请3位好友注册并完成首单',
current: 2,
goal: 3,
percent: 67,
reward: '解锁高佣金商品推广权',
icon: 'icon-zhifeiji1'
},
{
id: 'sales',
title: '月销售额达到5000元',
description: '单月团队销售额突破5000元',
current: 4200,
goal: 5000,
percent: 84,
reward: '晋升为调香分销员',
icon: 'icon-tubiaoshangshengqushi'
}
],
teamMembers: [
{
id: 'member-1',
name: '小美',
role: '探索分销员',
orders: 15,
commission: '234.5',
growth: 15,
avatar: 'https://picsum.photos/seed/distribution-1/120'
},
{
id: 'member-2',
name: '香香公主',
role: '品鉴分销员',
orders: 28,
commission: '456.8',
growth: 23,
avatar: 'https://picsum.photos/seed/distribution-2/120'
},
{
id: 'member-3',
name: '花仙子',
role: '调香分销员',
orders: 42,
commission: '789.2',
growth: 8,
avatar: 'https://picsum.photos/seed/distribution-3/120'
}
],
settlementRules: [
{
id: 'cycle',
title: '结算周期',
description: '每月1日结算上月佣金T+7个工作日到账',
icon: 'icon-shijian',
iconType: 'font',
tone: 'tone-blue'
},
{
id: 'rate',
title: '佣金比例',
description: '直推订单10%团队订单5%,高级分销员享受更高比例',
icon: '$',
iconType: 'text',
tone: 'tone-green'
},
{
id: 'withdraw',
title: '提现规则',
description: '最低提现金额100元每月可提现2次手续费2元/笔',
icon: 'icon-shaixuan1',
iconType: 'font',
tone: 'tone-purple'
},
{
id: 'frozen',
title: '冻结说明',
description: '订单完成后佣金冻结15天确保售后服务质量',
icon: 'icon-shandian',
iconType: 'font',
tone: 'tone-yellow'
}
],
commissionDetails: [
{
id: 'detail-1',
type: 'direct',
typeLabel: '直推',
product: '经典玫瑰香水30ml',
customer: '张小姐',
time: '2025-04-02 14:30',
amount: '19.9'
},
{
id: 'detail-2',
type: 'team',
typeLabel: '团队',
product: '薰衣草精油礼盒',
customer: '李女士',
time: '2025-04-02 13:15',
amount: '14.95'
}
]
};
},
methods: {
changeTab(index) {
this.activeTab = index;
},
handleInvite() {
uni.showToast({
title: '分享邀请即将开放',
icon: 'none'
});
}
}
};
</script>
<style lang="scss" scoped>
.distribution-page {
min-height: 100vh;
background: #f7f7ff;
padding-bottom: 60rpx;
}
.header-card {
background: var(--background-linear-gradient);
color: #ffffff;
padding: 120rpx 44rpx 220rpx;
border-bottom-left-radius: 48rpx;
border-bottom-right-radius: 48rpx;
box-shadow: 0 28rpx 48rpx rgba(136, 45, 255, 0.3);
position: relative;
}
.header-top {
align-items: flex-start;
}
.title-wrap {
.title-row {
margin-bottom: 20rpx;
}
.title-icon {
font-size: 44rpx;
margin-right: 16rpx;
}
.title-text {
font-size: 44rpx;
font-weight: 600;
}
.role-row {
.role-tag {
background: rgba(255, 255, 255, 0.18);
border-radius: 32rpx;
padding: 12rpx 24rpx;
font-size: 24rpx;
margin-right: 16rpx;
}
.team-size {
font-size: 26rpx;
opacity: 0.85;
}
}
}
.invite-btn {
display: flex;
align-items: center;
justify-content: center;
color: #9810fa;
background: #ffffff;
border-radius: 999rpx;
padding: 0 36rpx;
height: 72rpx;
font-size: 28rpx;
font-weight: 500;
box-shadow: 0 12rpx 24rpx rgba(255, 255, 255, 0.3);
}
.invite-btn .iconfont {
margin-right: 12rpx;
font-size: 32rpx;
}
.commission-panel {
margin-top: 80rpx;
background: rgba(255, 255, 255, 0.18);
border-radius: 32rpx;
padding: 48rpx 40rpx;
backdrop-filter: blur(8rpx);
}
.panel-label {
font-size: 28rpx;
opacity: 0.85;
}
.panel-value {
font-size: 72rpx;
font-weight: 600;
margin-top: 20rpx;
letter-spacing: 2rpx;
}
.progress-bar {
height: 16rpx;
border-radius: 999rpx;
background: rgba(255, 255, 255, 0.32);
margin-top: 40rpx;
overflow: hidden;
}
.progress-inner {
height: 100%;
background: linear-gradient(to right, #ffe2ff, #ffe5f9, #fff7d7);
border-radius: inherit;
}
.progress-text {
margin-top: 20rpx;
font-size: 24rpx;
text-align: right;
opacity: 0.9;
}
.content-wrap {
position: relative;
margin-top: -160rpx;
padding: 0 32rpx;
}
.shadow {
box-shadow: 0 20rpx 40rpx rgba(102, 106, 255, 0.12);
}
.overview-card {
background: #ffffff;
border-radius: 32rpx;
padding: 40rpx 34rpx;
}
.card-title {
font-size: 30rpx;
font-weight: 600;
color: #2c2d50;
gap: 12rpx;
margin-bottom: 36rpx;
}
.card-title .iconfont {
font-size: 32rpx;
color: #9810fa;
}
.title-left {
gap: 12rpx;
}
.overview-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-gap: 28rpx;
}
.overview-item {
background: #f7f8ff;
border-radius: 28rpx;
padding: 32rpx 30rpx;
box-shadow: inset 0 0 0 1rpx rgba(152, 16, 250, 0.05);
&.highlight {
background: rgba(152, 16, 250, 0.12);
color: #39146b;
}
&.span-2 {
grid-column: span 2;
display: flex;
align-items: center;
justify-content: space-between;
}
}
.item-label {
font-size: 26rpx;
color: #61638a;
}
.item-value {
font-size: 42rpx;
font-weight: 600;
margin: 16rpx 0 8rpx;
color: #2b2d4f;
}
.item-value.purple {
color: #9810fa;
}
.item-desc {
font-size: 24rpx;
color: #7f80aa;
}
.item-desc.success {
color: #00c951;
}
.item-desc.muted {
color: #a2a6d1;
}
.tabs-row {
margin-top: 32rpx;
background: #ffffff;
border-radius: 999rpx;
padding: 12rpx;
display: flex;
justify-content: space-between;
gap: 12rpx;
}
.tab-item {
flex: 1;
text-align: center;
padding: 22rpx 0;
border-radius: 999rpx;
font-size: 28rpx;
color: #7d7fad;
transition: all 0.3s;
}
.tab-item.active {
background: linear-gradient(135deg, #a548ff, #f24bbf);
color: #ffffff;
box-shadow: 0 10rpx 20rpx rgba(152, 16, 250, 0.25);
}
.achievement-card {
margin-top: 32rpx;
background: #ffffff;
border-radius: 32rpx;
padding: 40rpx 34rpx;
}
.settlement-card {
margin-top: 32rpx;
background: #ffffff;
border-radius: 32rpx;
padding: 40rpx 34rpx;
}
.info-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background: rgba(152, 16, 250, 0.12);
color: #9810fa;
font-weight: 600;
margin-right: 12rpx;
font-size: 28rpx;
}
.settlement-list {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.settlement-item {
display: flex;
align-items: center;
padding: 28rpx;
border-radius: 28rpx;
background: #f7f8ff;
gap: 24rpx;
&.tone-blue {
background: rgba(118, 141, 255, 0.14);
.rule-icon {
color: #4a6cff;
background: rgba(74, 108, 255, 0.16);
}
}
&.tone-green {
background: rgba(0, 201, 81, 0.14);
.rule-icon {
color: #00c951;
background: rgba(0, 201, 81, 0.16);
}
}
&.tone-purple {
background: rgba(152, 16, 250, 0.12);
.rule-icon {
color: #9810fa;
background: rgba(152, 16, 250, 0.18);
}
}
&.tone-yellow {
background: rgba(255, 166, 0, 0.14);
.rule-icon {
color: #ff8b0d;
background: rgba(255, 166, 0, 0.2);
}
}
}
.rule-icon {
width: 80rpx;
height: 80rpx;
border-radius: 24rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 36rpx;
color: #9810fa;
background: rgba(152, 16, 250, 0.12);
}
.rule-content {
flex: 1;
}
.rule-title {
font-size: 30rpx;
font-weight: 600;
color: #2b2d4f;
margin-bottom: 12rpx;
}
.rule-desc {
font-size: 26rpx;
color: #5a5c8f;
line-height: 1.6;
}
.detail-card {
margin-top: 32rpx;
background: #ffffff;
border-radius: 32rpx;
padding: 40rpx 34rpx;
}
.detail-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx 0;
border-bottom: 1rpx solid #f0f1ff;
gap: 32rpx;
&:last-child {
border-bottom: 0;
padding-bottom: 0;
}
}
.detail-info {
flex: 1;
}
.detail-header {
gap: 16rpx;
margin-bottom: 12rpx;
}
.detail-tag {
font-size: 22rpx;
border-radius: 999rpx;
padding: 10rpx 22rpx;
background: rgba(152, 16, 250, 0.12);
color: #9810fa;
&.direct {
background: rgba(0, 201, 81, 0.12);
color: #00c951;
}
&.team {
background: rgba(118, 141, 255, 0.14);
color: #4a6cff;
}
}
.detail-title {
font-size: 30rpx;
font-weight: 600;
color: #2b2d4f;
}
.detail-meta,
.detail-time {
font-size: 24rpx;
color: #9a9cc0;
margin-top: 8rpx;
}
.detail-amount {
font-size: 32rpx;
font-weight: 600;
color: #00c951;
white-space: nowrap;
}
.team-card {
margin-top: 32rpx;
background: #ffffff;
border-radius: 32rpx;
padding: 40rpx 34rpx;
}
.team-count {
font-size: 26rpx;
color: #7c7ea7;
background: rgba(152, 16, 250, 0.12);
padding: 10rpx 26rpx;
border-radius: 999rpx;
}
.team-item {
display: flex;
align-items: center;
padding: 32rpx 0;
border-bottom: 1rpx solid #f0f1ff;
gap: 24rpx;
&:last-child {
border-bottom: 0;
padding-bottom: 0;
}
}
.avatar {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
object-fit: cover;
}
.member-info {
flex: 1;
}
.member-header {
gap: 16rpx;
margin-bottom: 12rpx;
}
.member-name {
font-size: 30rpx;
font-weight: 600;
color: #2b2d4f;
}
.member-role {
font-size: 22rpx;
color: #7c7ea7;
background: rgba(152, 16, 250, 0.12);
padding: 8rpx 16rpx;
border-radius: 999rpx;
}
.member-stats {
display: flex;
gap: 56rpx;
}
.stat-label {
font-size: 24rpx;
color: #9a9cc0;
margin-bottom: 8rpx;
}
.stat-value {
font-size: 26rpx;
color: #2b2d4f;
font-weight: 600;
}
.member-right {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 16rpx;
}
.growth {
background: rgba(0, 201, 81, 0.12);
color: #00c951;
padding: 10rpx 28rpx;
border-radius: 999rpx;
font-size: 24rpx;
font-weight: 600;
}
.arrow {
font-size: 28rpx;
color: #a2a6d1;
}
.achievement-item {
display: flex;
padding: 32rpx 0;
border-bottom: 1rpx solid #f0f1ff;
gap: 24rpx;
&:last-child {
border-bottom: 0;
padding-bottom: 0;
}
}
.achievement-icon {
width: 96rpx;
height: 96rpx;
border-radius: 24rpx;
display: flex;
align-items: center;
justify-content: center;
background: rgba(152, 16, 250, 0.12);
color: #9810fa;
.iconfont {
font-size: 44rpx;
}
}
.achievement-content {
flex: 1;
}
.achievement-header {
margin-bottom: 12rpx;
.achievement-title {
font-size: 30rpx;
font-weight: 600;
color: #2b2d4f;
}
.achievement-percent {
font-size: 26rpx;
color: #9810fa;
font-weight: 600;
}
}
.achievement-desc {
font-size: 24rpx;
color: #7c7ea7;
line-height: 1.6;
margin-bottom: 24rpx;
}
.achievement-progress {
margin-bottom: 20rpx;
}
.progress-track {
height: 18rpx;
border-radius: 999rpx;
background: #f1f2fe;
overflow: hidden;
margin-bottom: 12rpx;
}
.progress-chunk {
height: 100%;
border-radius: inherit;
background: linear-gradient(135deg, #a246ff, #f447c3);
}
.progress-meta {
font-size: 24rpx;
color: #9a9cc0;
}
.achievement-reward {
gap: 12rpx;
}
.reward-badge {
background: rgba(152, 16, 250, 0.12);
color: #9810fa;
border-radius: 999rpx;
padding: 8rpx 20rpx;
font-size: 22rpx;
}
.reward-text {
font-size: 24rpx;
color: #5a5c8f;
}
</style>