转接方
Some checks failed
Close stale issues / stale (push) Has been cancelled
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Some checks failed
Close stale issues / stale (push) Has been cancelled
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
This commit is contained in:
@@ -794,7 +794,7 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
await addWestPrescription({
|
||||
const response = await addWestPrescription({
|
||||
patient: activePatient.value,
|
||||
drugs: currentDrugs.value,
|
||||
diagnosis: diagnosis.value,
|
||||
@@ -821,36 +821,44 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
// 诊所选择参数(使用传入的参数)
|
||||
send_mode: customSendMode,
|
||||
custom_store_id: customSendMode === 1 ? customStoreId : null,
|
||||
}).then((res) => {
|
||||
message.success('处方已发送');
|
||||
sendMessage({
|
||||
roomId: chatStore.currentFriend.room_id,
|
||||
senderId: userStore.currentUser.doctor_id,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
type: 'prescription',
|
||||
content: JSON.stringify(res),
|
||||
});
|
||||
chatStore.addMessage(
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
room_id: chatStore.currentFriend.room_id,
|
||||
sender_user_id: `doctor-${userStore.currentUser.doctor_id}`,
|
||||
receiver_user_id: chatStore.currentFriend.id,
|
||||
message_type: 4,
|
||||
message_content: JSON.stringify(res),
|
||||
messageTypeName: 'prescription',
|
||||
created_at: Date.now(),
|
||||
created_at_text: new Date().toLocaleTimeString().slice(0, 5),
|
||||
timestamp: Date.now(),
|
||||
isSent: true,
|
||||
read: true,
|
||||
duration: 0,
|
||||
},
|
||||
userStore.currentUser.doctor_id,
|
||||
);
|
||||
resetForm();
|
||||
});
|
||||
return true;
|
||||
|
||||
const res = await response;
|
||||
message.success('处方已发送');
|
||||
sendMessage({
|
||||
roomId: chatStore.currentFriend.room_id,
|
||||
senderId: userStore.currentUser.doctor_id,
|
||||
receiverId: chatStore.currentFriend.id,
|
||||
type: 'prescription',
|
||||
content: JSON.stringify(res),
|
||||
});
|
||||
chatStore.addMessage(
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
room_id: chatStore.currentFriend.room_id,
|
||||
sender_user_id: `doctor-${userStore.currentUser.doctor_id}`,
|
||||
receiver_user_id: chatStore.currentFriend.id,
|
||||
message_type: 4,
|
||||
message_content: JSON.stringify(res),
|
||||
messageTypeName: 'prescription',
|
||||
created_at: Date.now(),
|
||||
created_at_text: new Date().toLocaleTimeString().slice(0, 5),
|
||||
timestamp: Date.now(),
|
||||
isSent: true,
|
||||
read: true,
|
||||
duration: 0,
|
||||
},
|
||||
userStore.currentUser.doctor_id,
|
||||
);
|
||||
resetForm();
|
||||
|
||||
// 返回包含转诊信息的响应数据
|
||||
return {
|
||||
success: true,
|
||||
result: res?.result || res?.data || res,
|
||||
need_transfer: res?.result?.need_transfer || res?.data?.need_transfer || res?.need_transfer,
|
||||
transfer_prescription_id: res?.result?.transfer_prescription_id || res?.data?.transfer_prescription_id || res?.transfer_prescription_id,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('发送处方失败:', error);
|
||||
message.error('发送处方失败');
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const prefix = 'transfer-prescription/';
|
||||
|
||||
/**
|
||||
* 获取转诊详情
|
||||
* @param id 转诊ID
|
||||
*/
|
||||
export async function getTransferPrescriptionDetailApi(id: number) {
|
||||
return requestClient.get<any>(`${prefix}detail`, { params: { id } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据挂号ID获取转诊信息
|
||||
* @param registerId 挂号ID
|
||||
*/
|
||||
export async function getTransferPrescriptionByRegisterApi(registerId: number) {
|
||||
return requestClient.get<any>(`${prefix}get-by-register`, { params: { register_id: registerId } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认转诊
|
||||
* @param id 转诊ID
|
||||
*/
|
||||
export async function confirmTransferPrescriptionApi(id: number) {
|
||||
return requestClient.post<any>(`${prefix}confirm`, { id });
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键导入处方到在线问诊
|
||||
* @param id 转诊ID
|
||||
* @param registerId 挂号ID
|
||||
*/
|
||||
export async function importTransferPrescriptionApi(id: number, registerId: number) {
|
||||
return requestClient.post<any>(`${prefix}import`, { id, register_id: registerId });
|
||||
}
|
||||
@@ -14,6 +14,7 @@ const emit = defineEmits([
|
||||
// ... existing emits
|
||||
'openPrescription',
|
||||
'end-consultation-success',
|
||||
'transfer-import-success',
|
||||
]);
|
||||
|
||||
// 开方功能触发函数
|
||||
@@ -35,12 +36,17 @@ const handleEndConsultationSuccess = () => {
|
||||
<ChatHeader />
|
||||
|
||||
<!-- 消息区域 -->
|
||||
<MessageList class="flex-1" />
|
||||
<MessageList
|
||||
class="flex-1"
|
||||
@open-prescription="handleOpenPrescription"
|
||||
@transfer-import-success="(data) => emit('transfer-import-success', data)"
|
||||
/>
|
||||
|
||||
<!-- 输入区域 -->
|
||||
<MessageInput
|
||||
@open-prescription="handleOpenPrescription"
|
||||
@end-consultation-success="handleEndConsultationSuccess"
|
||||
@transfer-import-success="(data) => emit('transfer-import-success', data)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -12,8 +12,8 @@ import { sendMessage } from '#/views/business/chat/utils/request';
|
||||
|
||||
// 辅助函数:按需解析消息内容
|
||||
const getParsedContent = (messageType, messageContent) => {
|
||||
// 对于需要 JSON 解析的消息类型:4, 9, 10, 11, 12, 13
|
||||
if ([4, 9, 10, 11, 12, 13].includes(messageType)) {
|
||||
// 对于需要 JSON 解析的消息类型:4, 9, 10, 11, 12, 13, 14
|
||||
if ([4, 9, 10, 11, 12, 13, 14].includes(messageType)) {
|
||||
try {
|
||||
return JSON.parse(messageContent);
|
||||
} catch (e) {
|
||||
@@ -41,6 +41,7 @@ const getMessageTypeName = (messageType) => {
|
||||
11: 'patient-experience',
|
||||
12: 'product-card',
|
||||
13: 'end-consultation',
|
||||
14: 'transfer-prescription',
|
||||
};
|
||||
return types[messageType] || 'unknown';
|
||||
};
|
||||
@@ -56,6 +57,8 @@ import AudioMessage from './AudioMessage.vue';
|
||||
import PatientExperienceCard from '#/views/doctor/online-consultation/components/PatientExperienceCard.vue';
|
||||
import ProductCard from '#/views/doctor/online-consultation/components/ProductCard.vue';
|
||||
import EndConsultationCard from '#/views/doctor/online-consultation/components/EndConsultationCard.vue';
|
||||
import TransferPrescriptionMessageCard from '#/views/doctor/online-consultation/components/TransferPrescriptionMessageCard.vue';
|
||||
import TransferPrescriptionViewDrawer from '#/views/doctor/online-consultation/components/TransferPrescriptionViewDrawer.vue';
|
||||
|
||||
const props = defineProps({
|
||||
message: {
|
||||
@@ -71,12 +74,16 @@ const props = defineProps({
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['show-user-profile']);
|
||||
const emit = defineEmits(['show-user-profile', 'open-prescription', 'transfer-import-success']);
|
||||
const chatUserStore = chatUseUserStore();
|
||||
const userStore = useUserStore();
|
||||
const chatStore = useChatStore();
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
// 转接方查看抽屉相关
|
||||
const showTransferDrawer = ref(false);
|
||||
const transferRegisterId = ref(null);
|
||||
|
||||
const [RefusalOfTreatmentModals, RefusalOfTreatmentModalApi] = useVbenModal({
|
||||
connectedComponent: RefusalOfTreatmentModal,
|
||||
});
|
||||
@@ -199,6 +206,21 @@ const acceptRegister = async (registerId, orderNo) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 查看转接方详情
|
||||
const handleViewTransferDetail = (transferData) => {
|
||||
transferRegisterId.value = chatStore.currentFriend?.register_id;
|
||||
showTransferDrawer.value = true;
|
||||
};
|
||||
|
||||
// 处理转接方导入成功
|
||||
const handleTransferImportSuccess = (prescriptionData) => {
|
||||
// 触发打开处方模态框事件
|
||||
const registerId = transferRegisterId.value || chatStore.currentFriend?.register_id;
|
||||
if (registerId) {
|
||||
emit('open-prescription', registerId);
|
||||
}
|
||||
};
|
||||
|
||||
// 拒诊操作
|
||||
const rejectRegister = async (registerId, orderNo) => {
|
||||
if (registerOperating.value) return;
|
||||
@@ -821,6 +843,15 @@ if (props.message.message_type === 10) {
|
||||
:content="parsedContent"
|
||||
/>
|
||||
|
||||
<!-- 转接方消息卡片 (type=14) -->
|
||||
<TransferPrescriptionMessageCard
|
||||
v-else-if="message.message_type === 14"
|
||||
:content="parsedContent"
|
||||
:register-id="chatStore.currentFriend?.register_id"
|
||||
@view-detail="handleViewTransferDetail"
|
||||
@import-success="handleTransferImportSuccess"
|
||||
/>
|
||||
|
||||
<!-- 通话消息 -->
|
||||
<div
|
||||
v-else-if="
|
||||
@@ -861,6 +892,13 @@ if (props.message.message_type === 10) {
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 转接方查看抽屉 -->
|
||||
<TransferPrescriptionViewDrawer
|
||||
v-model:visible="showTransferDrawer"
|
||||
:register-id="transferRegisterId"
|
||||
@import-success="handleTransferImportSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import { useThemeStore } from '../stores/theme.ts';
|
||||
import { useUserStore } from '../stores/user.ts';
|
||||
import { sendMessage } from '../utils/request.ts';
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
import { getTransferPrescriptionByRegisterApi } from '#/views/business/chat/api/transferPrescription';
|
||||
import TransferPrescriptionViewDrawer from '#/views/doctor/online-consultation/components/TransferPrescriptionViewDrawer.vue';
|
||||
|
||||
// 根据路由判断是在线复诊-药店还是在线复诊-诊所
|
||||
const route = useRoute();
|
||||
@@ -58,6 +60,8 @@ const prescriptionStore = usePrescriptionStore();
|
||||
const messageText = ref('');
|
||||
const messageInputRef = ref(null);
|
||||
const showEmojiPicker = ref(false);
|
||||
const showTransferDrawer = ref(false);
|
||||
const transferRegisterId = ref(null);
|
||||
|
||||
// 使用文件上传组合式函数
|
||||
const {
|
||||
@@ -325,7 +329,8 @@ onUnmounted(() => {
|
||||
const emit = defineEmits([
|
||||
'sendMessage',
|
||||
'openPrescription', // 添加开方事件
|
||||
'end-consultation-success' // 结束接诊成功事件
|
||||
'end-consultation-success', // 结束接诊成功事件
|
||||
'transfer-import-success' // 转接方导入成功事件
|
||||
]);
|
||||
|
||||
// 开方功能触发函数
|
||||
@@ -453,6 +458,37 @@ const handleEndConsultation = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 打开转接方查看抽屉
|
||||
const handleOpenTransferView = async () => {
|
||||
const registerId = chatStore.currentFriend?.register_id;
|
||||
if (!registerId) {
|
||||
message.warning('患者信息不完整,无法查看转接方');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否有转接方
|
||||
try {
|
||||
const res = await getTransferPrescriptionByRegisterApi(registerId);
|
||||
const data = res?.result || res?.data || res;
|
||||
if (data && data.id) {
|
||||
transferRegisterId.value = registerId;
|
||||
showTransferDrawer.value = true;
|
||||
} else {
|
||||
message.warning('该患者没有转接方信息');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查转接方信息失败:', error);
|
||||
message.error('检查转接方信息失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
// 处理转接方导入成功
|
||||
const handleTransferImportSuccess = (prescriptionData) => {
|
||||
// 触发打开处方模态框的事件
|
||||
emit('transfer-import-success', prescriptionData);
|
||||
emit('openPrescription', transferRegisterId.value || chatStore.currentFriend?.register_id);
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -522,6 +558,15 @@ const handleEndConsultation = () => {
|
||||
>
|
||||
<PlusOutlined />
|
||||
</button>
|
||||
<!-- 转接方查看按钮(仅在线复诊场景显示) -->
|
||||
<button
|
||||
v-if="showOnlineConsultationButtons"
|
||||
class="function-btn transfer-view-btn"
|
||||
title="查看转接方"
|
||||
@click="handleOpenTransferView"
|
||||
>
|
||||
<i class="fas fa-exchange-alt"></i>
|
||||
</button>
|
||||
<!-- 结束问诊按钮(仅在线复诊场景显示) -->
|
||||
<button
|
||||
v-if="showOnlineConsultationButtons"
|
||||
@@ -575,6 +620,13 @@ const handleEndConsultation = () => {
|
||||
type="file"
|
||||
@change="handleFileUpload"
|
||||
/>
|
||||
|
||||
<!-- 转接方查看抽屉 -->
|
||||
<TransferPrescriptionViewDrawer
|
||||
v-model:visible="showTransferDrawer"
|
||||
:register-id="transferRegisterId"
|
||||
@import-success="handleTransferImportSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -654,6 +706,21 @@ const handleEndConsultation = () => {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.transfer-view-btn {
|
||||
color: #f97316;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.transfer-view-btn:hover {
|
||||
background-color: #fff7ed;
|
||||
color: #f97316;
|
||||
}
|
||||
|
||||
.dark .transfer-view-btn:hover {
|
||||
background-color: rgba(249, 115, 22, 0.2);
|
||||
color: #f97316;
|
||||
}
|
||||
|
||||
.function-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
|
||||
@@ -11,6 +11,8 @@ import MessageBubble from './MessageBubble.vue';
|
||||
const userStore = useUserStore();
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const emit = defineEmits(['open-prescription', 'transfer-import-success']);
|
||||
|
||||
const messagesContainer = ref(null);
|
||||
const loadingMessages = ref(false);
|
||||
const loadingOlderMessages = ref(false); // 加载历史消息状态
|
||||
@@ -163,6 +165,8 @@ onMounted(() => {
|
||||
:is-sent="msg.isSent"
|
||||
:message="msg"
|
||||
:sender-info="getSenderInfo(msg)"
|
||||
@open-prescription="(registerId) => emit('open-prescription', registerId)"
|
||||
@transfer-import-success="(data) => emit('transfer-import-success', data)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -227,12 +227,38 @@ const executeSendPrescription = async (
|
||||
sendMode: number,
|
||||
customStoreId: number | null,
|
||||
) => {
|
||||
const success = await prescriptionStore.sendPrescription(
|
||||
const result = await prescriptionStore.sendPrescription(
|
||||
doctorSecondSignValue,
|
||||
sendMode,
|
||||
customStoreId,
|
||||
);
|
||||
|
||||
// 检查返回结果,可能是boolean或包含转诊信息的对象
|
||||
const success = typeof result === 'boolean' ? result : result?.success !== false;
|
||||
const prescriptionResult = typeof result === 'object' ? result : null;
|
||||
|
||||
if (success) {
|
||||
// 检查是否需要转诊(西医诊所开中药处方)
|
||||
if (prescriptionResult?.need_transfer || prescriptionResult?.result?.need_transfer) {
|
||||
const transferId = prescriptionResult?.transfer_prescription_id || prescriptionResult?.result?.transfer_prescription_id;
|
||||
if (transferId) {
|
||||
// 显示转诊确认提示
|
||||
AntModal.info({
|
||||
title: '转诊提示',
|
||||
content: '该处方已触发转诊流程,转诊消息已发送给委托诊所的在线问诊医生。',
|
||||
okText: '确定',
|
||||
onOk: () => {
|
||||
if (modalData.value?.onPrescriptionSent) {
|
||||
modalData.value.onPrescriptionSent();
|
||||
}
|
||||
submittingType.value = false;
|
||||
modalApi.close();
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (modalData.value?.onPrescriptionSent) {
|
||||
modalData.value.onPrescriptionSent();
|
||||
}
|
||||
@@ -1356,65 +1382,90 @@ const cancelSaveCommonPrescription = () => {
|
||||
</div>
|
||||
|
||||
<div class="mt-5 flex gap-4 items-center flex-wrap">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-2">用量:</span>
|
||||
<InputNumber v-model:value="prescriptionStore.dosage" style="width: 100px">
|
||||
<template #addonBefore>
|
||||
<MinusOutlined
|
||||
class="cursor-pointer"
|
||||
@click="
|
||||
prescriptionStore.dosage =
|
||||
prescriptionStore.dosage > 1
|
||||
? prescriptionStore.dosage - 1
|
||||
: 1
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #addonAfter>
|
||||
<PlusOutlined
|
||||
class="cursor-pointer"
|
||||
@click="
|
||||
prescriptionStore.dosage =
|
||||
prescriptionStore.dosage < 100
|
||||
? prescriptionStore.dosage + 1
|
||||
: 100
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</InputNumber>
|
||||
<span class="ml-2">天 / {{ prescriptionStore.dosage }} 剂</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="mr-2 whitespace-nowrap">用量:</span>
|
||||
<div class="flex items-center border rounded" style="border-color: #d9d9d9;">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
class="border-0 border-r rounded-l"
|
||||
style="border-color: #d9d9d9;"
|
||||
@click="
|
||||
prescriptionStore.dosage =
|
||||
prescriptionStore.dosage > 1
|
||||
? prescriptionStore.dosage - 1
|
||||
: 1
|
||||
"
|
||||
>
|
||||
<MinusOutlined />
|
||||
</Button>
|
||||
<InputNumber
|
||||
v-model:value="prescriptionStore.dosage"
|
||||
:controls="false"
|
||||
:min="1"
|
||||
:max="100"
|
||||
class="border-0"
|
||||
style="width: 80px; text-align: center;"
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
class="border-0 border-l rounded-r"
|
||||
style="border-color: #d9d9d9;"
|
||||
@click="
|
||||
prescriptionStore.dosage =
|
||||
prescriptionStore.dosage < 100
|
||||
? prescriptionStore.dosage + 1
|
||||
: 100
|
||||
"
|
||||
>
|
||||
<PlusOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
<span class="ml-2 whitespace-nowrap">天 / {{ prescriptionStore.dosage }} 剂</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="mr-2">频次:</span>
|
||||
<InputNumber
|
||||
v-model:value="prescriptionStore.dayDosage"
|
||||
style="width: 100px"
|
||||
>
|
||||
<template #addonBefore>
|
||||
<MinusOutlined
|
||||
class="cursor-pointer"
|
||||
@click="
|
||||
prescriptionStore.dayDosage =
|
||||
prescriptionStore.dayDosage > 1
|
||||
? prescriptionStore.dayDosage - 1
|
||||
: 1
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #addonAfter>
|
||||
<PlusOutlined
|
||||
class="cursor-pointer"
|
||||
@click="
|
||||
prescriptionStore.dayDosage =
|
||||
prescriptionStore.dayDosage < 100
|
||||
? prescriptionStore.dayDosage + 1
|
||||
: 100
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</InputNumber>
|
||||
<span class="ml-2">次/天</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="mr-2 whitespace-nowrap">频次:</span>
|
||||
<div class="flex items-center border rounded" style="border-color: #d9d9d9;">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
class="border-0 border-r rounded-l"
|
||||
style="border-color: #d9d9d9;"
|
||||
@click="
|
||||
prescriptionStore.dayDosage =
|
||||
prescriptionStore.dayDosage > 1
|
||||
? prescriptionStore.dayDosage - 1
|
||||
: 1
|
||||
"
|
||||
>
|
||||
<MinusOutlined />
|
||||
</Button>
|
||||
<InputNumber
|
||||
v-model:value="prescriptionStore.dayDosage"
|
||||
:controls="false"
|
||||
:min="1"
|
||||
:max="100"
|
||||
class="border-0"
|
||||
style="width: 80px; text-align: center;"
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
class="border-0 border-l rounded-r"
|
||||
style="border-color: #d9d9d9;"
|
||||
@click="
|
||||
prescriptionStore.dayDosage =
|
||||
prescriptionStore.dayDosage < 100
|
||||
? prescriptionStore.dayDosage + 1
|
||||
: 100
|
||||
"
|
||||
>
|
||||
<PlusOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
<span class="ml-2 whitespace-nowrap">次/天</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -58,6 +58,14 @@ export async function updateNavSortApi(ids: number[]) {
|
||||
return requestClient.post<any>(`${prefix}update-nav-sort`, { ids });
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新诊所类型
|
||||
* @param data 包含clinic_type的对象,clinic_type: 1=西医诊所, 2=中医诊所
|
||||
*/
|
||||
export async function updateClinicTypeApi(data: { clinic_type: number }) {
|
||||
return requestClient.post<any>(`${prefix}update-clinic-type`, data);
|
||||
}
|
||||
|
||||
/*
|
||||
----------------------------推广员---------------------------------
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
ImagePreviewGroup,
|
||||
InputNumber,
|
||||
message,
|
||||
Modal,
|
||||
notification,
|
||||
Popconfirm,
|
||||
RadioButton,
|
||||
@@ -27,6 +28,7 @@ import {
|
||||
getStoreInfoApi,
|
||||
saveZSalePercentApi,
|
||||
updateNavSortApi,
|
||||
updateClinicTypeApi,
|
||||
} from '#/views/business/store/settings/api';
|
||||
|
||||
import UploadModal from './components/uploadModal.vue';
|
||||
@@ -41,6 +43,7 @@ interface TabBarItem {
|
||||
interface StoreInfo {
|
||||
name: string;
|
||||
type: number; // 0=诊所, 1=药店
|
||||
clinic_type?: number; // 1=西医诊所, 2=中医诊所
|
||||
star?: any;
|
||||
title: { name: string };
|
||||
contact: string;
|
||||
@@ -295,6 +298,44 @@ const openPreview = (index: number) => {
|
||||
previewCurrent.value = index;
|
||||
previewVisible.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换诊所类型
|
||||
*/
|
||||
const handleSwitchClinicType = () => {
|
||||
if (!data.value) return;
|
||||
|
||||
const currentType = data.value.clinic_type || 2; // 默认为中医诊所
|
||||
const newType = currentType === 1 ? 2 : 1;
|
||||
const currentTypeText = currentType === 1 ? '西医诊所' : '中医诊所';
|
||||
const newTypeText = newType === 1 ? '西医诊所' : '中医诊所';
|
||||
|
||||
Modal.confirm({
|
||||
title: '确认切换诊所类型',
|
||||
content: `确定要将诊所类型从【${currentTypeText}】切换为【${newTypeText}】吗?`,
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await updateClinicTypeApi({ clinic_type: newType });
|
||||
notification.success({
|
||||
message: '切换成功',
|
||||
description: `诊所类型已切换为【${newTypeText}】`,
|
||||
duration: 2,
|
||||
});
|
||||
// 刷新诊所信息
|
||||
getMyInfo();
|
||||
} catch (error) {
|
||||
console.error('切换诊所类型失败:', error);
|
||||
notification.error({
|
||||
message: '切换失败',
|
||||
description: '请稍后重试',
|
||||
duration: 2,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -410,6 +451,25 @@ const openPreview = (index: number) => {
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 诊所类型 -->
|
||||
<div v-if="!isPharmacy" class="mt-6 rounded-lg bg-gray-50 p-4 dark:bg-[#020817]">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm font-medium">诊所类型</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<Tag
|
||||
:color="data.clinic_type === 1 ? 'blue' : 'green'"
|
||||
class="clinic-type-tag cursor-pointer"
|
||||
@click="handleSwitchClinicType"
|
||||
>
|
||||
{{ data.clinic_type === 1 ? '西医诊所' : data.clinic_type === 2 ? '中医诊所' : '未设置' }}
|
||||
</Tag>
|
||||
<Button type="link" size="small" @click="handleSwitchClinicType">
|
||||
切换
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -733,4 +793,19 @@ const openPreview = (index: number) => {
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 诊所类型标签样式 */
|
||||
.clinic-type-tag {
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -66,6 +66,9 @@ import {
|
||||
saveChineseCommonPrescriptionApi,
|
||||
saveWestCommonPrescriptionApi,
|
||||
} from '#/views/doctor/settings/api';
|
||||
// 转诊相关
|
||||
import TransferPrescriptionCard from '#/views/doctor/online-consultation/components/TransferPrescriptionCard.vue';
|
||||
import { getTransferPrescriptionByRegisterApi } from '#/views/business/chat/api/transferPrescription';
|
||||
|
||||
interface Patient {
|
||||
id: number;
|
||||
@@ -191,6 +194,12 @@ const commonPrescriptionName = ref('');
|
||||
/** 是否正在保存常用方 */
|
||||
const isSavingCommonPrescription = ref(false);
|
||||
|
||||
// ==================== 转诊相关状态 ====================
|
||||
/** 转诊处方信息 */
|
||||
const transferPrescription = ref(null);
|
||||
/** 是否正在加载转诊信息 */
|
||||
const loadingTransfer = ref(false);
|
||||
|
||||
/**
|
||||
* 获取药品使用方式列表
|
||||
*/
|
||||
@@ -564,8 +573,22 @@ const sendPrescription = () => {
|
||||
day_dosage: dayDosage.value,
|
||||
// 是否二次签名
|
||||
doctor_second_sign: doctorSecondSign.value,
|
||||
}).then(() => {
|
||||
}).then((res) => {
|
||||
message.success('处方已发送');
|
||||
|
||||
// 检查是否需要转诊
|
||||
const needTransfer = res?.result?.need_transfer || res?.data?.need_transfer || res?.need_transfer;
|
||||
const transferPrescriptionId = res?.result?.transfer_prescription_id || res?.data?.transfer_prescription_id || res?.transfer_prescription_id;
|
||||
|
||||
if (needTransfer && transferPrescriptionId) {
|
||||
// 如果需要转诊,获取转诊信息
|
||||
fetchTransferPrescription(transferPrescriptionId);
|
||||
message.info('该处方需要转诊,请等待中医诊所确认');
|
||||
} else {
|
||||
// 不需要转诊,清空转诊信息
|
||||
transferPrescription.value = null;
|
||||
}
|
||||
|
||||
// 清空当前数据
|
||||
currentDrugs.value = [];
|
||||
diagnosis.value = '';
|
||||
@@ -577,6 +600,18 @@ const sendPrescription = () => {
|
||||
tabType.value = 1;
|
||||
newDrugInfo.value = {};
|
||||
updateLocalStorage();
|
||||
|
||||
// 刷新患者信息
|
||||
if (selectPatientId.value) {
|
||||
getPatientItem(selectPatientId.value).then((value) => {
|
||||
patientInfo.value = value;
|
||||
userPatientHealthInquiry.value = value.user_patient_health_inquiry;
|
||||
prescriptionList.value = value.prescription;
|
||||
});
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('发送处方失败:', error);
|
||||
message.error('发送处方失败,请重试');
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1436,6 +1471,49 @@ function handleSimpleProductSelect(drug: any) {
|
||||
|
||||
const newDrugInfo = ref({});
|
||||
|
||||
/**
|
||||
* 获取转诊信息
|
||||
* @param transferPrescriptionId 转诊处方ID
|
||||
*/
|
||||
const fetchTransferPrescription = async (transferPrescriptionId: number) => {
|
||||
if (!transferPrescriptionId) return;
|
||||
|
||||
loadingTransfer.value = true;
|
||||
try {
|
||||
// 通过转诊处方ID获取转诊信息
|
||||
// 注意:这里需要根据实际API调整,可能需要通过register_id获取
|
||||
const registerId = Number.parseInt(localStorage.getItem(`doctorReception-id`));
|
||||
if (registerId) {
|
||||
const res = await getTransferPrescriptionByRegisterApi(registerId);
|
||||
const data = res?.result || res?.data || res;
|
||||
if (data && data.id) {
|
||||
transferPrescription.value = data;
|
||||
} else {
|
||||
transferPrescription.value = null;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取转诊信息失败:', error);
|
||||
transferPrescription.value = null;
|
||||
} finally {
|
||||
loadingTransfer.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理转诊导入成功
|
||||
*/
|
||||
const handleTransferImportSuccess = () => {
|
||||
// 转诊导入成功后,可以刷新患者信息
|
||||
if (selectPatientId.value) {
|
||||
getPatientItem(selectPatientId.value).then((value) => {
|
||||
patientInfo.value = value;
|
||||
userPatientHealthInquiry.value = value.user_patient_health_inquiry;
|
||||
prescriptionList.value = value.prescription;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function switchStore(id) {
|
||||
switchStoreApi({store_id: id}).then(() => {
|
||||
myStoreId.value = id;
|
||||
@@ -1710,6 +1788,15 @@ watch(
|
||||
</Timeline>
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<!-- 转诊处方卡片 -->
|
||||
<div v-if="transferPrescription" class="transfer-section mt-5">
|
||||
<TransferPrescriptionCard
|
||||
:transfer-data="transferPrescription"
|
||||
:register-id="Number.parseInt(localStorage.getItem(`doctorReception-id`))"
|
||||
@import-success="handleTransferImportSuccess"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Page>
|
||||
|
||||
|
||||
@@ -5,8 +5,12 @@ import { getPatientDetail, reception } from '../api/index.ts';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { sendMessage } from '#/views/business/chat/utils/request';
|
||||
import { useUserStore } from '#/views/business/chat/stores/user';
|
||||
import { getTransferPrescriptionByRegisterApi } from '#/views/business/chat/api/transferPrescription';
|
||||
import TransferPrescriptionCard from '#/views/doctor/online-consultation/components/TransferPrescriptionCard.vue';
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const prescriptionStore = usePrescriptionStore();
|
||||
|
||||
const props = defineProps({
|
||||
patient: {
|
||||
@@ -19,11 +23,13 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['reception-success', 'enter-chat', 'refresh-list']);
|
||||
const emit = defineEmits(['reception-success', 'enter-chat', 'refresh-list', 'transfer-import-success']);
|
||||
|
||||
const patientDetail = ref(null);
|
||||
const loading = ref(false);
|
||||
const receptionLoading = ref(false);
|
||||
const transferPrescription = ref(null);
|
||||
const loadingTransfer = ref(false);
|
||||
|
||||
// 获取患者详情
|
||||
const fetchPatientDetail = async () => {
|
||||
@@ -49,6 +55,13 @@ const fetchPatientDetail = async () => {
|
||||
// 确保正确解析返回数据
|
||||
const data = res?.result || res?.data || res || null;
|
||||
patientDetail.value = data;
|
||||
|
||||
// 检查是否有转诊挂号
|
||||
if (data?.register_order?.is_from_transfer === 1 && registerId) {
|
||||
await fetchTransferPrescription(registerId);
|
||||
} else {
|
||||
transferPrescription.value = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取患者详情失败:', error);
|
||||
message.error('获取患者详情失败,请重试');
|
||||
@@ -92,6 +105,33 @@ const handleReception = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取转诊信息
|
||||
const fetchTransferPrescription = async (registerId) => {
|
||||
if (!registerId) return;
|
||||
|
||||
loadingTransfer.value = true;
|
||||
try {
|
||||
const res = await getTransferPrescriptionByRegisterApi(registerId);
|
||||
const data = res?.result || res?.data || res;
|
||||
if (data && data.id) {
|
||||
transferPrescription.value = data;
|
||||
} else {
|
||||
transferPrescription.value = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取转诊信息失败:', error);
|
||||
transferPrescription.value = null;
|
||||
} finally {
|
||||
loadingTransfer.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 处理转诊导入成功
|
||||
const handleTransferImportSuccess = (prescriptionData) => {
|
||||
// 触发打开处方模态框的事件
|
||||
emit('transfer-import-success', prescriptionData);
|
||||
};
|
||||
|
||||
// 获取性别文本
|
||||
const getSexText = (sex) => {
|
||||
if (sex === 1) return '男';
|
||||
@@ -173,6 +213,15 @@ watch(
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<!-- 转诊处方卡片 -->
|
||||
<div v-if="transferPrescription" class="transfer-section">
|
||||
<TransferPrescriptionCard
|
||||
:transfer-data="transferPrescription"
|
||||
:register-id="patient?.register_id || patientDetail?.register_order?.id"
|
||||
@import-success="handleTransferImportSuccess"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 就诊记录 -->
|
||||
<div v-if="patientDetail.register_infos && patientDetail.register_infos.length > 0" class="register-info-section">
|
||||
<h3 class="section-title text-gray-900 dark:text-gray-100 border-b-2 border-blue-600 dark:border-blue-400">就诊记录</h3>
|
||||
@@ -266,6 +315,10 @@ watch(
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.transfer-section {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.register-info-section {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,12 @@ const handlePrescriptionSent = () => {
|
||||
// 可以在这里添加其他逻辑,如刷新聊天记录等
|
||||
};
|
||||
|
||||
// 处理转诊导入成功
|
||||
const handleTransferImportSuccess = (prescriptionData) => {
|
||||
// 打开处方模态框
|
||||
openPrescriptionModule(registerId.value);
|
||||
};
|
||||
|
||||
// 处理选择患者
|
||||
const handleSelectPatient = (patient) => {
|
||||
selectedPatient.value = patient;
|
||||
@@ -513,6 +519,7 @@ const handleAddPatientProductsToPrescription = async () => {
|
||||
@reception-success="handleReceptionSuccess"
|
||||
@enter-chat="handleEnterChat"
|
||||
@refresh-list="handleRefreshList"
|
||||
@transfer-import-success="handleTransferImportSuccess"
|
||||
class="patient-info-panel"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -5,8 +5,12 @@ import { getPatientDetail, reception } from '../api/index.ts';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { sendMessage } from '#/views/business/chat/utils/request';
|
||||
import { useUserStore } from '#/views/business/chat/stores/user';
|
||||
import { getTransferPrescriptionByRegisterApi } from '#/views/business/chat/api/transferPrescription';
|
||||
import TransferPrescriptionCard from './TransferPrescriptionCard.vue';
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const prescriptionStore = usePrescriptionStore();
|
||||
|
||||
const props = defineProps({
|
||||
patient: {
|
||||
@@ -19,11 +23,13 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['reception-success', 'enter-chat']);
|
||||
const emit = defineEmits(['reception-success', 'enter-chat', 'transfer-import-success']);
|
||||
|
||||
const patientDetail = ref(null);
|
||||
const loading = ref(false);
|
||||
const receptionLoading = ref(false);
|
||||
const transferPrescription = ref(null);
|
||||
const loadingTransfer = ref(false);
|
||||
|
||||
// 获取患者详情
|
||||
const fetchPatientDetail = async () => {
|
||||
@@ -49,6 +55,13 @@ const fetchPatientDetail = async () => {
|
||||
// 确保正确解析返回数据
|
||||
const data = res?.result || res?.data || res || null;
|
||||
patientDetail.value = data;
|
||||
|
||||
// 检查是否有转诊挂号
|
||||
if (data?.register_order?.is_from_transfer === 1 && registerId) {
|
||||
await fetchTransferPrescription(registerId);
|
||||
} else {
|
||||
transferPrescription.value = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取患者详情失败:', error);
|
||||
message.error('获取患者详情失败,请重试');
|
||||
@@ -58,6 +71,33 @@ const fetchPatientDetail = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取转诊信息
|
||||
const fetchTransferPrescription = async (registerId) => {
|
||||
if (!registerId) return;
|
||||
|
||||
loadingTransfer.value = true;
|
||||
try {
|
||||
const res = await getTransferPrescriptionByRegisterApi(registerId);
|
||||
const data = res?.result || res?.data || res;
|
||||
if (data && data.id) {
|
||||
transferPrescription.value = data;
|
||||
} else {
|
||||
transferPrescription.value = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取转诊信息失败:', error);
|
||||
transferPrescription.value = null;
|
||||
} finally {
|
||||
loadingTransfer.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 处理转诊导入成功
|
||||
const handleTransferImportSuccess = (prescriptionData) => {
|
||||
// 触发打开处方模态框的事件
|
||||
emit('transfer-import-success', prescriptionData);
|
||||
};
|
||||
|
||||
// 接诊
|
||||
const handleReception = async () => {
|
||||
if (!props.patient) {
|
||||
@@ -173,6 +213,15 @@ watch(
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<!-- 转诊处方卡片 -->
|
||||
<div v-if="transferPrescription" class="transfer-section">
|
||||
<TransferPrescriptionCard
|
||||
:transfer-data="transferPrescription"
|
||||
:register-id="patient?.register_id || patientDetail?.register_order?.id"
|
||||
@import-success="handleTransferImportSuccess"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 就诊记录 -->
|
||||
<div v-if="patientDetail.register_infos && patientDetail.register_infos.length > 0" class="register-info-section">
|
||||
<h3 class="section-title text-gray-900 dark:text-gray-100 border-b-2 border-blue-600 dark:border-blue-400">就诊记录</h3>
|
||||
@@ -265,6 +314,10 @@ watch(
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.transfer-section {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.register-info-section {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
@@ -177,6 +177,9 @@ defineExpose({
|
||||
<span :class="['status', getStatusClass(patient.status)]">
|
||||
{{ getStatusText(patient.status) }}
|
||||
</span>
|
||||
<span v-if="patient.is_from_transfer === 1" class="transfer-tag">
|
||||
转诊
|
||||
</span>
|
||||
<span v-if="patient.register_type" class="register-type-tag">
|
||||
{{ getRegisterTypeText(patient.register_type) }}
|
||||
</span>
|
||||
@@ -294,6 +297,23 @@ defineExpose({
|
||||
border-color: rgba(24, 144, 255, 0.3);
|
||||
}
|
||||
|
||||
.transfer-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
background: #fff7ed;
|
||||
color: #ea580c;
|
||||
border: 1px solid #fed7aa;
|
||||
}
|
||||
|
||||
.dark .transfer-tag {
|
||||
background: rgba(234, 88, 12, 0.2);
|
||||
color: #fb923c;
|
||||
border-color: rgba(234, 88, 12, 0.3);
|
||||
}
|
||||
|
||||
.status {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { Button, message, Tag } from 'ant-design-vue';
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
|
||||
const props = defineProps({
|
||||
transferData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
registerId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const prescriptionStore = usePrescriptionStore();
|
||||
const importing = ref(false);
|
||||
|
||||
// 解析转诊数据
|
||||
const transferInfo = computed(() => {
|
||||
if (typeof props.transferData === 'string') {
|
||||
try {
|
||||
return JSON.parse(props.transferData);
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return props.transferData;
|
||||
});
|
||||
|
||||
// 解析处方内容(从content字段,后端已解析为对象)
|
||||
const prescriptionContent = computed(() => {
|
||||
if (!transferInfo.value) return null;
|
||||
|
||||
// 如果已经有解析好的prescription字段,直接使用
|
||||
if (transferInfo.value.prescription && transferInfo.value.prescription.content) {
|
||||
return {
|
||||
clinical_diagnose: transferInfo.value.prescription.clinical_diagnose || '',
|
||||
doctor_order: transferInfo.value.prescription.doctor_order || '',
|
||||
content: transferInfo.value.prescription.content || [],
|
||||
};
|
||||
}
|
||||
|
||||
// 从content字段获取(后端已解析为对象)
|
||||
const content = transferInfo.value.content;
|
||||
if (!content) return null;
|
||||
|
||||
// 构建药品列表
|
||||
let drugList = [];
|
||||
|
||||
// 如果content是对象,检查repice字段
|
||||
if (typeof content === 'object' && !Array.isArray(content)) {
|
||||
// 从repice数组中提取药品
|
||||
if (content.repice && Array.isArray(content.repice)) {
|
||||
for (const recipe of content.repice) {
|
||||
if (recipe.content) {
|
||||
// recipe.content可能是已解析的数组,也可能是JSON字符串
|
||||
let recipeContent = recipe.content;
|
||||
if (typeof recipeContent === 'string') {
|
||||
try {
|
||||
recipeContent = JSON.parse(recipeContent);
|
||||
} catch {
|
||||
recipeContent = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 如果recipeContent是数组,合并到drugList
|
||||
if (Array.isArray(recipeContent)) {
|
||||
drugList = drugList.concat(recipeContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
clinical_diagnose: content.clinical_diagnose || transferInfo.value.original_prescription?.clinical_diagnose || '',
|
||||
doctor_order: content.doctor_order || transferInfo.value.original_prescription?.doctor_order || '',
|
||||
content: drugList,
|
||||
};
|
||||
} else if (Array.isArray(content)) {
|
||||
// 如果content直接是数组,说明是药品列表
|
||||
return {
|
||||
clinical_diagnose: transferInfo.value.original_prescription?.clinical_diagnose || '',
|
||||
doctor_order: transferInfo.value.original_prescription?.doctor_order || '',
|
||||
content: content,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// 转诊状态文本
|
||||
const statusText = computed(() => {
|
||||
const status = transferInfo.value.status;
|
||||
const statusMap = {
|
||||
0: { text: '待确认', color: 'orange' },
|
||||
1: { text: '已确认', color: 'blue' },
|
||||
2: { text: '已导入', color: 'green' },
|
||||
3: { text: '已取消', color: 'red' },
|
||||
};
|
||||
return statusMap[status] || { text: '未知', color: 'default' };
|
||||
});
|
||||
|
||||
// 将转接方药品数据转换成addProducts需要的格式
|
||||
const convertDrugDataForImport = (drug) => {
|
||||
// addProducts期望的数据结构:
|
||||
// {
|
||||
// id: ...,
|
||||
// drug: {
|
||||
// id: ...,
|
||||
// drug_name: ...,
|
||||
// number: ...,
|
||||
// time_id: ...,
|
||||
// type_id: ...,
|
||||
// frequency_id: ...,
|
||||
// unit_id: ...,
|
||||
// way_id: ...,
|
||||
// image: ...,
|
||||
// instruction: ...,
|
||||
// type: ...,
|
||||
// },
|
||||
// price: ...,
|
||||
// }
|
||||
|
||||
// 转接方的药品数据结构:
|
||||
// {
|
||||
// id: ...,
|
||||
// drug_id: ...,
|
||||
// name: ...,
|
||||
// number: ...,
|
||||
// price: ...,
|
||||
// unit: {...},
|
||||
// use_unit: {...},
|
||||
// ...
|
||||
// }
|
||||
|
||||
return {
|
||||
id: drug.id || drug.drug_id || 0,
|
||||
drug: {
|
||||
id: drug.drug_id || drug.id || 0,
|
||||
drug_name: drug.name || drug.drug_name || '',
|
||||
number: drug.number || 1,
|
||||
time_id: drug.time_id || drug.use_num?.id || 0,
|
||||
type_id: drug.type_id || drug.use_type?.id || 0,
|
||||
frequency_id: drug.frequency_id || drug.use_frequency?.id || 0,
|
||||
unit_id: drug.unit_id || drug.unit?.id || drug.use_unit?.id || 0,
|
||||
way_id: drug.way_id || drug.use_way?.id || 0,
|
||||
image: drug.image || '',
|
||||
instruction: drug.instruction || '',
|
||||
type: drug.type || transferInfo.value?.prescription_type || 1,
|
||||
},
|
||||
price: parseFloat(drug.price) || 0,
|
||||
};
|
||||
};
|
||||
|
||||
// 一键导入处方到在线问诊(从前端数据导入)
|
||||
const handleImportToPrescription = async () => {
|
||||
if (!props.transferData?.id) {
|
||||
message.warning('转诊信息不完整');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.registerId) {
|
||||
message.warning('挂号ID不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!prescriptionContent.value || !prescriptionContent.value.content || !Array.isArray(prescriptionContent.value.content)) {
|
||||
message.warning('处方内容格式错误,无法导入');
|
||||
return;
|
||||
}
|
||||
|
||||
importing.value = true;
|
||||
try {
|
||||
// 先将处方类型设置为中药(1)
|
||||
prescriptionStore.changeCategory(1);
|
||||
|
||||
// 直接使用前端已获取的数据进行导入
|
||||
const drugList = prescriptionContent.value.content;
|
||||
|
||||
if (!drugList || drugList.length === 0) {
|
||||
message.warning('处方中没有药品信息');
|
||||
return;
|
||||
}
|
||||
|
||||
// 导入药品(需要转换数据格式)
|
||||
let addedCount = 0;
|
||||
for (const drug of drugList) {
|
||||
// 转换数据格式
|
||||
const convertedDrugData = convertDrugDataForImport(drug);
|
||||
const success = prescriptionStore.addProducts(convertedDrugData);
|
||||
if (success) {
|
||||
addedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 导入诊断和医嘱
|
||||
if (prescriptionContent.value.clinical_diagnose) {
|
||||
prescriptionStore.diagnosis = prescriptionContent.value.clinical_diagnose;
|
||||
}
|
||||
if (prescriptionContent.value.doctor_order) {
|
||||
prescriptionStore.medicalAdvice = prescriptionContent.value.doctor_order;
|
||||
}
|
||||
|
||||
if (addedCount > 0) {
|
||||
message.success(`已成功导入 ${addedCount} 个药品到处方单`);
|
||||
// 构建处方数据对象,用于触发事件
|
||||
const prescriptionData = {
|
||||
content: drugList,
|
||||
clinical_diagnose: prescriptionContent.value.clinical_diagnose,
|
||||
doctor_order: prescriptionContent.value.doctor_order,
|
||||
register_id: props.registerId,
|
||||
};
|
||||
// 触发事件,通知父组件打开处方模态框
|
||||
emit('import-success', prescriptionData);
|
||||
} else {
|
||||
message.warning('所有药品已在处方中');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('导入转诊处方失败:', error);
|
||||
message.error('导入转诊处方失败,请重试');
|
||||
} finally {
|
||||
importing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const emit = defineEmits(['import-success']);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="transfer-prescription-card">
|
||||
<!-- 卡片头部 -->
|
||||
<div class="card-header">
|
||||
<div class="header-icon">
|
||||
<i class="fas fa-exchange-alt"></i>
|
||||
</div>
|
||||
<div class="header-title">转诊处方</div>
|
||||
<Tag :color="statusText.color" class="status-tag">
|
||||
{{ statusText.text }}
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<div class="card-body">
|
||||
<!-- 转诊诊所信息 -->
|
||||
<div v-if="transferInfo.transfer_store" class="info-row">
|
||||
<div class="info-icon">
|
||||
<i class="fas fa-hospital"></i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">转诊诊所</div>
|
||||
<div class="info-value">{{ transferInfo.transfer_store.name || '未知诊所' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 委托诊所信息 -->
|
||||
<div v-if="transferInfo.delegate_store" class="info-row">
|
||||
<div class="info-icon">
|
||||
<i class="fas fa-clinic-medical"></i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">委托诊所</div>
|
||||
<div class="info-value">{{ transferInfo.delegate_store.name || '未知诊所' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 处方编号 -->
|
||||
<div v-if="transferInfo.prescription_no" class="info-row">
|
||||
<div class="info-icon">
|
||||
<i class="fas fa-file-prescription"></i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">处方编号</div>
|
||||
<div class="info-value">{{ transferInfo.prescription_no }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 转诊时间 -->
|
||||
<div v-if="transferInfo.transfer_time" class="info-row">
|
||||
<div class="info-icon">
|
||||
<i class="fas fa-clock"></i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">转诊时间</div>
|
||||
<div class="info-value">{{ transferInfo.transfer_time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 转诊原因 -->
|
||||
<div v-if="transferInfo.transfer_reason" class="info-row">
|
||||
<div class="info-icon">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">转诊原因</div>
|
||||
<div class="info-value">{{ transferInfo.transfer_reason }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡片底部操作 -->
|
||||
<div v-if="transferInfo.status !== 3" class="card-footer">
|
||||
<Button
|
||||
v-if="transferInfo.status !== 2"
|
||||
type="primary"
|
||||
:loading="importing"
|
||||
@click="handleImportToPrescription"
|
||||
class="import-btn"
|
||||
>
|
||||
<i class="fas fa-download mr-1"></i>
|
||||
添加到处方单
|
||||
</Button>
|
||||
<Button v-else type="default" disabled class="import-btn">
|
||||
已导入
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.transfer-prescription-card {
|
||||
width: 100%;
|
||||
min-width: 420px;
|
||||
max-width: 520px;
|
||||
background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);
|
||||
border-radius: 16px;
|
||||
border: 1px solid #fed7aa;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.transfer-prescription-card:hover {
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* 卡片头部 */
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px 20px;
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
flex: 1;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
/* 卡片内容 */
|
||||
.card-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 14px;
|
||||
padding: 14px 16px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid #fed7aa;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-row:hover {
|
||||
border-color: #f97316;
|
||||
background: #fff7ed;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #f97316;
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 12px;
|
||||
color: #64748b;
|
||||
margin-bottom: 4px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
line-height: 1.6;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* 卡片底部 */
|
||||
.card-footer {
|
||||
padding: 16px 20px;
|
||||
background: #fff7ed;
|
||||
border-top: 1px solid #fed7aa;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.import-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.import-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3);
|
||||
}
|
||||
|
||||
/* 暗黑模式适配 */
|
||||
.dark .transfer-prescription-card {
|
||||
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
|
||||
border-color: #334155;
|
||||
}
|
||||
|
||||
.dark .info-row {
|
||||
background: #1e293b;
|
||||
border-color: #334155;
|
||||
}
|
||||
|
||||
.dark .info-row:hover {
|
||||
background: #334155;
|
||||
}
|
||||
|
||||
.dark .info-value {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.dark .card-footer {
|
||||
background: #0f172a;
|
||||
border-color: #334155;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,442 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { Card, Button, Tag, message } from 'ant-design-vue';
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
registerId: {
|
||||
type: [Number, String],
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['view-detail', 'import-success']);
|
||||
|
||||
const prescriptionStore = usePrescriptionStore();
|
||||
const importing = ref(false);
|
||||
|
||||
// 解析转接方数据
|
||||
const transferInfo = computed(() => {
|
||||
if (typeof props.content === 'string') {
|
||||
try {
|
||||
return JSON.parse(props.content);
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return props.content;
|
||||
});
|
||||
|
||||
// 解析处方内容(从content字段,后端已解析为对象)
|
||||
const prescriptionContent = computed(() => {
|
||||
if (!transferInfo.value) return null;
|
||||
|
||||
// 如果已经有解析好的prescription字段,直接使用
|
||||
if (transferInfo.value.prescription && transferInfo.value.prescription.content) {
|
||||
return {
|
||||
clinical_diagnose: transferInfo.value.prescription.clinical_diagnose || '',
|
||||
doctor_order: transferInfo.value.prescription.doctor_order || '',
|
||||
content: transferInfo.value.prescription.content || [],
|
||||
};
|
||||
}
|
||||
|
||||
// 从content字段获取(后端已解析为对象)
|
||||
const content = transferInfo.value.content;
|
||||
if (!content) return null;
|
||||
|
||||
// 构建药品列表
|
||||
let drugList = [];
|
||||
|
||||
// 如果content是对象,检查repice字段
|
||||
if (typeof content === 'object' && !Array.isArray(content)) {
|
||||
// 从repice数组中提取药品
|
||||
if (content.repice && Array.isArray(content.repice)) {
|
||||
for (const recipe of content.repice) {
|
||||
if (recipe.content) {
|
||||
// recipe.content可能是已解析的数组,也可能是JSON字符串
|
||||
let recipeContent = recipe.content;
|
||||
if (typeof recipeContent === 'string') {
|
||||
try {
|
||||
recipeContent = JSON.parse(recipeContent);
|
||||
} catch {
|
||||
recipeContent = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 如果recipeContent是数组,合并到drugList
|
||||
if (Array.isArray(recipeContent)) {
|
||||
drugList = drugList.concat(recipeContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
clinical_diagnose: content.clinical_diagnose || transferInfo.value.original_prescription?.clinical_diagnose || '',
|
||||
doctor_order: content.doctor_order || transferInfo.value.original_prescription?.doctor_order || '',
|
||||
content: drugList,
|
||||
};
|
||||
} else if (Array.isArray(content)) {
|
||||
// 如果content直接是数组,说明是药品列表
|
||||
return {
|
||||
clinical_diagnose: transferInfo.value.original_prescription?.clinical_diagnose || '',
|
||||
doctor_order: transferInfo.value.original_prescription?.doctor_order || '',
|
||||
content: content,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// 转诊状态文本
|
||||
const statusText = computed(() => {
|
||||
const status = transferInfo.value.status;
|
||||
const statusMap = {
|
||||
0: { text: '待确认', color: 'orange' },
|
||||
1: { text: '已确认', color: 'blue' },
|
||||
2: { text: '已导入', color: 'green' },
|
||||
3: { text: '已取消', color: 'red' },
|
||||
};
|
||||
return statusMap[status] || { text: '未知', color: 'default' };
|
||||
});
|
||||
|
||||
// 查看详情
|
||||
const handleViewDetail = () => {
|
||||
emit('view-detail', transferInfo.value);
|
||||
};
|
||||
|
||||
// 将转接方药品数据转换成addProducts需要的格式
|
||||
const convertDrugDataForImport = (drug) => {
|
||||
// addProducts期望的数据结构:
|
||||
// {
|
||||
// id: ...,
|
||||
// drug: {
|
||||
// id: ...,
|
||||
// drug_name: ...,
|
||||
// number: ...,
|
||||
// time_id: ...,
|
||||
// type_id: ...,
|
||||
// frequency_id: ...,
|
||||
// unit_id: ...,
|
||||
// way_id: ...,
|
||||
// image: ...,
|
||||
// instruction: ...,
|
||||
// type: ...,
|
||||
// },
|
||||
// price: ...,
|
||||
// }
|
||||
|
||||
// 转接方的药品数据结构:
|
||||
// {
|
||||
// id: ...,
|
||||
// drug_id: ...,
|
||||
// name: ...,
|
||||
// number: ...,
|
||||
// price: ...,
|
||||
// unit: {...},
|
||||
// use_unit: {...},
|
||||
// ...
|
||||
// }
|
||||
|
||||
return {
|
||||
id: drug.id || drug.drug_id || 0,
|
||||
drug: {
|
||||
id: drug.drug_id || drug.id || 0,
|
||||
drug_name: drug.name || drug.drug_name || '',
|
||||
number: drug.number || 1,
|
||||
time_id: drug.time_id || drug.use_num?.id || 0,
|
||||
type_id: drug.type_id || drug.use_type?.id || 0,
|
||||
frequency_id: drug.frequency_id || drug.use_frequency?.id || 0,
|
||||
unit_id: drug.unit_id || drug.unit?.id || drug.use_unit?.id || 0,
|
||||
way_id: drug.way_id || drug.use_way?.id || 0,
|
||||
image: drug.image || '',
|
||||
instruction: drug.instruction || '',
|
||||
type: drug.type || transferInfo.value?.prescription_type || 1,
|
||||
},
|
||||
price: parseFloat(drug.price) || 0,
|
||||
};
|
||||
};
|
||||
|
||||
// 一键导入处方到在线问诊(从前端数据导入)
|
||||
const handleImportToPrescription = async () => {
|
||||
if (!transferInfo.value?.transfer_id && !transferInfo.value?.id) {
|
||||
message.warning('转接方信息不完整');
|
||||
return;
|
||||
}
|
||||
|
||||
const registerId = props.registerId || transferInfo.value.register_id;
|
||||
|
||||
if (!registerId) {
|
||||
message.warning('挂号ID不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!prescriptionContent.value || !prescriptionContent.value.content || !Array.isArray(prescriptionContent.value.content)) {
|
||||
message.warning('处方内容格式错误,无法导入');
|
||||
return;
|
||||
}
|
||||
|
||||
importing.value = true;
|
||||
try {
|
||||
// 先将处方类型设置为中药(1)
|
||||
prescriptionStore.changeCategory(1);
|
||||
|
||||
// 直接使用前端已获取的数据进行导入
|
||||
const drugList = prescriptionContent.value.content;
|
||||
|
||||
if (!drugList || drugList.length === 0) {
|
||||
message.warning('处方中没有药品信息');
|
||||
return;
|
||||
}
|
||||
|
||||
// 导入药品(需要转换数据格式)
|
||||
let addedCount = 0;
|
||||
for (const drug of drugList) {
|
||||
// 转换数据格式
|
||||
const convertedDrugData = convertDrugDataForImport(drug);
|
||||
const success = prescriptionStore.addProducts(convertedDrugData);
|
||||
if (success) {
|
||||
addedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 导入诊断和医嘱
|
||||
if (prescriptionContent.value.clinical_diagnose) {
|
||||
prescriptionStore.diagnosis = prescriptionContent.value.clinical_diagnose;
|
||||
}
|
||||
if (prescriptionContent.value.doctor_order) {
|
||||
prescriptionStore.medicalAdvice = prescriptionContent.value.doctor_order;
|
||||
}
|
||||
|
||||
if (addedCount > 0) {
|
||||
message.success(`已成功导入 ${addedCount} 个药品到处方单`);
|
||||
// 构建处方数据对象,用于触发事件
|
||||
const prescriptionData = {
|
||||
content: drugList,
|
||||
clinical_diagnose: prescriptionContent.value.clinical_diagnose,
|
||||
doctor_order: prescriptionContent.value.doctor_order,
|
||||
register_id: registerId,
|
||||
};
|
||||
// 触发事件,通知父组件打开处方模态框
|
||||
emit('import-success', prescriptionData);
|
||||
} else {
|
||||
message.warning('所有药品已在处方中');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('导入转接方处方失败:', error);
|
||||
message.error('导入转接方处方失败,请重试');
|
||||
} finally {
|
||||
importing.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="transfer-prescription-message-card" :bordered="true" style="max-width: 400px">
|
||||
<!-- 卡片头部 -->
|
||||
<div class="card-header">
|
||||
<div class="header-icon">
|
||||
<i class="fas fa-exchange-alt"></i>
|
||||
</div>
|
||||
<div class="header-title">转接方</div>
|
||||
<Tag :color="statusText.color" class="status-tag">
|
||||
{{ statusText.text }}
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<div class="card-body">
|
||||
<!-- 转诊诊所信息 -->
|
||||
<div v-if="transferInfo.transfer_store" class="info-row">
|
||||
<div class="info-label">转诊诊所:</div>
|
||||
<div class="info-value">{{ transferInfo.transfer_store.name || '未知诊所' }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 委托诊所信息 -->
|
||||
<div v-if="transferInfo.delegate_store" class="info-row">
|
||||
<div class="info-label">委托诊所:</div>
|
||||
<div class="info-value">{{ transferInfo.delegate_store.name || '未知诊所' }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 处方编号 -->
|
||||
<div v-if="transferInfo.prescription_no" class="info-row">
|
||||
<div class="info-label">处方编号:</div>
|
||||
<div class="info-value">{{ transferInfo.prescription_no }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 转诊时间 -->
|
||||
<div v-if="transferInfo.transfer_time" class="info-row">
|
||||
<div class="info-label">转诊时间:</div>
|
||||
<div class="info-value">{{ transferInfo.transfer_time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡片底部操作 -->
|
||||
<div class="card-footer">
|
||||
<Button
|
||||
type="default"
|
||||
size="small"
|
||||
@click="handleViewDetail"
|
||||
class="view-btn"
|
||||
>
|
||||
查看详情
|
||||
</Button>
|
||||
<Button
|
||||
v-if="transferInfo.status !== 3 && transferInfo.status !== 2"
|
||||
type="primary"
|
||||
size="small"
|
||||
:loading="importing"
|
||||
@click="handleImportToPrescription"
|
||||
class="import-btn"
|
||||
>
|
||||
<i class="fas fa-download mr-1"></i>
|
||||
导入处方
|
||||
</Button>
|
||||
<Button
|
||||
v-else-if="transferInfo.status === 2"
|
||||
type="default"
|
||||
size="small"
|
||||
disabled
|
||||
class="import-btn"
|
||||
>
|
||||
已导入
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.transfer-prescription-message-card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.transfer-prescription-message-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* 卡片头部 */
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
padding: 2px 8px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* 卡片内容 */
|
||||
.card-body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
min-width: 80px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dark .info-label {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #1e293b;
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.dark .info-value {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
/* 卡片底部 */
|
||||
.card-footer {
|
||||
padding: 12px 16px;
|
||||
background: #f5f5f5;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.dark .card-footer {
|
||||
background: #1e293b;
|
||||
border-top-color: #374151;
|
||||
}
|
||||
|
||||
.view-btn,
|
||||
.import-btn {
|
||||
font-size: 13px;
|
||||
padding: 4px 12px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.import-btn {
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.import-btn:hover:not(:disabled) {
|
||||
background: linear-gradient(135deg, #ea580c 0%, #dc2626 100%);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 8px rgba(249, 115, 22, 0.3);
|
||||
}
|
||||
|
||||
/* 暗黑模式适配 */
|
||||
.dark .transfer-prescription-message-card {
|
||||
background: #1e293b;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.dark .transfer-prescription-message-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,490 @@
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { Drawer, Descriptions, Button, Tag, message, Empty } from 'ant-design-vue';
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
import { getTransferPrescriptionByRegisterApi } from '#/views/business/chat/api/transferPrescription';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
registerId: {
|
||||
type: [Number, String],
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'import-success']);
|
||||
|
||||
const prescriptionStore = usePrescriptionStore();
|
||||
const transferData = ref(null);
|
||||
const loading = ref(false);
|
||||
const importing = ref(false);
|
||||
|
||||
// 解析转诊数据
|
||||
const transferInfo = computed(() => {
|
||||
if (!transferData.value) return null;
|
||||
if (typeof transferData.value === 'string') {
|
||||
try {
|
||||
return JSON.parse(transferData.value);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return transferData.value;
|
||||
});
|
||||
|
||||
// 解析处方内容(从content字段,后端已解析为对象)
|
||||
const prescriptionContent = computed(() => {
|
||||
if (!transferInfo.value) return null;
|
||||
|
||||
// 如果已经有解析好的prescription字段,直接使用
|
||||
if (transferInfo.value.prescription && transferInfo.value.prescription.content) {
|
||||
return {
|
||||
clinical_diagnose: transferInfo.value.prescription.clinical_diagnose || '',
|
||||
doctor_order: transferInfo.value.prescription.doctor_order || '',
|
||||
content: transferInfo.value.prescription.content || [],
|
||||
};
|
||||
}
|
||||
|
||||
// 从content字段获取(后端已解析为对象)
|
||||
const content = transferInfo.value.content;
|
||||
if (!content) return null;
|
||||
|
||||
// 构建药品列表
|
||||
let drugList = [];
|
||||
|
||||
// 如果content是对象,检查repice字段
|
||||
if (typeof content === 'object' && !Array.isArray(content)) {
|
||||
// 从repice数组中提取药品
|
||||
if (content.repice && Array.isArray(content.repice)) {
|
||||
for (const recipe of content.repice) {
|
||||
if (recipe.content) {
|
||||
// recipe.content可能是已解析的数组,也可能是JSON字符串
|
||||
let recipeContent = recipe.content;
|
||||
if (typeof recipeContent === 'string') {
|
||||
try {
|
||||
recipeContent = JSON.parse(recipeContent);
|
||||
} catch {
|
||||
recipeContent = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 如果recipeContent是数组,合并到drugList
|
||||
if (Array.isArray(recipeContent)) {
|
||||
drugList = drugList.concat(recipeContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
clinical_diagnose: content.clinical_diagnose || transferInfo.value.original_prescription?.clinical_diagnose || '',
|
||||
doctor_order: content.doctor_order || transferInfo.value.original_prescription?.doctor_order || '',
|
||||
content: drugList,
|
||||
};
|
||||
} else if (Array.isArray(content)) {
|
||||
// 如果content直接是数组,说明是药品列表
|
||||
return {
|
||||
clinical_diagnose: transferInfo.value.original_prescription?.clinical_diagnose || '',
|
||||
doctor_order: transferInfo.value.original_prescription?.doctor_order || '',
|
||||
content: content,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// 转诊状态文本
|
||||
const statusText = computed(() => {
|
||||
if (!transferInfo.value) return { text: '未知', color: 'default' };
|
||||
const status = transferInfo.value.status;
|
||||
const statusMap = {
|
||||
0: { text: '待确认', color: 'orange' },
|
||||
1: { text: '已确认', color: 'blue' },
|
||||
2: { text: '已导入', color: 'green' },
|
||||
3: { text: '已取消', color: 'red' },
|
||||
};
|
||||
return statusMap[status] || { text: '未知', color: 'default' };
|
||||
});
|
||||
|
||||
// 获取转接方数据
|
||||
const fetchTransferPrescription = async () => {
|
||||
if (!props.registerId) {
|
||||
message.warning('挂号ID不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getTransferPrescriptionByRegisterApi(props.registerId);
|
||||
const data = res?.result || res?.data || res;
|
||||
if (data && data.id) {
|
||||
transferData.value = data;
|
||||
} else {
|
||||
transferData.value = null;
|
||||
message.warning('未找到转接方信息');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取转接方信息失败:', error);
|
||||
message.error('获取转接方信息失败,请重试');
|
||||
transferData.value = null;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 将转接方药品数据转换成addProducts需要的格式
|
||||
const convertDrugDataForImport = (drug) => {
|
||||
// addProducts期望的数据结构:
|
||||
// {
|
||||
// id: ...,
|
||||
// drug: {
|
||||
// id: ...,
|
||||
// drug_name: ...,
|
||||
// number: ...,
|
||||
// time_id: ...,
|
||||
// type_id: ...,
|
||||
// frequency_id: ...,
|
||||
// unit_id: ...,
|
||||
// way_id: ...,
|
||||
// image: ...,
|
||||
// instruction: ...,
|
||||
// type: ...,
|
||||
// },
|
||||
// price: ...,
|
||||
// }
|
||||
|
||||
// 转接方的药品数据结构:
|
||||
// {
|
||||
// id: ...,
|
||||
// drug_id: ...,
|
||||
// name: ...,
|
||||
// number: ...,
|
||||
// price: ...,
|
||||
// unit: {...},
|
||||
// use_unit: {...},
|
||||
// ...
|
||||
// }
|
||||
|
||||
return {
|
||||
id: drug.id || drug.drug_id || 0,
|
||||
drug: {
|
||||
id: drug.drug_id || drug.id || 0,
|
||||
drug_name: drug.name || drug.drug_name || '',
|
||||
number: drug.number || 1,
|
||||
time_id: drug.time_id || drug.use_num?.id || 0,
|
||||
type_id: drug.type_id || drug.use_type?.id || 0,
|
||||
frequency_id: drug.frequency_id || drug.use_frequency?.id || 0,
|
||||
unit_id: drug.unit_id || drug.unit?.id || drug.use_unit?.id || 0,
|
||||
way_id: drug.way_id || drug.use_way?.id || 0,
|
||||
image: drug.image || '',
|
||||
instruction: drug.instruction || '',
|
||||
type: drug.type || transferInfo.value?.prescription_type || 1,
|
||||
},
|
||||
price: parseFloat(drug.price) || 0,
|
||||
};
|
||||
};
|
||||
|
||||
// 一键导入处方到在线问诊(从前端数据导入)
|
||||
const handleImportToPrescription = async () => {
|
||||
if (!transferInfo.value?.id) {
|
||||
message.warning('转接方信息不完整');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.registerId) {
|
||||
message.warning('挂号ID不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!prescriptionContent.value || !prescriptionContent.value.content || !Array.isArray(prescriptionContent.value.content)) {
|
||||
message.warning('处方内容格式错误,无法导入');
|
||||
return;
|
||||
}
|
||||
|
||||
importing.value = true;
|
||||
try {
|
||||
// 先将处方类型设置为中药(1)
|
||||
prescriptionStore.changeCategory(1);
|
||||
|
||||
// 直接使用前端已获取的数据进行导入
|
||||
const drugList = prescriptionContent.value.content;
|
||||
|
||||
if (!drugList || drugList.length === 0) {
|
||||
message.warning('处方中没有药品信息');
|
||||
return;
|
||||
}
|
||||
|
||||
// 导入药品(需要转换数据格式)
|
||||
let addedCount = 0;
|
||||
for (const drug of drugList) {
|
||||
// 转换数据格式
|
||||
const convertedDrugData = convertDrugDataForImport(drug);
|
||||
const success = prescriptionStore.addProducts(convertedDrugData);
|
||||
if (success) {
|
||||
addedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 导入诊断和医嘱
|
||||
if (prescriptionContent.value.clinical_diagnose) {
|
||||
prescriptionStore.diagnosis = prescriptionContent.value.clinical_diagnose;
|
||||
}
|
||||
if (prescriptionContent.value.doctor_order) {
|
||||
prescriptionStore.medicalAdvice = prescriptionContent.value.doctor_order;
|
||||
}
|
||||
|
||||
if (addedCount > 0) {
|
||||
message.success(`已成功导入 ${addedCount} 个药品到处方单`);
|
||||
// 构建处方数据对象,用于触发事件
|
||||
const prescriptionData = {
|
||||
content: drugList,
|
||||
clinical_diagnose: prescriptionContent.value.clinical_diagnose,
|
||||
doctor_order: prescriptionContent.value.doctor_order,
|
||||
register_id: props.registerId,
|
||||
};
|
||||
// 触发事件,通知父组件打开处方模态框
|
||||
emit('import-success', prescriptionData);
|
||||
// 关闭抽屉
|
||||
emit('update:visible', false);
|
||||
} else {
|
||||
message.warning('所有药品已在处方中');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('导入转接方处方失败:', error);
|
||||
message.error('导入转接方处方失败,请重试');
|
||||
} finally {
|
||||
importing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭抽屉
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
// 监听visible变化,打开时获取数据
|
||||
watch(
|
||||
() => props.visible,
|
||||
(newVal) => {
|
||||
if (newVal && props.registerId) {
|
||||
fetchTransferPrescription();
|
||||
} else {
|
||||
transferData.value = null;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Drawer
|
||||
:open="visible"
|
||||
title="转接方查看"
|
||||
:width="600"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div v-if="loading" class="loading-container">
|
||||
<text>加载中...</text>
|
||||
</div>
|
||||
|
||||
<div v-else-if="!transferInfo" class="empty-container">
|
||||
<Empty description="未找到转接方信息" />
|
||||
</div>
|
||||
|
||||
<div v-else class="transfer-prescription-drawer">
|
||||
<!-- 状态标签 -->
|
||||
<div class="status-section">
|
||||
<Tag :color="statusText.color" class="status-tag">
|
||||
{{ statusText.text }}
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<Descriptions
|
||||
:column="1"
|
||||
bordered
|
||||
class="info-descriptions"
|
||||
title="基本信息"
|
||||
>
|
||||
<Descriptions.Item v-if="transferInfo.transfer_store" label="转诊诊所">
|
||||
{{ transferInfo.transfer_store.name || '未知诊所' }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item v-if="transferInfo.delegate_store" label="委托诊所">
|
||||
{{ transferInfo.delegate_store.name || '未知诊所' }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item v-if="transferInfo.prescription_no" label="处方编号">
|
||||
{{ transferInfo.prescription_no }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item v-if="transferInfo.transfer_time" label="转诊时间">
|
||||
{{ transferInfo.transfer_time }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item v-if="transferInfo.transfer_reason" label="转诊原因">
|
||||
{{ transferInfo.transfer_reason }}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<!-- 处方内容 -->
|
||||
<div v-if="prescriptionContent" class="prescription-section">
|
||||
<h3 class="section-title">处方内容</h3>
|
||||
<div v-if="prescriptionContent.clinical_diagnose" class="prescription-item">
|
||||
<strong>临床诊断:</strong>
|
||||
<span>{{ prescriptionContent.clinical_diagnose }}</span>
|
||||
</div>
|
||||
<div v-if="prescriptionContent.doctor_order" class="prescription-item">
|
||||
<strong>医嘱:</strong>
|
||||
<span>{{ prescriptionContent.doctor_order }}</span>
|
||||
</div>
|
||||
<div v-if="prescriptionContent.content && prescriptionContent.content.length > 0" class="prescription-content">
|
||||
<strong>药品列表:</strong>
|
||||
<div class="drug-list">
|
||||
<div
|
||||
v-for="(drug, index) in prescriptionContent.content"
|
||||
:key="index"
|
||||
class="drug-item"
|
||||
>
|
||||
<span>{{ drug.drug_name || drug.name || '未知药品' }}</span>
|
||||
<span v-if="drug.number"> × {{ drug.number }}</span>
|
||||
<span v-if="drug.unit?.name || drug.unit"> {{ drug.unit?.name || drug.unit }}</span>
|
||||
<span v-if="drug.use_type?.name || drug.use_frequency?.name" class="drug-usage">
|
||||
({{ [drug.use_type?.name, drug.use_frequency?.name, drug.use_num?.name].filter(Boolean).join(',') }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="prescriptionContent.content && prescriptionContent.content.length === 0" class="prescription-item">
|
||||
<span class="text-gray-400">暂无药品信息</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div v-if="transferInfo.status !== 3" class="action-section">
|
||||
<Button
|
||||
v-if="transferInfo.status !== 2"
|
||||
type="primary"
|
||||
:loading="importing"
|
||||
block
|
||||
size="large"
|
||||
@click="handleImportToPrescription"
|
||||
>
|
||||
<i class="fas fa-download mr-1"></i>
|
||||
导入到处方单
|
||||
</Button>
|
||||
<Button v-else type="default" block disabled>
|
||||
已导入
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.loading-container,
|
||||
.empty-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.transfer-prescription-drawer {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.status-section {
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 6px 16px;
|
||||
}
|
||||
|
||||
.info-descriptions {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.prescription-section {
|
||||
margin-bottom: 24px;
|
||||
padding: 16px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.dark .prescription-section {
|
||||
background: #1e293b;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.dark .section-title {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.prescription-item {
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.prescription-item strong {
|
||||
color: #666;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.dark .prescription-item strong {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.prescription-content {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.drug-list {
|
||||
margin-top: 12px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.drug-item {
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dark .drug-item {
|
||||
border-bottom-color: #374151;
|
||||
}
|
||||
|
||||
.drug-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.drug-usage {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.dark .drug-usage {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.action-section {
|
||||
margin-top: 32px;
|
||||
padding-top: 24px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.dark .action-section {
|
||||
border-top-color: #374151;
|
||||
}
|
||||
</style>
|
||||
@@ -272,6 +272,15 @@ const handleEndConsultationSuccess = () => {
|
||||
patientListRef.value?.fetchPatientList();
|
||||
};
|
||||
|
||||
// 处理转诊导入成功
|
||||
const handleTransferImportSuccess = (prescriptionData) => {
|
||||
// 打开处方模态框
|
||||
const targetRegisterId = registerId.value || prescriptionData?.register_id;
|
||||
if (targetRegisterId) {
|
||||
openPrescriptionModule(targetRegisterId);
|
||||
}
|
||||
};
|
||||
|
||||
// 将患者购买的药品加入处方单
|
||||
const handleAddPatientProductsToPrescription = async () => {
|
||||
// 检查处方store是否已初始化
|
||||
@@ -374,6 +383,7 @@ const handleAddPatientProductsToPrescription = async () => {
|
||||
:doctor-id="userStore.currentUser?.doctor_id"
|
||||
@reception-success="handleReceptionSuccess"
|
||||
@enter-chat="handleEnterChat"
|
||||
@transfer-import-success="handleTransferImportSuccess"
|
||||
class="patient-info-panel"
|
||||
/>
|
||||
</template>
|
||||
@@ -385,6 +395,7 @@ const handleAddPatientProductsToPrescription = async () => {
|
||||
v-if="chatStore.currentFriend"
|
||||
@open-prescription="openPrescriptionModule"
|
||||
@end-consultation-success="handleEndConsultationSuccess"
|
||||
@transfer-import-success="handleTransferImportSuccess"
|
||||
/>
|
||||
<EmptyState v-else />
|
||||
</div>
|
||||
|
||||
@@ -149,3 +149,11 @@ export async function batchSyncDrugPriceApi(ids: number[]) {
|
||||
ids,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新诊所类型
|
||||
* @param data 包含id和clinic_type的对象,clinic_type: 1=西医诊所, 2=中医诊所
|
||||
*/
|
||||
export async function updateClinicTypeApi(data: { id: number; clinic_type: number }) {
|
||||
return requestClient.post<any>(`${prefix}update-clinic-type`, data);
|
||||
}
|
||||
|
||||
@@ -106,6 +106,22 @@ export const modalFormProps: VbenFormProps = {
|
||||
label: '是否包邮',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
// 诊所类型(单选)
|
||||
component: 'RadioGroup',
|
||||
formItemClass: 'col-span-6',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '西医诊所', value: 1 },
|
||||
{ label: '中医诊所', value: 2 },
|
||||
],
|
||||
placeholder: '诊所类型',
|
||||
},
|
||||
fieldName: 'clinic_type',
|
||||
label: '诊所类型',
|
||||
rules: 'required',
|
||||
defaultValue: 2, // 默认中医诊所
|
||||
},
|
||||
{
|
||||
// 是否订阅价格波动(单选,新增和编辑时都显示)
|
||||
component: 'RadioGroup',
|
||||
|
||||
@@ -25,6 +25,13 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{ field: 'id', align: 'left', title: 'ID', width: 100 },
|
||||
{ field: 'name', align: 'left', title: '诊所名称' },
|
||||
{
|
||||
field: 'clinic_type',
|
||||
align: 'left',
|
||||
title: '诊所类型',
|
||||
width: 120,
|
||||
slots: { default: 'clinic_type' },
|
||||
},
|
||||
{
|
||||
field: 'online_consultation_config',
|
||||
align: 'left',
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { Button, Image, message, Switch, Tag } from 'ant-design-vue';
|
||||
import { Button, Image, message, Modal, Switch, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { Icon } from '#/components/icon';
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
deleteStore,
|
||||
openPcWindowsApiByStore,
|
||||
openQrCodeApi,
|
||||
updateClinicTypeApi,
|
||||
updateStoreShippingFree,
|
||||
updateStoreSubscribeStatus,
|
||||
} from './api';
|
||||
@@ -189,6 +190,36 @@ const batchSyncDrugPrice = () => {
|
||||
message.error('批量同步失败!');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换诊所类型
|
||||
*/
|
||||
const handleSwitchClinicType = (row: any) => {
|
||||
if (!row) return;
|
||||
|
||||
const currentType = row.clinic_type || 2; // 默认为中医诊所
|
||||
const newType = currentType === 1 ? 2 : 1;
|
||||
const currentTypeText = currentType === 1 ? '西医诊所' : '中医诊所';
|
||||
const newTypeText = newType === 1 ? '西医诊所' : '中医诊所';
|
||||
const clinicName = row.name || '该诊所';
|
||||
|
||||
Modal.confirm({
|
||||
title: '确认切换诊所类型',
|
||||
content: `确定要将【${clinicName}】的诊所类型从【${currentTypeText}】切换为【${newTypeText}】吗?`,
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await updateClinicTypeApi({ id: row.id, clinic_type: newType });
|
||||
message.success(`诊所类型已切换为【${newTypeText}】`);
|
||||
gridApi.query();
|
||||
} catch (error) {
|
||||
console.error('切换诊所类型失败:', error);
|
||||
message.error('切换失败,请稍后重试');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -268,6 +299,15 @@ const batchSyncDrugPrice = () => {
|
||||
</template>
|
||||
<template #type="{ row }">
|
||||
</template>
|
||||
<template #clinic_type="{ row }">
|
||||
<Tag
|
||||
:color="row.clinic_type === 1 ? 'blue' : row.clinic_type === 2 ? 'green' : 'default'"
|
||||
class="clinic-type-tag cursor-pointer"
|
||||
@click="handleSwitchClinicType(row)"
|
||||
>
|
||||
{{ row.clinic_type === 1 ? '西医诊所' : row.clinic_type === 2 ? '中医诊所' : '未设置' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #online_consultation_config="{ row }">
|
||||
<div
|
||||
v-if="row.is_internet_medical === 1 && row.online_consultation_doctor_name"
|
||||
@@ -398,4 +438,19 @@ const batchSyncDrugPrice = () => {
|
||||
.qr_code:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 诊所类型标签样式 */
|
||||
.clinic-type-tag {
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user