|
|
@@ -1,17 +1,19 @@
|
|
|
<template>
|
|
|
<view class="upgrade-page-wrapper">
|
|
|
<scroll-view class="page" scroll-y>
|
|
|
- <!-- 当前会员状态卡片 -->
|
|
|
+ <!-- 当前会员状态条 -->
|
|
|
<view class="status-card">
|
|
|
- <view class="status-badge" :class="isFree ? 'badge-free' : 'badge-family'">
|
|
|
- <text class="badge-icon">{{ isFree ? '○' : '●' }}</text>
|
|
|
- <text class="badge-text">{{ currentLevelName }}</text>
|
|
|
+ <view class="status-top">
|
|
|
+ <view class="status-badge" :class="isFree ? 'badge-free' : 'badge-family'">
|
|
|
+ <text class="badge-icon">{{ isFree ? '○' : '●' }}</text>
|
|
|
+ <text class="badge-text">{{ currentLevelName }}</text>
|
|
|
+ </view>
|
|
|
+ <text class="free-hint" v-if="isFree">开通会员解锁全部特权</text>
|
|
|
+ <text class="expiry-value" v-else-if="membership && membership.memberLevel !== 'FREE'">
|
|
|
+ {{ formatDate(membership.endDate) }} 到期
|
|
|
+ </text>
|
|
|
</view>
|
|
|
<view class="status-body" v-if="membership && membership.memberLevel !== 'FREE'">
|
|
|
- <view class="expiry-row">
|
|
|
- <text class="expiry-label">到期时间</text>
|
|
|
- <text class="expiry-value">{{ formatDate(membership.endDate) }}</text>
|
|
|
- </view>
|
|
|
<view class="days-remaining" v-if="membership.isActive">
|
|
|
<text class="days-num">{{ membership.daysRemaining || 0 }}</text>
|
|
|
<text class="days-unit">天剩余</text>
|
|
|
@@ -20,30 +22,23 @@
|
|
|
<text class="expired-text">会员已过期,续费恢复权益</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view class="status-body" v-else>
|
|
|
- <text class="free-hint">当前为免费版,开通会员解锁全部特权</text>
|
|
|
- </view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 等级切换 tabs -->
|
|
|
- <view class="level-tabs" v-if="isFree">
|
|
|
- <view class="level-tab" :class="selectedLevel === 'FAMILY' ? 'level-tab-active' : ''"
|
|
|
- @click="selectLevel('FAMILY')">
|
|
|
- <text class="level-tab-name">家庭会员</text>
|
|
|
- <text class="level-tab-price">¥{{ getLevelYearlyPrice('FAMILY') }}/年</text>
|
|
|
- </view>
|
|
|
- <view class="level-tab" :class="selectedLevel === 'PREMIUM' ? 'level-tab-active' : ''"
|
|
|
- @click="selectLevel('PREMIUM')">
|
|
|
- <text class="level-tab-name">高级家庭会员</text>
|
|
|
- <text class="level-tab-price">¥{{ getLevelYearlyPrice('PREMIUM') }}/年</text>
|
|
|
+ <view class="level-tabs" v-if="buyableLevels.length > 0">
|
|
|
+ <view class="level-tab" v-for="lv in buyableLevels" :key="lv.levelCode"
|
|
|
+ :class="selectedLevel === lv.levelCode ? 'level-tab-active' : ''"
|
|
|
+ @click="selectLevel(lv.levelCode)">
|
|
|
+ <text class="level-tab-name">{{ lv.levelName }}</text>
|
|
|
+ <text class="level-tab-price">¥{{ getLevelYearlyPrice(lv.levelCode) }}/年</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 家庭会员开通卡片 -->
|
|
|
- <view class="upgrade-card" v-if="isFree">
|
|
|
+ <!-- 开通/升级卡片(免费用户开通,或已付费用户切换到其他等级时升级) -->
|
|
|
+ <view class="upgrade-card" v-if="isFree || selectedLevel !== currentMemberLevel">
|
|
|
<view class="upgrade-header">
|
|
|
- <text class="upgrade-title">{{ selectedLevel === 'FAMILY' ? '家庭会员' : '高级家庭会员' }}</text>
|
|
|
- <text class="upgrade-subtitle">{{ selectedLevel === 'FAMILY' ? 'FAMILY' : 'PREMIUM' }}</text>
|
|
|
+ <text class="upgrade-title">{{ getSelectedLevelName() }}</text>
|
|
|
+ <text class="upgrade-subtitle">{{ selectedLevel }}</text>
|
|
|
</view>
|
|
|
<!-- 档位选择 -->
|
|
|
<view class="period-tabs">
|
|
|
@@ -59,22 +54,10 @@
|
|
|
<text class="period-original" v-if="showOriginalPrice(p.key)">¥{{ getOriginalPriceForPeriod(p.key) / 100 }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view class="upgrade-price">
|
|
|
- <text class="price-original-line" v-if="showOriginalPrice(selectedPeriod)">¥{{ getOriginalPriceForPeriod(selectedPeriod) / 100 }}</text>
|
|
|
- <text class="price-symbol">¥</text>
|
|
|
- <text class="price-amount">{{ getPriceForPeriod(selectedPeriod) }}</text>
|
|
|
- <text class="price-unit">{{ getPeriodUnit() }}</text>
|
|
|
- </view>
|
|
|
- <view class="feature-list">
|
|
|
- <view class="feature-item" v-for="(feature, idx) in features" :key="idx">
|
|
|
- <text class="feature-check">✓</text>
|
|
|
- <text class="feature-text">{{ feature }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
<button class="btn-upgrade" @click="goNext">下一步</button>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 续费卡片 -->
|
|
|
+ <!-- 续费卡片(已付费用户保持当前等级) -->
|
|
|
<view class="upgrade-card" v-else>
|
|
|
<view class="upgrade-header">
|
|
|
<text class="upgrade-title">续费会员</text>
|
|
|
@@ -94,12 +77,6 @@
|
|
|
<text class="period-original" v-if="showOriginalPrice(p.key)">¥{{ getOriginalPriceForPeriod(p.key) / 100 }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view class="upgrade-price">
|
|
|
- <text class="price-original-line" v-if="showOriginalPrice(selectedPeriod)">¥{{ getOriginalPriceForPeriod(selectedPeriod) / 100 }}</text>
|
|
|
- <text class="price-symbol">¥</text>
|
|
|
- <text class="price-amount">{{ getPriceForPeriod(selectedPeriod) }}</text>
|
|
|
- <text class="price-unit">{{ getPeriodUnit() }}</text>
|
|
|
- </view>
|
|
|
<button class="btn-upgrade btn-renew" @click="goNext">下一步</button>
|
|
|
</view>
|
|
|
|
|
|
@@ -110,14 +87,14 @@
|
|
|
<view class="compare-row header-row">
|
|
|
<text class="compare-cell cell-feature">权益项</text>
|
|
|
<text class="compare-cell cell-free">免费</text>
|
|
|
- <text class="compare-cell cell-family active">家庭会员</text>
|
|
|
- <text class="compare-cell cell-premium active">高级会员</text>
|
|
|
+ <text class="compare-cell cell-family" :class="selectedLevel === 'FAMILY' ? 'active' : ''">家庭会员</text>
|
|
|
+ <text class="compare-cell cell-premium" :class="selectedLevel === 'PREMIUM' ? 'active' : ''">高级会员</text>
|
|
|
</view>
|
|
|
<view class="compare-row" v-for="(item, idx) in compareData" :key="idx">
|
|
|
<text class="compare-cell cell-feature">{{ item.name }}</text>
|
|
|
<text class="compare-cell cell-free">{{ item.free }}</text>
|
|
|
- <text class="compare-cell cell-family active">{{ item.family }}</text>
|
|
|
- <text class="compare-cell cell-premium active">{{ item.premium }}</text>
|
|
|
+ <text class="compare-cell cell-family" :class="selectedLevel === 'FAMILY' ? 'active' : ''">{{ item.family }}</text>
|
|
|
+ <text class="compare-cell cell-premium" :class="selectedLevel === 'PREMIUM' ? 'active' : ''">{{ item.premium }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -156,14 +133,13 @@ export default {
|
|
|
membership: null,
|
|
|
levels: [],
|
|
|
records: [],
|
|
|
- features: ['折扣购物', '家庭管理', '推荐佣金', '专属活动', '任务特权', '成长报告'],
|
|
|
isFree: true,
|
|
|
currentLevelName: '免费用户',
|
|
|
compareData: [
|
|
|
- { name: '商品折扣', free: '普通价格', family: '9折', premium: '8折', lifetime: '全场最低价' },
|
|
|
+ { name: '商品折扣', free: '普通价格', family: '会员折扣', premium: '会员折扣', lifetime: '会员折扣' },
|
|
|
{ name: '家庭管理', free: '基础功能', family: '全部功能', premium: '全部功能+优先响应', lifetime: '全部功能+专属管家' },
|
|
|
{ name: '管家服务', free: '—', family: '—', premium: '每周一次', lifetime: '专属管家7×24h' },
|
|
|
- { name: '推荐佣金', free: '不可参与', family: '最高15%', premium: '最高20%', lifetime: '最高25%+团队分红' },
|
|
|
+ { name: '推荐佣金', free: '不可参与', family: '可参与', premium: '可参与', lifetime: '可参与' },
|
|
|
{ name: '专属活动', free: '部分参与', family: '全部参与', premium: '优先参与', lifetime: 'VIP专属+定制活动' },
|
|
|
{ name: '成长报告', free: '月度', family: '每周+深度', premium: '每日+深度+专家解读', lifetime: '实时+AI专家深度解读' },
|
|
|
{ name: '任务配额', free: '每日5个', family: '不限量', premium: '不限量+优先审核', lifetime: '不限量+专属通道' }
|
|
|
@@ -175,10 +151,17 @@ export default {
|
|
|
],
|
|
|
selectedPeriod: 'yearly',
|
|
|
selectedLevel: 'FAMILY',
|
|
|
+ currentMemberLevel: 'FREE',
|
|
|
joinRules: [],
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
+ buyableLevels() {
|
|
|
+ var self = this
|
|
|
+ return this.levels.filter(function(lv) {
|
|
|
+ return lv.levelCode !== 'FREE' && lv.levelCode !== 'LIFETIME' && lv.levelCode !== 'PROVIDER'
|
|
|
+ })
|
|
|
+ },
|
|
|
visiblePeriods() {
|
|
|
var self = this
|
|
|
return this.periods.filter(function(p) {
|
|
|
@@ -215,6 +198,16 @@ export default {
|
|
|
}
|
|
|
return map[code] || code || ''
|
|
|
},
|
|
|
+ getSelectedLevelName() {
|
|
|
+ var name = ''
|
|
|
+ for (var i = 0; i < this.levels.length; i++) {
|
|
|
+ if (this.levels[i].levelCode === this.selectedLevel) {
|
|
|
+ name = this.levels[i].levelName
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return name || this.getLevelName(this.selectedLevel)
|
|
|
+ },
|
|
|
getJoinRuleKey(rule, idx) {
|
|
|
return rule.id + '-' + idx
|
|
|
},
|
|
|
@@ -231,11 +224,14 @@ export default {
|
|
|
this.membership = membershipRes.data
|
|
|
if (this.membership && this.membership.memberLevel && this.membership.memberLevel !== 'FREE') {
|
|
|
this.isFree = false
|
|
|
+ this.currentMemberLevel = this.membership.memberLevel
|
|
|
this.currentLevelName = this.membership.levelName || '家庭会员'
|
|
|
this.selectedLevel = this.membership.memberLevel
|
|
|
} else {
|
|
|
this.isFree = true
|
|
|
+ this.currentMemberLevel = 'FREE'
|
|
|
this.currentLevelName = '免费用户'
|
|
|
+ this.selectedLevel = 'FAMILY'
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('加载会员信息失败', e)
|
|
|
@@ -284,14 +280,6 @@ export default {
|
|
|
if (periodKey === 'yearly') return plan.yearly ? (plan.yearly / 100).toFixed(0) : '0'
|
|
|
return '0'
|
|
|
},
|
|
|
- getPeriodUnit: function() {
|
|
|
- for (var i = 0; i < this.periods.length; i++) {
|
|
|
- if (this.periods[i].key === this.selectedPeriod) {
|
|
|
- return this.periods[i].unit
|
|
|
- }
|
|
|
- }
|
|
|
- return '/年'
|
|
|
- },
|
|
|
goNext: function() {
|
|
|
var levelCode = this.selectedLevel
|
|
|
var period = this.selectedPeriod
|
|
|
@@ -339,8 +327,13 @@ export default {
|
|
|
.status-card {
|
|
|
background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
|
|
|
border-radius: 20rpx;
|
|
|
- padding: 40rpx;
|
|
|
- margin-bottom: 30rpx;
|
|
|
+ padding: 26rpx 30rpx;
|
|
|
+ margin-bottom: 24rpx;
|
|
|
+}
|
|
|
+.status-top {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
}
|
|
|
.status-badge {
|
|
|
display: inline-flex;
|
|
|
@@ -369,51 +362,42 @@ export default {
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
.status-body {
|
|
|
- margin-top: 24rpx;
|
|
|
-}
|
|
|
-.expiry-row {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-.expiry-label {
|
|
|
- font-size: 26rpx;
|
|
|
- color: rgba(255,255,255,0.8);
|
|
|
+ margin-top: 18rpx;
|
|
|
}
|
|
|
.expiry-value {
|
|
|
- font-size: 28rpx;
|
|
|
+ font-size: 26rpx;
|
|
|
color: #fff;
|
|
|
font-weight: 500;
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
|
.days-remaining {
|
|
|
display: flex;
|
|
|
align-items: baseline;
|
|
|
justify-content: center;
|
|
|
- margin-top: 20rpx;
|
|
|
+ margin-top: 14rpx;
|
|
|
}
|
|
|
.days-num {
|
|
|
- font-size: 56rpx;
|
|
|
+ font-size: 44rpx;
|
|
|
font-weight: bold;
|
|
|
color: #FEF3C7;
|
|
|
}
|
|
|
.days-unit {
|
|
|
- font-size: 26rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
color: rgba(255,255,255,0.7);
|
|
|
margin-left: 8rpx;
|
|
|
}
|
|
|
.expired-msg {
|
|
|
text-align: center;
|
|
|
- margin-top: 16rpx;
|
|
|
+ margin-top: 12rpx;
|
|
|
}
|
|
|
.expired-text {
|
|
|
- font-size: 26rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
color: #FEF3C7;
|
|
|
}
|
|
|
.free-hint {
|
|
|
- font-size: 26rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
color: rgba(255,255,255,0.85);
|
|
|
- text-align: center;
|
|
|
- display: block;
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
|
.lifetime-hint {
|
|
|
font-size: 26rpx;
|
|
|
@@ -447,50 +431,6 @@ export default {
|
|
|
margin-top: 6rpx;
|
|
|
display: block;
|
|
|
}
|
|
|
-.upgrade-price {
|
|
|
- text-align: center;
|
|
|
- margin: 24rpx 0;
|
|
|
-}
|
|
|
-.price-symbol {
|
|
|
- font-size: 28rpx;
|
|
|
- color: #F97316;
|
|
|
- vertical-align: top;
|
|
|
-}
|
|
|
-.price-amount {
|
|
|
- font-size: 64rpx;
|
|
|
- font-weight: bold;
|
|
|
- color: #F97316;
|
|
|
- line-height: 1;
|
|
|
-}
|
|
|
-.price-unit {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #94A3B8;
|
|
|
- margin-left: 6rpx;
|
|
|
-}
|
|
|
-.feature-list {
|
|
|
- margin: 24rpx 0;
|
|
|
-}
|
|
|
-.feature-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- padding: 12rpx 0;
|
|
|
-}
|
|
|
-.feature-check {
|
|
|
- width: 40rpx;
|
|
|
- height: 40rpx;
|
|
|
- line-height: 40rpx;
|
|
|
- text-align: center;
|
|
|
- background: #F97316;
|
|
|
- color: #fff;
|
|
|
- border-radius: 50%;
|
|
|
- font-size: 22rpx;
|
|
|
- margin-right: 16rpx;
|
|
|
- flex-shrink: 0;
|
|
|
-}
|
|
|
-.feature-text {
|
|
|
- font-size: 28rpx;
|
|
|
- color: #1E293B;
|
|
|
-}
|
|
|
.btn-upgrade {
|
|
|
width: 100%;
|
|
|
height: 88rpx;
|
|
|
@@ -562,10 +502,12 @@ export default {
|
|
|
color: #94A3B8;
|
|
|
}
|
|
|
.cell-family.active {
|
|
|
+ background: #FFEDD5;
|
|
|
color: #F97316;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
.cell-premium.active {
|
|
|
+ background: #EDE9FE;
|
|
|
color: #8B5CF6;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
@@ -587,9 +529,11 @@ export default {
|
|
|
color: #64748B;
|
|
|
}
|
|
|
.header-row .cell-family.active {
|
|
|
+ background: #FFEDD5;
|
|
|
color: #F97316;
|
|
|
}
|
|
|
.header-row .cell-premium.active {
|
|
|
+ background: #EDE9FE;
|
|
|
color: #8B5CF6;
|
|
|
}
|
|
|
|
|
|
@@ -906,10 +850,4 @@ export default {
|
|
|
text-decoration: line-through;
|
|
|
margin-top: 2rpx;
|
|
|
}
|
|
|
-.price-original-line {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #94A3B8;
|
|
|
- text-decoration: line-through;
|
|
|
- margin-right: 12rpx;
|
|
|
-}
|
|
|
</style>
|