feat: render real ticket event timeline

This commit is contained in:
hailin
2026-07-02 10:36:52 +08:00
parent a6df96ebb0
commit 399a5bdb73
8 changed files with 196 additions and 30 deletions

View File

@@ -12,12 +12,12 @@ import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import { SolutionLinkPanel } from '@/features/solutions/SolutionLinkPanel'
import { getTicket, transitionTicket } from './api'
import { getTicket, listTicketEvents, transitionTicket } from './api'
import { TicketComments } from './TicketComments'
import { TicketMetaPanel } from './TicketMetaPanel'
import { TicketStatusTimeline } from './TicketStatusTimeline'
import { TicketTransitionDialog } from './TicketTransitionDialog'
import type { Ticket, TicketStatus } from './types'
import type { Ticket, TicketEvent, TicketStatus } from './types'
const NEXT_STATUSES: Record<TicketStatus, TicketStatus[]> = {
pending_info: ['pending', 'closed'],
@@ -45,6 +45,7 @@ function getStatusActionLabel(currentStatus: TicketStatus, targetStatus: TicketS
export function TicketDetailPage({ ticketId }: { ticketId: number }) {
const [ticket, setTicket] = React.useState<Ticket | null>(null)
const [events, setEvents] = React.useState<TicketEvent[]>([])
const [error, setError] = React.useState('')
const [targetStatus, setTargetStatus] = React.useState<TicketStatus | null>(null)
const [targetActionLabel, setTargetActionLabel] = React.useState('')
@@ -55,8 +56,13 @@ export function TicketDetailPage({ ticketId }: { ticketId: number }) {
getTicket(ticketId)
.then(setTicket)
.catch((reason: unknown) => setError(reason instanceof Error ? reason.message : '加载失败'))
refreshEvents()
}, [ticketId])
function refreshEvents() {
listTicketEvents(ticketId).then(setEvents).catch(() => setEvents([]))
}
function openTransition(status: TicketStatus) {
setTargetStatus(status)
if (ticket) {
@@ -72,6 +78,7 @@ export function TicketDetailPage({ ticketId }: { ticketId: number }) {
const updated = await transitionTicket(ticket.id, status, remark)
setTicket(updated)
setTransitionError('')
refreshEvents()
} catch (reason) {
setTransitionError(reason instanceof Error ? reason.message : '状态流转失败')
throw reason
@@ -146,8 +153,8 @@ export function TicketDetailPage({ ticketId }: { ticketId: number }) {
<AppSection title="问题描述">
<p className="whitespace-pre-wrap text-sm leading-6">{ticket.description}</p>
</AppSection>
<TicketStatusTimeline ticket={ticket} />
<TicketComments ticketId={ticket.id} />
<TicketStatusTimeline ticket={ticket} events={events} />
<TicketComments ticketId={ticket.id} onCommentAdded={refreshEvents} />
</AppDetailLayout>
{transitionError ? <AppEmptyState title="状态流转失败" description={transitionError} /> : null}
<TicketTransitionDialog