|
|
@@ -37,7 +37,6 @@ const { loading, data } = useRequest(getConsultantListMethod, {
|
|
|
}).onSuccess(({ data }) => {
|
|
|
if (data && data.length > 0) {
|
|
|
patients.value = data;
|
|
|
- // 等待响应式更新完成后再选择第一个患者
|
|
|
nextTick(() => {
|
|
|
if (!selectedPatient.value && patients.value.length > 0) {
|
|
|
selectPatient(patients.value[0]);
|
|
|
@@ -45,12 +44,10 @@ const { loading, data } = useRequest(getConsultantListMethod, {
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
-// 搜索关键词
|
|
|
const searchKeyword = ref('');
|
|
|
|
|
|
// 当前选中的患者
|
|
|
const selectedPatient = ref<ConsultantPeopleModel | null>(null);
|
|
|
-// 保存上一次选中患者的 progress 状态,用于检测状态变化
|
|
|
const previousProgress = ref<number | string | undefined>(undefined);
|
|
|
watchDebounced(
|
|
|
searchKeyword,
|
|
|
@@ -60,25 +57,23 @@ watchDebounced(
|
|
|
{ debounce: 500 }
|
|
|
);
|
|
|
|
|
|
-// 当前患者的消息列表
|
|
|
const chatMessages = ref<ChatMessageModel[]>([]);
|
|
|
|
|
|
-// 输入消息
|
|
|
+
|
|
|
const inputMessage = ref('');
|
|
|
|
|
|
-// 最大字数限制
|
|
|
+
|
|
|
const MAX_MESSAGE_LENGTH = 2000;
|
|
|
|
|
|
-// 当前输入字数
|
|
|
+
|
|
|
const currentMessageLength = computed(() => inputMessage.value.length);
|
|
|
|
|
|
-// 待发送的图片列表
|
|
|
+
|
|
|
const pendingImages = ref<string[]>([]);
|
|
|
|
|
|
-// 聊天消息容器引用
|
|
|
+
|
|
|
const chatMessagesRef = ref<HTMLElement | null>(null);
|
|
|
|
|
|
-// 判断是否可以发送消息:咨询中且已转人工
|
|
|
const canSendMessage = computed(() => {
|
|
|
if (selectedPatient.value?.isCanSend) {
|
|
|
return true;
|
|
|
@@ -87,24 +82,18 @@ const canSendMessage = computed(() => {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-// 选择患者
|
|
|
+
|
|
|
function selectPatient(patient: ConsultantPeopleModel) {
|
|
|
selectedPatient.value = patient;
|
|
|
- // 保存当前患者的 progress 状态
|
|
|
previousProgress.value = patient.progress;
|
|
|
- // 加载该患者的聊天记录
|
|
|
loadChatMessages(patient.consultRecordId as number);
|
|
|
- // 清除未读数量
|
|
|
patient.doctorUnreadCount = 0;
|
|
|
}
|
|
|
|
|
|
-// 加载聊天消息(模拟)
|
|
|
async function loadChatMessages(consultRecordId: number) {
|
|
|
- // 这里应该调用 API 加载该患者的聊天记录
|
|
|
const res = await getAllConsultChatListMethod(consultRecordId);
|
|
|
if (res && res.length > 0) {
|
|
|
chatMessages.value = res as unknown as ChatMessageModel[];
|
|
|
- // 加载完成后滚动到底部
|
|
|
nextTick(() => {
|
|
|
scrollToBottom();
|
|
|
});
|
|
|
@@ -124,14 +113,11 @@ async function refreshPatientList() {
|
|
|
const res = await getConsultantListMethod(searchKeyword.value);
|
|
|
if (res && res.length > 0) {
|
|
|
patients.value = res as unknown as ConsultantPeopleModel[];
|
|
|
- // 如果当前有选中的患者,更新选中患者的信息
|
|
|
if (selectedPatient.value?.consultRecordId) {
|
|
|
const updatedPatient = patients.value.find((p) => p.consultRecordId === selectedPatient.value?.consultRecordId);
|
|
|
if (updatedPatient) {
|
|
|
- // 更新选中患者的信息,确保响应式更新
|
|
|
const currentConsultRecordId = selectedPatient.value.consultRecordId;
|
|
|
Object.assign(selectedPatient.value, updatedPatient);
|
|
|
- // 确保 consultRecordId 不变(防止丢失引用)
|
|
|
selectedPatient.value.consultRecordId = currentConsultRecordId;
|
|
|
}
|
|
|
}
|
|
|
@@ -160,15 +146,12 @@ async function pinPatient(patient: ConsultantPeopleModel) {
|
|
|
isCurrentlyPinned = isTop === 'Y';
|
|
|
}
|
|
|
if (isCurrentlyPinned) {
|
|
|
- // 当前已置顶,执行取消置顶
|
|
|
await cancelPinConsultantMethod(patient.consultRecordId as number);
|
|
|
message.success('取消置顶');
|
|
|
} else {
|
|
|
- // 当前未置顶,执行置顶
|
|
|
await pinConsultantMethod(patient.consultRecordId as number);
|
|
|
message.success('置顶成功');
|
|
|
}
|
|
|
- // 刷新患者列表
|
|
|
await refreshPatientList();
|
|
|
} catch (error: any) {
|
|
|
message.error(error.message);
|
|
|
@@ -178,28 +161,23 @@ async function pinPatient(patient: ConsultantPeopleModel) {
|
|
|
// 刷新页面
|
|
|
async function handleRefresh(showMessage = true) {
|
|
|
try {
|
|
|
- // 保存刷新前的 progress 状态
|
|
|
const oldProgress = previousProgress.value;
|
|
|
|
|
|
- // 刷新患者列表
|
|
|
+
|
|
|
await refreshPatientList();
|
|
|
- // 如果有选中的患者,判断是否需要刷新聊天记录
|
|
|
if (selectedPatient.value?.consultRecordId) {
|
|
|
const currentProgress = selectedPatient.value.progress;
|
|
|
- // 检查咨询是否已结束:progress === 1 或 progress === '1' 表示已结束
|
|
|
+
|
|
|
const isConsultEnded = currentProgress == 1 || String(currentProgress) === '1';
|
|
|
- // 检查上一次是否未结束
|
|
|
+
|
|
|
const wasConsultEnded = oldProgress == 1 || String(oldProgress) === '1';
|
|
|
|
|
|
- // 需要刷新的情况:
|
|
|
- // 1. 咨询未结束(正常刷新)
|
|
|
- // 2. 咨询刚刚结束(从进行中变为已结束,需要刷新一次以获取结束消息)
|
|
|
+
|
|
|
const shouldRefresh = !isConsultEnded || (!wasConsultEnded && isConsultEnded);
|
|
|
|
|
|
if (shouldRefresh) {
|
|
|
- // 重新加载聊天记录
|
|
|
await loadChatMessages(selectedPatient.value.consultRecordId);
|
|
|
- // 刷新(获取最新消息)
|
|
|
+
|
|
|
await refreshConsultMethod(selectedPatient.value.consultRecordId.toString());
|
|
|
}
|
|
|
|
|
|
@@ -221,22 +199,19 @@ async function handleRefresh(showMessage = true) {
|
|
|
/**
|
|
|
* 处理图片上传,将文件转换为 Data URL 并添加到预览列表。
|
|
|
* @param {File} file - 用户选择的文件对象。
|
|
|
- * @return {boolean} 返回 false 以阻止默认的自动上传行为。
|
|
|
+ * @return {boolean}
|
|
|
*/
|
|
|
function customUpload(e: any) {
|
|
|
- // 检查是否可以发送消息
|
|
|
if (!canSendMessage.value) {
|
|
|
message.warning('咨询已结束或未转人工,无法发送消息');
|
|
|
return false;
|
|
|
}
|
|
|
UploadIFile(e.file)
|
|
|
.then((res: any) => {
|
|
|
- // 调用实例的成功方法通知组件该文件上传成功
|
|
|
e.onSuccess(res, e);
|
|
|
pendingImages.value.push(res?.url);
|
|
|
})
|
|
|
.catch((err) => {
|
|
|
- // 调用实例的失败方法通知组件该文件上传失败
|
|
|
e.onError(err);
|
|
|
});
|
|
|
}
|
|
|
@@ -257,9 +232,7 @@ async function sendMessage(content?: string, imageUrl?: string) {
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
- // 确定消息内容:如果是图片就放URL,否则放文本内容
|
|
|
const messageContent = imageUrl || content || '';
|
|
|
- // 确定消息类型:图片是2,文本是1
|
|
|
const messageType = imageUrl ? '2' : '1';
|
|
|
let query = {
|
|
|
consultRecordId: selectedPatient.value.consultRecordId,
|
|
|
@@ -269,33 +242,28 @@ async function sendMessage(content?: string, imageUrl?: string) {
|
|
|
// 发送消息
|
|
|
await sendConsultChatMethod(selectedPatient.value.patientId, query);
|
|
|
|
|
|
- // 发送成功后,创建本地消息对象用于显示
|
|
|
const newMessage: ChatMessageModel = {
|
|
|
id: Date.now(),
|
|
|
consultRecordId: selectedPatient.value.consultRecordId,
|
|
|
sendTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
sendType: '2', // 2-医生(人工身份)
|
|
|
messageType: messageType, // 1-文本 2-图片
|
|
|
- messageContent: messageContent, // 图片就放URL,文本就放内容
|
|
|
+ messageContent: messageContent,
|
|
|
};
|
|
|
|
|
|
- // 直接将新消息添加到当前消息列表末尾,避免重新加载导致页面闪烁
|
|
|
chatMessages.value.push(newMessage);
|
|
|
|
|
|
- // 更新患者最后一条消息
|
|
|
if (selectedPatient.value) {
|
|
|
selectedPatient.value.messageType = imageUrl ? 2 : 1;
|
|
|
selectedPatient.value.messageContent = messageContent;
|
|
|
selectedPatient.value.sendTime = dayjs().format('YYYY-MM-DD HH:mm');
|
|
|
}
|
|
|
|
|
|
- // 滚动到底部,显示最新发送的消息
|
|
|
nextTick(() => {
|
|
|
scrollToBottom();
|
|
|
});
|
|
|
} catch (error) {
|
|
|
console.error('发送消息失败:', error);
|
|
|
- // message.error('发送消息失败');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -320,12 +288,10 @@ async function handleSend() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 先发送所有待发送的图片(每条图片单独发送)
|
|
|
for (const imageUrl of pendingImages.value) {
|
|
|
- await sendMessage('', imageUrl); // 正式发送
|
|
|
+ await sendMessage('', imageUrl);
|
|
|
}
|
|
|
|
|
|
- // 如果有文字内容,单独发送文字消息
|
|
|
if (hasText) {
|
|
|
const textContent = inputMessage.value.trim();
|
|
|
if (textContent.length > MAX_MESSAGE_LENGTH) {
|
|
|
@@ -335,7 +301,6 @@ async function handleSend() {
|
|
|
await sendMessage(textContent, undefined); // 正式发送
|
|
|
}
|
|
|
|
|
|
- // 清空输入和待发送图片
|
|
|
inputMessage.value = '';
|
|
|
pendingImages.value = [];
|
|
|
}
|
|
|
@@ -344,7 +309,6 @@ async function handleSend() {
|
|
|
function handleKeyPress(e: KeyboardEvent) {
|
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
|
e.preventDefault();
|
|
|
- // 如果禁用状态,不发送
|
|
|
if (!canSendMessage.value) {
|
|
|
return;
|
|
|
}
|
|
|
@@ -381,39 +345,33 @@ function formatTime(time: string) {
|
|
|
return time;
|
|
|
}
|
|
|
|
|
|
-// 格式化患者时间:当日显示时间,非当日显示日期
|
|
|
function formatPatientTime(time: string) {
|
|
|
if (!time) return '';
|
|
|
const timeDate = dayjs(time);
|
|
|
const today = dayjs();
|
|
|
- // 判断是否是同一天
|
|
|
if (timeDate.isSame(today, 'day')) {
|
|
|
- // 当日显示时间 HH:mm
|
|
|
return timeDate.format('HH:mm');
|
|
|
} else {
|
|
|
- // 非当日显示日期 YYYY-MM-DD
|
|
|
return timeDate.format('YYYY-MM-DD');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取性别图标
|
|
|
function getGenderIcon(sex: string) {
|
|
|
- // 1 女 其他 男
|
|
|
return sex === '1' ? '♀' : '♂';
|
|
|
}
|
|
|
|
|
|
// 定时刷新定时器
|
|
|
let refreshTimer: ReturnType<typeof setInterval> | null = null;
|
|
|
|
|
|
-// 初始化
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
- // 每5秒刷新一次页面(静默刷新,不显示提示)
|
|
|
+ // 每5秒刷新一次页面
|
|
|
refreshTimer = setInterval(() => {
|
|
|
handleRefresh(false);
|
|
|
}, 5000);
|
|
|
});
|
|
|
|
|
|
-// 清除定时器
|
|
|
onUnmounted(() => {
|
|
|
if (refreshTimer) {
|
|
|
clearInterval(refreshTimer);
|