refactor: single doctor, direct chat, any phone login, UI polish, fix animations
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { PageHeader } from '@/components/layout/PageHeader';
|
||||
import * as consultationService from '@/services/consultation.service';
|
||||
import type { Consultation, ConsultationMessage, Doctor } from '@/types';
|
||||
@@ -7,7 +6,6 @@ import { formatRelative } from '@/utils/format';
|
||||
import styles from './ChatPage.module.css';
|
||||
|
||||
export function ChatPage() {
|
||||
const { doctorId } = useParams<{ doctorId: string }>();
|
||||
const [doctor, setDoctor] = useState<Doctor | null>(null);
|
||||
const [consultation, setConsultation] = useState<Consultation | null>(null);
|
||||
const [messages, setMessages] = useState<ConsultationMessage[]>([]);
|
||||
@@ -16,36 +14,43 @@ export function ChatPage() {
|
||||
const bottomRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (doctorId) {
|
||||
consultationService.getDoctor(doctorId).then((d) => setDoctor(d || null));
|
||||
consultationService.getConsultation(doctorId).then(async (c) => {
|
||||
if (c) {
|
||||
setConsultation(c);
|
||||
} else {
|
||||
const newC = await consultationService.startConsultation(doctorId);
|
||||
setConsultation(newC);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [doctorId]);
|
||||
|
||||
// Fetch messages when consultation is loaded
|
||||
useEffect(() => {
|
||||
if (consultation?.id) {
|
||||
consultationService.getDoctorReply(consultation.id).then(() => {
|
||||
// The messages are fetched as a side effect; fetch them directly
|
||||
import('@/services/api-client').then(({ api }) => {
|
||||
api.get<ConsultationMessage[]>(`/api/consultations/${consultation.id}/messages`)
|
||||
.then((res) => setMessages(res.data));
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}, [consultation?.id]);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
const loadMessages = (cid: string) => {
|
||||
import('@/services/api-client').then(({ api }) => {
|
||||
api.get<ConsultationMessage[]>(`/api/consultations/${cid}/messages`)
|
||||
.then((res) => setMessages(res.data));
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
}, [messages]);
|
||||
|
||||
useEffect(() => {
|
||||
// Poll for new messages every 3 seconds
|
||||
if (!consultation?.id) return;
|
||||
const timer = setInterval(() => loadMessages(consultation.id), 3000);
|
||||
return () => clearInterval(timer);
|
||||
}, [consultation?.id]);
|
||||
|
||||
const handleSend = async () => {
|
||||
if (!text.trim() || !consultation || sending) return;
|
||||
setSending(true);
|
||||
@@ -54,22 +59,17 @@ export function ChatPage() {
|
||||
const sent = await consultationService.sendMessage(consultation.id, msgText);
|
||||
setMessages((prev) => [...prev, sent]);
|
||||
setSending(false);
|
||||
// Poll for doctor reply after delay
|
||||
setTimeout(async () => {
|
||||
const reply = await consultationService.getDoctorReply(consultation.id);
|
||||
if (reply) {
|
||||
setMessages((prev) => {
|
||||
if (prev.find((m) => m.id === reply.id)) return prev;
|
||||
return [...prev, reply];
|
||||
});
|
||||
}
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.page}>
|
||||
<PageHeader title={doctor?.name || '咨询'} />
|
||||
<PageHeader title={doctor?.name || '在线问诊'} />
|
||||
<div className={styles.messages}>
|
||||
{messages.length === 0 && (
|
||||
<div style={{ textAlign: 'center', color: '#9CA3AF', marginTop: 40, fontSize: 14 }}>
|
||||
您好,我是{doctor?.name || '医生'},请问有什么可以帮您?
|
||||
</div>
|
||||
)}
|
||||
{messages.map((msg) => (
|
||||
<div
|
||||
key={msg.id}
|
||||
@@ -90,7 +90,7 @@ export function ChatPage() {
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleSend()}
|
||||
/>
|
||||
<button className={styles.sendBtn} onClick={handleSend} disabled={sending}>
|
||||
{sending ? '...' : '发送'}
|
||||
↑
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user