import { useEffect, useState } from 'react' import { SpinLoading, Toast, Tag } from 'antd-mobile' interface Conversation { sessionId: string customerId: string customerName: string staffName: string currentStage: string stageConfidence: number roundCount: number intentCount: number startTime: string endTime: string contextSummary: string keyEvents: string } interface ConversationTurn { turnNumber: number studentContent: string seatContent: string turnType: string primaryIntent: string intentConfidence: number studentEmotion: string createdAt: string } interface Props { userInfo?: any } export default function ConversationAnalysis({ userInfo }: Props) { const [conversations, setConversations] = useState([]) const [selectedSession, setSelectedSession] = useState('') const [turns, setTurns] = useState([]) const [loading, setLoading] = useState(false) const [loadingTurns, setLoadingTurns] = useState(false) const customerId = localStorage.getItem('current_customer_id') || 'wx_001' const corpId = userInfo?.corpId || 'wwd483c2fba24ae30a' useEffect(() => { loadConversations() }, []) useEffect(() => { if (selectedSession) { loadTurns(selectedSession) } }, [selectedSession]) const loadConversations = async () => { setLoading(true) try { const res = await fetch(`/api/v1/conversations?customerId=${customerId}&corpId=${corpId}`) const data = await res.json() if (data.code === 0 && data.data) { setConversations(data.data) if (data.data.length > 0) { setSelectedSession(data.data[0].sessionId) } } } catch (e) { Toast.show({ content: '加载会话失败', icon: 'fail' }) } finally { setLoading(false) } } const loadTurns = async (sessionId: string) => { setLoadingTurns(true) try { const res = await fetch(`/api/v1/conversations/${sessionId}/turns`) const data = await res.json() if (data.code === 0 && data.data) { setTurns(data.data) } } catch (e) { Toast.show({ content: '加载对话失败', icon: 'fail' }) } finally { setLoadingTurns(false) } } const getStageLabel = (stage?: string) => { const map: Record = { 'STAGE-01': '开场白', 'STAGE-02': '需求挖掘', 'STAGE-03': '方案呈现', 'STAGE-04': '异议处理', 'STAGE-05': '促成签约', 'STAGE-06': '跟进维护', 'STAGE-07': '转介绍', 'STAGE-08': '沉默激活' } return map[stage || ''] || stage || '未知' } const getEmotionLabel = (emotion?: string) => { const map: Record = { 'POSITIVE': { text: '积极', color: '#52c41a' }, 'NEUTRAL': { text: '中性', color: '#faad14' }, 'NEGATIVE': { text: '消极', color: '#ff4d4f' } } return map[emotion || ''] || { text: emotion || '未知', color: '#999' } } const getTurnTypeLabel = (type?: string) => { const map: Record = { 'QUERY': '咨询', 'OBJECTION': '异议', 'INTEREST': '兴趣' } return map[type || ''] || type || '其他' } if (loading) { return (
) } const currentConv = conversations.find(c => c.sessionId === selectedSession) return (
{/* 会话选择器 */} {conversations.length > 1 && (
{conversations.map(conv => (
setSelectedSession(conv.sessionId)} style={{ padding: '6px 12px', borderRadius: 16, fontSize: 12, whiteSpace: 'nowrap', cursor: 'pointer', background: selectedSession === conv.sessionId ? '#1677ff' : '#f0f0f0', color: selectedSession === conv.sessionId ? '#fff' : '#666' }} > {new Date(conv.startTime).toLocaleDateString()} ({conv.roundCount}轮)
))}
)} {/* 会话概览 */} {currentConv && (
会话概览 {getStageLabel(currentConv.currentStage)}
轮次: {currentConv.roundCount}
意图: {currentConv.intentCount}
置信度: {Math.round((currentConv.stageConfidence || 0) * 100)}%
{currentConv.contextSummary && (
摘要: {currentConv.contextSummary}
)}
)} {/* 对话轮次 */}
对话记录
{loadingTurns ? (
) : turns.length === 0 ? (
暂无对话记录
) : (
{turns.map((turn) => { const emotion = getEmotionLabel(turn.studentEmotion) return (
{/* 轮次标识 */}
第{turn.turnNumber}轮 {emotion.text} {getTurnTypeLabel(turn.turnType)} {turn.primaryIntent && ( {turn.primaryIntent} )}
{/* 学员消息 */} {turn.studentContent && (
学员
{turn.studentContent}
)} {/* 顾问回复 */} {turn.seatContent && (
顾问
{turn.seatContent}
)}
) })}
)}
) }