import { useEffect, useState } from 'react'; import { Card, Table, Input, Button, Space, message, Modal, Tag, Form, Select, Pagination, } from 'antd'; import { ToolOutlined, PlusOutlined, DeleteOutlined, EyeOutlined, } from '@ant-design/icons'; import { useNavigate } from 'react-router-dom'; import { projectOrdersApi, authApi } from '@/services/api'; import type { ProjectOrder, ProjectOrderStatus, ProjectType, CreateProjectOrderRequest, } from '@/types'; const WORK_ORDER_STATUS_LABEL: Record = { created: '待处理', pending_completion: '待完成确认', closed: '已完成', }; const WORK_ORDER_STATUS_COLOR: Record = { created: 'default', pending_completion: 'processing', closed: 'success', }; const PROJECT_TYPE_LABEL: Record = { survey: '项目勘察', implementation: '工程实施', maintenance: '定期维保', business: '商务合作', other: '其他', }; function ProjectOrdersPage() { const navigate = useNavigate(); const currentUser = authApi.getCurrentUser(); const isAdmin = currentUser?.role === 'admin'; const [orders, setOrders] = useState([]); const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const [limit, setLimit] = useState(10); const [total, setTotal] = useState(0); const [search, setSearch] = useState(''); const [workOrderStatus, setWorkOrderStatus] = useState(); const [projectType, setProjectType] = useState(); const [mineOnly, setMineOnly] = useState(false); const [createModalVisible, setCreateModalVisible] = useState(false); const [creating, setCreating] = useState(false); const [createForm] = Form.useForm(); const loadOrders = async () => { setLoading(true); try { const result = await projectOrdersApi.list({ page, limit, search: search || undefined, workOrderStatus, projectType, mine: isAdmin ? mineOnly : undefined, }); setOrders(result.data || []); setTotal(result.pagination?.total || 0); } catch (err: any) { message.error(err?.response?.data?.message || err.message || '加载工单列表失败'); setOrders([]); } finally { setLoading(false); } }; useEffect(() => { loadOrders(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [page, limit, search, workOrderStatus, projectType, mineOnly]); const handleCreate = async (values: CreateProjectOrderRequest) => { setCreating(true); try { const order = await projectOrdersApi.create(values); message.success(`工单创建成功:${order.serialNumber}`); setCreateModalVisible(false); createForm.resetFields(); navigate(`/admin/project-orders/${order.serialNumber}`); } catch (err: any) { message.error(err?.response?.data?.message || err.message || '创建失败'); } finally { setCreating(false); } }; const handleDelete = (order: ProjectOrder) => { Modal.confirm({ title: '确认删除', content: `确定要删除工单 ${order.serialNumber} 吗?此操作不可恢复!`, okText: '确定', okType: 'danger', cancelText: '取消', onOk: async () => { try { await projectOrdersApi.delete(order.serialNumber); message.success('删除成功'); loadOrders(); } catch (err: any) { message.error(err?.response?.data?.message || err.message || '删除失败'); } }, }); }; const columns = [ { title: '工单号', dataIndex: 'serialNumber', key: 'serialNumber', width: 180, render: (sn: string) => ( {sn} ), }, { title: '公司名称', dataIndex: 'companyName', key: 'companyName', }, { title: '现场联系人', dataIndex: 'contactName', key: 'contactName', width: 100, }, { title: '项目类型', dataIndex: 'projectType', key: 'projectType', width: 100, render: (type: ProjectType) => PROJECT_TYPE_LABEL[type] || type, }, { title: '工程师', key: 'technician', width: 120, render: (_: any, record: ProjectOrder) => record.technician?.name || '-', }, { title: '工单状态', dataIndex: 'workOrderStatus', key: 'workOrderStatus', width: 130, render: (status: ProjectOrderStatus) => ( {WORK_ORDER_STATUS_LABEL[status]} ), }, { title: '创建时间', dataIndex: 'createdAt', key: 'createdAt', width: 170, render: (date: string) => new Date(date).toLocaleString('zh-CN'), }, { title: '操作', key: 'actions', width: 180, render: (_: any, record: ProjectOrder) => ( {isAdmin && ( )} ), }, ]; return (
项目工单 } extra={isAdmin ? ( ) : null} > { setPage(1); setSearch(v); }} onChange={(e) => { if (!e.target.value) { setPage(1); setSearch(''); } }} /> { setPage(1); setProjectType(v); }} options={(Object.keys(PROJECT_TYPE_LABEL) as ProjectType[]).map((k) => ({ value: k, label: PROJECT_TYPE_LABEL[k], }))} /> {isAdmin && ( )}
{ setPage(newPage); setLimit(newLimit); }} showSizeChanger showTotal={(t) => `共计 ${t} 条记录`} />
{ setCreateModalVisible(false); createForm.resetFields(); }} footer={null} width={560} >