fix(#643): 门诊手术安排-术中医嘱删除改为状态回退,修复刷新后医嘱重现

- 前端:删除操作改为 UPDATE 状态回退(statusEnum ACTIVE→DRAFT),清除签发人/签发时间
  - 后端:回退时跳过发放/计费/绑耗逻辑,清除 signCode,回退 chargeItem 状态为 DRAFT
  - 后端:回退时保持原始 generateSourceEnum,避免刷新查询不到记录
  - 安全:回退前校验 encounterId 所有权,防止跨就诊 IDOR
This commit is contained in:
wangjian963
2026-06-15 15:27:31 +08:00
parent 17616a32cb
commit 5c73cc6987
3 changed files with 174 additions and 12 deletions

View File

@@ -1632,7 +1632,7 @@
v-else
v-model:temporary-advices="temporaryAdvices"
:patient-info="temporaryPatientInfo"
:billing-medicines="temporaryBillingMedicines"
v-model:billing-medicines="temporaryBillingMedicines"
:is-signed-prop="temporarySigned"
@submit="handleTemporaryMedicalSubmit"
@cancel="handleTemporaryMedicalCancel"

View File

@@ -447,7 +447,7 @@ const props = defineProps({
})
// 定义emit事件
const emit = defineEmits(['submit', 'cancel', 'refresh', 'quote-billing', 'update:temporary-advices'])
const emit = defineEmits(['submit', 'cancel', 'refresh', 'quote-billing', 'update:temporary-advices', 'update:billing-medicines'])
// 用户store
const userStore = useUserStore()
@@ -917,22 +917,114 @@ const handleSignAndSubmit = () => {
}
}
const handleDeleteAdvice = (index) => {
ElMessageBox.confirm('确定要删除这条医嘱吗?', '提示', {
/**
* 回退已签发医嘱到待签发状态
* - 不是物理删除,而是将 statusEnum 从 2(ACTIVE) 回退到 1(DRAFT)
* - 清除签发人(signDoctorName)和签发时间(signDate)
* - 回退后刷新,该医嘱将从"已生成"移到"待生成"列表
*/
const handleDeleteAdvice = async (index) => {
ElMessageBox.confirm('确定要回退这条医嘱吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 构建新的临时医嘱数据
}).then(async () => {
const rollbackAdvice = displayAdvices.value[index]
if (!rollbackAdvice) return
const originalMedicine = rollbackAdvice.originalMedicine
const originalList = [...displayAdvices.value]
const updatedAdvices = [...displayAdvices.value]
updatedAdvices.splice(index, 1)
// 通知父组件更新数据
emit('update:temporary-advices', updatedAdvices)
ElMessage.success('删除成功')
if (originalMedicine && originalMedicine.requestId) {
try {
// 清除 contentJson 中的签发人和签发时间
let contentData = {}
try {
contentData = typeof originalMedicine.contentJson === 'string'
? JSON.parse(originalMedicine.contentJson)
: (originalMedicine.contentJson || {})
} catch (e) { /* ignore */ }
contentData.signDoctorName = ''
contentData.signDate = ''
const updateItem = {
requestId: originalMedicine.requestId,
dbOpType: '2', // UPDATE非 DELETE
adviceType: originalMedicine.adviceType || 1,
encounterId: originalMedicine.encounterId || props.patientInfo.visitId,
patientId: originalMedicine.patientId || props.patientInfo.patientId,
contentJson: JSON.stringify(contentData),
}
// adviceOpType='1'(SAVE) → 后端会设置 statusEnum=DRAFT完成状态回退
const res = await savePrescription(
{ organizationId: props.patientInfo.orgId || props.patientInfo.organizationId || 1, adviceSaveList: [updateItem] },
'1'
)
if (res.code === 200) {
// 回退成功:将药品放回"待生成"列表(保留 requestId只是状态变了
if (originalMedicine) {
const restoredItem = {
medicineName: originalMedicine.medicineName || contentData.adviceName || originalMedicine.adviceName || '',
specification: originalMedicine.specification || contentData.volume || '',
quantity: originalMedicine.quantity || contentData.quantity || 1,
batchNumber: originalMedicine.lotNumber || contentData.lotNumber || '',
unitPrice: originalMedicine.unitPrice || contentData.unitPrice || 0,
subtotal: originalMedicine.totalPrice || contentData.totalPrice || 0,
insuranceType: contentData.insuranceType === 1 || originalMedicine.insuranceType === 1 ? '医保' : '自费',
orgId: originalMedicine.orgId || contentData.orgId || props.patientInfo.orgId,
positionId: originalMedicine.positionId || contentData.positionId || props.patientInfo.orgId,
adviceDefinitionId: originalMedicine.adviceDefinitionId || contentData.adviceDefinitionId || null,
adviceTableName: originalMedicine.adviceTableName || contentData.adviceTableName || null,
adviceType: originalMedicine.adviceType || contentData.adviceType || 1,
definitionId: originalMedicine.definitionId || contentData.definitionId || null,
definitionDetailId: originalMedicine.definitionDetailId || contentData.definitionDetailId || null,
requestId: originalMedicine.requestId, // 保留 requestId记录仍在数据库
chargeItemId: originalMedicine.chargeItemId || null,
contentJson: JSON.stringify(contentData), // 已清除签名字段
_signed: false,
}
emit('update:billing-medicines', [...props.billingMedicines, restoredItem])
}
ElMessage.success('回退成功')
} else {
emit('update:temporary-advices', originalList)
ElMessage.error(res.msg || '回退失败,请重试')
}
} catch (e) {
emit('update:temporary-advices', originalList)
ElMessage.error('回退失败,请重试')
}
} else {
// 未持久化到数据库的医嘱(无 requestId本地移除即可
if (originalMedicine) {
const restoredItem = {
medicineName: originalMedicine.medicineName || originalMedicine.adviceName || '',
specification: originalMedicine.specification || '',
quantity: originalMedicine.quantity || 1,
unitPrice: originalMedicine.unitPrice || 0,
subtotal: originalMedicine.totalPrice || 0,
insuranceType: originalMedicine.insuranceType === 1 ? '医保' : '自费',
orgId: originalMedicine.orgId || props.patientInfo.orgId,
positionId: originalMedicine.positionId || props.patientInfo.orgId,
adviceDefinitionId: originalMedicine.adviceDefinitionId || null,
adviceTableName: originalMedicine.adviceTableName || null,
adviceType: originalMedicine.adviceType || 1,
definitionId: originalMedicine.definitionId || null,
definitionDetailId: originalMedicine.definitionDetailId || null,
requestId: null,
chargeItemId: null,
contentJson: originalMedicine.contentJson || null,
_signed: false,
}
emit('update:billing-medicines', [...props.billingMedicines, restoredItem])
}
ElMessage.success('回退成功')
}
}).catch(() => {
// 用户取消删除
// 用户取消
})
}