fix: 在线复诊
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
<script setup>
|
||||
import { ref, provide, nextTick, onMounted, onUnmounted } from 'vue';
|
||||
import { ref, provide, nextTick, onMounted, onUnmounted, computed } from 'vue';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { PlusOutlined, CloseOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
import { useFileUpload } from '../composables/useFileUpload.ts';
|
||||
import { useRecording } from '../composables/useRecording.ts';
|
||||
@@ -9,9 +10,13 @@ import { useChatStore } from '../stores/chat.ts';
|
||||
import { useThemeStore } from '../stores/theme.ts';
|
||||
import { useUserStore } from '../stores/user.ts';
|
||||
import { sendMessage } from '../utils/request.ts';
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
import { getProductListDoctorReception } from '#/views/doctor/doctor-reception/api';
|
||||
import { endConsultation } from '#/views/doctor/online-consultation/api/index';
|
||||
import CustomTextarea from './CustomTextarea.vue';
|
||||
import EmojiPicker from './EmojiPicker.vue';
|
||||
import FileUploadPreview from './FileUploadPreview.vue';
|
||||
import QuickReplyBubbles from '#/views/doctor/online-consultation/components/QuickReplyBubbles.vue';
|
||||
|
||||
// 定义 props
|
||||
const props = defineProps({
|
||||
@@ -24,6 +29,7 @@ const props = defineProps({
|
||||
const userStore = useUserStore();
|
||||
const chatStore = useChatStore();
|
||||
const themeStore = useThemeStore();
|
||||
const prescriptionStore = usePrescriptionStore();
|
||||
|
||||
const messageText = ref('');
|
||||
const messageInputRef = ref(null);
|
||||
@@ -46,21 +52,36 @@ const { isRecording, startRecording, stopRecording } = useRecording();
|
||||
const sendUploadedFile = () => {
|
||||
if (!uploadPreview.value) return;
|
||||
|
||||
// 消息类型映射
|
||||
const messageTypeMap = {
|
||||
text: 0,
|
||||
image: 1,
|
||||
audio: 2,
|
||||
video: 3,
|
||||
prescription: 4,
|
||||
'medical-record': 5,
|
||||
'video-call': 6,
|
||||
'audio-call': 7,
|
||||
file: 8,
|
||||
};
|
||||
|
||||
const messageObj = {
|
||||
type: uploadPreview.value.type,
|
||||
content: uploadPreview.value.url,
|
||||
time: new Date().toLocaleTimeString().slice(0, 5),
|
||||
senderId: `${userStore.currentUser.id}`,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
message_type: messageTypeMap[uploadPreview.value.type] || 0,
|
||||
message_content: uploadPreview.value.url,
|
||||
created_at_text: new Date().toLocaleTimeString().slice(0, 5),
|
||||
created_at: Date.now(),
|
||||
sender_user_id: `doctor-${userStore.currentUser.doctor_id}`,
|
||||
receiver_user_id: chatStore.currentFriend.id,
|
||||
room_id: chatStore.currentFriend.room_id,
|
||||
read: true,
|
||||
duration: 0,
|
||||
};
|
||||
|
||||
chatStore.addMessage(messageObj, userStore.currentUser.id);
|
||||
chatStore.addMessage(messageObj, userStore.currentUser.doctor_id);
|
||||
|
||||
// 发送到服务器
|
||||
sendMessage({
|
||||
senderId: userStore.currentUser.id,
|
||||
senderId: userStore.currentUser.doctor_id,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
type: uploadPreview.value.type,
|
||||
content: uploadPreview.value.url,
|
||||
@@ -92,26 +113,45 @@ const sendTextMessage = async () => {
|
||||
uploadPreview.value = null;
|
||||
}
|
||||
|
||||
// 创建消息对象
|
||||
// 消息类型映射
|
||||
const messageTypeMap = {
|
||||
text: 0,
|
||||
image: 1,
|
||||
audio: 2,
|
||||
video: 3,
|
||||
prescription: 4,
|
||||
'medical-record': 5,
|
||||
'video-call': 6,
|
||||
'audio-call': 7,
|
||||
file: 8,
|
||||
register: 10,
|
||||
'patient-experience': 11,
|
||||
'product-card': 12,
|
||||
'end-consultation': 13,
|
||||
};
|
||||
|
||||
// 创建消息对象 - 使用数据库字段名
|
||||
const messageObj = {
|
||||
type: messageType,
|
||||
content: messageContent,
|
||||
time: new Date().toLocaleTimeString().slice(0, 5),
|
||||
senderId: `${userStore.currentUser.id}`,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
message_type: messageTypeMap[messageType] || 0,
|
||||
message_content: messageContent,
|
||||
created_at_text: new Date().toLocaleTimeString().slice(0, 5),
|
||||
created_at: Date.now(),
|
||||
sender_user_id: `doctor-${userStore.currentUser.doctor_id}`,
|
||||
receiver_user_id: chatStore.currentFriend.id,
|
||||
room_id: chatStore.currentFriend.room_id,
|
||||
isSent: true,
|
||||
read: true,
|
||||
duration: 0,
|
||||
};
|
||||
|
||||
// return console.log('发送消息:' + userStore.currentUser.id, messageObj);
|
||||
// return console.log('发送消息:' + userStore.currentUser.doctor_id, messageObj);
|
||||
// 添加到本地消息列表
|
||||
chatStore.addMessage(messageObj, userStore.currentUser.id);
|
||||
chatStore.addMessage(messageObj, userStore.currentUser.doctor_id);
|
||||
|
||||
// 发送到服务器
|
||||
try {
|
||||
await sendMessage({
|
||||
senderId: userStore.currentUser.id,
|
||||
senderId: userStore.currentUser.doctor_id,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
roomId: chatStore.currentFriend.room_id,
|
||||
type: messageType,
|
||||
@@ -208,21 +248,23 @@ const handleAudioRecorded = (event) => {
|
||||
const { url, duration } = event.detail;
|
||||
|
||||
const messageObj = {
|
||||
type: 'audio',
|
||||
content: url,
|
||||
time: new Date().toLocaleTimeString().slice(0, 5),
|
||||
senderId: `${userStore.currentUser.id}`,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
message_type: 2, // audio
|
||||
message_content: url,
|
||||
created_at_text: new Date().toLocaleTimeString().slice(0, 5),
|
||||
created_at: Date.now(),
|
||||
sender_user_id: `doctor-${userStore.currentUser.doctor_id}`,
|
||||
receiver_user_id: chatStore.currentFriend.id,
|
||||
room_id: chatStore.currentFriend.room_id,
|
||||
isSent: true,
|
||||
read: true,
|
||||
duration,
|
||||
};
|
||||
|
||||
chatStore.addMessage(messageObj, userStore.currentUser.id);
|
||||
chatStore.addMessage(messageObj, userStore.currentUser.doctor_id);
|
||||
|
||||
// 发送到服务器
|
||||
sendMessage({
|
||||
senderId: userStore.currentUser.id,
|
||||
senderId: userStore.currentUser.doctor_id,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
roomId: chatStore.currentFriend.room_id,
|
||||
isSent: true,
|
||||
@@ -262,7 +304,6 @@ const emit = defineEmits([
|
||||
// 开方功能触发函数
|
||||
const handleOpenPrescription = () => {
|
||||
// 获取当前会话的register_id,这里假设可以通过某种方式获取
|
||||
console.log(chatStore.currentFriend.register_id, 'sssssssssssssss')
|
||||
// 例如从聊天存储或props中获取
|
||||
const registerId = chatStore.currentFriend?.register_id || 66;
|
||||
|
||||
@@ -275,10 +316,160 @@ const handleOpenPrescription = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 处理快速回复选择
|
||||
const handleQuickReplySelect = (content) => {
|
||||
// 设置输入框内容并发送
|
||||
messageText.value = content;
|
||||
sendTextMessage();
|
||||
};
|
||||
|
||||
// 判断是否显示在线复诊相关按钮
|
||||
const showOnlineConsultationButtons = computed(() => {
|
||||
// 检查是否有 register_id,如果有则说明是在线复诊场景
|
||||
return !!chatStore.currentFriend?.register_id;
|
||||
});
|
||||
|
||||
// 将患者就诊经历中的药品加入处方单
|
||||
const handleAddPatientProductsToPrescription = async () => {
|
||||
// 检查处方store是否已初始化
|
||||
if (!prescriptionStore.currentRegisterId) {
|
||||
const registerId = chatStore.currentFriend?.register_id;
|
||||
if (registerId) {
|
||||
prescriptionStore.initializePrescription(registerId, false);
|
||||
} else {
|
||||
message.warning('请先接诊患者');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 从聊天记录中筛选出所有 message_type=11 的消息(患者就诊经历)
|
||||
const experienceMessages = chatStore.messages.filter(
|
||||
(msg) => msg.message_type === 11
|
||||
);
|
||||
|
||||
if (experienceMessages.length === 0) {
|
||||
message.warning('当前聊天没有可添加的药品');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取诊所ID
|
||||
let storeId = prescriptionStore.myStoreId;
|
||||
if (!storeId || storeId === 0) {
|
||||
if (prescriptionStore.myStoreList && prescriptionStore.myStoreList.length > 0) {
|
||||
storeId = prescriptionStore.myStoreList[0].id;
|
||||
} else {
|
||||
message.warning('请先选择诊所');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 按时间排序,取最新的就诊经历
|
||||
const sortedMessages = [...experienceMessages].sort((a, b) => {
|
||||
const timeA = a.created_at ? new Date(a.created_at).getTime() : (a.timestamp || 0);
|
||||
const timeB = b.created_at ? new Date(b.created_at).getTime() : (b.timestamp || 0);
|
||||
return timeB - timeA; // 降序排列,最新的在前
|
||||
});
|
||||
|
||||
const latestMessage = sortedMessages[0];
|
||||
try {
|
||||
// 解析最新消息的内容
|
||||
let experienceData;
|
||||
try {
|
||||
experienceData = typeof latestMessage.message_content === 'string'
|
||||
? JSON.parse(latestMessage.message_content)
|
||||
: latestMessage.message_content;
|
||||
} catch (e) {
|
||||
console.error('解析就诊经历消息失败:', e);
|
||||
message.warning('当前聊天没有可添加的药品');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取药品名称
|
||||
const drugName = experienceData.drug_name;
|
||||
if (!drugName) {
|
||||
message.warning('当前聊天没有可添加的药品');
|
||||
return;
|
||||
}
|
||||
|
||||
// 通过药品名称搜索药品
|
||||
const res = await getProductListDoctorReception({
|
||||
store_id: storeId,
|
||||
type: 2, // 中成(西)药
|
||||
name: drugName,
|
||||
});
|
||||
|
||||
if (!res || res.length === 0) {
|
||||
message.warning('当前聊天没有可添加的药品');
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用第一个匹配的药品
|
||||
const drugData = res[0];
|
||||
|
||||
// 检查药品是否已在处方中
|
||||
const existItem = prescriptionStore.currentDrugs.find(
|
||||
(item) => item.index_id === drugData.id,
|
||||
);
|
||||
if (existItem) {
|
||||
message.warning('该药品已在处方中');
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加药品到处方单
|
||||
const success = prescriptionStore.addProducts(drugData);
|
||||
if (success) {
|
||||
message.success(`已将${drugData.drug.drug_name}添加到处方单`);
|
||||
// 触发打开处方模态框事件
|
||||
emit('openPrescription', prescriptionStore.currentRegisterId || chatStore.currentFriend?.register_id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('添加药品失败:', error);
|
||||
message.error('添加药品失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
// 结束问诊
|
||||
const handleEndConsultation = () => {
|
||||
const registerId = chatStore.currentFriend?.register_id;
|
||||
if (!registerId) {
|
||||
message.warning('患者信息不完整,无法结束接诊');
|
||||
return;
|
||||
}
|
||||
|
||||
const patientName = chatStore.currentFriend?.nick_name || '患者';
|
||||
|
||||
Modal.confirm({
|
||||
title: '确认结束接诊',
|
||||
content: `确定要结束${patientName}的复诊吗?`,
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await endConsultation({
|
||||
register_id: registerId,
|
||||
doctor_id: userStore.currentUser?.doctor_id || '39',
|
||||
reason: '医生主动结束'
|
||||
});
|
||||
|
||||
message.success('结束接诊成功');
|
||||
} catch (error) {
|
||||
console.error('结束接诊失败:', error);
|
||||
message.error('结束接诊失败,请重试');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="message-input-container" :class="{ dark: themeStore.isDarkMode }">
|
||||
<div class="message-input-container flex-shrink-0 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700">
|
||||
<!-- 快速回复气泡(仅在线复诊场景显示) -->
|
||||
<QuickReplyBubbles
|
||||
v-if="chatStore.currentFriend"
|
||||
:doctor-id="'32'"
|
||||
@select-reply="handleQuickReplySelect"
|
||||
/>
|
||||
|
||||
<!-- 文件上传预览 -->
|
||||
<FileUploadPreview v-if="uploadPreview" />
|
||||
@@ -328,6 +519,24 @@ const handleOpenPrescription = () => {
|
||||
>
|
||||
<i class="fas fa-microphone"></i>
|
||||
</button>
|
||||
<!-- 添加药品按钮(仅在线复诊场景显示) -->
|
||||
<button
|
||||
v-if="showOnlineConsultationButtons"
|
||||
class="function-btn"
|
||||
title="将患者就诊经历中的药品加入处方单"
|
||||
@click="handleAddPatientProductsToPrescription"
|
||||
>
|
||||
<PlusOutlined />
|
||||
</button>
|
||||
<!-- 结束问诊按钮(仅在线复诊场景显示) -->
|
||||
<button
|
||||
v-if="showOnlineConsultationButtons"
|
||||
class="function-btn end-consultation-btn"
|
||||
title="结束问诊"
|
||||
@click="handleEndConsultation"
|
||||
>
|
||||
<CloseOutlined />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="input-container">
|
||||
@@ -378,14 +587,12 @@ const handleOpenPrescription = () => {
|
||||
<style scoped>
|
||||
.message-input-container {
|
||||
padding: 20px;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
|
||||
}
|
||||
|
||||
.message-input-container.dark {
|
||||
border-top-color: #374151;
|
||||
background: linear-gradient(135deg, #2d2d2d 0%, #1f2937 100%);
|
||||
.dark .message-input-container {
|
||||
background: linear-gradient(135deg, #1f2937 0%, #111827 100%);
|
||||
}
|
||||
|
||||
.input-container {
|
||||
@@ -398,7 +605,11 @@ const handleOpenPrescription = () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
border-top: 1px solid #666666;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.dark .toolbar {
|
||||
border-top-color: #374151;
|
||||
}
|
||||
|
||||
.function-btn {
|
||||
@@ -413,10 +624,18 @@ const handleOpenPrescription = () => {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dark .function-btn {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.function-btn:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.dark .function-btn:hover {
|
||||
background-color: #374151;
|
||||
}
|
||||
|
||||
.prescription-button {
|
||||
color: #455cda;
|
||||
font-weight: 500;
|
||||
@@ -426,6 +645,21 @@ const handleOpenPrescription = () => {
|
||||
background-color: #e6e9ff;
|
||||
}
|
||||
|
||||
.end-consultation-btn {
|
||||
color: #ff4d4f;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.end-consultation-btn:hover {
|
||||
background-color: #fff1f0;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.dark .end-consultation-btn:hover {
|
||||
background-color: rgba(255, 77, 79, 0.2);
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.function-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
@@ -521,12 +755,12 @@ const handleOpenPrescription = () => {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.message-input-container.dark .function-btn {
|
||||
.dark .function-btn {
|
||||
background: linear-gradient(135deg, #374151, #4b5563);
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.message-input-container.dark .function-btn:hover {
|
||||
.dark .function-btn:hover {
|
||||
background: linear-gradient(135deg, #4361ee, #3f37c9);
|
||||
color: white;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user