fix(ticket): guard stale responses and stale hours

This commit is contained in:
mlogclub
2026-05-02 20:20:30 +08:00
parent 8a8b92a307
commit 8102f89308
5 changed files with 61 additions and 21 deletions
@@ -1,6 +1,6 @@
"use client"
import { useCallback, useEffect, useState } from "react"
import { useCallback, useEffect, useRef, useState } from "react"
import { MessageSquareTextIcon, RefreshCcwIcon, SendIcon, UserRoundIcon } from "lucide-react"
import { toast } from "sonner"
@@ -75,20 +75,32 @@ export function TicketDetailDialog({
const [assignOpen, setAssignOpen] = useState(false)
const [editOpen, setEditOpen] = useState(false)
const [editSaving, setEditSaving] = useState(false)
const loadSeqRef = useRef(0)
const loadDetail = useCallback(async () => {
const seq = loadSeqRef.current + 1
loadSeqRef.current = seq
if (!open || !ticketId) {
setDetail(null)
setLoading(false)
return
}
setLoading(true)
try {
const data = await fetchTicketDetail(ticketId)
if (loadSeqRef.current !== seq) {
return
}
setDetail(data)
} catch (error) {
if (loadSeqRef.current !== seq) {
return
}
toast.error(error instanceof Error ? error.message : "加载工单详情失败")
} finally {
setLoading(false)
if (loadSeqRef.current === seq) {
setLoading(false)
}
}
}, [open, ticketId])
+13 -2
View File
@@ -1,7 +1,7 @@
"use client"
import { PlusIcon, RefreshCcwIcon, SearchXIcon } from "lucide-react"
import { useCallback, useEffect, useMemo, useState } from "react"
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { toast } from "sonner"
import { OptionCombobox, type ComboboxOption } from "@/components/option-combobox"
@@ -119,6 +119,7 @@ export default function TicketsPage() {
const [detailOpen, setDetailOpen] = useState(false)
const [createOpen, setCreateOpen] = useState(false)
const [savingCreate, setSavingCreate] = useState(false)
const loadSeqRef = useRef(0)
const quickViews = useMemo(
() =>
@@ -138,6 +139,8 @@ export default function TicketsPage() {
const allPageSelected = tickets.length > 0 && tickets.every((ticket) => selectedTicketIds.has(ticket.id))
const loadData = useCallback(async () => {
const seq = loadSeqRef.current + 1
loadSeqRef.current = seq
setLoading(true)
try {
const staleThreshold = Number(staleHours)
@@ -166,13 +169,21 @@ export default function TicketsPage() {
fetchTickets(query),
fetchTicketSummary({ staleHours: staleThreshold }),
])
if (loadSeqRef.current !== seq) {
return
}
setTickets(Array.isArray(ticketData.results) ? ticketData.results : [])
setSummary(summaryData ?? emptySummary)
setSelectedTicketIds(new Set())
} catch (error) {
if (loadSeqRef.current !== seq) {
return
}
toast.error(error instanceof Error ? error.message : "加载工单失败")
} finally {
setLoading(false)
if (loadSeqRef.current === seq) {
setLoading(false)
}
}
}, [assigneeId, keyword, quickView, staleHours, tagId])