feat: update payment view UI and flow
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -19,6 +19,9 @@ const isScanning = ref(false);
|
||||
const isSuccess = ref(false);
|
||||
let timer = null;
|
||||
let pollTimer = null;
|
||||
let pollRetries = 0;
|
||||
const MAX_POLL_RETRIES = 20;
|
||||
const errorMessage = ref("");
|
||||
|
||||
const paymentMethodName = computed(() => {
|
||||
return paymentMethod.value === "alipay" ? "支付宝" : "余额";
|
||||
@@ -46,33 +49,28 @@ const loadOrder = async () => {
|
||||
isSuccess.value = true;
|
||||
isScanning.value = false;
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
console.error("Load order failed", e);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
const payOrder = async () => {
|
||||
try {
|
||||
isScanning.value = true;
|
||||
errorMessage.value = "";
|
||||
await orderApi.pay(orderId, { method: paymentMethod.value });
|
||||
// 支付接口若未立即更新状态,将继续依赖轮询
|
||||
// 触发一次立即刷新,后续由轮询收敛
|
||||
await loadOrder();
|
||||
} catch (e) {
|
||||
console.error("Pay order failed", e);
|
||||
errorMessage.value = "支付请求失败,请重试";
|
||||
} finally {
|
||||
isScanning.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const simulateSuccess = () => {
|
||||
isScanning.value = true;
|
||||
setTimeout(() => {
|
||||
isScanning.value = false;
|
||||
isSuccess.value = true;
|
||||
setTimeout(() => {
|
||||
router.replace(tenantRoute(`/me/orders/${orderId}`));
|
||||
}, 1500);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
timer = setInterval(() => {
|
||||
if (timeLeft.value > 0) timeLeft.value--;
|
||||
@@ -80,9 +78,10 @@ onMounted(() => {
|
||||
|
||||
loadOrder();
|
||||
|
||||
// Poll Status
|
||||
// Poll Status (节流 + 成功即停)
|
||||
pollTimer = setInterval(async () => {
|
||||
try {
|
||||
pollRetries += 1;
|
||||
const res = await orderApi.status(orderId);
|
||||
orderStatus.value = res?.status || "";
|
||||
if (res?.amount_paid !== undefined) {
|
||||
@@ -94,14 +93,23 @@ onMounted(() => {
|
||||
if (orderStatus.value === "paid" || orderStatus.value === "completed") {
|
||||
isScanning.value = false;
|
||||
isSuccess.value = true;
|
||||
errorMessage.value = "";
|
||||
clearInterval(pollTimer);
|
||||
setTimeout(
|
||||
() => router.replace(tenantRoute(`/me/orders/${orderId}`)),
|
||||
1500,
|
||||
1200,
|
||||
);
|
||||
}
|
||||
if (pollRetries >= MAX_POLL_RETRIES && pollTimer) {
|
||||
clearInterval(pollTimer);
|
||||
isScanning.value = false;
|
||||
errorMessage.value = "支付结果获取超时,请刷新页面或稍后重试";
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Poll status failed", e);
|
||||
isScanning.value = false;
|
||||
errorMessage.value = "获取支付状态失败,请重试";
|
||||
if (pollTimer) clearInterval(pollTimer);
|
||||
}
|
||||
}, 3000);
|
||||
});
|
||||
@@ -143,16 +151,20 @@ onUnmounted(() => {
|
||||
|
||||
<div class="p-8 md:p-12">
|
||||
<!-- Amount -->
|
||||
<div class="text-center mb-10">
|
||||
<p class="text-slate-500 mb-2">订单提交成功,请尽快支付</p>
|
||||
<div class="text-4xl font-bold text-slate-900">¥ {{ amount }}</div>
|
||||
<div class="text-sm text-slate-500 mt-2">
|
||||
商品:{{ productName || "加载中..." }}
|
||||
<div class="text-center mb-10">
|
||||
<p class="text-slate-500 mb-2">订单提交成功,请尽快支付</p>
|
||||
<div class="text-4xl font-bold text-slate-900">¥ {{ amount }}</div>
|
||||
<div class="text-sm text-slate-500 mt-2">
|
||||
商品:{{ productName || "加载中..." }}
|
||||
</div>
|
||||
<div class="text-xs text-slate-400 mt-1">
|
||||
状态:{{ orderStatus || "pending" }}
|
||||
</div>
|
||||
<div v-if="errorMessage" class="text-xs text-red-500 mt-2">
|
||||
{{ errorMessage }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs text-slate-400 mt-1">
|
||||
状态:{{ orderStatus || "pending" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-12">
|
||||
<!-- Payment Methods -->
|
||||
@@ -237,19 +249,13 @@ onUnmounted(() => {
|
||||
<p class="text-xs text-slate-400">二维码有效时间 2小时</p>
|
||||
</div>
|
||||
|
||||
<!-- Dev Tool -->
|
||||
<div class="flex flex-col items-center gap-3 mt-6">
|
||||
<button
|
||||
@click="payOrder"
|
||||
class="px-4 py-2 rounded-lg bg-primary-600 text-white hover:bg-primary-700"
|
||||
class="px-4 py-2 rounded-lg bg-primary-600 text-white hover:bg-primary-700 disabled:opacity-60"
|
||||
:disabled="isScanning || isSuccess"
|
||||
>
|
||||
立即支付
|
||||
</button>
|
||||
<button
|
||||
@click="simulateSuccess"
|
||||
class="text-xs text-slate-300 hover:text-slate-500 underline"
|
||||
>
|
||||
[开发调试] 模拟支付成功
|
||||
{{ isScanning ? "支付中..." : "立即支付" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user