Compare commits
4 Commits
bfebed44b0
...
remove-aig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54a83bad5d | ||
|
|
c7062e0b51 | ||
| c399bba109 | |||
| 54e6d423ae |
@@ -31,7 +31,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, getCurrentInstance, onMounted, ref } from "vue";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
|
||||
// 定义props
|
||||
const props = defineProps({
|
||||
@@ -85,11 +85,14 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
customBack: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
// 定义emits
|
||||
const emit = defineEmits(["back"]);
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
// 系统信息
|
||||
const statusBarHeight = ref(0);
|
||||
@@ -145,25 +148,9 @@ const navContentStyle = computed(() => {
|
||||
};
|
||||
});
|
||||
|
||||
const hasBackListener = computed(() => {
|
||||
const vnodeProps = instance?.vnode?.props || {};
|
||||
return Boolean(vnodeProps.onBack);
|
||||
});
|
||||
|
||||
// 处理返回事件
|
||||
const handleBack = () => {
|
||||
const pages = getCurrentPages();
|
||||
|
||||
if (pages.length <= 1) {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (typeof wx !== "undefined" && typeof wx.exitMiniProgram === "function") {
|
||||
wx.exitMiniProgram();
|
||||
return;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
if (hasBackListener.value) {
|
||||
if (props.customBack) {
|
||||
emit("back");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
safe-area-inset-bottom @query="queryList">
|
||||
<template #top>
|
||||
<TopNavBar title="积分明细" background="transparent" title-color="#172033" back-icon-color="#172033"
|
||||
:align-with-menu-button="true" :z-index="3" @back="handleBack" />
|
||||
custom-back :align-with-menu-button="true" :z-index="3" @back="handleBack" />
|
||||
</template>
|
||||
|
||||
<view class="points-details-content">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<template #top>
|
||||
<view class="aigc-record-nav">
|
||||
<TopNavBar title="最近任务" background="transparent" title-color="#162235" back-icon-color="#162235"
|
||||
:align-with-menu-button="true" :z-index="1" @back="handleBack" />
|
||||
custom-back :align-with-menu-button="true" :z-index="1" @back="handleBack" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<view class="shared-work-page">
|
||||
<view class="shared-work-nav">
|
||||
<TopNavBar :title="shareDetail.templateName || '旅行作品'" background="#fff" title-color="#173a5f"
|
||||
back-icon-color="#173a5f" :align-with-menu-button="true" :z-index="3" @back="handleBack" />
|
||||
back-icon-color="#173a5f" custom-back :align-with-menu-button="true" :z-index="3" @back="handleBack" />
|
||||
</view>
|
||||
|
||||
<view class="shared-work-scroll">
|
||||
@@ -106,13 +106,10 @@ const openAigcHome = () => {
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack();
|
||||
return;
|
||||
}
|
||||
|
||||
openAigcHome();
|
||||
uni.reLaunch({
|
||||
url: "/pages/index/index",
|
||||
fail: () => showToast("返回首页失败"),
|
||||
});
|
||||
};
|
||||
|
||||
const handleCreateOwn = async () => {
|
||||
|
||||
@@ -210,8 +210,8 @@ const validateUserForms = () => {
|
||||
return true;
|
||||
};
|
||||
|
||||
// 处理支付点击事件
|
||||
const handlePayClick = ThrottleUtils.createThrottle(async (goodsData) => {
|
||||
// 处理支付点击事件 - 使用执行锁防止重复支付
|
||||
const handlePayClick = ThrottleUtils.createExecutionLock(async (goodsData) => {
|
||||
console.log("处理支付点击事件", userFormList.value);
|
||||
// 预约日期,酒店类型不需要
|
||||
if (orderData.value.reservationEnabled) {
|
||||
@@ -267,72 +267,82 @@ const handlePayClick = ThrottleUtils.createThrottle(async (goodsData) => {
|
||||
|
||||
// 点击后立即展示 loading
|
||||
uni.showLoading({ title: "正在提交订单..." });
|
||||
const res = await orderPay(params);
|
||||
console.log("确认订单---2:", res);
|
||||
uni.hideLoading();
|
||||
|
||||
// 检查接口返回数据
|
||||
if (!res || !res.data) {
|
||||
try {
|
||||
const res = await orderPay(params);
|
||||
console.log("确认订单---2:", res);
|
||||
|
||||
// 检查接口返回数据
|
||||
if (!res || !res.data) {
|
||||
setTimeout(() => {
|
||||
uni.showToast({
|
||||
title: res.msg || "订单创建失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
const { data } = res;
|
||||
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
|
||||
|
||||
// 验证支付参数是否完整
|
||||
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
|
||||
setTimeout(() => {
|
||||
uni.showToast({ title: "支付参数错误,请重试", icon: "none" });
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// 关闭 loading
|
||||
uni.hideLoading();
|
||||
setTimeout(() => {
|
||||
uni.showToast({
|
||||
title: res.msg || "订单创建失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
const { data } = res;
|
||||
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
|
||||
|
||||
// 验证支付参数是否完整
|
||||
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
|
||||
uni.hideLoading();
|
||||
setTimeout(() => {
|
||||
uni.showToast({ title: "支付参数错误,请重试", icon: "none" });
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// 在发起微信支付前关闭 loading(避免与原生支付 UI 冲突)
|
||||
uni.hideLoading();
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 调用微信支付
|
||||
uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
timeStamp: String(timeStamp), // 确保为字符串类型
|
||||
nonceStr: String(nonceStr),
|
||||
package: String(packageVal), // 确保为字符串类型
|
||||
signType: String(signType),
|
||||
paySign: String(paySign),
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: "支付成功",
|
||||
icon: "success",
|
||||
// #ifdef MP-WEIXIN
|
||||
// 调用微信支付
|
||||
await new Promise((resolve) => {
|
||||
uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
timeStamp: String(timeStamp), // 确保为字符串类型
|
||||
nonceStr: String(nonceStr),
|
||||
package: String(packageVal), // 确保为字符串类型
|
||||
signType: String(signType),
|
||||
paySign: String(paySign),
|
||||
success: () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages-order/order/list",
|
||||
uni.showToast({
|
||||
title: "支付成功",
|
||||
icon: "success",
|
||||
success: () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages-order/order/list",
|
||||
});
|
||||
},
|
||||
});
|
||||
resolve();
|
||||
},
|
||||
fail: (e) => {
|
||||
console.error("支付失败:", e);
|
||||
uni.showToast({ title: "支付失败,请重试", icon: "none" });
|
||||
resolve();
|
||||
},
|
||||
});
|
||||
},
|
||||
fail: (e) => {
|
||||
console.error("支付失败:", e);
|
||||
uni.showToast({ title: "支付失败,请重试", icon: "none" });
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
});
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "支付功能开发中",
|
||||
showCancel: false,
|
||||
});
|
||||
// #endif
|
||||
}, 1000);
|
||||
// #ifdef APP-PLUS
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "支付功能开发中",
|
||||
showCancel: false,
|
||||
});
|
||||
// #endif
|
||||
} catch (error) {
|
||||
console.error("支付流程出错:", error);
|
||||
uni.showToast({ title: "支付失败,请重试", icon: "none" });
|
||||
} finally {
|
||||
// 确保 loading 被关闭
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, computed } from "vue";
|
||||
import { orderPayNow } from "@/request/api/OrderApi";
|
||||
import { DebounceUtils } from "@/utils";
|
||||
import { ThrottleUtils } from "@/utils";
|
||||
|
||||
const props = defineProps({
|
||||
orderData: {
|
||||
@@ -64,8 +64,8 @@ const buttonText = computed(() => {
|
||||
// 定义事件发射器
|
||||
const emit = defineEmits(["refund", "refresh"]);
|
||||
|
||||
// 处理按钮点击事件
|
||||
const handleButtonClick = DebounceUtils.createDebounce(async (orderData) => {
|
||||
// 处理按钮点击事件 - 使用执行锁防止重复支付
|
||||
const handleButtonClick = ThrottleUtils.createExecutionLock(async (orderData) => {
|
||||
try {
|
||||
// 再次预定跳转商品详情
|
||||
if (["1", "2", "3", "4", "5", "6"].includes(statusCode.value)) {
|
||||
@@ -89,7 +89,6 @@ const handleButtonClick = DebounceUtils.createDebounce(async (orderData) => {
|
||||
|
||||
// 检查接口返回数据
|
||||
if (!res || !res.data) {
|
||||
uni.hideLoading();
|
||||
setTimeout(() => {
|
||||
uni.showToast({ title: res.msg || "订单创建失败,请重试", icon: "none" });
|
||||
}, 100);
|
||||
@@ -101,38 +100,41 @@ const handleButtonClick = DebounceUtils.createDebounce(async (orderData) => {
|
||||
|
||||
// 验证支付参数是否完整
|
||||
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
|
||||
uni.hideLoading();
|
||||
setTimeout(() => {
|
||||
uni.showToast({ title: "支付参数错误,请重试", icon: "none" });
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// 在发起微信支付前关闭 loading(避免与原生支付 UI 冲突)
|
||||
// 关闭 loading
|
||||
uni.hideLoading();
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 调用微信支付
|
||||
uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
timeStamp: String(timeStamp), // 确保为字符串类型
|
||||
nonceStr: String(nonceStr),
|
||||
package: String(packageVal), // 确保为字符串类型
|
||||
signType: String(signType),
|
||||
paySign: String(paySign),
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: "支付成功",
|
||||
icon: "success",
|
||||
success: () => {
|
||||
console.log("支付成功,刷新订单详情");
|
||||
emit("refresh", { orderId: orderId });
|
||||
},
|
||||
});
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: "支付失败,请重试", icon: "none" });
|
||||
},
|
||||
// 调用微信支付 - 包装成 Promise 以便锁住执行状态
|
||||
await new Promise((resolve) => {
|
||||
uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
timeStamp: String(timeStamp), // 确保为字符串类型
|
||||
nonceStr: String(nonceStr),
|
||||
package: String(packageVal), // 确保为字符串类型
|
||||
signType: String(signType),
|
||||
paySign: String(paySign),
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: "支付成功",
|
||||
icon: "success",
|
||||
success: () => {
|
||||
console.log("支付成功,刷新订单详情");
|
||||
emit("refresh", { orderId: orderId });
|
||||
},
|
||||
});
|
||||
resolve();
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: "支付失败,请重试", icon: "none" });
|
||||
resolve();
|
||||
},
|
||||
});
|
||||
});
|
||||
// #endif
|
||||
|
||||
@@ -146,9 +148,12 @@ const handleButtonClick = DebounceUtils.createDebounce(async (orderData) => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("操作失败:", error);
|
||||
uni.showToast({ title: "操作失败,请重试", icon: "none" });
|
||||
} finally {
|
||||
// 确保 loading 被关闭
|
||||
uni.hideLoading();
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -280,7 +280,7 @@ export class DebounceUtils {
|
||||
*/
|
||||
export class ThrottleUtils {
|
||||
/**
|
||||
* 创建节流函数
|
||||
* 创建节流函数(传统时间戳方式)
|
||||
* @param {Function} func - 要节流的函数
|
||||
* @param {number} delay - 节流延迟时间
|
||||
* @returns {Function} 节流后的函数
|
||||
@@ -297,6 +297,81 @@ export class ThrottleUtils {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建异步安全的节流函数(带执行状态锁)
|
||||
* 适用于支付等需要等待完成的异步操作
|
||||
* @param {Function} func - 要节流的异步函数
|
||||
* @param {number} delay - 节流延迟时间(毫秒)
|
||||
* @returns {Function} 节流后的函数
|
||||
*/
|
||||
static createAsyncThrottle(func, delay = 1000) {
|
||||
let isExecuting = false; // 执行状态锁
|
||||
let lastExecTime = 0; // 上次执行时间
|
||||
|
||||
return async function (...args) {
|
||||
const now = Date.now();
|
||||
|
||||
// 如果正在执行中,直接返回
|
||||
if (isExecuting) {
|
||||
console.warn('函数正在执行中,跳过此次调用');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果还在节流时间内,直接返回
|
||||
if (now - lastExecTime < delay) {
|
||||
console.warn('节流时间内,跳过此次调用');
|
||||
return;
|
||||
}
|
||||
|
||||
// 加锁
|
||||
isExecuting = true;
|
||||
lastExecTime = now;
|
||||
|
||||
try {
|
||||
// 执行异步函数
|
||||
return await func.apply(this, args);
|
||||
} catch (error) {
|
||||
console.error('异步节流函数执行出错:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// 无论成功失败都解锁
|
||||
isExecuting = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建执行锁函数(最简单的防重复方式,只锁执行状态)
|
||||
* 适用于支付等场景,上一次没完成前绝对不执行第二次
|
||||
* @param {Function} func - 要加锁的函数
|
||||
* @returns {Function} 加锁后的函数
|
||||
*/
|
||||
static createExecutionLock(func) {
|
||||
let isExecuting = false;
|
||||
|
||||
return async function (...args) {
|
||||
// 如果正在执行中,直接返回
|
||||
if (isExecuting) {
|
||||
console.warn('函数正在执行中,跳过此次调用');
|
||||
return;
|
||||
}
|
||||
|
||||
// 加锁
|
||||
isExecuting = true;
|
||||
|
||||
try {
|
||||
// 执行函数
|
||||
return await func.apply(this, args);
|
||||
} catch (error) {
|
||||
console.error('执行锁函数执行出错:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// 无论成功失败都解锁
|
||||
isExecuting = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user