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

This commit is contained in:
2026-01-12 12:39:00 +08:00
parent f16cbf926e
commit 59a9dd3d81
7 changed files with 883 additions and 18 deletions

View File

@@ -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 />

View File

@@ -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>

View File

@@ -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">

View File

@@ -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">

View File

@@ -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 ||

View File

@@ -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>

View File

@@ -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>