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 } 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 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}分钟`; }; return ( <> 订单管理 - 翻译服务管理系统
{/* 页面标题和操作 */}

订单管理

管理所有翻译服务订单,包括订单状态、支付状态和服务详情。

{/* 搜索和过滤器 */}
handleSearch(e.target.value)} />
{/* 批量操作 */} {selectedOrders.length > 0 && (
已选择 {selectedOrders.length} 个订单
)} {/* 订单列表 */}
{loading ? (
) : ( <>
{orders.map((order) => ( ))}
0} onChange={handleSelectAll} /> 订单信息 用户/翻译员 服务详情 时间/时长 状态 金额 操作
handleSelectOrder(order.id)} />
{order.order_number}
创建于 {formatTime(order.created_at)}
{order.notes && (
备注: {order.notes}
)}
用户: {order.user_name}
{order.user_email}
翻译员: {order.interpreter_name}
{getServiceTypeIcon(order.service_type)} {getServiceTypeText(order.service_type)}
{order.language_pair}
{new Date(order.start_time).toLocaleString('zh-CN')}
{formatDuration(order.duration)}
{getStatusText(order.status)}
{getPaymentStatusText(order.payment_status)}
¥{order.amount}
{/* 分页 */} {totalPages > 1 && (

显示第 {(currentPage - 1) * pageSize + 1} 到{' '} {Math.min(currentPage * pageSize, totalCount)} 项, 共 {totalCount}

)} )}
); }