feat: redesign ticket detail experience

This commit is contained in:
hailin
2026-07-01 15:21:58 +08:00
parent 382237e9f5
commit 3aff628f52
6 changed files with 282 additions and 53 deletions

View File

@@ -0,0 +1,92 @@
import * as React from 'react'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from '@/components/ui/dialog'
import { Textarea } from '@/components/ui/textarea'
import type { TicketStatus } from './types'
const STATUS_ACTION_LABELS: Partial<Record<TicketStatus, string>> = {
in_progress: '开始处理',
pending_confirm: '提交确认',
resolved: '标记解决',
closed: '关闭工单'
}
type TicketTransitionDialogProps = {
open: boolean
status: TicketStatus | null
onOpenChange: (open: boolean) => void
onSubmit: (status: TicketStatus, remark: string) => Promise<void>
}
export function TicketTransitionDialog({
open,
status,
onOpenChange,
onSubmit
}: TicketTransitionDialogProps) {
const [remark, setRemark] = React.useState('')
const [submitting, setSubmitting] = React.useState(false)
const actionLabel = status ? STATUS_ACTION_LABELS[status] ?? '调整状态' : '调整状态'
React.useEffect(() => {
if (!open) {
setRemark('')
setSubmitting(false)
}
}, [open])
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault()
if (!status || !remark.trim()) return
setSubmitting(true)
try {
await onSubmit(status, remark.trim())
onOpenChange(false)
} finally {
setSubmitting(false)
}
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-lg">
<form className="grid gap-4" onSubmit={handleSubmit}>
<DialogHeader>
<DialogTitle>{actionLabel}</DialogTitle>
<DialogDescription>请说明本次流转的原因、处理动作或待确认事项。</DialogDescription>
</DialogHeader>
<div className="grid gap-2">
<label className="text-sm font-medium text-foreground" htmlFor="transition-remark">
处理说明
</label>
<Textarea
id="transition-remark"
required
minLength={2}
placeholder="例如:已完成日志排查,定位为配置变更导致,提交业务侧确认。"
value={remark}
onChange={(event) => setRemark(event.target.value)}
/>
</div>
<DialogFooter>
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
取消
</Button>
<Button type="submit" disabled={!remark.trim() || submitting}>
{submitting ? '提交中...' : '确认提交'}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
)
}