|
@@ -7,7 +7,7 @@
|
|
|
<text class="badge-icon">{{ isFree ? '○' : '●' }}</text>
|
|
<text class="badge-icon">{{ isFree ? '○' : '●' }}</text>
|
|
|
<text class="badge-text">{{ currentLevelName }}</text>
|
|
<text class="badge-text">{{ currentLevelName }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="status-body" v-if="membership && membership.levelCode !== 'FREE'">
|
|
|
|
|
|
|
+ <view class="status-body" v-if="membership && membership.memberLevel !== 'FREE'">
|
|
|
<view class="expiry-row">
|
|
<view class="expiry-row">
|
|
|
<text class="expiry-label">到期时间</text>
|
|
<text class="expiry-label">到期时间</text>
|
|
|
<text class="expiry-value">{{ formatDate(membership.endDate) }}</text>
|
|
<text class="expiry-value">{{ formatDate(membership.endDate) }}</text>
|
|
@@ -56,9 +56,11 @@
|
|
|
>
|
|
>
|
|
|
<text class="period-tab-label">{{ p.label }}</text>
|
|
<text class="period-tab-label">{{ p.label }}</text>
|
|
|
<text class="period-tab-price">¥{{ getPriceForPeriod(p.key) }}</text>
|
|
<text class="period-tab-price">¥{{ getPriceForPeriod(p.key) }}</text>
|
|
|
|
|
+ <text class="period-original" v-if="showOriginalPrice(p.key)">¥{{ getOriginalPriceForPeriod(p.key) / 100 }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="upgrade-price">
|
|
<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-symbol">¥</text>
|
|
|
<text class="price-amount">{{ getPriceForPeriod(selectedPeriod) }}</text>
|
|
<text class="price-amount">{{ getPriceForPeriod(selectedPeriod) }}</text>
|
|
|
<text class="price-unit">{{ getPeriodUnit() }}</text>
|
|
<text class="price-unit">{{ getPeriodUnit() }}</text>
|
|
@@ -69,14 +71,7 @@
|
|
|
<text class="feature-text">{{ feature }}</text>
|
|
<text class="feature-text">{{ feature }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- <!-- Coupon section -->
|
|
|
|
|
- <view class="coupon-row" @click="openCouponPicker">
|
|
|
|
|
- <text class="coupon-row-label">优惠券</text>
|
|
|
|
|
- <text v-if="selectedCoupon" class="coupon-row-discount">-{{ formatPriceWithSymbol(selectedCoupon.value) }} {{ selectedCoupon.name }}</text>
|
|
|
|
|
- <text v-else class="coupon-row-placeholder">选择优惠券</text>
|
|
|
|
|
- <text class="coupon-row-arrow">›</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <button class="btn-upgrade" @click="handleUpgrade">立即开通</button>
|
|
|
|
|
|
|
+ <button class="btn-upgrade" @click="goNext">下一步</button>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 续费卡片 -->
|
|
<!-- 续费卡片 -->
|
|
@@ -96,21 +91,16 @@
|
|
|
>
|
|
>
|
|
|
<text class="period-tab-label">{{ p.label }}</text>
|
|
<text class="period-tab-label">{{ p.label }}</text>
|
|
|
<text class="period-tab-price">¥{{ getPriceForPeriod(p.key) }}</text>
|
|
<text class="period-tab-price">¥{{ getPriceForPeriod(p.key) }}</text>
|
|
|
|
|
+ <text class="period-original" v-if="showOriginalPrice(p.key)">¥{{ getOriginalPriceForPeriod(p.key) / 100 }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="upgrade-price">
|
|
<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-symbol">¥</text>
|
|
|
<text class="price-amount">{{ getPriceForPeriod(selectedPeriod) }}</text>
|
|
<text class="price-amount">{{ getPriceForPeriod(selectedPeriod) }}</text>
|
|
|
<text class="price-unit">{{ getPeriodUnit() }}</text>
|
|
<text class="price-unit">{{ getPeriodUnit() }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <!-- Coupon section -->
|
|
|
|
|
- <view class="coupon-row" @click="openCouponPicker">
|
|
|
|
|
- <text class="coupon-row-label">优惠券</text>
|
|
|
|
|
- <text v-if="selectedCoupon" class="coupon-row-discount">-{{ formatPriceWithSymbol(selectedCoupon.value) }} {{ selectedCoupon.name }}</text>
|
|
|
|
|
- <text v-else class="coupon-row-placeholder">选择优惠券</text>
|
|
|
|
|
- <text class="coupon-row-arrow">›</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <button class="btn-upgrade btn-renew" @click="handleRenew">立即续费</button>
|
|
|
|
|
|
|
+ <button class="btn-upgrade btn-renew" @click="goNext">下一步</button>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 权益对比表 -->
|
|
<!-- 权益对比表 -->
|
|
@@ -153,47 +143,11 @@
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</scroll-view>
|
|
</scroll-view>
|
|
|
-
|
|
|
|
|
- <!-- Coupon Picker Bottom Sheet -->
|
|
|
|
|
- <view class="modal-mask" v-if="showCouponPicker" @click="showCouponPicker = false">
|
|
|
|
|
- <view class="coupon-picker" @click.stop>
|
|
|
|
|
- <view class="picker-header">
|
|
|
|
|
- <text class="picker-title">选择优惠券</text>
|
|
|
|
|
- <text class="picker-close" @click="showCouponPicker = false">关闭</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <scroll-view scroll-y class="picker-list">
|
|
|
|
|
- <view
|
|
|
|
|
- v-for="coupon in availableCoupons"
|
|
|
|
|
- :key="coupon.id"
|
|
|
|
|
- class="picker-item"
|
|
|
|
|
- :class="selectedCoupon && selectedCoupon.id === coupon.id ? 'picker-item-active' : ''"
|
|
|
|
|
- @click="selectCoupon(coupon)"
|
|
|
|
|
- >
|
|
|
|
|
- <view class="picker-item-left">
|
|
|
|
|
- <text class="picker-item-value">{{ formatPriceWithSymbol(coupon.value) }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="picker-item-right">
|
|
|
|
|
- <text class="picker-item-name">{{ coupon.name }}</text>
|
|
|
|
|
- <text class="picker-item-condition">{{ getCouponCondition(coupon.minSpend) }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="picker-item-check" v-if="selectedCoupon && selectedCoupon.id === coupon.id">
|
|
|
|
|
- <text>✓</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="picker-empty" v-if="availableCoupons.length === 0">
|
|
|
|
|
- <text>暂无可用优惠券</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </scroll-view>
|
|
|
|
|
- <view class="picker-footer" v-if="selectedCoupon">
|
|
|
|
|
- <button class="picker-btn-remove" @click="removeCoupon">不使用优惠券</button>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import { getMyMembership, getMembershipPlans, getUpgradeRecords, upgradeMember, createOrder, getCouponList, requestVirtualPayment, nextOrder, getJoinCouponRules } from '../../utils/api.js'
|
|
|
|
|
|
|
+import { getMyMembership, getMembershipPlans, getUpgradeRecords, getJoinCouponRules } from '../../utils/api.js'
|
|
|
import { parseDate } from '../../utils/format.js'
|
|
import { parseDate } from '../../utils/format.js'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
@@ -214,9 +168,6 @@ export default {
|
|
|
{ name: '成长报告', free: '月度', family: '每周+深度', premium: '每日+深度+专家解读' },
|
|
{ name: '成长报告', free: '月度', family: '每周+深度', premium: '每日+深度+专家解读' },
|
|
|
{ name: '任务配额', free: '每日5个', family: '不限量', premium: '不限量+优先审核' }
|
|
{ name: '任务配额', free: '每日5个', family: '不限量', premium: '不限量+优先审核' }
|
|
|
],
|
|
],
|
|
|
- coupons: [],
|
|
|
|
|
- selectedCoupon: null,
|
|
|
|
|
- showCouponPicker: false,
|
|
|
|
|
periods: [
|
|
periods: [
|
|
|
{ key: 'monthly', label: '月度', unit: '/月' },
|
|
{ key: 'monthly', label: '月度', unit: '/月' },
|
|
|
{ key: 'quarterly', label: '季度', unit: '/季' },
|
|
{ key: 'quarterly', label: '季度', unit: '/季' },
|
|
@@ -239,14 +190,6 @@ export default {
|
|
|
}
|
|
}
|
|
|
return true
|
|
return true
|
|
|
})
|
|
})
|
|
|
- },
|
|
|
|
|
- availableCoupons() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- return this.coupons.filter(function(c) {
|
|
|
|
|
- if (c.status && c.status !== 'AVAILABLE') return false
|
|
|
|
|
- if (c.applicableTo && c.applicableTo !== 'ALL' && c.applicableTo !== 'MEMBERSHIP') return false
|
|
|
|
|
- return true
|
|
|
|
|
- })
|
|
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
onLoad() {
|
|
onLoad() {
|
|
@@ -286,10 +229,10 @@ export default {
|
|
|
try {
|
|
try {
|
|
|
const membershipRes = await getMyMembership()
|
|
const membershipRes = await getMyMembership()
|
|
|
this.membership = membershipRes.data
|
|
this.membership = membershipRes.data
|
|
|
- if (this.membership && this.membership.levelCode && this.membership.levelCode !== 'FREE') {
|
|
|
|
|
|
|
+ if (this.membership && this.membership.memberLevel && this.membership.memberLevel !== 'FREE') {
|
|
|
this.isFree = false
|
|
this.isFree = false
|
|
|
this.currentLevelName = this.membership.levelName || '家庭会员'
|
|
this.currentLevelName = this.membership.levelName || '家庭会员'
|
|
|
- this.selectedLevel = this.membership.levelCode
|
|
|
|
|
|
|
+ this.selectedLevel = this.membership.memberLevel
|
|
|
} else {
|
|
} else {
|
|
|
this.isFree = true
|
|
this.isFree = true
|
|
|
this.currentLevelName = '免费用户'
|
|
this.currentLevelName = '免费用户'
|
|
@@ -311,31 +254,6 @@ export default {
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
console.error('加载升级记录失败', e)
|
|
console.error('加载升级记录失败', e)
|
|
|
}
|
|
}
|
|
|
- try {
|
|
|
|
|
- const couponsRes = await getCouponList()
|
|
|
|
|
- this.coupons = couponsRes.data || []
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error('加载优惠券失败', e)
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- openCouponPicker() {
|
|
|
|
|
- if (this.availableCoupons.length === 0 && !this.selectedCoupon) {
|
|
|
|
|
- uni.showToast({ title: '暂无可用优惠券', icon: 'none' })
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- this.showCouponPicker = true
|
|
|
|
|
- },
|
|
|
|
|
- selectCoupon(coupon) {
|
|
|
|
|
- this.selectedCoupon = coupon
|
|
|
|
|
- this.showCouponPicker = false
|
|
|
|
|
- },
|
|
|
|
|
- removeCoupon() {
|
|
|
|
|
- this.selectedCoupon = null
|
|
|
|
|
- this.showCouponPicker = false
|
|
|
|
|
- },
|
|
|
|
|
- getCouponCondition(minSpend) {
|
|
|
|
|
- if (!minSpend || minSpend <= 0) return '无门槛'
|
|
|
|
|
- return '满' + (minSpend / 100).toFixed(2) + '元可用'
|
|
|
|
|
},
|
|
},
|
|
|
selectLevel: function(code) {
|
|
selectLevel: function(code) {
|
|
|
this.selectedLevel = code
|
|
this.selectedLevel = code
|
|
@@ -374,124 +292,30 @@ export default {
|
|
|
}
|
|
}
|
|
|
return '/年'
|
|
return '/年'
|
|
|
},
|
|
},
|
|
|
- handleUpgrade: function() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- var priceText = '¥' + this.getPriceForPeriod(this.selectedPeriod) + this.getPeriodUnit()
|
|
|
|
|
- var levelName = this.selectedLevel === 'FAMILY' ? '家庭会员' : '高级家庭会员'
|
|
|
|
|
- uni.showModal({
|
|
|
|
|
- title: '确认开通',
|
|
|
|
|
- content: '确认开通' + levelName + '(' + priceText + ')?',
|
|
|
|
|
- success: function(res) {
|
|
|
|
|
- if (!res.confirm) return
|
|
|
|
|
- self.doUpgrade()
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- },
|
|
|
|
|
- doUpgrade: function() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- createOrder(self.selectedLevel, 'pay', self.selectedPeriod).then(function(res) {
|
|
|
|
|
- var data = res.data || {}
|
|
|
|
|
- if (data.orderInfo && data.sign) {
|
|
|
|
|
- self.payInstallments(data)
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: '开通成功', icon: 'success' })
|
|
|
|
|
- self.loadData()
|
|
|
|
|
- }
|
|
|
|
|
- }).catch(function(e) {
|
|
|
|
|
- if (e.code === 46001) {
|
|
|
|
|
- uni.showToast({ title: '该商品暂未开放购买', icon: 'none' })
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: e.message || '开通失败', icon: 'none' })
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- },
|
|
|
|
|
- pollOrderStatus: function() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- var times = 0
|
|
|
|
|
- var timer = setInterval(function() {
|
|
|
|
|
- times++
|
|
|
|
|
- getMyMembership().then(function(res) {
|
|
|
|
|
- var m = res.data || {}
|
|
|
|
|
- if (m.membership && m.membership.isActive) {
|
|
|
|
|
- clearInterval(timer)
|
|
|
|
|
- uni.showToast({ title: '开通成功', icon: 'success' })
|
|
|
|
|
- self.loadData()
|
|
|
|
|
- } else if (times >= 5) {
|
|
|
|
|
- clearInterval(timer)
|
|
|
|
|
- self.loadData()
|
|
|
|
|
- }
|
|
|
|
|
- }).catch(function() {
|
|
|
|
|
- if (times >= 5) { clearInterval(timer); self.loadData() }
|
|
|
|
|
- })
|
|
|
|
|
- }, 2000)
|
|
|
|
|
- },
|
|
|
|
|
- payInstallments: function(dto) {
|
|
|
|
|
- var self = this
|
|
|
|
|
- var current = (dto.currentPeriod || 1)
|
|
|
|
|
- var total = (dto.totalPeriods || 1)
|
|
|
|
|
- requestVirtualPayment(dto, {
|
|
|
|
|
- success: function() {
|
|
|
|
|
- if (current < total) {
|
|
|
|
|
- uni.showToast({ title: '第' + current + '期支付成功', icon: 'none' })
|
|
|
|
|
- nextOrder({ orderNo: dto.orderNo }).then(function(res) {
|
|
|
|
|
- var nd = res.data
|
|
|
|
|
- if (nd && nd.done) {
|
|
|
|
|
- self.pollOrderStatus()
|
|
|
|
|
- } else if (nd && nd.orderInfo && nd.sign) {
|
|
|
|
|
- self.payInstallments(nd)
|
|
|
|
|
- } else {
|
|
|
|
|
- self.pollOrderStatus()
|
|
|
|
|
- }
|
|
|
|
|
- }).catch(function() {
|
|
|
|
|
- self.pollOrderStatus()
|
|
|
|
|
- })
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: '支付成功,开通中…', icon: 'none' })
|
|
|
|
|
- self.pollOrderStatus()
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- fail: function(err) {
|
|
|
|
|
- var errCode = err && err.errCode
|
|
|
|
|
- var msg = ''
|
|
|
|
|
- if (errCode === -15007 || errCode === -15005) msg = '登录态已过期,请重新登录后支付'
|
|
|
|
|
- else if (errCode === -15010) msg = '商品未发布,请联系客服'
|
|
|
|
|
- else if (errCode === -15013) msg = '商品价格异常'
|
|
|
|
|
- else if (errCode === -2) msg = '支付已取消'
|
|
|
|
|
- else if (err && err.errMsg) msg = err.errMsg
|
|
|
|
|
- uni.showToast({ title: msg || '支付未完成', icon: 'none' })
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ goNext: function() {
|
|
|
|
|
+ var levelCode = this.selectedLevel
|
|
|
|
|
+ var period = this.selectedPeriod
|
|
|
|
|
+ uni.navigateTo({ url: '/pages/membership/pay?levelCode=' + levelCode + '&period=' + period })
|
|
|
},
|
|
},
|
|
|
- handleRenew: function() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- var priceText = '¥' + this.getPriceForPeriod(this.selectedPeriod) + this.getPeriodUnit()
|
|
|
|
|
- var levelName = this.selectedLevel === 'FAMILY' ? '家庭会员' : '高级家庭会员'
|
|
|
|
|
- uni.showModal({
|
|
|
|
|
- title: '确认续费',
|
|
|
|
|
- content: '确认续费' + levelName + '(' + priceText + ')?',
|
|
|
|
|
- success: function(res) {
|
|
|
|
|
- if (!res.confirm) return
|
|
|
|
|
- self.doRenew()
|
|
|
|
|
|
|
+ getOriginalPriceForPeriod: function(periodKey) {
|
|
|
|
|
+ var plan = null
|
|
|
|
|
+ for (var i = 0; i < this.levels.length; i++) {
|
|
|
|
|
+ if (this.levels[i].levelCode === this.selectedLevel) {
|
|
|
|
|
+ plan = this.levels[i]
|
|
|
|
|
+ break
|
|
|
}
|
|
}
|
|
|
- })
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!plan) return null
|
|
|
|
|
+ if (periodKey === 'monthly') return plan.originalMonthly || null
|
|
|
|
|
+ if (periodKey === 'quarterly') return plan.originalQuarterly || null
|
|
|
|
|
+ if (periodKey === 'yearly') return plan.originalYearly || null
|
|
|
|
|
+ return null
|
|
|
},
|
|
},
|
|
|
- doRenew: function() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- createOrder(self.selectedLevel, 'pay', this.selectedPeriod).then(function(res) {
|
|
|
|
|
- var data = res.data || {}
|
|
|
|
|
- if (data.orderInfo && data.sign) {
|
|
|
|
|
- self.payInstallments(data)
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: '续费成功', icon: 'success' })
|
|
|
|
|
- self.loadData()
|
|
|
|
|
- }
|
|
|
|
|
- }).catch(function(e) {
|
|
|
|
|
- if (e.code === 46001) {
|
|
|
|
|
- uni.showToast({ title: '该商品暂未开放购买', icon: 'none' })
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: e.message || '续费失败', icon: 'none' })
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ showOriginalPrice: function(periodKey) {
|
|
|
|
|
+ var original = this.getOriginalPriceForPeriod(periodKey)
|
|
|
|
|
+ var current = this.getPriceForPeriod(periodKey)
|
|
|
|
|
+ if (!original || !current) return false
|
|
|
|
|
+ return original > current * 100
|
|
|
},
|
|
},
|
|
|
formatDate(date) {
|
|
formatDate(date) {
|
|
|
if (!date) return ''
|
|
if (!date) return ''
|
|
@@ -1051,4 +875,18 @@ export default {
|
|
|
color: #F97316;
|
|
color: #F97316;
|
|
|
margin-top: 8rpx;
|
|
margin-top: 8rpx;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 划线原价 ===== */
|
|
|
|
|
+.period-original {
|
|
|
|
|
+ font-size: 20rpx;
|
|
|
|
|
+ color: #94A3B8;
|
|
|
|
|
+ text-decoration: line-through;
|
|
|
|
|
+ margin-top: 2rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.price-original-line {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #94A3B8;
|
|
|
|
|
+ text-decoration: line-through;
|
|
|
|
|
+ margin-right: 12rpx;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|