fix: 在线复诊的UI
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
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:
@@ -17,6 +17,7 @@ import {
|
||||
Card,
|
||||
Col,
|
||||
Descriptions,
|
||||
Empty,
|
||||
Image,
|
||||
ImagePreviewGroup,
|
||||
Input,
|
||||
@@ -44,9 +45,12 @@ import DiagnosisModal from '#/views/doctor/doctor-reception/components/Diagnosis
|
||||
import DoctorOrderModal from '#/views/doctor/doctor-reception/components/DoctorOrderModal.vue';
|
||||
import PrescriptionDetail from '#/views/doctor/doctor-reception/components/PrescriptionDetail.vue';
|
||||
import WesternModal from '#/views/doctor/doctor-reception/components/WesternModal.vue';
|
||||
import SimpleProductModal from '#/views/doctor/doctor-reception/components/SimpleProductModal.vue';
|
||||
// 常用方选择弹窗组件
|
||||
import CommonPrescriptionModal from '#/views/doctor/doctor-reception/components/CommonPrescriptionModal.vue';
|
||||
import StoreConfirmModal from './StoreConfirmModal.vue';
|
||||
// 药品搜索选择组件
|
||||
import { DrugSearchSelect } from '#/components/drug-search-select';
|
||||
|
||||
const splitString = (input: string) => input.split(',');
|
||||
|
||||
@@ -68,6 +72,10 @@ const isSavingCommonPrescription = ref(false);
|
||||
const categories = [
|
||||
{ label: '中药', value: 1 },
|
||||
{ label: '中成(西)药', value: 2 },
|
||||
{ label: '保健食品', value: 3 },
|
||||
{ label: '产品服务包', value: 5 },
|
||||
{ label: '非药品', value: 6 },
|
||||
{ label: '医疗器械', value: 7 },
|
||||
];
|
||||
|
||||
const packageMethod = [
|
||||
@@ -123,6 +131,10 @@ const [WesternDrugModal, WesternDrugModalApi] = useVbenModal({
|
||||
connectedComponent: WesternModal,
|
||||
});
|
||||
|
||||
const [SimpleProductModalComponent, SimpleProductModalApi] = useVbenModal({
|
||||
connectedComponent: SimpleProductModal,
|
||||
});
|
||||
|
||||
const [DiagnosisModals, DiagnosisModalApi] = useVbenModal({
|
||||
connectedComponent: DiagnosisModal,
|
||||
});
|
||||
@@ -259,6 +271,22 @@ const togglePatientInfo = () => {
|
||||
|
||||
// 打开西药模态框
|
||||
const openWesternModal = () => {
|
||||
// 判断是否为简单产品类型(3,5,6,7)
|
||||
const simpleProductTypes = [3, 5, 6, 7];
|
||||
if (simpleProductTypes.includes(prescriptionStore.activeCategory)) {
|
||||
// 使用简单产品模态框
|
||||
SimpleProductModalApi.setData({
|
||||
values: prescriptionStore.activeCategory,
|
||||
isChat: 'chat',
|
||||
activePatient_id: prescriptionStore.currentRegisterId,
|
||||
getCurrentDrugs: () => {
|
||||
// 这里可以添加获取当前药品的逻辑
|
||||
},
|
||||
storagePrefix: 'onlineConsultation-', // 在线复诊加前缀
|
||||
});
|
||||
SimpleProductModalApi.open();
|
||||
} else {
|
||||
// 使用原有的西药/中药模态框
|
||||
WesternDrugModalApi.setData({
|
||||
values: prescriptionStore.activeCategory,
|
||||
isChat: 'chat',
|
||||
@@ -266,9 +294,10 @@ const openWesternModal = () => {
|
||||
getCurrentDrugs: () => {
|
||||
// 这里可以添加获取当前药品的逻辑
|
||||
},
|
||||
storagePrefix: 'onlineConsultation', // 在线复诊加前缀
|
||||
storagePrefix: 'onlineConsultation-', // 在线复诊加前缀
|
||||
});
|
||||
WesternDrugModalApi.open();
|
||||
}
|
||||
};
|
||||
|
||||
// 打开诊断模态框
|
||||
@@ -443,6 +472,44 @@ const openSaveCommonPrescriptionModal = () => {
|
||||
showSaveCommonPrescriptionModal.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理DrugSearchSelect组件的select事件(用于新类型:3,5,6,7)
|
||||
* @param drug 选中的药品数据
|
||||
*/
|
||||
function handleSimpleProductSelect(drug: any) {
|
||||
// 检查是否已存在
|
||||
const existItem = prescriptionStore.currentDrugs.find(
|
||||
(item: any) => item.id === (drug._drugId || drug.drug_id || drug.drug?.id),
|
||||
);
|
||||
|
||||
if (existItem) {
|
||||
message.warning('该商品已在列表中');
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建新的商品对象(简化版,不需要用法用量字段)
|
||||
const newProduct = {
|
||||
index_id: drug._id || drug.id,
|
||||
id: drug._drugId || drug.drug_id || drug.drug?.id,
|
||||
drug_name: drug._drugName || drug.drug?.drug_name || drug.drug_name,
|
||||
number: 1,
|
||||
price: drug._price || drug.price,
|
||||
image: drug._image || drug.drug?.image || drug.image,
|
||||
instruction: drug.drug?.instruction || drug.instruction || '',
|
||||
type: drug.drug?.type || drug.type || prescriptionStore.activeCategory,
|
||||
select_number: 1,
|
||||
};
|
||||
|
||||
// 添加到选中列表
|
||||
prescriptionStore.currentDrugs.push(newProduct);
|
||||
|
||||
// 更新本地存储
|
||||
prescriptionStore.saveToLocalStorage();
|
||||
|
||||
// 提示成功
|
||||
message.success(`已将${newProduct.drug_name}添加到清单中!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存当前处方为常用方
|
||||
* @description 根据当前药品类型(中药/西药)调用不同的保存接口
|
||||
@@ -784,8 +851,14 @@ const cancelSaveCommonPrescription = () => {
|
||||
{{
|
||||
item.prescription_type === 1
|
||||
? '中药处方'
|
||||
: item.prescription_type === 3
|
||||
? '保健食品'
|
||||
: item.prescription_type === 5
|
||||
? '产品服务包'
|
||||
: item.prescription_type === 6
|
||||
? '非药品'
|
||||
: item.prescription_type === 7
|
||||
? '医疗器械'
|
||||
: '西药处方'
|
||||
}}
|
||||
/
|
||||
@@ -854,7 +927,7 @@ const cancelSaveCommonPrescription = () => {
|
||||
保存为常用方
|
||||
</Button>
|
||||
<Button
|
||||
v-if="prescriptionStore.activeCategory !== 1"
|
||||
v-if="prescriptionStore.activeCategory === 2"
|
||||
type="primary"
|
||||
@click="openWesternModal"
|
||||
>
|
||||
@@ -1189,8 +1262,8 @@ const cancelSaveCommonPrescription = () => {
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<!-- 西(中成)药列表 -->
|
||||
<div v-else class="selected-drugs">
|
||||
<!-- 西(中成)药列表(type=2) -->
|
||||
<div v-else-if="prescriptionStore.activeCategory === 2" class="selected-drugs">
|
||||
<div class="drug-table">
|
||||
<div class="table-header">
|
||||
<span>商品图片</span>
|
||||
@@ -1322,6 +1395,62 @@ const cancelSaveCommonPrescription = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 简单产品列表(type=3,5,6,7:保健食品、产品服务包、非药品、医疗器械) -->
|
||||
<div v-else-if="[3, 5, 6, 7].includes(prescriptionStore.activeCategory)" class="selected-drugs">
|
||||
<!-- 搜索组件 -->
|
||||
<div class="mb-5">
|
||||
<DrugSearchSelect
|
||||
:type="prescriptionStore.activeCategory"
|
||||
:store-id="prescriptionStore.storeId"
|
||||
:placeholder="`输入${categories.find(c => c.value === prescriptionStore.activeCategory)?.label || '商品'}名称搜索`"
|
||||
@select="handleSimpleProductSelect"
|
||||
/>
|
||||
</div>
|
||||
<!-- 已选商品列表(表格形式,与西药一致) -->
|
||||
<div class="drug-table">
|
||||
<div class="table-header">
|
||||
<span>商品图片</span>
|
||||
<span>商品名称</span>
|
||||
<span>数量</span>
|
||||
<span>单价</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div
|
||||
v-for="(drug, index) in prescriptionStore.currentDrugs"
|
||||
:key="drug.id"
|
||||
class="table-row"
|
||||
>
|
||||
<div style="width: 120px; margin: 0 auto">
|
||||
<Image :src="drug.image"/>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<span>药品名称:{{ drug.drug_name }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="quantity-control">
|
||||
<Button type="primary" @click="prescriptionStore.decrement(index)">-</Button>
|
||||
<span style="margin: 0 20px">{{ drug.select_number }}</span>
|
||||
<Button type="primary" @click="prescriptionStore.increment(index)">+</Button>
|
||||
</div>
|
||||
</div>
|
||||
<span>{{ drug.price }}</span>
|
||||
<div>
|
||||
<Button type="link" @click="prescriptionStore.removeDrug(index)">删除</Button>
|
||||
<Button
|
||||
v-if="drug.instruction !== ''"
|
||||
type="link"
|
||||
@click="setVisible(true, drug.instruction)"
|
||||
>
|
||||
查看说明书
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 诊断和医嘱区域 -->
|
||||
<div class="diagnosis-area">
|
||||
@@ -1666,6 +1795,7 @@ const cancelSaveCommonPrescription = () => {
|
||||
|
||||
<!-- 子模态框组件 - 按照VbenAdmin的方式声明 -->
|
||||
<WesternDrugModal />
|
||||
<SimpleProductModalComponent />
|
||||
<DiagnosisModals />
|
||||
<DoctorOrderModals />
|
||||
<PrescriptionDetailModal />
|
||||
|
||||
@@ -87,7 +87,7 @@ const openPrescriptionSourceModal = (id) => {
|
||||
商品【西药】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 3" color="purple">
|
||||
商品【非处方药】
|
||||
商品【保健食品】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 4" color="green">
|
||||
已退款
|
||||
@@ -95,6 +95,12 @@ const openPrescriptionSourceModal = (id) => {
|
||||
<Tag v-else-if="row.prescription_type === 5" color="pink">
|
||||
产品服务包
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 6" color="cyan">
|
||||
非药品
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 7" color="geekblue">
|
||||
医疗器械
|
||||
</Tag>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<Tag v-if="row.status === 0" color="red">待审核</Tag>
|
||||
|
||||
@@ -136,6 +136,20 @@ const orderTypeMap = {
|
||||
<Descriptions.Item label="处方来源">
|
||||
{{ data.store.name }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="订单来源">
|
||||
<Tag v-if="data.is_online === 1" color="blue">在线问诊</Tag>
|
||||
<Tag v-else-if="data.is_online === 2" color="green">在线复诊</Tag>
|
||||
<Tag v-else color="default">线下就诊</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处方类型">
|
||||
<Tag v-if="data.prescription_type === 1" color="orange">中药</Tag>
|
||||
<Tag v-else-if="data.prescription_type === 2" color="blue">西药</Tag>
|
||||
<Tag v-else-if="data.prescription_type === 3" color="purple">保健食品</Tag>
|
||||
<Tag v-else-if="data.prescription_type === 5" color="pink">产品服务包</Tag>
|
||||
<Tag v-else-if="data.prescription_type === 6" color="cyan">非药品</Tag>
|
||||
<Tag v-else-if="data.prescription_type === 7" color="geekblue">医疗器械</Tag>
|
||||
<Tag v-else>其他</Tag>
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<div class="mt-4">
|
||||
|
||||
@@ -276,13 +276,19 @@ const toggleFreeShipping = async (row: any, checked: boolean) => {
|
||||
处方订单【西药】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 3" color="purple">
|
||||
处方订单【非处方药】
|
||||
处方订单【保健食品】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 4" color="green">
|
||||
处方订单【西药】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 5" color="pink">
|
||||
产品服务包
|
||||
处方订单【产品服务包】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 6" color="cyan">
|
||||
处方订单【非药品】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 7" color="geekblue">
|
||||
处方订单【医疗器械】
|
||||
</Tag>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
|
||||
@@ -175,7 +175,7 @@ const getImageSource = (imageString) => {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="item.prescription_type === 2 || item.prescription_type === 5">
|
||||
<div v-else-if="item.prescription_type === 2 || item.prescription_type === 3 || item.prescription_type === 5 || item.prescription_type === 6 || item.prescription_type === 7">
|
||||
<div class="medicine-item">
|
||||
<span class="drug-name">{{
|
||||
JSON.parse(recipe.content).name ||
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 简单产品选择模态框组件
|
||||
*
|
||||
* @description 用于保健食品、产品服务包、非药品、医疗器械等简单产品的选择
|
||||
* 这些类型不需要用法用量等复杂字段,只需要选择产品和数量
|
||||
* @author 系统
|
||||
* @date 2024
|
||||
*/
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import {
|
||||
ContainerOutlined,
|
||||
MinusOutlined,
|
||||
PlusOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Card,
|
||||
CardMeta,
|
||||
Col,
|
||||
Image,
|
||||
InputNumber,
|
||||
InputSearch,
|
||||
message,
|
||||
Popover,
|
||||
Row,
|
||||
} from 'ant-design-vue';
|
||||
import { debounce } from 'lodash-es';
|
||||
|
||||
import {
|
||||
getProductListDoctorReception,
|
||||
} from '#/views/doctor/doctor-reception/api';
|
||||
import { usePrescriptionStore } from '#/store/prescription'
|
||||
|
||||
// 使用 Pinia store
|
||||
const prescriptionStore = usePrescriptionStore();
|
||||
const { currentDrugs, initializeForModal, updateCurrentDrugs } = prescriptionStore;
|
||||
|
||||
// 获取用户信息
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 搜索关键词
|
||||
const searchKey = ref('');
|
||||
// 药品类型:3-保健食品,5-产品服务包,6-非药品,7-医疗器械
|
||||
const type = ref(3);
|
||||
// 当前药品回调函数
|
||||
const currentDrugsCallback = ref();
|
||||
// 是否为聊天模式
|
||||
const isChatMode = ref(false);
|
||||
// 当前患者ID
|
||||
const activePatientId = ref(0);
|
||||
// 药品列表
|
||||
const drugList = ref([]);
|
||||
// 已选择的药品列表
|
||||
const selectList = ref([]);
|
||||
// 缓存前缀(用于区分接诊和在线复诊)
|
||||
const storagePrefix = ref('');
|
||||
// 预览图片URL
|
||||
const previewImage = ref('');
|
||||
|
||||
// 图片预览控制
|
||||
const visible = ref(false);
|
||||
// 设置图片预览状态
|
||||
const setVisible = (value: boolean, instruction = '') => {
|
||||
visible.value = value;
|
||||
previewImage.value = instruction;
|
||||
};
|
||||
|
||||
// 本地存储键名(支持前缀区分不同场景)
|
||||
const storageKey = computed(() => {
|
||||
const prefix = storagePrefix.value ? `${storagePrefix.value}-` : '';
|
||||
return `${prefix}prescriptionData_${type.value}_${activePatientId.value}`;
|
||||
});
|
||||
|
||||
// 获取当前患者的药品数据
|
||||
const getCurrentDrugs = () => {
|
||||
try {
|
||||
// 从localStorage获取数据并解析
|
||||
const storedData = localStorage.getItem(storageKey.value);
|
||||
selectList.value = storedData ? JSON.parse(storedData) : [];
|
||||
} catch (error) {
|
||||
console.error('解析处方数据失败:', error);
|
||||
selectList.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取药品列表
|
||||
* @param {string} searchText - 搜索关键词
|
||||
*/
|
||||
const getDrugList = debounce(async (searchText = '') => {
|
||||
if (searchText === '') {
|
||||
drugList.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
getCurrentDrugs();
|
||||
|
||||
try {
|
||||
const res = await getProductListDoctorReception({
|
||||
store_id: userStore.userInfo?.store_id || 0,
|
||||
type: type.value,
|
||||
name: searchText,
|
||||
});
|
||||
|
||||
drugList.value = res.map((item) => {
|
||||
const matched = selectList.value.find((v) => v.index_id === item.id);
|
||||
return {
|
||||
...item,
|
||||
select_number: matched?.select_number || 0,
|
||||
drug: {
|
||||
...item.drug,
|
||||
number: matched?.number || 1,
|
||||
},
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取药品列表失败:', error);
|
||||
message.error('获取药品列表失败');
|
||||
}
|
||||
}, 300);
|
||||
|
||||
/**
|
||||
* 添加商品到处方
|
||||
* @param {object} data - 商品对象
|
||||
*/
|
||||
function addProducts(data: any) {
|
||||
// 查找是否已存在于选择列表中
|
||||
const existItem = selectList.value.find(
|
||||
(item) => item.index_id === data.id,
|
||||
);
|
||||
|
||||
if (existItem) {
|
||||
// 已存在,增加数量
|
||||
const newNumber = existItem.select_number + 1;
|
||||
|
||||
// 验证数量上限
|
||||
if (newNumber > 100) {
|
||||
message.error(`${existItem.drug_name}数量不能大于100!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新选中列表中的数量
|
||||
selectList.value = selectList.value.map((item) =>
|
||||
item.index_id === data.id ? { ...item, select_number: newNumber } : item,
|
||||
);
|
||||
|
||||
// 同步更新药品列表中的数量
|
||||
syncDrugList(data.id, newNumber);
|
||||
|
||||
// 更新本地存储
|
||||
updateSelectStorage();
|
||||
|
||||
// 提示成功
|
||||
message.success(`${existItem.drug_name}数量已增加至${newNumber}!`);
|
||||
} else {
|
||||
// 创建新的商品对象
|
||||
const newProduct = {
|
||||
index_id: data.id,
|
||||
id: data.drug.id,
|
||||
drug_name: data.drug.drug_name,
|
||||
number: 1,
|
||||
price: data.price,
|
||||
image: data.drug.image,
|
||||
instruction: data.drug.instruction,
|
||||
type: data.drug.type,
|
||||
select_number: 1,
|
||||
};
|
||||
|
||||
// 添加到选中列表
|
||||
selectList.value.push(newProduct);
|
||||
|
||||
// 同步更新药品列表
|
||||
syncDrugList(newProduct.index_id, 1);
|
||||
|
||||
// 更新本地存储
|
||||
updateSelectStorage();
|
||||
|
||||
// 提示成功
|
||||
message.success(`已将${newProduct.drug_name}添加到清单中!`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少商品数量
|
||||
* @param {object} data - 商品对象
|
||||
*/
|
||||
function propProducts(data: any) {
|
||||
// 查找是否存在于选择列表中
|
||||
const existItem = selectList.value.find((item) => item.index_id === data.id);
|
||||
|
||||
// 如果不存在,提示错误并返回
|
||||
if (!existItem) {
|
||||
message.error(`${data.drug.drug_name}不在清单中!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算新的数量
|
||||
const newNumber = existItem.select_number - 1;
|
||||
|
||||
// 验证数量下限
|
||||
if (newNumber < 0) {
|
||||
message.error(`${data.drug.drug_name}数量不能小于0!`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newNumber === 0) {
|
||||
// 数量为0,从清单中移除
|
||||
selectList.value = selectList.value.filter(
|
||||
(item) => item.index_id !== data.id,
|
||||
);
|
||||
|
||||
// 同步更新药品列表
|
||||
syncDrugList(data.id, 0);
|
||||
|
||||
// 更新本地存储
|
||||
updateSelectStorage();
|
||||
|
||||
// 提示成功
|
||||
message.success(`${data.drug.drug_name}已从清单移出!`);
|
||||
} else {
|
||||
// 更新数量
|
||||
selectList.value = selectList.value.map((item) =>
|
||||
item.index_id === data.id ? { ...item, select_number: newNumber } : item,
|
||||
);
|
||||
|
||||
// 同步更新药品列表
|
||||
syncDrugList(data.id, newNumber);
|
||||
|
||||
// 更新本地存储
|
||||
updateSelectStorage();
|
||||
|
||||
// 提示成功
|
||||
message.success(`${data.drug.drug_name}数量已减少至${newNumber}!`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新本地存储中的选择列表
|
||||
*/
|
||||
function updateSelectStorage() {
|
||||
try {
|
||||
localStorage.setItem(storageKey.value, JSON.stringify(selectList.value));
|
||||
if (isChatMode.value) {
|
||||
// 使用 Pinia store 的方法更新 currentDrugs
|
||||
updateCurrentDrugs(selectList.value);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存处方数据失败:', error);
|
||||
message.error('保存处方数据失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步更新药品列表中的数量
|
||||
* @param {number} productId - 药品ID
|
||||
* @param {number} number - 新的数量
|
||||
*/
|
||||
function syncDrugList(productId: number, number: number) {
|
||||
// 使用map创建新数组,避免直接修改原数组
|
||||
drugList.value = drugList.value.map((item) =>
|
||||
item.id === productId ? { ...item, select_number: number } : item,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新药品数量
|
||||
* @param {number} id - 药品ID
|
||||
* @param {number} number - 新的数量
|
||||
*/
|
||||
function updateProductNumber(id: number, number: number) {
|
||||
// 验证数量范围
|
||||
if (number > 100 || number <= 0) {
|
||||
message.error('数量不能大于100或小于1');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新选择列表中的数量
|
||||
selectList.value = selectList.value.map((item) =>
|
||||
item.index_id === id
|
||||
? {
|
||||
...item,
|
||||
select_number: number,
|
||||
number: number,
|
||||
}
|
||||
: item,
|
||||
);
|
||||
|
||||
// 更新本地存储
|
||||
updateSelectStorage();
|
||||
}
|
||||
|
||||
// 使用modal组件
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
fullscreenButton: false,
|
||||
draggable: true,
|
||||
onCancel() {
|
||||
// 关闭时也更新本地存储
|
||||
updateSelectStorage();
|
||||
modalApi.close();
|
||||
},
|
||||
onConfirm: async () => {
|
||||
// 更新本地存储
|
||||
updateSelectStorage();
|
||||
// 调用回调函数
|
||||
if (typeof currentDrugsCallback.value === 'function') {
|
||||
currentDrugsCallback.value();
|
||||
}
|
||||
// 关闭modal
|
||||
modalApi.close();
|
||||
// 提示成功
|
||||
message.success('保存成功');
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
// 获取回调函数
|
||||
const data = modalApi.getData();
|
||||
currentDrugsCallback.value = data?.getCurrentDrugs;
|
||||
|
||||
// 获取参数
|
||||
const { values, activePatient_id, isChat, storagePrefix: prefix } = data || {};
|
||||
|
||||
if (values) {
|
||||
// 设置缓存前缀
|
||||
storagePrefix.value = prefix || '';
|
||||
// 设置药品类型
|
||||
type.value = values;
|
||||
// 设置患者ID
|
||||
activePatientId.value = activePatient_id;
|
||||
if (isChat === 'chat') {
|
||||
isChatMode.value = true;
|
||||
// 使用轻量级初始化,不获取患者信息
|
||||
initializeForModal(activePatient_id);
|
||||
} else {
|
||||
isChatMode.value = false;
|
||||
}
|
||||
// 获取药品列表
|
||||
getDrugList();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// 获取类型标签
|
||||
const getTypeLabel = computed(() => {
|
||||
const typeMap: Record<number, string> = {
|
||||
3: '保健食品',
|
||||
5: '产品服务包',
|
||||
6: '非药品',
|
||||
7: '医疗器械',
|
||||
};
|
||||
return typeMap[type.value] || '商品';
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :class="'w-[60%]'" :title="`${getTypeLabel}列表`">
|
||||
<!-- 图片预览组件 -->
|
||||
<Image
|
||||
:preview="{
|
||||
visible,
|
||||
onVisibleChange: setVisible,
|
||||
}"
|
||||
:src="previewImage"
|
||||
:style="{ display: 'none' }"
|
||||
:width="200"
|
||||
/>
|
||||
<Page>
|
||||
<Row :gutter="12">
|
||||
<!-- 搜索框 -->
|
||||
<Col :span="24">
|
||||
<InputSearch
|
||||
v-model:value="searchKey"
|
||||
enter-button
|
||||
:placeholder="`请输入${getTypeLabel}名称或拼音首拼`"
|
||||
@input="(e) => getDrugList(e.target.value)"
|
||||
@search="getDrugList"
|
||||
/>
|
||||
</Col>
|
||||
<!-- 商品列表 -->
|
||||
<Col v-for="item in drugList" :key="item.id" :span="6">
|
||||
<Badge :count="item.select_number" class="mt-5">
|
||||
<Card hoverable>
|
||||
<template #cover>
|
||||
<Image :height="200" :src="item.drug?.image" />
|
||||
</template>
|
||||
<template #actions>
|
||||
<MinusOutlined key="prop" @click="propProducts(item)" />
|
||||
<ContainerOutlined
|
||||
v-if="item.drug.instruction"
|
||||
@click="setVisible(true, item.drug.instruction)"
|
||||
/>
|
||||
<PlusOutlined key="add" @click="addProducts(item)" />
|
||||
</template>
|
||||
<CardMeta
|
||||
:description="item.drug?.function || item.drug?.specification"
|
||||
:title="`${item.drug?.drug_name}${item.drug?.pinyin_simple ? `(${item.drug?.pinyin_simple})` : ''}`"
|
||||
>
|
||||
<template #avatar>
|
||||
<a-avatar src="https://joeschmoe.io/api/v1/random" />
|
||||
</template>
|
||||
</CardMeta>
|
||||
<div class="card-box mt-5" style="padding: 10px 5px">
|
||||
<Popover v-if="item.drug?.function || item.drug?.usage">
|
||||
<template #content>
|
||||
<p v-if="item.drug?.function">功效:{{ item.drug?.function }}</p>
|
||||
<p v-if="item.drug?.usage">用法:{{ item.drug?.usage }}</p>
|
||||
</template>
|
||||
</Popover>
|
||||
<p class="text-source mt-5">{{ item.drug?.source }}</p>
|
||||
<p class="mt-3">单价:¥{{ item.price }}</p>
|
||||
<!-- 数量输入框 -->
|
||||
<div class="mt-3">
|
||||
<InputNumber
|
||||
v-model:value="item.select_number"
|
||||
:min="0"
|
||||
:max="100"
|
||||
class="w-full"
|
||||
@change="updateProductNumber(item.id, item.select_number)"
|
||||
>
|
||||
<template #addonBefore>
|
||||
<MinusOutlined
|
||||
key="prop"
|
||||
@click="
|
||||
updateProductNumber(
|
||||
item.id,
|
||||
item.select_number > 0 ? item.select_number - 1 : 0,
|
||||
)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #addonAfter>
|
||||
<PlusOutlined
|
||||
key="add"
|
||||
@click="
|
||||
updateProductNumber(
|
||||
item.id,
|
||||
item.select_number < 100
|
||||
? item.select_number + 1
|
||||
: 100,
|
||||
)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</InputNumber>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Badge>
|
||||
</Col>
|
||||
</Row>
|
||||
</Page>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.card-box {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.text-source {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
@@ -52,12 +52,15 @@ import DiagnosisModal from './components/DiagnosisModal.vue';
|
||||
import DoctorOrderModal from './components/DoctorOrderModal.vue';
|
||||
import PrescriptionDetail from './components/PrescriptionDetail.vue';
|
||||
import WesternModal from './components/WesternModal.vue';
|
||||
import SimpleProductModal from './components/SimpleProductModal.vue';
|
||||
import RefusalOfTreatmentModal
|
||||
from "#/views/doctor/doctor-reception/components/RefusalOfTreatmentModal.vue";
|
||||
// 常用方选择弹窗组件
|
||||
import CommonPrescriptionModal from './components/CommonPrescriptionModal.vue';
|
||||
// 确认模态框组件
|
||||
import ConfirmModal from './components/ConfirmModal.vue';
|
||||
// 药品搜索选择组件
|
||||
import { DrugSearchSelect } from '#/components/drug-search-select';
|
||||
// 保存常用方API
|
||||
import {
|
||||
saveChineseCommonPrescriptionApi,
|
||||
@@ -161,10 +164,10 @@ setInterval(getPatientListByReception, 600_000);
|
||||
const categories = [
|
||||
{label: '中药', value: 1},
|
||||
{label: '中成(西)药', value: 2},
|
||||
// { label: '西药', value: 2 },
|
||||
// { label: '保健商品', value: 3 },
|
||||
// { label: '中成药商品', value: 4 },
|
||||
// { label: '服务包', value: 5 },
|
||||
{label: '保健食品', value: 3},
|
||||
{label: '产品服务包', value: 5},
|
||||
{label: '非药品', value: 6},
|
||||
{label: '医疗器械', value: 7},
|
||||
];
|
||||
|
||||
// 当前状态
|
||||
@@ -608,6 +611,10 @@ const [WesternDrugModal, WesternDrugModalApi] = useVbenModal({
|
||||
connectedComponent: WesternModal,
|
||||
});
|
||||
|
||||
const [SimpleProductModalComponent, SimpleProductModalApi] = useVbenModal({
|
||||
connectedComponent: SimpleProductModal,
|
||||
});
|
||||
|
||||
const [DiagnosisModals, DiagnosisModalApi] = useVbenModal({
|
||||
connectedComponent: DiagnosisModal,
|
||||
});
|
||||
@@ -886,7 +893,19 @@ const cancelSaveCommonPrescription = () => {
|
||||
};
|
||||
|
||||
const openWesternModal = () => {
|
||||
// 打开西药处方模态框逻辑
|
||||
// 判断是否为简单产品类型(3,5,6,7)
|
||||
const simpleProductTypes = [3, 5, 6, 7];
|
||||
if (simpleProductTypes.includes(activeCategory.value)) {
|
||||
// 使用简单产品模态框
|
||||
SimpleProductModalApi.setData({
|
||||
values: activeCategory.value,
|
||||
activePatient_id: activePatient.value?.id,
|
||||
getCurrentDrugs,
|
||||
storagePrefix: '', // 接诊页面不加前缀
|
||||
});
|
||||
SimpleProductModalApi.open();
|
||||
} else {
|
||||
// 使用原有的西药/中药模态框
|
||||
WesternDrugModalApi.setData({
|
||||
values: activeCategory.value,
|
||||
activePatient_id: activePatient.value?.id,
|
||||
@@ -894,6 +913,7 @@ const openWesternModal = () => {
|
||||
storagePrefix: '', // 接诊页面不加前缀
|
||||
});
|
||||
WesternDrugModalApi.open();
|
||||
}
|
||||
};
|
||||
const openPrescriptionDetail = (values) => {
|
||||
// 打开西药处方模态框逻辑
|
||||
@@ -1376,6 +1396,44 @@ function addProducts(data) {
|
||||
message.success(`已将${newProduct.drug_name}添加到清单中!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理DrugSearchSelect组件的select事件(用于新类型:3,5,6,7)
|
||||
* @param drug 选中的药品数据
|
||||
*/
|
||||
function handleSimpleProductSelect(drug: any) {
|
||||
// 检查是否已存在
|
||||
const existItem = currentDrugs.value.find(
|
||||
(item) => item.id === (drug._drugId || drug.drug_id || drug.drug?.id),
|
||||
);
|
||||
|
||||
if (existItem) {
|
||||
message.warning('该商品已在列表中');
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建新的商品对象(简化版,不需要用法用量字段)
|
||||
const newProduct = {
|
||||
index_id: drug._id || drug.id,
|
||||
id: drug._drugId || drug.drug_id || drug.drug?.id,
|
||||
drug_name: drug._drugName || drug.drug?.drug_name || drug.drug_name,
|
||||
number: 1,
|
||||
price: drug._price || drug.price,
|
||||
image: drug._image || drug.drug?.image || drug.image,
|
||||
instruction: drug.drug?.instruction || drug.instruction || '',
|
||||
type: drug.drug?.type || drug.type || activeCategory.value,
|
||||
select_number: 1,
|
||||
};
|
||||
|
||||
// 添加到选中列表
|
||||
currentDrugs.value.push(newProduct);
|
||||
|
||||
// 更新本地存储
|
||||
updateLocalStorage();
|
||||
|
||||
// 提示成功
|
||||
message.success(`已将${newProduct.drug_name}添加到清单中!`);
|
||||
}
|
||||
|
||||
const newDrugInfo = ref({});
|
||||
|
||||
function switchStore(id) {
|
||||
@@ -1627,7 +1685,15 @@ watch(
|
||||
item.created_at
|
||||
}}</span>
|
||||
<Tag class="ml-5" :color="item.category === 1? '' : '#455cda'">
|
||||
{{ item.prescription_type === 1 ? '中药处方' : item.prescription_type === 5 ? '产品服务包' : '西药处方' }} /
|
||||
{{
|
||||
item.prescription_type === 1 ? '中药处方' :
|
||||
item.prescription_type === 2 ? '西药处方' :
|
||||
item.prescription_type === 3 ? '保健食品' :
|
||||
item.prescription_type === 5 ? '产品服务包' :
|
||||
item.prescription_type === 6 ? '非药品' :
|
||||
item.prescription_type === 7 ? '医疗器械' :
|
||||
'未知类型'
|
||||
}} /
|
||||
{{ item.category === 1 ? '自费' : '医保' }}
|
||||
</Tag>
|
||||
|
||||
@@ -1670,7 +1736,7 @@ watch(
|
||||
|
||||
<div class="mt-5">
|
||||
<Button
|
||||
v-if="activeCategory !== 1"
|
||||
v-if="activeCategory === 2"
|
||||
type="primary"
|
||||
@click="openWesternModal"
|
||||
>
|
||||
@@ -2024,8 +2090,8 @@ watch(
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<!-- 西(中成)药列表 -->
|
||||
<div v-else class="selected-drugs">
|
||||
<!-- 西(中成)药列表(type=2) -->
|
||||
<div v-else-if="activeCategory === 2" class="selected-drugs">
|
||||
<div class="drug-table">
|
||||
<div class="table-header">
|
||||
<span v-if="activeCategory !== 1">商品图片</span>
|
||||
@@ -2149,6 +2215,62 @@ watch(
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 简单产品列表(type=3,5,6,7:保健食品、产品服务包、非药品、医疗器械) -->
|
||||
<div v-else-if="[3, 5, 6, 7].includes(activeCategory)" class="selected-drugs">
|
||||
<!-- 搜索组件 -->
|
||||
<div class="mb-5">
|
||||
<DrugSearchSelect
|
||||
:type="activeCategory"
|
||||
:store-id="myStoreId"
|
||||
:placeholder="`输入${categories.find(c => c.value === activeCategory)?.label || '商品'}名称搜索`"
|
||||
@select="handleSimpleProductSelect"
|
||||
/>
|
||||
</div>
|
||||
<!-- 已选商品列表(表格形式,与西药一致) -->
|
||||
<div class="drug-table">
|
||||
<div class="table-header">
|
||||
<span>商品图片</span>
|
||||
<span>商品名称</span>
|
||||
<span>数量</span>
|
||||
<span>单价</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<div class="table-body">
|
||||
<div
|
||||
v-for="(drug, index) in currentDrugs"
|
||||
:key="drug.id"
|
||||
class="table-row"
|
||||
>
|
||||
<div style="width: 120px; margin: 0 auto">
|
||||
<Image :src="drug.image"/>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<span>药品名称:{{ drug.drug_name }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="quantity-control">
|
||||
<Button type="primary" @click="decrement(index)">-</Button>
|
||||
<span style="margin: 0 20px">{{ drug.select_number }}</span>
|
||||
<Button type="primary" @click="increment(index)">+</Button>
|
||||
</div>
|
||||
</div>
|
||||
<span>{{ drug.price }}</span>
|
||||
<div>
|
||||
<Button type="link" @click="removeDrug(index)">删除</Button>
|
||||
<Button
|
||||
v-if="drug.instruction !== ''"
|
||||
type="link"
|
||||
@click="setVisible(true, drug.instruction)"
|
||||
>
|
||||
查看说明书
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 诊断和医嘱 -->
|
||||
<div class="diagnosis-area">
|
||||
@@ -2279,7 +2401,22 @@ watch(
|
||||
</div>
|
||||
<div class="total-cost">总计:¥{{ totalCost.toFixed(2) }}</div>
|
||||
|
||||
<Button class="mt-5 w-full" style="display: block" type="primary" @click="checkChineseMedicineConflict">
|
||||
<Button
|
||||
v-if="activeCategory === 1"
|
||||
class="mt-5 w-full"
|
||||
style="display: block"
|
||||
type="primary"
|
||||
@click="checkChineseMedicineConflict"
|
||||
>
|
||||
发送处方
|
||||
</Button>
|
||||
<Button
|
||||
v-else
|
||||
class="mt-5 w-full"
|
||||
style="display: block"
|
||||
type="primary"
|
||||
@click="sendPrescription"
|
||||
>
|
||||
发送处方
|
||||
</Button>
|
||||
</div>
|
||||
@@ -2290,6 +2427,7 @@ watch(
|
||||
<DiagnosisModals/>
|
||||
<DoctorOrderModals/>
|
||||
<WesternDrugModal/>
|
||||
<SimpleProductModalComponent/>
|
||||
<PrescriptionDetailModal/>
|
||||
<!-- 常用方选择弹窗 -->
|
||||
<CommonPrescriptionModals/>
|
||||
@@ -2588,4 +2726,105 @@ watch(
|
||||
color: #909399;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
/* 简单产品列表样式 */
|
||||
.simple-product-list {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.selected-products-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 16px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.product-card {
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.dark .product-card {
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
.product-card-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.product-image-placeholder {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f5f5;
|
||||
border-radius: 6px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.dark .product-image-placeholder {
|
||||
background: #374151;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.dark .product-name {
|
||||
color: #f3f4f6;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.dark .product-price {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.product-quantity {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.product-total {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.product-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.dark .product-actions {
|
||||
border-top-color: #333;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user