diff --git a/openhis-ui-vue3/src/views/doctorstation/components/adviceBaseList.vue b/openhis-ui-vue3/src/views/doctorstation/components/adviceBaseList.vue index 4458eca7..e8516337 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/adviceBaseList.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/adviceBaseList.vue @@ -143,8 +143,8 @@ watch( () => props.adviceQueryParams, (newValue) => { queryParams.value.searchKey = newValue.searchKey; - if (newValue.adviceType) { - queryParams.value.adviceTypes = [newValue.adviceType].join(','); + if (newValue.adviceTypes) { + queryParams.value.adviceTypes = [newValue.adviceTypes].join(','); } else { queryParams.value.adviceTypes = '1,2,3'; } diff --git a/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue b/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue index fe700206..554a375f 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue @@ -191,12 +191,18 @@ @@ -734,7 +729,7 @@ size="small" /> - + @@ -957,32 +952,6 @@ const { method_code, unit_code, rate_code, distribution_category_code, drord_doc 'drord_doctor_type' ); -// 格式化价格显示 -function formatPrice(price, suffix = ' 元', defaultValue = '-') { - if (price !== undefined && price !== null && !isNaN(price) && isFinite(price)) { - return Number(price).toFixed(2) + suffix; - } - return defaultValue; -} - -// 格式化价格(用于编辑状态,不带单位) -function formatPriceEdit(price) { - if (price !== undefined && price !== null && !isNaN(price) && isFinite(price)) { - return Number(price).toFixed(2); - } - return '0.00'; -} - -// 格式化剂量显示 -function formatDose(dose, unitText) { - return dose ? dose + ' ' + (unitText || '') : ''; -} - -// 格式化数量显示 -function formatQuantity(quantity, unitText) { - return quantity ? quantity + ' ' + (unitText || '') : ''; -} - // 删除硬编码的adviceTypeList,直接使用drord_doctor_type字典 // drord_doctor_type: 1=西药, 2=中成药, 3=诊疗, 4=耗材, 5=会诊, 6=全部 const adviceTypeList = ref([ @@ -1614,11 +1583,6 @@ function getListInfo(addNewRow) { console.log('BugFix#219: 过滤掉已作废的会诊医嘱, requestId=', item.requestId); return false; } - // 🔧 Bug Fix: 过滤掉项目名称为空的无效医嘱 - if (!item.adviceName || item.adviceName.trim() === '') { - console.log('BugFix: 过滤掉空白医嘱, requestId=', item.requestId, 'adviceType=', item.adviceType); - return false; - } return true; }); @@ -2062,7 +2026,6 @@ function handleDelete() { adviceType: item.adviceType, statusEnum: item.statusEnum, requestId: item.requestId, - adviceName: item.adviceName }))); // 🔧 BugFix: 放宽条件,只要有requestId的会诊医嘱都可以尝试删除 @@ -2167,18 +2130,13 @@ function handleDelete() { adviceType: item.adviceType, statusEnum: item.statusEnum, requestId: item.requestId, - adviceName: item.adviceName, uniqueKey: item.uniqueKey }))); console.log('BugFix#219: prescriptionList 中的所有医嘱=', prescriptionList.value.map(item => ({ adviceType: item.adviceType, statusEnum: item.statusEnum, - adviceName: item.adviceName, - uniqueKey: item.uniqueKey, - totalPrice: item.totalPrice, - dose: item.dose, - doseQuantity: item.doseQuantity + uniqueKey: item.uniqueKey }))); for (let i = prescriptionList.value.length - 1; i >= 0; i--) { @@ -2367,10 +2325,14 @@ function handleSave(prescriptionId) { // 签发核心逻辑 function executeSaveLogic() { - // 🔧 Bug Fix: 获取当前选中的费用性质,保持字符串类型避免大整数精度丢失 + // 🔧 Bug Fix: 获取当前选中的费用性质,如果是'ZIFEI'或0则转为null,让后端查询默认账户 let finalAccountId = accountId.value; if (finalAccountId === 'ZIFEI' || finalAccountId === 0) { finalAccountId = null; + } else if (finalAccountId && !isNaN(Number(finalAccountId))) { + finalAccountId = Number(finalAccountId); + } else { + finalAccountId = null; } // 🔧 Bug Fix: 校验患者信息完整性 @@ -2383,7 +2345,11 @@ function handleSave(prescriptionId) { saveList.forEach((item) => { item.patientId = props.patientInfo.patientId; item.encounterId = props.patientInfo.encounterId; - item.accountId = finalAccountId; + // 🔧 使用项目自己的 accountId,而不是全局的 finalAccountId + // 这样自动带出的耗材才能保持与药品相同的账户 + if (!item.accountId) { + item.accountId = finalAccountId; + } item.dbOpType = '1'; }); @@ -2393,7 +2359,7 @@ function handleSave(prescriptionId) { // 先解析contentJson let parsedContent = JSON.parse(item.contentJson || '{}'); // 🔧 Bug Fix: 强制将accountId设为正确的值 - parsedContent.accountId = finalAccountId; + parsedContent.accountId = item.accountId || finalAccountId; // 🔧 使用 item 自己的 accountId // --- 【修改点2:Bug 2 修复 (单位换算)】 --- let finalQuantity = item.quantity; @@ -2443,7 +2409,6 @@ function handleSave(prescriptionId) { } console.log('保存医嘱参数:', { - adviceName: item.adviceName, adviceType: item.adviceType, saveAdviceType: saveAdviceType, adviceTableName: adviceTableNameVal, @@ -2467,15 +2432,28 @@ function handleSave(prescriptionId) { adviceTableName: adviceTableNameVal, locationId: locationIdVal, // 🔧 确保 methodCode 被传递(用于触发耗材绑定逻辑) - methodCode: item.methodCode || parsedContent.methodCode + methodCode: item.methodCode || parsedContent.methodCode, + // 🔧 确保 accountId 被传递(用于预结算) + accountId: item.accountId || parsedContent.accountId, + // 🔧 更新 contentJson 中的 adviceType,确保后端分类正确 + contentJson: JSON.stringify({ + ...parsedContent, + adviceType: saveAdviceType + }) }; }); // 提交签发请求 isSaving.value = true; - console.log('签发处方参数:', { - organizationId: props.patientInfo.orgId, - adviceSaveList: list, + console.log('organizationId:', props.patientInfo.orgId); + console.log('adviceSaveList:', list); + list.forEach((item, idx) => { + console.log(`项目${idx + 1}:`, { + adviceName: item.adviceName, + adviceType: item.adviceType, + accountId: item.accountId, + methodCode: item.methodCode + }); }); savePrescriptionSign({ @@ -2628,7 +2606,8 @@ function handleOrderBindInfo(bindIdInfo, currentMethodCode) { uniqueKey: nextId.value++, patientId: props.patientInfo.patientId, encounterId: props.patientInfo.encounterId, - accountId: accountId.value, + accountId: accountId.value, // 🔧 使用当前全局的 accountId + requestId: undefined, // 🔧 耗材的 requestId 设为 undefined,让后端自动生成 quantity: item.quantity, methodCode: item.methodCode, // 🔧 现在 item.methodCode 有值了 rateCode: item.rateCode, @@ -2639,7 +2618,7 @@ function handleOrderBindInfo(bindIdInfo, currentMethodCode) { unitCode: item.unitCode, unitCode_dictText: item.unitCodeName || '', statusEnum: 1, - dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1', + dbOpType: '1', // 🔧 新耗材总是 INSERT conditionId: conditionId.value, conditionDefinitionId: conditionDefinitionId.value, encounterDiagnosisId: encounterDiagnosisId.value, @@ -2908,10 +2887,11 @@ function handleSaveBatch(prescriptionId) { } // 🔧 Bug Fix: 在保存时才转换 accountId - // 保持为字符串类型,避免 JavaScript 大整数精度丢失问题 let finalAccountId = accountId.value; - if (finalAccountId === 'ZIFEI' || finalAccountId === 0) { + if (finalAccountId === 'ZIFEI') { finalAccountId = null; + } else if (finalAccountId && !isNaN(Number(finalAccountId))) { + finalAccountId = Number(finalAccountId); } // 更新到处方对象 @@ -2993,10 +2973,12 @@ function handleSaveBatch(prescriptionId) { }; const contentJson = JSON.stringify(itemToSave); - // 🔧 Bug Fix: 处理accountId,保持字符串类型避免大整数精度丢失 + // 🔧 Bug Fix: 处理accountId,如果是'ZIFEI'或0则转为null,让后端查询默认账户 let itemAccountId = finalAccountId; if (itemAccountId === 'ZIFEI' || itemAccountId === 0) { itemAccountId = null; + } else if (itemAccountId && !isNaN(Number(itemAccountId))) { + itemAccountId = Number(itemAccountId); } // 🔧 Bug Fix: 确保库存匹配成功的关键字段 @@ -3170,12 +3152,6 @@ function syncGroupFields(row) { } function setValue(row) { - // 🔧 Bug Fix: 强制设置耗材类型,确保 adviceType 为 4 - // 如果 adviceTableName 是 adm_device_definition,强制设为耗材类型 - if (row.adviceTableName === 'adm_device_definition') { - row.adviceType = 4; - } - unitCodeList.value = []; unitCodeList.value.push({ value: row.unitCode, label: row.unitCode_dictText, type: 'unit' }); unitCodeList.value.push({ @@ -3548,7 +3524,6 @@ function handleSingOut() { let selectRows = prescriptionRef.value.getSelectionRows(); console.log('BugFix#219: handleSingOut called, selectRows=', selectRows); console.log('BugFix#219: 选中行详情:', selectRows.map(item => ({ - adviceName: item.adviceName, adviceType: item.adviceType, statusEnum: item.statusEnum, statusEnumType: typeof item.statusEnum, @@ -3566,7 +3541,6 @@ function handleSingOut() { console.log('BugFix#219: consultationRows=', consultationRows.length, 'normalRows=', normalRows.length); console.log('BugFix#219: normalRows详情:', normalRows.map(item => ({ - adviceName: item.adviceName, statusEnum: item.statusEnum, statusEnumType: typeof item.statusEnum, requestId: item.requestId @@ -3579,7 +3553,6 @@ function handleSingOut() { adviceType: item.adviceType, statusEnum: item.statusEnum, requestId: item.requestId, - adviceName: item.adviceName }))); // 🔧 BugFix: 放宽条件,只要有requestId的会诊医嘱都可以处理 @@ -3682,7 +3655,6 @@ function handleSingOut() { adviceType: item.adviceType, statusEnum: item.statusEnum, requestId: item.requestId, - adviceName: item.adviceName }))); // 🔧 BugFix: 将requestId转换为数字类型 @@ -3922,9 +3894,8 @@ function convertValues(row, index) { row.dose = row.doseQuantity / row.partPercent; break; } - // 🔧 Bug #273 修复:单次剂量变化后重新计算总量 - calculateTotalAmount(row, index); }); + // calculateTotalAmount(row, index); } // 单次剂量数量改变时自动计算总量 @@ -3950,106 +3921,25 @@ function convertDoseValues(row, index) { row.doseQuantity = row.dose * row.partPercent; break; } - // 🔧 Bug #273 修复:单次剂量变化后重新计算总量 - calculateTotalAmount(row, index); }); + // 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] 非西药/中成药,跳过计算'); + if (row.adviceType == 2) { + calculateTotalPrice(row, index); 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(() => { - // 项目为西药或中成药时 if (row.adviceType != 1 && row.adviceType != 2) { 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; + const count = calculateQuantityByDays(row.rateCode, row.dispensePerDuration); if (!count) return; let quantity; @@ -4069,62 +3959,100 @@ function calculateTotalAmount2(row, index) { } 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 dose 单次剂量 最小单位 * @param count 用药频次和用药天数计算出的总数 - * @param partPercent 拆零比 */ -function calculateQuantityBySplitType(type, dose, count, partPercent) { - // 先计算最小单位总量 - const minUnitTotal = dose * count; - +function calculateQuantityBySplitType(type, dose, count) { switch (type) { case 1: // 门诊按最小单位每次量向上取整 - // 每次用量向上取整,然后计算总量 - return Math.ceil(Math.ceil(dose) * count / partPercent); + return Math.ceil(dose) * count; case 2: // 门诊按包装单位不可拆分 - // 总量向上取整到包装单位 - return Math.ceil(minUnitTotal / partPercent); + return Math.ceil(dose * count); case 3: // 门诊按最小单位总量向上取整 - // 总量向上取整,然后转换为包装单位 - return Math.ceil(minUnitTotal / partPercent); + return Math.ceil(dose * count); case 4: // 门诊按包装单位每次量向上取整 - // 每次用量转换为包装单位后向上取整 - return Math.ceil(Math.ceil(dose / partPercent) * count); + return Math.ceil(dose) * count; } } /** - * 根据门诊拆分类型计算总药量 - 包装单位 - * 🔧 Bug #273 修复:统一使用拆零比计算 + * 根据门诊拆分类型计算总药量 + * * @param type 门诊拆分类型 * @param dose 单次剂量 最小单位 * @param count 用药频次和用药天数计算出的总数 - * @param partPercent 拆零比 */ function calculateQuantity(type, dose, count, partPercent) { - // 先计算最小单位总量 - const minUnitTotal = dose * count; - switch (type) { case 1: // 门诊按最小单位每次量向上取整 - // 每次用量向上取整,然后计算总量 - return Math.ceil(Math.ceil(dose) * count / partPercent); + return Math.ceil(dose / partPercent) * count; case 2: // 门诊按包装单位不可拆分 - // 总量向上取整到包装单位 - return Math.ceil(minUnitTotal / partPercent); + return Math.ceil(dose * count); case 3: // 门诊按最小单位总量向上取整 - // 总量向上取整,然后转换为包装单位 - return Math.ceil(minUnitTotal / partPercent); + return Math.ceil((dose / partPercent) * count); case 4: // 门诊按包装单位每次量向上取整 - // 每次用量转换为包装单位后向上取整 - return Math.ceil(Math.ceil(dose / partPercent) * count); + return Math.ceil(dose) * count; } } @@ -4508,16 +4436,6 @@ defineExpose({ getListInfo, getDiagnosisInfo }); 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 风格侧边栏 - 组套列表样式 */ .order-group-container { display: flex;