Files
xiuhuwangqiu/bundle/combo/details.vue
wangxiaowei f8ac363bcd 优化页面
2026-04-12 15:04:01 +08:00

950 lines
28 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page-container">
<!-- Top Background & Card -->
<view class="top-section">
<view style="width: 100%; height: 100%; position: relative;">
<image class="bg-img" src="https://xh.stnav.com/uploads/sport/card-bg.png"></image>
<view style="position: absolute; left: 50%; transform: translateX(-50%); bottom: 0;">
<image :src="info.img" style="width: 690rpx; height: 290rpx;"></image>
<view class="info-name" style="position: absolute; top: 40rpx; left: 40rpx;">{{ info.eg_name }}
</view>
<view class="info-name" style="position: absolute; top: 100rpx; left: 40rpx;">{{ info.name }}</view>
<view v-if="info.order && info.order.end_time && id == info.order.group_id" style="position: absolute; bottom: 68rpx; right: 40rpx; display: flex; align-items: center;">
<image class="diamond" src="https://xh.stnav.com/uploads/sport/icon_zs.png" mode="aspectFit">
</image>
<text style="color: #834B08;font-weight: bold;">有效期{{ info.order.end_time }}到期</text>
</view>
</view>
</view>
<view class="nav-header" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav-content" :style="{ height: navHeight + 'px' }">
<image class="back-icon" src="@/static/icon/back3.png" @click="goBack" mode="aspectFit"></image>
<text class="nav-title">我的会员</text>
</view>
</view>
</view>
<!-- Rights Content -->
<view class="content-section">
<view class="section-title">
<image src="https://xh.stnav.com/uploads/sport/hyqy.png" mode="heightFix" style="height: 40rpx;">
</image>
</view>
<view class="rights-list">
<view class="right-item">
<view class="icon-circle">
<image src="https://xh.stnav.com/uploads/sport/icon_vip.png"
style="width: 80rpx; height: 80rpx;"></image>
</view>
<view class="right-info">
<view class="right-name">VIP优惠</view>
<view class="right-desc">每次打球立享折扣运动更划算</view>
</view>
</view>
<view class="right-item">
<view class="icon-circle">
<image src="https://xh.stnav.com/uploads/sport/icon_money.png"
style="width: 80rpx; height: 80rpx;"></image>
</view>
<view class="right-info">
<view class="right-name">入场不限次</view>
<view class="right-desc">凭有效凭证不限次进出场地自由通行</view>
</view>
</view>
<view class="right-item">
<view class="icon-circle">
<image src="https://xh.stnav.com/uploads/sport/icon_service.png"
style="width: 80rpx; height: 80rpx;"></image>
</view>
<view class="right-info">
<view class="right-name">专属客服</view>
<view class="right-desc">任何问题将由专属客服优先跟进处理</view>
</view>
</view>
</view>
<!-- Rules Box -->
<view class="rules-box">
<view class="rules-tag">
<image src="https://xh.stnav.com/uploads/sport/jshy.png" style="width: 100rpx; height: 80rpx;">
</image>
</view>
<view class="rules-title">权益说明</view>
<view class="rules-subtitle">更多会员专属权益与服务内容</view>
<view class="rules-list">
<rich-text :nodes="info.content"></rich-text>
</view>
</view>
</view>
<!-- Bottom Button -->
<view class="bottom-bar">
<!-- 两个按钮并排显示的情况 -->
<view class="btn-group" v-if="result && result.status == 1 && id == result.group_id && info.order && info.order.id">
<view class="btn-submit btn-half" @click="handleSubmit">立即续费</view>
<view class="btn-submit btn-half btn-secondary" @click="hanldeTakePhoto">人脸信息</view>
</view>
<!-- 单个按钮显示的情况 -->
<template v-else>
<view class="btn-submit btn-disabled" v-if="result && result.status == 0 && id == result.group_id">审核中</view>
<view class="btn-submit" @click="handleSubmit" v-else-if="result && result.status == 2 && id == result.group_id">重新提交</view>
<view class="btn-submit" @click="handleSubmit" v-else>立即开通</view>
</template>
</view>
<!-- 完善信息提示弹窗 -->
<view class="modal-container" v-if="showInfoModal">
<view class="modal-mask" @click="closeInfoModal"></view>
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">温馨提示</text>
<view class="close-icon" @click="closeInfoModal">×</view>
</view>
<view class="modal-desc">检测到您未填写相关信息为不影响使用请尽快完善</view>
<view class="modal-btn" @click="goToFillInfo">立即去完善</view>
</view>
</view>
<!-- 会员购买弹窗 -->
<view class="buy-modal-container" v-if="showBuyModal">
<view class="buy-modal-mask" @click="closeBuyModal"></view>
<view class="buy-modal-content">
<view class="buy-modal-title">会员购买</view>
<view class="plan-list">
<view class="plan-item" :class="{ active: selectedPlan === 1 }" @click="selectPlan(1)">
<view class="plan-name">月卡</view>
<view class="plan-price">
<text style="font-size: 24rpx; margin-right: 4rpx;"></text>
<text>{{ info.month_price }}</text>
</view>
<view class="plan-desc" v-if="info.m_price && info.m_price > 0">指导价{{ info.m_price }}/</view>
<view class="check-mark"></view>
</view>
<view class="plan-item" :class="{ active: selectedPlan === 2 }" @click="selectPlan(2)">
<view class="plan-name">季卡</view>
<view class="plan-price">
<text style="font-size: 24rpx; margin-right: 4rpx;"></text>
<text>{{ info.seasonal_price }}</text>
</view>
<view class="plan-desc" v-if="info.s_price && info.s_price > 0">指导价{{ info.s_price }}/</view>
<view class="check-mark"></view>
</view>
</view>
<view class="buy-modal-tips" v-if="!isRenewal">
开通成功之后需要录入人脸信息
</view>
<view class="buy-modal-btn" @click="confirmBuy">{{ isRenewal ? '立即续费' : '立即开通' }}</view>
</view>
</view>
<!-- 购买成功弹窗 -->
<view class="success-modal-container" v-if="showSuccessModal">
<view class="success-modal-mask" @click="closeSuccessModal"></view>
<view class="success-modal-content">
<view class="success-img-wrapper">
<image class="success-img" src="https://xh.stnav.com/uploads/sport/buy-success.png" mode="widthFix">
</image>
<view class="success-confirm-btn" @click="closeSuccessModal">确定</view>
</view>
<image class="success-close" src="https://xh.stnav.com/uploads/sport/icon_close2.png" mode="aspectFit"
@click="closeSuccessModal"></image>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
id: 0,
statusBarHeight: 20,
navHeight: 44,
comboType: 'adult', // 套餐类型adult(成人卡) youth(青年卡) family(亲子卡)
showInfoModal: false, // 完善信息提示弹窗
showBuyModal: false, // 会员购买弹窗
showSuccessModal: false, // 购买成功弹窗
selectedPlan: 1, // 选择的套餐 1-月卡 2-季卡
info: {
order: {
id: 0,
group_id: 0, // 套餐ID
end_time: '', // 会员到期时间
},
}, // 套餐详情数据
result: null, // 审核数据
isRenewal: false, // 是否为续费
};
},
created() {
let sysInfo = uni.getSystemInfoSync();
this.statusBarHeight = sysInfo.statusBarHeight;
// #ifdef MP-WEIXIN
let menuButtonInfo = uni.getMenuButtonBoundingClientRect();
this.navHeight = menuButtonInfo.height + (menuButtonInfo.top - this.statusBarHeight) * 2;
// #endif
},
onLoad(args) {
this.comboType = args.type || 'adult'
this.id = args.id
this.handleGetDetails();
this.handleInit();
},
methods: {
goBack() {
uni.navigateBack();
},
handleInit() {
let self = this;
self._post(
'ground.group/getGroupData',
{
group_id: self.id
},
result => {
self.result = result.data
console.log("🚀 ~ self.result:", self.result)
},
false,
() => {
}
);
},
handleGetDetails() {
let self = this;
self._post(
'ground.group/getGroupDetails',
{ id: self.id },
result => {
self.info = result.data;
console.log("🚀 ~ self.info:", self.info)
},
false,
() => {
}
);
},
handleSubmit() {
let self = this;
if (self.info.order && self.info.order.id) {
self.isRenewal = true;
} else {
self.isRenewal = false;
}
if (!self.result) {
// 没有填写过信息,弹出完善信息提示弹窗
self.showInfoModal = true;
return false;
}
const birthDate = new Date(self.result.both);
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
if (self.result && self.result.group_id == 1 && age >= 18) {
// 没有填写过信息,弹出完善信息提示弹窗
self.showInfoModal = true;
return false;
}
if (self.result && (self.result.group_id == 3 || self.result.group_id == 4) && age >= 18) {
// 没有填写过信息,弹出完善信息提示弹窗
self.showInfoModal = true;
return false;
}
if (self.result.status == 0) {
setTimeout(() => {
uni.showToast({ title: '信息审核中,请耐心等待', icon: 'none' });
}, 100);
return false;
}
if (self.result.status == 2) {
setTimeout(() => {
uni.showToast({ title: '审核失败,请重新提交', icon: 'none' });
}, 100);
// 没有填写过信息,弹出完善信息提示弹窗
self.showInfoModal = true;
return false;
}
if (self.result.status == 1) {
// 已经审核通过,弹出开通会员弹窗
self.showBuyModal = true;
return false;
}
},
closeInfoModal() {
this.showInfoModal = false;
},
goToFillInfo() {
let self = this;
self.showInfoModal = false;
uni.navigateTo({
url: '/bundle/combo/info?id=' + self.id,
events:{
data: (e) => {
if (e.notice == 'success') {
self.handleInit()
}
}
}
});
},
closeBuyModal() {
this.showBuyModal = false;
},
selectPlan(index) {
this.selectedPlan = index;
},
confirmBuy() {
let self = this
self.showBuyModal = false;
self._post(
'order.group/submitGroupOrder',
{
group_id: self.id,
group_type: self.selectedPlan, // 1-月卡 2-季卡
order_amount: self.selectedPlan === 1 ? self.info.month_price : self.info.seasonal_price
},
result => {
if (result.code == 1) {
uni.showLoading({
title: '支付中'
});
const payId = result.data.lists.id;
self._post(
'order.group/Pay', {
order_id: payId,
},
function (pay) {
console.log("🚀 ~ pay:", pay)
uni.requestPayment({
provider: 'wxpay',
timeStamp: pay.data.payment.timeStamp,
nonceStr: pay.data.payment.nonceStr,
package: 'prepay_id=' + pay.data.payment.prepay_id,
signType: 'MD5',
paySign: pay.data.payment.paySign,
success: res => {
uni.hideLoading();
setTimeout(() => {
self.handleGetDetails();
self.showSuccessModal = true;
}, 1000);
},
fail: res => {
setTimeout(() => {
uni.showToast({
title: '支付失败',
icon: 'none'
});
}, 200);
},
});
}
);
} else {
uni.showToast({ title: result.msg || '订单创建失败', icon: 'none' });
}
},
false,
() => {
}
)
},
closeSuccessModal() {
this.showSuccessModal = false;
if (this.isRenewal) {
this.handleGetDetails();
return;
}
let orderId = this.info.order ? this.info.order.id : '';
uni.navigateTo({
url: '/bundle/combo/face-list?id=' + this.id + '&order_id=' + orderId
});
},
hanldeTakePhoto() {
if (this.result.status == 0) {
setTimeout(() => {
uni.showToast({ title: '信息审核中,请耐心等待', icon: 'none' });
}, 100);
return false;
}
let orderId = this.info.order ? this.info.order.id : '';
uni.navigateTo({
url: '/bundle/combo/face-list?id=' + this.id + '&order_id=' + orderId
});
}
}
}
</script>
<style lang="scss">
page {
background-color: #fff;
}
.page-container {
padding-bottom: 200rpx;
}
.top-section {
position: relative;
width: 100%;
height: 460rpx;
.bg-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
.card-text-content {
position: absolute;
left: 100rpx;
right: 80rpx;
z-index: 1;
.card-title {
.en {
font-size: 32rpx;
color: #D19A57;
font-weight: 500;
margin-bottom: 8rpx;
}
.zh {
font-size: 32rpx;
color: #D19A57;
font-weight: bold;
}
}
.card-title-parten {
.en {
font-size: 32rpx;
color: #834B08;
font-weight: 500;
margin-bottom: 8rpx;
}
.zh {
font-size: 32rpx;
color: #834B08;
font-weight: bold;
}
}
.card-date {
font-weight: 400;
margin-top: 40rpx;
text-align: right;
font-size: 26rpx;
color: #A47539;
display: flex;
justify-content: flex-end;
align-items: center;
}
}
.nav-header {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
.nav-content {
display: flex;
align-items: center;
justify-content: center;
position: relative;
color: #fff;
font-size: 34rpx;
}
.back-icon {
position: absolute;
left: 30rpx;
width: 44rpx;
height: 44rpx;
}
}
.card-box {
position: relative;
z-index: 1;
padding: 40rpx 30rpx 0;
.card-img {
width: 100%;
border-radius: 20rpx;
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.1);
}
}
}
.content-section {
position: relative;
z-index: 2;
background-color: #fff;
border-radius: 40rpx 40rpx 0 0;
padding: 10rpx 40rpx;
.section-title {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 60rpx;
.line {
width: 60rpx;
height: 2rpx;
background-color: #D4B481;
margin: 0 20rpx;
}
.title-text {
font-size: 32rpx;
color: #A37F4B;
font-weight: bold;
}
}
.rights-list {
margin-bottom: 60rpx;
.right-item {
display: flex;
align-items: flex-start;
margin-bottom: 40rpx;
.icon-circle {
width: 80rpx;
height: 80rpx;
background-color: #E8C18E;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: bold;
font-size: 28rpx;
margin-right: 30rpx;
flex-shrink: 0;
}
.right-info {
.right-name {
font-size: 26rpx;
line-height: 36rpx;
color: #D19A57;
font-weight: bold;
margin-bottom: 6rpx;
}
.right-desc {
font-size: 24rpx;
color: #D19A57;
font-weight: 400;
line-height: 34rpx;
}
}
}
}
.rules-box {
border: 2rpx solid #E8C18E;
border-radius: 20rpx;
padding: 24rpx 30rpx;
position: relative;
.rules-tag {
position: absolute;
top: 0;
right: 52rpx;
}
.rules-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 16rpx;
}
.rules-subtitle {
font-size: 24rpx;
color: #999;
margin-bottom: 30rpx;
}
.rule-item {
font-size: 26rpx;
color: #666;
margin-bottom: 16rpx;
line-height: 1.5;
}
}
}
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 99;
background-color: #fff;
padding: 20rpx 40rpx 60rpx;
box-sizing: border-box;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
.btn-group {
display: flex;
align-items: center;
justify-content: space-between;
gap: 30rpx;
}
.btn-submit {
flex: 1;
background: linear-gradient(90deg, #F6E1B0 0%, #EDC66E 100%);
color: #333;
font-size: 32rpx;
font-weight: bold;
height: 90rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 45rpx;
box-shadow: 0 6rpx 12rpx rgba(237, 198, 110, 0.3);
transition: all 0.2s;
}
.btn-submit:active {
transform: scale(0.98);
box-shadow: 0 2rpx 6rpx rgba(237, 198, 110, 0.2);
}
.btn-disabled {
background: #F5F5F5;
color: #999;
box-shadow: none;
}
.btn-secondary {
background: #FDF8EE;
border: 2rpx solid #EDC66E;
color: #834B08;
box-shadow: none;
}
}
/* 完善信息提示弹窗 */
.modal-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
}
.modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
.modal-content {
position: relative;
width: 560rpx;
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 40rpx;
display: flex;
flex-direction: column;
align-items: center;
z-index: 101;
.modal-header {
width: 100%;
position: relative;
display: flex;
justify-content: center;
margin-bottom: 40rpx;
.modal-title {
font-size: 32rpx;
color: #333333;
font-weight: 500;
}
.close-icon {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
font-size: 40rpx;
color: #666666;
line-height: 1;
}
}
.modal-desc {
font-size: 28rpx;
color: #666666;
line-height: 1.6;
text-align: center;
margin-bottom: 50rpx;
padding: 0 10rpx;
}
.modal-btn {
width: 100%;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background-color: #3B5B9B;
color: #FFFFFF;
font-size: 30rpx;
border-radius: 8rpx;
}
}
/* 会员购买弹窗样式 */
.buy-modal-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
display: flex;
align-items: flex-end;
justify-content: center;
}
.buy-modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
.buy-modal-content {
position: relative;
width: 100%;
box-sizing: border-box;
background-color: #FFFFFF;
border-radius: 20rpx 20rpx 0 0;
padding: 50rpx 40rpx;
padding-bottom: calc(50rpx + env(safe-area-inset-bottom));
z-index: 101;
.buy-modal-title {
text-align: center;
font-size: 36rpx;
font-weight: 500;
color: #333;
margin-bottom: 50rpx;
}
.plan-list {
display: flex;
justify-content: space-between;
margin-bottom: 40rpx;
.plan-item {
width: 48%;
border: 2rpx solid #EEEEEE;
border-radius: 12rpx;
padding: 38rpx 0;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
overflow: hidden;
transition: all 0.3s;
&.active {
border-color: #E8C18E;
background-color: #FFFDF8;
.check-mark {
display: block;
}
}
.plan-name {
font-size: 30rpx;
color: #333;
margin-bottom: 16rpx;
}
.plan-price {
font-size: 40rpx;
color: #E53935;
font-weight: bold;
margin-bottom: 16rpx;
display: flex;
align-items: baseline;
}
.plan-desc {
font-size: 22rpx;
color: #999;
}
.check-mark {
display: none;
position: absolute;
right: -2rpx;
bottom: -2rpx;
width: 44rpx;
height: 40rpx;
background-color: #D4B481;
border-radius: 20rpx 0 0 0;
&::after {
content: '';
position: absolute;
left: 18rpx;
top: 10rpx;
width: 8rpx;
height: 14rpx;
border-right: 3rpx solid #fff;
border-bottom: 3rpx solid #fff;
transform: rotate(45deg);
}
}
}
}
.buy-modal-tips {
font-size: 24rpx;
color: #666;
line-height: 1.6;
margin-bottom: 50rpx;
}
.buy-modal-btn {
background: linear-gradient(90deg, #F6E1B0 0%, #EDC66E 100%);
color: #333;
font-size: 32rpx;
font-weight: bold;
height: 90rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 45rpx;
}
}
/* 购买成功弹窗 */
.success-modal-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 102;
display: flex;
align-items: center;
justify-content: center;
}
.success-modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
}
.success-modal-content {
position: relative;
width: 580rpx;
display: flex;
flex-direction: column;
align-items: center;
z-index: 103;
.success-img-wrapper {
position: relative;
width: 100%;
.success-img {
width: 100%;
display: block;
}
.success-confirm-btn {
position: absolute;
bottom: 60rpx;
left: 50%;
transform: translateX(-50%);
width: 396rpx;
height: 88rpx;
background: linear-gradient(90deg, #F6E1B0 0%, #EDC66E 100%);
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: bold;
color: #5C3D10;
}
}
.success-close {
width: 60rpx;
height: 60rpx;
margin-top: 40rpx;
}
}
.info-name {
font-weight: bold;
font-size: 32rpx;
color: #834B08;
line-height: 44rpx;
}
.diamond {
width: 26rpx;
height: 20rpx;
margin-right: 6rpx;
}
</style>