259 lines
6.8 KiB
Vue
259 lines
6.8 KiB
Vue
<template>
|
||
<view class="quick-wrapper">
|
||
<view>
|
||
<view class="quick-money">
|
||
<text class="quick-title">收款金额</text>
|
||
<view class="quick-input">
|
||
<view class="quick-number">{{ vdata.payAmount }}</view>
|
||
<text>(元)</text>
|
||
</view>
|
||
</view>
|
||
<view class="quick-remarks-wrapper"><text class="quick-remarks" @tap="jeepayPopupInputRef.open()">添加备注</text></view>
|
||
</view>
|
||
|
||
<!-- 键盘页面 -->
|
||
<JKeyboard @selectedStore="selectedStore" @boardDown="boardDown" v-model:value="vdata.payAmount" :storeName="vdata.store.storeName" />
|
||
</view>
|
||
|
||
<!-- 备注弹层 -->
|
||
<JeepayPopupInput ref="jeepayPopupInputRef" label="备注" :maxLength="12" v-model:value="vdata.payRemark" />
|
||
<PaymentSuccess ref="paymentSuccessRef" @close="resetData" />
|
||
|
||
<JeepayBizinfoSelect ref="jeepayBizinfoSelect" />
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive } from 'vue'
|
||
import { onUnload, onShow } from '@dcloudio/uni-app'
|
||
import PaymentSuccess from './components/PaymentSuccess.vue'
|
||
import { req, reqLoad, API_URL_MCH_STORE_LIST, $appPay, API_URL_PAY_ORDER_LIST } from '@/http/apiManager.js'
|
||
import infoBox from '@/commons/utils/infoBox.js'
|
||
import timer from '@/commons/utils/timer.js'
|
||
import go from '@/commons/utils/go.js'
|
||
import emit from '@/commons/utils/emit.js'
|
||
|
||
const jeepayPopupInputRef = ref()
|
||
const paymentSuccessRef = ref()
|
||
const jeepayBizinfoSelect = ref()
|
||
|
||
const vdata = reactive({
|
||
payRemark: '', // 支付备注
|
||
payAmount: 0, // 支付金额
|
||
store: {}, //选择的门店
|
||
isUnload: false, // 页面是否已销毁。
|
||
isOpenScan: false, // 是否直接打开相机
|
||
})
|
||
|
||
// 页面销毁需要将 定时任务结束。
|
||
onUnload(() => {
|
||
vdata.isUnload = true
|
||
uni.$off(emit.ENAME_E_PAY_SCAN)
|
||
uni.$off(emit.ENAME_RESET_PAY_AMOUNT)
|
||
})
|
||
|
||
onShow(() => {
|
||
if (vdata.isOpenScan) {
|
||
// 打开相机
|
||
funObj.scan()
|
||
vdata.isOpenScan = false
|
||
} else {
|
||
// 其他页面进入, 需要金额初始化。
|
||
// 调起扫一扫, 会重新 onShow, 暂时不重置金额。
|
||
// vdata.payAmount = 0; // 金额初始化
|
||
}
|
||
})
|
||
|
||
// 监听扫一扫, 之后需要在 onShow中调用。
|
||
uni.$on(emit.ENAME_E_PAY_SCAN, function (data) {
|
||
vdata.isOpenScan = true
|
||
})
|
||
uni.$on(emit.ENAME_RESET_PAY_AMOUNT, function (data) {
|
||
vdata.payAmount = 0
|
||
vdata.payRemark = ''
|
||
})
|
||
|
||
function reqTableDataByStoreFunc(params) {
|
||
return reqLoad.list(API_URL_MCH_STORE_LIST, params)
|
||
}
|
||
|
||
// 预先检查
|
||
function preCheckFunc(callbackFunc) {
|
||
if (isNaN(vdata.payAmount) || vdata.payAmount <= 0) {
|
||
infoBox.showToast('请输入金额')
|
||
return false
|
||
}
|
||
|
||
if (!vdata.store.storeId) {
|
||
infoBox.showToast('请选择门店')
|
||
selectedStore().then(() => {
|
||
if (callbackFunc) {
|
||
callbackFunc()
|
||
}
|
||
})
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
const funObj = {
|
||
scan: () => {
|
||
if (!preCheckFunc(funObj.scan)) {
|
||
return false
|
||
}
|
||
uni.scanCode().then(({ result }) => {
|
||
// 调起支付
|
||
$appPay(vdata.store.storeId, vdata.payAmount, vdata.payRemark, 'AUTO_BAR', result).then(({ bizData }) => {
|
||
processPayData(bizData, true)
|
||
})
|
||
})
|
||
},
|
||
code: () => {
|
||
if (!preCheckFunc(funObj.code)) {
|
||
return false
|
||
}
|
||
// 调起支付
|
||
$appPay(vdata.store.storeId, vdata.payAmount, vdata.payRemark, 'QR_CASHIER').then(({ bizData }) => {
|
||
// 处理支付结果
|
||
processPayData(bizData, false)
|
||
})
|
||
},
|
||
}
|
||
|
||
// 选择门店
|
||
const selectedStore = () => {
|
||
return jeepayBizinfoSelect.value.open(vdata.store).then((selected) => {
|
||
if (selected) {
|
||
vdata.store = selected
|
||
return Promise.resolve()
|
||
} else {
|
||
vdata.store = {}
|
||
return Promise.reject()
|
||
}
|
||
})
|
||
}
|
||
|
||
// 处理调起下单接口的返回数据
|
||
function processPayData(bizData, isScan) {
|
||
if (bizData.orderState == 2) {
|
||
// 成功
|
||
|
||
// 跳转到支付成功页面, 兼容payOrderInfo没有数据的情况。
|
||
let payOrderInfo = Object.assign(bizData, { state: bizData.orderState, amount: vdata.payAmount * 100 })
|
||
if (bizData.payOrderInfo) {
|
||
payOrderInfo = JSON.parse(bizData.payOrderInfo)
|
||
}
|
||
vdata.payAmount = 0
|
||
return paymentSuccessRef.value.open(payOrderInfo)
|
||
} else if (bizData.orderState == 3) {
|
||
// 成功
|
||
|
||
// 失败
|
||
return infoBox.showToast('失败:' + bizData.errMsg, 3)
|
||
} else {
|
||
// 聚合二维码方式 - 显示弹层
|
||
if (!isScan) {
|
||
return go.to('PAGES_QR_CASHIER', { qrImgUrl: bizData.payData, payOrderId: bizData.payOrderId, payAmount: vdata.payAmount })
|
||
}
|
||
|
||
// 仅scan 需要 轮询查单
|
||
return orderPollingByScan(bizData.payOrderId)
|
||
}
|
||
}
|
||
|
||
// 轮询查单 ( 扫一扫方式 )
|
||
function orderPollingByScan(payOrderId) {
|
||
// 总共查询几次
|
||
let allCount = 10
|
||
|
||
timer.startTimeoutTask(2, allCount, (subTime) => {
|
||
// 页面已销毁。
|
||
if (vdata.isUnload) {
|
||
return false
|
||
}
|
||
|
||
infoBox.showLoading(`等待付款, 第[${allCount - subTime}/${allCount}]次查单中...`)
|
||
|
||
// 任务结束
|
||
if (subTime <= 0) {
|
||
return infoBox.showToast('请于订单列表查询结果').then(() => {
|
||
emit.pageEmit(emit.ENAME_REF_PAY_ORDER) // 刷新订单数据
|
||
go.to('PAGES_PAY_ORDER', {}, go.GO_TYPE_SWITCHTAB)
|
||
})
|
||
}
|
||
|
||
return req.getById(API_URL_PAY_ORDER_LIST, payOrderId).then(({ bizData }) => {
|
||
switch (bizData.state) {
|
||
case 2:
|
||
infoBox.showSuccessToast('支付成功')
|
||
paymentSuccessRef.value.open(bizData)
|
||
return Promise.reject()
|
||
break
|
||
case 3:
|
||
infoBox.showToast('支付失败')
|
||
return Promise.reject()
|
||
break
|
||
case 4:
|
||
infoBox.showErrorToast('订单撤销')
|
||
return Promise.reject()
|
||
break
|
||
default:
|
||
return Promise.resolve()
|
||
break
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
const boardDown = (key) => {
|
||
if (['scan', 'code'].includes(key)) return funObj[key]()
|
||
}
|
||
// 成功清除数据
|
||
const resetData = () => {
|
||
vdata.payAmount = 0
|
||
vdata.payRemark = ''
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.quick-wrapper {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
min-height: calc(100vh - 90rpx);
|
||
.quick-money {
|
||
margin: 0 auto;
|
||
margin-top: 50rpx;
|
||
width: 630rpx;
|
||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.2);
|
||
.quick-title {
|
||
color: rgba(0, 0, 0, 0.5);
|
||
font-size: 30rpx;
|
||
}
|
||
.quick-input {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
height: 130rpx;
|
||
margin-top: 10rpx;
|
||
.quick-number {
|
||
flex: 1;
|
||
font-size: 60rpx;
|
||
font-weight: 500;
|
||
}
|
||
text {
|
||
align-self: flex-end;
|
||
transform: translateY(-30rpx);
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
}
|
||
.quick-remarks-wrapper {
|
||
margin-top: 58rpx;
|
||
text-align: center;
|
||
font-size: 30rpx;
|
||
color: $J-color-t29;
|
||
}
|
||
}
|
||
</style>
|