food_wechat/pages/shop/pay.vue
sszdot 6abfd95c8a 【类 型】:factor
【原  因】:防止 重复点击按钮
【过  程】:给支付按钮加一个标记 点击之后改变按钮样式 并且标记点击过 点击过 则不继续执行pay 函数
【影  响】:

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-12-18 18:35:51 +08:00

204 lines
5.3 KiB
Vue

<template>
<view>
<!-- topbar -->
<u-navbar title="收银台" bgColor="#d43030" :titleStyle="{ color: '#FFF'}" :autoBack="true" placeholder>
<view class="u-nav-slot" slot="left">
<u-icon name="arrow-left" color="#fff" size="19"></u-icon>
</view>
</u-navbar>
<!-- body -->
<view class="flex column msb bodyBox">
<view>
<view class="priceBox fb flex mc">¥{{fullPrice | formatPrice}}</view>
<view class="fcb fz24 flex mc" v-if="countdown !== ''">
<span class="m-r-24">支付剩余时间</span>
<span>{{ countdown }}</span>
</view>
<view class="fcb fz24 flex mc" v-else>
<span>订单加载中···</span>
</view>
<view class="flex msb mac rad8 bg-w m-l-24 m-r-24 m-t-24 p-24">
<view class="flex mac">
<u--image src="/static/icons/wxPayLogo.svg" width="75rpx" height="60rpx" />
<view class="fz36 m-l-24">微信支付</view>
</view>
<view class="flex border rad-c border-m bg-m checkBox">
<u-icon name="checkbox-mark" size="40rpx" color="#fff"></u-icon>
</view>
</view>
</view>
<view @click="pay" class="butBox fci bg-m rad8 fb fz36 flex mc p-24 m-l-24 m-r-24" :class="isPressed?'bg-g':'bg-m'">确认支付</view>
</view>
</view>
</template>
<script>
import {
formatPrice,
formatSeconds
} from '@/utils/index.js'
export default {
data() {
return {
order_sn: '', //订单号
fullPrice: 0, //总价格 包括附加费用
order_time: -1, //订单创建时间
countdown: '', // 用于显示倒计时
timer: null, // 存储计时器
isPressed: false, //支付按钮是否锁定
}
},
onLoad(options) {
this.$store.dispatch('fetchOrderList')
this.order_sn = options.order_sn // 从提交订单页面传递过来的订单号
this.fullPrice = Number(options.fullPrice) // 从提交订单页面传递过来的订单号
if (this.orderShow) {
this.order_time = Number(this.orderShow.order_time)
}
},
computed: {
// 订单详情
orderShow() {
if (this.$store.state.orderList && this.$store.state.orderList.length > 0) {
// 使用 find 查找匹配的订单
return this.$store.state.orderList.find(item => item.order_sn === this.order_sn) || null
}
return null // 如果 orderList 为空或未定义,返回 null
}
},
filters: {
formatPrice, //格式化价格
},
watch: {
orderShow: {
handler(val) {
// 先判断数据有效性
if (val && val.order_time) {
this.order_time = Number(val.order_time)
} else {
this.order_time = -1 // 重置为无效值
}
},
deep: true,
immediate: true,
},
order_time: {
handler(val) {
if (this.timer) {
clearInterval(this.timer) // 清除已有定时器
}
// 如果 order_time 无效,则不启动倒计时
if (!val || val < 0) return
this.timer = setInterval(() => {
const tempTime = this.order_time + 900 - Math.floor(Date.now() / 1000)
if (tempTime <= 0) {
this.countdown = '00:00'
clearInterval(this.timer) // 清除定时器
// 倒计时结束后跳转到首页
uni.navigateTo({
url: '/pages/index/index', // 非 Tab 页的路径
})
} else {
this.countdown = this.formatSeconds(tempTime)
}
}, 1000)
},
immediate: true, // 确保初次赋值时立即触发
}
},
methods: {
//秒格式化成 00:00格式
formatSeconds,
// 支付方法
pay() {
if (this.isPressed) { //防止支付按钮重复点击
return
}
this.isPressed = true
uni.$u.http.post('/Api/Pay/pay', {
order_sn: this.order_sn
}, {
header: {
'Token': this.$store.state.userInfo.token,
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then((res) => {
if (res.data.status === 1) {
// 调用微信支付接口
this.requestPayment(res.data.payMsg)
} else {
uni.showToast({
title: '支付失败',
icon: 'error'
})
// 延迟跳转到首页
setTimeout(() => {
uni.reLaunch({
url: '/pages/main/order',
})
}, 1500) // 1.5秒后跳转
console.error(res.data.msg)
}
})
},
// 调用微信支付接口
requestPayment(payMsg) {
uni.requestPayment({
timeStamp: payMsg.timeStamp,
nonceStr: payMsg.nonceStr,
package: payMsg.package,
signType: payMsg.signType,
paySign: payMsg.paySign,
success: (res) => {
uni.showToast({
title: '支付成功',
icon: 'success'
})
// 延迟跳转到首页
setTimeout(() => {
uni.reLaunch({
url: '/pages/main/order',
})
}, 1500) // 1.5秒后跳转
},
fail: (err) => {
console.error('支付失败:', err)
uni.showToast({
title: '支付失败',
icon: 'error'
})
// 延迟跳转到首页
setTimeout(() => {
uni.reLaunch({
url: '/pages/main/order',
})
}, 1500) // 1.5秒后跳转
}
})
}
},
destroyed() {
// 在组件销毁前清除定时器
clearInterval(this.timer) // 倒计时结束后清除定时器
}
}
</script>
<style lang="scss" scoped>
.priceBox {
font-size: 72rpx;
margin-top: 140rpx;
}
.butBox {
margin-bottom: 72rpx;
}
.bodyBox {
height: calc(100vh - 176rpx);
}
</style>