Files

411 lines
9.3 KiB
Vue
Raw Normal View History

<!--
@name: index
@author: kahu4
@date: 2024-01-21 15:38
@description订单核销
@update: 2024-01-21 15:38
-->
<script setup>
import Header from "@/components/Header/index.vue"
import { useScroll } from "@/hooks/useScroll";
import { wechatIcon } from "@/utils/images";
import { useInterface } from "@/hooks/useInterface";
import { computed, ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { useRouter } from "@/hooks/useRouter";
import { createRechargeOrder, getRechargeConfig } from "@/api/account/balance";
import { doPayment, PayType } from "@/utils/paymentUtils";
import { h5InWeChat } from "@/utils";
// ========================= hooks ==========================
const {toast, loading, hideLoading} = useInterface();
const {scrollTop} = useScroll();
const {getParams, push} = useRouter();
// =========================== 充值方式 =========================
const methodRenderList = ref([
{
label: '微信',
value: 0,
icon: wechatIcon
}
])
// ========================== 充值 =============================
// 当前选中的充值配置
const current = ref(undefined)
// 充值配置
const rechargeConfig = ref({
content: '',
customMin: 0, // 用户最小提现数
customSwitch: 0, // 是否支持用户自定义金额0关闭1开启
rechargePackageBaseVOS: []
})
/**
* 获取充值配置
* @return {Promise<void>}
*/
async function doGetRechargeConfig() {
const res = await getRechargeConfig();
// 是否开启了自定义
if (res.customSwitch === 1) {
res.rechargePackageBaseVOS.push({
id: 'other',
name: '其他',
rechargeAmount: '',
})
}
// 默认选中充值配置的第一项
if (res.rechargePackageBaseVOS.length > 0) {
current.value = res.rechargePackageBaseVOS[0].id
rechargeForm.value.amount = res.rechargePackageBaseVOS[0].rechargeAmount
rechargeForm.value.packageId = res.rechargePackageBaseVOS[0].id
}
rechargeConfig.value = res
}
// 计算其他输入金额的位置
const otherIndex = computed(() => rechargeConfig.value.rechargePackageBaseVOS.findIndex(i => i.id === 'other'))
/**
* 改变金额tab项
* @param item
*/
function currentDefaultMoneyItemChange(item) {
current.value = item.id
rechargeForm.value.packageId = item.id
rechargeForm.value.amount = item.rechargeAmount
}
/**
* 其他金额输入在此给form赋值
* @param e
*/
function handleOtherInput(e) {
rechargeForm.value.amount = parseInt(e.detail.value)
}
// 是否正在请求
const rechargeLoading = ref(false)
// 发起充值的form表单
const rechargeForm = ref({
type: 0, // 0微信
amount: 0,
packageId: null
})
/**
* 提交充值创建充值订单
* @return {Promise<void>}
*/
async function confirm() {
try {
rechargeLoading.value = true
rechargeForm.value.amount = parseInt(rechargeForm.value.amount)
// 如果是其他金额,校验有没有大于最低金额
if (current.value === 'other') {
delete rechargeForm.value.packageId
if (rechargeForm.value.amount < rechargeConfig.value.customMin)
return toast({title: `最低充值${ rechargeConfig.value.customMin }`})
}
const orderId = await createRechargeOrder(rechargeForm.value);
await doPayment({
type: PayType["0"],
payInfo: {orderId}
})
// #ifndef H5
push?.({url: '/pages/payStatus/index?type=2'})
// #endif
// 处理微信内h5
// #ifdef H5
if (h5InWeChat()) {
push?.({url: '/pages/payStatus/index?type=2'})
}
// #endif
} catch (e) {
console.error(e)
throw new Error(e)
} finally {
rechargeLoading.value = false
}
}
onLoad(async (options) => {
await doGetRechargeConfig()
})
</script>
<template>
<view>
<Header
:scroll-top="scrollTop"
system-bar-area-bg="#fff"
header-area-bg="#fff"> 充值
</Header>
<view class="verification">
<view class="ver-card">
<view class="title">选择充值面额</view>
<view class="select-row">
<view
class="select-item"
:class="{current:current === money.id}"
v-for="money in rechargeConfig.rechargePackageBaseVOS"
:key="money.value"
@click="currentDefaultMoneyItemChange(money)">
{{ money.id === 'other' ? money.name : money.rechargeAmount }}
<view
class="give"
v-if="money.giftAmount>0">{{ money.giftAmount }}
</view>
</view>
</view>
<view
class="input row"
:class="{hidden:current !== 'other' }">
<view class="flex flex-ai__center">
<text class="price"></text>
<input
v-if="rechargeConfig.rechargePackageBaseVOS[otherIndex]"
v-model="rechargeConfig.rechargePackageBaseVOS[otherIndex].rechargeAmount"
type="number"
placeholder="请输入充值金额"
@input="handleOtherInput" />
</view>
</view>
</view>
<view class="ver-card">
<view class="title">支付方式</view>
2024-02-22 18:37:23 +08:00
<uv-radio-group
activeColor="#EE6D46"
v-model="rechargeForm.type"
placement="column"
>
<template
v-for="item in methodRenderList"
:key="item.value">
<view
class="flex flex-jc__sb flex-ai__center"
@click="rechargeForm.type = item.value">
<view class="input row method none-border none-bg">
<view class="flex flex-ai__center">
<image
class="icon"
:src="item.icon" />
<text class="text">{{ item.label }}</text>
</view>
</view>
2024-02-22 18:37:23 +08:00
<uv-radio
:customStyle="{marginBottom: '8px'}"
label=" "
:name="item.value"
/>
</view>
</template>
2024-02-22 18:37:23 +08:00
</uv-radio-group>
</view>
2024-02-22 18:37:23 +08:00
<view class="tips-content">
<view class="title">充值说明</view>
<view
class="content"
v-html="rechargeConfig.content"></view>
</view>
<view style="width: 100%;height: 140rpx"></view>
<view
class="btn-row row animation-button"
:class="{disabled:rechargeForm.amount<=0}"
@click="confirm">
确认充值
</view>
</view>
</view>
</template>
<style
scoped
lang="scss">
.verification {
@include usePadding(34, 34);
.ver-card {
@include usePadding(32, 32);
margin-bottom: 24rpx;
border-radius: 15rpx;
background: #fff;
.title {
text-align: left;
font-size: 38rpx;
font-weight: bold;
}
.select-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15rpx;
margin: 24rpx 0;
.select-item {
@include usePadding(0, 30);
text-align: center;
width: 100%;
background: #f6f8f8;
border: 1rpx solid #f6f8f8;;
border-radius: 10rpx;
transition: all .3s;
position: relative;
.give {
@include usePadding(11, 5);
position: absolute;
left: 0;
top: 0;
background: #EE6D46;
border-radius: 10rpx 0 10rpx 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 20rpx;
color: #fff;
}
&.current {
background: #fdf0ed;
border: 1rpx solid #EE6D46;
color: #EE6D46;
font-weight: bold;
}
}
}
.input {
@include useFlex(space-between, center);
@include usePadding(21, 24);
width: 100%;
scale: 1;
overflow: hidden;
transition: all .3s;
border-radius: 8rpx;
background: #f6f8f8;
transform-origin: left top;
.price {
font-size: 48rpx;
font-weight: bolder;
}
input {
width: 100%;
flex-grow: 1;
}
.icon {
width: 80rpx;
height: 80rpx;
margin-right: 30rpx;
}
}
.hidden {
scale: 0;
height: 0;
margin: 0;
padding: 0;
}
.method {
margin-top: 0 !important;
}
.none-border {
border: none;
}
.none-bg {
background: transparent;
}
.qr-scan {
@include useFlex(center, center);
margin-top: 40rpx !important;
image {
width: 120rpx;
height: 120rpx;
transition: all .3s;
&:active {
scale: 1.1;
}
}
}
}
2024-02-22 18:37:23 +08:00
.tips-content {
width: 100%;
color: #999999;
.title {
font-size: 28rpx;
}
.content {
padding: 16rpx 0;
font-size: 24rpx;
}
}
.row {
margin-top: 24rpx;
}
.btn-row {
@include useFlex(center, center);
height: 80rpx;
border-radius: 15rpx;
position: fixed;
width: 90%;
margin: 0 auto;
bottom: 50rpx;
}
.disabled {
background: #f3997d;
&:active {
scale: 1;
animation: disabledAnimation 200ms 15;
}
}
@keyframes disabledAnimation {
0%, 90% {
transform: translateX(0);
}
30% {
transform: translateX(-20rpx);
}
60% {
transform: translateX(20rpx);
}
}
}
:deep(.u-radio) {
margin-bottom: 0 !important;
}
</style>