fix: prevent duplicate consultations with db unique constraint, frontend init once guard, chat history preserved

This commit is contained in:
MingNian
2026-05-22 11:20:48 +08:00
parent 8caa374699
commit 90615a6cb3
2 changed files with 33 additions and 4 deletions

View File

@@ -41,7 +41,19 @@ public class ConsultationService(AppDbContext db)
Subject = subject, Subject = subject,
}; };
db.Consultations.Add(consultation); db.Consultations.Add(consultation);
try
{
await db.SaveChangesAsync(); await db.SaveChangesAsync();
}
catch (DbUpdateException)
{
// Race condition: another request created one between our check and save
// The unique index on (PatientId, DoctorId) where Status='active' caught it
db.ChangeTracker.Clear();
var retry = await db.Consultations
.FirstOrDefaultAsync(c => c.PatientId == patientId && c.DoctorId == doctorId && c.Status == "active");
return retry!;
}
return consultation; return consultation;
} }

View File

@@ -13,6 +13,7 @@ export function ChatPage() {
const [text, setText] = useState(''); const [text, setText] = useState('');
const [sending, setSending] = useState(false); const [sending, setSending] = useState(false);
const bottomRef = useRef<HTMLDivElement>(null); const bottomRef = useRef<HTMLDivElement>(null);
const initRef = useRef(false);
const loadMessages = useCallback((cid: string) => { const loadMessages = useCallback((cid: string) => {
api.get<ConsultationMessage[]>(`/api/consultations/${cid}/messages`) api.get<ConsultationMessage[]>(`/api/consultations/${cid}/messages`)
@@ -20,17 +21,33 @@ export function ChatPage() {
.catch(() => {}); .catch(() => {});
}, []); }, []);
// Init once - prevent Strict Mode double-fire
useEffect(() => { useEffect(() => {
if (initRef.current) return;
initRef.current = true;
consultationService.getDoctors().then((docs) => { consultationService.getDoctors().then((docs) => {
if (docs.length > 0) { if (docs.length > 0) {
const doc = docs[0]; const doc = docs[0];
setDoctor(doc); setDoctor(doc);
// Find existing active consultation first
api.get<Consultation[]>('/api/consultations').then((res) => {
const existing = (res.data as Record<string, unknown>[]).find(
(c) => c.doctorId === doc.id && c.status === 'active'
);
if (existing) {
setConsultation(existing as unknown as Consultation);
loadMessages((existing as Record<string, string>).id);
} else {
// Create new only if none exists
consultationService.startConsultation(doc.id, '在线咨询').then((c) => { consultationService.startConsultation(doc.id, '在线咨询').then((c) => {
setConsultation(c); setConsultation(c);
loadMessages(c.id); loadMessages(c.id);
}); });
} }
}); });
}
});
}, [loadMessages]); }, [loadMessages]);
useEffect(() => { useEffect(() => {