361 lines
7.0 KiB
Vue
361 lines
7.0 KiB
Vue
|
<template>
|
||
|
<view class="success-page">
|
||
|
<!-- 状态栏占位 -->
|
||
|
<view class="status-bar"></view>
|
||
|
|
||
|
<!-- 成功状态区域 -->
|
||
|
<view class="success-section">
|
||
|
<view class="success-icon-wrapper">
|
||
|
<view class="success-icon">
|
||
|
<text class="success-checkmark">✓</text>
|
||
|
</view>
|
||
|
<view class="success-rings">
|
||
|
<view class="ring ring1"></view>
|
||
|
<view class="ring ring2"></view>
|
||
|
<view class="ring ring3"></view>
|
||
|
</view>
|
||
|
</view>
|
||
|
|
||
|
<view class="success-title">{{ paySuccessText }}</view>
|
||
|
<view v-if="isRecharge === undefined" class="success-subtitle"
|
||
|
>您的订单已支付完成</view
|
||
|
>
|
||
|
</view>
|
||
|
|
||
|
<!-- 操作按钮区域 -->
|
||
|
<view class="action-section">
|
||
|
<view class="button-group">
|
||
|
<button
|
||
|
v-if="isRecharge === undefined"
|
||
|
class="btn btn-secondary"
|
||
|
@click="goToOrderList"
|
||
|
>
|
||
|
查看订单
|
||
|
</button>
|
||
|
<button class="btn btn-primary" @click="goToHome">返回首页</button>
|
||
|
</view>
|
||
|
</view>
|
||
|
|
||
|
<successDialog @successClose="successClose" ref="successDialog" />
|
||
|
</view>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import { mapGetters } from 'vuex'
|
||
|
import { payStatus, registerInfo } from '@/config/pay.js'
|
||
|
import successDialog from '@/components/successDialog.vue'
|
||
|
|
||
|
let paySetTimeoutFlag = null
|
||
|
let getRegisterInfoTimeoutFlag = null
|
||
|
export default {
|
||
|
name: 'PaySuccess',
|
||
|
components: {
|
||
|
successDialog,
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
orderCode: '',
|
||
|
specialArea: null,
|
||
|
isRecharge: undefined,
|
||
|
}
|
||
|
},
|
||
|
computed: {
|
||
|
...mapGetters(['userInfo']),
|
||
|
paySuccessText() {
|
||
|
if (this.isRecharge === undefined) {
|
||
|
return ''
|
||
|
}
|
||
|
if (this.isRecharge === true) {
|
||
|
return '充值成功'
|
||
|
}
|
||
|
return '支付成功'
|
||
|
},
|
||
|
},
|
||
|
onLoad(options) {
|
||
|
// 获取传递的参数
|
||
|
const extParam = JSON.parse(atob(options.extParam || '{}'))
|
||
|
this.specialArea = extParam.specialArea
|
||
|
this.isRecharge = extParam.source
|
||
|
this.orderCode = extParam.orderCode || ''
|
||
|
if (this.orderCode) {
|
||
|
setTimeout(() => {
|
||
|
this.pollingPayStatus(this.orderCode)
|
||
|
}, 500)
|
||
|
}
|
||
|
// 设置导航栏
|
||
|
uni.setNavigationBarTitle({
|
||
|
title: '支付成功',
|
||
|
})
|
||
|
},
|
||
|
onUnload() {
|
||
|
clearTimeout(paySetTimeoutFlag)
|
||
|
clearTimeout(getRegisterInfoTimeoutFlag)
|
||
|
},
|
||
|
methods: {
|
||
|
getRegisterInfo() {
|
||
|
registerInfo(this.orderCode).then(res => {
|
||
|
if (res.data) {
|
||
|
uni.hideLoading()
|
||
|
this.$refs.successDialog.showSuccess(res.data)
|
||
|
} else {
|
||
|
getRegisterInfoTimeoutFlag = setTimeout(() => {
|
||
|
this.getRegisterInfo()
|
||
|
}, 3000)
|
||
|
}
|
||
|
})
|
||
|
},
|
||
|
pollingPayStatus(orderCode) {
|
||
|
payStatus({ businessCode: orderCode }).then(res => {
|
||
|
if (res.data == 1) {
|
||
|
clearTimeout(paySetTimeoutFlag)
|
||
|
if ([1, 7, 24].includes(Number(this.specialArea))) {
|
||
|
uni.showLoading({
|
||
|
title: '注册信息加载中...',
|
||
|
mask: false,
|
||
|
})
|
||
|
setTimeout(() => {
|
||
|
this.getRegisterInfo()
|
||
|
}, 2000)
|
||
|
}
|
||
|
} else {
|
||
|
paySetTimeoutFlag = setTimeout(() => {
|
||
|
this.pollingPayStatus(orderCode)
|
||
|
}, 1000)
|
||
|
}
|
||
|
})
|
||
|
},
|
||
|
|
||
|
// 跳转到订单列表
|
||
|
goToOrderList() {
|
||
|
uni.redirectTo({
|
||
|
url: '/pages/mine/order/index',
|
||
|
})
|
||
|
},
|
||
|
successClose() {
|
||
|
uni.redirectTo({
|
||
|
url: '/pages/mine/order/index',
|
||
|
})
|
||
|
},
|
||
|
|
||
|
// 返回首页
|
||
|
goToHome() {
|
||
|
uni.switchTab({
|
||
|
url: '/pages/index/index',
|
||
|
})
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
.success-page {
|
||
|
min-height: 100vh;
|
||
|
background: linear-gradient(135deg, #f8fafc 0%, #e3f2fd 100%);
|
||
|
position: relative;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
}
|
||
|
|
||
|
.status-bar {
|
||
|
height: var(--status-bar-height);
|
||
|
background: transparent;
|
||
|
}
|
||
|
|
||
|
.success-section {
|
||
|
flex: 1;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
align-items: center;
|
||
|
justify-content: center;
|
||
|
padding: 60rpx 40rpx 40rpx;
|
||
|
position: relative;
|
||
|
}
|
||
|
|
||
|
.success-icon-wrapper {
|
||
|
position: relative;
|
||
|
margin-bottom: 40rpx;
|
||
|
}
|
||
|
|
||
|
.success-icon {
|
||
|
width: 120rpx;
|
||
|
height: 120rpx;
|
||
|
background: #005bac;
|
||
|
border-radius: 50%;
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
justify-content: center;
|
||
|
position: relative;
|
||
|
z-index: 2;
|
||
|
box-shadow: 0 8rpx 24rpx rgba(0, 91, 172, 0.3);
|
||
|
animation: successBounce 0.6s ease-out;
|
||
|
}
|
||
|
|
||
|
.success-checkmark {
|
||
|
color: #ffffff;
|
||
|
font-size: 60rpx;
|
||
|
font-weight: bold;
|
||
|
line-height: 1;
|
||
|
}
|
||
|
|
||
|
.success-rings {
|
||
|
position: absolute;
|
||
|
top: 50%;
|
||
|
left: 50%;
|
||
|
transform: translate(-50%, -50%);
|
||
|
z-index: 1;
|
||
|
}
|
||
|
|
||
|
.ring {
|
||
|
position: absolute;
|
||
|
border: 2rpx solid #005bac;
|
||
|
border-radius: 50%;
|
||
|
opacity: 0;
|
||
|
top: 50%;
|
||
|
left: 50%;
|
||
|
transform: translate(-50%, -50%);
|
||
|
}
|
||
|
|
||
|
.ring1 {
|
||
|
width: 140rpx;
|
||
|
height: 140rpx;
|
||
|
animation: ripple 1.5s ease-out 0.2s infinite;
|
||
|
}
|
||
|
|
||
|
.ring2 {
|
||
|
width: 180rpx;
|
||
|
height: 180rpx;
|
||
|
animation: ripple 1.5s ease-out 0.6s infinite;
|
||
|
}
|
||
|
|
||
|
.ring3 {
|
||
|
width: 220rpx;
|
||
|
height: 220rpx;
|
||
|
animation: ripple 1.5s ease-out 1s infinite;
|
||
|
}
|
||
|
|
||
|
.success-title {
|
||
|
font-size: 48rpx;
|
||
|
font-weight: 600;
|
||
|
color: #1a1a1a;
|
||
|
margin-bottom: 16rpx;
|
||
|
text-align: center;
|
||
|
}
|
||
|
|
||
|
.success-subtitle {
|
||
|
font-size: 28rpx;
|
||
|
color: #666666;
|
||
|
text-align: center;
|
||
|
line-height: 1.4;
|
||
|
}
|
||
|
|
||
|
.action-section {
|
||
|
padding: 32rpx;
|
||
|
}
|
||
|
|
||
|
.button-group {
|
||
|
display: flex;
|
||
|
gap: 24rpx;
|
||
|
}
|
||
|
|
||
|
.btn {
|
||
|
flex: 1;
|
||
|
height: 88rpx;
|
||
|
border-radius: 44rpx;
|
||
|
font-size: 32rpx;
|
||
|
font-weight: 500;
|
||
|
border: none;
|
||
|
transition: all 0.3s ease;
|
||
|
position: relative;
|
||
|
overflow: hidden;
|
||
|
|
||
|
&::after {
|
||
|
border: none;
|
||
|
}
|
||
|
|
||
|
&.btn-secondary {
|
||
|
background: #ffffff;
|
||
|
color: #005bac;
|
||
|
border: 2rpx solid #005bac;
|
||
|
|
||
|
&:active {
|
||
|
background: #f8fafc;
|
||
|
transform: scale(0.98);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.btn-primary {
|
||
|
background: linear-gradient(135deg, #005bac 0%, #0066cc 100%);
|
||
|
color: #ffffff;
|
||
|
box-shadow: 0 4rpx 16rpx rgba(0, 91, 172, 0.3);
|
||
|
|
||
|
&:active {
|
||
|
background: linear-gradient(135deg, #004691 0%, #0052a3 100%);
|
||
|
transform: scale(0.98);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 动画效果
|
||
|
@keyframes successBounce {
|
||
|
0% {
|
||
|
transform: scale(0);
|
||
|
opacity: 0;
|
||
|
}
|
||
|
50% {
|
||
|
transform: scale(1.2);
|
||
|
opacity: 1;
|
||
|
}
|
||
|
100% {
|
||
|
transform: scale(1);
|
||
|
opacity: 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@keyframes ripple {
|
||
|
0% {
|
||
|
opacity: 0.6;
|
||
|
transform: translate(-50%, -50%) scale(0.1);
|
||
|
}
|
||
|
100% {
|
||
|
opacity: 0;
|
||
|
transform: translate(-50%, -50%) scale(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 暗黑模式适配
|
||
|
@media (prefers-color-scheme: dark) {
|
||
|
.success-page {
|
||
|
background: linear-gradient(135deg, #1a1a1a 0%, #2d3748 100%);
|
||
|
}
|
||
|
|
||
|
.success-title {
|
||
|
color: #ffffff;
|
||
|
}
|
||
|
|
||
|
.success-subtitle {
|
||
|
color: #a0aec0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 适配不同屏幕尺寸
|
||
|
@media screen and (max-width: 375px) {
|
||
|
.success-icon {
|
||
|
width: 100rpx;
|
||
|
height: 100rpx;
|
||
|
}
|
||
|
|
||
|
.success-checkmark {
|
||
|
font-size: 50rpx;
|
||
|
}
|
||
|
|
||
|
.success-title {
|
||
|
font-size: 42rpx;
|
||
|
}
|
||
|
|
||
|
.button-group {
|
||
|
flex-direction: column;
|
||
|
gap: 16rpx;
|
||
|
}
|
||
|
}
|
||
|
</style>
|