fix(prescription): 解决处方列表中药品拆零比计算问题
- 修复药品名称显示格式,添加拆零比信息显示 - 在用药天数输入框添加失焦和输入事件触发总量计算 - 调整单位选择下拉框样式间距 - 添加拆零比提示信息显示功能 - 重构总量计算逻辑,使用字典数据获取频次对应次数 - 修复拆零比计算算法,统一使用partPercent参数 - 添加调试日志便于问题排查 - 优化计算精度,将toFixed从6位改为2位 - 添加CSS样式支持拆零比提示显示
This commit is contained in:
@@ -191,18 +191,12 @@
|
|||||||
<template v-if="scope.row.adviceType == 1">
|
<template v-if="scope.row.adviceType == 1">
|
||||||
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
|
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
|
||||||
<span class="medicine-title">
|
<span class="medicine-title">
|
||||||
{{
|
{{ scope.row.adviceName }} {{ scope.row.volume }}
|
||||||
scope.row.adviceName +
|
<template v-if="scope.row.partPercent !== null && scope.row.partPercent !== undefined && scope.row.partPercent - 1 > 0">
|
||||||
' ' +
|
[1{{ scope.row.unitCode_dictText }}={{ scope.row.partPercent }}{{ scope.row.minUnitCode_dictText }}]
|
||||||
scope.row.volume +
|
</template>
|
||||||
' [' +
|
[{{ (scope.row.unitPrice !== undefined && scope.row.unitPrice !== null && !isNaN(scope.row.unitPrice) &&
|
||||||
(scope.row.unitPrice !== undefined && scope.row.unitPrice !== null && !isNaN(scope.row.unitPrice) &&
|
isFinite(scope.row.unitPrice)) ? Number(scope.row.unitPrice).toFixed(2) : '-' }} 元/{{ scope.row.unitCode_dictText }}]
|
||||||
isFinite(scope.row.unitPrice) ? Number(scope.row.unitPrice).toFixed(2) : '-') +
|
|
||||||
' 元' +
|
|
||||||
'/' +
|
|
||||||
scope.row.unitCode_dictText +
|
|
||||||
']'
|
|
||||||
}}
|
|
||||||
</span>
|
</span>
|
||||||
<el-form-item prop="lotNumber" label="药房:">
|
<el-form-item prop="lotNumber" label="药房:">
|
||||||
<el-select v-model="scope.row.inventoryId" style="width: 330px; margin-right: 20px"
|
<el-select v-model="scope.row.inventoryId" style="width: 330px; margin-right: 20px"
|
||||||
@@ -313,7 +307,9 @@
|
|||||||
@keyup.enter.prevent="
|
@keyup.enter.prevent="
|
||||||
handleEnter('dispensePerDuration', scope.row, scope.$index)
|
handleEnter('dispensePerDuration', scope.row, scope.$index)
|
||||||
"
|
"
|
||||||
@change="calculateTotalAmount(scope.row, scope.$index)">
|
@change="calculateTotalAmount(scope.row, scope.$index)"
|
||||||
|
@blur="calculateTotalAmount(scope.row, scope.$index)"
|
||||||
|
@input="calculateTotalAmount(scope.row, scope.$index)">
|
||||||
<template #suffix>天</template>
|
<template #suffix>天</template>
|
||||||
</el-input-number>
|
</el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -324,8 +320,8 @@
|
|||||||
@keyup.enter.prevent="handleEnter('quantity', scope.row, scope.$index)"
|
@keyup.enter.prevent="handleEnter('quantity', scope.row, scope.$index)"
|
||||||
@input="calculateTotalPrice(scope.row, scope.$index)" />
|
@input="calculateTotalPrice(scope.row, scope.$index)" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item style="margin-left: -10px;">
|
||||||
<el-select v-model="scope.row.unitCode" style="width: 70px; margin-right: 20px" placeholder=" "
|
<el-select v-model="scope.row.unitCode" style="width: 70px; margin-right: 10px" placeholder=" "
|
||||||
@change="calculateTotalAmount(scope.row, scope.$index)">
|
@change="calculateTotalAmount(scope.row, scope.$index)">
|
||||||
<template v-for="item in scope.row.unitCodeList" :key="item.value">
|
<template v-for="item in scope.row.unitCodeList" :key="item.value">
|
||||||
<el-option v-if="checkUnit(item, scope.row)" :value="item.value" :label="item.label" @click="
|
<el-option v-if="checkUnit(item, scope.row)" :value="item.value" :label="item.label" @click="
|
||||||
@@ -346,6 +342,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- 🔧 Bug #273 拆零比提示 -->
|
||||||
|
<span v-if="scope.row.partPercent !== null && scope.row.partPercent !== undefined && scope.row.partPercent - 1 > 0 && scope.row.unitCode !== scope.row.minUnitCode"
|
||||||
|
class="part-percent-hint">
|
||||||
|
{{ scope.row.partPercent }}<template v-if="scope.row.minUnitCode_dictText">{{ scope.row.minUnitCode_dictText }}</template><template v-else>袋</template>/<template v-if="scope.row.unitCode_dictText">{{ scope.row.unitCode_dictText }}</template><template v-else>盒</template>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="
|
<div style="
|
||||||
@@ -3921,15 +3922,99 @@ function convertDoseValues(row, index) {
|
|||||||
|
|
||||||
// 总量计算,仅适用只有两种单位的情况
|
// 总量计算,仅适用只有两种单位的情况
|
||||||
function calculateTotalAmount(row, index) {
|
function calculateTotalAmount(row, index) {
|
||||||
|
nextTick(() => {
|
||||||
|
// 🔧 Bug #273 调试日志
|
||||||
|
console.log('[calculateTotalAmount] 开始计算', {
|
||||||
|
adviceType: row.adviceType,
|
||||||
|
rateCode: row.rateCode,
|
||||||
|
dispensePerDuration: row.dispensePerDuration,
|
||||||
|
doseQuantity: row.doseQuantity,
|
||||||
|
partAttributeEnum: row.partAttributeEnum,
|
||||||
|
unitCode: row.unitCode,
|
||||||
|
minUnitCode: row.minUnitCode
|
||||||
|
});
|
||||||
|
|
||||||
|
// 项目为西药或中成药时
|
||||||
|
if (row.adviceType != 1 && row.adviceType != 2) {
|
||||||
|
console.log('[calculateTotalAmount] 非西药/中成药,跳过计算');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔧 Bug #273 修复:使用字典数据计算频次对应的每日次数
|
||||||
|
function getRateCount(rateCode) {
|
||||||
|
// 先从字典中查找
|
||||||
|
const rateDict = rate_code.value?.find(item => item.value === rateCode);
|
||||||
|
if (rateDict && rateDict.remark) {
|
||||||
|
return Number(rateDict.remark);
|
||||||
|
}
|
||||||
|
// 回退到固定映射
|
||||||
|
const frequencyMap = {
|
||||||
|
ST: 1, QD: 1, BID: 2, TID: 3, QID: 4, QN: 1,
|
||||||
|
QOD: 0.5, QW: 1/7, BIW: 2/7, TIW: 3/7, QOW: 1/14
|
||||||
|
};
|
||||||
|
return frequencyMap[rateCode] || 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 情况1: 根据用药天数和频次计算
|
||||||
|
if (row.rateCode && row.dispensePerDuration) {
|
||||||
|
const rateCount = getRateCount(row.rateCode);
|
||||||
|
const count = rateCount * row.dispensePerDuration;
|
||||||
|
console.log('[calculateTotalAmount] 计算count:', { rateCount, days: row.dispensePerDuration, count });
|
||||||
|
if (!count) return;
|
||||||
|
|
||||||
|
let quantity;
|
||||||
|
if (row.unitCode == row.minUnitCode) {
|
||||||
|
// 🔧 使用最小单位时,计算的是最小单位数量(如袋数)
|
||||||
|
quantity = calculateQuantityBySplitType(row.partAttributeEnum, row.doseQuantity, count, row.partPercent);
|
||||||
|
row.quantity = quantity;
|
||||||
|
row.totalPrice = (quantity * row.minUnitPrice).toFixed(2);
|
||||||
|
console.log('[calculateTotalAmount] 计算结果(最小单位):', { quantity, totalPrice: row.totalPrice, partPercent: row.partPercent });
|
||||||
|
} else {
|
||||||
|
// 🔧 使用包装单位时,计算的是包装单位数量(如盒数)
|
||||||
|
quantity = calculateQuantity(
|
||||||
|
row.partAttributeEnum,
|
||||||
|
row.doseQuantity,
|
||||||
|
count,
|
||||||
|
row.partPercent
|
||||||
|
);
|
||||||
|
row.quantity = quantity;
|
||||||
|
row.totalPrice = (quantity * row.unitPrice).toFixed(2);
|
||||||
|
console.log('[calculateTotalAmount] 计算结果(包装单位):', { quantity, totalPrice: row.totalPrice, partPercent: row.partPercent });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[calculateTotalAmount] 条件不满足,未计算(rateCode或dispensePerDuration为空)');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 总量计算,仅适用只有两种单位的情况
|
||||||
|
function calculateTotalAmount2(row, index) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 项目为西药或中成药时
|
// 项目为西药或中成药时
|
||||||
if (row.adviceType != 1 && row.adviceType != 2) {
|
if (row.adviceType != 1 && row.adviceType != 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🔧 Bug #273 修复:使用字典数据计算频次对应的每日次数
|
||||||
|
function getRateCount(rateCode) {
|
||||||
|
// 先从字典中查找
|
||||||
|
const rateDict = rate_code.value?.find(item => item.value === rateCode);
|
||||||
|
if (rateDict && rateDict.remark) {
|
||||||
|
return Number(rateDict.remark);
|
||||||
|
}
|
||||||
|
// 回退到固定映射
|
||||||
|
const frequencyMap = {
|
||||||
|
ST: 1, QD: 1, BID: 2, TID: 3, QID: 4, QN: 1,
|
||||||
|
QOD: 0.5, QW: 1/7, BIW: 2/7, TIW: 3/7, QOW: 1/14
|
||||||
|
};
|
||||||
|
return frequencyMap[rateCode] || 1;
|
||||||
|
}
|
||||||
|
|
||||||
// 情况1: 根据用药天数和频次计算
|
// 情况1: 根据用药天数和频次计算
|
||||||
if (row.rateCode && row.dispensePerDuration) {
|
if (row.rateCode && row.dispensePerDuration) {
|
||||||
const count = calculateQuantityByDays(row.rateCode, row.dispensePerDuration);
|
const rateCount = getRateCount(row.rateCode);
|
||||||
|
const count = rateCount * row.dispensePerDuration;
|
||||||
if (!count) return;
|
if (!count) return;
|
||||||
|
|
||||||
let quantity;
|
let quantity;
|
||||||
@@ -3949,100 +4034,62 @@ function calculateTotalAmount(row, index) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 情况2: 中成药兼容旧逻辑
|
|
||||||
if (row.adviceType == 2) {
|
|
||||||
if (row.partPercent == 1) {
|
|
||||||
row.totalPrice = (row.quantity * row.unitPrice).toFixed(6);
|
|
||||||
} else {
|
|
||||||
// 拆零比不为1时, 如果当前总量单位是大单位,总价等于数量乘以大单位价格 否则总价等于数量乘以小单位价格
|
|
||||||
if (row.unitCodeList.find((k) => k.value == row.unitCode).type == 'unit') {
|
|
||||||
row.totalPrice = (row.quantity * row.unitPrice).toFixed(6);
|
|
||||||
} else {
|
|
||||||
row.totalPrice = (row.quantity * row.minUnitPrice).toFixed(6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (row.adviceType == 1) {
|
|
||||||
if (row.rateCode && row.dispensePerDuration) {
|
|
||||||
// 根据用药天数和用药频次计算数量,医生按顺序填的情况
|
|
||||||
let count = calculateQuantityByDays(row.rateCode, row.dispensePerDuration);
|
|
||||||
if (count) {
|
|
||||||
let quantity;
|
|
||||||
if (row.unitCode == row.minUnitCode) {
|
|
||||||
quantity = calculateQuantityBySplitType(row.partAttributeEnum, row.doseQuantity, count);
|
|
||||||
prescriptionList.value[index].quantity = quantity;
|
|
||||||
prescriptionList.value[index].totalPrice = (quantity * row.minUnitPrice).toFixed(6);
|
|
||||||
} else {
|
|
||||||
quantity = calculateQuantity(
|
|
||||||
row.partAttributeEnum,
|
|
||||||
row.doseQuantity,
|
|
||||||
count,
|
|
||||||
row.partPercent
|
|
||||||
);
|
|
||||||
prescriptionList.value[index].quantity = quantity;
|
|
||||||
prescriptionList.value[index].totalPrice = (quantity * row.unitPrice).toFixed(6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (row.quantity) {
|
|
||||||
// 如果医生开药先填总量 直接计算总价格
|
|
||||||
if (row.unitCode == row.minUnitCode) {
|
|
||||||
prescriptionList.value[index].totalPrice = (row.quantity * row.minUnitPrice).toFixed(6);
|
|
||||||
} else {
|
|
||||||
prescriptionList.value[index].totalPrice = (row.quantity * row.unitPrice).toFixed(6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 情况3: 医生先填总量
|
|
||||||
if (row.quantity) {
|
|
||||||
if (row.unitCode == row.minUnitCode) {
|
|
||||||
prescriptionList.value[index].totalPrice = (row.quantity * row.minUnitPrice).toFixed(6);
|
|
||||||
} else {
|
|
||||||
prescriptionList.value[index].totalPrice = (row.quantity * row.unitPrice).toFixed(6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据门诊拆分类型计算总药量
|
* 根据门诊拆分类型计算总药量 - 最小单位
|
||||||
*
|
* 🔧 Bug #273 修复:统一使用拆零比计算
|
||||||
* @param type 门诊拆分类型
|
* @param type 门诊拆分类型
|
||||||
* @param dose 单次剂量 最小单位
|
* @param dose 单次剂量 最小单位
|
||||||
* @param count 用药频次和用药天数计算出的总数
|
* @param count 用药频次和用药天数计算出的总数
|
||||||
|
* @param partPercent 拆零比
|
||||||
*/
|
*/
|
||||||
function calculateQuantityBySplitType(type, dose, count) {
|
function calculateQuantityBySplitType(type, dose, count, partPercent) {
|
||||||
|
// 先计算最小单位总量
|
||||||
|
const minUnitTotal = dose * count;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1: // 门诊按最小单位每次量向上取整
|
case 1: // 门诊按最小单位每次量向上取整
|
||||||
return Math.ceil(dose) * count;
|
// 每次用量向上取整,然后计算总量
|
||||||
|
return Math.ceil(Math.ceil(dose) * count / partPercent);
|
||||||
case 2: // 门诊按包装单位不可拆分
|
case 2: // 门诊按包装单位不可拆分
|
||||||
return Math.ceil(dose * count);
|
// 总量向上取整到包装单位
|
||||||
|
return Math.ceil(minUnitTotal / partPercent);
|
||||||
case 3: // 门诊按最小单位总量向上取整
|
case 3: // 门诊按最小单位总量向上取整
|
||||||
return Math.ceil(dose * count);
|
// 总量向上取整,然后转换为包装单位
|
||||||
|
return Math.ceil(minUnitTotal / partPercent);
|
||||||
case 4: // 门诊按包装单位每次量向上取整
|
case 4: // 门诊按包装单位每次量向上取整
|
||||||
return Math.ceil(dose) * count;
|
// 每次用量转换为包装单位后向上取整
|
||||||
|
return Math.ceil(Math.ceil(dose / partPercent) * count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据门诊拆分类型计算总药量
|
* 根据门诊拆分类型计算总药量 - 包装单位
|
||||||
*
|
* 🔧 Bug #273 修复:统一使用拆零比计算
|
||||||
* @param type 门诊拆分类型
|
* @param type 门诊拆分类型
|
||||||
* @param dose 单次剂量 最小单位
|
* @param dose 单次剂量 最小单位
|
||||||
* @param count 用药频次和用药天数计算出的总数
|
* @param count 用药频次和用药天数计算出的总数
|
||||||
|
* @param partPercent 拆零比
|
||||||
*/
|
*/
|
||||||
function calculateQuantity(type, dose, count, partPercent) {
|
function calculateQuantity(type, dose, count, partPercent) {
|
||||||
|
// 先计算最小单位总量
|
||||||
|
const minUnitTotal = dose * count;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1: // 门诊按最小单位每次量向上取整
|
case 1: // 门诊按最小单位每次量向上取整
|
||||||
return Math.ceil(dose / partPercent) * count;
|
// 每次用量向上取整,然后计算总量
|
||||||
|
return Math.ceil(Math.ceil(dose) * count / partPercent);
|
||||||
case 2: // 门诊按包装单位不可拆分
|
case 2: // 门诊按包装单位不可拆分
|
||||||
return Math.ceil(dose * count);
|
// 总量向上取整到包装单位
|
||||||
|
return Math.ceil(minUnitTotal / partPercent);
|
||||||
case 3: // 门诊按最小单位总量向上取整
|
case 3: // 门诊按最小单位总量向上取整
|
||||||
return Math.ceil((dose / partPercent) * count);
|
// 总量向上取整,然后转换为包装单位
|
||||||
|
return Math.ceil(minUnitTotal / partPercent);
|
||||||
case 4: // 门诊按包装单位每次量向上取整
|
case 4: // 门诊按包装单位每次量向上取整
|
||||||
return Math.ceil(dose) * count;
|
// 每次用量转换为包装单位后向上取整
|
||||||
|
return Math.ceil(Math.ceil(dose / partPercent) * count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4426,6 +4473,16 @@ defineExpose({ getListInfo, getDiagnosisInfo });
|
|||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 🔧 Bug #273 拆零比提示样式 */
|
||||||
|
.part-percent-hint {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-left: 8px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
/* V1.3 风格侧边栏 - 组套列表样式 */
|
/* V1.3 风格侧边栏 - 组套列表样式 */
|
||||||
.order-group-container {
|
.order-group-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user