'use client' import { useState } from 'react' import { useRouter } from 'next/navigation' import { Button, Input, Select } from '@/components/ui' import { Search } from 'lucide-react' import SelectWithInput from '@/components/ui/SelectWithInput' interface TicketFormProps { initialData?: Record ticketId?: number } const defaultFaultCategories = [ '硬件故障', '软件故障', '网络故障', '存储故障', '电源故障', '无故障', '其他', ] const defaultTicketTypes = ['OEM诊断', 'OEM维修'] const defaultFaultSubcategories = [ 'GPU故障', 'CPU故障', '内存故障', '硬盘故障', '电源故障', '风扇故障', 'OS崩溃', '驱动故障', '软件崩溃', '配置错误', '网络丢包', '网络中断', '存储掉盘', 'RAID故障', '无故障', '其他', ] export default function TicketForm({ initialData, ticketId }: TicketFormProps) { const router = useRouter() const isEdit = !!ticketId const timeRe = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(:\d{2})?$/ const [loading, setLoading] = useState(false) const [error, setError] = useState('') const [assignTimeError, setAssignTimeError] = useState('') const [closeTimeError, setCloseTimeError] = useState('') const [lookingUp, setLookingUp] = useState(false) const [form, setForm] = useState({ ticket_no: String(initialData?.id || ''), device_ip: (initialData?.device_ip as string) || '', device_sn: (initialData?.device_sn as string) || '', device_name: (initialData?.device_name as string) || '', content: (initialData?.content as string) || '', assign_time: (initialData?.assign_time as string) || (() => { const d = new Date(Date.now() + 8 * 60 * 60 * 1000); return d.toISOString().slice(0, 10) + ' ' + d.toISOString().slice(11, 19); })(), ticket_type: (initialData?.ticket_type as string) || '', fault_category: (initialData?.fault_category as string) || '', fault_subcategory: (initialData?.fault_subcategory as string) || '', responsibility: (initialData?.responsibility as string) || '', current_status: (initialData?.current_status as string) || 'open', counted_in_sla: (initialData?.counted_in_sla as number) ?? 1, close_time: (initialData?.close_time as string) || '', duration_minutes: (initialData?.duration_minutes as number) || '', process_summary: (initialData?.process_summary as string) || '', conclusion: (initialData?.conclusion as string) || '', parts_replaced: (initialData?.parts_replaced as string) || '', parts_name: (initialData?.parts_name as string) || '', }) const handleIpLookup = async () => { if (!form.device_ip) return setLookingUp(true) try { const res = await fetch(`/api/assets/lookup?ip=${encodeURIComponent(form.device_ip)}`) if (res.ok) { const data = await res.json() if (data.asset) { setForm(prev => ({ ...prev, device_name: data.asset.node_name || prev.device_name, device_sn: data.asset.serial_number || prev.device_sn, })) } } } catch { // ignore } finally { setLookingUp(false) } } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (form.assign_time && !timeRe.test(form.assign_time)) { setError('派单时间格式不正确,请使用 YYYY-MM-DD HH:mm:ss 格式') return } if (form.close_time && !timeRe.test(form.close_time)) { setError('结单时间格式不正确,请使用 YYYY-MM-DD HH:mm:ss 格式') return } setError('') setLoading(true) try { const url = isEdit ? `/api/tickets/${ticketId}` : '/api/tickets' const method = isEdit ? 'PUT' : 'POST' const body: Record = { ...form } if (body.duration_minutes === '') delete body.duration_minutes else body.duration_minutes = Number(body.duration_minutes) const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) const data = await res.json() if (!res.ok) { setError(data.error || '操作失败'); return } router.push(isEdit ? `/tickets/${ticketId}` : '/tickets/pending') router.refresh() } catch { setError('网络错误') } finally { setLoading(false) } } const update = (key: string, value: string | number) => setForm(prev => ({ ...prev, [key]: value })) return (
{/* 工单号独占一行 */}
update('ticket_no', e.target.value)} placeholder="14位工单号(如 20260420039303)" disabled={isEdit} required />
update('device_ip', e.target.value)} placeholder="输入设备 IP" />
update('device_name', e.target.value)} placeholder="自动填充或手动输入" /> update('device_sn', e.target.value)} placeholder="自动填充或手动输入" /> update('ticket_type', val)} options={defaultTicketTypes} placeholder="请选择或输入工单类型..." /> update('fault_category', val)} options={defaultFaultCategories} placeholder="请选择或输入故障大类..." /> update('fault_subcategory', val)} options={defaultFaultSubcategories} placeholder="请选择或输入故障小类..." /> update('responsibility', e.target.value)} /> { update('assign_time', e.target.value); setAssignTimeError('') }} onBlur={() => { if (form.assign_time && !timeRe.test(form.assign_time)) setAssignTimeError('时间格式不正确,请使用 YYYY-MM-DD HH:mm:ss 格式') }} placeholder="2026-05-02 18:34:36" error={assignTimeError} />