feat: add ticket solution closure loop

This commit is contained in:
hailin
2026-07-02 10:11:30 +08:00
parent 0ea4a3c853
commit a6df96ebb0
18 changed files with 435 additions and 68 deletions

View File

@@ -22,7 +22,7 @@ import type { Ticket, TicketStatus } from './types'
const NEXT_STATUSES: Record<TicketStatus, TicketStatus[]> = {
pending_info: ['pending', 'closed'],
pending: ['in_progress', 'closed'],
in_progress: ['pending_confirm', 'resolved', 'closed'],
in_progress: ['pending_confirm'],
pending_confirm: ['resolved', 'in_progress', 'closed'],
resolved: ['closed'],
closed: []
@@ -36,10 +36,18 @@ const STATUS_ACTIONS: Partial<Record<TicketStatus, { label: string; icon: React.
closed: { label: '关闭工单', icon: XCircle }
}
function getStatusActionLabel(currentStatus: TicketStatus, targetStatus: TicketStatus) {
if (targetStatus === 'closed' && currentStatus !== 'resolved') {
return '取消工单'
}
return STATUS_ACTIONS[targetStatus]?.label ?? '调整状态'
}
export function TicketDetailPage({ ticketId }: { ticketId: number }) {
const [ticket, setTicket] = React.useState<Ticket | null>(null)
const [error, setError] = React.useState('')
const [targetStatus, setTargetStatus] = React.useState<TicketStatus | null>(null)
const [targetActionLabel, setTargetActionLabel] = React.useState('')
const [transitionDialogOpen, setTransitionDialogOpen] = React.useState(false)
const [transitionError, setTransitionError] = React.useState('')
@@ -51,6 +59,9 @@ export function TicketDetailPage({ ticketId }: { ticketId: number }) {
function openTransition(status: TicketStatus) {
setTargetStatus(status)
if (ticket) {
setTargetActionLabel(getStatusActionLabel(ticket.status, status))
}
setTransitionError('')
setTransitionDialogOpen(true)
}
@@ -107,7 +118,7 @@ export function TicketDetailPage({ ticketId }: { ticketId: number }) {
onClick={() => openTransition(status)}
>
{Icon ? <Icon className="size-4" /> : null}
{action?.label ?? '调整状态'}
{getStatusActionLabel(ticket.status, status)}
</Button>
)
})}
@@ -132,7 +143,7 @@ export function TicketDetailPage({ ticketId }: { ticketId: number }) {
</>
}
>
<AppSection title="问题描述" description="当前工单的核心问题、影响场景和处理上下文。">
<AppSection title="问题描述">
<p className="whitespace-pre-wrap text-sm leading-6">{ticket.description}</p>
</AppSection>
<TicketStatusTimeline ticket={ticket} />
@@ -142,6 +153,7 @@ export function TicketDetailPage({ ticketId }: { ticketId: number }) {
<TicketTransitionDialog
open={transitionDialogOpen}
status={targetStatus}
actionLabel={targetActionLabel}
onOpenChange={setTransitionDialogOpen}
onSubmit={handleTransition}
/>