Files

411 lines
9.3 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.

<!--
@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>
<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>
<uv-radio
:customStyle="{marginBottom: '8px'}"
label=" "
:name="item.value"
/>
</view>
</template>
</uv-radio-group>
</view>
<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;
}
}
}
}
.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>