702
openhis-ui-vue3/src/utils/printUtils.js
Executable file
702
openhis-ui-vue3/src/utils/printUtils.js
Executable file
@@ -0,0 +1,702 @@
|
||||
/**
|
||||
* 打印工具类
|
||||
* 集中管理所有打印相关功能
|
||||
*/
|
||||
|
||||
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<Object>} 模板对象
|
||||
*/
|
||||
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 '<style>@media print { @page { margin: 0; } }</style>';
|
||||
},
|
||||
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 = `
|
||||
<div class="print-header">
|
||||
<div class="header-content">
|
||||
<div class="document-title">门诊预约挂号凭条</div>
|
||||
<div class="print-time">打印时间:${data.printTime || new Date().toLocaleString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="print-section">
|
||||
<div class="section-title">患者基本信息</div>
|
||||
<div class="info-row">
|
||||
<span class="label">患者姓名:</span>
|
||||
<span class="value">${data.patientName || '-'}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">就诊卡号:</span>
|
||||
<span class="value">${data.cardNo || data.busNo || '-'}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">身份证号:</span>
|
||||
<span class="value">${data.idCard ? maskIdCard(data.idCard) : '-'}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">联系电话:</span>
|
||||
<span class="value">${data.phone || '-'}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="print-section">
|
||||
<div class="section-title">挂号信息</div>
|
||||
<div class="info-row">
|
||||
<span class="label">就诊科室:</span>
|
||||
<span class="value">${data.organizationName || '-'}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">医生姓名:</span>
|
||||
<span class="value">${data.practitionerName || '-'}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">挂号类型:</span>
|
||||
<span class="value">${data.healthcareName || '-'}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">挂号时间:</span>
|
||||
<span class="value">${data.visitTime || data.chargeTime || '-'}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="print-section">
|
||||
<div class="section-title">费用信息</div>
|
||||
<table class="fee-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>项目</th>
|
||||
<th>数量</th>
|
||||
<th>单价</th>
|
||||
<th>金额</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>挂号费</td>
|
||||
<td>1</td>
|
||||
<td>¥${parseFloat(data.price || 0).toFixed(2)}</td>
|
||||
<td>¥${parseFloat(data.price || 0).toFixed(2)}</td>
|
||||
</tr>
|
||||
${parseFloat(data.activityPrice || 0) > 0 ? `
|
||||
<tr>
|
||||
<td>诊疗费</td>
|
||||
<td>1</td>
|
||||
<td>¥${parseFloat(data.activityPrice || 0).toFixed(2)}</td>
|
||||
<td>¥${parseFloat(data.activityPrice || 0).toFixed(2)}</td>
|
||||
</tr>` : ''}
|
||||
${parseFloat(data.medicalRecordFee || 0) > 0 ? `
|
||||
<tr>
|
||||
<td>病历费</td>
|
||||
<td>1</td>
|
||||
<td>¥${parseFloat(data.medicalRecordFee || 0).toFixed(2)}</td>
|
||||
<td>¥${parseFloat(data.medicalRecordFee || 0).toFixed(2)}</td>
|
||||
</tr>` : ''}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3" class="total-label">合计:</td>
|
||||
<td class="total-value">¥${parseFloat(data.totalPrice || data.amount || 0).toFixed(2)}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 流水号显示在左下角 -->
|
||||
<div class="serial-number-bottom-left">
|
||||
<span class="serial-label">流水号:</span>
|
||||
<span class="serial-value">${data.serialNo || data.encounterId || '-'}</span>
|
||||
</div>
|
||||
|
||||
<div class="print-footer">
|
||||
<div class="reminder">温馨提示:请妥善保管此凭条,就诊时请携带。</div>
|
||||
</div>
|
||||
|
||||
<!-- 二维码区域 -->
|
||||
<div class="qr-code-section">
|
||||
<div class="qr-code-container">
|
||||
<div id="qrcode-print" class="qrcode-print"></div>
|
||||
<div class="qr-code-label">扫码查看挂号信息</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 创建新窗口用于打印
|
||||
const printWindow = window.open('', '_blank');
|
||||
if (!printWindow) {
|
||||
reject(new Error('无法打开打印窗口,请检查浏览器弹窗设置'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 写入打印内容
|
||||
printWindow.document.write(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>门诊预约挂号凭条</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; padding: 20px; margin: 0; }
|
||||
.print-header { margin-bottom: 20px; position: relative; }
|
||||
.header-content { text-align: center; }
|
||||
.document-title { font-size: 16px; font-weight: bold; margin-bottom: 10px; }
|
||||
.print-time { font-size: 12px; color: #666; text-align: right; }
|
||||
.print-section { margin-bottom: 20px; }
|
||||
.section-title { font-size: 14px; font-weight: bold; margin-bottom: 10px; border-bottom: 1px solid #ddd; padding-bottom: 5px; }
|
||||
.info-row { margin-bottom: 8px; font-size: 13px; }
|
||||
.label { display: inline-block; width: 100px; font-weight: bold; }
|
||||
.value { display: inline-block; }
|
||||
.fee-table { width: 100%; border-collapse: collapse; margin-top: 10px; }
|
||||
.fee-table th, .fee-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
|
||||
.fee-table th { background-color: #f5f5f5; font-weight: bold; }
|
||||
.total-label { font-weight: bold; text-align: right; }
|
||||
.total-value { font-weight: bold; color: red; }
|
||||
.serial-number-bottom-left { position: absolute; bottom: 20px; left: 20px; font-size: 14px; font-weight: bold; }
|
||||
.serial-number-bottom-left .serial-label { font-weight: bold; margin-right: 5px; }
|
||||
.serial-number-bottom-left .serial-value { font-weight: bold; color: #333; }
|
||||
.print-content { position: relative; min-height: 500px; padding-bottom: 60px; }
|
||||
.print-footer { margin-top: 20px; font-size: 12px; color: #666; }
|
||||
.reminder { text-align: center; padding: 10px; background-color: #f9f9f9; border-radius: 4px; }
|
||||
.qr-code-section { margin-top: 20px; display: flex; justify-content: center; align-items: center; padding: 15px; }
|
||||
.qr-code-container { display: flex; flex-direction: column; align-items: center; gap: 10px; }
|
||||
.qrcode-print { width: 120px; height: 120px; }
|
||||
.qr-code-label { font-size: 12px; color: #666; text-align: center; }
|
||||
@media print { body { padding: 0; } .qr-code-section { page-break-inside: avoid; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="print-content">
|
||||
${printContent}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
|
||||
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,
|
||||
};
|
||||
Reference in New Issue
Block a user