UNPKG

fastlion-amis

Version:

一种MIS页面生成工具

800 lines (735 loc) 39.7 kB
import { decode } from "js-base64" import { PrinterParam, TableColumn, ColumnInfo, SettingValues, OptionValues, IFPTableValue, DetailOptionValues } from "../../renderers/Lion/LabelPrint/types" import { FormTemplate, LabelNumber, LabelTemplate, LabelPageParam, LabelCodeType, LabelPrintStyleParam, LabelText, LabelBarCode, LabelEllipse, LabelHtml, LabelLine, LabelRect, LabelShape, LabelTable, LabelImage, Rect, DetailTemplate, CodeRect, TitleRect } from "./type" import moment from 'moment' import { calcFn, sortFn } from "../utils" import { getCellValue } from "../../store/utils/commonTableFunction" import { flatMap } from "lodash" type ColumnDataType = IFPTableValue type TemplateSetting = Pick<SettingValues, 'width' | 'height' | 'direction' | 'left' | 'right' | 'bottom' | 'top'> export const buildDetailTemplate = (settings: TemplateSetting, options: DetailOptionValues & { subTitle?: string, extraTitle: string, codeValue?: string, codeLabel?: string }): DetailTemplate => { const userInfo = sessionStorage.getItem('userInfo') ?? '{}' const userObj = userInfo && JSON.parse(userInfo) const { width, height, direction, top: defaultTop, bottom: defaultBottom, left: defaultLeft, right: defaultRight } = settings const { showLogo, title, showTitle, showDynamicSubTitles, dynamicSubTiltes, showPrinter, showDate, subTitle, extraTitle, showPageNum, showBarCode, showQRCode, codeLabel, codeValue } = options const pageWidth = direction == 'vertical' ? width : height const pageHeight = direction == 'vertical' ? height : width const headerHeight = 15 const codeWidth = (showBarCode || showQRCode) ? showBarCode ? 60 : 25 : 0 const codeHeight = (showBarCode || showQRCode) ? showBarCode ? 15 : 25 : 0 const titleHeight = showTitle ? 5 : 0 const titleMarginTop = 3 const subTitleHeight = showDynamicSubTitles ? 6 : 0 const subTitleMarginTop = showDynamicSubTitles ? 3 : 0 const subTitleCount = dynamicSubTiltes.length const htmlMarginTop = 3 const htmlMarginBottom = 8 const footerHeight = 4 const pageNumWidth = 12 const rect: Rect = { top: defaultTop, left: defaultLeft, width: pageWidth - defaultLeft - defaultRight, height: pageHeight - defaultTop - defaultBottom } const headerRect: Rect = { top: rect.top, left: rect.left, width: rect.width, height: headerHeight } const logoRect: Rect = { top: headerRect.top, left: headerRect.left, width: showLogo ? headerRect.height : 0, height: showLogo ? headerRect.height : 0, content: showLogo ? `<img src="./public/images/sanfu.png"/>` : '' } const codeRect: CodeRect = { top: headerRect.top, left: headerRect.width + headerRect.left - codeWidth, width: codeWidth, height: codeHeight, label: '', codeType: showQRCode ? 'QRCode' : 'code39', content: (showBarCode || showQRCode) ? codeValue : undefined } const codeLabelRect: Rect = { top: codeRect.top + codeRect.height + 1, left: codeRect.left, width: codeRect.width + 5, height: 10, content: `${codeLabel}:${codeValue}` } const extraTitleRect: Rect = { top: headerRect.top, left: headerRect.left + logoRect.width, width: headerRect.width - logoRect.width, height: headerRect.height, content: extraTitle } const titleRect: Rect = { top: headerRect.top + headerRect.height + titleMarginTop, left: rect.left, width: rect.width, height: titleHeight, content: showTitle ? title + (subTitle ? `[${subTitle}]` : '') : '' } const subTitleRect: Rect = { top: titleRect.top + titleRect.height + subTitleMarginTop, left: defaultLeft, width: rect.width, height: subTitleHeight } const subTitleRect1: Rect = { top: subTitleRect.top, left: subTitleRect.left, width: subTitleRect.width / (subTitleCount || 1), height: subTitleRect.height, content: showDynamicSubTitles ? dynamicSubTiltes[0] : undefined } const subTitleRect2: Rect = { top: subTitleRect.top, left: subTitleCount <= 1 ? 0 : subTitleRect.left + (subTitleRect.width / subTitleCount), width: subTitleCount <= 1 ? 0 : subTitleRect.width / (subTitleCount || 1), height: subTitleRect.height, content: showDynamicSubTitles ? dynamicSubTiltes[1] : undefined } const subTitleRect3: Rect = { top: subTitleRect.top, left: subTitleCount <= 2 ? 0 : subTitleRect.left + (subTitleRect.width / subTitleCount * (subTitleCount - 1)), width: subTitleCount <= 2 ? 0 : subTitleRect.width / (subTitleCount || 1), height: subTitleRect.height, content: showDynamicSubTitles ? dynamicSubTiltes[2] : undefined } const footerRect: Rect = { top: rect.height + defaultTop - footerHeight, left: rect.left, width: rect.width, height: footerHeight } const printerRect: Rect = { top: footerRect.top, left: rect.left, width: footerRect.width * 0.3, height: showPrinter ? footerRect.height : 0, content: showPrinter ? `打印者:${userObj.user_name ?? ''}` : '' } const dateRect: Rect = { top: footerRect.top, left: footerRect.left + printerRect.width, width: footerRect.width * 0.4, height: showDate ? footerRect.height : 0, content: showDate ? `打印时间:${moment(new Date()).format('YYYY-MM-DD HH:mm:ss')}` : '' } const numRect: Rect = { top: footerRect.top, left: footerRect.left + printerRect.width + dateRect.width + (footerRect.width * 0.3 - pageNumWidth * 2) - 2, width: pageNumWidth, height: footerRect.height, content: showPageNum ? '第#页' : '' } const sumRect: Rect = { top: footerRect.top, left: numRect.left + numRect.width + 2, width: pageNumWidth, height: footerRect.height, content: showPageNum ? '共#页' : '' } const htmlRect: Rect = { top: subTitleRect.top + subTitleRect.height + htmlMarginTop, left: rect.left, width: rect.width, height: footerRect.top - (subTitleRect.top + subTitleRect.height + htmlMarginTop) - htmlMarginBottom } return { header: headerRect, logo: logoRect, code: codeRect, codeLabel: codeLabelRect, extraTitle: extraTitleRect, title: titleRect, subTitle: subTitleRect, subTitle1: subTitleRect1, subTitle2: subTitleRect2, subTitle3: subTitleRect3, html: htmlRect, date: dateRect, printer: printerRect, footer: footerRect, num: numRect, sum: sumRect } } export const buildFormTemplate = (settings: TemplateSetting, options: OptionValues): FormTemplate => { const userInfo = sessionStorage.getItem('userInfo') ?? '{}' const userObj = userInfo && JSON.parse(userInfo) const { width, height, direction, top: defaultTop, bottom: defaultBottom, left: defaultLeft, right: defaultRight } = settings const { showHeaderTitle, headerTitle, showHeaderLine, showLogo, showTitle, titleAllPrint, title, showSubTitle, subTitleAllPrint, subTitle = [], showFooterLine, showFooterTitle, footerTitle, showPrinter, showDate, showPageNum } = options const pageWidth = direction == 'vertical' ? width : height const pageHeight = direction == 'vertical' ? height : width const headerHeight = (showLogo || showHeaderTitle || showHeaderLine) ? 18 : 0 const footerHeight = 5 const titleHeight = 3.4 const subTitleHeight = showSubTitle ? 6 : 0 const subTitleMarginTop = showSubTitle ? 3 : 0 const subTitleCount = subTitle.length const pageNumWidth = 12 const lineHeight = 0.3 const headerRect: Rect = { top: defaultTop, left: defaultLeft, width: pageWidth - defaultLeft - defaultRight, height: headerHeight } const headerLineRect = { top: headerRect.top + headerRect.height + 2, left: headerRect.left, width: headerRect.width, height: showHeaderLine ? lineHeight : 0 } const logoRect: Rect = { top: headerRect.top, left: headerRect.left, width: showLogo ? headerRect.height : 0, height: showLogo ? headerRect.height : 0, content: showLogo ? `<img src="./public/images/sanfu.png"/>` : '' } const headerTitleRect: Rect = { top: headerRect.top + (headerRect.height / 2 - 2), left: headerRect.left + logoRect.width + 5, width: headerRect.width - logoRect.width - 5, height: titleHeight, content: showHeaderTitle ? headerTitle : '' } const footerRect: Rect = { top: pageHeight - defaultBottom - footerHeight, left: defaultLeft, width: pageWidth - defaultLeft - defaultRight, height: footerHeight } const footerTitleRect: Rect = { top: footerRect.top - footerHeight, left: footerRect.left, width: footerRect.width, height: showFooterTitle ? footerHeight : 0, content: showFooterTitle ? footerTitle : '' } const footerLineRect: Rect = { top: footerRect.top, left: footerRect.left, width: footerRect.width, height: showFooterLine ? lineHeight : 0 } const printerRect: Rect = { top: footerRect.top + 2, left: footerRect.left, width: footerRect.width * 0.3, height: footerRect.height, content: showPrinter ? `打印者:${userObj.user_name ?? ''}` : '' } const dateRect: Rect = { top: footerRect.top + 2, left: footerRect.left + printerRect.width, width: footerRect.width * 0.4, height: footerRect.height, content: showDate ? `打印时间:${moment(new Date()).format('YYYY-MM-DD HH:mm:ss')}` : '' } const numRect: Rect = { top: footerRect.top + 2, left: footerRect.left + printerRect.width + dateRect.width + (footerRect.width * 0.3 - pageNumWidth * 2) - 2, width: pageNumWidth, height: footerRect.height, content: showPageNum ? '第#页' : '' } const sumRect: Rect = { top: footerRect.top + 2, left: numRect.left + numRect.width + 2, width: pageNumWidth, height: footerRect.height, content: showPageNum ? '共#页' : '' } const bodyRect: Rect = { top: 5 + headerRect.top + headerRect.height, left: defaultLeft, width: pageWidth - defaultLeft - defaultRight, height: pageHeight - (headerRect.top + headerRect.height + 3) - (footerRect.height + defaultBottom + 3) - (showFooterTitle ? footerHeight : 0) } const titleRect: TitleRect = { top: bodyRect.top, left: bodyRect.left, width: bodyRect.width, height: titleHeight, content: showTitle ? title : '', itemType: titleAllPrint ? 1 : 0 } const subTitleRect: Rect = { top: titleRect.top + titleRect.height + subTitleMarginTop, left: bodyRect.left, width: bodyRect.width, height: subTitleHeight } const subTitleRect1: TitleRect = { top: subTitleRect.top, left: subTitleRect.left, width: subTitleRect.width / (subTitleCount || 1), height: subTitleRect.height, content: showSubTitle ? subTitle[0] : undefined, itemType: subTitleAllPrint ? 1 : 0 } const subTitleRect2: TitleRect = { top: subTitleRect.top, left: subTitleCount <= 1 ? 0 : subTitleRect.left + (subTitleRect.width / subTitleCount), width: subTitleCount <= 1 ? 0 : subTitleRect.width / (subTitleCount || 1), height: subTitleRect.height, content: showSubTitle ? subTitle[1] : undefined, itemType: subTitleAllPrint ? 1 : 0 } const subTitleRect3: TitleRect = { top: subTitleRect.top, left: subTitleCount <= 2 ? 0 : subTitleRect.left + (subTitleRect.width / subTitleCount * (subTitleCount - 1)), width: subTitleCount <= 2 ? 0 : subTitleRect.width / (subTitleCount || 1), height: subTitleRect.height, content: showSubTitle ? subTitle[2] : undefined, itemType: subTitleAllPrint ? 1 : 0 } const tableRect: Rect = { top: subTitleRect.top + subTitleRect.height + 3, left: bodyRect.left, width: bodyRect.width, height: bodyRect.height - titleRect.height - subTitleRect.height - subTitleMarginTop - 9 } return { header: headerRect, logo: logoRect, headerLine: headerLineRect, headerTitle: headerTitleRect, body: bodyRect, title: titleRect, subTitle: subTitleRect, subTitle1: subTitleRect1, subTitle2: subTitleRect2, subTitle3: subTitleRect3, table: tableRect, footer: footerRect, footerLine: footerLineRect, footerTitle: footerTitleRect, printer: printerRect, date: dateRect, num: numRect, sum: sumRect } } // 计算每行放的个最大数 export const getMaxCount = (templateWidth: number, pageWidth: number, spacing: number): number => { let count = 1 while ((count * templateWidth + (count - 1) * spacing) <= pageWidth) { count++ if (count > 50) { break } } return (count - 1) || 1 } // 解析base64内容构造标签模板 export const buildLabelTemplate = (templateContent: string): LabelTemplate => { const getParams = (dataStr: string): string[] => { const start = dataStr.indexOf('(') + 1 const end = dataStr.lastIndexOf(')') const str = dataStr.substring(start, end) const params = str.split(',') return params.map(value => { const left = value.startsWith('"') ? value.substring(1) : value const right = left.endsWith('"') ? left.substring(0, left.length - 1) : left return right.replaceAll('\\"', '"').replaceAll('\\r', '').replaceAll('\\n', '') }) } const getStyleParams = (dataStr: string): LabelPrintStyleParam => { const isNumber = (value: string): boolean => { return /^[0-9]+.?[0-9]*/.test(value) } const params = getParams(dataStr) const id = isNumber(params[0]) ? Number(params[0]) : params[0] const name = params[1] const value = isNumber(params[2]) ? Number(params[2]) : params[2] return [id, name, value] } const labelTemplate: LabelTemplate = { tempTop: new LabelNumber(0, 297), tempLeft: new LabelNumber(0, 210), tempWidth: new LabelNumber(0, 210), tempHeight: new LabelNumber(0, 297), labelTexts: [], labelHtmls: [], labelImages: [], labelTables: [], labelBarCodes: [], labelRects: [], labelEllipses: [], labelShapes: [], labelLines: [] } const value = decode(templateContent) const tempDatas = value.split('LODOP') const exprs = [LabelCodeType.ADD_RECT, LabelCodeType.ADD_ELLIPSE, LabelCodeType.ADD_LINE] const initData = tempDatas.find(data => data.includes(LabelCodeType.INITA))! const initParams = getParams(initData) const tempWidth = new LabelNumber(initParams[2]) const tempHeight = new LabelNumber(initParams[3]) labelTemplate.tempTop = new LabelNumber(initParams[0]) labelTemplate.tempLeft = new LabelNumber(initParams[1]) labelTemplate.tempWidth = tempWidth labelTemplate.tempHeight = tempHeight for (let i = 0; i < tempDatas.length; i++) { const data = tempDatas[i] let j = i + 1 const params = getParams(data) // 添加文本 if (data.includes(LabelCodeType.ADD_TEXT)) { const styles: LabelPrintStyleParam[] = [] while (tempDatas[j] && tempDatas[j].includes(LabelCodeType.SET_STYLE)) { const param = getStyleParams(tempDatas[j]) styles.push(param) j++ } const labelText: LabelText = data.includes(LabelCodeType.ADD_TEXTA) ? { fieldName: params[0], top: new LabelNumber(params[1], tempHeight.number), left: new LabelNumber(params[2], tempWidth.number), width: new LabelNumber(params[3], tempWidth.number), height: new LabelNumber(params[4], tempHeight.number), content: params[5], styles } : { top: new LabelNumber(params[0], tempHeight.number), left: new LabelNumber(params[1], tempWidth.number), width: new LabelNumber(params[2], tempWidth.number), height: new LabelNumber(params[3], tempHeight.number), content: params[4], styles } labelTemplate.labelTexts.push(labelText) } // 添加富文本和图片 if (data.includes(LabelCodeType.ADD_HTML)) { const styles: LabelPrintStyleParam[] = [] while (tempDatas[j] && tempDatas[j].includes(LabelCodeType.SET_STYLE)) { const param = getStyleParams(tempDatas[j]) styles.push(param) j++ } const fieldName = styles.find(([_id, name]) => name === 'ItemName')?.[2] as string | undefined const labelHtml: LabelHtml = { top: new LabelNumber(params[0], tempHeight.number), left: new LabelNumber(params[1], tempWidth.number), width: new LabelNumber(params[2], tempWidth.number), height: new LabelNumber(params[3], tempHeight.number), content: params[4], fieldName, styles } labelTemplate.labelHtmls.push(labelHtml) } // 添加图片 if (data.includes(LabelCodeType.ADD_IMAGE)) { const styles: LabelPrintStyleParam[] = [] while (tempDatas[j] && tempDatas[j].includes(LabelCodeType.SET_STYLE)) { const param = getStyleParams(tempDatas[j]) styles.push(param) j++ } const fieldName = styles.find(([_id, name]) => name === 'ItemName')?.[2] as string | undefined const labelImage: LabelImage = { top: new LabelNumber(params[0], tempHeight.number), left: new LabelNumber(params[1], tempWidth.number), width: new LabelNumber(params[2], tempWidth.number), height: new LabelNumber(params[3], tempHeight.number), url: params.slice(4).join(), fieldName, styles } labelTemplate.labelImages.push(labelImage) } // 添加表格 if (data.includes(LabelCodeType.ADD_TABLE)) { const styles: LabelPrintStyleParam[] = [] while (tempDatas[j] && tempDatas[j].includes(LabelCodeType.SET_STYLE)) { const param = getStyleParams(tempDatas[j]) styles.push(param) j++ } const fieldName = styles.find(([_id, name]) => name === 'ItemName')?.[2] as string | undefined const labelTable: LabelTable = { top: new LabelNumber(params[0], tempHeight.number), left: new LabelNumber(params[1], tempWidth.number), width: new LabelNumber(params[2], tempWidth.number), height: new LabelNumber(params[3], tempHeight.number), content: params.slice(4).join(), fieldName, styles } labelTemplate.labelTables.push(labelTable) } // 添加条码 if (data.includes(LabelCodeType.ADD_BARCODE)) { const styles: LabelPrintStyleParam[] = [] while (tempDatas[j] && tempDatas[j].includes(LabelCodeType.SET_STYLE)) { const param = getStyleParams(tempDatas[j]) styles.push(param) j++ } const labelBarCode: LabelBarCode = data.includes(LabelCodeType.ADD_BARCODEA) ? { fieldName: params[0], top: new LabelNumber(params[1], tempHeight.number), left: new LabelNumber(params[2], tempWidth.number), width: new LabelNumber(params[3], tempWidth.number), height: new LabelNumber(params[4], tempHeight.number), codeType: params[5], codeValue: params[6], styles } : { top: new LabelNumber(params[0], tempHeight.number), left: new LabelNumber(params[1], tempWidth.number), width: new LabelNumber(params[2], tempWidth.number), height: new LabelNumber(params[3], tempHeight.number), codeType: params[4], codeValue: params[5], styles } labelTemplate.labelBarCodes.push(labelBarCode) } // 添加其它图形 if (data.includes(LabelCodeType.ADD_SHAPE)) { const labelShape: LabelShape = { shapeType: Number(params[0]), top: new LabelNumber(params[1], tempHeight.number), left: new LabelNumber(params[2], tempWidth.number), width: new LabelNumber(params[3], tempWidth.number), height: new LabelNumber(params[4], tempHeight.number), lineStyle: Number(params[5]), lineWidth: Number(params[6]), fillColor: params[7] } labelTemplate.labelShapes.push(labelShape) } // 添加图形 const expr = exprs.find(expr => data.includes(expr)) if (expr) { const label: LabelLine = { top: new LabelNumber(params[0], tempHeight.number), left: new LabelNumber(params[1], tempWidth.number), width: new LabelNumber(params[2], tempWidth.number), height: new LabelNumber(params[3], tempHeight.number), lineStyle: Number(params[4]), lineWidth: Number(params[5]) } switch (expr) { case LabelCodeType.ADD_RECT: labelTemplate.labelRects.push(label) break case LabelCodeType.ADD_ELLIPSE: labelTemplate.labelEllipses.push(label) break case LabelCodeType.ADD_LINE: labelTemplate.labelLines.push(label) break default: break } } } return labelTemplate } // 设置模板内标签的数据,一页放一个模板 export const setLabelTemplateData = (labelTemplate: LabelTemplate, printData: any[], baseUrl?: string, tableColumn?: TableColumn): LabelTemplate[][] => { const { labelTexts, labelHtmls, labelImages, labelBarCodes, labelTables } = labelTemplate const labelDatas: LabelTemplate[][] = [] for (let i = 0; i < printData.length; i++) { const tempTexts: LabelText[] = [] const tempHtmls: LabelHtml[] = [] const tempImages: LabelImage[] = [] const tempTables: LabelTable[] = [] const tempBarCodes: LabelBarCode[] = [] const labelData = printData[i] const fields = Object.keys(labelData) labelTexts.forEach(text => { let content = text.content const field = fields.find(field => field === text.fieldName) if (field) { const data = labelData[field] if (data) { if (content.includes(`[${field}]`)) { content = content.replaceAll(`[${field}]`, data) } else { content = data } } } tempTexts.push({ ...text, content }) }) labelHtmls.forEach(html => { let content = html.content const field = fields.find(field => field === html.fieldName) if (field) { const data = labelData[field] if (data) { const info = data.info if (info) { const url = baseUrl ? (baseUrl + info[0].addr) : info[0].addr content = `<img style="width:100%" src=${url} alt="" />` } else if (typeof data === 'string') { content = data.replaceAll('text-decoration-line', 'text-decoration') } else { content = data } } } tempHtmls.push({ ...html, content }) }) labelImages.forEach(image => { let url = image.url const field = fields.find(field => field === image.fieldName) if (field) { const data = labelData[field] if (data) { url = `<img style="width:100%" src=${data} alt="" />` } } tempImages.push({ ...image, url }) }) labelTables.forEach(table => { let content = table.content const field = fields.find(field => field === table.fieldName) if (field) { const data = labelData[field] if (typeof data !== 'string' && tableColumn) { content = buildTableData(tableColumn[field], data) } } tempTables.push({ ...table, content }) }) labelBarCodes.forEach(barCode => { let codeValue = barCode.codeValue const field = fields.find(field => field === barCode.fieldName) if (field) { const data = labelData[field] if (data) { codeValue = data } } tempBarCodes.push({ ...barCode, codeValue }) }) labelDatas.push([ { ...labelTemplate, labelTexts: tempTexts, labelHtmls: tempHtmls, labelTables: tempTables, labelBarCodes: tempBarCodes, } ]) } return labelDatas } // 设置模板内标签的数据,一页放多个模板 export const setLabelTemplateDataWithArrange = (labelTemplate: LabelTemplate, printData: any[], printerParam: PrinterParam, countOfPage: number, countOfColumn: number, baseUrl?: string): LabelTemplate[][] => { const labelCount = printData.length const { tempWidth, tempHeight, labelTexts, labelHtmls, labelImages, labelBarCodes, labelRects, labelEllipses, labelLines, labelShapes } = labelTemplate const { colSpacing, rowSpacing } = printerParam const pageParams: LabelPageParam[] = [] for (let i = 0; i < labelCount; i++) { const labelData = printData[i] const tempTexts: LabelText[] = [] const tempHtmls: LabelHtml[] = [] const tempImages: LabelImage[] = [] const tempBarCodes: LabelBarCode[] = [] const tempShapes: LabelShape[] = [] const tempRects: LabelRect[] = [] const tempEllipses: LabelEllipse[] = [] const tempLines: LabelLine[] = [] const pageIndex = Math.floor(i / countOfPage) const column = i % countOfColumn const row = Math.floor(i % countOfPage / countOfColumn) const left = tempWidth.number * column + column * colSpacing const top = tempHeight.number * row + row * rowSpacing const fields = Object.keys(labelData) labelTexts.forEach(text => { let content = text.content const field = fields.find(field => field === text.fieldName) if (field) { const data = labelData[field] if (data) { if (content.includes(`[${field}]`)) { content = content.replaceAll(`[${field}]`, data) } else { content = data } } } const textLeft = new LabelNumber(left + text.left.number) const textTop = new LabelNumber(top + text.top.number) tempTexts.push({ ...text, content, left: textLeft, top: textTop }) }) labelHtmls.forEach(html => { let content = html.content const field = fields.find(field => field === html.fieldName) if (field) { const data = labelData[field] if (data) { const info = data.info if (info) { const url = baseUrl ? (baseUrl + info[0].addr) : info[0].addr content = `<img style="width:100%" src=${url} alt="" />` } else if (typeof data === 'string') { content = data.replaceAll('text-decoration-line', 'text-decoration') } else { content = data } } } const htmlLeft = new LabelNumber(left + html.left.number) const htmlTop = new LabelNumber(top + html.top.number) tempHtmls.push({ ...html, content, left: htmlLeft, top: htmlTop }) }) labelImages.forEach(image => { let url = image.url const field = fields.find(field => field === image.fieldName) if (field) { const data = labelData[field] if (url) { url = `<img style="width:100%" src=${data} alt="" />` } } const imageLeft = new LabelNumber(left + image.left.number) const imageTop = new LabelNumber(top + image.top.number) tempImages.push({ ...image, url, left: imageLeft, top: imageTop }) }) labelBarCodes.forEach(barCode => { let codeValue = barCode.codeValue const field = fields.find(field => field === barCode.fieldName) if (field) { const data = labelData[field] if (data) { codeValue = data } } const barCodeLeft = new LabelNumber(left + barCode.left.number) const barCodeTop = new LabelNumber(top + barCode.top.number) tempBarCodes.push({ ...barCode, codeValue, left: barCodeLeft, top: barCodeTop }) }) labelShapes.forEach(shape => { const shapeLeft = new LabelNumber(left + shape.left.number) const shapeTop = new LabelNumber(top + shape.top.number) tempShapes.push({ ...shape, left: shapeLeft, top: shapeTop }) }) labelEllipses.forEach(ellipse => { const ellipseLeft = new LabelNumber(left + ellipse.left.number) const ellipseTop = new LabelNumber(top + ellipse.top.number) tempEllipses.push({ ...ellipse, left: ellipseLeft, top: ellipseTop }) }) labelRects.forEach(rect => { const rectLeft = new LabelNumber(left + rect.left.number) const rectTop = new LabelNumber(top + rect.top.number) tempRects.push({ ...rect, left: rectLeft, top: rectTop }) }) labelLines.forEach(line => { const lineLeft = new LabelNumber(left + line.left.number) const lineTop = new LabelNumber(top + line.top.number) tempLines.push({ ...line, left: lineLeft, top: lineTop }) }) pageParams.push([pageIndex, { ...labelTemplate, tempTop: new LabelNumber(top), tempLeft: new LabelNumber(left), labelTexts: tempTexts, labelHtmls: tempHtmls, labelBarCodes: tempBarCodes, labelShapes: tempShapes, labelEllipses: tempEllipses, labelRects: tempRects, labelLines: tempLines }]) } const pageIndexs = Array.from(new Set(pageParams.map(rect => rect[0]))) const labelDatas: LabelTemplate[][] = [] for (let i = 0; i < pageIndexs.length; i++) { const pageIndex = pageIndexs[i] const tempDatas: LabelTemplate[] = [] for (let j = 0; j < pageParams.length; j++) { const pageParam = pageParams[j]; const pageTemplate = pageParam[1] if (pageParam[0] === pageIndex) { tempDatas.push(pageTemplate) } } labelDatas.push(tempDatas) } return labelDatas } const buildTableData = (columnInfo: ColumnInfo, rowDatas: any[]) => { const { columns, statistics } = columnInfo columns.forEach(column => { const stastic = statistics?.find(stastic => stastic.field === column.name) column.statistics = stastic?.property }) const div = document.createElement('div') const table = document.createElement('table') table.setAttribute('border', '1') table.setAttribute('cellSpacing', '0') table.setAttribute('width', '100%') table.setAttribute('style', 'border-collapse:collapse') table.setAttribute('bordercolor', '#333333') const thead = document.createElement('thead') const tr = document.createElement('tr') for (let i = 0; i < columns.length; i++) { const th = document.createElement('th') const column = columns[i] th.textContent = column.label tr.appendChild(th) } thead.appendChild(tr) table.appendChild(thead) const tbody = document.createElement('tbody') for (let i = 0; i < rowDatas.length; i++) { const row = rowDatas[i] const tr = document.createElement('tr') for (let j = 0; j < columns.length; j++) { const td = document.createElement('td') const column = columns[j] td.textContent = row[column.name] tr.appendChild(td) } tbody.appendChild(tr) } table.appendChild(tbody) if (statistics) { const tfoot = document.createElement('tfoot') const maxRow = statistics.map(item => item.property.length).sort((a, b) => b - a)?.[0] ?? 0 for (let i = 0; i < maxRow; i++) { const tr = document.createElement('tr') for (let j = 0; j < columns.length; j++) { const column = columns[j] const statistic = column.statistics?.[i] const td = document.createElement('td') if (statistic) { td.textContent = statistic.label td.setAttribute('format', statistic.format) td.setAttribute('tdata', statistic.tdata) } tr.appendChild(td) } tfoot.appendChild(tr) } table.appendChild(tfoot) } div.appendChild(table) return div.innerHTML } export const buildTableHtml = (tableStyle: OptionValues & { tableWidth: number }, tableColumns: ColumnDataType[], tableHeadRows: any[], tableData: any[], range: [number, number], isLastTask: boolean) => { const [start, end] = range const showColumns = tableColumns.filter(column => column.printType != 'none' && column.width != 0 && column.width != undefined) let width = 0 let idx = showColumns.length for (let i = 0; i < showColumns.length; i++) { const column = showColumns[i] width += column.width! if (width > tableStyle.tableWidth) { idx = i break } } const columns = showColumns.slice(0, idx) const hasStatistic = columns.some(column => column.statistic != 'none') const wrap = document.createElement('div') const div = document.createElement('div') div.setAttribute('style', `text-align: center; overflow: hidden`) const table = document.createElement('table') table.setAttribute('border', tableStyle.lineWidth.toString()) table.setAttribute('cellSpacing', '0') table.setAttribute('style', `font-size: 13px; width: ${width}px; border-collapse:collapse; margin: 0 auto; border: ${tableStyle.borderWidth}px solid; table-layout: fixed;`) table.setAttribute('bordercolor', '#333333') const colgroup = document.createElement('colgroup') columns.forEach(column => { const col = document.createElement('col') if (column.width) { col.style.setProperty('width', `${column.width * 3.78}px`) } colgroup.appendChild(col) }) table.appendChild(colgroup) const thead = document.createElement('thead') thead.setAttribute('style', 'display: table-header-group') for (let i = 0; i < tableHeadRows.length; i++) { const headRow = tableHeadRows[i] const tr = document.createElement('tr') headRow.forEach((item: any) => { const temp = item.rowspan == tableHeadRows.length - i const th = document.createElement('th') th.textContent = temp ? item.column.label : item.label th.setAttribute('colspan', item.colspan.toString()) th.setAttribute('rowspan', item.rowspan.toString()) tr.appendChild(th) }) thead.appendChild(tr) } table.appendChild(thead) const sortColumnNames = flatMap(columns ?? [], column => column.sort != 'none' ? { name: column.name, func: column.sort } : []) const tbody = document.createElement('tbody') const data = sortArray(tableData.slice(start, end), sortColumnNames) for (let i = 0; i < data.length; i++) { const row = data[i] const tr = document.createElement('tr') for (let j = 0; j < columns.length; j++) { const td = document.createElement('td') const column = columns[j] const value = getCellValue(row[column.name], column) td.textContent = value td.setAttribute('style', `white-space: pre-line; word-wrap: break-word; text-align: ${column.align || 'left'}; padding: ${tableStyle.rowPadding * 3.78}px ${tableStyle.colPadding * 3.78}px ; `) tr.appendChild(td) } tbody.appendChild(tr) } const dataTypeArr = ['number', 'static-number', 'input-number', 'progress', 'static-progress'] if (isLastTask && !tableStyle.countAllPage && hasStatistic) { const tr = document.createElement('tr') for (let j = 0; j < columns.length; j++) { const td = document.createElement('td') if (j == 0) { td.textContent = '合计:' } const column = columns[j] if (column.statistic == 'Sum') { if (dataTypeArr.includes(column.type) || column.pristine.isNumerical) { const value = calcFn('sum', column.name, tableData) td.textContent = getCellValue(value, column) } else { const value = data.filter(item => item[column.name]).length td.textContent = value.toString() } td.setAttribute('style', `white-space: pre-line; word-wrap: break-word; text-align: ${column.align || 'left'}`) } tr.appendChild(td) } tbody.appendChild(tr) } table.appendChild(tbody) if (tableStyle.countAllPage && hasStatistic) { const tfoot = document.createElement('tfoot') const tr = document.createElement('tr') columns.forEach((column, index) => { const td = document.createElement('td') if (index == 0) { td.textContent = '合计:' } if (column.statistic == 'Sum') { if (dataTypeArr.includes(column.type) || column.pristine.isNumerical) { const value = calcFn('sum', column.name, tableData) td.textContent = getCellValue(value, column) } else { const value = data.filter(item => item[column.name]).length td.textContent = value.toString() } td.setAttribute('style', `white-space: pre-line; word-wrap: break-word; text-align: ${column.align || 'left'}`) } tr.appendChild(td) }) tfoot.appendChild(tr) table.append(tfoot) } div.appendChild(table) wrap.appendChild(div) return wrap.innerHTML } const sortArray = (datas: any[], columns: { name: string, func: 'asc' | 'desc' }[]) => { if (columns.length > 0) { const column = columns.pop() if (column) { const name = column.name const func = column.func datas = datas.sort((a, b) => { const valueA = a[name] const valueB = b[name] return sortFn(valueA, valueB, func) }) sortArray(datas, columns) } } return datas }