fix: 中药相冲检测、处方详情页面优化(展示医生签名)

This commit is contained in:
2025-04-08 17:07:08 +08:00
parent 3ac645e4a0
commit bd6b5979f3
7 changed files with 215 additions and 26 deletions

View File

@@ -0,0 +1,32 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
const list = ref('');
const previewTitle = ref('二维码');
const [Modal, modalApi] = useVbenModal({
fullscreenButton: false,
draggable: true,
onCancel() {
modalApi.close();
},
onConfirm: async () => {
modalApi.close();
},
onOpenChange(isOpen: boolean) {
if (isOpen) {
const { values, title } = modalApi.getData<Record<string, any>>();
if (values) {
list.value = values;
previewTitle.value = title;
}
}
},
});
</script>
<template>
<Modal title="提示框" class="w-[50%]">
您的处方中有以下药品存在{{previewTitle}}
</Modal>
</template>

View File

@@ -55,15 +55,15 @@ export const modalFormProps: VbenFormProps = {
// label: 'LOGO',
// rules: 'required',
// },
{
component: 'Textarea',
componentProps: {
placeholder: '请输入快递公司介绍',
},
fieldName: 'introduce',
label: '快递公司介绍',
rules: 'required',
},
// {
// component: 'Textarea',
// componentProps: {
// placeholder: '请输入快递公司介绍',
// },
// fieldName: 'introduce',
// label: '快递公司介绍',
// rules: 'required',
// },
],
showDefaultActions: false,
};

View File

@@ -260,7 +260,7 @@ const openPrescriptionDetail = (values) => {
type: 'link',
icon: 'ri:send-plane-fill',
// auth: ['超级订单', 'sys:user:save'],
onClick: openPrescriptionDetail.bind(null, row.prescription),
onClick: openPrescriptionDetail.bind(null, row.p_id),
},
]"
/>

View File

@@ -99,3 +99,20 @@ export async function addWestPrescription(data: any) {
export async function switchStoreApi(data: any) {
return requestClient.post<any>(`${prefix}switch-store`, data);
}
/**
* 获取患者详情
* @param id
*/
export async function getPrescriptionInfoApi(id: number) {
return requestClient.get<any>('prescription/detail', { params: { id } });
}
/**
* 检查是否有药物相冲
* @param data
*/
export async function checkChineseMedicineConflictApi(data: any) {
return requestClient.post<any>(`${prefix}check-chinese-medicine-conflict`, data);
}

View File

@@ -5,6 +5,8 @@ import { Page, useVbenModal } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { getPrescriptionInfoApi } from '#/views/doctor/doctor-reception/api';
const item = ref<Record<string, any>>({});
const [Modal, modalApi] = useVbenModal({
@@ -16,7 +18,15 @@ const [Modal, modalApi] = useVbenModal({
onOpenChange(isOpen: boolean) {
if (isOpen) {
const { values } = modalApi.getData<Record<string, any>>();
if (values) item.value = values;
if (values) {
if (typeof values === 'number') {
getPrescriptionInfoApi(values).then((res) => {
item.value = res;
});
} else {
item.value = values;
}
}
}
},
});
@@ -125,7 +135,12 @@ const decrypt = (str: string) => str; // 简单base64解码示例
>
<!-- <div class="medicine-item" v-for="drug in JSON.parse(recipe.content)" :key="drug?.id">-->
<div v-if="item.prescription_type === 1" class="w-full">
<div v-for="drug in JSON.parse(recipe.content)" :key="drug?.id" class="w-1/3" style="display: inline-block">
<div
v-for="drug in JSON.parse(recipe.content)"
:key="drug?.id"
class="w-1/3"
style="display: inline-block"
>
<div class="medicine-item">
<!-- {{ drug }}-->
<span class="drug-name">{{
@@ -133,7 +148,13 @@ const decrypt = (str: string) => str; // 简单base64解码示例
}}</span>
<span class="drug-quantity mr-5">{{ drug?.number }} /g</span>
</div>
<div class="">煎服方法: {{ drug.use_way?.name || '煎服' }}</div>
<!-- <div class="">煎服方法: {{ drug.use_way?.name || '煎服' }}</div>-->
<div>
方法:
<span class="preparation-info">{{
drug.use_way?.name || '煎服'
}}</span>
</div>
</div>
<div class="preparation-info">
<p>
@@ -186,23 +207,63 @@ const decrypt = (str: string) => str; // 简单base64解码示例
<div class="signature-area">
<div class="signature">
<label>开方医生:</label>
{{ item.content?.doctor.name }}
<img
v-if="item.doctor_info?.identity?.sign_image"
:src="`data:image/jpeg;base64,${
item.doctor_info.identity.sign_image
}`"
alt="签名"
style="width: 120px; height: 50px; display: inline-block"
/>
<span v-else>{{ item.content?.doctor.name }}</span>
</div>
<div class="signature">
<label>审核药师:</label>
{{ item?.first_view_info?.name || '' }}
<img
v-if="item.pharmacist_info?.identity?.sign_image"
:src="`data:image/jpeg;base64,${
item.pharmacist_info.identity.sign_image
}`"
alt="签名"
style="width: 120px; height: 50px; display: inline-block"
/>
<span v-else>{{ item.pharmacist_info?.name }}</span>
</div>
<div class="signature">
<label>调配人:</label>
{{ item.content?.doctor.name }}
<img
v-if="item.doctor_info?.identity?.sign_image"
:src="`data:image/jpeg;base64,${
item.doctor_info.identity.sign_image
}`"
alt="签名"
style="width: 120px; height: 50px; display: inline-block"
/>
<span v-else>{{ item.content?.doctor.name }}</span>
</div>
<div class="signature">
<label>核对人:</label>
{{ item?.again_view_info?.name || '' }}
<img
v-if="item.pharmacist_info?.identity?.sign_image"
:src="`data:image/jpeg;base64,${
item.pharmacist_info.identity.sign_image
}`"
alt="签名"
style="width: 120px; height: 50px; display: inline-block"
/>
<span v-else>{{ item.pharmacist_info?.name }}</span>
</div>
<div class="signature">
<label>发药人:</label>
{{ item.content?.doctor.name }}
<img
v-if="item.doctor_info?.identity?.sign_image"
:src="`data:image/jpeg;base64,${
item.doctor_info.identity.sign_image
}`"
alt="签名"
style="width: 120px; height: 50px; display: inline-block"
/>
<span v-else>{{ item.content?.doctor.name }}</span>
</div>
<!-- <div class="signature">-->
<!-- <label>加工费:</label>-->
@@ -212,7 +273,12 @@ const decrypt = (str: string) => str; // 简单base64解码示例
</div>
<div class="price-info"></div>
<div class="price-info">总价: {{ item.total_pay_price }}</div>
<div class="validity">处方有效期: {{ item.valid_hours }}小时</div>
<div v-if="item.auto_expire_txt === ''" class="validity">
处方有效期: {{ item.valid_hours }}小时
</div>
<div v-else class="validity" style="color: red">
{{ item.auro_expire_txt }}
</div>
</div>
</div>
</Page>

View File

@@ -28,13 +28,13 @@ import {
Tag,
Textarea,
Timeline,
TimelineItem,
TimelineItem, notification,
} from 'ant-design-vue';
import {debounce} from 'lodash-es'; // 或者使用自定义防抖函数
import {getRegisterStatus} from '#/util/tool';
import {
addWestPrescription,
addWestPrescription, checkChineseMedicineConflictApi,
endOfDiagnosisApi,
getDrugUseList,
getMyStoreListApi,
@@ -381,6 +381,40 @@ const getCurrentDrugs = () => {
);
};
getCurrentDrugs();
const doctorSecondSign = ref(0);
const checkData = ref([]);
/**
* 检查中药的相冲
*/
const checkChineseMedicineConflict = () => {
if (activeCategory.value === 2) {
// eslint-disable-next-line no-use-before-define
sendPrescription();
return;
}
notification.info({
message: '正在检查药物相冲',
duration: 1,
description: '正在检查药物相冲,请稍等...',
})
const names = currentDrugs.value.map((item) => item.drug_name);
checkChineseMedicineConflictApi({names: names}).then((res) => {
if (res.is_exist === true) {
checkData.value.message = res.message;
doctorSecondSignModal.value = true;
} else {
notification.success({
message: '检查成功',
duration: 3,
description: '暂无相冲药品',
})
// eslint-disable-next-line no-use-before-define
sendPrescription();
}
})
return;
}
/**
* 发送处方
*/
@@ -455,6 +489,8 @@ const sendPrescription = () => {
dosage: dosage.value,
// 每日用药次数
day_dosage: dayDosage.value,
// 是否二次签名
doctor_second_sign: doctorSecondSign.value,
}).then(() => {
message.success('处方已发送');
// 清空当前数据
@@ -702,7 +738,10 @@ function updateChineseNumber() {
updateLocalStorage();
}
// 新药品确认弹窗
const showNewDrugModal = ref(false);
// 二次签名确认弹窗
const doctorSecondSignModal = ref(false);
/**
* 在新的药品数量框失去焦点后弹出新药品弹窗
@@ -718,6 +757,12 @@ function newDrugModalOk() {
showNewDrugModal.value = false;
}
function doctorSecondSignModalOk() {
doctorSecondSign.value = 1;
doctorSecondSignModal.value = false;
sendPrescription();
}
function updateChineseNumberGoNewDrug(event: KeyboardEvent) {
if (event.key === 'Enter') {
updateLocalStorage();
@@ -773,7 +818,6 @@ const getDrugListByWesternModal = debounce(async (searchText = '') => {
/**
* 选择药品
* @param id
*/
function selectNewDrugInfo() {
// 如果是新药品输入框,调用添加新药品方法
@@ -893,7 +937,6 @@ function searchOption(inputValue) {
/**
* 添加中药
* @param inputValue
*/
function addDrugByChinese() {
// 如果是新药品输入框,调用添加新药品方法
@@ -1247,16 +1290,22 @@ watch(
<Timeline>
<TimelineItem v-for="item in prescriptionList" :key="item.id">
<Tag color="#455cda">{{ item.prescription_no }}</Tag>
<Button type="link" @click="openPrescriptionDetail(item)">
<Button type="link" @click="openPrescriptionDetail(item.id)">
查看处方
</Button>
<span class="time-line-item-created">{{
item.created_at
}}</span>
<Tag class="ml-5">
<Tag class="ml-5" :color="item.category === 1? '' : '#455cda'">
{{ item.prescription_type === 1 ? '中药处方' : '西药处方' }} /
{{ item.category === 1 ? '自费' : '医保' }}
</Tag>
<Tag v-if="item.status === 0" color="warning">待审核</Tag>
<Tag v-else-if="item.status === 1" color="success">已通过</Tag>
<Tag v-else-if="item.status === 2" color="error">未通过</Tag>
<Tag v-else-if="item.status === 3" color="#455cda">无需审核(服务包)</Tag>
<Tag color="#455cda">处方ID{{ item.id }}</Tag>
<!-- <Tag class="ml-5">-->
<!-- {{ item.category === 1 ? '自费' : '医保' }}-->
<!-- </Tag>-->
@@ -1821,7 +1870,7 @@ watch(
</div>
<div class="total-cost">总计:¥{{ totalCost.toFixed(2) }}</div>
<Button class="mt-5 w-full" style="display: block" type="primary" @click="sendPrescription">
<Button class="mt-5 w-full" style="display: block" type="primary" @click="checkChineseMedicineConflict">
发送处方
</Button>
</div>
@@ -1836,10 +1885,26 @@ watch(
<Modal v-model:open="showNewDrugModal" @ok="newDrugModalOk">
要把【{{ newDrugInfo.name }}】添加到清单吗?
</Modal>
<Modal title="二次签名" v-model:open="doctorSecondSignModal" @ok="doctorSecondSignModalOk">
<div class="doctor-second-sign-title">有毒:</div>
<p v-for="item in checkData.message.poisonous || []">【{{ item }}】</p>
<div class="doctor-second-sign-title">十八反:</div>
<p v-for="item in checkData.message.opposition || []">【{{ item }}】</p>
<div class="doctor-second-sign-title">十九畏:</div>
<p v-for="item in checkData.message.conflict || []">【{{ item }}】</p>
<p class="mt-5" style="color: red;">如需继续开方需要二次签名确认要二次签名吗</p>
</Modal>
</div>
</template>
<style scoped>
.doctor-second-sign-title {
font-size: 16px;
margin: 10px 0;
font-weight: bold;
border-left: 5px solid rgb(55, 71, 162);
padding-left: 10px;
}
.card-index {
font-size: 20px;
font-weight: bold;

View File

@@ -15,6 +15,15 @@ export const formOptions: VbenFormProps = {
fieldName: 'name',
label: '诊所名称',
},
{
component: 'VbenInput',
componentProps: {
placeholder: '输入名称',
},
defaultValue: '',
fieldName: 'shouzimu',
label: '诊所首字母',
},
{
component: 'VbenInput',
componentProps: {