bug 445 497 565

This commit is contained in:
Ranyunqiao
2026-05-25 15:49:49 +08:00
parent 232577caaa
commit 5132de3680
13 changed files with 316 additions and 177 deletions

View File

@@ -317,10 +317,11 @@ const getMethodCodeDict = computed(() => {
return dict
})
// 🔧 修复 Bug #446: 检查计费药品是否已全部提交(有 requestId用于区分"首次签名"和"已提交重开"
// 🔧 检查是否已全部签发statusEnum=2用于控制"一键签名"按钮是否禁用
// 注意:不能依赖 requestId因为草稿记录也有 requestId
const allItemsSubmitted = computed(() => {
const meds = props.billingMedicines || []
return meds.length > 0 && meds.every(m => m.requestId)
return meds.length > 0 && meds.every(m => m._signed)
})
// 展开/收起控制
@@ -425,32 +426,20 @@ const displayAdvices = ref([])
// 初始化 displayAdvices
const initDisplayAdvices = () => {
// 只要有用户修改过的数据,就优先使用用户修改后的数据
// 避免自动转换覆盖用户的修改
// 区域二只显示已生成(已签发)的数据,没有时保持为空,不自动转换区域一的草稿
if (props.temporaryAdvices && props.temporaryAdvices.length > 0) {
// 🔧 修复:将旧编码映射到新编码
displayAdvices.value = props.temporaryAdvices.map(mapUsageCode)
} else {
// 否则自动转换第一区域的已引用计费药品
displayAdvices.value = convertedAdvices.value
displayAdvices.value = []
}
}
// 初始化
initDisplayAdvices()
// 组件挂载时,如果没有传入临时医嘱数据,将自动转换后的数据同步到父组件
// 确保修改可以被父组件保存,下次打开仍然能看到
onMounted(() => {
// 初始化 displayAdvices
initDisplayAdvices()
if ((!props.temporaryAdvices || props.temporaryAdvices.length === 0) && convertedAdvices.value.length > 0) {
console.log('=== onMounted 触发 emit ===')
emit('update:temporary-advices', convertedAdvices.value)
}
// 🔧 修复:不再自动把区域一草稿转为区域二数据
})
// 🔧 新增:监听 temporary-advices prop 的变化,同步更新 displayAdvices
@@ -465,23 +454,9 @@ watch(() => props.temporaryAdvices, (newVal, oldVal) => {
}
}, { deep: true, immediate: true })
// 监听第一区域的计费药品变化,如果第一区域更新了,并且用户还没修改过第二区域数据,自动更新第二区域
// 🔧 修复:不再自动把区域一草稿转为区域二数据,区域二只显示已签发的记录
watch(() => props.billingMedicines, (newVal) => {
console.log('=== watch billingMedicines 被调用 ===')
console.log('=== newVal ===', newVal)
console.log('=== props.temporaryAdvices ===', props.temporaryAdvices)
console.log('=== props.temporaryAdvices.length ===', props.temporaryAdvices?.length)
// 🔧 修复:只有当 temporary-advices 为空时才自动更新,避免覆盖用户的修改
if (!props.temporaryAdvices || props.temporaryAdvices.length === 0) {
if (newVal.length > 0) {
console.log('=== watch 触发 emit ===')
displayAdvices.value = convertedAdvices.value
emit('update:temporary-advices', convertedAdvices.value)
}
} else {
console.log('=== watch 不触发 emit因为 props.temporaryAdvices 已有数据 ===')
}
// 空 watcher仅保留结构避免破坏其他逻辑
}, { deep: true })
// 🔧 新增:监听字典加载,确保字典加载后编辑弹窗能正确显示
@@ -697,7 +672,9 @@ const handleSubmit = async () => {
}
// 检查是否有医嘱数据
if (displayAdvices.value.length === 0) {
// 🔧 修复签发应该处理区域一中所有待签发的药品billingMedicines而非区域二中已有数据displayAdvices
const itemsToSign = convertedAdvices.value
if (itemsToSign.length === 0) {
ElMessage.warning('没有可保存的医嘱数据')
return
}
@@ -709,7 +686,7 @@ const handleSubmit = async () => {
// 构建保存医嘱的请求参数
const saveData = {
organizationId: props.patientInfo.orgId || props.patientInfo.organizationId || 1, // 使用计费时的orgId
adviceSaveList: displayAdvices.value.map((advice, index) => {
adviceSaveList: itemsToSign.map((advice, index) => {
// 获取原始药品数据
const originalMedicine = advice.originalMedicine
@@ -764,53 +741,44 @@ const handleSubmit = async () => {
// 重新序列化contentJson
const updatedContentJson = JSON.stringify(contentJsonData);
// 构造请求参数(与门诊医生工作站完全一致
// 🔧 构造请求参数:与计费弹窗 handleSave 保持完全一致的模式
// 先展开原始 contentJson 的所有字段,然后用当前值覆盖(保证不丢字段)
return {
...contentJsonData,
// 基础信息
// 🔧 修复dbOpType 的判断逻辑 - 如果有 requestId 则为修改,否则为新增
// 但对于从计费药品转换来的数据,即使没有 requestId也应该先更新 chargeItemId
dbOpType: originalMedicine?.requestId ? '2' : (originalMedicine?.chargeItemId ? '2' : '1'),
adviceType: originalMedicine?.adviceType || 1, // 使用原始类型或默认1
adviceType: originalMedicine?.adviceType || 1,
requestId: originalMedicine?.requestId,
chargeItemId: originalMedicine?.chargeItemId,
contentJson: updatedContentJson,
categoryCode: contentJsonData.categoryCode || originalMedicine?.categoryCode,
pharmacologyCategoryCode: contentJsonData.pharmacologyCategoryCode || originalMedicine?.pharmacologyCategoryCode,
partPercent: originalMedicine?.partPercent || contentJsonData.partPercent || 1,
partAttributeEnum: originalMedicine?.partAttributeEnum || contentJsonData.partAttributeEnum,
executeNum: contentJsonData.executeNum || originalMedicine?.executeNum || 1,
prescriptionNo: originalMedicine?.prescriptionNo,
// 数量和单位:使用重新计算后的数量
quantity: quantity,
dispensePerDuration: originalMedicine?.dispensePerDuration || contentJsonData.dispensePerDuration,
unitCode: contentJsonData.unitCode || originalMedicine?.unitCode || advice.unit,
unitPrice: unitPrice,
// 总价根据新的数量重新计算
totalPrice: totalPrice,
definitionId: originalMedicine?.definitionId ? String(originalMedicine.definitionId) : contentJsonData.definitionId ? String(contentJsonData.definitionId) : advice.definitionId ? String(advice.definitionId) : null,
definitionDetailId: originalMedicine?.definitionDetailId ? String(originalMedicine.definitionDetailId) : contentJsonData.definitionDetailId ? String(contentJsonData.definitionDetailId) : advice.definitionDetailId ? String(advice.definitionDetailId) : null,
lotNumber: originalMedicine?.lotNumber || contentJsonData.lotNumber,
// 状态和类型
statusEnum: originalMedicine?.statusEnum || 2, // 默认状态:已发送
categoryEnum: originalMedicine?.categoryEnum || contentJsonData.categoryEnum || 1,
// 药品/诊疗信息 - 🔧 修复优先使用originalMedicine中的adviceDefinitionId和adviceTableName
// 🔧 关键修复确保adviceDefinitionId不为null使用definitionId作为后备
adviceDefinitionId: originalMedicine?.adviceDefinitionId || contentJsonData.adviceDefinitionId || advice.definitionId || contentJsonData.definitionId || definitionId,
// 药品/诊疗信息
adviceDefinitionId: originalMedicine?.adviceDefinitionId || contentJsonData.adviceDefinitionId || advice.definitionId || contentJsonData.definitionId,
adviceTableName: originalMedicine?.adviceTableName || contentJsonData.adviceTableName || 'med_medication_definition',
adviceName: advice.adviceName,
minUnitQuantity: originalMedicine?.minUnitQuantity || contentJsonData.minUnitQuantity,
// 患者和就诊信息
patientId: props.patientInfo.patientId,
practitionerId: currentUser.value.id || originalMedicine?.practitionerId, // 开方医生
practitionerId: currentUser.value.id || originalMedicine?.practitionerId,
locationId: originalMedicine?.positionId || contentJsonData.locationId || props.patientInfo.orgId || props.patientInfo.positionId,
positionId: originalMedicine?.positionId || contentJsonData.positionId,
orgId: originalMedicine?.orgId || props.patientInfo.orgId || props.patientInfo.positionId,
performLocation: originalMedicine?.performLocation || contentJsonData.performLocation,
founderOrgId: currentUser.value.id || originalMedicine?.founderOrgId, // 开方人科室
founderOrgId: currentUser.value.id || originalMedicine?.founderOrgId,
encounterId: props.patientInfo.visitId || contentJsonData.encounterId || originalMedicine?.encounterId,
accountId: contentJsonData.accountId || originalMedicine?.accountId,
conditionId: contentJsonData.conditionId || originalMedicine?.conditionId,
@@ -818,12 +786,10 @@ const handleSubmit = async () => {
conditionDefinitionId: originalMedicine?.conditionDefinitionId || contentJsonData.conditionDefinitionId,
// 治疗信息
therapyEnum: originalMedicine?.therapyEnum || contentJsonData.therapyEnum || 1, // 默认临时医嘱
// 🔧 修复:methodCode 使用编码,而不是中文名称
methodCode: methodCode, // 用法(使用编码)
rateCode: advice.frequency, // 频次
therapyEnum: originalMedicine?.therapyEnum || contentJsonData.therapyEnum || 1,
methodCode: methodCode,
rateCode: advice.frequency,
dose: advice.dosage,
firstDose: originalMedicine?.firstDose || contentJsonData.firstDose,
doseUnitCode: contentJsonData.doseUnitCode || originalMedicine?.doseUnitCode || advice.unit,
skinTestFlag: originalMedicine?.skinTestFlag || contentJsonData.skinTestFlag,
injectFlag: originalMedicine?.injectFlag || contentJsonData.injectFlag,
@@ -832,55 +798,30 @@ const handleSubmit = async () => {
groupId: originalMedicine?.groupId,
packageId: originalMedicine?.packageId || contentJsonData.packageId,
// 诊疗活动信息
activityId: contentJsonData.adviceDefinitionId || originalMedicine?.adviceDefinitionId, // 对于诊疗类型,使用 adviceDefinitionId 作为 activity_id
// 医保信息
ybClassEnum: originalMedicine?.ybClassEnum || contentJsonData.ybClassEnum,
// 中药信息
chineseHerbsDoseQuantity: originalMedicine?.chineseHerbsDoseQuantity || contentJsonData.chineseHerbsDoseQuantity || 1
// 🔧 补充:手术计费上下文
generateSourceEnum: 6,
sourceBillNo: props.patientInfo?.operCode || originalMedicine?.sourceBillNo || ''
}
})
}
// 调用保存医嘱接口
// 如果已签名,则执行签发操作('1'),否则执行保存操作('0'
const adviceOpType = isSigned.value ? '1' : '0'
const response = await savePrescription(saveData, adviceOpType)
// 🔧 修复:使用 savePrescription + adviceOpType='2'(后端 AdviceOpType: '2'=SIGN_ADVICE 签发)
const response = await savePrescription(saveData, '2')
if (response.code === 200) {
ElMessage.success('临时医嘱保存成功')
// 🔧 关键修复:处理后端返回的医嘱 ID
// 后端返回的 data 数组只包含新创建的医嘱记录的 ID不包含已更新的记录
// 我们需要正确地映射这些 ID 到对应的临时医嘱数据
if (response.data && Array.isArray(response.data) && response.data.length > 0) {
// 创建一个索引,记录哪些记录是新创建的
let newDataIndex = 0
displayAdvices.value.forEach((advice, index) => {
const originalMedicine = advice.originalMedicine || {}
// 如果这个记录没有 requestId说明是新创建的
if (!originalMedicine.requestId) {
if (newDataIndex < response.data.length) {
// 更新 originalMedicine 中的 requestId
if (!displayAdvices.value[index].originalMedicine) {
displayAdvices.value[index].originalMedicine = {}
}
displayAdvices.value[index].originalMedicine.requestId = response.data[newDataIndex]
newDataIndex++
}
}
})
}
// 🔧 签名成功,后端已更新已有记录的 statusEnum 为 2
// 不需要手动更新 requestId签名操作是 UPDATE不是 INSERT后端返回新 ID
// 🔧 修复:将保存后的医嘱数据(包含用户的修改和后端返回的 requestId传递给父组件
// 这样父组件可以使用用户修改后的数据,而不是重新加载数据
// 🔧 修复:将保存后的医嘱数据传递给父组件
const submitData = {
patientInfo: props.patientInfo,
billingMedicines: props.billingMedicines,
temporaryAdvices: displayAdvices.value, // 使用用户修改后的数据,包含后端返回的 requestId
temporaryAdvices: itemsToSign,
signature: {
doctorName: currentUser.value.name,
signatureTime: signatureTime.value