import { useState, useEffect, useMemo } from 'react' import { Input, Select, Tag, Empty, Spin } from 'antd' import { SearchOutlined, UserOutlined } from '@ant-design/icons' import { getCustomers, getSession, getSessions, type Customer, type Message, type Session, type SessionEvent, } from '@/services/api' const statusColors: Record = { active: 'blue', waiting: 'orange', ended: 'green', archived: 'default', } const statusLabels: Record = { active: '进行中', ended: '已结束', waiting: '等待中', archived: '已归档', } const priorityLabels: Record = { urgent: '紧急', normal: '普通' } const ChatHistory = () => { const [sessions, setSessions] = useState([]) const [customers, setCustomers] = useState>({}) const [loading, setLoading] = useState(true) const [search, setSearch] = useState('') const [statusFilter, setStatusFilter] = useState() const [priorityFilter, setPriorityFilter] = useState() const [selectedId, setSelectedId] = useState(null) const [messages, setMessages] = useState([]) const [events, setEvents] = useState([]) const [selectedSession, setSelectedSession] = useState(null) const [detailLoading, setDetailLoading] = useState(false) useEffect(() => { loadSessions() }, [statusFilter, priorityFilter]) const loadSessions = async () => { setLoading(true) try { const [sessionRes, customerRes] = await Promise.all([ getSessions({ status: statusFilter, priority: priorityFilter, page: 1, pageSize: 100 }), getCustomers({ page: 1, pageSize: 200 }), ]) const list = Array.isArray(sessionRes.list) ? sessionRes.list : [] setSessions(list) const map = Object.fromEntries((customerRes.list || []).map(c => [c.id, c])) setCustomers(map) if (list.length > 0) { const still = selectedId && list.some(s => s.id === selectedId) if (!still) setSelectedId(list[0].id) } else { setSelectedId(null) } } catch { setSessions([]) } finally { setLoading(false) } } useEffect(() => { if (!selectedId) { setMessages([]) setEvents([]) setSelectedSession(null) return } setDetailLoading(true) getSession(selectedId).then(res => { setMessages(res.data.messages || []) setEvents(res.data.events || []) setSelectedSession(res.data.session || sessions.find(s => s.id === selectedId) || null) }).catch(() => { setMessages([]) setEvents([]) }).finally(() => setDetailLoading(false)) }, [selectedId]) const filtered = useMemo(() => { const keyword = search.trim().toLowerCase() return sessions.filter(s => { if (!keyword) return true const name = customers[s.customer_id]?.name || '' return name.toLowerCase().includes(keyword) || String(s.id).includes(keyword) || String(s.customer_id).includes(keyword) || (s.last_message || '').toLowerCase().includes(keyword) }) }, [sessions, customers, search]) const selected = selectedSession || sessions.find(s => s.id === selectedId) const customer = selected ? customers[selected.customer_id] : null return (
} placeholder="搜索客户/会话/消息" value={search} onChange={e => setSearch(e.target.value)} allowClear size="small" />
({ value: k, label: v }))} />
{loading ? (
) : filtered.map(s => { const name = customers[s.customer_id]?.name || `客户${s.customer_id}` return ( ) })} {!loading && filtered.length === 0 && (
)}
{selected ? (

{customer?.name || `客户${selected.customer_id}`}

{statusLabels[selected.status] || selected.status} {selected.priority === 'urgent' && 紧急}
会话 #{selected.id} {customer?.source ? ` · ${customer.source}` : ''} {' · '} {new Date(selected.created_at).toLocaleString('zh-CN')} {selected.ended_at ? ` ~ ${new Date(selected.ended_at).toLocaleString('zh-CN')}` : ''}
{selected.satisfaction_score != null && (
{'★'.repeat(selected.satisfaction_score)}{'☆'.repeat(Math.max(0, 5 - selected.satisfaction_score))}
满意度评分
{selected.satisfaction_text && (
{selected.satisfaction_text}
)}
)}
消息记录
{detailLoading ? (
) : messages.length === 0 ? ( ) : messages.map(message => { const isAgent = message.sender_type === 'agent' return (
{isAgent ? '客服' : '访客'}
{message.type === 'image' ? ( 图片 ) : (
{message.content}
)}
{new Date(message.sent_at).toLocaleString('zh-CN')}
) })}
{events.length > 0 && (
操作记录
{events.slice().reverse().map(ev => (
{new Date(ev.created_at).toLocaleString('zh-CN')} {ev.action} {ev.detail}
))}
)}
) : (
选择一个对话查看详情
)}
) } export default ChatHistory