feat: add ticket solution closure loop
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user