2
0

feat:增加余额支付功能

This commit is contained in:
zhongzm
2025-02-13 20:35:43 +08:00
parent 29f58edef6
commit 93579c7dde
6 changed files with 212 additions and 40 deletions

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
import { useI18n } from 'vue-i18n';
import { AlipayOutlined, WechatOutlined } from '@ant-design/icons-vue';
import { AlipayOutlined, WechatOutlined, WalletOutlined } from '@ant-design/icons-vue';
const { t } = useI18n();
@@ -12,6 +12,9 @@ interface Props {
orderType: number; // 0: 购买套餐, 1: 余额充值
orderAmount: number;
};
enableBalancePay?: boolean;
userBalance?: number;
loading?: boolean;
}
const props = defineProps<Props>();
@@ -22,11 +25,14 @@ const orderTypeMap = {
1: t('page.order.balanceRecharge')
} as const;
const handleConfirm = (paymentMethod: 'alipay' | 'wxpay') => {
const handleConfirm = (paymentMethod: 'alipay' | 'wxpay' | 'balance') => {
emit('confirm', paymentMethod);
};
const handleCancel = () => {
if (props.loading) {
return;
}
emit('update:visible', false);
emit('cancel');
};
@@ -40,35 +46,63 @@ const handleCancel = () => {
@cancel="handleCancel"
width="460px"
:maskClosable="false"
:closable="!loading"
>
<div class="order-info">
<div class="info-item">
<span class="label">{{ t('page.order.orderType') }}</span>
<span class="value">{{ orderTypeMap[orderInfo.orderType] }}</span>
<a-spin :spinning="loading" tip="Processing payment...">
<div class="order-info">
<div class="info-item">
<span class="label">{{ t('page.order.orderType') }}</span>
<span class="value">{{ orderTypeMap[orderInfo.orderType] }}</span>
</div>
<div class="info-item">
<span class="label">{{ t('page.order.orderAmount') }}</span>
<span class="value highlight">¥{{ orderInfo.orderAmount.toFixed(2) }}</span>
</div>
<div class="info-item">
<span class="label">{{ t('page.order.orderId') }}</span>
<span class="value">{{ orderInfo.orderId }}</span>
</div>
</div>
<div class="info-item">
<span class="label">{{ t('page.order.orderAmount') }}</span>
<span class="value highlight">¥{{ orderInfo.orderAmount.toFixed(2) }}</span>
</div>
<div class="info-item">
<span class="label">{{ t('page.order.orderId') }}</span>
<span class="value">{{ orderInfo.orderId }}</span>
</div>
</div>
<div class="payment-methods">
<h4>{{ t('page.order.selectPayment') }}</h4>
<div class="methods-container">
<div class="method-item" @click="handleConfirm('alipay')">
<AlipayOutlined class="payment-icon alipay-icon" />
<span>{{ t('page.order.alipay') }}</span>
</div>
<div class="method-item" @click="handleConfirm('wxpay')">
<WechatOutlined class="payment-icon wxpay-icon" />
<span>{{ t('page.order.wxpay') }}</span>
<div class="payment-methods">
<h4>{{ t('page.order.selectPayment') }}</h4>
<div class="methods-container">
<div
v-if="orderInfo.orderType === 0"
class="method-item"
:class="{
disabled: !enableBalancePay || loading,
}"
@click="(!loading && enableBalancePay) && handleConfirm('balance')"
>
<div class="debug-info" style="display: none;">
Enable balance pay: {{ enableBalancePay }}
</div>
<WalletOutlined class="payment-icon balance-icon" />
<span>{{ t('page.order.balancePay') }}</span>
<div class="balance-info" v-if="userBalance !== undefined">
{{ t('page.order.availableBalance') }}: ¥{{ userBalance.toFixed(2) }}
</div>
</div>
<div
class="method-item"
:class="{ disabled: loading }"
@click="!loading && handleConfirm('alipay')"
>
<AlipayOutlined class="payment-icon alipay-icon" />
<span>{{ t('page.order.alipay') }}</span>
</div>
<div
class="method-item"
:class="{ disabled: loading }"
@click="!loading && handleConfirm('wxpay')"
>
<WechatOutlined class="payment-icon wxpay-icon" />
<span>{{ t('page.order.wxpay') }}</span>
</div>
</div>
</div>
</div>
</a-spin>
</a-modal>
</template>
@@ -152,4 +186,41 @@ const handleCancel = () => {
.wxpay-icon {
color: #07c160;
}
.method-item.disabled {
opacity: 0.5;
cursor: not-allowed;
background: #f5f5f5;
}
.balance-icon {
color: #52c41a;
}
.balance-info {
font-size: 12px;
color: #666;
margin-top: 4px;
}
:deep(.ant-spin-container) {
position: relative;
}
:deep(.ant-spin) {
max-height: none;
}
:deep(.ant-spin-spinning) {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background: rgba(255, 255, 255, 0.6);
display: flex;
align-items: center;
justify-content: center;
}
</style>