This commit is contained in:
左哥 2025-11-13 22:53:09 +08:00
parent 405bfa41f4
commit ce44170338
8 changed files with 2878 additions and 14 deletions

View File

@ -50,7 +50,7 @@
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "",
"appid" : "wx26ad074017e1e63f",
"setting" : {
"urlCheck" : false
},

View File

@ -1,5 +1,5 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
"pages": [
{
"path": "pages/index/index",
"style": {
@ -30,6 +30,12 @@
"style": {
"navigationBarTitleText": "我的"
}
},
{
"path": "pages/my/editInfo/index",
"style": {
"navigationBarTitleText": "编辑信息"
}
}
],
"globalStyle": {

View File

@ -1,11 +1,240 @@
<template>
<view class="">
<view class="create-page">
<view class="header-section">
<view class="header-badge">
<text class="iconfont icon-shandian"></text>
</view>
<view class="header-title">
选择您想要创建的内容类型
</view>
<view class="header-subtitle">
根据业务需求选择合适的方案快速完成配置
</view>
</view>
<view class="card-list">
<view
v-for="option in createOptions"
:key="option.id"
class="create-card"
:class="option.tone"
@click="handleCreate(option)"
>
<view class="card-icon">
<text class="iconfont" :class="option.icon"></text>
</view>
<view class="card-title">{{ option.title }}</view>
<view class="card-desc">
{{ option.description }}
</view>
<view class="card-tags">
<view
class="tag"
v-for="tag in option.tags"
:key="tag"
>
{{ tag }}
</view>
</view>
<view class="action-button" :class="option.tone">
<text class="plus">+</text>
<text class="action-text">立即创建</text>
<text class="iconfont icon-zhifeiji1"></text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
createOptions: [
{
id: 'group',
title: '香水团购',
description: '发起香水团购活动,人数越多折扣越大',
tags: ['阶梯折扣', '正品保证', '快速成团'],
icon: 'icon-shandian',
tone: 'group',
url: '/pages/index/index',
navType: 'switchTab'
},
{
id: 'distribution',
title: '香水分装',
description: '发起香水分装服务,小容量更实惠',
tags: ['小容量', '超值价格', '多款选择'],
icon: 'icon-lihe',
tone: 'distribution',
url: '/pages/distribution/index',
navType: 'switchTab'
}
]
};
},
methods: {
handleCreate(option) {
if (!option.url) {
uni.showToast({
title: '功能即将上线',
icon: 'none'
});
return;
}
if (option.navType === 'switchTab') {
uni.switchTab({
url: option.url
});
return;
}
uni.navigateTo({
url: option.url
});
}
}
};
</script>
<style>
<style scoped>
.create-page {
min-height: 100vh;
padding: 48rpx 32rpx 80rpx;
background: linear-gradient(180deg, #f4f2ff 0%, #ffffff 45%, #ffffff 100%);
box-sizing: border-box;
}
.header-section {
display: flex;
flex-direction: column;
gap: 20rpx;
margin-bottom: 40rpx;
}
.header-badge {
width: 120rpx;
height: 120rpx;
border-radius: 32rpx;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #f401ff 0%, #8317ff 100%);
color: #fff;
box-shadow: 0 20rpx 40rpx rgba(132, 23, 255, 0.2);
font-size: 52rpx;
}
.header-title {
font-size: 42rpx;
font-weight: 700;
color: #1f2240;
}
.header-subtitle {
font-size: 28rpx;
color: #7d8198;
}
.card-list {
display: flex;
flex-direction: column;
gap: 32rpx;
}
.create-card {
background: #ffffff;
border-radius: 36rpx;
padding: 48rpx 40rpx;
box-shadow: 0 28rpx 68rpx rgba(148, 110, 255, 0.12);
display: flex;
flex-direction: column;
gap: 26rpx;
}
.card-icon {
width: 120rpx;
height: 120rpx;
border-radius: 36rpx;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 54rpx;
}
.create-card.group .card-icon {
background: linear-gradient(135deg, #ff6388 0%, #ff3b6d 100%);
box-shadow: 0 20rpx 40rpx rgba(255, 62, 120, 0.25);
}
.create-card.distribution .card-icon {
background: linear-gradient(135deg, #6e6bff 0%, #9828ff 100%);
box-shadow: 0 20rpx 40rpx rgba(120, 64, 255, 0.25);
}
.card-title {
font-size: 38rpx;
font-weight: 700;
color: #1f2240;
}
.card-desc {
font-size: 28rpx;
line-height: 44rpx;
color: #646887;
}
.card-tags {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.tag {
padding: 12rpx 24rpx;
border-radius: 999rpx;
background: rgba(132, 23, 255, 0.08);
color: #5a4cff;
font-size: 24rpx;
}
.create-card.group .tag {
background: rgba(255, 61, 109, 0.1);
color: #ff3d6d;
}
.create-card.distribution .tag {
background: rgba(120, 64, 255, 0.12);
color: #624dff;
}
.action-button {
margin-top: 12rpx;
height: 96rpx;
border-radius: 999rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
color: #ffffff;
font-size: 32rpx;
font-weight: 600;
}
.action-button .plus {
font-size: 40rpx;
}
.action-button.group {
background: linear-gradient(90deg, #ff3d6d 0%, #ff00b8 100%);
box-shadow: 0 18rpx 34rpx rgba(255, 0, 120, 0.2);
}
.action-button.distribution {
background: linear-gradient(90deg, #6158ff 0%, #9f21ff 100%);
box-shadow: 0 18rpx 34rpx rgba(97, 88, 255, 0.22);
}
</style>

View File

@ -1,11 +1,936 @@
<template>
<view class="">
<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>
<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>

View File

@ -230,7 +230,7 @@
}
</script>
<style lang="scss">
<style lang="scss" scoped>
.header {
padding: 30rpx;
box-shadow: 0 2rpx 6rpx 0 rgb(0 0 0 / 0.1), 0 2rpx 4rpx -2rpx rgb(0 0 0 / 0.1);

268
pages/my/editInfo/index.vue Normal file
View File

@ -0,0 +1,268 @@
<template>
<view class="page">
<view class="header">
<text class="title">编辑个人信息</text>
<text class="subtitle">完善资料便于我们为您提供更贴心的服务</text>
</view>
<view class="form-card">
<view class="form-item">
<text class="form-label">姓名</text>
<input
class="form-input"
v-model="form.name"
type="text"
placeholder="请输入您的姓名"
placeholder-class="form-placeholder"
/>
</view>
<view class="form-item">
<text class="form-label">手机号</text>
<input
class="form-input"
v-model="form.phone"
type="number"
maxlength="11"
placeholder="请输入常用手机号"
placeholder-class="form-placeholder"
/>
</view>
<view class="form-item">
<text class="form-label">邮箱</text>
<input
class="form-input"
v-model="form.email"
type="text"
placeholder="请输入联系邮箱"
placeholder-class="form-placeholder"
/>
</view>
<view class="form-item">
<text class="form-label">地址</text>
<textarea
class="form-textarea"
v-model="form.address"
placeholder="请输入联系地址"
placeholder-class="form-placeholder"
auto-height="true"
/>
</view>
</view>
<view class="tips-card">
<text class="tips-title">信息使用说明</text>
<text class="tips-text">
姓名和联系方式仅用于订单通知及售后服务我们会严格保护您的隐私信息
</text>
</view>
<view class="actions">
<button class="btn cancel" @click="handleCancel">取消</button>
<button class="btn submit" type="primary" @click="handleSubmit">保存信息</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
form: {
name: '',
phone: '',
email: '',
address: ''
}
};
},
onLoad() {
this.loadProfile();
},
methods: {
loadProfile() {
try {
const stored = uni.getStorageSync('userProfile');
if (stored) {
this.form = {
...this.form,
...stored
};
}
} catch (error) {
console.warn('加载个人信息失败', error);
}
},
validatePhone(phone) {
const phoneReg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/;
return phoneReg.test(phone);
},
validateEmail(email) {
const emailReg =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@(([^<>()[\]\.,;:\s@"]+\.)+[^<>()[\]\.,;:\s@"]{2,})$/i;
return emailReg.test(email);
},
handleCancel() {
uni.navigateBack({
delta: 1
});
},
handleSubmit() {
if (!this.form.name.trim()) {
return this.showToast('请填写姓名');
}
if (!this.form.phone.trim() || !this.validatePhone(this.form.phone.trim())) {
return this.showToast('请填写有效的手机号');
}
if (this.form.email.trim() && !this.validateEmail(this.form.email.trim())) {
return this.showToast('请填写有效的邮箱');
}
if (!this.form.address.trim()) {
return this.showToast('请填写联系地址');
}
try {
uni.setStorageSync('userProfile', { ...this.form });
this.showToast('保存成功', 'success');
setTimeout(() => {
uni.navigateBack({
delta: 1
});
}, 800);
} catch (error) {
this.showToast('信息保存失败,请稍后重试');
console.error('保存个人信息失败', error);
}
},
showToast(title, icon = 'none') {
uni.showToast({
title,
icon,
duration: 2000
});
}
}
};
</script>
<style scoped>
.page {
background: #f7f8fa;
padding: 40rpx 32rpx 80rpx;
display: flex;
flex-direction: column;
gap: 32rpx;
}
.header {
display: flex;
flex-direction: column;
gap: 12rpx;
}
.title {
font-size: 36rpx;
color: #1a1a1a;
font-weight: 600;
}
.subtitle {
font-size: 26rpx;
color: #8c8c8c;
line-height: 1.6;
}
.form-card {
background: #ffffff;
border-radius: 24rpx;
padding: 32rpx;
display: flex;
flex-direction: column;
gap: 32rpx;
box-shadow: 0 12rpx 30rpx rgba(16, 30, 54, 0.06);
}
.form-item {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.form-label {
font-size: 28rpx;
color: #1a1a1a;
font-weight: 500;
}
.form-input{
height: 80rpx;
}
.form-input,
.form-textarea {
width: 100%;
background: #f5f7fb;
border-radius: 16rpx;
padding: 24rpx 28rpx;
font-size: 28rpx;
color: #1a1a1a;
box-sizing: border-box;
}
.form-textarea {
min-height: 160rpx;
line-height: 1.6;
}
.form-placeholder {
color: #b0b3ba;
font-size: 28rpx;
}
.tips-card {
background: #fff8f2;
border-radius: 24rpx;
padding: 28rpx 32rpx;
display: flex;
flex-direction: column;
gap: 12rpx;
}
.tips-title {
font-size: 28rpx;
color: #ff7a00;
font-weight: 600;
}
.tips-text {
font-size: 26rpx;
color: #a66b3a;
line-height: 1.6;
}
.actions {
display: flex;
gap: 24rpx;
padding: 0 4rpx;
}
.btn {
flex: 1;
height: 92rpx;
border-radius: 46rpx;
font-size: 30rpx;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
}
.cancel {
color: #1a1a1a;
background: #e9ecf1;
}
.submit {
color: #ffffff;
background: linear-gradient(135deg, #8b40ff 0%, #ff3c8d 100%);
border: none;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,398 @@
<template>
<view class="">
<view class="subscribe-page">
<view class="banner">
<view class="banner-head">
<view class="banner-icon">
<text class="iconfont icon-lihe"></text>
</view>
<view class="banner-info">
<view class="banner-title">盲盒订阅</view>
<view class="banner-desc">每月惊喜专属香氛体验</view>
</view>
<view class="banner-meta">
<view class="meta-item">
<view class="meta-label">当前等级</view>
<view class="meta-value">{{ memberInfo.level }}</view>
</view>
<view class="meta-item">
<view class="meta-label">下次配送</view>
<view class="meta-value">{{ memberInfo.nextDelivery }}</view>
</view>
<view class="meta-item unlocked">
<view class="meta-label">已解锁</view>
<view class="meta-value">{{ memberInfo.unlocked }}</view>
</view>
</view>
</view>
<view class="tab-bar">
<view
v-for="tab in tabs"
:key="tab.key"
class="tab-item"
:class="{ active: activeTab === tab.key }"
@click="switchTab(tab.key)"
>
{{ tab.label }}
</view>
</view>
</view>
<view class="content">
<view class="membership-card">
<view class="card-header">
<view class="card-icon">
<text class="iconfont icon-xingxing"></text>
</view>
<view class="card-title">
<view class="card-name">{{ plan.name }}</view>
<view class="card-subtitle">{{ plan.tagline }}</view>
</view>
<view class="card-price">
<view class="current">{{ plan.price }}</view>
<view class="original">{{ plan.originalPrice }}</view>
<view class="discount">{{ plan.discount }}</view>
</view>
</view>
<view class="card-section">
<view class="section-title">会员权益</view>
<view class="benefit-list">
<view
class="benefit-item"
v-for="benefit in plan.benefits"
:key="benefit"
>
<view class="indicator"></view>
<text>{{ benefit }}</text>
</view>
</view>
</view>
<view class="card-section">
<view class="section-title">订阅特色</view>
<view class="feature-tags">
<view
class="tag"
v-for="tag in plan.features"
:key="tag"
>
{{ tag }}
</view>
</view>
</view>
<view class="card-action">
<button class="subscribe-button" @click="handleSubscribe">
立即订阅
</button>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
activeTab: 'plan',
tabs: [
{ key: 'plan', label: '订阅计划' },
{ key: 'scents', label: '香型管理' },
{ key: 'records', label: '配送记录' },
{ key: 'settings', label: '订阅设置' }
],
memberInfo: {
level: '品鉴会员',
nextDelivery: '2025-04-05',
unlocked: 4
},
plan: {
name: '探索会员',
tagline: '无门槛',
price: 99,
originalPrice: 129,
discount: '95折',
benefits: [
'盲盒95折优惠',
'月返5%积分',
'基础客服支持',
'每月1次退换货',
'标准配送'
],
features: ['4种香型', '基础包装', '标准配送']
}
};
},
methods: {
switchTab(key) {
this.activeTab = key;
if (key !== 'plan') {
uni.showToast({
title: '即将上线,敬请期待',
icon: 'none'
});
}
},
handleSubscribe() {
uni.showToast({
title: '订阅成功',
icon: 'success'
});
}
}
};
</script>
<style>
<style scoped>
.subscribe-page {
min-height: 100vh;
padding: 48rpx 32rpx 80rpx;
box-sizing: border-box;
background: linear-gradient(180deg, #fdf2ff 0%, #ffffff 45%, #ffffff 100%);
}
.banner {
padding: 48rpx 36rpx 32rpx;
border-radius: 32rpx;
background: linear-gradient(135deg, #ff3fb4 0%, #8f39ff 100%);
color: #fff;
box-shadow: 0 30rpx 50rpx rgba(143, 57, 255, 0.18);
}
.banner-head {
display: flex;
align-items: center;
gap: 32rpx;
}
.banner-icon {
width: 120rpx;
height: 120rpx;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.16);
font-size: 60rpx;
box-shadow: inset 0 10rpx 20rpx rgba(255, 255, 255, 0.2);
}
.banner-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 12rpx;
}
.banner-title {
font-size: 42rpx;
font-weight: 600;
}
.banner-desc {
font-size: 28rpx;
opacity: 0.85;
}
.banner-meta {
display: flex;
gap: 32rpx;
}
.meta-item {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.meta-label {
font-size: 24rpx;
opacity: 0.7;
}
.meta-value {
font-size: 30rpx;
font-weight: 600;
}
.meta-item.unlocked .meta-value {
display: flex;
align-items: baseline;
}
.tab-bar {
margin-top: 32rpx;
padding: 4rpx;
border-radius: 24rpx;
background: rgba(255, 255, 255, 0.18);
display: flex;
gap: 12rpx;
}
.tab-item {
flex: 1;
padding: 18rpx 0;
text-align: center;
border-radius: 18rpx;
font-size: 26rpx;
opacity: 0.85;
transition: all 0.2s ease-in-out;
}
.tab-item.active {
background: #fff;
color: #7b3cff;
box-shadow: 0 12rpx 20rpx rgba(255, 255, 255, 0.26);
opacity: 1;
}
.content {
margin-top: 40rpx;
}
.membership-card {
background: #fff;
border-radius: 32rpx;
padding: 40rpx 36rpx;
box-shadow: 0 20rpx 40rpx rgba(30, 10, 80, 0.05);
display: flex;
flex-direction: column;
gap: 40rpx;
}
.card-header {
display: flex;
align-items: center;
gap: 28rpx;
}
.card-icon {
width: 110rpx;
height: 110rpx;
border-radius: 32rpx;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #ff60e9 0%, #894dff 100%);
color: #fff;
font-size: 52rpx;
box-shadow: 0 20rpx 40rpx rgba(137, 77, 255, 0.25);
}
.card-title {
flex: 1;
display: flex;
flex-direction: column;
gap: 8rpx;
}
.card-name {
font-size: 36rpx;
font-weight: 600;
color: #2c2440;
}
.card-subtitle {
font-size: 26rpx;
color: #8f87a5;
}
.card-price {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 6rpx;
}
.card-price .current {
font-size: 40rpx;
font-weight: 700;
color: #7b3cff;
}
.card-price .original {
font-size: 26rpx;
color: #b4acc8;
text-decoration: line-through;
}
.card-price .discount {
font-size: 24rpx;
color: #7b3cff;
padding: 8rpx 20rpx;
border-radius: 16rpx;
background: rgba(123, 60, 255, 0.1);
}
.card-section {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.section-title {
font-size: 30rpx;
font-weight: 600;
color: #30274a;
}
.benefit-list {
display: flex;
flex-direction: column;
gap: 18rpx;
}
.benefit-item {
display: flex;
align-items: center;
gap: 16rpx;
font-size: 26rpx;
color: #4a3f63;
}
.benefit-item .indicator {
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background: linear-gradient(135deg, #ff62e2 0%, #864dff 100%);
}
.feature-tags {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.feature-tags .tag {
padding: 14rpx 24rpx;
border-radius: 20rpx;
font-size: 24rpx;
color: #7b3cff;
background: rgba(123, 60, 255, 0.08);
}
.card-action {
display: flex;
justify-content: center;
}
.subscribe-button {
width: 100%;
height: 96rpx;
border-radius: 28rpx;
background: linear-gradient(135deg, #ff47c8 0%, #8547ff 100%);
color: #fff;
font-size: 30rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 20rpx 40rpx rgba(133, 71, 255, 0.25);
}
.subscribe-button::after {
border: none;
}
</style>