feat(ticket): 添加支付后自动刷新水票列表功能
- 在订单确认页面跳转到水票列表时添加时间戳参数 - 在水票列表页面添加支付后自动刷新逻辑 - 使用 ref 防止重复执行自动刷新 - 添加缓存键避免重复处理同一支付请求 - 支付后自动重试刷新水票列表三次,确保数据同步 - 实现了防抖机制防止并发刷新操作
This commit is contained in:
@@ -507,6 +507,7 @@ const OrderConfirm = () => {
|
|||||||
await PaymentHandler.pay(updatedOrderData, currentPaymentType, hasTicketTemplate ? {
|
await PaymentHandler.pay(updatedOrderData, currentPaymentType, hasTicketTemplate ? {
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
const id = goods.goodsId
|
const id = goods.goodsId
|
||||||
|
const ticketIndexUrl = `/user/ticket/index?fromPayAt=${Date.now()}`
|
||||||
try {
|
try {
|
||||||
const res = await Taro.showModal({
|
const res = await Taro.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
@@ -518,13 +519,13 @@ const OrderConfirm = () => {
|
|||||||
if (id) {
|
if (id) {
|
||||||
await Taro.redirectTo({ url: `/user/ticket/use?goodsId=${id}` })
|
await Taro.redirectTo({ url: `/user/ticket/use?goodsId=${id}` })
|
||||||
} else {
|
} else {
|
||||||
await Taro.redirectTo({ url: '/user/ticket/index' })
|
await Taro.redirectTo({ url: ticketIndexUrl })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await Taro.redirectTo({ url: '/user/ticket/index' })
|
await Taro.redirectTo({ url: ticketIndexUrl })
|
||||||
}
|
}
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
await Taro.redirectTo({ url: '/user/ticket/index' })
|
await Taro.redirectTo({ url: ticketIndexUrl })
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -583,6 +584,7 @@ const OrderConfirm = () => {
|
|||||||
await PaymentHandler.pay(orderData, paymentType, hasTicketTemplate ? {
|
await PaymentHandler.pay(orderData, paymentType, hasTicketTemplate ? {
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
const id = goods.goodsId
|
const id = goods.goodsId
|
||||||
|
const ticketIndexUrl = `/user/ticket/index?fromPayAt=${Date.now()}`
|
||||||
try {
|
try {
|
||||||
const res = await Taro.showModal({
|
const res = await Taro.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
@@ -594,13 +596,13 @@ const OrderConfirm = () => {
|
|||||||
if (id) {
|
if (id) {
|
||||||
await Taro.redirectTo({ url: `/user/ticket/use?goodsId=${id}` })
|
await Taro.redirectTo({ url: `/user/ticket/use?goodsId=${id}` })
|
||||||
} else {
|
} else {
|
||||||
await Taro.redirectTo({ url: '/user/ticket/index' })
|
await Taro.redirectTo({ url: ticketIndexUrl })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await Taro.redirectTo({ url: '/user/ticket/index' })
|
await Taro.redirectTo({ url: ticketIndexUrl })
|
||||||
}
|
}
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
await Taro.redirectTo({ url: '/user/ticket/index' })
|
await Taro.redirectTo({ url: ticketIndexUrl })
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import Taro, { useDidShow } from '@tarojs/taro';
|
import Taro, { useDidShow } from '@tarojs/taro';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -23,6 +23,7 @@ import dayjs from "dayjs";
|
|||||||
import { ensureLoggedIn } from '@/utils/auth';
|
import { ensureLoggedIn } from '@/utils/auth';
|
||||||
|
|
||||||
const PAGE_SIZE = 10;
|
const PAGE_SIZE = 10;
|
||||||
|
const PAY_REFRESH_HANDLED_KEY = 'user_ticket_from_pay_at_handled';
|
||||||
|
|
||||||
const UserTicketList = () => {
|
const UserTicketList = () => {
|
||||||
const [ticketList, setTicketList] = useState<GltUserTicket[]>([]);
|
const [ticketList, setTicketList] = useState<GltUserTicket[]>([]);
|
||||||
@@ -47,6 +48,25 @@ const UserTicketList = () => {
|
|||||||
const [qrVisible, setQrVisible] = useState(false);
|
const [qrVisible, setQrVisible] = useState(false);
|
||||||
const [qrTicket, setQrTicket] = useState<GltUserTicket | null>(null);
|
const [qrTicket, setQrTicket] = useState<GltUserTicket | null>(null);
|
||||||
const [qrImageUrl, setQrImageUrl] = useState('');
|
const [qrImageUrl, setQrImageUrl] = useState('');
|
||||||
|
const payAutoRefreshRunningRef = useRef(false);
|
||||||
|
|
||||||
|
const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
const parsePositiveNumberParam = (v: unknown) => {
|
||||||
|
const n = Number(v);
|
||||||
|
return Number.isFinite(n) && n > 0 ? n : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFromPayAtParam = () => {
|
||||||
|
const params = Taro.getCurrentInstance().router?.params;
|
||||||
|
return parsePositiveNumberParam((params as any)?.fromPayAt);
|
||||||
|
};
|
||||||
|
|
||||||
|
const shouldAutoRefreshAfterPay = (fromPayAt?: number) => {
|
||||||
|
if (!fromPayAt) return false;
|
||||||
|
const handled = parsePositiveNumberParam(Taro.getStorageSync(PAY_REFRESH_HANDLED_KEY)) || 0;
|
||||||
|
return handled !== fromPayAt;
|
||||||
|
};
|
||||||
|
|
||||||
const getUserId = () => {
|
const getUserId = () => {
|
||||||
const raw = Taro.getStorageSync('UserId');
|
const raw = Taro.getStorageSync('UserId');
|
||||||
@@ -530,22 +550,36 @@ const UserTicketList = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useDidShow(() => {
|
useDidShow(() => {
|
||||||
const tabParam = Taro.getCurrentInstance().router?.params?.tab
|
void (async () => {
|
||||||
const nextTab =
|
const tabParam = Taro.getCurrentInstance().router?.params?.tab;
|
||||||
tabParam === 'ticket' || tabParam === 'order'
|
const nextTab = tabParam === 'ticket' || tabParam === 'order' ? tabParam : undefined;
|
||||||
? tabParam
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
if (nextTab && nextTab !== activeTab) {
|
if (nextTab && nextTab !== activeTab) {
|
||||||
setActiveTab(nextTab)
|
setActiveTab(nextTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabToLoad = nextTab || activeTab
|
const tabToLoad = nextTab || activeTab;
|
||||||
if (tabToLoad === 'ticket') {
|
if (tabToLoad === 'ticket') {
|
||||||
reloadTickets(true).then()
|
await reloadTickets(true);
|
||||||
} else {
|
|
||||||
reloadOrders(true).then()
|
const fromPayAt = getFromPayAtParam();
|
||||||
|
if (shouldAutoRefreshAfterPay(fromPayAt) && !payAutoRefreshRunningRef.current) {
|
||||||
|
payAutoRefreshRunningRef.current = true;
|
||||||
|
try {
|
||||||
|
Taro.setStorageSync(PAY_REFRESH_HANDLED_KEY, fromPayAt);
|
||||||
|
// 支付后水票可能异步入账:自动再刷新几次,避免用户手动下拉刷新。
|
||||||
|
for (const delayMs of [800, 1500, 2500]) {
|
||||||
|
await sleep(delayMs);
|
||||||
|
await reloadTickets(true);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
payAutoRefreshRunningRef.current = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await reloadOrders(true);
|
||||||
|
}
|
||||||
|
})();
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user