diff --git a/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue b/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue index 5cb1b8c6e..b34976556 100755 --- a/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue +++ b/openhis-ui-vue3/src/views/clinicmanagement/bargain/component/prescriptionlist.vue @@ -375,7 +375,7 @@ > @@ -613,6 +613,26 @@ function getRowDisabled(row) { return row.isEdit; } +function formatUnitText(row) { + if (!row.quantity) return '' + const unitText = row.unitCode_dictText + // unitCode_dictText 为有效文本时直接使用 + if (unitText && !/^\d+$/.test(unitText)) return row.quantity + ' ' + unitText + // 优先从行级 unitCodeList 查找 + const list = row.unitCodeList + if (list && list.length) { + const match = list.find(u => u.value === row.unitCode) + if (match) return row.quantity + ' ' + match.label + } + // 回退:从字典 unit_code 查找 + if (unit_code.value && unit_code.value.length) { + const dictMatch = unit_code.value.find(d => d.value === row.unitCode) + if (dictMatch) return row.quantity + ' ' + dictMatch.label + } + // 最后兜底用 unitCode + return row.quantity + ' ' + (row.unitCode || '') +} + /** * 是否已由医生接诊(非待诊) * EncounterStatus: 1=待诊 2=在诊 3=暂离 … diff --git a/openhis-ui-vue3/src/views/surgicalschedule/index.vue b/openhis-ui-vue3/src/views/surgicalschedule/index.vue index e9c8643b7..ae7952a47 100755 --- a/openhis-ui-vue3/src/views/surgicalschedule/index.vue +++ b/openhis-ui-vue3/src/views/surgicalschedule/index.vue @@ -2339,6 +2339,10 @@ function handleMedicalAdvice(row) { const draftItems = filteredItems.filter(item => item.statusEnum === 1) const activeItems = filteredItems.filter(item => item.statusEnum === 2) + if (activeItems.length > 0) { + temporarySigned.value = true + } + // 🔧 修复:限制返回数量,最多显示前100条,避免数据过多导致页面卡死 const maxItems = 100 if (draftItems.length > maxItems) { @@ -2414,9 +2418,9 @@ function handleMedicalAdvice(row) { 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 specMatch = spec.match(/([\d.]+)\s*([a-zA-Z一-龥]+)/) + const specValue = specMatch ? parseFloat(specMatch[1]) : 1 + const specUnit = specMatch ? specMatch[2] : '' const dosage = specValue * (contentData.quantity || item.quantity || 1) let usageCode = contentData.methodCode || 'iv' @@ -2434,8 +2438,8 @@ function handleMedicalAdvice(row) { unit: specUnit, usage: usageCode, usageLabel, - frequency: '临时', - executeTime: new Date().toLocaleString('zh-CN'), + frequency: '立即', + executeTime: '', originalMedicine: { ...item, medicineName: medicineName, @@ -2449,8 +2453,8 @@ function handleMedicalAdvice(row) { id: index + 1, adviceName: item.adviceName || item.advice_name || '', dosage: 1, unit: 'ml', usage: 'iv', usageLabel: '静脉注射', - frequency: '临时', - executeTime: new Date().toLocaleString('zh-CN'), + frequency: '立即', + executeTime: '', originalMedicine: { ...item, medicineName: item.adviceName || item.advice_name || '', @@ -2584,14 +2588,14 @@ function handleTemporaryMedicalSubmit(data) { let usageCode = contentData.methodCode || 'iv' return { id: index + 1, adviceName: medicineName, dosage, unit: specUnit, - usage: usageCode, frequency: '临时', - executeTime: new Date().toLocaleString('zh-CN'), + usage: usageCode, frequency: '立即', + executeTime: '', 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'), + usage: 'iv', frequency: '立即', executeTime: '', originalMedicine: { ...item, medicineName: item.adviceName || '', specification: item.volume || '', quantity: item.quantity || 1, encounterId: row.visitId } } } @@ -2705,8 +2709,8 @@ function handleQuoteBilling() { else if (usageCode === 'po' && (medicineName.includes('片') || medicineName.includes('胶囊'))) { usageLabel = '口服' } return { id: index + 1, adviceName: medicineName, dosage, unit: specUnit, - usage: usageCode, usageLabel, frequency: '临时', - executeTime: new Date().toLocaleString('zh-CN'), + usage: usageCode, usageLabel, frequency: '立即', + executeTime: '', originalMedicine: { ...item, medicineName: medicineName, @@ -2719,7 +2723,7 @@ function handleQuoteBilling() { return { id: index + 1, adviceName: item.adviceName || item.advice_name || '', dosage: 1, unit: 'ml', usage: 'iv', usageLabel: '静脉注射', - frequency: '临时', executeTime: new Date().toLocaleString('zh-CN'), + frequency: '立即', executeTime: '', originalMedicine: { ...item, medicineName: item.adviceName || item.advice_name || '', diff --git a/openhis-ui-vue3/src/views/surgicalschedule/temporaryMedical.vue b/openhis-ui-vue3/src/views/surgicalschedule/temporaryMedical.vue index a48dd7ad7..d10bd5247 100755 --- a/openhis-ui-vue3/src/views/surgicalschedule/temporaryMedical.vue +++ b/openhis-ui-vue3/src/views/surgicalschedule/temporaryMedical.vue @@ -173,6 +173,8 @@ border style="width: 100%;" fit + highlight-current-row + @row-click="handleAdviceRowClick" > {{ isSigned ? currentUser.name : '未签名' }} + >{{ isSigned ? signatureDoctor : '未签名' }}
签名时间: @@ -398,6 +400,7 @@ import { ElMessage, ElMessageBox } from 'element-plus' import useUserStore from '@/store/modules/user' import { checkPassword } from '@/api/surgicalschedule' import { savePrescription } from '@/views/clinicmanagement/bargain/component/api.js' +import { parseTime } from '@/utils/openhis' // 定义props const props = defineProps({ @@ -507,16 +510,11 @@ const displayAdvicesList = computed(() => { return advicesExpanded.value ? all : all.slice(0, PAGE_SIZE) }) -// 响应式数据 - isSigned 从父组件传入的 prop 初始化 -const isSigned = ref(props.isSignedProp) - -// 🔧 修复 Bug #446: 同步父组件 isSignedProp 的变化到本地 isSigned -// ref(props.isSignedProp) 只在初始化时读取一次,父组件后续更新不会自动同步 -watch(() => props.isSignedProp, (newVal) => { - isSigned.value = newVal -}) +const isSigned = ref(false) +const signatureDoctor = ref(userStore.nickName || userStore.name || '未知用户') const signatureTime = ref('') + const showSignDialog = ref(false) const signPassword = ref('') const showEditDialog = ref(false) @@ -531,7 +529,7 @@ const editForm = ref({ // 计算属性 const currentUser = computed(() => ({ - name: userStore.name || '未知用户', + name: userStore.nickName || userStore.name || '未知用户', id: userStore.id })) @@ -554,10 +552,10 @@ const totalAmount = computed(() => { // 将计费药品转换为临时医嘱数据 const convertedAdvices = computed(() => { return props.billingMedicines.map((medicine, index) => { - // 解析规格中的数值和单位 - const specMatch = medicine.specification ? medicine.specification.match(/(\d+)(\D+)/) : null - const specValue = specMatch ? parseInt(specMatch[1]) : 1 - const specUnit = specMatch ? specMatch[2] : 'ml' + // 解析规格中的数值和单位(支持小数,去除 ×、:、/、* 等多余字符) + const specMatch = medicine.specification ? medicine.specification.match(/([\d.]+)\s*([a-zA-Z一-龥]+)/) : null + const specValue = specMatch ? parseFloat(specMatch[1]) : 1 + const specUnit = specMatch ? specMatch[2] : '' // 计算剂量 = 规格数值 × 数量 const dosage = specValue * (medicine.quantity || 1) @@ -583,8 +581,8 @@ const convertedAdvices = computed(() => { unit: specUnit, usage: usageCode, // 🔧 修复:使用后端字典的正确编码 usageLabel: usageLabel, // 🔧 新增:保存显示名称 - frequency: '临时', - executeTime: new Date().toLocaleString('zh-CN'), + frequency: '立即', + executeTime: '', originalMedicine: medicine } }) @@ -640,6 +638,24 @@ const handleSign = () => { showSignDialog.value = true } +// 点击已生成列表行 → 回显该行的签名信息 +const handleAdviceRowClick = (row) => { + const om = row?.originalMedicine + if (!om) return + const contentJson = om.contentJson || om.content_json + if (!contentJson) return + try { + const cd = typeof contentJson === 'string' ? JSON.parse(contentJson) : contentJson + if (cd.signDoctorName) { + signatureDoctor.value = cd.signDoctorName + } + if (cd.signDate) { + signatureTime.value = cd.signDate + } + isSigned.value = true + } catch (e) {} +} + // 编辑医嘱 const handleEditAdvice = (index) => { const advice = displayAdvices.value[index] @@ -662,7 +678,7 @@ const handleEditAdvice = (index) => { } // 保存编辑 -const handleSaveEdit = () => { +const handleSaveEdit = async () => { if (!editForm.value.dosage && editForm.value.dosage !== 0) { ElMessage.warning('请填写剂量') return @@ -720,8 +736,8 @@ const handleSaveEdit = () => { // 如果用户修改了剂量,重新计算数量 if (originalMedicine.specification) { - const specMatch = originalMedicine.specification.match(/(\d+)(\D+)/) - const specValue = specMatch ? parseInt(specMatch[1]) : 1 + const specMatch = originalMedicine.specification.match(/([\d.]+)\s*([a-zA-Z一-龥]+)/) + const specValue = specMatch ? parseFloat(specMatch[1]) : 1 if (specValue > 0) { const newQuantity = editForm.value.dosage / specValue contentData.quantity = newQuantity @@ -731,12 +747,9 @@ const handleSaveEdit = () => { updatedAdvice.quantity = newQuantity } } - - // 更新 contentJson - updatedAdvice.originalMedicine = { - ...originalMedicine, - contentJson: JSON.stringify(contentData) - } + + // 🔧 修复:原地修改 contentJson,保存使用最新数据 + originalMedicine.contentJson = JSON.stringify(contentData) } catch (e) { console.error('解析 originalMedicine.contentJson 失败', e) } @@ -750,7 +763,49 @@ const handleSaveEdit = () => { emit('update:temporary-advices', updatedAdvices) showEditDialog.value = false - ElMessage.success('编辑成功(已暂存本地,请点击"一键签名并生成医嘱"按钮提交到服务器)') + + // 🔧 修复 Bug #604: 编辑保存后直接提交到服务器 + const editMedicine = updatedAdvice.originalMedicine + if (editMedicine) { + let contentJsonData = {} + try { contentJsonData = JSON.parse(editMedicine.contentJson || '{}') } catch (e) {} + const quantity = editMedicine.quantity || contentJsonData.quantity || 1 + const unitPrice = editMedicine.unitPrice || contentJsonData.unitPrice || 0 + contentJsonData.dose = editForm.value.dosage + contentJsonData.doseUnitCode = editForm.value.unit + contentJsonData.methodCode = updatedAdvice.usage + contentJsonData.quantity = quantity + contentJsonData.totalPrice = unitPrice * quantity + contentJsonData.adviceName = updatedAdvice.adviceName + + const saveItem = { + ...contentJsonData, + dbOpType: editMedicine.requestId ? '2' : '1', + adviceType: editMedicine.adviceType || 1, + requestId: editMedicine.requestId, + chargeItemId: editMedicine.chargeItemId, + contentJson: JSON.stringify(contentJsonData), + quantity, + unitCode: editMedicine.unitCode || editForm.value.unit, + unitPrice, + totalPrice: unitPrice * quantity, + adviceName: updatedAdvice.adviceName, + patientId: props.patientInfo.patientId, + encounterId: props.patientInfo.visitId, + orgId: props.patientInfo.orgId, + methodCode: updatedAdvice.usage, + dose: editForm.value.dosage, + doseUnitCode: editForm.value.unit, + generateSourceEnum: 6, + sourceBillNo: props.patientInfo?.operCode || '' + } + try { + await savePrescription({ organizationId: props.patientInfo.orgId || 1, adviceSaveList: [saveItem] }, '2') + ElMessage.success('医嘱修改已保存到服务器') + } catch (e) { + ElMessage.error('保存失败,请重试') + } + } } // 取消编辑 @@ -762,7 +817,7 @@ const handleCancelEdit = () => { dosage: '', unit: '', usage: '', - frequency: '临时' + frequency: '立即' } } @@ -777,10 +832,10 @@ const confirmSign = async () => { const response = await checkPassword({ password: signPassword.value }) - if (response.code === 200 && response.data) { isSigned.value = true - signatureTime.value = new Date().toLocaleString('zh-CN') + signatureDoctor.value = userStore.nickName || userStore.name + signatureTime.value = parseTime(new Date()) showSignDialog.value = false signPassword.value = '' ElMessage.success('签名成功') @@ -799,10 +854,8 @@ const confirmSign = async () => { const handleSignAndSubmit = () => { if (isSigned.value) { - // 如果已经签名,直接提交 handleSubmit() } else { - // 如果未签名,打开签名弹窗 handleSign() } } @@ -907,6 +960,8 @@ const handleSubmit = async () => { contentJsonData.dose = advice.dosage; contentJsonData.doseUnitCode = advice.unit; contentJsonData.rateCode = advice.frequency; + contentJsonData.signDoctorName = signatureDoctor.value + contentJsonData.signDate = signatureTime.value // 重新序列化contentJson const updatedContentJson = JSON.stringify(contentJsonData); @@ -993,7 +1048,7 @@ const handleSubmit = async () => { billingMedicines: props.billingMedicines, temporaryAdvices: itemsToSign, signature: { - doctorName: currentUser.value.name, + doctorName: signatureDoctor.value, signatureTime: signatureTime.value } }