bug 445 497 565
This commit is contained in:
@@ -1519,13 +1519,14 @@ function handleMedicalAdvice(row) {
|
||||
}
|
||||
|
||||
// 🔧 每次打开临时医嘱都重新拉取最新数据,确保计费弹窗签发后数据自动更新
|
||||
// 先清空旧数据
|
||||
// 🔧 修复 Bug #446: 先保存旧数据再清空,避免竟态条件
|
||||
const prevAdvices = [...temporaryAdvices.value]
|
||||
temporaryBillingMedicines.value = []
|
||||
temporaryAdvices.value = []
|
||||
// 🔧 修复 Bug #446: 如果是同一 encounter 且已有提交的医嘱(有 requestId),保留签名状态
|
||||
const hasSubmittedAdvices = temporaryAdvices.value.length > 0 &&
|
||||
temporaryAdvices.value[0]?.originalMedicine?.encounterId === row.visitId &&
|
||||
temporaryAdvices.value.some(a => a.originalMedicine?.requestId);
|
||||
const hasSubmittedAdvices = prevAdvices.length > 0 &&
|
||||
prevAdvices[0]?.originalMedicine?.encounterId === row.visitId &&
|
||||
prevAdvices.some(a => a.originalMedicine?.requestId);
|
||||
temporarySigned.value = hasSubmittedAdvices; // 修复:根据已有数据状态设置,而非盲目重置
|
||||
temporaryMedicalLoading.value = true // 🔧 新增:开始加载
|
||||
|
||||
@@ -1585,7 +1586,13 @@ function handleMedicalAdvice(row) {
|
||||
adviceType: item.adviceType || contentData.adviceType || item.advice_type || null,
|
||||
chargeItemId: item.chargeItemId || contentData.chargeItemId || item.charge_item_id || null,
|
||||
definitionId: item.definitionId || contentData.definitionId || item.definition_id || null,
|
||||
definitionDetailId: item.definitionDetailId || contentData.definitionDetailId || item.definition_detail_id || null
|
||||
definitionDetailId: item.definitionDetailId || contentData.definitionDetailId || item.definition_detail_id || null,
|
||||
// 🔧 修复:传递 requestId,临时医嘱签署时需要用于更新已有记录而非新建
|
||||
requestId: item.requestId || null,
|
||||
// 🔧 保留原始 contentJson,临时医嘱签发时需要展开所有字段传给后端
|
||||
contentJson: item.contentJson || item.content_json || null,
|
||||
// 🔧 标记是否已签发,用于临时医嘱弹窗控制按钮状态
|
||||
_signed: item.statusEnum === 2
|
||||
};
|
||||
} catch (e) {
|
||||
// 如果解析失败,使用顶层数据 - 兼容 snake_case 和 camelCase 以及后端不同字段名
|
||||
@@ -1606,7 +1613,13 @@ function handleMedicalAdvice(row) {
|
||||
adviceType: item.adviceType || item.advice_type || null,
|
||||
chargeItemId: item.chargeItemId || item.charge_item_id || null,
|
||||
definitionId: item.definitionId || item.definition_id || null,
|
||||
definitionDetailId: item.definitionDetailId || item.definition_detail_id || null
|
||||
definitionDetailId: item.definitionDetailId || item.definition_detail_id || null,
|
||||
// 🔧 修复:传递 requestId,临时医嘱签署时需要用于更新已有记录而非新建
|
||||
requestId: item.requestId || null,
|
||||
// 🔧 保留原始 contentJson,临时医嘱签发时需要展开所有字段传给后端
|
||||
contentJson: item.contentJson || item.content_json || null,
|
||||
// 🔧 标记是否已签发,用于临时医嘱弹窗控制按钮状态
|
||||
_signed: item.statusEnum === 2
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -1694,73 +1707,134 @@ function closeTemporaryMedical() {
|
||||
// 处理临时医嘱提交
|
||||
// 🔧 修复:提交成功后,更新 temporaryAdvices 中的 requestId,以便下次提交时执行更新操作
|
||||
function handleTemporaryMedicalSubmit(data) {
|
||||
// 🔧 修复:使用用户修改后的数据,而不是重新加载数据
|
||||
// 这样可以确保用户修改的内容(如剂量)在保存后仍然正确显示
|
||||
if (data.temporaryAdvices && data.temporaryAdvices.length > 0) {
|
||||
// 🔧 关键修复:更新 temporaryAdvices 中的数据,保留用户的修改
|
||||
// 但是需要从后端返回的数据中获取 requestId,以便下次提交时执行更新操作
|
||||
// 如果后端返回了医嘱ID(requestId),我们需要更新到 temporaryAdvices 中
|
||||
temporaryAdvices.value = data.temporaryAdvices.map((advice, index) => {
|
||||
const originalMedicine = advice.originalMedicine || {}
|
||||
|
||||
// 🔧 关键修复:从后端返回的数据中获取 requestId(如果有)
|
||||
// 后端返回的医嘱ID可能需要通过某个字段获取,这里暂时假设后端会返回
|
||||
// 如果后端返回的 response 中包含医嘱ID,需要更新到 originalMedicine 中
|
||||
// 这里暂时保留原逻辑,等待用户提供后端返回的具体数据结构
|
||||
|
||||
return {
|
||||
...advice,
|
||||
// 确保 originalMedicine 包含所有必要字段
|
||||
originalMedicine: {
|
||||
...originalMedicine,
|
||||
// 保留用户的修改
|
||||
contentJson: originalMedicine.contentJson || JSON.stringify({
|
||||
dose: advice.dosage,
|
||||
methodCode: advice.usage,
|
||||
rateCode: advice.frequency,
|
||||
quantity: advice.quantity,
|
||||
totalPrice: advice.totalPrice
|
||||
// 🔧 Bug #445 修复:提交成功后重新拉取数据,确保"待生成"列表正确更新
|
||||
if (data.patientInfo && data.patientInfo.visitId) {
|
||||
const row = { visitId: data.patientInfo.visitId, operCode: data.patientInfo.operCode }
|
||||
temporarySigned.value = true
|
||||
ElMessage.success('临时医嘱已生成(已签发)')
|
||||
|
||||
// 重新拉取最新数据,后端已将 statusEnum 从 1(草稿) 更新为 2(已签发)
|
||||
getPrescriptionList(row.visitId, 6, row.operCode).then((res) => {
|
||||
if (res.code === 200 && res.data) {
|
||||
const seenIds = new Set()
|
||||
const filteredItems = res.data.filter(item => {
|
||||
if (item.encounterId !== row.visitId) return false
|
||||
const at = Number(item.adviceType ?? item.advice_type)
|
||||
if (at !== 1 && at !== 2) return false
|
||||
const medicineName = item.adviceName || item.advice_name
|
||||
if (!medicineName || medicineName.trim() === '') return false
|
||||
const excludedKeywords = ['术', '超声', '多普勒', '检查', '检验', '彩超', 'X线', 'CT', 'MRI', '扫描', '造影']
|
||||
if (excludedKeywords.some(kw => medicineName.includes(kw))) return false
|
||||
const itemId = item.requestId || item.id
|
||||
if (itemId && seenIds.has(itemId)) return false
|
||||
if (itemId) seenIds.add(itemId)
|
||||
return true
|
||||
})
|
||||
|
||||
const draftItems = filteredItems.filter(item => item.statusEnum === 1)
|
||||
const activeItems = filteredItems.filter(item => item.statusEnum === 2)
|
||||
|
||||
// 更新待生成列表:只保留未生成的项目
|
||||
temporaryBillingMedicines.value = draftItems.map(item => {
|
||||
try {
|
||||
const jsonContent = item.contentJson || item.content_json
|
||||
const contentData = jsonContent ? JSON.parse(jsonContent) : {}
|
||||
return {
|
||||
medicineName: contentData.adviceName || contentData.advice_name || item.adviceName || item.advice_name || item.chargeName || item.charge_name || contentData.itemName || contentData.item_name || '未知药品',
|
||||
specification: contentData.volume || contentData.specification || item.volume || item.specification || '',
|
||||
quantity: contentData.quantity || item.quantity || 0,
|
||||
batchNumber: contentData.lotNumber || contentData.lot_number || item.lotNumber || item.lot_number || '',
|
||||
unitPrice: contentData.unitPrice || contentData.unit_price || item.unitPrice || item.unit_price || 0,
|
||||
subtotal: contentData.totalPrice || contentData.total_price || item.totalPrice || item.total_price ||
|
||||
(contentData.unitPrice || contentData.unit_price || item.unitPrice || item.unit_price || 0) *
|
||||
(contentData.quantity || item.quantity || 0),
|
||||
insuranceType: (contentData.insuranceType || contentData.insurance_type) === 1 ? '医保' : (item.insuranceType === 1 || item.insurance_type === 1) ? '医保' : '自费',
|
||||
adviceDefinitionId: item.adviceDefinitionId || contentData.adviceDefinitionId || item.advice_definition_id || null,
|
||||
adviceTableName: item.adviceTableName || contentData.adviceTableName || item.advice_table_name || null,
|
||||
adviceType: item.adviceType || contentData.adviceType || item.advice_type || null,
|
||||
chargeItemId: item.chargeItemId || contentData.chargeItemId || item.charge_item_id || null,
|
||||
definitionId: item.definitionId || contentData.definitionId || item.definition_id || null,
|
||||
definitionDetailId: item.definitionDetailId || contentData.definitionDetailId || item.definition_detail_id || null,
|
||||
// 🔧 修复:传递 requestId
|
||||
requestId: item.requestId || null,
|
||||
// 🔧 保留原始 contentJson,临时医嘱签发时需要展开所有字段传给后端
|
||||
contentJson: item.contentJson || item.content_json || null,
|
||||
// 🔧 标记是否已签发,用于临时医嘱弹窗控制按钮状态
|
||||
_signed: item.statusEnum === 2
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
medicineName: item.adviceName || item.advice_name || item.chargeName || '',
|
||||
specification: item.specification || item.volume || '',
|
||||
quantity: item.quantity || item.quantity_value || item.quantityValue || 0,
|
||||
batchNumber: item.lotNumber || item.lot_number || '',
|
||||
unitPrice: item.unitPrice || item.unit_price || 0,
|
||||
subtotal: item.totalPrice || item.total_price || 0,
|
||||
insuranceType: (item.insuranceType || item.insurance_type) === 1 ? '医保' : '自费',
|
||||
adviceDefinitionId: item.adviceDefinitionId || item.advice_definition_id || null,
|
||||
adviceTableName: item.adviceTableName || item.advice_table_name || null,
|
||||
adviceType: item.adviceType || item.advice_type || null,
|
||||
chargeItemId: item.chargeItemId || item.charge_item_id || null,
|
||||
definitionId: item.definitionId || item.definition_id || null,
|
||||
definitionDetailId: item.definitionDetailId || item.definition_detail_id || null,
|
||||
// 🔧 修复:传递 requestId
|
||||
requestId: item.requestId || null,
|
||||
// 🔧 保留原始 contentJson,临时医嘱签发时需要展开所有字段传给后端
|
||||
contentJson: item.contentJson || item.content_json || null,
|
||||
// 🔧 标记是否已签发,用于临时医嘱弹窗控制按钮状态
|
||||
_signed: item.statusEnum === 2
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 更新已生成列表
|
||||
temporaryAdvices.value = activeItems.map((item, index) => {
|
||||
try {
|
||||
const jsonContent = item.contentJson || item.content_json
|
||||
const contentData = jsonContent ? JSON.parse(jsonContent) : {}
|
||||
const medicineName = contentData.adviceName || contentData.advice_name || item.adviceName || item.advice_name || ''
|
||||
const spec = contentData.volume || contentData.specification || item.volume || item.specification || ''
|
||||
const specMatch = spec.match(/(\d+)(\D+)/)
|
||||
const specValue = specMatch ? parseInt(specMatch[1]) : 1
|
||||
const specUnit = specMatch ? specMatch[2] : 'ml'
|
||||
const dosage = specValue * (contentData.quantity || item.quantity || 1)
|
||||
let usageCode = contentData.methodCode || 'iv'
|
||||
return {
|
||||
id: index + 1, adviceName: medicineName, dosage, unit: specUnit,
|
||||
usage: usageCode, frequency: '临时',
|
||||
executeTime: new Date().toLocaleString('zh-CN'),
|
||||
originalMedicine: { ...item, medicineName, specification: spec, quantity: contentData.quantity || item.quantity || 1, encounterId: row.visitId }
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
id: index + 1, adviceName: item.adviceName || '', dosage: 1, unit: 'ml',
|
||||
usage: 'iv', frequency: '临时', executeTime: new Date().toLocaleString('zh-CN'),
|
||||
originalMedicine: { ...item, medicineName: item.adviceName || '', specification: item.volume || '', quantity: item.quantity || 1, encounterId: row.visitId }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
// 拉取失败时使用本地过滤作为兜底
|
||||
if (data.temporaryAdvices && data.temporaryAdvices.length > 0) {
|
||||
const submittedKeys = new Set(
|
||||
data.temporaryAdvices.map(a => {
|
||||
const om = a.originalMedicine || {}
|
||||
return `${om.medicineName || a.adviceName || ''}|||${om.specification || ''}|||${om.quantity || 0}`
|
||||
}).filter(k => k !== '|||0')
|
||||
)
|
||||
if (submittedKeys.size > 0) {
|
||||
temporaryBillingMedicines.value = (temporaryBillingMedicines.value || []).filter(m => {
|
||||
return !submittedKeys.has(`${m.medicineName || ''}|||${m.specification || ''}|||${m.quantity || 0}`)
|
||||
})
|
||||
}
|
||||
temporaryAdvices.value = data.temporaryAdvices
|
||||
}
|
||||
})
|
||||
|
||||
// 🔧 修复 Bug #445: 使用稳定的字段组合匹配已提交项目,而不是依赖可能为空的 requestId/chargeItemId
|
||||
// 构建已提交项目的匹配键集合(药品名称 + 规格 + 数量)
|
||||
const submittedKeys = new Set(
|
||||
(data.temporaryAdvices || [])
|
||||
.map(a => {
|
||||
const om = a.originalMedicine || {}
|
||||
const name = om.medicineName || om.adviceName || om.advice_name || a.adviceName || ''
|
||||
const spec = om.specification || om.volume || ''
|
||||
const qty = om.quantity || 0
|
||||
return `${name}|||${spec}|||${qty}`
|
||||
})
|
||||
.filter(k => k !== '|||0') // 过滤掉空项
|
||||
)
|
||||
|
||||
if (submittedKeys.size > 0) {
|
||||
temporaryBillingMedicines.value = (temporaryBillingMedicines.value || []).filter(m => {
|
||||
const key = `${m.medicineName || ''}|||${m.specification || ''}|||${m.quantity || 0}`
|
||||
return !submittedKeys.has(key)
|
||||
})
|
||||
} else {
|
||||
// 如果没有任何匹配键,清空待生成列表(所有项目都已提交)
|
||||
temporaryBillingMedicines.value = []
|
||||
}
|
||||
|
||||
} else {
|
||||
// 如果没有传递数据,则清空
|
||||
temporaryAdvices.value = []
|
||||
temporaryBillingMedicines.value = []
|
||||
}
|
||||
|
||||
// 🔧 设置签名状态,保持按钮名称一致
|
||||
temporarySigned.value = true
|
||||
|
||||
// 显示成功提示,不关闭弹窗,让用户可以查看已签发的医嘱状态
|
||||
ElMessage.success('临时医嘱已生成(已签发),可继续查看或修改')
|
||||
|
||||
}
|
||||
function handleTemporaryMedicalCancel() {
|
||||
// 🔧 修复:用户点击取消时才清空数据,因为用户可能要放弃修改
|
||||
@@ -1911,7 +1985,13 @@ function handleQuoteBilling() {
|
||||
orgId: contentData.orgId || item.orgId || contentData.positionId || item.positionId || userStore.orgId,
|
||||
positionId: contentData.positionId || item.positionId || userStore.orgId,
|
||||
definitionId: contentData.definitionId || item.definitionId,
|
||||
definitionDetailId: contentData.definitionDetailId || item.definitionDetailId
|
||||
definitionDetailId: contentData.definitionDetailId || item.definitionDetailId,
|
||||
// 🔧 修复:传递 requestId
|
||||
requestId: item.requestId || null,
|
||||
// 🔧 保留原始 contentJson,临时医嘱签发时需要展开所有字段传给后端
|
||||
contentJson: item.contentJson || item.content_json || null,
|
||||
// 🔧 标记是否已签发,用于临时医嘱弹窗控制按钮状态
|
||||
_signed: item.statusEnum === 2
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
@@ -1927,7 +2007,13 @@ function handleQuoteBilling() {
|
||||
orgId: item.orgId || item.positionId || userStore.orgId,
|
||||
positionId: item.positionId || userStore.orgId,
|
||||
definitionId: item.definitionId,
|
||||
definitionDetailId: item.definitionDetailId
|
||||
definitionDetailId: item.definitionDetailId,
|
||||
// 🔧 修复:传递 requestId
|
||||
requestId: item.requestId || null,
|
||||
// 🔧 保留原始 contentJson,临时医嘱签发时需要展开所有字段传给后端
|
||||
contentJson: item.contentJson || item.content_json || null,
|
||||
// 🔧 标记是否已签发,用于临时医嘱弹窗控制按钮状态
|
||||
_signed: item.statusEnum === 2
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user