From 026d0e0a485233b057b533500b1cf6d64e09770c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=90=A6?= Date: Fri, 10 Jul 2026 15:10:49 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E7=89=B9=E8=89=B2=E6=96=B9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E8=BF=AD=E4=BB=A3(=E5=9B=BA=E5=AE=9A=E4=BB=B7?= =?UTF-8?q?=E6=A0=BC)=EF=BC=8C=E5=9B=BA=E5=AE=9A=E4=BB=B7=E6=A0=BC?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8=E8=8D=AF?= =?UTF-8?q?=E5=93=81id=EF=BC=88-102=EF=BC=89=EF=BC=8C=E5=90=8E=E6=9C=9F?= =?UTF-8?q?=E4=BC=9A=E8=80=83=E8=99=91=E6=96=B0=E5=A2=9E=E7=89=B9=E8=89=B2?= =?UTF-8?q?=E6=96=B9=E7=9A=84=E6=97=B6=E5=80=99=E8=87=AA=E5=8A=A8=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=B8=80=E4=B8=AA=E7=89=B9=E8=89=B2=E6=96=B9=E8=8D=AF?= =?UTF-8?q?=E5=93=81=202.=20=E9=80=80=E6=AC=BE=E7=9A=84=E6=97=B6=E5=80=99?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E9=80=80=E5=9B=9E=E5=88=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/store/prescription.ts | 124 +++++-- apps/web-antd/src/store/usePrescription.ts | 28 +- apps/web-antd/src/utils/formatPrice.ts | 32 ++ .../chat/components/PrescriptionModal.vue | 188 +--------- .../order/product-order/components/detail.vue | 3 +- .../components/PrescriptionDetail.vue | 3 +- .../views/doctor/doctor-reception/index.vue | 346 ++++++++---------- .../components/AddCommonPrescriptionModal.vue | 36 ++ .../EditCommonPrescriptionModal.vue | 36 ++ 9 files changed, 385 insertions(+), 411 deletions(-) diff --git a/apps/web-antd/src/store/prescription.ts b/apps/web-antd/src/store/prescription.ts index 25f1bf4a..326dec7c 100644 --- a/apps/web-antd/src/store/prescription.ts +++ b/apps/web-antd/src/store/prescription.ts @@ -22,6 +22,11 @@ import { calcTotalMarginPercent, isSeeRateEnabled, } from '#/utils/chinesePrescriptionMargin'; +import { calculateProcessingFee, parsePriceValue } from '#/utils/formatPrice'; +import { + applySingleChildProcessRuleAutoSelect, + resolveProcessRuleLoadedLevel, +} from '#/utils/processRuleCascade'; import { getRegisterStoreInfo as getRegisterStoreInfoPharmacy } from '#/views/doctor/online-consultation/api'; import { getRegisterStoreInfo as getRegisterStoreInfoClinic } from '#/views/doctor/online-consultation-clinic/api'; import traditionalJson from '#/views/business/chat/config/traditional.json'; @@ -121,31 +126,16 @@ export const usePrescriptionStore = defineStore('prescription', () => { ); }); - const processRulePrice = ref(0); - const calcMethod = ref(0); - const processingFee = computed(() => { - if (ruleType.value === 1) return 0; - if (currentDrugs.value.length === 0) return 0; - + if (ruleType.value !== 2 || currentDrugs.value.length === 0) return 0; const processRule = childProcessRuleList.value.find( (item) => item.id === childProcessRuleId.value, ); - if (!processRule) return 0; - - calcMethod.value = processRule.calc_method; - processRulePrice.value = processRule.price; - - if (calcMethod.value === 1) return processRulePrice.value; - if (calcMethod.value === 2) return processRulePrice.value * dosage.value; - if (calcMethod.value === 3) { - const totalNumber = currentDrugs.value.reduce( - (sum, drug) => sum + drug.number, - 0, - ); - return processRulePrice.value * dosage.value * totalNumber; - } - return 0; + const totalQty = currentDrugs.value.reduce( + (sum, drug) => sum + parsePriceValue(drug.number ?? 1), + 0, + ); + return calculateProcessingFee(processRule, dosage.value, totalQty); }); const totalCost = computed(() => { @@ -393,6 +383,38 @@ export const usePrescriptionStore = defineStore('prescription', () => { } else { childProcessRuleList.value = res; } + await applySingleChildProcessRuleAutoSelect( + resolveProcessRuleLoadedLevel(pid, ruleId), + { + ruleType: ruleType.value, + processRuleId: processRuleId.value, + childProcessRuleId: childProcessRuleId.value, + processRuleNoteId: processRuleNoteId.value, + processRuleList: processRuleList.value, + childProcessRuleList: childProcessRuleList.value, + processRuleNoteList: processRuleNoteList.value, + load: getProcessRuleListData, + setProcessRuleId: (id) => { + processRuleId.value = id; + }, + setChildProcessRuleId: (id) => { + childProcessRuleId.value = id; + }, + setProcessRuleNoteId: (id) => { + processRuleNoteId.value = id; + }, + clearBelowProcessRule: () => { + childProcessRuleId.value = undefined; + processRuleNoteId.value = undefined; + childProcessRuleList.value = []; + processRuleNoteList.value = []; + }, + clearBelowChild: () => { + processRuleNoteId.value = undefined; + processRuleNoteList.value = []; + }, + }, + ); console.log('获取加工规则成功'); } catch (error) { console.error('获取加工规则失败:', error); @@ -796,6 +818,62 @@ export const usePrescriptionStore = defineStore('prescription', () => { packageMethodId.value = id; }; + /** + * 中药配置变更(标签选择,对齐移动端级联逻辑) + */ + const handleChineseConfigChange = async (payload: { + ruleType?: number; + packageMethodId?: number | null; + processRuleId?: number | null; + childProcessRuleId?: number | null; + processRuleNoteId?: number | null; + dosage?: number; + dayDosage?: number; + }) => { + const oldRuleType = ruleType.value; + const oldProcessRuleId = processRuleId.value; + const oldChildProcessRuleId = childProcessRuleId.value; + + if (payload.ruleType === 2 && payload.ruleType !== oldRuleType) { + if (processRuleList.value.length === 0) { + await getProcessRuleListData(); + } + } + if (payload.ruleType === 1 && oldRuleType === 2) { + processRuleId.value = undefined; + childProcessRuleId.value = undefined; + processRuleNoteId.value = undefined; + processRuleList.value = []; + childProcessRuleList.value = []; + processRuleNoteList.value = []; + } + if (payload.processRuleId != null && payload.processRuleId !== oldProcessRuleId) { + childProcessRuleId.value = undefined; + processRuleNoteId.value = undefined; + childProcessRuleList.value = []; + processRuleNoteList.value = []; + } + if (payload.childProcessRuleId != null && payload.childProcessRuleId !== oldChildProcessRuleId) { + processRuleNoteId.value = undefined; + processRuleNoteList.value = []; + } + + if (payload.ruleType != null) ruleType.value = payload.ruleType; + if (payload.packageMethodId !== undefined) packageMethodId.value = payload.packageMethodId ?? 2; + if (payload.processRuleId !== undefined) processRuleId.value = payload.processRuleId ?? undefined; + if (payload.childProcessRuleId !== undefined) childProcessRuleId.value = payload.childProcessRuleId ?? undefined; + if (payload.processRuleNoteId !== undefined) processRuleNoteId.value = payload.processRuleNoteId ?? undefined; + if (payload.dosage != null) dosage.value = payload.dosage; + if (payload.dayDosage != null) dayDosage.value = payload.dayDosage; + + if (payload.processRuleId != null && payload.processRuleId !== oldProcessRuleId) { + await getProcessRuleListData(payload.processRuleId); + } + if (payload.childProcessRuleId != null && payload.childProcessRuleId !== oldChildProcessRuleId) { + await getProcessRuleListData(0, payload.childProcessRuleId); + } + }; + // 中药相冲检查 const checkChineseMedicineConflict = async () => { if (activeCategory.value === 2) { @@ -897,7 +975,7 @@ export const usePrescriptionStore = defineStore('prescription', () => { child_process_rule_id: childProcessRuleId.value, process_rule_type: ruleType.value, prescription_type: activeCategory.value, - processing_fee: processRulePrice.value, + processing_fee: processingFee.value, dosage: dosage.value, day_dosage: dayDosage.value, doctor_second_sign: doctorSecondSignValue, @@ -958,7 +1036,6 @@ export const usePrescriptionStore = defineStore('prescription', () => { diagnosis.value = ''; medicalAdvice.value = ''; packageMethodId.value = 2; - processRulePrice.value = 0; dosage.value = 7; dayDosage.value = 2; newDrugInfo.value = {}; @@ -1084,6 +1161,7 @@ export const usePrescriptionStore = defineStore('prescription', () => { selectProcessRuleNot, selectProcessRuleNotCommit, selectPackageMethod, + handleChineseConfigChange, checkChineseMedicineConflict, sendPrescription, resetForm, diff --git a/apps/web-antd/src/store/usePrescription.ts b/apps/web-antd/src/store/usePrescription.ts index 15f6442a..d6000890 100644 --- a/apps/web-antd/src/store/usePrescription.ts +++ b/apps/web-antd/src/store/usePrescription.ts @@ -2,6 +2,7 @@ import { computed, ref, nextTick } from "vue" import { message, notification } from "ant-design-vue" import { debounce } from "lodash-es" +import { calculateProcessingFee, parsePriceValue } from '#/utils/formatPrice' import { addWestPrescription, checkChineseMedicineConflictApi, @@ -75,26 +76,14 @@ export const usePrescriptionStore = () => { return currentDrugs.value.reduce((sum, drug) => sum + drug.price * (drug.select_number || 1), 0) }) - const processRulePrice = ref(0) - const calcMethod = ref(0) - const processingFee = computed(() => { - if (ruleType.value === 1) return 0 - if (currentDrugs.value.length === 0) return 0 - + if (ruleType.value !== 2 || currentDrugs.value.length === 0) return 0 const processRule = childProcessRuleList.value.find((item) => item.id === childProcessRuleId.value) - if (!processRule) return 0 - - calcMethod.value = processRule.calc_method - processRulePrice.value = processRule.price - - if (calcMethod.value === 1) return processRulePrice.value - if (calcMethod.value === 2) return processRulePrice.value * dosage.value - if (calcMethod.value === 3) { - const totalNumber = currentDrugs.value.reduce((sum, drug) => sum + drug.number, 0) - return processRulePrice.value * dosage.value * totalNumber - } - return 0 + const totalQty = currentDrugs.value.reduce( + (sum, drug) => sum + parsePriceValue(drug.number ?? 1), + 0, + ) + return calculateProcessingFee(processRule, dosage.value, totalQty) }) const totalCost = computed(() => { @@ -548,7 +537,7 @@ export const usePrescriptionStore = () => { child_process_rule_id: childProcessRuleId.value, process_rule_type: ruleType.value, prescription_type: activeCategory.value, - processing_fee: processRulePrice.value, + processing_fee: processingFee.value, dosage: dosage.value, day_dosage: dayDosage.value, doctor_second_sign: doctorSecondSignValue, @@ -569,7 +558,6 @@ export const usePrescriptionStore = () => { diagnosis.value = "" medicalAdvice.value = "" packageMethodId.value = 2 - processRulePrice.value = 0 dosage.value = 7 dayDosage.value = 2 newDrugInfo.value = {} diff --git a/apps/web-antd/src/utils/formatPrice.ts b/apps/web-antd/src/utils/formatPrice.ts index 9bd55c04..dcf0497d 100644 --- a/apps/web-antd/src/utils/formatPrice.ts +++ b/apps/web-antd/src/utils/formatPrice.ts @@ -67,3 +67,35 @@ export function calculateChineseProductPriceLikeBackend( export function formatPriceDisplay(value: unknown): string { return formatPriceLikeBackend(value).toFixed(2); } + +type ProcessRuleLine = { + calc_method?: number; + price?: unknown; +}; + +/** + * 计算委托调剂加工费(与移动端 PrescriptionCalculator.calculateProcessingFee 一致) + * calc_method: 1=固定价格,2=按剂数,3=按数量 + */ +export function calculateProcessingFee( + processRule: ProcessRuleLine | null | undefined, + dosage = 7, + totalDrugQuantity = 0, +): number { + if (!processRule?.calc_method) { + return 0; + } + const price = parsePriceValue(processRule.price); + const dose = parsePriceValue(dosage); + const qty = parsePriceValue(totalDrugQuantity); + switch (processRule.calc_method) { + case 1: + return price; + case 2: + return price * dose; + case 3: + return price * dose * qty; + default: + return 0; + } +} diff --git a/apps/web-antd/src/views/business/chat/components/PrescriptionModal.vue b/apps/web-antd/src/views/business/chat/components/PrescriptionModal.vue index c940f0c8..4bc29baa 100644 --- a/apps/web-antd/src/views/business/chat/components/PrescriptionModal.vue +++ b/apps/web-antd/src/views/business/chat/components/PrescriptionModal.vue @@ -53,7 +53,8 @@ import CommonPrescriptionModal from '#/views/doctor/doctor-reception/components/ // 信息提示模态框 import InfoModal from '#/components/modal/InfoModal.vue'; // 药品搜索选择组件 -import { DrugSearchSelect } from '#/components/drug-search-select'; +import { formatPriceDisplay } from '#/utils/formatPrice'; +import ChineseMedicineConfig from '#/views/doctor/doctor-reception/components/ChineseMedicineConfig.vue'; const splitString = (input: string) => input.split(','); @@ -82,11 +83,6 @@ const categories = [ { label: '医疗器械', value: 7 }, ]; -const packageMethod = [ - { label: '味包', value: 1 }, - { label: '剂包', value: 2 }, -]; - // 使用 Pinia store const prescriptionStore = usePrescriptionStore(); @@ -1361,165 +1357,21 @@ const cancelSaveCommonPrescription = () => { /> - -
- - 自制剂 - 委托调剂 - - -
- -
- -
- - - - - -
- -
-
- 用量: -
- - - -
- 天 / {{ prescriptionStore.dosage }} 剂 -
- -
- 频次: -
- - - -
- 次/天 -
-
-
+
@@ -1539,10 +1391,10 @@ const cancelSaveCommonPrescription = () => {
- 加工费:¥{{ prescriptionStore.processingFee.toFixed(2) }} + 加工费:¥{{ formatPriceDisplay(prescriptionStore.processingFee) }}
- 商品价格:¥{{ prescriptionStore.totalProductCost.toFixed(2) }} + 商品价格:¥{{ formatPriceDisplay(prescriptionStore.totalProductCost) }} {
- 总计:¥{{ prescriptionStore.totalCost.toFixed(2) }} + 总计:¥{{ formatPriceDisplay(prescriptionStore.totalCost) }}
diff --git a/apps/web-antd/src/views/business/order/product-order/components/detail.vue b/apps/web-antd/src/views/business/order/product-order/components/detail.vue index 888a65cd..3b45118c 100644 --- a/apps/web-antd/src/views/business/order/product-order/components/detail.vue +++ b/apps/web-antd/src/views/business/order/product-order/components/detail.vue @@ -14,6 +14,7 @@ import { formatPriceDiscountLabel, normalizeQuickOptions } from '#/utils/pricePe import { expressDetailByOrderId, getOrderInfo } from '../api'; import SensitiveText from '#/components/sensitive-text/SensitiveText.vue'; +import { formatDoctorOrderText } from '#/utils/prescriptionDoctorOrder'; defineOptions({ name: 'DetailModal', @@ -414,7 +415,7 @@ function prescriptionStatusColor() { {{ data.prescription.content.clinical_diagnose }} - {{ data.prescription.content.doctor_order }} + {{ formatDoctorOrderText(data.prescription) }} {{ data.prescription.content.doctor.name }} diff --git a/apps/web-antd/src/views/doctor/doctor-reception/components/PrescriptionDetail.vue b/apps/web-antd/src/views/doctor/doctor-reception/components/PrescriptionDetail.vue index 96390e54..9517912a 100644 --- a/apps/web-antd/src/views/doctor/doctor-reception/components/PrescriptionDetail.vue +++ b/apps/web-antd/src/views/doctor/doctor-reception/components/PrescriptionDetail.vue @@ -6,6 +6,7 @@ import { Page, useVbenModal } from '@vben/common-ui'; import { Button } from 'ant-design-vue'; import { getPrescriptionInfoApi } from '#/views/doctor/doctor-reception/api'; +import { formatDoctorOrderText } from '#/utils/prescriptionDoctorOrder'; const item = ref>({}); @@ -228,7 +229,7 @@ function parseRecipeContent(content: string | Record) {