import { useState, useCallback } from "react"; import { Table, Select, Button, Modal, Form, Space, Popconfirm, message, DatePicker, } from "antd"; import { PlusOutlined, CloseCircleOutlined } from "@ant-design/icons"; import type { ColumnsType, TablePaginationConfig } from "antd/es/table"; import { useNavigate, useSearchParams } from "react-router-dom"; import { consultationApi, type Session, type CreateSessionReq, } from "../../api/health/consultations"; import { StatusTag } from "./components/StatusTag"; import { PatientSelect } from "./components/PatientSelect"; import { DoctorSelect } from "./components/DoctorSelect"; import { ExportButton } from "./components/ExportButton"; import { AuthButton } from "../../components/AuthButton"; import { PageContainer } from "../../components/PageContainer"; import { EntityName } from "../../components/EntityName"; import { formatDateTime } from "../../utils/format"; import { usePaginatedData } from "../../hooks/usePaginatedData"; import { useDictionary } from "../../hooks/useDictionary"; const STATUS_OPTIONS = [ { value: "waiting", label: "等待中" }, { value: "active", label: "进行中" }, { value: "closed", label: "已关闭" }, ]; const CONSULTATION_TYPE_FALLBACK = [ { value: "customer_service", label: "客服咨询" }, { value: "medical", label: "医疗咨询" }, { value: "health_consultation", label: "健康咨询" }, { value: "online", label: "在线咨询" }, { value: "phone", label: "电话咨询" }, { value: "doctor", label: "医生咨询" }, { value: "follow_up", label: "随访咨询" }, ]; const CONSULTATION_TYPE_MAP: Record = { customer_service: "客服咨询", medical: "医疗咨询", health_consultation: "健康咨询", online: "在线咨询", phone: "电话咨询", doctor: "医生咨询", follow_up: "随访咨询", }; interface ConsultationFilters { status?: string; dateRange?: [string, string]; } export default function ConsultationList() { const { options: CONSULTATION_TYPE_OPTIONS } = useDictionary( "health_consultation_type", CONSULTATION_TYPE_FALLBACK, ); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const urlPatientId = searchParams.get("patient_id"); // Close session const [closingId, setClosingId] = useState(null); // Create modal const [createOpen, setCreateOpen] = useState(false); const [createLoading, setCreateLoading] = useState(false); const [createForm] = Form.useForm(); // --- Paginated data with usePaginatedData --- const fetchFn = useCallback( async (page: number, pageSize: number, filters: ConsultationFilters) => { const params: Record = { page, page_size: pageSize }; if (filters.status) params.status = filters.status; if (urlPatientId) params.patient_id = urlPatientId; if (filters.dateRange) { params.created_start = filters.dateRange[0]; params.created_end = filters.dateRange[1]; } return consultationApi.listSessions( params as Parameters[0], ); }, [urlPatientId], ); const { data: sessions, total, page, loading, filters, setFilters, refresh, } = usePaginatedData(fetchFn, { pageSize: 20, defaultFilters: {}, }); // --- Handlers --- const handleTableChange = (pagination: TablePaginationConfig) => { refresh(pagination.current ?? 1); }; // Create session const handleCreate = async () => { try { const values = await createForm.validateFields(); setCreateLoading(true); await consultationApi.createSession(values); message.success("咨询会话创建成功"); setCreateOpen(false); createForm.resetFields(); refresh(page); } catch (err: unknown) { if (err && typeof err === "object" && "errorFields" in err) return; message.error("创建咨询会话失败"); } finally { setCreateLoading(false); } }; // Close session const handleClose = async (session: Session) => { setClosingId(session.id); try { await consultationApi.closeSession(session.id, { version: session.version, }); message.success("会话已关闭"); refresh(page); } catch { message.error("关闭会话失败"); } finally { setClosingId(null); } }; // Row click -> navigate to detail const handleRowClick = (record: Session) => { navigate(`/health/consultations/${record.id}`); }; // Export params const exportParams: Record = {}; if (filters.status) exportParams.status = filters.status; // --- Columns --- const columns: ColumnsType = [ { title: "患者", dataIndex: "patient_name", key: "patient_name", width: 140, render: (_: unknown, record: Session) => ( ), }, { title: "医护", dataIndex: "doctor_name", key: "doctor_name", width: 140, render: (_: unknown, record: Session) => ( ), }, { title: "咨询类型", dataIndex: "consultation_type", key: "consultation_type", width: 110, render: (v: string) => CONSULTATION_TYPE_MAP[v] || v, }, { title: "状态", dataIndex: "status", key: "status", width: 100, render: (status: string) => , }, { title: "未读(患者/医护)", key: "unread", width: 140, render: (_: unknown, record: Session) => ( {record.unread_count_patient} / {record.unread_count_doctor} ), }, { title: "最后消息时间", dataIndex: "last_message_at", key: "last_message_at", width: 160, render: (v: string | undefined) => formatDateTime(v), }, { title: "创建时间", dataIndex: "created_at", key: "created_at", width: 160, render: (v: string) => formatDateTime(v), }, { title: "操作", key: "actions", width: 120, render: (_: unknown, record: Session) => ( {record.status !== "closed" && ( handleClose(record)} okText="确认" cancelText="取消" > )} ), }, ]; return ( ); }