PC端收银台添加聚合支付 以及 功能优化

This commit is contained in:
ren
2025-04-07 18:07:26 +08:00
parent 9215fe6913
commit c5746d7b44
7 changed files with 232 additions and 32 deletions

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -37,9 +37,9 @@ export function auth(param: GatewayAuthCodeParam) {
}
/**
* 支付成功获取信息
* 支付成功获取状态
*/
export function getSuccessOrder(orderNo) {
export function getSuccessOrderStatus(orderNo) {
return http.request<Result<paySuccess>>({
url: '/unipay/gateway/findStatusByOrderNo',
method: 'POST',
@@ -47,6 +47,17 @@ export function getSuccessOrder(orderNo) {
})
}
/**
* 支付成功获取信息
*/
export function getSuccessOrderMessage(orderNo) {
return http.request<Result<paySuccess>>({
url: '/unipay/gateway/findOrderByOrderNo',
method: 'get',
params: { orderNo },
})
}
/**
* 发起支付
*/

View File

@@ -40,7 +40,7 @@
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { getSuccessOrder } from '@/views/daxpay/h5/aggregate/Aggregate.api'
import { getSuccessOrderMessage } from '@/views/daxpay/h5/aggregate/Aggregate.api'
import type { paySuccess } from '@/views/daxpay/h5/aggregate/Aggregate.api'
import { getBrowserUA } from '@/utils/uaUtil'
// 获取路由参数
@@ -70,7 +70,7 @@ onMounted(() => {
})
function init() {
getSuccessOrder(orderNo).then(({ data }) => {
getSuccessOrderMessage(orderNo).then(({ data }) => {
orderAndConfig.value = data
})
}

View File

@@ -30,7 +30,14 @@ export function orderStatus(orderNo) {
params: { orderNo },
})
}
// 查询订单信息
export function orderMessage(orderNo) {
return http.request<Result<boolean>>({
url: '/unipay/gateway/findOrderByOrderNo',
method: 'GET',
params: { orderNo },
})
}
/**
* 收银台配置
*/
@@ -41,6 +48,8 @@ export interface OrderAndConfig {
config: GatewayPayConfig
/** 收银台分类配置信息 */
groupConfigs: CashierGroupConfig[]
/** 聚合二维码 */
aggregateUrl?: string
}
/**

View File

@@ -1,5 +1,13 @@
<template>
<div class="pcPayTai">
<van-overlay :show="loading" class-name="loadingOverlay">
<div class="loading-wrapper" @click.stop>
<van-loading size="24px">
请稍后...
</van-loading>
</div>
</van-overlay>
<div class="pcPayBox">
<div class="header">
<h1>支付收银台</h1>
@@ -39,15 +47,19 @@
:class="{ methodItemClick: payMethObj.payClickItemId === item.id }"
@click="payMethObj.payClick(item)"
>
<!-- <img :src="item.icon" alt=""> -->
<img src="@/assets/images/alipay.png" alt="">
<img v-if="item.icon === 'aggregate-pay'" :src="getImageUrl(item.icon)" alt="">
<img v-else src="@/assets/images/alipay.png" alt="">
<span>{{ item.name }}</span>
<div v-if="item.recommend" class="recommon">
推荐
</div>
</div>
</div>
<div class="payMethodChildBox">
<!-- 聚合支付 -->
<div v-if="isAggregateShow" class="payMethodCode">
<vue-qr :text="orderObj?.aggregateUrl" :size="200" />
</div>
<div v-else class="payMethodChildBox">
<div
v-for="item in childRenList"
:key="item.id"
@@ -60,7 +72,13 @@
</div>
</div>
</div>
<van-popup v-model:show="codeshow" round closeable :close-on-click-overlay="false">
<van-popup
v-model:show="codeshow"
round
closeable
:close-on-click-overlay="false"
@click-close-icon="closeCode"
>
<template #default>
<div class="codeBox">
<div class="title">
@@ -80,7 +98,7 @@
<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { showDialog, showFailToast } from 'vant'
import { showConfirmDialog, showDialog, showFailToast } from 'vant'
import { result } from 'lodash-es'
import vueQr from 'vue-qr/src/packages/vue-qr.vue'
import { getOrderAndConfig, orderStatus, payOrder } from '@/views/daxpay/pc/cashier/Cashier.api'
@@ -91,6 +109,7 @@ import { GatewayCallTypeEnum } from '@/enums/daxpay/DaxPayEnum'
const route = useRoute()
const router = useRouter()
const { orderNo } = route.params
const loading = ref<boolean>(false)
// 页面信息对象
const orderObj = ref<OrderAndConfig>()
// 分组下的支付列表
@@ -104,6 +123,25 @@ function getImageUrl(icon) {
const codeshow = ref<boolean>(false)
// 二维码链接
const codeLink = ref<string>('')
// 判断是否含有聚合支付
const isAggregateShow = ref<boolean>(false)
// 关闭菜单触发
function closeCode() {
showConfirmDialog({
title: '是否关闭支付弹窗?',
message: '关闭弹窗后该订单会被取消',
className: 'confirmDialogPC',
overlayClass: 'confirmOverlayPC',
})
.then(() => {
codeshow.value = false
router.replace({ path: `/pc/payFail`, query: { msg: '订单已取消,请重新发起支付!' } })
})
.catch(() => {
codeshow.value = true
})
}
// 倒计时对象
const orderTime = reactive({
@@ -133,17 +171,21 @@ const orderTime = reactive({
return time.toString().padStart(2, '0')
},
})
// 定时器
const { pause, resume } = useIntervalFn(() => {
// 倒计时定时器
const { pause: timePause, resume: timeResume } = useIntervalFn(() => {
orderTime.getMinter() // 每秒获取分秒方法
}, 1000)
// 轮询监听定时器
const { pause: lunPause, resume: lunResume } = useIntervalFn(() => {
queryOrderStatus() // 执行订单状态查询
}, 3000)
// 监听倒计时,到时间跳转超时页面
watch(
() => orderTime.totalTme,
(newValue) => {
if (newValue === 0) {
router.replace({ path: `/pc/payFail`, replace: true })
router.replace({ path: `/pc/payFail`, query: { msg: '支付超时,请重新发起支付!' } })
}
},
)
@@ -158,11 +200,13 @@ const payMethObj = reactive({
},
// 点击支付
toPayTypeClick: (item) => {
loading.value = true
payOrder({ orderNo: orderNo as string, itemId: item.id }).then(({ code, data, msg }) => {
if (code !== 0) {
router.replace({ path: `/pc/payFail`, query: { msg } })
return
}
loading.value = false
// 如果是二维码方式 打开支付弹窗
if (item.callType === GatewayCallTypeEnum.qr_code) {
codeshow.value = true
@@ -181,21 +225,24 @@ watch(
() => payMethObj.payClickItemId,
(newValue) => {
if (newValue) {
// 判断是否为聚合支付
if (newValue === '111111111111111111') {
isAggregateShow.value = true
return
}
isAggregateShow.value = false
// 查找点击的分组下面的子项
childRenList.value = orderObj.value?.groupConfigs.find(item => item.id === newValue)?.items
}
},
)
// 轮询定时器
const timer = ref()
onMounted(() => {
init() // 初始化数据
})
onUnmounted(() => {
pause()
timer.value = null
clearInterval(timer.value)
timePause() // 关闭倒计时
lunPause() // 关闭轮询
})
// 初始化
@@ -206,12 +253,21 @@ function init() {
router.replace({ path: `/pc/payFail`, query: { msg } })
return
}
queryOrderStatus() // 查询订单状态开启
lunResume() // 开始轮询查询状态
// 判断是否存在聚合支付
if (data.config.aggregateShow) {
data.groupConfigs.unshift({
id: '111111111111111111',
name: '聚合支付',
recommend: false,
icon: 'aggregate-pay',
})
}
orderObj.value = data
payMethObj.payClickItemId = orderObj.value.groupConfigs[0].id || '' // 赋值第一个
orderTime.getDownTotalTime(data.order.expiredTime) // 计算倒计时
orderTime.getMinter() // 先执行一下 解决进入页面一秒后才显示倒计时
resume() // 开启倒计时
timeResume() // 开启倒计时
})
.catch((error) => {
console.log(error)
@@ -220,19 +276,31 @@ function init() {
// 查询订单状态
function queryOrderStatus() {
timer.value = setInterval(() => {
orderStatus(orderNo).then((res) => {
// 判断订单是否支付成功
if (res.data) {
codeshow.value = false
router.replace({ path: `/pc/paySuccess/${orderNo}`, replace: true })
}
})
}, 3000) as unknown as number
orderStatus(orderNo).then((res) => {
// 判断订单是否支付成功
if (res.data) {
codeshow.value = false
router.replace({ path: `/pc/paySuccess/${orderNo}`, replace: true })
}
})
}
</script>
<style lang="less">
.loadingOverlay {
.van-loading__circular {
color: #fff;
}
.van-loading__text {
color: #fff;
font-weight: 400;
}
}
.confirmOverlayPC {
left: 0;
width: 100%;
height: 100%;
}
.pcPayTai {
.van-overlay {
left: 0;
@@ -406,7 +474,12 @@ function queryOrderStatus() {
border-bottom: none;
}
}
.payMethodCode {
padding: 2.0833vw 0;
display: flex;
justify-content: center;
align-items: center;
}
.payMethodChildBox {
padding: 2.0833vw 0 2.0833vw 15.625vw;
display: flex;

View File

@@ -2,7 +2,9 @@
<div class="pcPayTai">
<div class="pcPayBox">
<img src="@/assets/images/fail1.png" alt="">
<p class="errMessage">{{ msg ? msg : "支付失败,请重新尝试!" }}</p>
<p class="errMessage">
{{ msg ? msg : "支付失败,请重新尝试!" }}
</p>
</div>
</div>
</template>

View File

@@ -3,12 +3,63 @@
<div class="pcPayBox">
<img src="@/assets/images/success1.png" alt="">
<p>支付成功</p>
<div class="payPrice">
<span class="unit"></span>
<div class="price">
{{ orderAndConfig?.amount }}
</div>
</div>
<div class="payMessBox">
<div class="payMessItem">
<div class="itemTitle">
支付标题
</div>
<div class="itemContent">
{{ orderAndConfig?.title }}
</div>
</div>
<div class="payMessItem">
<div class="itemTitle">
订单编号
</div>
<div class="itemContent">
{{ orderAndConfig?.orderNo }}
</div>
</div>
</div>
<div class="payBtnBox" @click="closeSuccessClick">
完成
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { onMounted } from 'vue'
import { orderMessage } from '@/views/daxpay/pc/cashier/Cashier.api'
const route = useRoute()
const { orderNo } = route.params
const orderAndConfig = ref()
onMounted(() => {
init()
console.log(route)
})
// 初始化函数
function init() {
orderMessage(orderNo).then(({ data }) => {
orderAndConfig.value = data
})
}
// 点击关闭
function closeSuccessClick() {
window.close()
}
</script>
<style scoped lang="less">
@@ -35,7 +86,7 @@
overflow: hidden; // 防止内容溢出
display: flex;
flex-direction: column;
justify-content: center;
padding: 7.2083vw 0;
align-items: center;
gap: 1.5625vw;
p {
@@ -43,5 +94,59 @@
color: #1e90ff;
}
}
.payPrice {
display: flex;
gap: 0.2604vw;
align-items: center;
.unit {
font-size: 0.625vw;
transform: translateY(0.4167vw);
}
.price {
font-size: 1.6667vw;
font-weight: 700;
}
}
.payMessBox {
width: 100%;
padding: 0px 1.0417vw;
display: flex;
flex-direction: column;
gap: 0.5208vw;
.payMessItem {
width: 100%;
display: flex;
justify-content: center;
.itemTitle {
font-size: 0.8333vw;
color: #797d81;
}
.itemContent {
font-size: 0.8333vw;
font-weight: 500;
font-size: '微软雅黑';
}
}
}
.payBtnBox {
width: 20%;
margin: 0 auto;
background-color: #0d6eff;
color: #fff;
height: 2.7083vw;
position: absolute;
bottom: 7.6042vw;
text-align: center;
line-height: 2.7083vw;
border-radius: 0.5208vw;
cursor: pointer;
}
}
</style>