fix(ticket): invalidate reopened detail actions
This commit is contained in:
@@ -76,15 +76,16 @@ export function TicketDetailDialog({
|
|||||||
const [editOpen, setEditOpen] = useState(false)
|
const [editOpen, setEditOpen] = useState(false)
|
||||||
const [editSaving, setEditSaving] = useState(false)
|
const [editSaving, setEditSaving] = useState(false)
|
||||||
const loadSeqRef = useRef(0)
|
const loadSeqRef = useRef(0)
|
||||||
|
const dialogSeqRef = useRef(0)
|
||||||
const currentTicketIdRef = useRef<number | null>(null)
|
const currentTicketIdRef = useRef<number | null>(null)
|
||||||
currentTicketIdRef.current = open ? ticketId : null
|
currentTicketIdRef.current = open ? ticketId : null
|
||||||
|
|
||||||
function isCurrentTicket(targetTicketId: number) {
|
function isCurrentOperation(targetTicketId: number, dialogSeq: number) {
|
||||||
return currentTicketIdRef.current === targetTicketId
|
return currentTicketIdRef.current === targetTicketId && dialogSeqRef.current === dialogSeq
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadDetail = useCallback(async (targetTicketId = ticketId) => {
|
const loadDetail = useCallback(async (targetTicketId = ticketId, dialogSeq = dialogSeqRef.current) => {
|
||||||
if (currentTicketIdRef.current !== targetTicketId) {
|
if (!targetTicketId || !isCurrentOperation(targetTicketId, dialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const seq = loadSeqRef.current + 1
|
const seq = loadSeqRef.current + 1
|
||||||
@@ -97,12 +98,12 @@ export function TicketDetailDialog({
|
|||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const data = await fetchTicketDetail(targetTicketId)
|
const data = await fetchTicketDetail(targetTicketId)
|
||||||
if (loadSeqRef.current !== seq || currentTicketIdRef.current !== targetTicketId) {
|
if (loadSeqRef.current !== seq || !isCurrentOperation(targetTicketId, dialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setDetail(data)
|
setDetail(data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (loadSeqRef.current !== seq || currentTicketIdRef.current !== targetTicketId) {
|
if (loadSeqRef.current !== seq || !isCurrentOperation(targetTicketId, dialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toast.error(error instanceof Error ? error.message : "加载工单详情失败")
|
toast.error(error instanceof Error ? error.message : "加载工单详情失败")
|
||||||
@@ -114,10 +115,9 @@ export function TicketDetailDialog({
|
|||||||
}, [open, ticketId])
|
}, [open, ticketId])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void loadDetail()
|
dialogSeqRef.current += 1
|
||||||
}, [loadDetail])
|
setDetail(null)
|
||||||
|
setLoading(false)
|
||||||
useEffect(() => {
|
|
||||||
setStatusSaving(null)
|
setStatusSaving(null)
|
||||||
setProgressSaving(false)
|
setProgressSaving(false)
|
||||||
setEditSaving(false)
|
setEditSaving(false)
|
||||||
@@ -126,30 +126,35 @@ export function TicketDetailDialog({
|
|||||||
setProgressContent("")
|
setProgressContent("")
|
||||||
}, [open, ticketId])
|
}, [open, ticketId])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
void loadDetail(ticketId, dialogSeqRef.current)
|
||||||
|
}, [loadDetail, ticketId])
|
||||||
|
|
||||||
async function handleStatusChange(status: TicketStatus) {
|
async function handleStatusChange(status: TicketStatus) {
|
||||||
if (!detail || detail.ticket.status === status) {
|
if (!detail || detail.ticket.status === status) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const activeTicketId = detail.ticket.id
|
const activeTicketId = detail.ticket.id
|
||||||
|
const activeDialogSeq = dialogSeqRef.current
|
||||||
setStatusSaving(status)
|
setStatusSaving(status)
|
||||||
try {
|
try {
|
||||||
await changeTicketStatus({ ticketId: activeTicketId, status })
|
await changeTicketStatus({ ticketId: activeTicketId, status })
|
||||||
if (!isCurrentTicket(activeTicketId)) {
|
if (!isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toast.success("工单状态已更新")
|
toast.success("工单状态已更新")
|
||||||
await loadDetail(activeTicketId)
|
await loadDetail(activeTicketId, activeDialogSeq)
|
||||||
if (!isCurrentTicket(activeTicketId)) {
|
if (!isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
onChanged()
|
onChanged()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isCurrentTicket(activeTicketId)) {
|
if (!isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toast.error(error instanceof Error ? error.message : "更新工单状态失败")
|
toast.error(error instanceof Error ? error.message : "更新工单状态失败")
|
||||||
} finally {
|
} finally {
|
||||||
if (isCurrentTicket(activeTicketId)) {
|
if (isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
setStatusSaving(null)
|
setStatusSaving(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,6 +165,7 @@ export function TicketDetailDialog({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const activeTicketId = detail.ticket.id
|
const activeTicketId = detail.ticket.id
|
||||||
|
const activeDialogSeq = dialogSeqRef.current
|
||||||
const content = progressContent.trim()
|
const content = progressContent.trim()
|
||||||
if (!content) {
|
if (!content) {
|
||||||
toast.error("请填写处理进展")
|
toast.error("请填写处理进展")
|
||||||
@@ -171,23 +177,23 @@ export function TicketDetailDialog({
|
|||||||
ticketId: activeTicketId,
|
ticketId: activeTicketId,
|
||||||
content,
|
content,
|
||||||
})
|
})
|
||||||
if (!isCurrentTicket(activeTicketId)) {
|
if (!isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toast.success("处理进展已记录")
|
toast.success("处理进展已记录")
|
||||||
setProgressContent("")
|
setProgressContent("")
|
||||||
await loadDetail(activeTicketId)
|
await loadDetail(activeTicketId, activeDialogSeq)
|
||||||
if (!isCurrentTicket(activeTicketId)) {
|
if (!isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
onChanged()
|
onChanged()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isCurrentTicket(activeTicketId)) {
|
if (!isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toast.error(error instanceof Error ? error.message : "记录处理进展失败")
|
toast.error(error instanceof Error ? error.message : "记录处理进展失败")
|
||||||
} finally {
|
} finally {
|
||||||
if (isCurrentTicket(activeTicketId)) {
|
if (isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
setProgressSaving(false)
|
setProgressSaving(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,11 +201,12 @@ export function TicketDetailDialog({
|
|||||||
|
|
||||||
async function handleAssigned() {
|
async function handleAssigned() {
|
||||||
const activeTicketId = ticket?.id
|
const activeTicketId = ticket?.id
|
||||||
if (!activeTicketId || !isCurrentTicket(activeTicketId)) {
|
const activeDialogSeq = dialogSeqRef.current
|
||||||
|
if (!activeTicketId || !isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await loadDetail(activeTicketId)
|
await loadDetail(activeTicketId, activeDialogSeq)
|
||||||
if (!isCurrentTicket(activeTicketId)) {
|
if (!isCurrentOperation(activeTicketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
onChanged()
|
onChanged()
|
||||||
@@ -210,26 +217,27 @@ export function TicketDetailDialog({
|
|||||||
toast.error("请选择工单")
|
toast.error("请选择工单")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const activeDialogSeq = dialogSeqRef.current
|
||||||
setEditSaving(true)
|
setEditSaving(true)
|
||||||
try {
|
try {
|
||||||
await updateTicket(payload)
|
await updateTicket(payload)
|
||||||
if (!isCurrentTicket(payload.ticketId)) {
|
if (!isCurrentOperation(payload.ticketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toast.success("工单已更新")
|
toast.success("工单已更新")
|
||||||
setEditOpen(false)
|
setEditOpen(false)
|
||||||
await loadDetail(payload.ticketId)
|
await loadDetail(payload.ticketId, activeDialogSeq)
|
||||||
if (!isCurrentTicket(payload.ticketId)) {
|
if (!isCurrentOperation(payload.ticketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
onChanged()
|
onChanged()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isCurrentTicket(payload.ticketId)) {
|
if (!isCurrentOperation(payload.ticketId, activeDialogSeq)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toast.error(error instanceof Error ? error.message : "更新工单失败")
|
toast.error(error instanceof Error ? error.message : "更新工单失败")
|
||||||
} finally {
|
} finally {
|
||||||
if (isCurrentTicket(payload.ticketId)) {
|
if (isCurrentOperation(payload.ticketId, activeDialogSeq)) {
|
||||||
setEditSaving(false)
|
setEditSaving(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user