UNPKG

wui-print

Version:

前端打印插件,包含打印设计器、打印表单、打印API

704 lines (703 loc) 23.7 kB
import printDesignerStyleHelper from "./print-designer-style-helper"; import { deepCopy } from "./print-designer-utils"; import useCreateHtml from "./use-create-html/index"; import useCreatePrintJs from "./use-create-print-js/index"; const createPrintDataByLayoutConfig = (layoutConfig) => { // 通过布局配置生成打印数据 let printData = {}; if (!layoutConfig || layoutConfig.length <= 0) { return printData; } layoutConfig.forEach((item, index) => { if (item.type == "grid") { item.children.forEach((gridItem, gridItemIndex) => { gridItem.children.forEach((componentItem, componentIndex) => { _createPrintDataItem(componentItem); }); }); } else if (item.type == "tableLayout") { item.children.forEach((componentItem, componentIndex) => { _createPrintDataItem(componentItem); }); } else { _createPrintDataItem(item); } }); function _createPrintDataItem(componentItem) { let componentItemProps = !!componentItem.props ? componentItem.props : {}; let componentItemField = componentItemProps.field; if (!componentItemField) { return; } if (componentItem.type == "table") { printData[componentItemField] = []; if (!!componentItem.columns && componentItem.columns.length > 0) { let rowData = {}; componentItem.columns.forEach((columnItem, columnIndex) => { if (!columnItem.props.field) { return; } rowData[columnItem.props.field] = ""; }); printData[componentItemField].push(rowData); } return; } if (componentItem.type == "complexTable") { printData[componentItemField] = []; if (!!componentItemProps.columnsField && componentItemProps.columnsField.length > 0) { let rowData = {}; componentItemProps.columnsField.forEach((columnItem, columnIndex) => { if (!columnItem.field) { return; } rowData[columnItem.field] = ""; }); printData[componentItemField].push(rowData); } return; } printData[componentItemField] = ""; } return printData; }; const createPrintHtmlByDesignerConfig = ({ renderType = "print", printData = {}, printConfig, formConfig, layoutConfig, printedRowCount = 0, printedRows = [], continuePrintElements }) => { // 通过设计器配置生成打印html let printHtml = ""; if (!printConfig || !formConfig || !layoutConfig) { return printHtml; } if (!printData) { printData = {}; } const errorLogs = []; const createHtmlInstance = useCreateHtml({ printData, printConfig, formConfig, layoutConfig, printedRowCount, printedRows, continuePrintElements, errorLogs }); if (createHtmlInstance.layoutConfig.length <= 0) { return _getReturnStr(); } createHtmlInstance.layoutConfig.forEach((item, index) => { if (item.type == "grid") { printHtml += createHtmlInstance.gridHelper.createGridHtml(item); } else if (item.type == "tableLayout") { printHtml += createHtmlInstance.tableLayoutHelper.createTableLayoutHtml(item); } else { printHtml += createHtmlInstance.createHtmlByComponentItem(item); } }); if (errorLogs.length > 0) { console.warn(`创建打印文档异常日志:\n${errorLogs.join("\n")}`); return false; } function _getReturnStr() { // 返参 let containerClassList = []; let pageSizeStr = !!printConfig.pageSize ? printConfig.pageSize : ""; if (!!pageSizeStr && !!printConfig.landscape) { pageSizeStr += "-landscape"; } containerClassList.push(`print-container--${renderType}`); containerClassList.push(`print-container--${pageSizeStr.toLowerCase()}`); let formConfigProps = !!formConfig.props ? formConfig.props : {}; if (!!formConfigProps.size) { containerClassList.push(`print-form-${formConfigProps.size}`); } if (!!formConfigProps.labelPosition) { containerClassList.push(`print-form_label-${formConfigProps.labelPosition}`); } let containerClassStr = containerClassList.join(" "); printHtml = `<div class="print-container ${containerClassStr}" style="${printDesignerStyleHelper.createContainerStyle({ styleConfig: printConfig.style })}">${printHtml}</div>`; return printHtml; } return _getReturnStr(); }; const createPrintJsStringByDesignerConfig = ({ printData = {}, layoutConfig }) => { // 通过设计器配置生成打印html let jsString = ""; if (!printData || !layoutConfig) { return jsString; } const createPrintJsInstance = useCreatePrintJs({ printData, layoutConfig }); jsString += createPrintJsInstance.createBaseJsString(); layoutConfig.forEach((item, index) => { if (item.type == "grid") { jsString += createPrintJsInstance.createJsStringOnGrid(item); } else if (item.type == "tableLayout") { jsString += createPrintJsInstance.createJsStringOnTablelayout(item); } else if (item.type == "complexTable") { jsString += createPrintJsInstance.createJsStringByComplexTable(item); } else { jsString += createPrintJsInstance.createJsStringByComponentItem(item); } }); return jsString; }; export const createPrintSoketHtml = ({ printStyle = "", printHtml = "" } = {}) => { let printSoketHml = ` <style>${printStyle}</style> ${printHtml} `; return printSoketHml; }; export const createPrintDocument = ({ title = "", printStyle = "", printHtml = "" } = {}) => { let printHml = ` <!DOCTYPE html> <html> <head> <title>${title}</title> <style>${printStyle}</style> </head> <body> ${printHtml} </body> </html> `; return printHml; }; export const preview = ({ printData = {}, designerConfig = {}, printedRowCount = 0, printedRows = [] } = {}) => { return new Promise(async (resolve, reject) => { let designerConfigDemo = { printConfig: {}, layoutConfig: {} }; if (Array.isArray(designerConfig)) { return reject(`参数【designerConfig】当前类型是数组,合法参数:${JSON.stringify(designerConfigDemo)}`); } if (typeof designerConfig != "object") { return reject(`参数【designerConfig】的类型无效,合法参数:${JSON.stringify(designerConfigDemo)}`); } if (!printData) { // 特意这样写避免printData存在时再次赋值 printData = {}; } let { printConfig, formConfig, layoutConfig } = designerConfig; if (!printConfig) { return reject(`参数【designerConfig】缺少【printConfig】`); } if (!formConfig) { return reject(`参数【designerConfig】缺少【formConfig】`); } if (!layoutConfig) { return reject(`参数【designerConfig】缺少【layoutConfig】`); } let { continuePrintElements, windowInstance } = await _getContinuePrintElementsOnAutoHeightMode({ printData, printConfig, formConfig, layoutConfig, printedRows, windowTitle: "preview" }); let printHtml = createPrintHtmlByDesignerConfig({ renderType: "preview", printData, printConfig, formConfig, layoutConfig, printedRowCount, printedRows, continuePrintElements }); if (!printHtml) { return reject("创建文档失败"); } let printStyle = printDesignerStyleHelper.createPrintStyle({ printConfig }); let printJsString = createPrintJsStringByDesignerConfig({ printData, layoutConfig }); await _webPrintPreview({ windowInstance, designerConfig, title: printConfig.title, printStyle, printHtml, printJsString }); return resolve(); }); }; export const previewInIframe = ({ iframeId = "", printData = {}, designerConfig = {}, printedRowCount = 0, printedRows = [] } = {}) => { return new Promise(async (resolve, reject) => { let designerConfigDemo = { printConfig: {}, layoutConfig: {} }; if (!iframeId) { return reject(`参数【iframeId】无效`); } let iframeInstance = document.getElementById(iframeId); if (!iframeInstance) { return reject(`id为【iframeId】的元素不存在`); } if (Array.isArray(designerConfig)) { return reject(`参数【designerConfig】当前类型是数组,合法参数:${JSON.stringify(designerConfigDemo)}`); } if (typeof designerConfig != "object") { return reject(`参数【designerConfig】的类型无效,合法参数:${JSON.stringify(designerConfigDemo)}`); } if (!printData) { // 特意这样写避免printData存在时再次赋值 printData = {}; } let { printConfig, formConfig, layoutConfig } = designerConfig; if (!printConfig) { return reject(`参数【designerConfig】缺少【printConfig】`); } if (!formConfig) { return reject(`参数【designerConfig】缺少【formConfig】`); } if (!layoutConfig) { return reject(`参数【designerConfig】缺少【layoutConfig】`); } let { continuePrintElements, windowInstance } = await _getContinuePrintElementsOnAutoHeightMode({ printData, printConfig, formConfig, layoutConfig, printedRows, windowTitle: "preview" }); !!windowInstance && windowInstance.close(); let printHtml = createPrintHtmlByDesignerConfig({ renderType: "preview", printData, printConfig, formConfig, layoutConfig, printedRowCount, printedRows, continuePrintElements }); if (!printHtml) { return reject("创建文档失败"); } let printStyle = printDesignerStyleHelper.createPrintStyle({ printConfig }); let printJsString = createPrintJsStringByDesignerConfig({ printData, layoutConfig }); let printDocment = createPrintDocument({ printStyle, printHtml }); let iframeWindowInstance = iframeInstance.contentWindow; iframeWindowInstance.document.documentElement.innerHTML = printDocment; _appendPlugins({ windowInstance: iframeWindowInstance, designerConfig, callback: () => { let script = document.createElement("script"); script.type = "text/javascript"; script.text = `${printJsString}`; iframeWindowInstance.document.body.appendChild(script); } }); return resolve(printDocment); }); }; export const print = ({ type = "web", printData = {}, designerConfig = {}, printedRowCount = 0, printedRows = [] } = {}) => { return new Promise(async (resolve, reject) => { let ableTypeList = ["web", "soket"]; let designerConfigDemo = { printConfig: {}, layoutConfig: {} }; if (ableTypeList.indexOf(type) < 0) { return reject(`参数【type】的值【${type}】无效,合法参数:【${ableTypeList.join(",")}】`); } if (Array.isArray(designerConfig)) { return reject(`参数【designerConfig】当前类型是数组,合法参数:${JSON.stringify(designerConfigDemo)}`); } if (typeof designerConfig != "object") { return reject(`参数【designerConfig】的类型无效,合法参数:${JSON.stringify(designerConfigDemo)}`); } if (!printData) { // 特意这样写避免printData存在时再次赋值 printData = {}; } let { printConfig, formConfig, layoutConfig } = designerConfig; if (!printConfig) { return reject(`参数【designerConfig】缺少【printConfig】`); } if (!formConfig) { return reject(`参数【designerConfig】缺少【formConfig】`); } if (!layoutConfig) { return reject(`参数【designerConfig】缺少【layoutConfig】`); } if (type == "web") { // 浏览器打印 let { continuePrintElements, windowInstance } = await _getContinuePrintElementsOnAutoHeightMode({ printData, printConfig, formConfig, layoutConfig, printedRows, windowTitle: "print" }); let printHtml = createPrintHtmlByDesignerConfig({ printData, printConfig, formConfig, layoutConfig, printedRowCount, printedRows, continuePrintElements }); if (!printHtml) { return reject("创建文档失败"); } let printStyle = printDesignerStyleHelper.createPrintStyle({ printConfig }); let printJsString = createPrintJsStringByDesignerConfig({ printData, layoutConfig }); await _webPrint({ windowInstance, designerConfig, title: printConfig.title, printStyle, printHtml, printJsString }); return resolve(); } if (type == "soket") { // 静默打印 if (!window.WuiPrintSocket) { return reject("未集成打印助手"); } if (!!window.WuiPrintSocket && !window.WuiPrintSocket.connected) { return reject("请检查【打印助手】是否正常运行"); } await _soketPrint({ printData, printConfig, formConfig, layoutConfig, printedRowCount, printedRows }).catch((error) => { return reject(error); }); return resolve(); } }); }; export const printGroup = () => { // 打印分组 // 物资入库单打印解决方案 }; const _webPrint = ({ windowInstance, designerConfig, title = "", printStyle = "", printHtml = "", printJsString = "" } = {}) => { // 浏览器打印 return new Promise(async (resolve, reject) => { try { if (!windowInstance) { windowInstance = window.open("", "print", "height=700,width=1200"); } // windowInstance.document.write(createPrintDocument({ title, printStyle, printHtml })); windowInstance.document.documentElement.innerHTML = createPrintDocument({ title, printStyle, printHtml }); _appendPlugins({ windowInstance, designerConfig, callback: () => { let script = document.createElement("script"); script.type = "text/javascript"; script.text = `${printJsString}`; windowInstance.document.body.appendChild(script); windowInstance.print(); // 调用打印 windowInstance.close(); // 打印后关闭窗口 } }); return resolve(); } catch (error) { console.warn(error); return reject(error); } }); }; const _webPrintPreview = ({ windowInstance, designerConfig, title = "", printStyle = "", printHtml = "", printJsString = "" } = {}) => { // 浏览器打印预览 return new Promise(async (resolve, reject) => { try { if (!windowInstance) { windowInstance = window.open("", "printPreview", "height=700,width=1200"); } windowInstance.document.documentElement.innerHTML = createPrintDocument({ title, printStyle, printHtml }); _appendPlugins({ windowInstance, designerConfig, callback: () => { let script = document.createElement("script"); script.type = "text/javascript"; script.text = `${printJsString}`; windowInstance.document.body.appendChild(script); } }); return resolve(); } catch (error) { console.warn(error); return reject(error); } }); }; const _soketPrint = ({ printData = {}, printConfig = {}, formConfig = {}, layoutConfig = {}, printedRowCount = 0, printedRows } = {}) => { // 通过soket发起静默打印 return new Promise((resolve, reject) => { let printHtml = createPrintHtmlByDesignerConfig({ printData, printConfig, formConfig, layoutConfig, printedRowCount, printedRows }); if (!printHtml) { return reject("创建文档失败"); } let printStyle = printDesignerStyleHelper.createPrintStyle({ printConfig }); let printJsString = createPrintJsStringByDesignerConfig({ printData, layoutConfig }); let printDocumentHtml = createPrintSoketHtml({ printStyle, printHtml }); let printOptions = { templateId: printConfig.templateTitle, type: printConfig.servePrintType, html: printDocumentHtml, pageSize: printConfig.pageSize, // 设置纸张 printer: printConfig.printer, // 可以指定打印机名称 silent: printConfig.silent, // 静默打印 landscape: !!printConfig.landscape, // 是否横向打印 margins: { top: 0, bottom: 0, left: 0, right: 0 }, printJsString }; //调用打印 window.WuiPrintSocket.emit("news", printOptions); return resolve(); }); }; const _appendPlugins = ({ windowInstance, designerConfig, callback } = {}) => { let { printConfig, formConfig, layoutConfig } = designerConfig; let { hasBarcode, hasQrcode } = __getPlugins(); if (!hasBarcode && !hasQrcode) { !!callback && callback(); return; } let appendNum = 0; let successNum = 0; if (hasBarcode) { appendNum++; let scriptJsBarcode = windowInstance.document.createElement("script"); scriptJsBarcode.type = "text/javascript"; scriptJsBarcode.src = "/wui-print-designer-plugins/JsBarcode.all.min.js"; windowInstance.document.head.appendChild(scriptJsBarcode); } if (hasQrcode) { appendNum++; let scriptJsBarcode = windowInstance.document.createElement("script"); scriptJsBarcode.type = "text/javascript"; scriptJsBarcode.src = "/wui-print-designer-plugins/qrcode.min.js"; windowInstance.document.head.appendChild(scriptJsBarcode); } let intervalId = setInterval(() => { successNum = 0; if (hasBarcode && !!windowInstance.JsBarcode && typeof windowInstance.JsBarcode == "function") { successNum++; } if (hasQrcode && !!windowInstance.QRCode && typeof windowInstance.QRCode == "function") { successNum++; } __canCallback(); }, 100); function __canCallback() { if (successNum == appendNum) { clearInterval(intervalId); !!callback && callback(); } } function __getPlugins() { let hasBarcode = false; let hasQrcode = false; layoutConfig.forEach((item, index) => { if (!!hasBarcode && !!hasQrcode) { return; } if (item.type == "grid" && !!item.children) { item.children.forEach((cellItem, cellIndex) => { if (!!cellItem.children) { cellItem.children.forEach((componentItem, componentIndex) => { __setState(componentItem); }); } }); return; } if (item.type == "tableLayout" && !!item.children) { item.children.forEach((componentItem, componentIndex) => { __setState(componentItem); }); return; } __setState(item); }); function __setState(componentItem) { if (componentItem.type == "barcode") { hasBarcode = true; } else if (componentItem.type == "qrcode") { hasQrcode = true; } } return { hasBarcode, hasQrcode }; } }; async function _getContinuePrintElementsOnAutoHeightMode({ printData, printConfig, formConfig, layoutConfig, printedRows, windowTitle = "continuePrintElementsPreview" }) { return new Promise((resolve, reject) => { let autoContinueDetails = _getAutoContinueDetails({ layoutConfig, printData, printedRows }); if (!autoContinueDetails.state) { return resolve(false); } let printStyle = printDesignerStyleHelper.createPrintStyle({ printConfig }); let autoContinuePrintHtml = _createAutoContinuePrintHtml({ printData: autoContinueDetails.printData, printConfig, formConfig, layoutConfig: autoContinueDetails.layoutConfig }); const windowInstance = window.open("", windowTitle, "height=700,width=1200"); windowInstance.document.documentElement.innerHTML = createPrintDocument({ title: "正在加载", printStyle, printHtml: autoContinuePrintHtml }); const checkLoadStatus = setInterval(() => { if (windowInstance.document.readyState === "complete") { clearInterval(checkLoadStatus); // 加载完成后停止检查 let continuePrintElements = windowInstance.document.querySelectorAll(".print-complex-table")[0]; setTimeout(() => { return resolve({ continuePrintElements, windowInstance }); }, 1000); } }, 100); }); } function _createAutoContinuePrintHtml({ printData, printConfig, formConfig, layoutConfig, printedRows }) { const createHtmlInstance = useCreateHtml({ printData, printConfig, formConfig, layoutConfig, printedRows }); let printHtml = ""; createHtmlInstance.layoutConfig.forEach((item, index) => { printHtml += createHtmlInstance.createHtmlByComponentItem(item); }); let containerClassList = []; let renderType = "auto-continue-preview"; let pageSizeStr = !!printConfig.pageSize ? printConfig.pageSize : ""; if (!!pageSizeStr && !!printConfig.landscape) { pageSizeStr += "-landscape"; } containerClassList.push(`print-container--${renderType}`); containerClassList.push(`print-container--${pageSizeStr.toLowerCase()}`); let containerClassStr = containerClassList.join(" "); printHtml = `<div class="print-container ${containerClassStr}" style="${printDesignerStyleHelper.createContainerStyle({ styleConfig: printConfig.style })}">${printHtml}</div>`; return printHtml; } function _getAutoContinueDetails({ layoutConfig, printData, printedRows = [] }) { if (!printData) { printData = {}; } if (!printedRows) { printedRows = []; } let autoContinueDetails = { state: false, layoutConfig: [], printData: deepCopy(printData) }; if (!layoutConfig || layoutConfig.length <= 0) { return autoContinueDetails; } let autoContinueConfigItem = false; layoutConfig.forEach((item, index) => { if (!!autoContinueConfigItem) { return; } let nowProps = !!item.props ? item.props : {}; if (item.type == "complexTable" && !!nowProps.canContinue && nowProps.continuePrintMode == "autoHeight") { autoContinueConfigItem = deepCopy(item); } }); if (!autoContinueConfigItem) { return autoContinueDetails; } autoContinueDetails.state = true; autoContinueConfigItem.props.continuePrintMode = "_autoHeight_previewElements"; autoContinueDetails.layoutConfig.push(deepCopy(autoContinueConfigItem)); let dataField = autoContinueConfigItem.props.field; if (!!dataField && !!autoContinueDetails.printData[dataField]) { autoContinueDetails.printData[dataField].unshift(...printedRows); } return autoContinueDetails; } export default { createPrintDataByLayoutConfig, createPrintHtmlByDesignerConfig, createPrintJsStringByDesignerConfig, createPrintSoketHtml, createPrintDocument, preview, previewInIframe, print, printGroup };