小说小程序前端代码仓库(小程序)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

530 lines
11 KiB

<template>
<!-- 豆豆充值页面 -->
<view class="recharge-page">
<!-- 顶部导航栏 -->
<navbar title="豆豆充值" leftClick @leftClick="$utils.navigateBack" />
<!-- 当前余额卡片 -->
<view class="card balance-card">
<view class="card-title">当前余额</view>
<view class="current-balance">
<text class="balance-amount">{{ userInfo.integerPrice || 0 }}</text>
<text class="balance-unit">豆豆</text>
</view>
</view>
<!-- 充值套餐选择 -->
<view class="card package-card">
<view class="card-title">选择充值套餐</view>
<view class="package-grid">
<view
v-for="(item, index) in rechargePackages"
:key="index"
:class="['package-item', { selected: selectedPackage === index }]"
@click="selectPackage(index)"
>
<view class="package-beans">{{ item.num }}豆豆</view>
<view class="package-price">¥{{ item.money }}</view>
<view v-if="item.giveNum" class="package-bonus">送{{ item.giveNum }}豆豆</view>
</view>
</view>
</view>
<!-- 自定义充值 -->
<!-- <view class="card custom-card">
<view class="card-title">自定义充值</view>
<view class="form-row">
<view class="form-label required">
<text class="star">*</text> 充值金额(元)
</view>
<input
class="form-input"
placeholder="请输入充值金额"
v-model="customAmount"
type="number"
:placeholder-style="'color:#bbb;'"
:style="customAmount ? 'color:#222;' : ''"
@input="onCustomAmountChange"
/>
</view>
<view class="divider"></view>
<view class="form-row">
<view class="form-label">可获得豆豆</view>
<view class="form-value">{{ customBeans }}豆豆</view>
</view>
</view> -->
<!-- 订单信息卡片 -->
<view class="card order-card" v-if="totalPrice > 0">
<view class="order-title">订单信息</view>
<view class="order-item">
<text class="order-label">充值金额:</text>
<text class="order-value">¥{{ totalPrice.toFixed(2) }}</text>
</view>
<view class="order-item">
<text class="order-label">获得豆豆:</text>
<text class="order-value">{{ totalBeans }}豆豆</text>
</view>
<view class="order-divider"></view>
<view class="order-item total-row">
<view class="order-total-label">合计:</view>
<view class="order-total">
<text class="order-total-highlight">¥{{ totalPrice.toFixed(2) }}</text>
</view>
</view>
</view>
<!-- 支付方式 -->
<!-- <view class="card payment-card">
<view class="card-title">支付方式</view>
<view class="payment-methods">
<view
v-for="(method, index) in paymentMethods"
:key="index"
:class="['payment-item', { selected: selectedPayment === index }]"
@click="selectPayment(index)"
>
<view class="payment-icon">
<uv-icon :name="method.icon" size="40rpx" color="#223a7a" />
</view>
<text class="payment-name">{{ method.name }}</text>
<view class="payment-radio">
<view v-if="selectedPayment === index" class="radio-checked"></view>
</view>
</view>
</view>
</view> -->
<!-- 提示信息 -->
<view class="tip-text">
请仔细核查并确认相关信息。因用户个人疏忽导致的充值错误,需由用户自行承担。一旦完成充值,概不退换。
</view>
<!-- 底部充值按钮 -->
<view class="footer-bar">
<button class="recharge-btn" @click="handleRecharge" :disabled="totalPrice <= 0">
立即充值 ¥{{ totalPrice.toFixed(2) }}
</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
selectedPackage: null,
customAmount: '',
selectedPayment: 0,
rechargePackages: [
// { beans: 100, price: 10, bonus: 0 },
// { beans: 300, price: 30, bonus: 20 },
// { beans: 680, price: 68, bonus: 50 },
// { beans: 1280, price: 128, bonus: 120 },
// { beans: 3280, price: 328, bonus: 320 },
// { beans: 6480, price: 648, bonus: 680 }
],
paymentMethods: [
{ name: '微信支付', icon: 'weixin-fill' },
]
}
},
computed: {
customBeans() {
const amount = parseFloat(this.customAmount)
return isNaN(amount) ? 0 : Math.floor(amount * 10)
},
totalPrice() {
if (this.selectedPackage !== null) {
return this.rechargePackages[this.selectedPackage].money
} else if (this.customAmount) {
return parseFloat(this.customAmount) || 0
}
return 0
},
totalBeans() {
if (this.selectedPackage !== null) {
const pkg = this.rechargePackages[this.selectedPackage]
return pkg.num + (pkg.giveNum || 0)
} else if (this.customAmount) {
return this.customBeans
}
return 0
}
},
onLoad(query) {
// 可以通过参数预设充值金额
if (query.amount) {
this.customAmount = query.amount
}
},
onShow() {
this.$store.commit('getUserInfo')
this.getPayPackageList()
},
methods: {
getPayPackageList(){
this.$api('getPayPackageList')
.then(res => {
if(res.code == 200){
this.rechargePackages = res.result
}
})
},
// 选择充值套餐
selectPackage(index) {
this.selectedPackage = index
this.customAmount = ''
},
// 选择支付方式
selectPayment(index) {
this.selectedPayment = index
},
// 自定义金额输入变化
onCustomAmountChange() {
if (this.customAmount) {
this.selectedPackage = null
}
},
// 处理充值
async handleRecharge() {
if (this.totalPrice <= 0) {
uni.showToast({
title: '请选择充值套餐或输入充值金额',
icon: 'none'
})
return
}
if (this.selectedPayment === null) {
uni.showToast({
title: '请选择支付方式',
icon: 'none'
})
return
}
try {
// 这里应该调用充值接口
const result = await this.$fetch('createPayPackageOrder', {
// amount: this.totalPrice,
// beans: this.totalBeans,
// paymentMethod: this.paymentMethods[this.selectedPayment].name
packageId : this.rechargePackages[this.selectedPackage].id
})
await uni.requestPaymentWxPay({result})
uni.showToast({
title: `充值成功,获得${this.totalBeans}豆豆`,
icon: 'success'
})
// 更新用户信息
this.$store.commit('getUserInfo')
setTimeout(() => {
uni.navigateBack()
}, 1500)
} catch (error) {
uni.showToast({
title: '充值失败,请重试',
icon: 'none'
})
}
}
}
}
</script>
<style scoped lang="scss">
.recharge-page {
min-height: 100vh;
background: #f8f8f8;
padding-bottom: 120rpx;
}
.card {
background: #fff;
border-radius: 20rpx;
margin: 24rpx 16rpx 0 16rpx;
padding: 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
}
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #222;
margin-bottom: 24rpx;
}
// 当前余额卡片
.balance-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
text-align: center;
.card-title {
color: #fff;
opacity: 0.9;
}
.current-balance {
display: flex;
align-items: baseline;
justify-content: center;
gap: 8rpx;
margin-top: 16rpx;
.balance-amount {
font-size: 56rpx;
font-weight: bold;
}
.balance-unit {
font-size: 28rpx;
opacity: 0.8;
}
}
}
// 充值套餐
.package-grid {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.package-item {
width: calc(50% - 8rpx);
background: #f8f9ff;
border: 2rpx solid #f0f0f0;
border-radius: 16rpx;
padding: 24rpx 16rpx;
text-align: center;
transition: all 0.2s;
position: relative;
box-sizing: border-box;
&.selected {
border-color: #223a7a;
background: rgba(34, 58, 122, 0.05);
}
.package-beans {
font-size: 32rpx;
font-weight: bold;
color: #222;
margin-bottom: 8rpx;
}
.package-price {
font-size: 28rpx;
color: #223a7a;
font-weight: 500;
margin-bottom: 4rpx;
}
.package-bonus {
font-size: 20rpx;
color: #e94f7a;
background: rgba(233, 79, 122, 0.1);
padding: 2rpx 8rpx;
border-radius: 8rpx;
display: inline-block;
}
}
// 表单样式
.form-row {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 24rpx;
}
.form-label {
color: #888;
font-size: 28rpx;
margin-bottom: 12rpx;
font-weight: 400;
&.required {
color: #222;
font-weight: 500;
display: flex;
align-items: center;
}
}
.star {
color: #e94f7a;
margin-right: 4rpx;
font-size: 28rpx;
}
.form-value {
color: #222;
font-size: 28rpx;
font-weight: 600;
}
.form-input {
width: 100%;
border: 1rpx solid #e5e5e5;
border-radius: 12rpx;
font-size: 28rpx;
padding: 16rpx;
background: #fafafa;
color: #222;
box-sizing: border-box;
}
.divider {
height: 1rpx;
background: #f2f2f2;
margin: 16rpx 0;
width: 100%;
}
// 订单信息
.order-card {
.order-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
.order-label {
font-size: 28rpx;
color: #666;
}
.order-value {
font-size: 28rpx;
color: #222;
font-weight: 500;
}
&.total-row {
margin-bottom: 0;
margin-top: 16rpx;
.order-total-label {
font-size: 32rpx;
color: #222;
font-weight: 600;
}
.order-total-highlight {
font-size: 32rpx;
color: #223a7a;
font-weight: bold;
}
}
}
.order-divider {
height: 1rpx;
background: #f2f2f2;
margin: 16rpx 0;
}
}
// 支付方式
.payment-methods {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.payment-item {
display: flex;
align-items: center;
padding: 20rpx;
border: 2rpx solid #f0f0f0;
border-radius: 12rpx;
transition: all 0.2s;
&.selected {
border-color: #223a7a;
background: rgba(34, 58, 122, 0.05);
}
.payment-icon {
width: 48rpx;
height: 48rpx;
margin-right: 16rpx;
image {
width: 100%;
height: 100%;
}
}
.payment-name {
flex: 1;
font-size: 28rpx;
color: #222;
}
.payment-radio {
width: 32rpx;
height: 32rpx;
border: 2rpx solid #ddd;
border-radius: 50%;
position: relative;
.radio-checked {
width: 16rpx;
height: 16rpx;
background: #223a7a;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
.tip-text {
color: #bbb;
font-size: 22rpx;
margin: 32rpx 32rpx 0 32rpx;
line-height: 1.6;
}
.footer-bar {
// position: fixed;
// left: 0;
// right: 0;
// bottom: 90rpx;
background: #fff;
padding: 24rpx 32rpx 32rpx 32rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
z-index: 10;
}
.recharge-btn {
width: 100%;
background: #223a7a;
color: #fff;
font-size: 32rpx;
border-radius: 32rpx;
height: 88rpx;
line-height: 88rpx;
border: none;
font-weight: 500;
&[disabled] {
background: #ccc;
color: #999;
}
}
</style>