修复了处方打印不能打印的错误

This commit is contained in:
叶锦涛
2025-11-03 13:48:20 +08:00
parent f03d2e1633
commit 3888859b2b
2 changed files with 336 additions and 54 deletions

View File

@@ -360,7 +360,7 @@
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"renderFormatter": "function(value,row,colIndex,options,rowIndex){ return value + '<br/>' + '用法用量'; }",
"renderFormatter": "function(value,row,colIndex,options,rowIndex){ return value + '<br/>' + (row.totalVolume || '') + '<br/>' + '用法用量'; }",
"styler2": "function(value,row,index,options){ return {padding: '5px 5px' }; }",
"width": 86.5148548770295,
"field": "itemName",
@@ -462,7 +462,7 @@
"tableQRCodeLevel": 0,
"tableSummaryTitle": true,
"tableSummary": "",
"renderFormatter": "function(value,row,colIndex,options,rowIndex){ return value + '<br/>' + '用法用量'; }",
"renderFormatter": "function(value,row,colIndex,options,rowIndex){ return value + '<br/>' + (row.totalVolume || '') + '<br/>' + (row.methodCode_dictText || '用法用量'); }",
"styler2": "function(value,row,index,options){ return {padding: '5px 5px' }; }",
"width": 86.5148548770295,
"field": "medicineName",

View File

@@ -196,7 +196,7 @@
批量发药
</el-button>
<el-button type="primary" @click="handleScan()" style="margin-left: 30px"> 扫码 </el-button>
<el-button type="primary" @click="printPrescription()" style="margin-left: 30px">
<el-button type="primary" @click="previewAndPrint()" style="margin-left: 30px">
处方打印
</el-button>
<div style="position: absolute; top: 30px; right: 25px">
@@ -398,7 +398,7 @@ import { advicePrint } from '@/api/public';
import { formatDate, formatDateStr } from '@/utils/index';
import { debounce } from 'lodash-es';
import TraceNoDialog from '@/components/OpenHis/TraceNoDialog/index.vue';
import { hiprint } from 'vue-plugin-hiprint';
// 使用window.hiprint不再从vue-plugin-hiprint导入
import templateJson from './components/templateJson.json';
// import disposalTemplate from './components/disposalTemplate.json';
import {
@@ -655,20 +655,29 @@ function getList() {
const printerList = ref([]); // 打印机列表
const selectedPrinter = ref(''); // 选中的打印机
const showPrinterDialog = ref(false); // 显示打印机选择对话框
const previewData = ref(null); // 预览数据
// 修改printPrescription方法强制显示打印机选择弹窗
async function printPrescription() {
// 抽取获取打印数据的公共函数
async function getPrintData() {
const selectedRows = tableRef.value.getSelectionRows();
if (selectedRows.length === 0) {
proxy.$modal.msgWarning('未选择要打印的项目,请重新选择,打印失败');
return;
proxy.$modal.msgWarning('未选择要打印的项目,请重新选择');
return null;
}
try {
// 获取打印数据
let requestIds = selectedRows.map((item) => item.requestId).join(',');
console.log('打印请求ID:', requestIds);
const res = await advicePrint({ requestIds: requestIds, isPrescription: '1' });
console.log('打印数据获取结果:', res);
if (!res || !res.data || !res.data.adviceItemList) {
proxy.$modal.msgError('获取打印数据失败:数据格式不正确');
return null;
}
advicePrint({ requestIds: requestIds, isPrescription: '1' }).then((res) => {
const groupedRows = {};
res.data.adviceItemList.forEach((row) => {
const prescriptionNo = row.prescriptionNo;
@@ -683,63 +692,336 @@ async function printPrescription() {
const result = [];
groupedArray.forEach((item) => {
if (item && item.length > 0) {
// 从处方列表的第一个条目提取处方信息
const firstItem = item[0];
const total = item.reduce((sum, item) => {
return sum + (item.totalPrice || 0);
}, 0);
// 转换药品列表字段,确保与打印模板匹配
const transformedPrescriptionList = item.map(medItem => ({
...medItem,
// 添加模板需要的字段映射
medicineName: medItem.itemName, // 用于模板中的medicineName字段
totalVolume: medItem.totalVolume || medItem.spec || '', // 后端返回的规格字段是totalVolume
unitPrice: medItem.unitPrice || medItem.price || 0, // 使用后端返回的unitPrice
unitCode_dictText: medItem.unitCode_dictText || medItem.unit || '', // 使用后端返回的unitCode_dictText
// 添加其他可能需要的字段
dose: medItem.dose || '',
doseUnitCode_dictText: medItem.doseUnitCode_dictText || '',
methodCode_dictText: medItem.methodCode_dictText || medItem.usage || '',
rateCode_dictText: medItem.rateCode_dictText || medItem.rateCode || ''
}));
result.push({
...res.data,
// 确保处方号、患者信息等关键数据正确提取,并添加模板需要的字段映射
prescriptionNo: firstItem.prescriptionNo,
patientName: res.data.patientName || firstItem.patientName,
gender: res.data.genderEnum || firstItem.gender,
genderEnum_enumText: res.data.genderEnum_enumText || firstItem.gender || '', // 使用后端返回的性别文本
age: res.data.age || firstItem.age,
adviceDate: res.data.reqTime || firstItem.adviceDate || firstItem.createTime || new Date().toLocaleDateString(),
reqTime: res.data.reqTime || firstItem.adviceDate || firstItem.createTime || new Date().toLocaleDateString(), // 开具日期字段映射
doctorName: res.data.doctorName || firstItem.doctorName,
medTotalAmount: total,
prescriptionList: item,
// 添加模板需要的其他字段
encounterNo: res.data.encounterNo || firstItem.encounterNo || '', // 门诊号
departmentName: res.data.departmentName || firstItem.departmentName || '', // 科室
conditionName: res.data.conditionName || firstItem.conditionName || '', // 临床诊断
phone: res.data.phone || firstItem.phone || '', // 电话
contractName: res.data.contractName || firstItem.contractName || '', // 医疗机构
prescriptionList: transformedPrescriptionList, // 使用转换后的药品列表
});
}
});
console.log('打印数据准备完成:', result);
return result;
} catch (error) {
console.error('获取打印数据失败:', error);
proxy.$modal.msgError('获取打印数据失败: ' + error.message);
return null;
}
}
// 合并预览和打印功能的主函数
async function previewAndPrint() {
try {
const result = await getPrintData();
if (!result) return;
// 保存预览数据
previewData.value = result;
console.log('执行处方预览和打印');
// 构建预览HTML
let previewHtml = '';
// 为每个处方生成预览内容
result.forEach((prescription, index) => {
// 确保处方数据存在
if (!prescription) return;
// 从处方获取药品列表,确保是数组
const prescriptionList = Array.isArray(prescription.prescriptionList) ? prescription.prescriptionList : [];
previewHtml += '<div class="prescription-container">';
previewHtml += '<h3>处方 ' + (index + 1) + '</h3>';
previewHtml += '<div class="prescription-info">';
previewHtml += '<p><strong>处方号:</strong> ' + (prescription.prescriptionNo || 'N/A') + '</p>';
previewHtml += '<p><strong>患者姓名:</strong> ' + (prescription.patientName || 'N/A') + '</p>';
previewHtml += '<p><strong>性别:</strong> ' + (prescription.genderEnum_enumText || prescription.gender || 'N/A') + '</p>';
previewHtml += '<p><strong>年龄:</strong> ' + (prescription.age || 'N/A') + '</p>';
previewHtml += '<p><strong>开具日期:</strong> ' + (prescription.reqTime || prescription.adviceDate || prescription.createTime || new Date().toLocaleDateString()) + '</p>';
previewHtml += '<p><strong>医生:</strong> ' + (prescription.doctorName || 'N/A') + '</p>';
// 添加额外的处方信息
if (prescription.encounterNo) previewHtml += '<p><strong>门诊号:</strong> ' + prescription.encounterNo + '</p>';
if (prescription.departmentName) previewHtml += '<p><strong>科室:</strong> ' + prescription.departmentName + '</p>';
if (prescription.conditionName) previewHtml += '<p><strong>临床诊断:</strong> ' + prescription.conditionName + '</p>';
if (prescription.phone) previewHtml += '<p><strong>电话:</strong> ' + prescription.phone + '</p>';
previewHtml += '</div>';
previewHtml += '<table class="prescription-table">';
previewHtml += '<thead>';
previewHtml += '<tr>';
previewHtml += '<th>药品名称</th>';
previewHtml += '<th>规格</th>';
previewHtml += '<th>单价</th>';
previewHtml += '<th>数量</th>';
previewHtml += '<th>金额</th>';
previewHtml += '<th>费用等级</th>';
previewHtml += '<th>用法用量</th>';
previewHtml += '</tr>';
previewHtml += '</thead>';
previewHtml += '<tbody>';
// 添加药品列表
if (prescriptionList.length > 0) {
prescriptionList.forEach((item) => {
previewHtml += '<tr>';
// 使用映射后的字段名,确保与打印模板一致
previewHtml += '<td>' + (item.medicineName || item.itemName || 'N/A') + '</td>';
previewHtml += '<td>' + (item.totalVolume || item.spec || '') + '</td>';
previewHtml += '<td>' + (item.unitPrice || item.price || '0.00') + '</td>';
previewHtml += '<td>' + (item.quantity || 'N/A') + ' ' + (item.unitCode_dictText || item.unit || '') + '</td>';
previewHtml += '<td>' + (item.totalPrice || '0.00') + '</td>';
previewHtml += '<td>' + (item.contractName || 'N/A') + '</td>';
// 组合用法用量信息
const usageInfo = [];
if (item.dose && item.doseUnitCode_dictText) usageInfo.push(item.dose + item.doseUnitCode_dictText);
if (item.methodCode_dictText || item.usage) usageInfo.push(item.methodCode_dictText || item.usage);
if (item.frequency) usageInfo.push(item.frequency);
previewHtml += '<td>' + usageInfo.join('<br/>') + '</td>';
previewHtml += '</tr>';
});
} else {
previewHtml += '<tr><td colspan="7" style="text-align: center;">暂无药品信息</td></tr>';
}
previewHtml += '</tbody>';
previewHtml += '<tfoot>';
previewHtml += '<tr>';
previewHtml += '<td colspan="6" style="text-align: right; font-weight: bold;">总计:</td>';
previewHtml += '<td style="font-weight: bold;">' + (prescription.medTotalAmount || '0.00') + '</td>';
previewHtml += '</tr>';
previewHtml += '</tfoot>';
previewHtml += '</table>';
previewHtml += '<div class="prescription-footer">';
previewHtml += '<p><strong>医疗机构:</strong> ' + (prescription.contractName || 'N/A') + '</p>';
previewHtml += '</div>';
previewHtml += '</div>';
previewHtml += '<hr class="prescription-separator">';
});
// 将打印数据序列化,以便在预览窗口中访问
const serializedData = encodeURIComponent(JSON.stringify(result));
// 创建预览窗口
const previewWindow = window.open('', '_blank');
if (!previewWindow) {
throw new Error('无法打开预览窗口,请检查浏览器弹窗设置');
}
// 使用更安全的方式生成HTML内容避免Vue编译错误
const createPreviewHtml = (prescriptionData) => {
// 简单的HTML结构避免复杂标签嵌套
let html = '<!DOCTYPE html><html><head><meta charset="utf-8"><title>处方预览</title>';
// 简化的样式
html += '<style>';
html += 'body{font-family:Arial,sans-serif;margin:20px;}';
html += '.content{max-width:800px;margin:0 auto;}';
html += '.header{text-align:center;margin-bottom:20px;}';
html += '.print-btn{background:#1890ff;color:white;border:none;padding:10px 20px;margin-bottom:20px;cursor:pointer;}';
html += 'table{width:100%;border-collapse:collapse;margin-bottom:20px;}';
html += 'th,td{border:1px solid #ddd;padding:8px;}';
html += 'th{background:#f2f2f2;}';
html += '.prescription{margin-bottom:40px;padding-bottom:20px;border-bottom:1px solid #ddd;}';
html += '@media print{.print-btn{display:none;}}';
html += '</style>';
html += '</head><body><div class="content">';
html += '<div class="header"><h2>处方预览</h2></div>';
html += '<button class="print-btn" onclick="window.print()">打印</button>';
// 添加处方内容
html += prescriptionData;
html += '</div></body></html>';
return html;
};
// 使用创建的函数生成HTML并写入
previewWindow.document.write(createPreviewHtml(previewHtml));
previewWindow.document.close();
proxy.$modal.msgSuccess('预览成功,请在新窗口中查看并点击打印按钮');
// 同时处理后台打印逻辑(使用原来的打印功能)
setTimeout(() => {
handleBackgroundPrint(result);
}, 1000);
} catch (error) {
console.error('预览和打印过程出错:', error);
proxy.$modal.msgError('操作失败: ' + error.message);
}
}
// 后台打印逻辑,复用原有的打印功能
function handleBackgroundPrint(result) {
try {
// 获取打印机列表
const printers = getPrinterList();
console.log('获取到的打印机列表:', printers);
if (printers.length === 0) {
proxy.$modal.msgWarning('未检测到可用打印机');
console.log('未检测到可用打印机,仅提供预览功能');
return;
}
// 强制显示打印机选择对话框,无论是否有缓存
// 设置打印机列表
printerList.value = printers;
// 显示对话框
showPrinterDialog.value = true;
// 保存当前打印数据到临时变量
window.currentPrintData = result;
});
// 检查是否有缓存的打印机
const cachedPrinter = getCachedPrinter();
console.log('缓存的打印机:', cachedPrinter);
if (cachedPrinter && printers.some(printer => printer.name === cachedPrinter)) {
// 如果有缓存的打印机,直接使用
selectedPrinter.value = cachedPrinter;
confirmPrinter(result);
} else {
// 否则不自动显示打印机选择对话框,让用户在预览页面手动选择打印
console.log('无缓存打印机,用户可在预览页面手动打印');
}
} catch (error) {
console.error('打印过程出错:', error);
proxy.$modal.msgError('打印失败: ' + error.message);
console.error('后台打印过程出错:', error);
// 不显示错误提示,以免干扰用户在预览页面的操作
}
}
// 使用保存的打印数据执行打印
function confirmPrinter() {
function confirmPrinter(printData) {
console.log('开始打印,传入数据:', printData);
console.log('window临时数据:', window.currentPrintData);
// 如果没有传入数据尝试从window临时变量获取
let data = printData || window.currentPrintData;
if (!selectedPrinter.value) {
proxy.$modal.msgWarning('请选择打印机');
return;
}
if (!data || !Array.isArray(data) || data.length === 0) {
proxy.$modal.msgError('没有找到有效的打印数据');
showPrinterDialog.value = false;
return;
}
if (!templateJson) {
proxy.$modal.msgError('打印模板加载失败');
showPrinterDialog.value = false;
return;
}
// 确保数据字段映射正确,特别是规格字段
data = data.map(prescription => {
const mappedPrescription = { ...prescription };
// 确保药品列表字段映射正确
if (Array.isArray(prescription.prescriptionList)) {
mappedPrescription.prescriptionList = prescription.prescriptionList.map(med => ({
...med,
// 确保规格字段正确映射优先使用totalVolume
totalVolume: med.totalVolume || med.spec || '',
// 确保其他关键字段存在
medicineName: med.medicineName || med.itemName || '',
unitPrice: med.unitPrice || med.price || 0,
unitCode_dictText: med.unitCode_dictText || med.unit || '',
methodCode_dictText: med.methodCode_dictText || med.usage || ''
}));
}
return mappedPrescription;
});
console.log('处理后的打印数据:', data);
console.log('准备执行打印,打印机:', selectedPrinter.value);
// 使用his.js中的savePrinterToCache保存选择
savePrinterToCache(selectedPrinter.value);
// 使用his.js中的executePrint方法执行打印
if (window.currentPrintData) {
executePrint(window.currentPrintData, templateJson, selectedPrinter.value)
.then(() => {
try {
// 检查hiprint是否可用
if (!window.hiprint) {
throw new Error('打印插件未正确加载');
}
// 直接使用hiprint执行打印确保功能正常
const hiprintTemplate = new window.hiprint.PrintTemplate({ template: templateJson });
const printOptions = {
title: '处方打印',
height: 210,
width: 148,
printer: selectedPrinter.value
};
// 打印成功回调
hiprintTemplate.on('printSuccess', function (e) {
console.log('打印成功:', e);
proxy.$modal.msgSuccess('打印成功');
showPrinterDialog.value = false;
// 清除临时数据
window.currentPrintData = null;
})
.catch((error) => {
proxy.$modal.msgError(error.message || '打印失败');
});
// 打印失败回调
hiprintTemplate.on('printError', function (e) {
console.error('打印失败:', e);
proxy.$modal.msgError('打印失败,请检查打印机连接');
showPrinterDialog.value = false;
window.currentPrintData = null;
});
// 执行打印
console.log('调用hiprint.print2方法');
hiprintTemplate.print2(data, printOptions);
} catch (error) {
console.error('打印执行出错:', error);
proxy.$modal.msgError('打印执行失败: ' + error.message);
showPrinterDialog.value = false;
window.currentPrintData = null;
}
}
// 取消打印机选择
function cancelPrinter() {
showPrinterDialog.value = false;
window.currentPrintData = null;
}
/** 重置按钮操作 */
function resetQuery() {
setDefaultDateRange();