/** * 打印工具类 * 集中管理所有打印相关功能 */ import {hiprint} from 'vue-plugin-hiprint'; // 打印模板映射表 . const TEMPLATE_MAP = { // CLINIC_CHARGE: () => import('@/views/charge/cliniccharge/components/template.json'), // DISPOSAL: () => import('@/views/clinicmanagement/disposal/components/disposalTemplate.json'), //处方签 PRESCRIPTION: () => import('@/components/Print/Prescription.json'), //处置单 DISPOSAL: () => import('@/components/Print/Disposal.json'), //门诊日结 DAY_END: () => import('@/components/Print/DailyOutpatientSettlement.json'), WESTERN_MEDICINE: () => import('@/views/pharmacymanagement/westernmedicine/components/templateJson.json'), IN_HOSPITAL_DISPENSING: () => import('@/views/drug/inHospitalDispensing/components/templateJson.json'), // 门诊挂号 OUTPATIENT_REGISTRATION: () => import('@/components/Print/OutpatientRegistration.json'), // 门诊手术计费(含流程图) OUTPATIENT_SURGERY_CHARGE: () => import('@/components/Print/OutpatientSurgeryCharge.json'), //门诊收费 OUTPATIENT_CHARGE: () => import('@/components/Print/OutpatientBilling.json'), //门诊病历 OUTPATIENT_MEDICAL_RECORD: () => import('@/components/Print/OutpatientMedicalRecord.json'), //门诊输液贴 OUTPATIENT_INFUSION: () => import('@/components/Print/OutpatientInfusion.json'), //手术记录 OPERATIVE_RECORD: () => import('@/components/Print/OperativeRecord.json'), //红旗门诊病历 HQOUTPATIENT_MEDICAL_RECORD: () => import('@/components/Print/HQOutpatientMedicalRecord.json'), //预交金 ADVANCE_PAYMENT: () => import('@/components/Print/AdvancePayment.json'), //中药处方单 CHINESE_MEDICINE_PRESCRIPTION: () => import('@/components/Print/ChineseMedicinePrescription.json'), //药房处方单 PHARMACY_PRESCRIPTION: () => import('@/components/Print/Pharmacy.json'), //中药医生处方单 DOC_CHINESE_MEDICINE_PRESCRIPTION: () => import('@/components/Print/DocChineseMedicinePrescription.json'), // ========== 新增模板(原LODOP迁移)========== //腕带 WRIST_BAND: () => import('@/components/Print/WristBand.json'), //分诊条 TRIAGE_TICKET: () => import('@/components/Print/TriageTicket.json'), //输液标签 INJECT_LABEL: () => import('@/components/Print/InjectLabel.json'), //床头卡 BED_CARD: () => import('@/components/Print/BedCard.json'), //护理交接班 CHANGE_SHIFT_BILL: () => import('@/components/Print/ChangeShiftBill.json'), //医嘱执行单 EXE_ORDER_SHEET: () => import('@/components/Print/ExeOrderSheet.json'), //体温单 TEMPERATURE_SHEET: () => import('@/components/Print/TemperatureSheet.json'), //会诊申请单 CONSULTATION: () => import('@/components/Print/Consultation.json'), }; /** * 极简打印方法 * @param {string} templateName 打印模板名称(常量或字符串) * @param {Array|Object} data 打印数据 * @param {string} printerName 打印机名称(可选) * @param {Object} options 打印选项(可选) * @returns {Promise} 打印结果Promise */ export async function simplePrint(templateName, data, printerName, options = {}) { try { // 获取模板 const template = await loadTemplate(templateName); // 执行打印,业务名称默认为模板名称 return await executePrint(data, template, printerName, options, templateName); } catch (error) { console.error('打印失败:', error); throw error; } } /** * 加载打印模板 * @param {string} templateName 模板名称 * @returns {Promise} 模板对象 */ async function loadTemplate(templateName) { // 如果是常量形式,获取实际的键名 const templateKey = typeof templateName === 'symbol' ? templateName.description : templateName; if (!TEMPLATE_MAP[templateKey]) { throw new Error(`未找到打印模板: ${templateKey}`); } try { const templateModule = await TEMPLATE_MAP[templateKey](); return templateModule.default || templateModule; } catch (error) { console.error(`加载模板 ${templateKey} 失败:`, error); throw error; } } /** * 带打印机选择的极简打印方法 * @param {string} templateName 打印模板名称 * @param {Array|Object} data 打印数据 * @param {Function} showPrinterDialog 显示打印机选择对话框的函数 * @param {Object} modal 消息提示对象 * @param {Function} callback 打印完成后的回调函数(可选) * @returns {Promise} 打印结果Promise */ export async function simplePrintWithDialog( templateName, data, showPrinterDialog, modal, callback ) { try { // 获取模板 const template = await loadTemplate(templateName); // 执行打印 await selectPrinterAndPrint(data, template, showPrinterDialog, modal, callback, templateName); } catch (error) { modal.msgError(error.message || '打印失败'); if (callback) callback(error); } } // 导出模板名称常量 export const PRINT_TEMPLATE = { // CLINIC_CHARGE: 'CLINIC_CHARGE', DAY_END: 'DAY_END', WESTERN_MEDICINE: 'WESTERN_MEDICINE', IN_HOSPITAL_DISPENSING: 'IN_HOSPITAL_DISPENSING', //门诊挂号 OUTPATIENT_REGISTRATION: 'OUTPATIENT_REGISTRATION', // 门诊手术计费 OUTPATIENT_SURGERY_CHARGE: 'OUTPATIENT_SURGERY_CHARGE', //门诊收费 OUTPATIENT_CHARGE: 'OUTPATIENT_CHARGE', //处方签 PRESCRIPTION: 'PRESCRIPTION', //处置单 DISPOSAL: 'DISPOSAL', //门诊病历 OUTPATIENT_MEDICAL_RECORD: 'OUTPATIENT_MEDICAL_RECORD', //门诊输液贴 OUTPATIENT_INFUSION: 'OUTPATIENT_INFUSION', //手术记录 OPERATIVE_RECORD: 'OPERATIVE_RECORD', //红旗门诊病历 HQOUTPATIENT_MEDICAL_RECORD: 'HQOUTPATIENT_MEDICAL_RECORD', //预交金 ADVANCE_PAYMENT: 'ADVANCE_PAYMENT', //中药处方单 CHINESE_MEDICINE_PRESCRIPTION: 'CHINESE_MEDICINE_PRESCRIPTION', //药房处方单 PHARMACY_PRESCRIPTION: 'PHARMACY_PRESCRIPTION', //中药医生处方单 DOC_CHINESE_MEDICINE_PRESCRIPTION: 'DOC_CHINESE_MEDICINE_PRESCRIPTION', // ========== 新增模板(原LODOP迁移)========== //腕带 WRIST_BAND: 'WRIST_BAND', //分诊条 TRIAGE_TICKET: 'TRIAGE_TICKET', //输液标签 INJECT_LABEL: 'INJECT_LABEL', //床头卡 BED_CARD: 'BED_CARD', //护理交接班 CHANGE_SHIFT_BILL: 'CHANGE_SHIFT_BILL', //医嘱执行单 EXE_ORDER_SHEET: 'EXE_ORDER_SHEET', //体温单 TEMPERATURE_SHEET: 'TEMPERATURE_SHEET', //会诊申请单 CONSULTATION: 'CONSULTATION', }; /** * 获取打印机列表 * @returns {Array} 打印机列表 */ export function getPrinterList() { try { if (hiprint && hiprint.hiwebSocket && hiprint.hiwebSocket.connected) { const printerList = hiprint.hiwebSocket.getPrinterList(); return printerList || []; } else { console.warn('打印服务未连接,返回空打印机列表'); return []; } } catch (error) { console.error('获取打印机列表失败:', error); return []; } } import useUserStore from '@/store/modules/user'; import {ElMessage} from 'element-plus'; /** * 获取当前登录用户ID * @returns {string} 用户ID */ function getCurrentUserId() { try { // 从Pinia store中获取当前用户ID const userStore = useUserStore(); return userStore.id || ''; } catch (e) { console.error('获取用户ID失败:', e); return ''; } } /** * 生成打印机缓存键 * @param {string} businessName 打印业务名称 * @returns {string} 缓存键 */ function getPrinterCacheKey(businessName) { const userId = getCurrentUserId(); return `selectedPrinter_${businessName || 'default'}_${userId}`; } /** * 从缓存获取上次选择的打印机 * @param {string} businessName 打印业务名称 * @returns {string} 打印机名称 */ export function getCachedPrinter(businessName = 'default') { const cacheKey = getPrinterCacheKey(businessName); return localStorage.getItem(cacheKey) || ''; } /** * 保存打印机选择到缓存 * @param {string} printerName 打印机名称 * @param {string} businessName 打印业务名称 */ export function savePrinterToCache(printerName, businessName = 'default') { if (printerName) { const cacheKey = getPrinterCacheKey(businessName); localStorage.setItem(cacheKey, printerName); } } /** * 执行打印操作 * @param {Array} data 打印数据 * @param {Object} template 打印模板 * @param {string} printerName 打印机名称(可选) * @param {Object} options 打印选项(可选) * @param {string} businessName 打印业务名称(可选) * @returns {Promise} 打印结果Promise */ export function executePrint(data, template, printerName, options = {}, businessName = 'default') { return new Promise((resolve, reject) => { try { // 调试信息 console.log('========== 打印诊断日志开始 =========='); console.log('[1] hiprint对象检查:'); console.log(' - hiprint存在:', !!hiprint); console.log(' - hiprint.PrintTemplate存在:', !!(hiprint && hiprint.PrintTemplate)); console.log(' - hiprint.hiwebSocket存在:', !!(hiprint && hiprint.hiwebSocket)); console.log(' - hiprint.hiwebSocket.connected:', hiprint?.hiwebSocket?.connected); console.log('[2] 模板数据检查:'); console.log(' - 模板类型:', typeof template); console.log(' - 模板存在:', !!template); console.log(' - 模板panels存在:', !!(template && template.panels)); console.log(' - panels数量:', template?.panels?.length); if (template?.panels?.[0]) { const panel = template.panels[0]; console.log(' - panel.name:', panel.name, '(类型:', typeof panel.name, ')'); console.log(' - panel.index:', panel.index); console.log(' - panel.printElements数量:', panel.printElements?.length); // 检查每个元素的类型 if (panel.printElements) { panel.printElements.forEach((el, idx) => { console.log(` - 元素[${idx}]:`, el.printElementType?.type, '-', el.printElementType?.title); }); } } const userStore = useUserStore(); console.log('[3] 医院名称:', userStore.hospitalName); let processedTemplate; try { processedTemplate = JSON.parse( JSON.stringify(template).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName) ); console.log('[4] 模板处理成功'); } catch (parseError) { console.error('[4] 模板处理失败:', parseError); throw new Error('模板处理失败: ' + parseError.message); } console.log('[5] 打印数据检查:'); console.log(' - 数据类型:', typeof data); console.log(' - 数据存在:', !!data); if (data && typeof data === 'object') { console.log(' - 数据字段:', Object.keys(data)); } // 创建打印模板 let hiprintTemplate; try { console.log('[6] 开始创建PrintTemplate...'); hiprintTemplate = new hiprint.PrintTemplate({ template: processedTemplate }); console.log('[6] PrintTemplate创建成功:', hiprintTemplate); } catch (templateError) { console.error('[6] 创建打印模板失败:', templateError); console.error('错误堆栈:', templateError.stack); console.error('模板内容:', JSON.stringify(processedTemplate, null, 2)); throw new Error('打印模板创建失败: ' + templateError.message); } const printOptions = { title: '打印标题', height: 210, width: 148, ...options, }; console.log('[7] 打印选项:', printOptions); // 检查客户端是否连接 const isClientConnected = hiprint.hiwebSocket && hiprint.hiwebSocket.connected; console.log('[8] 客户端连接状态:', isClientConnected); // 如果指定了打印机且客户端已连接,添加到打印选项中 if (printerName && isClientConnected) { printOptions.printer = printerName; // 保存到缓存 savePrinterToCache(printerName, businessName); console.log('[8] 使用指定打印机:', printerName); } // 打印成功回调 hiprintTemplate.on('printSuccess', function (e) { console.log('[9] 打印成功:', e); console.log('========== 打印诊断日志结束 =========='); resolve({ success: true, event: e }); }); // 打印失败回调 hiprintTemplate.on('printError', function (e) { console.error('[9] 打印失败:', e); console.log('========== 打印诊断日志结束 =========='); reject({ success: false, event: e, message: '打印失败' }); }); // 根据客户端连接状态选择打印方式 console.log('[10] 开始执行打印...'); if (isClientConnected && printerName) { // 客户端已连接且指定了打印机,使用静默打印 console.log('[10] 使用print2静默打印'); try { hiprintTemplate.print2(data, printOptions); console.log('[10] print2调用完成'); } catch (print2Error) { console.error('[10] print2调用失败:', print2Error); console.error('[10] print2错误堆栈:', print2Error.stack); throw new Error('print2打印失败: ' + print2Error.message); } } else { // 客户端未连接或未指定打印机,使用浏览器打印预览(不需要客户端连接) console.log('[10] 使用print浏览器打印预览'); console.log('[10] hiprintTemplate.print方法存在:', typeof hiprintTemplate.print === 'function'); try { hiprintTemplate.print(data, printOptions, { styleHandler: () => { console.log('[10] styleHandler被调用'); return ''; }, callback: (e) => { console.log('[10] 打印回调被调用:', e); } }); console.log('[10] print调用完成'); } catch (printError) { console.error('[10] print调用失败:', printError); console.error('[10] print错误堆栈:', printError.stack); throw new Error('print打印失败: ' + printError.message); } // 浏览器打印模式下,直接resolve(因为打印窗口已打开) console.log('[10] 浏览器打印模式,直接返回成功'); console.log('========== 打印诊断日志结束 =========='); resolve({ success: true, message: '打印窗口已打开' }); } } catch (error) { console.error('[ERROR] 打印过程中发生错误:', error); console.error('[ERROR] 错误类型:', error?.constructor?.name); console.error('[ERROR] 错误消息:', error?.message); console.error('[ERROR] 错误堆栈:', error?.stack); console.log('========== 打印诊断日志结束 =========='); reject({ success: false, error: error, message: error?.message || '打印过程中发生错误' }); } }); } /** * 选择打印机并执行打印 * @param {Array} data 打印数据 * @param {Object} template 打印模板 * @param {Function} showPrinterDialog 显示打印机选择对话框的函数 * @param {Object} modal 消息提示对象 * @param {Function} callback 打印完成后的回调函数 * @param {string} businessName 打印业务名称(可选) */ export async function selectPrinterAndPrint( data, template, showPrinterDialog, modal, callback, businessName = 'default' ) { try { // 获取打印机列表 const printerList = getPrinterList(); if (printerList.length === 0) { modal.msgWarning('未检测到可用打印机'); return; } // 获取缓存的打印机 const cachedPrinter = getCachedPrinter(businessName); let selectedPrinter = ''; // 判断打印机选择逻辑 if (printerList.length === 1) { selectedPrinter = printerList[0].name; await executePrint(data, template, selectedPrinter, {}, businessName); if (callback) callback(); } else if (cachedPrinter && printerList.some((printer) => printer.name === cachedPrinter)) { selectedPrinter = cachedPrinter; await executePrint(data, template, selectedPrinter, {}, businessName); if (callback) callback(); } else { // 调用显示打印机选择对话框的函数 showPrinterDialog(printerList, async (chosenPrinter) => { try { await executePrint(data, template, chosenPrinter, {}, businessName); if (callback) callback(); } catch (error) { modal.msgError(error.message || '打印失败'); } }); } } catch (error) { modal.msgError(error.message || '获取打印机列表失败'); } } // 预览打印 export function previewPrint(elementDom) { if (elementDom) { // 初始化已在 main.js 中完成,无需重复调用 // hiprint.init(); const hiprintTemplate = new hiprint.PrintTemplate(); // printByHtml为预览打印 hiprintTemplate.printByHtml(elementDom, {}); } else { ElMessage({ type: 'error', message: '加载模版失败', }); } } /** * 打印门诊挂号收据(使用浏览器打印,模板与补打挂号一致) * @param {Object} data 打印数据 * @param {Object} options 打印选项 * @returns {Promise} 打印结果 Promise */ export function printRegistrationReceipt(data, options = {}) { return new Promise((resolve, reject) => { try { // 构建打印内容的 HTML const printContent = `
流水号: ${data.serialNo || data.encounterId || '-'}
扫码查看挂号信息
`; // 创建新窗口用于打印 const printWindow = window.open('', '_blank'); if (!printWindow) { reject(new Error('无法打开打印窗口,请检查浏览器弹窗设置')); return; } // 写入打印内容 printWindow.document.write(` 门诊预约挂号凭条 `); printWindow.document.close(); printWindow.onload = function() { setTimeout(() => { printWindow.print(); resolve({ success: true, message: '打印窗口已打开' }); }, 250); }; } catch (error) { console.error('打印门诊挂号收据失败:', error); reject(error); } }); } /** * 脱敏身份证号 * @param {string} idCard 身份证号 * @returns {string} 脱敏后的身份证号 */ function maskIdCard(idCard) { if (!idCard) return ''; if (idCard.length >= 10) { const prefix = idCard.substring(0, 6); const suffix = idCard.substring(idCard.length - 4); const stars = '*'.repeat(Math.max(0, idCard.length - 10)); return prefix + stars + suffix; } else if (idCard.length >= 6) { const prefix = idCard.substring(0, 3); const suffix = idCard.substring(idCard.length - 1); return prefix + '*'.repeat(idCard.length - 4) + suffix; } return idCard; } // 默认导出简化的打印方法 export default { print: simplePrint, printWithDialog: simplePrintWithDialog, TEMPLATE: PRINT_TEMPLATE, executePrint, selectPrinterAndPrint, getPrinterList, getCachedPrinter, savePrinterToCache, };