import { useEffect, useRef, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { ArrowLeft, AlertTriangle } from 'lucide-react'; import { api, ApiError } from '../api/client'; import type { KnowledgeCitation } from '../api/types'; import './ChatPage.css'; interface Message { id: string; role: 'user' | 'assistant'; text: string; grounded?: boolean; citations?: KnowledgeCitation[]; } const AUTHORITY_LABEL: Record = { authoritative: '权威', reference: '参考', self: '自建', }; const WELCOME: Message = { id: 'welcome', role: 'assistant', text: '你好呀~我是你的孕期助手。关于孕期饮食、监测、不适或注意事项,都可以问我。我会附上知识来源,遇到拿不准的会建议你及时就医。', }; export function ChatPage(): JSX.Element { const navigate = useNavigate(); const location = useLocation(); const initialQuestion = (location.state as { initialQuestion?: string } | null)?.initialQuestion; const [messages, setMessages] = useState([WELCOME]); const [input, setInput] = useState(''); const [sending, setSending] = useState(false); const listRef = useRef(null); const askedInitial = useRef(false); async function send(question: string): Promise { const q = question.trim(); if (!q || sending) return; const userMsg: Message = { id: `u-${Date.now()}`, role: 'user', text: q }; setMessages((prev) => [...prev, userMsg]); setInput(''); setSending(true); try { const answer = await api.ask(q); setMessages((prev) => [ ...prev, { id: `a-${Date.now()}`, role: 'assistant', text: answer.answer, grounded: answer.grounded, citations: answer.citations, }, ]); } catch (err) { setMessages((prev) => [ ...prev, { id: `e-${Date.now()}`, role: 'assistant', text: err instanceof ApiError ? err.message : '抱歉,我暂时没能回答,请稍后再试。', }, ]); } finally { setSending(false); } } useEffect(() => { if (initialQuestion && !askedInitial.current) { askedInitial.current = true; void send(initialQuestion); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [initialQuestion]); useEffect(() => { listRef.current?.scrollTo({ top: listRef.current.scrollHeight, behavior: 'smooth' }); }, [messages]); return (
孕期助手
{messages.map((m) => (

{m.text}

{m.role === 'assistant' && m.grounded === false && (

这个问题我暂时没有权威依据,建议你咨询医生或管理师。

)} {m.citations && m.citations.length > 0 && (

来源

{m.citations.map((c) => (
{AUTHORITY_LABEL[c.authority] ?? c.authority} {c.title} · {c.source}
))}
)}
))} {sending && (
正在思考…
)}
{ e.preventDefault(); void send(input); }} > setInput(e.target.value)} placeholder="问问孕期助手…" />
); }