|
|
@@ -0,0 +1,286 @@
|
|
|
+<template>
|
|
|
+ <view class="result-page">
|
|
|
+ <!-- 成功态 -->
|
|
|
+ <view class="result-body" v-if="status === 'success'">
|
|
|
+ <view class="result-icon success">
|
|
|
+ <text class="icon-text">✅</text>
|
|
|
+ </view>
|
|
|
+ <text class="result-title">开通成功</text>
|
|
|
+ <text class="result-sub">{{ levelName }} {{ levelCode }}</text>
|
|
|
+ <view class="info-card">
|
|
|
+ <view class="info-row">
|
|
|
+ <text class="info-label">有效期至</text>
|
|
|
+ <text class="info-value">{{ expireText }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="info-row" v-if="giftCoupons.length > 0">
|
|
|
+ <text class="info-label">开通赠券</text>
|
|
|
+ <text class="info-value gift">{{ giftCouponsText }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="btn-group">
|
|
|
+ <button class="btn-primary" @click="goBenefits">查看我的权益</button>
|
|
|
+ <button class="btn-secondary" @click="goHome">返回会员中心</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 失败态 -->
|
|
|
+ <view class="result-body" v-else>
|
|
|
+ <view class="result-icon fail">
|
|
|
+ <text class="icon-text">❌</text>
|
|
|
+ </view>
|
|
|
+ <text class="result-title">支付未完成</text>
|
|
|
+ <text class="result-sub">{{ failReason }}</text>
|
|
|
+ <view class="btn-group">
|
|
|
+ <button class="btn-primary" v-if="canContinue" @click="continuePay">继续支付</button>
|
|
|
+ <button class="btn-primary" v-else @click="retryPay">重新支付</button>
|
|
|
+ <button class="btn-secondary" @click="goUpgrade">返回套餐选择</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getMyMembership, getJoinCouponRules, nextOrder, requestVirtualPayment } from '../../utils/api.js'
|
|
|
+import { parseDate } from '../../utils/format.js'
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ orderNo: '',
|
|
|
+ status: 'success',
|
|
|
+ levelName: '会员',
|
|
|
+ levelCode: '',
|
|
|
+ expireText: '',
|
|
|
+ giftCoupons: [],
|
|
|
+ failReason: '支付未完成,请重试',
|
|
|
+ canContinue: false,
|
|
|
+ nextPayParams: null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ giftCouponsText: function() {
|
|
|
+ var self = this
|
|
|
+ return this.giftCoupons.map(function(r) {
|
|
|
+ return '「' + r.name + '」×' + (r.grantQuantity || 1)
|
|
|
+ }).join('、')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad: function(options) {
|
|
|
+ this.orderNo = options.orderNo || ''
|
|
|
+ this.status = options.status || 'success'
|
|
|
+ if (this.status === 'success') {
|
|
|
+ this.loadSuccess()
|
|
|
+ } else {
|
|
|
+ this.loadFail()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ loadSuccess: function() {
|
|
|
+ var self = this
|
|
|
+ // 轮询确认开通
|
|
|
+ var times = 0
|
|
|
+ var timer = setInterval(function() {
|
|
|
+ times++
|
|
|
+ getMyMembership().then(function(res) {
|
|
|
+ var m = res.data || {}
|
|
|
+ var mem = m.membership
|
|
|
+ if (mem && mem.isActive) {
|
|
|
+ clearInterval(timer)
|
|
|
+ self.levelCode = mem.levelCode || ''
|
|
|
+ self.levelName = mem.levelName || self.levelName
|
|
|
+ self.expireText = self.formatDate(mem.endDate)
|
|
|
+ self.loadGiftCoupons()
|
|
|
+ } else if (times >= 8) {
|
|
|
+ clearInterval(timer)
|
|
|
+ self.loadGiftCoupons()
|
|
|
+ }
|
|
|
+ }).catch(function() {
|
|
|
+ if (times >= 8) {
|
|
|
+ clearInterval(timer)
|
|
|
+ self.loadGiftCoupons()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }, 1500)
|
|
|
+ },
|
|
|
+ loadGiftCoupons: function() {
|
|
|
+ var self = this
|
|
|
+ getJoinCouponRules().then(function(res) {
|
|
|
+ var rules = res.data || []
|
|
|
+ self.giftCoupons = rules.filter(function(r) {
|
|
|
+ return r.grantLevelCode === self.levelCode
|
|
|
+ })
|
|
|
+ }).catch(function() {})
|
|
|
+ },
|
|
|
+ loadFail: function() {
|
|
|
+ var self = this
|
|
|
+ if (!this.orderNo) {
|
|
|
+ this.failReason = '订单信息缺失'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 尝试获取下一期支付参数(拆单未付清时可用)
|
|
|
+ nextOrder({ orderNo: this.orderNo }).then(function(res) {
|
|
|
+ var nd = res.data
|
|
|
+ if (nd && nd.done) {
|
|
|
+ self.failReason = '订单已全部支付,请稍后查看会员状态'
|
|
|
+ self.canContinue = false
|
|
|
+ } else if (nd && nd.orderInfo && nd.sign) {
|
|
|
+ self.canContinue = true
|
|
|
+ self.nextPayParams = nd
|
|
|
+ self.failReason = '第 ' + (nd.currentPeriod || 1) + ' 期尚未支付'
|
|
|
+ } else {
|
|
|
+ self.failReason = '支付未完成,请重试'
|
|
|
+ self.canContinue = false
|
|
|
+ }
|
|
|
+ }).catch(function() {
|
|
|
+ self.failReason = '支付未完成,请重试'
|
|
|
+ })
|
|
|
+ },
|
|
|
+ continuePay: function() {
|
|
|
+ var self = this
|
|
|
+ if (!this.nextPayParams) {
|
|
|
+ this.retryPay()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ requestVirtualPayment(this.nextPayParams, {
|
|
|
+ success: function() {
|
|
|
+ uni.redirectTo({ url: '/pages/membership/result?orderNo=' + self.orderNo + '&status=success' })
|
|
|
+ },
|
|
|
+ fail: function(err) {
|
|
|
+ var errCode = err && err.errCode
|
|
|
+ if (errCode === -2) {
|
|
|
+ uni.showToast({ title: '支付已取消', icon: 'none' })
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: '支付未完成', icon: 'none' })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ retryPay: function() {
|
|
|
+ uni.redirectTo({ url: '/pages/membership/upgrade' })
|
|
|
+ },
|
|
|
+ goBenefits: function() {
|
|
|
+ uni.redirectTo({ url: '/pages/membership/benefits' })
|
|
|
+ },
|
|
|
+ goHome: function() {
|
|
|
+ uni.switchTab({ url: '/pages/index/index' })
|
|
|
+ },
|
|
|
+ goUpgrade: function() {
|
|
|
+ uni.redirectTo({ url: '/pages/membership/upgrade' })
|
|
|
+ },
|
|
|
+ formatDate: function(date) {
|
|
|
+ if (!date) return ''
|
|
|
+ var d = parseDate(date)
|
|
|
+ if (!d) return ''
|
|
|
+ return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0')
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.result-page {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #FFF7ED;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 120rpx 30rpx 60rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+.result-body {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.result-icon {
|
|
|
+ width: 160rpx;
|
|
|
+ height: 160rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-bottom: 32rpx;
|
|
|
+}
|
|
|
+.result-icon.success {
|
|
|
+ background: #D1FAE5;
|
|
|
+}
|
|
|
+.result-icon.fail {
|
|
|
+ background: #FEE2E2;
|
|
|
+}
|
|
|
+.icon-text {
|
|
|
+ font-size: 80rpx;
|
|
|
+}
|
|
|
+.result-title {
|
|
|
+ font-size: 40rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #1E293B;
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 12rpx;
|
|
|
+}
|
|
|
+.result-sub {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #64748B;
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 48rpx;
|
|
|
+}
|
|
|
+.info-card {
|
|
|
+ width: 100%;
|
|
|
+ background: #FFFFFF;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ padding: 30rpx;
|
|
|
+ box-shadow: 0 4rpx 24rpx rgba(249, 115, 22, 0.08);
|
|
|
+ margin-bottom: 60rpx;
|
|
|
+}
|
|
|
+.info-row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 16rpx 0;
|
|
|
+}
|
|
|
+.info-label {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #64748B;
|
|
|
+}
|
|
|
+.info-value {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #1E293B;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+.info-value.gift {
|
|
|
+ color: #F97316;
|
|
|
+}
|
|
|
+.btn-group {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+.btn-primary {
|
|
|
+ width: 100%;
|
|
|
+ height: 96rpx;
|
|
|
+ line-height: 96rpx;
|
|
|
+ background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ border-radius: 48rpx;
|
|
|
+ border: none;
|
|
|
+ margin-bottom: 24rpx;
|
|
|
+}
|
|
|
+.btn-primary::after {
|
|
|
+ border: none;
|
|
|
+}
|
|
|
+.btn-secondary {
|
|
|
+ width: 100%;
|
|
|
+ height: 96rpx;
|
|
|
+ line-height: 96rpx;
|
|
|
+ background: #FFFFFF;
|
|
|
+ color: #F97316;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ border-radius: 48rpx;
|
|
|
+ border: 2rpx solid #FED7AA;
|
|
|
+}
|
|
|
+.btn-secondary::after {
|
|
|
+ border: none;
|
|
|
+}
|
|
|
+</style>
|