wui-print
Version:
前端打印插件,包含打印设计器、打印表单、打印API
704 lines (703 loc) • 23.7 kB
JavaScript
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
};