Files
xk-doctor-wx/subPackages/sub_workbench/prescription_v2/index.vue

2159 lines
72 KiB
Vue
Raw Normal View History

2026-03-06 13:59:22 +08:00
<template>
<view class="safe-area-inset-bottom">
<!-- 导航栏 -->
<u-navbar class="navbar" :is-back="true" title="开方" :custom-back="handleCustomBack" title-color="#000">
</u-navbar>
<!-- 处方类型Tab切换 -->
<view class="tabs flex p-32 flex-ali-center flex-jus-sp" style="overflow-x: auto">
<u-button
:throttle-time="0"
:plain="true"
:type="activeCategory === category.value ? 'success' : 'default'"
v-for="(category, index) in prescriptionCategories"
:key="category.value"
:custom-style="tabsBtnStyle"
@click="handleSwitchCategory(category.value)"
:hairline="true"
:hoverStayTime="0"
:style="{
display: (index === 0 && identity === 2) || identity === 1 ? 'block' : 'none',
marginLeft: '10rpx',
}">
{{ category.label }}
</u-button>
</view>
<!-- 诊断输入区域 -->
<view class="top white p-32 flex-col m-t-2">
<view class="top_title flex-row flex-ali-center">
<image :src="require('@/static/image/js.png')" class="size-32"></image>
<d-text text="诊断" className="light-c fs-32 m-l-16"></d-text>
</view>
<view class="m-t-16 flex flex-wrap">
<view class="m-r-2 m-t-16" v-for="(item, i) in diagnoses" :key="item.id ? item.id : `diag_${i}`">
<u-tag
shape="circle"
:text="item.name"
bg-color="#6ACDBB"
color="#fff"
close-color="#fff"
:closeable="true"
@close="handleRemoveDiagnosis(i)" />
</view>
</view>
<view class="m-t-24">
<u-input
disabled
placeholder="请输入疾病"
:custom-style="illnessStyle"
@click="handleOpenDiagnosisModal" />
</view>
</view>
<!-- 滚动内容区域 -->
<scroll-view :style="scrollStyle" scroll-y="true">
<!-- 西药列表 -->
<view class="m-t-2 b-r-8 white p-32 flex-col" v-if="activeCategory === 2">
<view class="flex-row flex-jus-sp flex-ali-center">
<d-text text="R" className="main-c fs-4" :bold="true"></d-text>
<view class="flex-row m-l-163" style="height: 50rpx;">
<u-button
v-if="!isCommonPrescription"
:throttle-time="0"
shape="circle"
size="mini"
:custom-style="{backgroundColor: 'transparent !important',border:'1px solid #6ACDBB',color:'#6ACDBB'}"
plain
@click="handleOpenCommonPrescriptionModal"
:ripple="true">
常用方
</u-button>
<view class="m-l-16">
<u-button
:throttle-time="0"
shape="circle"
size="mini"
:custom-style="{ backgroundColor:'#6ACDBB',color:'#fff' }"
@click="handleOpenWesternMedicineModal">
添加商品
</u-button>
</view>
</view>
</view>
<view class="bottom-border p-col-32" v-for="(item, index) in currentDrugs" :key="index">
<view class="drug-item-content flex-row">
<image
v-if="item.image"
:src="item.image"
class="drug-image"
mode="aspectFill"
></image>
<view class="drug-info-wrapper flex-1">
<view class="flex-row flex-jus-sp flex-ali-center">
<d-text :text="`${index+1}、${item.drug_name}`" className="fs-3 content-c"></d-text>
<d-text :text="`¥${parseFloat(item.price || 0).toFixed(2)}`" className="error-c fs-3"></d-text>
</view>
<view class="flex-row flex-ali-center flex-jus-sp m-t-16">
<view class="flex-row flex-ali-center m-t-16">
<d-text text="规格:" color="#6C7380"></d-text>
<d-text :text="item.specification || '--'" color="#6C7380"></d-text>
</view>
<view class="flex-row flex-ali-center m-t-16">
<d-text :text="`${item.select_number || item.number}盒`" color="#6C7380"></d-text>
</view>
</view>
<view class="flex-row flex-ali-center">
<d-text text="用法:" color="#6C7380"></d-text>
<d-text :text="formatDrugUsage(item) || '--'" color="#6C7380"></d-text>
</view>
</view>
</view>
<view class="m-t-24 flex-row flex-jus-sa btnBox">
<view @click="handleEditWesternDrug(item, index)" class="btn left">调整用量</view>
<view class="btn right" @click="handleRemoveDrug(index)">删除</view>
</view>
</view>
<view class="m-t-32 flex-col" v-if="currentDrugs.length > 0">
<view class="flex-jus-sp flex-row flex-ali-center">
<d-text text="医嘱" color="#6C7380"></d-text>
<d-text @click="handleOpenDoctorOrderModal" text="常用医嘱" color="#6ACDBB"></d-text>
</view>
<u-input v-model="medicalAdvice" placeholder="请输入" :custom-style="entrustStyle" />
</view>
<view class="flex-row flex-jus-center" v-if="currentDrugs.length === 0">
<d-empty @click="handleOpenWesternMedicineModal"></d-empty>
</view>
</view>
<!-- 中药列表 -->
<view class="white b-r-8 p-32 p-b-0 m-t-2" v-if="activeCategory === 1">
<view class="flex-row flex-jus-sp flex-ali-center">
<view class="flex-row flex-ali-end">
<d-text text="R" className="main-c fs-4" :bold="true"></d-text>
<d-text text="" className="main-c fs-4" :bold="true"></d-text>
</view>
<view class="flex-row" style="height: 50rpx;">
<u-button
v-if="!isCommonPrescription"
:throttle-time="0"
shape="circle"
size="mini"
:custom-style="{backgroundColor: 'transparent !important',border:'1px solid #6ACDBB',color:'#6ACDBB'}"
plain
@click="handleOpenCommonPrescriptionModal"
:ripple="true">
常用方
</u-button>
<view class="m-l-16">
<u-button
:throttle-time="0"
:custom-style="{ backgroundColor:'#6ACDBB',color:'#fff' }"
shape="circle"
size="mini"
@click="handleOpenChineseMedicineModal">
添加商品
</u-button>
</view>
</view>
</view>
<view class="p-col-32" v-if="currentDrugs.length > 0">
<view class="label">药材</view>
<view class="mBox">
<view class="grid-tem-col-2 rp">
<view class="" v-for="(it) in currentDrugs" :key="it.id">
<view class="flex-row flex-jus-sp flex-ali-center m-t-12 delBox">
<d-text :text="it.drug_name || it.name" className="fs-3 content-c"></d-text>
<d-text :text="`${String(it.number)}${it.unit ? it.unit.name : 'g'}`" className="fs-3 tips-c"></d-text>
</view>
</view>
</view>
</view>
<view class="m-t-24 flex-row flex-jus-sa btnBox">
<view @click="handleOpenChineseMedicineModal" class="btn left">调整用量</view>
<view class="btn right" @click="handleRemoveAllDrugs">删除</view>
</view>
</view>
<view class="flex-row flex-jus-center" v-else>
<d-empty @click="handleOpenChineseMedicineModal"></d-empty>
</view>
</view>
<!-- 简单产品列表保健食品产品服务包非药品医疗器械 -->
<view class="m-t-2 b-r-8 white p-32 flex-col" v-if="[3, 5, 6, 7].includes(activeCategory)">
<view class="flex-row flex-jus-sp flex-ali-center">
<d-text text="R" className="main-c fs-4" :bold="true"></d-text>
<view class="flex-row m-l-163" style="height: 50rpx;">
<view class="m-l-16">
<u-button
:throttle-time="0"
:custom-style="{ backgroundColor:'#6ACDBB',color:'#fff' }"
shape="circle"
size="mini"
@click="handleOpenSimpleProductModal">
添加商品
</u-button>
</view>
</view>
</view>
<view class="bottom-border p-col-32" v-for="(item, index) in currentDrugs" :key="index">
2026-05-07 11:04:56 +08:00
<view class="drug-item-content flex-row">
<image
v-if="item.image"
:src="item.image"
class="drug-image"
mode="aspectFill"
></image>
<view class="drug-info-wrapper flex-1">
<view class="flex-row flex-jus-sp flex-ali-center">
<d-text :text="`${index+1}、${item.drug_name}`" className="fs-3 content-c"></d-text>
<d-text :text="`¥${parseFloat(item.price || 0).toFixed(2)}`" className="error-c fs-3"></d-text>
</view>
<view class="flex-row flex-ali-center flex-jus-sp m-t-16">
<view class="flex-row flex-ali-center m-t-16">
<d-text text="规格:" color="#6C7380"></d-text>
<d-text :text="item.specification || '--'" color="#6C7380"></d-text>
</view>
<view class="flex-row flex-ali-center m-t-16">
<view class="quantity-control flex-row flex-ali-center">
<u-button
size="mini"
:custom-style="{ backgroundColor: '#6ACDBB', color: '#fff', width: '48rpx', height: '48rpx', padding: 0 }"
@click.stop="handleDecrementSimpleProduct(index)"
>
-
</u-button>
<d-text :text="`${item.select_number || item.number}${getProductUnit(activeCategory)}`" color="#6C7380" className="m-l-16 m-r-16"></d-text>
<u-button
size="mini"
:custom-style="{ backgroundColor: '#6ACDBB', color: '#fff', width: '48rpx', height: '48rpx', padding: 0 }"
@click.stop="handleIncrementSimpleProduct(index)"
>
+
</u-button>
</view>
</view>
</view>
2026-03-06 13:59:22 +08:00
</view>
</view>
<view class="m-t-24 flex-row flex-jus-sa btnBox">
<view class="btn right" @click="handleRemoveDrug(index)">删除</view>
</view>
</view>
<view class="m-t-32 flex-col" v-if="currentDrugs.length > 0">
<view class="flex-jus-sp flex-row flex-ali-center">
<d-text text="医嘱" color="#6C7380"></d-text>
<d-text @click="handleOpenDoctorOrderModal" text="常用医嘱" color="#6ACDBB"></d-text>
</view>
<u-input v-model="medicalAdvice" placeholder="请输入" :custom-style="entrustStyle" />
</view>
<view class="flex-row flex-jus-center" v-if="currentDrugs.length === 0">
<d-empty @click="handleOpenSimpleProductModal"></d-empty>
</view>
</view>
<!-- 医嘱输入区域中药和简单产品共用 -->
<view class="flex-col b-r-8 white p-32" v-if="activeCategory === 1 && currentDrugs.length > 0">
<view class="flex-jus-sp flex-row flex-ali-center">
<d-text text="医嘱" color="#6C7380"></d-text>
<d-text @click="handleOpenDoctorOrderModal" text="常用医嘱" color="#6ACDBB"></d-text>
</view>
<u-input v-model="medicalAdvice" placeholder="请输入" :custom-style="entrustStyle" />
</view>
<!-- 中药配置区域 -->
<view class="white b-r-8 p-32 m-t-2" v-if="activeCategory === 1">
<ChineseMedicineConfig
:config="chineseConfig"
:processRuleList="processRuleList"
:childProcessRuleList="childProcessRuleList"
:processRuleNoteList="processRuleNoteList"
@update:config="handleUpdateChineseConfig"
/>
</view>
<!-- 费用计算区域 -->
<view class="flex-row p-2 flex-jus-end m-t-2">
<view class="flex-row flex-ali-center" style="margin-right: 20rpx">
<text>诊疗费</text>
<u-input
v-model="treatmentPrice"
placeholder="请输入"
:custom-style="entrustStyle2"
style="width: 200rpx" />
</view>
<view class="flex-row flex-ali-center">
<d-text
v-if="processingFee > 0"
text="加工费:"
className="m-r-16 tips-c"></d-text>
<d-text
v-if="processingFee > 0"
:text="`¥${processingFee.toFixed(2)}`"
class="m-r-16"
color="#F44336"
:bold="true"></d-text>
<d-text text="商品计费:" className="m-r-16 tips-c"></d-text>
<d-text :text="`¥${totalProductCost.toFixed(2)}`" color="#F44336" :bold="true"></d-text>
</view>
</view>
<!-- 总价显示 -->
<view class="flex-row p-2 flex-jus-end m-t-2" v-if="currentDrugs.length > 0">
<view class="flex-row flex-ali-center">
<d-text text="总价:" className="m-r-16 tips-c fs-32"></d-text>
<d-text :text="`¥${totalPrice}`" color="#F44336" :bold="true" className="fs-36"></d-text>
</view>
</view>
<!-- 提示信息 -->
<view class="ac m-t-2 p-32">
<d-text text="请确认患者已在实体医院就诊,并有明确诊断" className="tips-c fs-24"></d-text>
</view>
</scroll-view>
<!-- 底部操作栏 -->
<view class="bottom flex-jus-sp flex-ali-center safe-area-inset-bottom">
<view v-if="!isCommonPrescription" @click="handleSaveAsCommonPrescription" class="btnText">另存常用方</view>
<u-button
:throttle-time="0"
@click="handleSendPrescription"
shape="circle"
:custom-style="{
backgroundColor: isSubmitting ? '#A5DCD2' : '#6ACDBB',
color: '#fff',
height: '86rpx',
width: isCommonPrescription ? '686rpx' : '448rpx'
}"
:disabled="isSubmitting">
{{ isCommonPrescription ? '保存常用方' : '发送处方' }}
</u-button>
</view>
<!-- 诊断选择弹窗 -->
<DiagnosisModal
v-model="showDiagnosisModal"
:selectedDiagnosis="diagnosisText"
@confirm="handleDiagnosisConfirm"
/>
<!-- 医嘱选择弹窗 -->
<DoctorOrderModal
v-model="showDoctorOrderModal"
:selectedDoctorOrder="medicalAdvice"
@confirm="handleDoctorOrderConfirm"
/>
<!-- 常用方选择弹窗 -->
<CommonPrescriptionModal
v-model="showCommonPrescriptionModal"
:prescriptionType="activeCategory"
@select="handleSelectCommonPrescription"
/>
<!-- 西药选择弹窗 -->
<WesternMedicineModal
v-model="showWesternMedicineModal"
:currentDrugs="currentDrugs"
@select="handleSelectWesternDrug"
/>
<!-- 中药选择弹窗 -->
<ChineseMedicineModal
v-model="showChineseMedicineModal"
:currentDrugs="currentDrugs"
@select="handleSelectChineseDrug"
/>
<!-- 简单产品选择弹窗 -->
<SimpleProductModal
v-model="showSimpleProductModal"
:productType="activeCategory"
:currentProducts="currentDrugs"
@select="handleSelectSimpleProduct"
/>
<!-- 西药用法用量设置弹窗 -->
<WesternMedicineUsageModal
v-model="showWesternUsageModal"
:drug="editingDrug"
@confirm="handleConfirmWesternUsage"
/>
<!-- 保存常用方弹窗 -->
<u-modal
v-model="showSaveCommonPrescriptionModal"
:show-cancel-button="true"
title="保存常用方"
@confirm="handleConfirmSaveCommonPrescription"
@cancel="showSaveCommonPrescriptionModal = false">
<view class="slot-content" style="padding: 20rpx;">
<u-input
v-model="commonPrescriptionName"
placeholder="请输入处方名称"
type="text"
:border="true" />
</view>
</u-modal>
</view>
</template>
<script>
import {
addWestPrescription,
checkChineseMedicineConflictApi,
getDiseaseList,
getDrugUseList,
getProductListDoctorReception,
getPatientInfoByPatientId,
getProcessRuleList,
getCommonPrescriptionListApi,
getCommonPrescriptionDetailApi,
saveWestCommonPrescriptionApi,
saveChineseCommonPrescriptionApi,
getCurrentStoreTypeApi
} from '@/api/reception.js';
import { PrescriptionStorage } from './utils/prescriptionStorage.js';
import { PrescriptionCalculator } from './utils/prescriptionCalculator.js';
import { PrescriptionValidator } from './utils/prescriptionValidator.js';
import DiagnosisModal from './components/modals/DiagnosisModal.vue';
import DoctorOrderModal from './components/modals/DoctorOrderModal.vue';
import CommonPrescriptionModal from './components/modals/CommonPrescriptionModal.vue';
import WesternMedicineModal from './components/modals/WesternMedicineModal.vue';
import ChineseMedicineModal from './components/modals/ChineseMedicineModal.vue';
import SimpleProductModal from './components/modals/SimpleProductModal.vue';
import WesternMedicineUsageModal from './components/modals/WesternMedicineUsageModal.vue';
import ChineseMedicineConfig from './components/ChineseMedicineConfig.vue';
export default {
name: 'PrescriptionV2',
components: {
DiagnosisModal,
DoctorOrderModal,
CommonPrescriptionModal,
WesternMedicineModal,
ChineseMedicineModal,
SimpleProductModal,
WesternMedicineUsageModal,
ChineseMedicineConfig
},
data() {
return {
// 页面参数
registerId: '',
patientId: '',
// 患者信息
patientInfo: null,
// 处方类型配置
prescriptionCategories: [
{ label: '中药', value: 1 },
{ label: '西药', value: 2 },
{ label: '保健食品', value: 3 },
{ label: '产品服务包', value: 5 },
{ label: '非药品', value: 6 },
{ label: '医疗器械', value: 7 }
],
// 当前激活的处方类型1=中药2=西药3=保健食品5=产品服务包6=非药品7=医疗器械
activeCategory: 2,
// 当前药品列表
currentDrugs: [],
// 诊断相关
diagnoses: [], // 诊断列表
diagnosisText: '', // 诊断文本(用于显示)
// 医嘱
medicalAdvice: '',
// 诊疗费
treatmentPrice: '',
// 中药配置
chineseConfig: {
ruleType: 1, // 1=自制剂2=委托调剂
packageMethodId: null, // 包法ID自制剂
processRuleId: null, // 制剂ID委托调剂
childProcessRuleId: null, // 煎法ID委托调剂
processRuleNoteId: null, // 备注ID委托调剂
dosage: 7, // 剂数(天数)
dayDosage: 2 // 每日次数
},
// 加工规则列表
processRuleList: [],
childProcessRuleList: [],
processRuleNoteList: [],
// 药品使用方式列表
drugUseList: {
drug_use_num: [],
drug_use_frequency: [],
drug_use_type: [],
drug_unit: [],
drug_time: [],
drug_use_way: []
},
// 弹窗显示状态
showDiagnosisModal: false,
showDoctorOrderModal: false,
showCommonPrescriptionModal: false,
showWesternMedicineModal: false,
showChineseMedicineModal: false,
showSimpleProductModal: false,
showWesternUsageModal: false,
showSaveCommonPrescriptionModal: false,
// 编辑中的药品
editingDrug: null,
editingDrugIndex: -1,
// 常用方名称
commonPrescriptionName: '',
// 是否保存常用方模式
isCommonPrescription: false,
// 提交状态
isSubmitting: false,
// 用户身份
identity: uni.getStorageSync('role'),
// 挂号诊所信息
registerStoreInfo: null, // 挂号诊所信息(包含转诊信息)
sendMode: 0, // 发送模式0=默认使用医生当前诊所1=自定义(使用挂号诊所或承接方诊所)
selectedStoreId: null, // 用户选择的诊所ID
// 样式配置
tabsBtnStyle: {
padding: '8rpx 16px',
height: '58rpx',
fontSize: '30rpx',
width: '212rpx'
},
illnessStyle: {
fontSize: '28rpx',
backgroundColor: '#F3F4F5',
borderRadius: '66rpx',
height: '66rpx',
padding: '8rpx 32rpx'
},
entrustStyle: {
fontSize: '30rpx',
backgroundColor: '#F3F4F5',
height: '74rpx',
padding: '16rpx',
borderRadius: '8rpx',
marginTop: '16rpx'
},
entrustStyle2: {
fontSize: '30rpx',
backgroundColor: '#F3F4F5',
height: '52rpx',
padding: '0 16rpx',
borderRadius: '8rpx',
},
scrollStyle: {
height: 'calc(100vh - 600rpx)',
marginBottom: '200rpx'
}
};
},
computed: {
/**
* 计算商品总价
* @returns {number} 商品总价
*/
totalProductCost() {
if (this.currentDrugs.length === 0) {
return 0;
}
if (this.activeCategory === 1) {
// 中药:药品价格 * 用量 * 剂数
return PrescriptionCalculator.calculateChineseMedicineProductPrice(
this.currentDrugs,
this.chineseConfig.dosage
);
} else if (this.activeCategory === 2) {
// 西药:药品价格 * 数量
return PrescriptionCalculator.calculateWesternMedicineProductPrice(this.currentDrugs);
} else if ([3, 5, 6, 7].includes(this.activeCategory)) {
// 简单产品:产品价格 * 数量
return PrescriptionCalculator.calculateSimpleProductPrice(this.currentDrugs);
}
return 0;
},
/**
* 计算加工费仅中药委托调剂
* @returns {number} 加工费
*/
processingFee() {
if (this.activeCategory !== 1 || this.chineseConfig.ruleType !== 2) {
return 0;
}
// 查找选中的加工规则
const processRule = this.childProcessRuleList.find(
item => item.id === this.chineseConfig.childProcessRuleId
);
if (!processRule) {
return 0;
}
// 计算总药品数量
const totalDrugQuantity = this.currentDrugs.reduce(
(sum, drug) => sum + parseFloat(drug.number || 1),
0
);
return PrescriptionCalculator.calculateProcessingFee(
processRule,
this.chineseConfig.dosage,
totalDrugQuantity
);
},
/**
* 计算总价
* @returns {string} 总价保留两位小数
*/
totalPrice() {
const total = PrescriptionCalculator.calculateTotalPrice({
category: this.activeCategory,
drugs: this.currentDrugs,
dosage: this.chineseConfig.dosage,
processingFee: this.processingFee,
treatmentPrice: parseFloat(this.treatmentPrice || 0)
});
return total.toFixed(2);
}
},
onLoad(options) {
// 获取页面参数
this.registerId = options.register_id || '';
this.patientId = options.patient_id || '';
this.isCommonPrescription = uni.getStorageSync('add') === true;
// 初始化页面数据
this.initializePageData();
},
async onShow() {
// 从本地存储恢复当前分类的药品数据
this.loadCurrentCategoryDrugs();
// 如果当前是中药类型,检查转诊提示
if (this.activeCategory === 1) {
await this.checkAndShowTransferTip();
}
},
onShow() {
// 从本地存储恢复当前分类的药品数据
this.loadCurrentCategoryDrugs();
},
methods: {
/**
* 初始化页面数据
* 职责加载患者信息恢复本地存储的处方数据加载基础配置数据获取挂号诊所信息
*/
async initializePageData() {
try {
// 恢复本地存储数据
this.restoreFromLocalStorage();
// 加载患者信息
await this.loadPatientInfo();
// 加载基础配置数据
await this.loadBasicConfigData();
// 获取挂号诊所信息(包含转诊信息)
await this.loadRegisterStoreInfo();
// 加载当前分类的药品数据
this.loadCurrentCategoryDrugs();
// 如果当前是中药类型,检查转诊提示
if (this.activeCategory === 1) {
await this.checkAndShowTransferTip();
}
} catch (error) {
console.error('初始化页面数据失败:', error);
this.$toast('初始化失败,请重试');
}
},
/**
* 从本地存储恢复数据
* 职责恢复当前激活的分类患者ID等
*/
restoreFromLocalStorage() {
// 恢复当前激活的分类
const savedCategory = PrescriptionStorage.getActiveCategory(this.registerId);
if (savedCategory) {
this.activeCategory = savedCategory;
} else {
// 检查哪个分类有数据
const categories = [1, 2, 3, 5, 6, 7];
for (const category of categories) {
const data = PrescriptionStorage.loadPrescriptionData(category, this.registerId);
if (data && data.drugs && data.drugs.length > 0) {
this.activeCategory = category;
break;
}
}
}
},
/**
* 加载当前分类的药品数据
* 职责从本地存储加载当前分类的药品列表
*/
loadCurrentCategoryDrugs() {
const data = PrescriptionStorage.loadPrescriptionData(this.activeCategory, this.registerId);
if (data) {
this.currentDrugs = data.drugs || [];
this.diagnoses = data.diagnoses || [];
this.diagnosisText = data.diagnosisText || '';
this.medicalAdvice = data.medicalAdvice || '';
this.treatmentPrice = data.treatmentPrice || '';
if (data.chineseConfig) {
this.chineseConfig = { ...this.chineseConfig, ...data.chineseConfig };
}
} else {
this.currentDrugs = [];
}
},
/**
* 保存当前数据到本地存储
* 职责保存当前分类的药品列表诊断医嘱等到本地存储
*/
saveToLocalStorage() {
const data = {
drugs: this.currentDrugs,
diagnoses: this.diagnoses,
diagnosisText: this.diagnosisText,
medicalAdvice: this.medicalAdvice,
treatmentPrice: this.treatmentPrice,
chineseConfig: this.activeCategory === 1 ? this.chineseConfig : null
};
PrescriptionStorage.savePrescriptionData(this.activeCategory, this.registerId, data);
PrescriptionStorage.saveActiveCategory(this.activeCategory, this.registerId);
},
/**
* 加载患者信息
* 职责调用接口获取患者详细信息
*/
async loadPatientInfo() {
if (!this.patientId) {
console.warn('患者ID为空无法加载患者信息');
return;
}
try {
// 使用新的接口根据患者ID获取患者信息
const res = await getPatientInfoByPatientId(this.patientId);
// 后端返回的数据在 result 字段中
const data = res.result || res.data || res;
if (data && data.user_patient) {
this.patientInfo = {
id: data.user_patient.id || this.patientId, // 包含患者ID后端需要
name: data.user_patient.name,
mobile: data.user_patient.mobile,
age: data.user_patient.age,
sex: data.user_patient.sex
};
console.log('患者信息加载成功:', this.patientInfo);
} else {
console.warn('获取患者信息返回数据格式不正确:', res);
this.$toast('获取患者信息失败,数据格式不正确');
}
} catch (error) {
console.error('获取患者信息失败:', error);
this.$toast('获取患者信息失败,请检查网络连接');
// 不抛出错误,允许页面继续加载,但会在发送处方时检查
}
},
/**
* 加载基础配置数据
* 职责加载药品使用方式加工规则等基础配置
*/
async loadBasicConfigData() {
try {
// 加载药品使用方式列表
const drugUseRes = await getDrugUseList();
if (drugUseRes) {
this.drugUseList = drugUseRes;
}
// 如果当前是中药类别,加载制剂列表
if (this.activeCategory === 1 && this.processRuleList.length === 0) {
await this.loadProcessRuleList(0, 0);
}
} catch (error) {
console.error('加载基础配置数据失败:', error);
}
},
/**
* 加载挂号诊所信息
* 职责获取挂号诊所信息包括转诊信息诊所类型委托诊所等
*/
async loadRegisterStoreInfo() {
if (!this.registerId) {
return;
}
try {
// 传入 register_id 参数以获取转诊信息
const res = await getCurrentStoreTypeApi({ register_id: this.registerId });
if (res) {
this.registerStoreInfo = res;
// 如果是转诊挂号自动使用承接方诊所ID转接方开处方时
if (res.is_from_transfer === 1 && res.delegate_store_id) {
// 转接方开处方时自动设置store_id为承接方诊所ID
this.selectedStoreId = res.delegate_store_id;
this.sendMode = 1; // 使用自定义模式但使用承接方诊所ID
} else if (res.store_id) {
// 非转诊挂号,默认选择挂号诊所
this.selectedStoreId = res.store_id;
// 如果挂号诊所与医生当前诊所不同,设置为自定义模式
if (res.can_change) {
this.sendMode = 1;
} else {
this.sendMode = 0;
}
}
console.log('获取挂号诊所信息成功:', res);
}
} catch (error) {
console.error('获取挂号诊所信息失败:', error);
}
},
/**
* 切换处方类型
* @param {number} category - 处方类型1=中药2=西药3=保健食品5=产品服务包6=非药品7=医疗器械
* 职责保存当前类型数据切换到新类型加载新类型数据检查转诊提示
*/
async handleSwitchCategory(category) {
// 保存当前类型数据
this.saveToLocalStorage();
// 切换到新类型
this.activeCategory = category;
// 加载新类型数据
this.loadCurrentCategoryDrugs();
// 如果切换到中药category === 1检查是否需要显示转诊提示并加载制剂列表
if (category === 1) {
await this.checkAndShowTransferTip();
// 如果制剂列表为空,自动加载制剂列表
if (this.processRuleList.length === 0) {
await this.loadProcessRuleList(0, 0);
}
}
},
/**
* 检查并显示转诊提示
* 职责当切换到中药处方时如果当前诊所为西医诊所显示转诊提示
*/
async checkAndShowTransferTip() {
try {
// 确保已获取诊所信息
if (!this.registerStoreInfo) {
await this.loadRegisterStoreInfo();
}
const storeInfo = this.registerStoreInfo;
if (!storeInfo) {
return;
}
// 检测是否为西医诊所clinic_type === 1且有委托诊所
if (storeInfo.clinic_type === 1 && storeInfo.delegate_store) {
const delegateStore = storeInfo.delegate_store;
const doctorName = delegateStore.doctor?.name || '委托医生';
const storeName = delegateStore.name || '委托诊所';
uni.showModal({
title: '转诊提示',
content: `检测到当前诊所为西医诊所,本次处方开具后自动转接到【${storeName}】的【${doctorName}】的在线复诊中`,
showCancel: false,
confirmText: '我知道了'
});
}
} catch (error) {
console.error('获取诊所信息失败:', error);
}
},
/**
* 打开诊断选择弹窗
* 职责显示诊断选择弹窗
*/
handleOpenDiagnosisModal() {
this.showDiagnosisModal = true;
},
/**
* 处理诊断确认
* @param {string} diagnosisText - 诊断文本
* 职责将诊断文本转换为诊断数组
*/
handleDiagnosisConfirm(diagnosisText) {
this.diagnosisText = diagnosisText;
// 将诊断文本转换为诊断数组
if (diagnosisText) {
const diagnosisNames = diagnosisText.split('').filter(Boolean);
this.diagnoses = diagnosisNames.map((name, index) => ({
id: `temp_${index}`,
name: name
}));
} else {
this.diagnoses = [];
}
// 保存到本地存储
this.saveToLocalStorage();
},
/**
* 删除诊断
* @param {number} index - 诊断索引
* 职责从诊断列表中删除指定诊断
*/
handleRemoveDiagnosis(index) {
this.diagnoses.splice(index, 1);
// 更新诊断文本
this.diagnosisText = this.diagnoses.map(item => item.name).join('');
// 保存到本地存储
this.saveToLocalStorage();
},
/**
* 打开医嘱选择弹窗
* 职责显示医嘱选择弹窗
*/
handleOpenDoctorOrderModal() {
this.showDoctorOrderModal = true;
},
/**
* 处理医嘱确认
* @param {string} doctorOrderText - 医嘱文本
* 职责更新医嘱内容
*/
handleDoctorOrderConfirm(doctorOrderText) {
this.medicalAdvice = doctorOrderText;
// 保存到本地存储
this.saveToLocalStorage();
},
/**
* 打开常用方选择弹窗
* 职责显示常用方选择弹窗
*/
handleOpenCommonPrescriptionModal() {
this.showCommonPrescriptionModal = true;
},
/**
* 处理选择常用方
* @param {Object} prescription - 常用方数据
* 职责填充药品诊断医嘱到当前处方
*/
async handleSelectCommonPrescription(prescription) {
try {
// 获取常用方详情
const detailRes = await getCommonPrescriptionDetailApi(
prescription.id,
this.getCommonPrescriptionType(this.activeCategory)
);
if (!detailRes || !detailRes.recipes) {
this.$toast('获取常用方详情失败');
return;
}
// 填充药品
this.currentDrugs = detailRes.recipes.map(recipe => {
if (this.activeCategory === 1) {
// 中药
return {
id: recipe.drug_id || recipe.id,
drug_id: recipe.drug_id || recipe.id,
drug_name: recipe.drug_name || recipe.name,
number: recipe.number || 1,
price: recipe.price || 0,
way_id: recipe.way_id || 0
};
} else {
// 西药
return {
id: recipe.drug_id || recipe.id,
drug_id: recipe.drug_id || recipe.id,
drug_name: recipe.drug_name,
number: recipe.number || 1,
select_number: recipe.select_number || 1,
price: recipe.price || 0,
time_id: recipe.time_id || 0,
type_id: recipe.type_id || 0,
frequency_id: recipe.frequency_id || 0,
unit_id: recipe.unit_id || 0,
image: recipe.image || '',
instruction: recipe.instruction || ''
};
}
});
// 填充诊断和医嘱
if (detailRes.prescription) {
if (detailRes.prescription.clinical_diagnose) {
this.diagnosisText = detailRes.prescription.clinical_diagnose;
const diagnosisNames = this.diagnosisText.split('').filter(Boolean);
this.diagnoses = diagnosisNames.map((name, index) => ({
id: `temp_${index}`,
name: name
}));
}
if (detailRes.prescription.doctor_order) {
this.medicalAdvice = detailRes.prescription.doctor_order;
}
// 填充中药配置
if (this.activeCategory === 1 && detailRes.prescription) {
this.chineseConfig = {
...this.chineseConfig,
ruleType: detailRes.prescription.rule_type || 1,
dosage: detailRes.prescription.dosage || 7,
dayDosage: detailRes.prescription.day_dosage || 2,
packageMethodId: detailRes.prescription.package_method_id || null,
processRuleId: detailRes.prescription.process_rule_id || null,
childProcessRuleId: detailRes.prescription.child_process_rule_id || null,
processRuleNoteId: detailRes.prescription.process_rule_note_id || null
};
// 加载加工规则列表
if (this.chineseConfig.processRuleId) {
await this.loadProcessRuleList(this.chineseConfig.processRuleId, 0);
}
if (this.chineseConfig.childProcessRuleId) {
await this.loadProcessRuleList(0, this.chineseConfig.childProcessRuleId);
}
}
}
// 保存到本地存储
this.saveToLocalStorage();
this.$toast('常用方已填充');
} catch (error) {
console.error('选择常用方失败:', error);
this.$toast('选择常用方失败');
}
},
/**
* 获取常用方类型字符串
* @param {number} category - 处方类型
* @returns {string} 常用方类型westchinesegranular
*/
getCommonPrescriptionType(category) {
if (category === 1) {
return 'chinese';
} else if (category === 2) {
return 'west';
} else {
return 'granular';
}
},
/**
* 打开西药选择弹窗
* 职责显示西药选择弹窗
*/
handleOpenWesternMedicineModal() {
this.showWesternMedicineModal = true;
},
/**
* 处理选择西药
* @param {Object} drug - 药品数据
* 职责验证药品是否已存在添加到列表保存到本地存储
*/
handleSelectWesternDrug(drug) {
// 验证药品是否已存在
if (PrescriptionValidator.isDrugExists(this.currentDrugs, drug)) {
this.$toast('该药品已在列表中');
return;
}
// 添加到列表
const newDrug = {
index_id: drug.id,
id: drug.drug_id || drug.drug?.id || drug.id,
drug_id: drug.drug_id || drug.drug?.id || drug.id,
drug_name: drug.drug_name || drug.drug?.drug_name,
number: drug.number || 1,
select_number: drug.select_number || 1,
price: drug.price || 0,
specification: drug.specification || drug.drug?.specification || '',
image: drug.image || drug.drug?.image || '',
instruction: drug.instruction || drug.drug?.instruction || '',
// 用法用量
time_id: drug.time_id || drug.drug?.time_id || 0,
type_id: drug.type_id || drug.drug?.type_id || 0,
frequency_id: drug.frequency_id || drug.drug?.frequency_id || 0,
unit_id: drug.unit_id || drug.drug?.unit_id || 0,
use_num: this.drugUseList.drug_time?.find(item => item.id === (drug.time_id || drug.drug?.time_id)),
use_type: this.drugUseList.drug_use_type?.find(item => item.id === (drug.type_id || drug.drug?.type_id)),
use_frequency: this.drugUseList.drug_use_frequency?.find(item => item.id === (drug.frequency_id || drug.drug?.frequency_id)),
unit: this.drugUseList.drug_unit?.find(item => item.id === (drug.unit_id || drug.drug?.unit_id))
};
this.currentDrugs.push(newDrug);
// 选完药后立即打开用法用量设置弹窗
const index = this.currentDrugs.length - 1;
this.handleEditWesternDrug(this.currentDrugs[index], index);
// 保存到本地存储
this.saveToLocalStorage();
this.$toast(`已将${newDrug.drug_name}添加到清单中!`);
},
/**
* 打开中药选择弹窗
* 职责显示中药选择弹窗
*/
handleOpenChineseMedicineModal() {
this.showChineseMedicineModal = true;
},
/**
* 处理选择中药
* @param {Array} drugs - 药品列表
* 职责更新中药列表保存到本地存储
*/
handleSelectChineseDrug(drugs) {
this.currentDrugs = drugs || [];
// 保存到本地存储
this.saveToLocalStorage();
},
/**
* 打开简单产品选择弹窗
* 职责显示简单产品选择弹窗
*/
handleOpenSimpleProductModal() {
this.showSimpleProductModal = true;
},
/**
* 处理选择简单产品
* @param {Object} product - 产品数据
* 职责验证产品是否已存在添加到列表保存到本地存储
*/
handleSelectSimpleProduct(product) {
// 验证产品是否已存在
if (PrescriptionValidator.isDrugExists(this.currentDrugs, product)) {
this.$toast('该产品已在列表中');
return;
}
// 添加到列表
2026-05-07 11:04:56 +08:00
// 参考PC端index_id, id, drug_name, number, price, image, instruction, type, select_number
2026-03-06 13:59:22 +08:00
const newProduct = {
index_id: product.id,
id: product.drug_id || product.drug?.id || product.id,
drug_name: product.drug_name || product.drug?.drug_name || product.name,
number: 1,
price: product.price || 0,
image: product.image || product.drug?.image || '',
2026-05-07 11:04:56 +08:00
instruction: product.instruction || product.drug?.instruction || '',
type: product.drug?.type || product.type || this.activeCategory,
select_number: 1
2026-03-06 13:59:22 +08:00
};
this.currentDrugs.push(newProduct);
// 保存到本地存储
this.saveToLocalStorage();
this.$toast(`已将${newProduct.drug_name}添加到清单中!`);
},
/**
* 编辑西药用法用量
* @param {Object} drug - 药品数据
* @param {number} index - 药品索引
* 职责打开用法用量设置弹窗
*/
handleEditWesternDrug(drug, index) {
this.editingDrug = JSON.parse(JSON.stringify(drug));
this.editingDrugIndex = index;
this.showWesternUsageModal = true;
},
/**
* 确认西药用法用量
* @param {Object} usageData - 用法用量数据
* 职责更新药品的用法用量保存到本地存储
*/
handleConfirmWesternUsage(usageData) {
if (this.editingDrugIndex >= 0) {
const drug = this.currentDrugs[this.editingDrugIndex];
// 更新用法用量
drug.time_id = usageData.time_id;
drug.type_id = usageData.type_id;
drug.frequency_id = usageData.frequency_id;
drug.unit_id = usageData.unit_id;
drug.number = usageData.number;
drug.select_number = usageData.select_number || drug.select_number;
drug.use_num = usageData.use_num;
drug.use_type = usageData.use_type;
drug.use_frequency = usageData.use_frequency;
drug.unit = usageData.unit;
// 保存到本地存储
this.saveToLocalStorage();
}
this.editingDrug = null;
this.editingDrugIndex = -1;
},
/**
* 从处方中删除药品
* @param {number} index - 药品索引
* 职责从列表中删除更新本地存储
*/
handleRemoveDrug(index) {
uni.showModal({
title: '删除药品',
content: '是否要删除?',
showCancel: true,
success: ({ confirm }) => {
if (confirm) {
this.currentDrugs.splice(index, 1);
// 保存到本地存储
this.saveToLocalStorage();
}
}
});
},
2026-05-07 11:04:56 +08:00
/**
* 增加简单产品数量
* @param {number} index - 产品索引
* 职责增加简单产品的数量
*/
handleIncrementSimpleProduct(index) {
if (index >= 0 && index < this.currentDrugs.length) {
const product = this.currentDrugs[index];
const currentNumber = product.select_number || product.number || 1;
this.$set(product, 'select_number', currentNumber + 1);
// 保存到本地存储
this.saveToLocalStorage();
}
},
/**
* 减少简单产品数量
* @param {number} index - 产品索引
* 职责减少简单产品的数量如果为1则提示删除
*/
handleDecrementSimpleProduct(index) {
if (index >= 0 && index < this.currentDrugs.length) {
const product = this.currentDrugs[index];
const currentNumber = product.select_number || product.number || 1;
if (currentNumber > 1) {
this.$set(product, 'select_number', currentNumber - 1);
// 保存到本地存储
this.saveToLocalStorage();
} else {
// 数量为1时提示是否删除
uni.showModal({
title: '删除产品',
content: '数量为1时是否要删除该产品',
showCancel: true,
success: ({ confirm }) => {
if (confirm) {
this.currentDrugs.splice(index, 1);
// 保存到本地存储
this.saveToLocalStorage();
}
}
});
}
}
},
2026-03-06 13:59:22 +08:00
/**
* 删除所有药品中药
* 职责清空中药列表保存到本地存储
*/
handleRemoveAllDrugs() {
uni.showModal({
title: '删除药品',
content: '是否要删除所有药品?',
showCancel: true,
success: ({ confirm }) => {
if (confirm) {
this.currentDrugs = [];
// 保存到本地存储
this.saveToLocalStorage();
}
}
});
},
/**
* 更新中药配置
* @param {Object} config - 新的配置
* 职责更新中药配置加载加工规则列表保存到本地存储
*/
async handleUpdateChineseConfig(config) {
// 保存旧的配置值,用于比较
const oldRuleType = this.chineseConfig.ruleType;
const oldProcessRuleId = this.chineseConfig.processRuleId;
const oldChildProcessRuleId = this.chineseConfig.childProcessRuleId;
// 如果切换到委托调剂ruleType = 2且制剂列表为空则加载制剂列表
if (config.ruleType === 2 && config.ruleType !== oldRuleType) {
if (this.processRuleList.length === 0) {
await this.loadProcessRuleList(0, 0);
}
}
// 如果从委托调剂切换回自制剂,清空相关配置
if (config.ruleType === 1 && oldRuleType === 2) {
config.processRuleId = null;
config.childProcessRuleId = null;
config.processRuleNoteId = null;
this.processRuleList = [];
this.childProcessRuleList = [];
this.processRuleNoteList = [];
}
// 如果选择了新的制剂清空煎法和备注ID级联清空
if (config.processRuleId && config.processRuleId !== oldProcessRuleId) {
config.childProcessRuleId = null;
config.processRuleNoteId = null;
// 清空煎法和备注列表,等待重新加载
this.childProcessRuleList = [];
this.processRuleNoteList = [];
}
// 如果选择了新的煎法清空备注ID级联清空
if (config.childProcessRuleId && config.childProcessRuleId !== oldChildProcessRuleId) {
config.processRuleNoteId = null;
// 清空备注列表,等待重新加载
this.processRuleNoteList = [];
}
// 更新配置
this.chineseConfig = { ...this.chineseConfig, ...config };
// 如果选择了制剂,加载煎法选项
if (config.processRuleId && config.processRuleId !== oldProcessRuleId) {
await this.loadProcessRuleList(config.processRuleId, 0);
}
// 如果选择了煎法,加载备注选项
if (config.childProcessRuleId && config.childProcessRuleId !== oldChildProcessRuleId) {
await this.loadProcessRuleList(0, config.childProcessRuleId);
}
// 保存到本地存储
this.saveToLocalStorage();
},
/**
* 加载加工规则列表
* @param {number} pid - 父级ID加载煎法时使用
* @param {number} ruleId - 规则ID加载备注时使用
* 职责调用接口加载加工规则列表
*/
async loadProcessRuleList(pid = 0, ruleId = 0) {
try {
const data = ruleId === 0 ? { pid } : { rule_id: ruleId };
const res = await getProcessRuleList(data);
// 提取数据,兼容不同的响应格式
const list = res?.data || res?.result || res || [];
if (ruleId !== 0) {
// 加载备注列表
this.processRuleNoteList = list;
} else if (pid === 0) {
// 加载制剂列表
this.processRuleList = list;
} else {
// 加载煎法列表
this.childProcessRuleList = list;
}
console.log('加载加工规则列表成功:', { pid, ruleId, listLength: list.length });
} catch (error) {
console.error('加载加工规则列表失败:', error);
this.$toast('加载加工规则列表失败');
}
},
/**
* 格式化药品用法显示
* @param {Object} drug - 药品数据
* @returns {string} 用法文本
*/
formatDrugUsage(drug) {
if (!drug.use_type || !drug.use_frequency || !drug.use_num || !drug.unit) {
return '';
}
return `${drug.use_type.name}${drug.use_frequency.name}${drug.use_num.name},每次${drug.number}${drug.unit.name}`;
},
/**
* 获取产品单位
* @param {number} category - 产品类型
* @returns {string} 单位文本
*/
getProductUnit(category) {
if (category === 5) {
return '周期';
}
return '盒';
},
/**
* 验证处方数据
* @returns {Object} { valid: boolean, message: string }
* 职责验证药品诊断医嘱等必填项
*/
validatePrescriptionData() {
return PrescriptionValidator.validatePrescriptionData({
category: this.activeCategory,
drugs: this.currentDrugs,
diagnoses: this.diagnoses,
medicalAdvice: this.medicalAdvice,
chineseConfig: this.activeCategory === 1 ? this.chineseConfig : null
});
},
/**
* 检查中药相冲
* @returns {Promise<Object>} { hasConflict: boolean, message: string }
* 职责调用接口检查中药相冲情况
*/
async checkChineseMedicineConflict() {
if (this.activeCategory !== 1) {
return { hasConflict: false };
}
try {
const names = this.currentDrugs.map((item) => item.drug_name || item.name);
const res = await checkChineseMedicineConflictApi({ names });
if (res && res.is_exist === true) {
return {
hasConflict: true,
message: res.message || '检测到该处方内具有药物相冲'
};
}
return { hasConflict: false };
} catch (error) {
console.error('检查中药相冲失败:', error);
return { hasConflict: false };
}
},
/**
* 发送处方
* @param {number} doctorSecondSign - 是否需要二次签名0-1-
* 职责验证数据检查相冲获取诊所信息处理诊所选择调用接口处理结果
*/
async handleSendPrescription(doctorSecondSign = 0) {
if (this.isSubmitting) {
this.$toast('正在处理中,请勿重复提交');
return;
}
// 验证处方数据
const validation = this.validatePrescriptionData();
if (!validation.valid) {
this.$toast(validation.message);
return;
}
this.isSubmitting = true;
try {
// 确保已获取诊所信息
if (!this.registerStoreInfo) {
await this.loadRegisterStoreInfo();
}
// 如果是中药,先检查相冲
if (this.activeCategory === 1) {
const conflictCheck = await this.checkChineseMedicineConflict();
if (conflictCheck.hasConflict) {
uni.showModal({
title: '药物相冲提示',
content: conflictCheck.message || '检测到该处方内具有药物相冲,是否继续开方?',
showCancel: true,
success: ({ confirm }) => {
if (confirm) {
this.handleSendPrescriptionWithStoreSelection(1);
} else {
this.isSubmitting = false;
}
}
});
return;
}
}
// 处理诊所选择和发送处方
await this.handleSendPrescriptionWithStoreSelection(doctorSecondSign);
} catch (error) {
console.error('发送处方失败:', error);
this.$toast('发送处方失败,请重试');
this.isSubmitting = false;
}
},
/**
* 处理诊所选择和发送处方
* @param {number} doctorSecondSign - 是否需要二次签名0-1-
* 职责根据转诊逻辑和诊所选择确定发送模式然后执行发送
*/
async handleSendPrescriptionWithStoreSelection(doctorSecondSign = 0) {
const storeInfo = this.registerStoreInfo;
// 如果是转诊挂号自动使用承接方诊所ID不需要弹出诊所选择弹窗
if (storeInfo?.is_from_transfer === 1 && storeInfo?.delegate_store_id) {
// 转接方开处方时自动使用承接方诊所ID
await this.executeSendPrescription(doctorSecondSign, 1, storeInfo.delegate_store_id);
} else if (storeInfo?.can_change) {
// 如果允许切换诊所,弹出诊所选择弹窗
const registerStoreName = storeInfo?.store_name || '挂号诊所';
const registerStoreId = storeInfo?.store_id;
const currentStoreName = storeInfo?.current_store_name || '当前诊所';
uni.showModal({
title: '选择诊所',
content: `请选择使用哪个诊所开方:\n\n挂号诊所${registerStoreName}\n当前诊所${currentStoreName}`,
confirmText: '使用挂号诊所',
cancelText: '使用当前诊所',
success: ({ confirm, cancel }) => {
if (confirm) {
// 使用挂号诊所
this.executeSendPrescription(doctorSecondSign, 1, registerStoreId);
} else if (cancel) {
// 使用当前诊所
this.executeSendPrescription(doctorSecondSign, 0, null);
} else {
this.isSubmitting = false;
}
},
fail: () => {
this.isSubmitting = false;
}
});
} else {
// 直接发送(使用默认诊所)
await this.executeSendPrescription(doctorSecondSign, 0, null);
}
},
/**
* 执行发送处方
* @param {number} doctorSecondSign - 是否需要二次签名0-1-
* @param {number} sendMode - 发送模式0=默认使用医生当前诊所1=自定义使用挂号诊所或承接方诊所
* @param {number|null} customStoreId - 自定义诊所IDsendMode=1时使用
* 职责构建参数调用接口处理结果
*/
async executeSendPrescription(doctorSecondSign = 0, sendMode = 0, customStoreId = null) {
try {
// 发送前参数校验(仅西药相关)
if (this.activeCategory === 2) {
// 如果患者信息缺失,尝试重新加载
if (!this.patientInfo || !this.patientId) {
// 如果 patientId 存在但 patientInfo 为空,尝试重新加载
if (this.patientId && !this.patientInfo) {
console.log('患者信息缺失,尝试重新加载...');
await this.loadPatientInfo();
}
// 重新检查患者信息
if (!this.patientInfo || !this.patientId) {
let errorMsg = '患者信息缺失,无法发送处方';
if (!this.patientId) {
errorMsg += '缺少患者ID';
} else if (!this.patientInfo) {
errorMsg += '(无法获取患者信息,请检查网络连接)';
}
this.$toast(errorMsg);
this.isSubmitting = false;
return;
}
}
const invalidDrug = this.currentDrugs.find((drug) => {
return !(
drug.id &&
(drug.select_number || drug.number) &&
drug.time_id &&
drug.type_id &&
drug.frequency_id &&
drug.unit_id &&
drug.use_type && drug.use_type.name &&
drug.use_num && drug.use_num.name &&
drug.unit && drug.unit.name
);
});
if (invalidDrug) {
this.$toast('请先为西药设置完整的用法用量');
return;
}
}
// 如果是转诊挂号自动使用承接方诊所ID转接方开处方时
let finalSendMode = sendMode;
let finalStoreId = customStoreId;
const storeInfo = this.registerStoreInfo;
if (storeInfo?.is_from_transfer === 1 && storeInfo?.delegate_store_id) {
// 转接方开处方时自动使用承接方诊所ID不需要在模态框选择
finalSendMode = 1;
finalStoreId = storeInfo.delegate_store_id;
}
// 构建诊断文本
const clinical_diagnose = this.diagnosisText || this.diagnoses.map((item) => item.name).join(',');
// 确保 doctor_second_sign 是数字如果是对象则提取值或默认为0
let doctorSecondSignValue = 0;
if (typeof doctorSecondSign === 'number') {
doctorSecondSignValue = doctorSecondSign;
} else if (typeof doctorSecondSign === 'object' && doctorSecondSign !== null) {
// 如果是对象(可能是事件对象),尝试从 value 属性提取数字值
// 注意:不要使用 type 属性,因为事件对象的 type 是字符串(如 'tap'
if (typeof doctorSecondSign.value === 'number') {
doctorSecondSignValue = doctorSecondSign.value;
} else {
// 如果无法提取数字值默认为0
doctorSecondSignValue = 0;
}
} else if (typeof doctorSecondSign === 'string') {
// 如果是字符串,尝试转换为数字
const parsed = parseInt(doctorSecondSign, 10);
doctorSecondSignValue = isNaN(parsed) ? 0 : parsed;
} else {
// 其他类型boolean等转换为0或1
doctorSecondSignValue = doctorSecondSign ? 1 : 0;
}
// 构建参数
// 确保patient对象格式与PC端一致
const patientData = {
id: this.patientInfo.id || this.patientId,
user_id: this.patientInfo.user_id || null, // PC端有 user_id需要添加
name: this.patientInfo.name || '',
age: this.patientInfo.age || 0,
sex: this.patientInfo.sex || 0,
mobile: this.patientInfo.mobile || '' // 移动端可能是加密的,但格式应该一致
};
// 根据处方类型(中药/西药)分别处理 drugs 数组
// 参考PC端PC端直接传递 currentDrugs.value不做额外处理
// 移动端需要确保字段与PC端完全一致
let drugsData;
if (this.activeCategory === 1) {
// 中药处方只保留必要字段与PC端格式完全一致
// PC端字段index_id, id, drug_name, number, price, way_id, select_number
drugsData = this.currentDrugs.map((drug) => {
const cleanDrug = {
index_id: drug.index_id, // 必须存在ChineseMedicineModal已返回
id: drug.id, // 必须存在ChineseMedicineModal已返回
drug_name: drug.drug_name || drug.name, // 药品名称
number: drug.number || drug._quantity || 0, // 数量
price: drug.price || '0.0000', // 价格
way_id: drug.way_id || 0, // 用法ID
select_number: drug.select_number || 1 // 选择数量
};
2026-05-07 11:04:56 +08:00
return cleanDrug;
});
} else if ([3, 5, 6, 7].includes(this.activeCategory)) {
// 简单产品保健食品、产品服务包、非药品、医疗器械参考PC端不需要用法用量
// PC端字段index_id, id, drug_name, number, price, image, instruction, type, select_number
drugsData = this.currentDrugs.map((drug) => {
const cleanDrug = {
index_id: drug.index_id,
id: drug.id,
drug_name: drug.drug_name || drug.name,
number: drug.number || 1,
price: drug.price || '0.0000',
select_number: drug.select_number || 1
};
// 可选字段image, instruction, type如果存在则保留
if (drug.image) {
cleanDrug.image = drug.image;
}
if (drug.instruction) {
cleanDrug.instruction = drug.instruction;
}
if (drug.type) {
cleanDrug.type = drug.type;
}
2026-03-06 13:59:22 +08:00
return cleanDrug;
});
} else {
// 西药处方:保留用法用量字段(原有逻辑)
drugsData = this.currentDrugs.map(drug => {
const drugData = { ...drug };
// 确保用法用量字段是对象且包含name属性
if (!drugData.use_type || typeof drugData.use_type !== 'object' || !drugData.use_type.name) {
if (drugData.type_id && this.drugUseList.drug_use_type) {
drugData.use_type = this.drugUseList.drug_use_type.find(item => item.id === drugData.type_id) || { name: '' };
} else {
drugData.use_type = { name: '' };
}
}
if (!drugData.use_num || typeof drugData.use_num !== 'object' || !drugData.use_num.name) {
if (drugData.time_id && this.drugUseList.drug_time) {
drugData.use_num = this.drugUseList.drug_time.find(item => item.id === drugData.time_id) || { name: '' };
} else {
drugData.use_num = { name: '' };
}
}
if (!drugData.unit || typeof drugData.unit !== 'object' || !drugData.unit.name) {
if (drugData.unit_id && this.drugUseList.drug_unit) {
drugData.unit = this.drugUseList.drug_unit.find(item => item.id === drugData.unit_id) || { name: '' };
} else {
drugData.unit = { name: '' };
}
}
return drugData;
});
}
const params = {
patient: patientData,
drugs: drugsData,
diagnosis: clinical_diagnose,
medicalAdvice: this.medicalAdvice,
total: parseFloat(this.totalPrice),
category: 1, // 1-自费2-医保TODO: 从配置获取
drug_type: 2, // TODO: 根据实际需求设置
register_id: parseInt(this.registerId),
treatment_price: parseFloat(this.treatmentPrice || 0),
prescription_type: this.activeCategory,
doctor_second_sign: doctorSecondSignValue,
// 诊所选择参数转诊挂号时自动使用承接方诊所ID
send_mode: finalSendMode,
custom_store_id: finalSendMode === 1 ? finalStoreId : null
};
// 中药特有字段
if (this.activeCategory === 1) {
params.package_method_id = this.chineseConfig.packageMethodId || null;
params.process_rule_id = this.chineseConfig.processRuleId || null;
params.process_rule_note_id = this.chineseConfig.processRuleNoteId || null;
params.child_process_rule_id = this.chineseConfig.childProcessRuleId || null;
params.process_rule_type = this.chineseConfig.ruleType || 1;
params.processing_fee = this.processingFee;
params.dosage = this.chineseConfig.dosage || 7;
params.day_dosage = this.chineseConfig.dayDosage || 2;
}
// 调用接口
const res = await addWestPrescription(params);
if (res && (res.code === 0 || res.errcode === 0)) {
this.$toast('发送成功');
// 检查是否需要转诊(西医诊所开中药处方)
const needTransfer = res?.result?.need_transfer || res?.data?.need_transfer || res?.need_transfer;
if (needTransfer) {
const transferId = res?.result?.transfer_prescription_id || res?.data?.transfer_prescription_id || res?.transfer_prescription_id;
if (transferId) {
uni.showModal({
title: '转诊提示',
content: '该处方已触发转诊流程,转诊消息已发送给委托诊所的在线问诊医生。',
showCancel: false,
confirmText: '确定',
success: () => {
// 清空当前数据
this.clearPrescriptionData();
// 清空本地存储
PrescriptionStorage.clearAllPrescriptionData(this.registerId);
setTimeout(() => {
uni.navigateBack();
}, 500);
}
});
return;
}
}
// 清空当前数据
this.clearPrescriptionData();
// 清空本地存储
PrescriptionStorage.clearAllPrescriptionData(this.registerId);
setTimeout(() => {
uni.navigateBack();
}, 1500);
} else {
this.$toast(res.msg || res.message || '发送失败');
}
} catch (error) {
console.error('发送处方失败:', error);
this.$toast('发送处方失败,请重试');
throw error;
} finally {
this.isSubmitting = false;
}
},
/**
* 清空处方数据
* 职责清空当前页面的所有处方数据
*/
clearPrescriptionData() {
this.currentDrugs = [];
this.diagnoses = [];
this.diagnosisText = '';
this.medicalAdvice = '';
this.treatmentPrice = '';
this.chineseConfig = {
ruleType: 1,
packageMethodId: null,
processRuleId: null,
childProcessRuleId: null,
processRuleNoteId: null,
dosage: 7,
dayDosage: 2
};
},
/**
* 保存为常用方
* 职责打开保存常用方弹窗
*/
handleSaveAsCommonPrescription() {
if (this.currentDrugs.length === 0) {
this.$toast('请先添加药品后再保存为常用方');
return;
}
this.showSaveCommonPrescriptionModal = true;
},
/**
* 确认保存常用方
* 职责验证名称调用接口保存提示结果
*/
async handleConfirmSaveCommonPrescription() {
if (!this.commonPrescriptionName || !this.commonPrescriptionName.trim()) {
this.$toast('请输入常用方名称');
return;
}
try {
const storeId = uni.getStorageSync('store_id') || 11001;
if (this.activeCategory === 1) {
// 保存中药常用方
const drugs = this.currentDrugs.map((drug) => ({
drug_id: drug.id || drug.drug_id,
drug_name: drug.drug_name || drug.name,
number: drug.number || 1,
price: drug.price || 0,
way_id: drug.way_id || 0
}));
await saveChineseCommonPrescriptionApi({
name: this.commonPrescriptionName.trim(),
drugs,
store_id: storeId,
clinical_diagnose: this.diagnosisText || '',
doctor_order: this.medicalAdvice || '',
category: '1',
dosage: this.chineseConfig.dosage || 7,
day_dosage: this.chineseConfig.dayDosage || 2
});
} else {
// 保存西药常用方
const drugs = this.currentDrugs.map((drug) => ({
drug_id: drug.id || drug.drug_id,
drug_name: drug.drug_name,
number: drug.number || 1,
select_number: drug.select_number || 1,
price: drug.price || 0,
time_id: drug.time_id || 0,
type_id: drug.type_id || 0,
frequency_id: drug.frequency_id || 0,
unit_id: drug.unit_id || 0,
image: drug.image || '',
instruction: drug.instruction || ''
}));
await saveWestCommonPrescriptionApi({
name: this.commonPrescriptionName.trim(),
drugs,
store_id: storeId,
clinical_diagnose: this.diagnosisText || '',
doctor_order: this.medicalAdvice || '',
category: '1'
});
}
this.$toast('保存成功');
this.showSaveCommonPrescriptionModal = false;
this.commonPrescriptionName = '';
} catch (error) {
console.error('保存常用方失败:', error);
this.$toast('保存常用方失败,请重试');
}
},
/**
* 自定义返回
* 职责处理页面返回逻辑
*/
handleCustomBack() {
uni.navigateBack();
}
}
};
</script>
<style lang="scss" scoped>
.safe-area-inset-bottom {
padding-bottom: env(safe-area-inset-bottom);
}
.tabs {
background: #fff;
}
.top {
border-radius: 8rpx;
}
.top_title {
margin-bottom: 16rpx;
}
.size-32 {
width: 32rpx;
height: 32rpx;
}
.m-t-2 {
margin-top: 16rpx;
}
.p-32 {
padding: 32rpx;
}
.m-t-16 {
margin-top: 16rpx;
}
.m-t-24 {
margin-top: 24rpx;
}
.m-r-2 {
margin-right: 16rpx;
}
2026-05-07 11:04:56 +08:00
.m-l-16 {
margin-left: 16rpx;
}
.m-r-16 {
margin-right: 16rpx;
}
.quantity-control {
display: flex;
align-items: center;
gap: 16rpx;
}
2026-03-06 13:59:22 +08:00
.flex {
display: flex;
}
.flex-wrap {
flex-wrap: wrap;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-col {
display: flex;
flex-direction: column;
}
.flex-jus-sp {
justify-content: space-between;
}
.flex-ali-center {
align-items: center;
}
.flex-jus-center {
justify-content: center;
}
.flex-jus-sa {
justify-content: space-around;
}
.white {
background: #fff;
}
.b-r-8 {
border-radius: 8rpx;
}
.bottom-border {
border-bottom: 1px solid #f0f0f0;
padding: 32rpx 0;
}
.p-col-32 {
padding: 0 32rpx;
}
.btnBox {
display: flex;
justify-content: space-around;
}
.btn {
padding: 16rpx 32rpx;
border-radius: 8rpx;
border: 1px solid #6ACDBB;
color: #6ACDBB;
font-size: 28rpx;
}
.btn.left {
border-color: #6ACDBB;
color: #6ACDBB;
}
.btn.right {
border-color: #FC3636;
color: #FC3636;
}
.bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 32rpx;
background: #fff;
border-top: 1px solid #f0f0f0;
z-index: 99;
2026-05-07 11:04:56 +08:00
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
2026-03-06 13:59:22 +08:00
}
.btnText {
color: #6ACDBB;
font-size: 28rpx;
padding: 0 32rpx;
2026-05-07 11:04:56 +08:00
flex-shrink: 0;
2026-03-06 13:59:22 +08:00
}
.label {
font-size: 28rpx;
color: #6C7380;
margin-bottom: 16rpx;
}
.mBox {
margin-top: 16rpx;
}
.grid-tem-col-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
}
.rp {
padding: 16rpx;
}
.delBox {
padding: 16rpx;
background: #f9f9f9;
border-radius: 8rpx;
}
.ac {
text-align: center;
}
.drug-item-content {
gap: 24rpx;
}
.drug-image {
width: 120rpx;
height: 120rpx;
border-radius: 8rpx;
flex-shrink: 0;
background-color: #f5f5f5;
}
.drug-info-wrapper {
min-width: 0;
flex: 1;
}
</style>