import { postOrderErpTicketsGetStatus, postOrderErpTicketsGetType, postOrderErpTicketsSearch, postOrderErpTicketsUpdate, postServiceOrderQuerySalesCode, } from '@/services'; import { enumToSelect } from '@/utils'; import dayjs from '@/utils/time'; import { ActionType, EditableProTable, ProColumns, } from '@ant-design/pro-components'; import { Button, Select, Space, Table, Tag } from 'antd'; import { useEffect, useRef, useState } from 'react'; import AddTicketsModal from './components/addTicketsModal'; import DeleteFlowButton from './components/deleteFlowModal'; import DeleteButton from './components/deleteModal'; import ReSetPeopleModal from './components/reSetPeopleModal'; import ReadModal from './components/readModal'; import SolveModal from './components/solveModal'; import './index.less'; const TicketsPage = () => { const [assignPeopleOptions, setAssignPeopleOptions] = useState([]); useEffect(() => { const fetchAssignPeopleOptions = async () => { try { const res = await postServiceOrderQuerySalesCode(); const options = res.data?.map((item) => ({ label: item.userName, value: item.userName, })); setAssignPeopleOptions(options || []); } catch (error) { console.error('Failed to fetch assign people options:', error); } }; fetchAssignPeopleOptions(); }, []); const ref = useRef<ActionType>({ reload: () => { // implementation for reload }, reloadAndRest: () => { // implementation for reloadAndRest }, reset: () => { // implementation for reset }, startEditable: () => { // implementation for startEditable }, cancelEditable: () => { // implementation for cancelEditable }, }); function reload() { ref.current.reload(); } type ticketItem = { id?: number; origin?: string; detailText?: string; type?: string; typeText?: string; assignPeople?: string; status?: string; statusText?: string; annexUrl?: string; annexName?: string; resolveTime?: Date; createByName?: string; createTime?: Date; paths?: string[]; }; const columns: ProColumns<ticketItem>[] = [ { title: '序号', dataIndex: 'index', valueType: 'index', width: 70, }, { title: 'ID', dataIndex: 'id', key: 'id', valueType: 'index', hideInSearch: true, hideInTable: true, }, { title: '工单来源', dataIndex: 'origin', width: 200, key: 'origin', fieldProps: { placeholder: '请输入工单来源', }, disable: true, onFilter: true, ellipsis: true, }, { title: '工单详情', dataIndex: 'detailText', width: 400, key: 'detailText', hideInSearch: true, disable: true, onFilter: true, ellipsis: true, }, { title: '工单类型', dataIndex: 'typeText', width: 120, key: 'typeText', hideInSearch: true, disable: true, onFilter: true, ellipsis: true, render: (_, record) => { if (record.type !== null) { if (record.type === 'DEMAND') { return <Tag color="blue">{record.typeText}</Tag>; } if (record.type === 'ADVICE') { return <Tag color="green">{record.typeText}</Tag>; } if (record.type === 'QUESTION') { return <Tag color="red">{record.typeText}</Tag>; } } }, }, { title: '工单类型', dataIndex: 'type', width: 120, key: 'type', valueType: 'select', request: async () => { const ticketsType = await postOrderErpTicketsGetType(); return enumToSelect(ticketsType.data); }, hideInTable: true, }, { title: '附件', dataIndex: 'annexName', width: 120, key: 'annexName', disable: true, onFilter: true, ellipsis: true, hideInSearch: true, render: (_, record) => { if (record.id && record.annexUrl !== null) { return <a href={record.annexUrl}>{record.annexName}</a>; } }, }, { title: '指派人员', dataIndex: 'assignPeople', width: 120, key: 'assignPeople', request: async () => { const res = await postServiceOrderQuerySalesCode(); let map = []; res.data?.forEach((item) => { map.push({ label: item.userName, value: item.userName }); }); return map; }, hideInTable: true, }, { title: '指派人员', dataIndex: 'assignPeople', width: 120, key: 'assignPeople', hideInSearch: true, disable: true, onFilter: true, ellipsis: true, render: (_, record) => ( <Select disabled={record.status === 'SOLVED'} // defaultValue={record.assignPeople} value={record.assignPeople} style={{ width: '100%' }} options={assignPeopleOptions} onChange={(newValue) => { record.assignPeople = newValue; postOrderErpTicketsUpdate({ data: { ...record }, }); reload(); }} /> ), }, { title: '工单状态', dataIndex: 'statusText', width: 120, key: 'statusText', hideInSearch: true, disable: true, onFilter: true, ellipsis: true, render: (_, record) => { if (record.status !== null) { if (record.status === 'SOLVED') { return <Tag color="green">{record.statusText}</Tag>; } if (record.status === 'PENDING') { return <Tag color="red">{record.statusText}</Tag>; } } }, }, { title: '工单状态', dataIndex: 'status', width: 120, key: 'status', valueType: 'select', request: async () => { const statusType = await postOrderErpTicketsGetStatus(); return enumToSelect(statusType.data); }, hideInTable: true, }, { title: '创建人', dataIndex: 'createByName', width: 120, key: 'createByName', fieldProps: { placeholder: '请输入选择创建人', }, hideInSearch: true, disable: true, onFilter: true, ellipsis: true, }, { title: '创建日期', dataIndex: 'createTime', key: 'createTime', valueType: 'dateTimeRange', fieldProps: { placeholder: '请选择创建时间', }, hideInTable: true, }, { title: '创建日期', dataIndex: 'createTime', key: 'createTime', hideInSearch: true, width: 130, render: (text) => (text ? dayjs(text).format('YYYY-MM-DD HH:mm') : ''), }, { title: '处理时间', dataIndex: 'resolveTime', key: 'resolveTime', valueType: 'dateTimeRange', fieldProps: { placeholder: '请选择处理时间', }, hideInTable: true, }, { title: '处理时间', dataIndex: 'resolveTime', key: 'resolveTime', hideInSearch: true, width: 130, render: (text) => (text ? dayjs(text).format('YYYY-MM-DD HH:mm') : ''), }, { title: '操作', valueType: 'option', fixed: 'right', width: 160, disable: true, onFilter: true, ellipsis: true, render: (_text, record) => { if (record?.id) { const hasResolvePermission = record?.paths?.includes('RESOLVE'); const hasDeletePermission = record?.paths?.includes('DELETE'); return ( <> {hasResolvePermission && ( <> <SolveModal id={record.id} toReload={reload}></SolveModal> </> )} <> <ReadModal id={record.id} toReload={reload}></ReadModal> </> {hasDeletePermission && ( <> <DeleteButton ids={[record.id]} toReload={reload} ></DeleteButton> </> )} </> ); } return null; }, }, ]; return ( <> <EditableProTable<ticketItem> className="tickets-index" columnEmptyText="" columns={columns} rowSelection={{ selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT], defaultSelectedRowKeys: [], }} cardBordered actionRef={ref} scroll={{ x: 1400 }} recordCreatorProps={false} request={async (params) => { let res = await postOrderErpTicketsSearch({ data: { ...params }, }); return { data: res.data.data || [], total: res?.data?.total || 0, }; }} editable={{ type: 'multiple', }} columnsState={{ persistenceKey: 'pro-table-singe-demos', persistenceType: 'localStorage', defaultValue: { option: { fixed: 'right', disable: true }, }, }} rowKey="id" search={{ labelWidth: 'auto', }} options={{ setting: { listsHeight: 800, }, }} form={{ syncToUrl: (values, type) => { if (type === 'get') { return { ...values, created_at: [values.startTime, values.endTime], }; } return values; }, }} pagination={{ pageSize: 10, }} dateFormatter="string" headerTitle={[]} tableAlertOptionRender={({ selectedRows, onCleanSelected }) => { return ( <Space size={16}> <ReSetPeopleModal ids={selectedRows .filter((item) => item.status === 'PENDING') .map((item) => item.id)} toReload={reload} /> <DeleteFlowButton ids={selectedRows .filter((item) => item.status === 'PENDING') .map((item: any) => { return item.id; })} toReload={reload} ></DeleteFlowButton> <Button type="primary" onClick={onCleanSelected}> 取消选中 </Button> </Space> ); }} toolBarRender={() => [ <> <AddTicketsModal toReload={reload}></AddTicketsModal> </>, ]} /> </> ); }; export default TicketsPage;