feat:诊所问题优化,气泡卡片优化,修复了导入药品的时候无法打开开方组件并且切换tab的问题
Some checks failed
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
Close stale issues / stale (push) Has been cancelled

This commit is contained in:
李琦
2026-07-28 16:53:31 +08:00
parent 5506c8917f
commit 52a1cb1ce5
8 changed files with 174 additions and 33 deletions

View File

@@ -1094,7 +1094,7 @@ export const usePrescriptionStore = defineStore('prescription', () => {
},
userStore.currentUser.doctor_id,
);
// 在线复诊开方后自动连发购药指引与用药温馨提示
// 在线复诊开方后自动连发购药指引与用药温馨提示(小助手发送)
const tipTexts = [
'根据您的病情描述,已为您开具电子处方,请点击上方的‘立即支付’,进行购药;如有商品价格和订单等问题请咨询平台客服。',
'温馨提示:用药前请详细阅读药品说明书,并严格按照线下医嘱用药。如用药过程中出现病情变化或其它不适症状,请立即停药并及时就医。(请您注意,如果您尚未在医院就诊或未曾使用过本次申请的药品,请暂时不要支付订单。我们建议您在医生的指导下使用药品,以确保用药安全。)',
@@ -1102,7 +1102,7 @@ export const usePrescriptionStore = defineStore('prescription', () => {
tipTexts.forEach((tip, tipIdx) => {
sendMessage({
roomId: chatStore.currentFriend.room_id,
senderId: userStore.currentUser.doctor_id,
senderId: 'doctor_assistant',
receiverId: chatStore.currentFriend.id,
type: 'text',
content: tip,
@@ -1111,7 +1111,7 @@ export const usePrescriptionStore = defineStore('prescription', () => {
{
id: `${Date.now()}_tip_${tipIdx}`,
room_id: chatStore.currentFriend.room_id,
sender_user_id: `doctor-${userStore.currentUser.doctor_id}`,
sender_user_id: 'doctor_assistant',
receiver_user_id: chatStore.currentFriend.id,
message_type: 0,
message_content: tip,

View File

@@ -43,6 +43,14 @@ const answeredLabel = computed(() => {
return '';
});
/** 是否就诊过:有明确 0/1 才展示 */
const visitedLabel = computed(() => {
const v = data.value.has_visited;
if (v === 1 || v === '1') return '是';
if (v === 0 || v === '0') return '否';
return '';
});
const drugs = computed(() =>
Array.isArray(data.value.drugs) ? data.value.drugs : [],
);
@@ -98,6 +106,11 @@ const canShowAddBtn = computed(
<span class="value">{{ answeredLabel }}</span>
</div>
<div v-if="visitedLabel" class="answer-row">
<span class="label">是否就诊过</span>
<span class="value">{{ visitedLabel }}</span>
</div>
<div v-if="illnessInfo" class="info-block">
<div class="info-block-label">适用症/症状</div>
<div class="info-block-content">{{ illnessInfo }}</div>

View File

@@ -747,9 +747,13 @@ const getSexText = (sex) => {
</div>
</div>
<!-- 主诉 / 所选药品逐药缩略图 + 规格 + 数量对齐小程序 -->
<!-- 主诉 / 适用症 / 所选药品逐药缩略图 + 规格 + 数量对齐小程序 -->
<div
v-if="registerCardDisplay.chief_complaint || registerCardDrugRows.length"
v-if="
registerCardDisplay.chief_complaint ||
registerCardDisplay.illnessInfo ||
registerCardDrugRows.length
"
class="mt-3 space-y-2 rounded-lg border border-gray-100 p-3 text-sm dark:border-gray-600"
>
<div v-if="registerCardDisplay.chief_complaint">
@@ -758,6 +762,33 @@ const getSexText = (sex) => {
registerCardDisplay.chief_complaint
}}</span>
</div>
<div v-if="registerCardDisplay.illnessInfo">
<span class="font-medium text-gray-600 dark:text-gray-300">适用症/症状:</span>
<span class="text-gray-800 dark:text-gray-100">{{
registerCardDisplay.illnessInfo
}}</span>
</div>
<div
v-if="registerCardDisplay.illnessInfo"
class="flex flex-wrap gap-x-4 gap-y-1 text-gray-700 dark:text-gray-200"
>
<span>
是否就诊过:{{
registerCardDisplay.has_visited === 1 ||
registerCardDisplay.has_visited === '1'
? '是'
: '否'
}}
</span>
<span>
是否使用过药品:{{
registerCardDisplay.has_used_drug === 1 ||
registerCardDisplay.has_used_drug === '1'
? '是'
: '否'
}}
</span>
</div>
<div v-if="registerCardDrugRows.length" class="space-y-2">
<div class="font-medium text-gray-600 dark:text-gray-300">所选药品:</div>
<div

View File

@@ -134,9 +134,12 @@ export const sendMessage = (data) => {
const receiverId = data.receiverId.toString();
const normalizedReceiverId = receiverId.startsWith('user-') ? receiverId : `user-${receiverId}`;
// 确保 sender_user_id doctor- 前缀(医生端)
// 确保 sender_user_id:小助手保持 doctor_assistant医生端补 doctor- 前缀
const senderId = data.senderId.toString();
const normalizedSenderId = senderId.startsWith('doctor-') ? senderId : `doctor-${senderId}`;
const normalizedSenderId =
senderId === 'doctor_assistant' || senderId.startsWith('doctor-')
? senderId
: `doctor-${senderId}`;
const requestData = {
room_id: data.roomId,

View File

@@ -1,14 +1,15 @@
<script setup>
import { computed, ref, watch } from 'vue';
import { Descriptions, Button, Empty, Image } from 'ant-design-vue';
import { Descriptions, Button, Empty, Image, message } from 'ant-design-vue';
import { useVbenModal } from '@vben/common-ui';
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 SensitiveText from '#/components/sensitive-text/SensitiveText.vue';
import { usePrescriptionStore } from '#/store/prescription';
import RefusalOfTreatmentModal from '#/views/doctor/doctor-reception/components/RefusalOfTreatmentModal.vue';
const userStore = useUserStore();
const prescriptionStore = usePrescriptionStore();
@@ -24,7 +25,7 @@ const props = defineProps({
}
});
const emit = defineEmits(['reception-success', 'enter-chat', 'refresh-list', 'transfer-import-success']);
const emit = defineEmits(['reception-success', 'enter-chat', 'refresh-list', 'transfer-import-success', 'refuse-success']);
const patientDetail = ref(null);
const loading = ref(false);
@@ -32,6 +33,11 @@ const receptionLoading = ref(false);
const transferPrescription = ref(null);
const loadingTransfer = ref(false);
/** 拒诊弹窗:复用接诊模块 RefusalOfTreatmentModal */
const [RefusalOfTreatmentModals, RefusalOfTreatmentModalApi] = useVbenModal({
connectedComponent: RefusalOfTreatmentModal,
});
// 获取患者详情
const fetchPatientDetail = async () => {
// 至少需要 room_id 或 register_id 其中之一
@@ -106,6 +112,19 @@ const handleReception = async () => {
}
};
/** 打开拒诊原因弹窗;成功后通知父页刷新列表并清空当前患者 */
const handleRefuse = () => {
if (!props.patient?.register_id) {
message.error('缺少挂号ID');
return;
}
RefusalOfTreatmentModalApi.setData({
values: { register_id: props.patient.register_id },
getPatientListByReception: () => emit('refuse-success'),
});
RefusalOfTreatmentModalApi.open();
};
// 获取转诊信息
const fetchTransferPrescription = async (registerId) => {
if (!registerId) return;
@@ -330,23 +349,34 @@ watch(
</div>
</div>
<!-- 接诊按钮 -->
<!-- 接诊 / 拒诊待接诊时并列展示避免只能进聊天卡才能拒诊 -->
<div v-if="!patientDetail.is_recepted" class="action-section border-t border-gray-200 dark:border-gray-700">
<div class="action-row">
<Button
type="primary"
:loading="receptionLoading"
size="large"
block
class="action-btn"
@click="handleReception"
>
接诊
</Button>
<Button
danger
size="large"
class="action-btn"
@click="handleRefuse"
>
拒诊
</Button>
</div>
</div>
<div v-else class="recepted-info bg-green-50 dark:bg-green-900/20">
<text class="recepted-text text-green-600 dark:text-green-400">已接诊</text>
</div>
</div>
<RefusalOfTreatmentModals />
</div>
</template>
@@ -505,6 +535,15 @@ watch(
padding-top: 24px;
}
.action-row {
display: flex;
gap: 12px;
}
.action-btn {
flex: 1;
}
.recepted-info {
margin-top: 24px;
padding: 16px;

View File

@@ -227,6 +227,13 @@ const handleRefreshList = () => {
patientListRef.value?.fetchPatientList();
};
/** 拒诊成功:刷新列表并清空当前选中,回到待选状态 */
const handleRefuseSuccess = () => {
selectedPatient.value = null;
registerId.value = null;
patientListRef.value?.fetchPatientList();
};
// 结束接诊
const handleEndConsultation = () => {
if (!selectedPatient.value) {
@@ -517,6 +524,7 @@ const handleAddPatientProductsToPrescription = async () => {
:patient="selectedPatient"
:doctor-id="userStore.currentUser?.doctor_id"
@reception-success="handleReceptionSuccess"
@refuse-success="handleRefuseSuccess"
@enter-chat="handleEnterChat"
@refresh-list="handleRefreshList"
@transfer-import-success="handleTransferImportSuccess"

View File

@@ -1,14 +1,15 @@
<script setup>
import { computed, ref, watch } from 'vue';
import { Descriptions, Button, Empty, Image } from 'ant-design-vue';
import { Descriptions, Button, Empty, Image, message } from 'ant-design-vue';
import { useVbenModal } from '@vben/common-ui';
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 SensitiveText from '#/components/sensitive-text/SensitiveText.vue';
import { usePrescriptionStore } from '#/store/prescription';
import RefusalOfTreatmentModal from '#/views/doctor/doctor-reception/components/RefusalOfTreatmentModal.vue';
const userStore = useUserStore();
const prescriptionStore = usePrescriptionStore();
@@ -24,7 +25,7 @@ const props = defineProps({
}
});
const emit = defineEmits(['reception-success', 'enter-chat', 'transfer-import-success']);
const emit = defineEmits(['reception-success', 'enter-chat', 'transfer-import-success', 'refuse-success']);
const patientDetail = ref(null);
const loading = ref(false);
@@ -32,6 +33,11 @@ const receptionLoading = ref(false);
const transferPrescription = ref(null);
const loadingTransfer = ref(false);
/** 拒诊弹窗:复用接诊模块 RefusalOfTreatmentModal */
const [RefusalOfTreatmentModals, RefusalOfTreatmentModalApi] = useVbenModal({
connectedComponent: RefusalOfTreatmentModal,
});
// 获取患者详情
const fetchPatientDetail = async () => {
// 至少需要 room_id 或 register_id 其中之一
@@ -132,6 +138,19 @@ const handleReception = async () => {
}
};
/** 打开拒诊原因弹窗;成功后通知父页刷新列表并清空当前患者 */
const handleRefuse = () => {
if (!props.patient?.register_id) {
message.error('缺少挂号ID');
return;
}
RefusalOfTreatmentModalApi.setData({
values: { register_id: props.patient.register_id },
getPatientListByReception: () => emit('refuse-success'),
});
RefusalOfTreatmentModalApi.open();
};
// 获取性别文本
const getSexText = (sex) => {
if (sex === 1) return '男';
@@ -330,23 +349,34 @@ watch(
</div>
</div>
<!-- 接诊按钮 -->
<!-- 接诊 / 拒诊待接诊时并列展示避免只能进聊天卡才能拒诊 -->
<div v-if="!patientDetail.is_recepted" class="action-section border-t border-gray-200 dark:border-gray-700">
<div class="action-row">
<Button
type="primary"
:loading="receptionLoading"
size="large"
block
class="action-btn"
@click="handleReception"
>
接诊
</Button>
<Button
danger
size="large"
class="action-btn"
@click="handleRefuse"
>
拒诊
</Button>
</div>
</div>
<div v-else class="recepted-info bg-green-50 dark:bg-green-900/20">
<text class="recepted-text text-green-600 dark:text-green-400">已接诊</text>
</div>
</div>
<RefusalOfTreatmentModals />
</div>
</template>
@@ -504,6 +534,15 @@ watch(
padding-top: 24px;
}
.action-row {
display: flex;
gap: 12px;
}
.action-btn {
flex: 1;
}
.recepted-info {
margin-top: 24px;
padding: 16px;

View File

@@ -217,6 +217,13 @@ const handleReceptionSuccess = (patient) => {
patientListRef.value?.fetchPatientList();
};
/** 拒诊成功:刷新列表并清空当前选中,回到待选状态 */
const handleRefuseSuccess = () => {
selectedPatient.value = null;
registerId.value = null;
patientListRef.value?.fetchPatientList();
};
// 结束接诊
const handleEndConsultation = () => {
if (!selectedPatient.value) {
@@ -385,6 +392,7 @@ const handleAddPatientProductsToPrescription = async () => {
:patient="selectedPatient"
:doctor-id="userStore.currentUser?.doctor_id"
@reception-success="handleReceptionSuccess"
@refuse-success="handleRefuseSuccess"
@enter-chat="handleEnterChat"
@transfer-import-success="handleTransferImportSuccess"
class="patient-info-panel"