fix: chat history persists, reuse active consultation, load messages properly

This commit is contained in:
MingNian
2026-05-22 10:48:14 +08:00
parent a9d70aa130
commit 4a525124c5
5 changed files with 83 additions and 79 deletions

View File

@@ -1,5 +1,6 @@
import { useEffect, useState, useRef } from 'react';
import { useEffect, useState, useRef, useCallback } from 'react';
import { PageHeader } from '@/components/layout/PageHeader';
import { api } from '@/services/api-client';
import * as consultationService from '@/services/consultation.service';
import type { Consultation, ConsultationMessage, Doctor } from '@/types';
import { formatRelative } from '@/utils/format';
@@ -13,51 +14,45 @@ export function ChatPage() {
const [sending, setSending] = useState(false);
const bottomRef = useRef<HTMLDivElement>(null);
const loadMessages = useCallback((cid: string) => {
api.get<ConsultationMessage[]>(`/api/consultations/${cid}/messages`)
.then((res) => setMessages(res.data))
.catch(() => {});
}, []);
useEffect(() => {
// Get the first available doctor
consultationService.getDoctors().then((docs) => {
if (docs.length > 0) {
const doc = docs[0];
setDoctor(doc);
// Find or create consultation
consultationService.getConsultation(doc.id).then(async (c) => {
if (c) {
setConsultation(c);
loadMessages(c.id);
} else {
const newC = await consultationService.startConsultation(doc.id, '在线咨询');
setConsultation(newC);
}
consultationService.startConsultation(doc.id, '在线咨询').then((c) => {
setConsultation(c);
loadMessages(c.id);
});
}
});
}, []);
const loadMessages = (cid: string) => {
import('@/services/api-client').then(({ api }) => {
api.get<ConsultationMessage[]>(`/api/consultations/${cid}/messages`)
.then((res) => setMessages(res.data));
});
};
}, [loadMessages]);
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
// Poll every 3s
useEffect(() => {
// Poll for new messages every 3 seconds
if (!consultation?.id) return;
const timer = setInterval(() => loadMessages(consultation.id), 3000);
return () => clearInterval(timer);
}, [consultation?.id]);
}, [consultation?.id, loadMessages]);
const handleSend = async () => {
if (!text.trim() || !consultation || sending) return;
setSending(true);
const msgText = text;
setText('');
const sent = await consultationService.sendMessage(consultation.id, msgText);
setMessages((prev) => [...prev, sent]);
try {
const sent = await consultationService.sendMessage(consultation.id, msgText);
setMessages((prev) => [...prev, sent]);
} catch { /* ignore */ }
setSending(false);
};
@@ -71,10 +66,7 @@ export function ChatPage() {
</div>
)}
{messages.map((msg) => (
<div
key={msg.id}
className={`${styles.bubble} ${msg.senderRole === 'patient' ? styles.patient : styles.doctor}`}
>
<div key={msg.id} className={`${styles.bubble} ${msg.senderRole === 'patient' ? styles.patient : styles.doctor}`}>
<div className={styles.bubbleContent}>{msg.content}</div>
<div className={styles.bubbleTime}>{formatRelative(msg.createdAt)}</div>
</div>
@@ -82,16 +74,9 @@ export function ChatPage() {
<div ref={bottomRef} />
</div>
<div className={styles.inputBar}>
<input
className={styles.input}
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="输入消息..."
onKeyDown={(e) => e.key === 'Enter' && handleSend()}
/>
<button className={styles.sendBtn} onClick={handleSend} disabled={sending}>
</button>
<input className={styles.input} value={text} onChange={(e) => setText(e.target.value)}
placeholder="输入消息..." onKeyDown={(e) => e.key === 'Enter' && handleSend()} />
<button className={styles.sendBtn} onClick={handleSend} disabled={sending}></button>
</div>
</div>
);