feat(ticket): 添加票券自动重试加载功能

- 引入 ticketAutoRetryCountRef 和 ticketAutoRetryTimerRef 引用计数器
- 实现购买票券后异步重试刷新逻辑,最多重试4次
- 添加延迟重试机制,间隔时间分别为800ms、1500ms、2500ms、4000ms
- 在页面显示时重置重试计数器并清除现有定时器
- 添加清理函数确保组件卸载时清除定时器
- 当检测到可用票券时不进行重试并重置计数器
This commit is contained in:
2026-03-11 17:33:33 +08:00
parent 8b902be603
commit 0628a0f6b4

View File

@@ -75,6 +75,8 @@ const OrderConfirm = () => {
const [ticketLoading, setTicketLoading] = useState(false)
const [ticketLoaded, setTicketLoaded] = useState(false)
const noTicketPromptedRef = useRef(false)
const ticketAutoRetryCountRef = useRef(0)
const ticketAutoRetryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
// Delivery range (geofence): block ordering if address/current location is outside.
const [fences, setFences] = useState<ShopStoreFence[]>([])
@@ -207,6 +209,39 @@ const OrderConfirm = () => {
return !!userId && ticketLoaded && !ticketLoading && usableTickets.length === 0
}, [ticketLoaded, ticketLoading, usableTickets.length, userId])
// After buying tickets and redirecting here, some backends may issue tickets asynchronously.
// If opened with a `goodsId`, retry a few times to refresh tickets.
useEffect(() => {
if (isEditMode) return
if (!numericGoodsId) return
if (!ticketLoaded || ticketLoading) return
if (usableTickets.length > 0) {
ticketAutoRetryCountRef.current = 0
return
}
if (ticketAutoRetryCountRef.current >= 4) return
if (ticketAutoRetryTimerRef.current) return
const delays = [800, 1500, 2500, 4000]
const delay = delays[ticketAutoRetryCountRef.current] ?? 2500
ticketAutoRetryCountRef.current += 1
ticketAutoRetryTimerRef.current = setTimeout(async () => {
ticketAutoRetryTimerRef.current = null
await loadUserTickets()
}, delay)
}, [isEditMode, numericGoodsId, ticketLoaded, ticketLoading, usableTickets.length])
useEffect(() => {
return () => {
if (ticketAutoRetryTimerRef.current) {
clearTimeout(ticketAutoRetryTimerRef.current)
ticketAutoRetryTimerRef.current = null
}
}
}, [])
const maxQuantity = useMemo(() => {
const stockMax = goods?.stock ?? 999
if (!isEditMode) return Math.max(0, Math.min(stockMax, availableTicketTotal))
@@ -784,6 +819,11 @@ const OrderConfirm = () => {
useDidShow(() => {
// 返回/切换到该页面时,刷新一下当前已选门店
setSelectedStore(getSelectedStoreFromStorage())
ticketAutoRetryCountRef.current = 0
if (ticketAutoRetryTimerRef.current) {
clearTimeout(ticketAutoRetryTimerRef.current)
ticketAutoRetryTimerRef.current = null
}
loadAllData({ silent: hasInitialLoadedRef.current })
})