import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import Head from 'next/head'; import DashboardLayout from '../../components/Layout/DashboardLayout'; import { toast } from 'react-hot-toast'; import { MagnifyingGlassIcon, PlusIcon, EyeIcon, PencilIcon, TrashIcon, ClockIcon, CheckCircleIcon, XCircleIcon, ExclamationTriangleIcon, ArrowDownTrayIcon, PhoneIcon, VideoCameraIcon, UserIcon, LanguageIcon, CalendarIcon, CurrencyDollarIcon, DocumentTextIcon, PlayIcon, PauseIcon, StopIcon, XMarkIcon } from '@heroicons/react/24/outline'; import { getDemoData } from '../../lib/demo-data'; import { formatTime } from '../../lib/utils'; interface Order { id: string; order_number: string; user_name: string; user_email: string; interpreter_name: string; language_pair: string; service_type: 'audio' | 'video' | 'onsite'; start_time: string; end_time?: string; duration?: number; status: 'pending' | 'confirmed' | 'in_progress' | 'completed' | 'cancelled' | 'failed'; amount: number; payment_status: 'pending' | 'paid' | 'failed' | 'refunded'; notes?: string; created_at: string; updated_at: string; } interface OrderFilters { search: string; status: string; service_type: string; payment_status: string; date_range: string; } export default function Orders() { const router = useRouter(); const [orders, setOrders] = useState([]); const [loading, setLoading] = useState(true); const [selectedOrders, setSelectedOrders] = useState([]); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [totalCount, setTotalCount] = useState(0); const [filters, setFilters] = useState({ search: '', status: '', service_type: '', payment_status: '', date_range: '' }); // 添加模态框状态 const [showCreateOrderModal, setShowCreateOrderModal] = useState(false); const [newOrder, setNewOrder] = useState({ user_name: '', user_email: '', interpreter_name: '', language_pair: '', service_type: 'audio' as 'audio' | 'video' | 'onsite', start_time: '', duration: 60, amount: 0, notes: '' }); const [isSubmitting, setIsSubmitting] = useState(false); const pageSize = 10; useEffect(() => { fetchOrders(); }, [currentPage, filters]); const fetchOrders = async () => { try { setLoading(true); // 模拟加载延迟 await new Promise(resolve => setTimeout(resolve, 800)); // 使用演示数据 const mockOrders: Order[] = [ { id: '1', order_number: 'ORD-2024-001', user_name: '张先生', user_email: 'zhang@example.com', interpreter_name: '王翻译', language_pair: '中文 ↔ 英文', service_type: 'video', start_time: '2024-01-20T14:00:00Z', end_time: '2024-01-20T15:30:00Z', duration: 90, status: 'completed', amount: 450, payment_status: 'paid', notes: '商务会议翻译,需要专业术语支持', created_at: '2024-01-19T10:00:00Z', updated_at: '2024-01-20T15:30:00Z' }, { id: '2', order_number: 'ORD-2024-002', user_name: '李女士', user_email: 'li@example.com', interpreter_name: '陈口译', language_pair: '中文 ↔ 日文', service_type: 'audio', start_time: '2024-01-21T09:00:00Z', status: 'confirmed', amount: 300, payment_status: 'paid', notes: '医疗咨询翻译', created_at: '2024-01-20T08:00:00Z', updated_at: '2024-01-20T08:30:00Z' }, { id: '3', order_number: 'ORD-2024-003', user_name: '王总', user_email: 'wangzong@example.com', interpreter_name: '刘同传', language_pair: '中文 ↔ 英文', service_type: 'onsite', start_time: '2024-01-22T10:00:00Z', end_time: '2024-01-22T16:00:00Z', duration: 360, status: 'in_progress', amount: 1800, payment_status: 'paid', notes: '大型会议同声传译', created_at: '2024-01-18T15:00:00Z', updated_at: '2024-01-22T10:00:00Z' }, { id: '4', order_number: 'ORD-2024-004', user_name: '赵经理', user_email: 'zhao@example.com', interpreter_name: '李专家', language_pair: '中文 ↔ 韩文', service_type: 'video', start_time: '2024-01-20T16:00:00Z', status: 'cancelled', amount: 200, payment_status: 'refunded', notes: '客户临时取消', created_at: '2024-01-19T12:00:00Z', updated_at: '2024-01-20T14:00:00Z' }, { id: '5', order_number: 'ORD-2024-005', user_name: '孙先生', user_email: 'sun@example.com', interpreter_name: '张语言', language_pair: '中文 ↔ 德文', service_type: 'audio', start_time: '2024-01-23T13:00:00Z', status: 'pending', amount: 250, payment_status: 'pending', notes: '技术文档翻译咨询', created_at: '2024-01-20T16:00:00Z', updated_at: '2024-01-20T16:00:00Z' }, { id: '6', order_number: 'ORD-2024-006', user_name: '周女士', user_email: 'zhou@example.com', interpreter_name: '赵技术', language_pair: '中文 ↔ 英文', service_type: 'video', start_time: '2024-01-19T11:00:00Z', end_time: '2024-01-19T12:00:00Z', duration: 60, status: 'failed', amount: 200, payment_status: 'failed', notes: '技术问题导致服务中断', created_at: '2024-01-18T20:00:00Z', updated_at: '2024-01-19T12:00:00Z' } ]; // 应用过滤器 let filteredOrders = mockOrders; if (filters.search) { filteredOrders = filteredOrders.filter(order => order.order_number.toLowerCase().includes(filters.search.toLowerCase()) || order.user_name.toLowerCase().includes(filters.search.toLowerCase()) || order.user_email.toLowerCase().includes(filters.search.toLowerCase()) || order.interpreter_name.toLowerCase().includes(filters.search.toLowerCase()) || order.language_pair.toLowerCase().includes(filters.search.toLowerCase()) ); } if (filters.status) { filteredOrders = filteredOrders.filter(order => order.status === filters.status); } if (filters.service_type) { filteredOrders = filteredOrders.filter(order => order.service_type === filters.service_type); } if (filters.payment_status) { filteredOrders = filteredOrders.filter(order => order.payment_status === filters.payment_status); } // 分页 const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; const paginatedOrders = filteredOrders.slice(startIndex, endIndex); setOrders(paginatedOrders); setTotalCount(filteredOrders.length); setTotalPages(Math.ceil(filteredOrders.length / pageSize)); } catch (error) { console.error('Failed to fetch orders:', error); toast.error('加载订单失败'); } finally { setLoading(false); } }; const handleSearch = (value: string) => { setFilters(prev => ({ ...prev, search: value })); setCurrentPage(1); }; const handleFilterChange = (key: keyof OrderFilters, value: string) => { setFilters(prev => ({ ...prev, [key]: value })); setCurrentPage(1); }; const handleSelectOrder = (orderId: string) => { setSelectedOrders(prev => prev.includes(orderId) ? prev.filter(id => id !== orderId) : [...prev, orderId] ); }; const handleSelectAll = () => { if (selectedOrders.length === orders.length) { setSelectedOrders([]); } else { setSelectedOrders(orders.map(order => order.id)); } }; const handleBulkAction = async (action: 'confirm' | 'cancel' | 'delete') => { if (selectedOrders.length === 0) { toast.error('请选择要操作的订单'); return; } try { const actionText = action === 'confirm' ? '确认' : action === 'cancel' ? '取消' : '删除'; toast.loading(`正在${actionText}订单...`, { id: 'bulk-action' }); // 模拟操作延迟 await new Promise(resolve => setTimeout(resolve, 1500)); toast.success(`成功${actionText} ${selectedOrders.length} 个订单`, { id: 'bulk-action' }); setSelectedOrders([]); fetchOrders(); } catch (error) { toast.error('操作失败', { id: 'bulk-action' }); } }; const handleExport = async () => { try { toast.loading('正在导出订单数据...', { id: 'export' }); // 模拟导出延迟 await new Promise(resolve => setTimeout(resolve, 2000)); toast.success('订单数据导出成功', { id: 'export' }); } catch (error) { toast.error('导出失败', { id: 'export' }); } }; const getStatusColor = (status: string) => { switch (status) { case 'completed': return 'text-green-800 bg-green-100'; case 'confirmed': return 'text-blue-800 bg-blue-100'; case 'in_progress': return 'text-yellow-800 bg-yellow-100'; case 'pending': return 'text-gray-800 bg-gray-100'; case 'cancelled': return 'text-red-800 bg-red-100'; case 'failed': return 'text-red-800 bg-red-100'; default: return 'text-gray-800 bg-gray-100'; } }; const getStatusText = (status: string) => { switch (status) { case 'completed': return '已完成'; case 'confirmed': return '已确认'; case 'in_progress': return '进行中'; case 'pending': return '待确认'; case 'cancelled': return '已取消'; case 'failed': return '失败'; default: return status; } }; const getPaymentStatusColor = (status: string) => { switch (status) { case 'paid': return 'text-green-800 bg-green-100'; case 'pending': return 'text-yellow-800 bg-yellow-100'; case 'failed': return 'text-red-800 bg-red-100'; case 'refunded': return 'text-purple-800 bg-purple-100'; default: return 'text-gray-800 bg-gray-100'; } }; const getPaymentStatusText = (status: string) => { switch (status) { case 'paid': return '已支付'; case 'pending': return '待支付'; case 'failed': return '支付失败'; case 'refunded': return '已退款'; default: return status; } }; const getServiceTypeIcon = (type: string) => { switch (type) { case 'audio': return ; case 'video': return ; case 'onsite': return ; default: return ; } }; const getServiceTypeText = (type: string) => { switch (type) { case 'audio': return '语音通话'; case 'video': return '视频通话'; case 'onsite': return '现场翻译'; default: return type; } }; const formatDuration = (minutes?: number) => { if (!minutes) return '-'; const hours = Math.floor(minutes / 60); const mins = minutes % 60; if (hours > 0) { return `${hours}小时${mins}分钟`; } return `${mins}分钟`; }; // 创建订单提交函数 const handleCreateOrder = async (e: React.FormEvent) => { e.preventDefault(); setIsSubmitting(true); try { // 模拟API调用 await new Promise(resolve => setTimeout(resolve, 1000)); // 创建新订单对象 const newOrderData: Order = { id: Date.now().toString(), order_number: `ORD-${Date.now()}`, ...newOrder, status: 'pending', payment_status: 'pending', created_at: new Date().toISOString(), updated_at: new Date().toISOString() }; // 添加到订单列表 setOrders(prev => [newOrderData, ...prev]); // 重置表单 setNewOrder({ user_name: '', user_email: '', interpreter_name: '', language_pair: '', service_type: 'audio', start_time: '', duration: 60, amount: 0, notes: '' }); // 关闭模态框 setShowCreateOrderModal(false); // 可以添加成功提示 alert('订单创建成功!'); } catch (error) { console.error('创建订单失败:', error); alert('创建订单失败,请重试'); } finally { setIsSubmitting(false); } }; // 创建订单模态框组件 const CreateOrderModal = () => (

创建新订单

setNewOrder({...newOrder, user_name: e.target.value})} />
setNewOrder({...newOrder, user_email: e.target.value})} />
setNewOrder({...newOrder, interpreter_name: e.target.value})} />
setNewOrder({...newOrder, language_pair: e.target.value})} />
setNewOrder({...newOrder, duration: parseInt(e.target.value) || 60})} />
setNewOrder({...newOrder, start_time: e.target.value})} />
setNewOrder({...newOrder, amount: parseFloat(e.target.value) || 0})} />