UReport2 多报表文件打印,ZIP下载实现

2023-05-16

项目中报表较多,客户要求多报表 zip下载或打印,查看ureport内部代码实现,代码相对简单,直接上代码。
实现了多文件混合zip下载,基于浏览器的打印和Lodop打印插件两种方式。

Java代码


package org.plugin.ureport.controller;

import com.bstek.ureport.build.Context;
import com.bstek.ureport.build.ReportBuilder;
import com.bstek.ureport.build.paging.Page;
import com.bstek.ureport.cache.CacheUtils;
import com.bstek.ureport.chart.ChartData;
import com.bstek.ureport.definition.ReportDefinition;
import com.bstek.ureport.exception.ReportComputeException;
import com.bstek.ureport.export.ExportManager;
import com.bstek.ureport.export.FullPageData;
import com.bstek.ureport.export.PageBuilder;
import com.bstek.ureport.export.ReportRender;
import com.bstek.ureport.export.excel.high.builder.ExcelBuilderDirect;
import com.bstek.ureport.export.html.HtmlProducer;
import com.bstek.ureport.model.Report;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.plugin.iot.utils.StringUtils;
import org.springblade.plugin.iot.utils.UreportPrintUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * Ureprot2 报表下载  控制器
 *
 * @author smile
 */
@RestController
@AllArgsConstructor
@RequestMapping("/plugin/ureport")
@Api(value = "报表下载", tags = "Ureprot2报表下载")
public class UreportPrintController extends BaseController {

	private final ReportRender reportRender;
	private final ReportBuilder reportBuilder;

	private final ExportManager exportManager;

	/**
	 * 导出多个报表的HTML格式数据,供前端打印使用
	 *
	 * @return
	 */
	@PostMapping("/print")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "打印", notes = "扩展ureport2功能,实现多报表HTML打印和下载")
	public R loadPrintHtml(HttpServletRequest req) {
		//获取 报表参数
		Map<String, Object> parameters =buildParameters(req);
		//最终返回的集合
		List<Map> printList = new ArrayList<>();
		HtmlProducer htmlProducer = new HtmlProducer();
		//获取所有的报表文件名称(逗号隔开)
		String name = req.getParameter("_u");


		if (StringUtils.isBlank(name)) {
			throw new ReportComputeException("请选择报表文件!");
		}
		try {
			//逗号隔开的多个表名
			String[] files = name.split(",");

			for (String fileName : files) {
				ReportDefinition reportDefinition = reportRender.getReportDefinition(fileName);
				//关键方法
				Report report = reportBuilder.buildReport(reportDefinition, parameters);
				Map<String, ChartData> chartMap = report.getContext().getChartDataMap();
				if (chartMap.size() > 0) {
					CacheUtils.storeChartDataMap(chartMap);
				}
				FullPageData pageData = PageBuilder.buildFullPageData(report);
				StringBuilder sb = new StringBuilder();
				List<List<Page>> list = pageData.getPageList();
				Context context = report.getContext();
				if (list.size() > 0) {
					for (int i = 0; i < list.size(); i++) {
						List<Page> columnPages = list.get(i);
						if (i == 0) {
							String html = htmlProducer.produce(context, columnPages, pageData.getColumnMargin(), false);
							sb.append(html);
						} else {
							String html = htmlProducer.produce(context, columnPages, pageData.getColumnMargin(), false);
							sb.append(html);
						}
					}
				} else {
					List<Page> pages = report.getPages();
					for (int i = 0; i < pages.size(); i++) {
						Page page = pages.get(i);
						if (i == 0) {
							String html = htmlProducer.produce(context, page, false);
							sb.append(html);
						} else {
							String html = htmlProducer.produce(context, page, true);
							sb.append(html);
						}
					}
				}
				//获取拼接完成的HTML对象
				Map<String, Object> map = new HashMap<>(5);
				map.put("html", sb.toString());
				map.put("style", reportDefinition.getStyle());
				map.put("paper", report.getPaper());
				//添加到集合中
				printList.add(map);
			}

		} catch (Exception e) {
			throw new ReportComputeException("加载失败,可能已被删除或数据不正确!");
		}
		return R.data(printList);
	}

	/**
	 * 导出多个报表的zip压缩包,单文件为 excel格式
	 * 也可扩展为pdf等其他ureport2所支持的格式文件
	 *
	 * @return
	 */
	@GetMapping("/excel")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "导出excel", notes = "传入参数")
	public void reportToExcel(HttpServletRequest req, HttpServletResponse resp) {
		Map<String, Object> parameters =buildParameters(req);
		//多个报表文件名称(逗号隔开)
		String name = req.getParameter("_u");
		//报表文件对应的 自定义文件名
		String fileName = req.getParameter("_n");
		//最终压缩包 的文件名称
		String zipName = req.getParameter("_z");
		if (StringUtils.isBlank(name)) {
			throw new ReportComputeException("请选择报表文件!");
		}
		OutputStream outputStream = null;
		try {
			outputStream = resp.getOutputStream();
			String[] files = name.split(",");
			String[] fileNames = fileName.split(",");
			//zip压缩包
			File zipFile = File.createTempFile("temp-report", ".zip");
			ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
			byte[] buf = new byte[1024];
			int j = 0;
			for (String file : files) {
				//同打印逻辑,获取到参数和对应报表,调用对应的ureport2的实现方法
				ReportDefinition reportDefinition = reportRender.getReportDefinition(file);
				Report report = reportBuilder.buildReport(reportDefinition, parameters);

				String encoding = System.getProperty("file.encoding");
				File tempFile = File.createTempFile("temp-excel", ".xls");
				FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
				ExcelBuilderDirect excelBuilderDirect = new ExcelBuilderDirect();
				excelBuilderDirect.build(report, fileOutputStream);
				fileName=buildDownloadFileName(file, fileNames[j++], ".xls");
				zipOut.putNextEntry(new ZipEntry(fileName));
				FileInputStream in = new FileInputStream(tempFile);
				int len;
				while ((len = in.read(buf)) > 0) {
					zipOut.write(buf, 0, len);
				}
				zipOut.closeEntry();
				in.close();
			}
			zipName=buildDownloadFileName("报表数据", zipName, ".zip");
			resp.setContentType("application/octet-stream;charset=ISO8859-1");
			zipName=new String(zipName.getBytes("UTF-8"),"ISO8859-1");
			resp.setHeader("Content-Disposition","attachment;filename=\"" + zipName + "\"");

			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipFile));
			int i = bis.read(buf);
			while (i != -1) {
				outputStream.write(buf, 0, buf.length);
				outputStream.flush();
				i = bis.read(buf);
			}
		} catch (Exception e) {
			throw new ReportComputeException("加载失败,可能已被删除或数据不正确!");
		} finally {
			try {
				outputStream.flush();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}


	protected String buildDownloadFileName(String reportFileName, String fileName, String extName) {
		if (StringUtils.isNotBlank(fileName)) {
			if (!fileName.toLowerCase().endsWith(extName)) {
				fileName = fileName + extName;
			}
			return fileName;
		} else {
			int pos = reportFileName.indexOf(":");
			if (pos > 0) {
				reportFileName = reportFileName.substring(pos + 1, reportFileName.length());
			}
			pos = reportFileName.toLowerCase().indexOf(".ureport.xml");
			if (pos > 0) {
				reportFileName = reportFileName.substring(0, pos);
			}
			return "ureport-" + reportFileName + extName;
		}
	}


	protected Map<String, Object> buildParameters(HttpServletRequest req) {
		Map<String,Object> parameters=new HashMap<String,Object>();
		Enumeration<?> enumeration=req.getParameterNames();
		while(enumeration.hasMoreElements()){
			Object obj=enumeration.nextElement();
			if(obj==null){
				continue;
			}
			String name=obj.toString();
			String value=req.getParameter(name);
			if(name==null || value==null || name.startsWith("_")){
				continue;
			}
			parameters.put(name, value);
		}
		return parameters;
	}


}

JavaScript代码

import request from '@/router/axios';
import {pointToMM} from "@/util/ureport/utils";
import {Message} from "element-ui";
import {getLodop} from "@/util/ureport/lodopFuncs";
import { Loading } from 'element-ui';

/**
 *
 *  使用方式如下
 *
 *  下载zip压缩包,打开新窗口 直接下载
 window.open(`/api/iot/ureport/excel?_u=设备统计.ureport.xml,物品领用.ureport.xml&_n=设备统计,物品领用表&_z=统计表zip&token=${getToken()}`);


打印两种方式,
 *   使用浏览器打开新窗口,调用window.print打印,只支持单文件
 printByBrowser({
          _u:"使用情况表.ureport.xml",
          startTime: `${parseTime(Date.now(), '{y}-{m}-{d}') + ' 00:00:00'}`,
          endTime: `${parseTime(Date.now(), '{y}-{m}-{d}') + ' 23:59:59'}`,
          _n: `${dateFormat(new Date(), "yyyy年M月dd日 ") + " 的使用记录"}`
      });

 * 使用lodop打印插件进行打印,支持多个报表文件
 printByLodop({
          _u:"运行状况统计.ureport.xml,使用情况表.ureport.xml",
          startTime: `${parseTime(Date.now(), '{y}-{m}-{d}') + ' 00:00:00'}`,
          endTime: `${parseTime(Date.now(), '{y}-{m}-{d}') + ' 23:59:59'}`,
      });

 */

/**
 *  报表导出为excle
 *  因CSS样式原因,此方式只能打一个报表
 * @param param
 */
export function exportToExcel(param) {

  request({
    url: "/api/iot/ureport/excel",
    method: 'get',
    params: {
      ...param,
    }
  }).then(res => {
    console.log(res)
    let filename = "test.xls"
    const content = res.data
    const blob = new Blob([content])
    if ('download' in document.createElement('a')) {
      const elink = document.createElement('a')
      if (filename) elink.download = filename
      elink.style.display = 'none'
      elink.href = URL.createObjectURL(blob)
      document.body.appendChild(elink)
      elink.click()
      URL.revokeObjectURL(elink.href)
      document.body.removeChild(elink)
    } else {
      navigator.msSaveBlob(blob, filename)
    }
  })

}


/**
 *  报表打印 使用Lodop插件  支持多报表同时打印
 *  客户端必须安装lodop插件
 * @param category
 * @returns {string}
 */
export function printByLodop(param) {
  let loadingInstance = Loading.service({ fullscreen: true });
  request({
    url: "/api/iot/ureport/print",
    method: 'post',
    params: {
      ...param,
    }
  }).then(res => {
    if (res.data.success) {
      let report = res.data.data;
      let lodop = getLodop()//调用getLodop获取LODOP对象
      lodop.PRINT_INIT("reportPrint")
      // 隐藏预览窗口上的缩放比例选项
      // lodop.SET_SHOW_MODE("HIDE_PAGE_PERCENT",true);
      //宽高自适应当前页
      lodop.SET_PRINT_MODE("FULL_WIDTH_FOR_OVERFLOW",true);
      // lodop.SET_PRINT_MODE("FULL_HEIGHT_FOR_OVERFLOW",true);
      report.forEach(file =>{
        let printStr="";
        let styles = `<style type="text/css">`;
        styles += buildPrintStyle(file.paper);
        styles += file.style;
        styles += `</style>`;
        printStr += `${styles}${file.html}`
        // LODOP.NewPageA()的区别,如果前面打印项自动分页不止一页,如果想要后面的页不重叠分页后的内容,应该用LODOP.NewPageA()。
        lodop.NewPageA();
        // lodop.NEWPAGE();
        lodop.ADD_PRINT_HTM("5mm","5mm","100%","100%",printStr)
      })

      lodop.PREVIEW()
      loadingInstance.close();
    }else{
      Message({
        message: "获取数据发生意外,请重试!",
        type: 'error'
      });
    }
  })
}


/**
 *  报表打印-使用浏览器打印
 *  因CSS样式原因,此方式只能打一个报表
 * @param param
 */
export function printByBrowser(param) {

  request({
    url: "/api/iot/ureport/print",
    method: 'post',
    params: {
      ...param,
    }
  }).then(res => {
    if (res.data.success) {
      let report = res.data.data[0];
      let styles = `<style type="text/css">`;
      styles += buildPrintStyle(report.paper);
      styles += report.style;
      styles += `</style>`;
      let printStr = `<html><head><title>文件打印-${website.title}</title></head>${styles}${report.html}</html>`
      //打开新页面
      let pwin = window.open("_blank");
      pwin.document.write(printStr);
      pwin.document.close();
      pwin.focus();
      setTimeout(() => {
        pwin.print();
        pwin.close();
      }, 10);
    }else{
      Message({
        message: "获取数据发生意外,请重试!",
        type: 'error'
      });
    }

  })

}

/**
 * 构建样式
 * @param paper
 * @returns {string}
 */
function buildPrintStyle(paper) {
  const marginLeft = pointToMM(paper.leftMargin);
  const marginTop = pointToMM(paper.topMargin);
  const marginRight = pointToMM(paper.rightMargin);
  const marginBottom = pointToMM(paper.bottomMargin);
  const paperType = paper.paperType;
  let page = paperType;
  if (paperType === 'CUSTOM') {
    page = pointToMM(paper.width) + 'mm ' + pointToMM(paper.height) + 'mm';
  }
  const style = `
        @media print {
            .page-break{
                display: block;
                page-break-before: always;
            }
        }
        @page {
          size: ${page} ${paper.orientation};
          margin-left: ${marginLeft}mm;
          margin-top: ${marginTop}mm;
          margin-right:${marginRight}mm;
          margin-bottom:${marginBottom}mm;
        }
    `;
  return style;
}

ureport2 utils

export function resetTableData(hot){
    const countCols=hot.countCols(),countRows=hot.countRows(),context=hot.context,data=[];
    for(let i=0;i<countRows;i++){
        let rowData=[];
        for(let j=0;j<countCols;j++){
            let td=hot.getCell(i,j);
            if(!td){
                rowData.push("");
                continue;
            }
            let cellDef=context.getCell(i,j);
            if(cellDef){
                let valueType=cellDef.value.type,value=cellDef.value;
                if(valueType==='dataset'){
                    let text=value.datasetName+"."+value.aggregate+"(";
                    let prop=value.property;
                    if(prop.length>13){
                        text+=prop.substring(0,10)+'..)';
                    }else{
                        text+=prop+")";
                    }
                    rowData.push(text);
                }else if(valueType==='expression'){
                    let v=value.value || '';
                    if(v.length>16){
                        v=v.substring(0,13)+'...';
                    }
                    rowData.push(v);
                }else{
                    rowData.push(value.value || "");
                }
            }else{
                rowData.push("");
            }
        }
        data.push(rowData);
    }
    hot.loadData(data);
};

export function buildNewCellDef(rowNumber,columnNumber){
    let cellDef = {rowNumber,columnNumber,expand: 'None', cellStyle: {fontSize:9,forecolor:'0,0,0',fontFamily:'宋体',align:'center',valign:'middle'}, value: {type: 'simple', value: ''}};
    return cellDef;
};

export function tableToXml(context){
    const hot=context.hot;
    const countRows=hot.countRows(),countCols=hot.countCols();
    let xml=`<?xml version="1.0" encoding="UTF-8"?><ureport>`;
    let rowsXml='',columnXml='';
    const rowHeaders=context.rowHeaders;
    for(let i=0;i<countRows;i++){
        let height=hot.getRowHeight(i) || 16;
        height=pixelToPoint(height);
        let band=null;
        for(let header of rowHeaders){
            if(header.rowNumber===i){
                band=header.band;
                break;
            }
        }
        if(band){
            rowsXml+=`<row row-number="${i+1}" height="${height}" band="${band}"/>`;
        }else{
            rowsXml+=`<row row-number="${i+1}" height="${height}"/>`;
        }
    }
    for(let i=0;i<countCols;i++){
        let width=hot.getColWidth(i) || 30;
        width=pixelToPoint(width);
        columnXml+=`<column col-number="${i+1}" width="${width}"/>`;
    }
    let cellXml='',spanData=[];
    for(let i=0;i<countRows;i++){
        for(let j=0;j<countCols;j++){
            if(spanData.indexOf(i+","+j)>-1){
                continue;
            }
            let cellDef=context.getCell(i,j);
            if(!cellDef){
                continue;
            }
            let cellName=context.getCellName(i,j);
            cellXml+=`<cell expand="${cellDef.expand}" name="${cellName}" row="${(i+1)}" col="${(j+1)}"`;
            if(cellDef.leftParentCellName && cellDef.leftParentCellName!==''){
                cellXml+=` left-cell="${cellDef.leftParentCellName}"`;
            }
            if(cellDef.topParentCellName && cellDef.topParentCellName!==''){
                cellXml+=` top-cell="${cellDef.topParentCellName}"`;
            }
            if(cellDef.fillBlankRows){
                cellXml+=` fill-blank-rows="${cellDef.fillBlankRows}"`;
                if(cellDef.multiple){
                    cellXml+=` multiple="${cellDef.multiple}"`;
                }
            }

            const span=getSpan(hot,i,j);
            let rowSpan=span.rowspan,colSpan=span.colspan;
            let startRow=i,endRow=i+rowSpan-1,startCol=j,endCol=j+colSpan-1;
            for(let r=startRow;r<=endRow;r++){
                for(let c=startCol;c<=endCol;c++){
                    spanData.push(r+","+c);
                }
            }
            if(rowSpan>1){
                cellXml+=` row-span="${rowSpan}"`;
            }
            if(colSpan>1){
                cellXml+=` col-span="${colSpan}"`;
            }

            if(cellDef.linkUrl && cellDef.linkUrl!==''){
                cellXml+=` link-url="${cellDef.linkUrl}"`;
            }
            if(cellDef.linkTargetWindow && cellDef.linkTargetWindow!==''){
                cellXml+=` link-target-window="${cellDef.linkTargetWindow}"`;
            }

            cellXml+='>';
            let cellStyle=cellDef.cellStyle;
            cellXml+=buildCellStyle(cellStyle);
            if(cellDef.linkParameters && cellDef.linkParameters.length>0){
                for(let param of cellDef.linkParameters){
                    cellXml+=`<link-parameter name="${param.name}">`;
                    cellXml+=`<value><![CDATA[${param.value}]]></value>`;
                    cellXml+=`</link-parameter>`;
                }
            }
            const value=cellDef.value;
            if(value.type==='dataset'){
                let msg=null;
                if(!value.datasetName){
                    msg=`${cellName}单元格数据集属性不能为空!`;
                }
                if(!msg && !value.property){
                    msg=`${cellName}单元格属性不能为空!`;
                }
                if(!msg && !value.aggregate){
                    msg=`${cellName}单元格聚合方式属性不能为空!`;
                }
                if(msg){
                    console.log(msg);
                    throw msg;
                }
                const mappingType=value.mappingType || 'simple';
                cellXml+=`<dataset-value dataset-name="${encode(value.datasetName)}" aggregate="${value.aggregate}" property="${value.property}" order="${value.order}" mapping-type="${mappingType}"`;
                if(mappingType==='dataset'){
                    cellXml+=` mapping-dataset="${value.mappingDataset}" mapping-key-property="${value.mappingKeyProperty}" mapping-value-property="${value.mappingValueProperty}"`;
                }
                cellXml+='>';
                cellXml+=buildConditions(value.conditions);
                if(value.aggregate==='customgroup'){
                    const groupItems=value.groupItems;
                    for(let groupItem of groupItems){
                        cellXml+=`<group-item name="${groupItem.name}">`;
                        for(let condition of groupItem.conditions){
                            cellXml+=`<condition property="${condition.left}" op="${encode(condition.operation || condition.op)}" id="${condition.id}"`;
                            if(condition.join){
                                cellXml+=` join="${condition.join}">`;
                            }else{
                                cellXml+=`>`;
                            }
                            cellXml+=`<value><![CDATA[${condition.right}]]></value>`;
                            cellXml+=`</condition>`;
                        }
                        cellXml+='</group-item>';
                    }
                }
                if(mappingType==='simple'){
                    const mappingItems=value.mappingItems;
                    if(mappingItems && mappingItems.length>0){
                        for(let mappingItem of mappingItems){
                            cellXml+=`<mapping-item value="${encode(mappingItem.value)}" label="${encode(mappingItem.label)}"/>`;
                        }
                    }
                }
                cellXml+=`</dataset-value>`;
            }else if(value.type==='expression'){
                if(!value.value || value.value===''){
                    const msg=`${cellName}单元格表达式不能为空`;
                    console.log(msg);
                    throw msg;
                }
                cellXml+=`<expression-value>`;
                cellXml+=`<![CDATA[${value.value}]]>`;
                cellXml+=`</expression-value>`;
            }else if(value.type==='simple'){
                cellXml+=`<simple-value>`;
                cellXml+=`<![CDATA[${value.value || ''}]]>`;
                cellXml+=`</simple-value>`;
            }else if(value.type==='image'){
                cellXml+=`<image-value source="${value.source}"`;
                if(value.width){
                    cellXml+=` width="${value.width}"`
                }
                if(value.height){
                    cellXml+=` height="${value.height}"`;
                }
                cellXml+=`>`;
                cellXml+=`<text>`;
                cellXml+=`<![CDATA[${value.value}]]>`;
                cellXml+=`</text>`;
                cellXml+=`</image-value>`;
            }else if(value.type==='zxing'){
                cellXml+=`<zxing-value source="${value.source}" category="${value.category}" width="${value.width}" height="${value.height}"`;
                if(value.format){
                    cellXml+=` format="${value.format}"`;
                }
                cellXml+=`>`;
                cellXml+=`<text>`;
                cellXml+=`<![CDATA[${value.value}]]>`;
                cellXml+=`</text>`;
                cellXml+=`</zxing-value>`;
            }else if(value.type==='slash'){
                cellXml+=`<slash-value>`;
                const slashes=value.slashes;
                for(let slash of slashes){
                    cellXml+=`<slash text="${slash.text}" x="${slash.x}" y="${slash.y}" degree="${slash.degree}"/>`;
                }
                cellXml+=`<base64-data>`;
                cellXml+=`<![CDATA[${value.base64Data}]]>`;
                cellXml+=`</base64-data>`;
                cellXml+=`</slash-value>`;
            }else if(value.type==='chart'){
                cellXml+=`<chart-value>`;
                const chart=value.chart;
                const dataset=chart.dataset;
                cellXml+=`<dataset dataset-name="${dataset.datasetName}" type="${dataset.type}"`;
                if(dataset.categoryProperty){
                    cellXml+=` category-property="${dataset.categoryProperty}"`;
                }
                if(dataset.seriesProperty){
                    cellXml+=` series-property="${dataset.seriesProperty}"`;
                }
                if(dataset.seriesType){
                    cellXml+=` series-type="${dataset.seriesType}"`;
                }
                if(dataset.seriesText){
                    cellXml+=` series-text="${dataset.seriesText}"`;
                }
                if(dataset.valueProperty){
                    cellXml+=` value-property="${dataset.valueProperty}"`;
                }
                if(dataset.rProperty){
                    cellXml+=` r-property="${dataset.rProperty}"`;
                }
                if(dataset.xProperty){
                    cellXml+=` x-property="${dataset.xProperty}"`;
                }
                if(dataset.yProperty){
                    cellXml+=` y-property="${dataset.yProperty}"`;
                }
                if(dataset.collectType){
                    cellXml+=` collect-type="${dataset.collectType}"`;
                }
                cellXml+=`/>`;
                const xaxes=chart.xaxes;
                if(xaxes){
                    cellXml+=`<xaxes`;
                    if(xaxes.rotation){
                        cellXml+=` rotation="${xaxes.rotation}"`;
                    }
                    cellXml+=`>`;
                    const scaleLabel=xaxes.scaleLabel;
                    if(scaleLabel){
                        cellXml+=`<scale-label display="${scaleLabel.display}"`;
                        if(scaleLabel.labelString){
                            cellXml+=` label-string="${scaleLabel.labelString}"`;
                        }
                        cellXml+=`/>`;
                    }
                    cellXml+=`</xaxes>`;
                }
                const yaxes=chart.yaxes;
                if(yaxes){
                    cellXml+=`<yaxes`;
                    if(yaxes.rotation){
                        cellXml+=` rotation="${yaxes.rotation}"`;
                    }
                    cellXml+=`>`;
                    const scaleLabel=yaxes.scaleLabel;
                    if(scaleLabel){
                        cellXml+=`<scale-label display="${scaleLabel.display}"`;
                        if(scaleLabel.labelString){
                            cellXml+=` label-string="${scaleLabel.labelString}"`;
                        }
                        cellXml+=`/>`;
                    }
                    cellXml+=`</yaxes>`;
                }
                const options=chart.options;
                if(options){
                    for(let option of options){
                        cellXml+=`<option type="${option.type}"`;
                        if(option.position){
                            cellXml+=` position="${option.position}"`;
                        }
                        if(option.display!==undefined && option.display!==null){
                            cellXml+=` display="${option.display}"`;
                        }
                        if(option.duration){
                            cellXml+=` duration="${option.duration}"`;
                        }
                        if(option.easing){
                            cellXml+=` easing="${option.easing}"`;
                        }
                        if(option.text){
                            cellXml+=` text="${option.text}"`;
                        }
                        cellXml+=`/>`;
                    }
                }
                const plugins=chart.plugins || [];
                for(let plugin of plugins){
                    cellXml+=`<plugin name="${plugin.name}" display="${plugin.display}"/>`;
                }
                if(plugins){

                }
                cellXml+=`</chart-value>`;
            }
            const propertyConditions=cellDef.conditionPropertyItems || [];
            for(let pc of propertyConditions){
                cellXml+=`<condition-property-item name="${pc.name}"`;
                const rowHeight=pc.rowHeight;
                if(rowHeight!==null && rowHeight!==undefined && rowHeight!==-1){
                    cellXml+=` row-height="${rowHeight}"`;
                }
                const colWidth=pc.colWidth;
                if(colWidth!==null && colWidth!==undefined && colWidth!==-1){
                    cellXml+=` col-width="${colWidth}"`;
                }
                if(pc.newValue && pc.newValue!==''){
                    cellXml+=` new-value="${pc.newValue}"`;
                }
                if(pc.linkUrl && pc.linkUrl!==''){
                    cellXml+=` link-url="${pc.linkUrl}"`;
                    let targetWindow=pc.linkTargetWindow;
                    if(!targetWindow || targetWindow===''){
                        targetWindow="_self";
                    }
                    cellXml+=` link-target-window="${pc.linkTargetWindow}"`;
                }
                cellXml+=`>`;
                const paging=pc.paging;
                if(paging){
                    cellXml+=`<paging position="${paging.position}" line="${paging.line}"/>`;
                }
                if(pc.linkParameters && pc.linkParameters.length>0){
                    for(let param of pc.linkParameters){
                        cellXml+=`<link-parameter name="${param.name}">`;
                        cellXml+=`<value><![CDATA[${param.value}]]></value>`;
                        cellXml+=`</link-parameter>`;
                    }
                }
                const style=pc.cellStyle;
                if(style){
                    cellXml+=buildCellStyle(style,true);
                }
                cellXml+=buildConditions(pc.conditions);
                cellXml+=`</condition-property-item>`;
            }
            cellXml+='</cell>';
        }
    }
    xml+=cellXml;
    xml+=rowsXml;
    xml+=columnXml;
    const header=context.reportDef.header;
    if(header && (header.left || header.center || header.right)){
        xml+='<header ';
        if(header.fontFamily){
            xml+=` font-family="${header.fontFamily}"`
        }
        if(header.fontSize){
            xml+=` font-size="${header.fontSize}"`
        }
        if(header.forecolor){
            xml+=` forecolor="${header.forecolor}"`
        }
        if(header.bold){
            xml+=` bold="${header.bold}"`
        }
        if(header.italic){
            xml+=` italic="${header.italic}"`
        }
        if(header.underline){
            xml+=` underline="${header.underline}"`
        }
        if(header.margin){
            xml+=` margin="${header.margin}"`
        }
        xml+='>';
        if(header.left){
            xml+=`<left><![CDATA[${header.left}]]></left>`;
        }
        if(header.center){
            xml+=`<center><![CDATA[${header.center}]]></center>`;
        }
        if(header.right){
            xml+=`<right><![CDATA[${header.right}]]></right>`;
        }
        xml+='</header>';
    }
    const footer=context.reportDef.footer;
    if(footer && (footer.left || footer.center || footer.right)){
        xml+='<footer ';
        if(footer.fontFamily){
            xml+=` font-family="${footer.fontFamily}"`
        }
        if(footer.fontSize){
            xml+=` font-size="${footer.fontSize}"`
        }
        if(footer.forecolor){
            xml+=` forecolor="${footer.forecolor}"`
        }
        if(footer.bold){
            xml+=` bold="${footer.bold}"`
        }
        if(footer.italic){
            xml+=` italic="${footer.italic}"`
        }
        if(footer.underline){
            xml+=` underline="${footer.underline}"`
        }
        if(footer.margin){
            xml+=` margin="${footer.margin}"`
        }
        xml+='>';
        if(footer.left){
            xml+=`<left><![CDATA[${footer.left}]]></left>`;
        }
        if(footer.center){
            xml+=`<center><![CDATA[${footer.center}]]></center>`;
        }
        if(footer.right){
            xml+=`<right><![CDATA[${footer.right}]]></right>`;
        }
        xml+='</footer>';
    }
    let datasourceXml="";
    const datasources=context.reportDef.datasources;
    for(let datasource of datasources){
        let ds=`<datasource name="${encode(datasource.name)}" type="${datasource.type}"`;
        let type=datasource.type;
        if(type==='jdbc'){
            ds+=` username="${encode(datasource.username)}"`;
            ds+=` password="${encode(datasource.password)}"`;
            ds+=` url="${encode(datasource.url)}"`;
            ds+=` driver="${datasource.driver}"`;
            ds+='>';
            for(let dataset of datasource.datasets){
                ds+=`<dataset name="${encode(dataset.name)}" type="sql">`;
                ds+=`<sql><![CDATA[${dataset.sql}]]></sql>`;
                for(let field of dataset.fields){
                    ds+=`<field name="${field.name}"/>`;
                }
                for(let parameter of dataset.parameters){
                    ds+=`<parameter name="${encode(parameter.name)}" type="${parameter.type}" default-value="${encode(parameter.defaultValue)}"/>`;
                }
                ds+=`</dataset>`;
            }
        }else if(type==='spring'){
            ds+=` bean="${datasource.beanId}">`;
            for(let dataset of datasource.datasets){
                ds+=`<dataset name="${encode(dataset.name)}" type="bean" method="${dataset.method}" clazz="${dataset.clazz}">`;
                for(let field of dataset.fields){
                    ds+=`<field name="${field.name}"/>`;
                }
                ds+=`</dataset>`;
            }
        }else if(type==='buildin'){
            ds+='>';
            for(let dataset of datasource.datasets){
                ds+=`<dataset name="${encode(dataset.name)}" type="sql">`;
                ds+=`<sql><![CDATA[${dataset.sql}]]></sql>`;
                for(let field of dataset.fields){
                    ds+=`<field name="${field.name}"/>`;
                }
                for(let parameter of dataset.parameters){
                    ds+=`<parameter name="${parameter.name}" type="${parameter.type}" default-value="${parameter.defaultValue}"/>`;
                }
                ds+=`</dataset>`;
            }
        }
        ds+="</datasource>";
        datasourceXml+=ds;
    }
    xml+=datasourceXml;
    const paper=context.reportDef.paper;
    let htmlIntervalRefreshValue=0;
    if(paper.htmlIntervalRefreshValue!==null && paper.htmlIntervalRefreshValue!==undefined){
        htmlIntervalRefreshValue=paper.htmlIntervalRefreshValue;
    }
    xml+=`<paper type="${paper.paperType}" left-margin="${paper.leftMargin}" right-margin="${paper.rightMargin}"
    top-margin="${paper.topMargin}" bottom-margin="${paper.bottomMargin}" paging-mode="${paper.pagingMode}" fixrows="${paper.fixRows}"
    width="${paper.width}" height="${paper.height}" orientation="${paper.orientation}" html-report-align="${paper.htmlReportAlign}" bg-image="${paper.bgImage || ''}" html-interval-refresh-value="${htmlIntervalRefreshValue}" column-enabled="${paper.columnEnabled}"`;
    if(paper.columnEnabled){
        xml+=` column-count="${paper.columnCount}" column-margin="${paper.columnMargin}"`;
    }
    xml+=`></paper>`;
    if(context.reportDef.searchFormXml){
        xml+=context.reportDef.searchFormXml;
    }
    xml+=`</ureport>`;
    xml=encodeURIComponent(xml);
    return xml;
};

function getSpan(hot,row,col){
    const mergeCells=hot.getSettings().mergeCells || [];
    for(let item of mergeCells){
        if(item.row===row && item.col===col){
            return item;
        }
    }
    return {rowspan:0,colspan:0};
}

function buildConditions(conditions){
    let cellXml='';
    if(conditions){
        const size=conditions.length;
        for(let condition of conditions){
            if(!condition.type || condition.type==='property'){
                if(condition.left){
                    cellXml+=`<condition property="${condition.left}" op="${encode(condition.operation)}" id="${condition.id}"`;
                }else{
                    cellXml+=`<condition op="${encode(condition.operation)}" id="${condition.id}"`;
                }
                cellXml+=` type="${condition.type}"`;
                if(condition.join && size>1){
                    cellXml+=` join="${condition.join}">`;
                }else{
                    cellXml+=`>`;
                }
                cellXml+=`<value><![CDATA[${condition.right}]]></value>`;
            }else{
                cellXml+=`<condition type="${condition.type}" op="${encode(condition.operation)}" id="${condition.id}"`;
                if(condition.join && size>1){
                    cellXml+=` join="${condition.join}">`;
                }else{
                    cellXml+=`>`;
                }
                cellXml+=`<left><![CDATA[${condition.left}]]></left>`;
                cellXml+=`<right><![CDATA[${condition.right}]]></right>`;
            }
            cellXml+=`</condition>`;
        }
    }
    return cellXml;
};

function buildCellStyle(cellStyle,condition){
    let cellXml="<cell-style";
    if(condition){
        cellXml+=` for-condition="true"`;
    }
    if(cellStyle.fontSize && cellStyle.fontSize!==''){
        cellXml+=` font-size="${cellStyle.fontSize}"`;
    }
    if(cellStyle.fontSizeScope){
        cellXml+=` font-size-scope="${cellStyle.fontSizeScope}"`;
    }
    if(cellStyle.forecolor && cellStyle.forecolor!==''){
        cellXml+=` forecolor="${cellStyle.forecolor}"`;
    }
    if(cellStyle.forecolorScope){
        cellXml+=` forecolor-scope="${cellStyle.forecolorScope}"`;
    }
    if(cellStyle.fontFamily){
        if(cellStyle.fontFamily==='0'){
            cellXml+=` font-family=""`;
        }else{
            cellXml+=` font-family="${cellStyle.fontFamily}"`;
        }
    }
    if(cellStyle.fontFamilyScope){
        cellXml+=` font-family-scope="${cellStyle.fontFamilyScope}"`;
    }
    if(cellStyle.bgcolor && cellStyle.bgcolor!==''){
        cellXml+=` bgcolor="${cellStyle.bgcolor}"`;
    }
    if(cellStyle.bgcolorScope){
        cellXml+=` bgcolor-scope="${cellStyle.bgcolorScope}"`;
    }
    if(cellStyle.format && cellStyle.format!==''){
        cellXml+=` format="${cellStyle.format}"`;
    }
    if(cellStyle.bold!==undefined && cellStyle.bold!==null){
        cellXml+=` bold="${cellStyle.bold}"`;
    }
    if(cellStyle.boldScope){
        cellXml+=` bold-scope="${cellStyle.boldScope}"`;
    }
    if(cellStyle.italic!==undefined && cellStyle.italic!==null){
        cellXml+=` italic="${cellStyle.italic}"`;
    }
    if(cellStyle.italicScope){
        cellXml+=` italic-scope="${cellStyle.italicScope}"`;
    }
    if(cellStyle.underline!==undefined && cellStyle.underline!==null){
        cellXml+=` underline="${cellStyle.underline}"`;
    }
    if(cellStyle.underlineScope){
        cellXml+=` underline-scope="${cellStyle.underlineScope}"`;
    }
    if(cellStyle.wrapCompute!==undefined && cellStyle.wrapCompute!==null){
        cellXml+=` wrap-compute="${cellStyle.wrapCompute}"`;
    }
    if(cellStyle.align && cellStyle.align!==''){
        cellXml+=` align="${cellStyle.align}"`;
    }
    if(cellStyle.alignScope){
        cellXml+=` align-scope="${cellStyle.alignScope}"`;
    }
    if(cellStyle.valign && cellStyle.valign!==''){
        cellXml+=` valign="${cellStyle.valign}"`;
    }
    if(cellStyle.valignScope){
        cellXml+=` valign-scope="${cellStyle.valignScope}"`;
    }
    if(cellStyle.lineHeight){
        cellXml+=` line-height="${cellStyle.lineHeight}"`;
    }
    cellXml+='>';
    let leftBorder=cellStyle.leftBorder;
    if(leftBorder && leftBorder.style!=="none"){
        cellXml+=`<left-border width="${leftBorder.width}" style="${leftBorder.style}" color="${leftBorder.color}"/>`;
    }
    let rightBorder=cellStyle.rightBorder;
    if(rightBorder && rightBorder.style!=="none"){
        cellXml+=`<right-border width="${rightBorder.width}" style="${rightBorder.style}" color="${rightBorder.color}"/>`;
    }
    let topBorder=cellStyle.topBorder;
    if(topBorder && topBorder.style!=="none"){
        cellXml+=`<top-border width="${topBorder.width}" style="${topBorder.style}" color="${topBorder.color}"/>`;
    }
    let bottomBorder=cellStyle.bottomBorder;
    if(bottomBorder && bottomBorder.style!=="none"){
        cellXml+=`<bottom-border width="${bottomBorder.width}" style="${bottomBorder.style}" color="${bottomBorder.color}"/>`;
    }
    cellXml+='</cell-style>';
    return cellXml;
};

export function encode(text){
    let result = text.replace(/[<>&"]/g,function(c){return {'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'}[c];});
    return result;
};

export function getParameter(name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    var r = window.location.search.substr(1).match(reg);
    if (r != null)return r[2];
    return null;
};

export function mmToPoint(mm){
    let value=mm*2.834646;
    return Math.round(value);
};
export function pointToMM(point){
    let value=point*0.352778;
    return Math.round(value);
};

export function pointToPixel(point){
    const value=point * 1.33;
    return Math.round(value);
};

export function pixelToPoint(pixel){
    const value=pixel * 0.75;
    return Math.round(value);
};

export function setDirty(){
    $('#__save_btn').removeClass('disabled');
};

export function resetDirty(){
    $('#__save_btn').addClass('disabled');
};

export function formatDate(date,format){
    if(typeof date === 'number'){
        date=new Date(date);
    }
    if(typeof date==='string'){
        return date;
    }
    var o = {
        "M+" : date.getMonth()+1,
        "d+" : date.getDate(),
        "H+" : date.getHours(),
        "m+" : date.getMinutes(),
        "s+" : date.getSeconds()
    };
    if(/(y+)/.test(format))
        format=format.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
    for(var k in o)
        if(new RegExp("("+ k +")").test(format))
            format = format.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
    return format;
};

export function buildPageSizeList(){
    return {
        A0:{width:841,height:1189},
        A1:{width:594,height:841},
        A2:{width:420,height:594},
        A3:{width:297,height:420},
        A4:{width:210,height:297},
        A5:{width:148,height:210},
        A6:{width:105,height:148},
        A7:{width:74,height:105},
        A8:{width:52,height:74},
        A9:{width:37,height:52},
        A10:{width:26,height:37},
        B0:{width:1000,height:1414},
        B1:{width:707,height:1000},
        B2:{width:500,height:707},
        B3:{width:353,height:500},
        B4:{width:250,height:353},
        B5:{width:176,height:250},
        B6:{width:125,height:176},
        B7:{width:88,height:125},
        B8:{width:62,height:88},
        B9:{width:44,height:62},
        B10:{width:31,height:44}
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UReport2 多报表文件打印,ZIP下载实现 的相关文章

  • 最全Python绘制饼形图(饼状图)

    饼状图 xff08 pie chart xff09 一般用于描述分类型数据的相对频数或百分数频数分布 xff0c 呈现部分与总体的关系 一 导入绘图数据 首先导入绘图所需的数据 span class token keyword import
  • 最全Python绘制条形图(柱状图)

    条形图 xff08 bar chart xff09 也称为柱状图 xff0c 是一种以长方形的长度为变量的统计图表 xff0c 长方形的长度与它所对应的数值呈一定比例 一 导入绘图数据 首先导入绘图所需的数据 span class toke
  • 算法题 股票买卖IV(Python)

    题目 https leetcode cn com problems best time to buy and sell stock iv 给定一个长度为 N 的数组 xff0c 数组中的第 i 个数字表示一个给定股票在第 i 天的价格 设计
  • 【Python】情人节表白烟花(带声音和文字)

    今天就是情人节了 xff0c 有想好送什么给亲爱的他 她吗 xff1f 去年5月20日的时候整理了Python浪漫表白源码合集 xff08 爱心 玫瑰花 照片墙 星空下的告白 xff09 xff0c 今天向大家介绍表白烟花 xff0c 祝单
  • 【Python】用pyecharts绘制我国人口分布和迁移地图

    一直很好奇我国人口分布和迁移情况 xff0c 所以想用Python分析一下 由于我国省份较多 xff0c 把数据放在地图上展示会更加清晰 xff0c 故本文用Python中的pyecharts库进行人口分布和迁移绘图展示 pyecharts
  • 模型评价指标—ROC曲线

    对于分类模型 xff0c 在建立好模型后 xff0c 我们想对模型进行评价 xff0c 常见的指标有混淆矩阵 F1值 KS曲线 ROC曲线 AUC面积等 也可以自己定义函数 xff0c 把模型结果分割成n 100 份 xff0c 计算top
  • 模型评价指标—F1值

    最近空余时间在参加数字中国创新大赛 xff0c 比赛规则是根据模型的F1值对参赛者进行排名 为了更深刻地理解这个指标 xff0c 我最近对它做了一些梳理 xff0c 现在把它分享给更多有需要的人图片 最近在参赛时也发现了一个问题 xff0c
  • 【Python常用函数】一文让你彻底掌握Python中的pivot_table函数

    任何事情都是由量变到质变的过程 xff0c 学习Python也不例外 只有把一个语言中的常用函数了如指掌了 xff0c 才能在处理问题的过程中得心应手 xff0c 快速地找到最优方案 本文和你一起来探索Python中的pivot table
  • python画生肖兔

    2022已经过去 xff0c 2023正在继续 xff0c 希望我们都能在平凡的日子里 xff0c 熠熠生辉 本文介绍运用Python中的turtle库控制函数画生肖兔 xff0c 并设置了2023年幸运词 xff0c 快截屏看看你的幸运词
  • 判断变量是否存在

    来获取一个变量是否存在 xff0c 用 if typeof a 61 34 undefined 34 alert 34 ok 34 xff0c xff0c 而不要去使用 if a 因为如果 a 不存在 xff08 未声明 xff09 则会出
  • Nextcloud 内部服务器错误解决

    在部署nextcloud过程中最后登录页面时出现内部服务器错误 xff0c 心态当时就炸了 在网上找了各种方案 xff0c 但是大部分博主都告诉我是 var lib php session 属组的权限问题 xff0c 或者web目录的权限不
  • golang中的(data race )典型数据竞争问题举例

    示例一 func main var wg sync WaitGroup wg Add 5 for i 61 0 i lt 5 i 43 43 go func fmt Println i Not the 39 i 39 you are loo
  • Jupyter Notebook怎么全选输出的内容?

    Ctrl 43 A 单击 双击 三连击 三连击 xff01 xff01 xff01
  • RetinaNet详细解读

    网络名称RetinaNet发表时间2018年1月作者Tsung Yi Lin Priya Goyal Ross Girshick Kaiming He and Piotr Dollar机构Facebook AI Research FAIR
  • 微信公众号服务器token验证失败?

    很可能是你用了官方的python范例 xff0c 官方的范例是python2的 xff0c 而我用的是python3的 将 map sha1 update list 修改为sha1 61 hashlib sha1 34 34 join li
  • 三分钟学会lightGBM安装及入门指南(一)

    果然标题大法好啊 xff0c 还是成功的让你进来了吧 xff0c xff0c 但是以下都是干货 我的机器环境python3 6 xff0c win7操作系统 xff0c 当然win10也是同样适用的 xff0c 有不懂的可以留言 xff0c
  • 微信小程序文字水平垂直居中对齐问题(完美解决方案)

    我们知道常用的居中对齐方式有很多种例如 xff1a text align center align items center justify content center margin auto 子容器在父容器中居中 但是在view中的文字
  • mac下python matplotlib中文乱码解决方案(亲测可用)!!

    在网上找了一大堆方法 xff0c 花了很久 xff0c 发现不是要安装各种字体就是要改配置 xff0c 而且字体真的不好找也不好安装 就例如下面这两种办法 xff0c mac下根本不管用 xff0c 别人管不管用我不知道 xff0c 反正我
  • python使用threading.Timer实现线程循环任务定时器(一)

    在进行爬虫系统开发的过程中遇到需要间隔一段时间就重复执行的任务的需求 xff0c 就想实现一个线程服务在后台监控数据的抓取状态 xff0c 要想实现定时循环任务的脚本可以使用linux下的crontab命令来执行 xff0c 但是在一个常驻
  • cross_val_score的 scoring参数值解析

    一般我们在模型训练过程中 xff0c 会采用K折交叉验证的方法来验证模型的表现 xff0c 从而进行调参 xff0c 一般我们会用到 sklearn model selection 的 cross val score 方法来计算模型的得分

随机推荐

  • windows 10下 itunes 备份默认存储路径问题

    最近在研究iphone手机备份的问题 xff0c 在使用itunes给手机备份的时候 xff0c 发现C盘空间不够用了 xff0c 于是想把itunes的默认存储路径修改一下 xff0c 在网上查找资料了解了相关操作教程后 xff0c 发现
  • MAC查看与修改系统默认的shell

    查看系统当前默认使用的shell有如下几个方法 一 查看所有的shell cat etc shells 输出 List of acceptable shells for chpass 1 Ftpd will not allow users
  • windows下redis的配置文件(redis.windows.conf)

    redis的配置 Redis默认不是以守护进程的方式运行 xff0c 可以通过该配置项修改 xff0c 使用yes启用守护进程 daemonize yes 当Redis以守护进程方式运行时 xff0c Redis默认会把pid写入redis
  • UITabBarController

    1 UITabBarController的常用属性和方法 一般来说 xff0c 目前市面上的App很多都是由一个UITabBarController管理着4 xff5e 5个UINavigationController xff0c 然后每个
  • LJSpeech-1.1.tar.bz2 下载分享

    数据集 xff1a http data keithito com data speech LJSpeech 1 1 tar bz2 xff08 用迅雷下载很快 xff09 百度网盘地址 xff1a 链接 xff1a https pan ba
  • cookie存放位置(Win10)

    IE浏览器 xff1a APPDATA Microsoft Windows Cookies 目录中的xxx txt文件 xff08 IE浏览器分开存放的 xff09 火狐浏览器 xff1a APPDATA Mozilla Firefox P
  • C语言 将一个整数的二进制序列分别输出

    include lt stdio h gt int main int i j num char arr1 16 char arr2 16 printf 34 输入一个整数 xff1a 34 scanf 34 d 34 amp num for
  • openSSL中SSL_MODE_AUTO_RETRY使用引发的问题

    1 SSL MODE AUTO RETRY的作用 关于这个flag的作用 xff0c openSSL官方的解释如下所示 xff1a SSL MODE AUTO RETRY Never bother the application with
  • Github下载代码和运行

    本文介绍利用Git工具下载和运行GitHub代码 文章目录 一 Win下载安装Git二 运行python代码1 下载Github代码2 运行代码 一 Win下载安装Git 官网下载 xff1a https git scm com downl
  • 批量修改txt文件名,删除相同部分

    转载 xff1a https www cnblogs com cyh2009 p 10593776 html 1 在包括需要修改的txt文件夹中新建txt文件 xff0c 输入 xff1a 64 echo off span class to
  • 8086汇编指令笔记

    8086 8088汇编指令总结 一 数据传送指令 1 传送指令 xff1a MOV move 格式 xff1a mov dst src 具体用法 xff1a 1 CPU内部寄存器之间的数据传送 xff0c 如 xff1a mov ah al
  • CentOS(linux)循环登录(闪退)的一种可能的解决方法

    前言 最近开机之后通过远程ssh刷init 5进系统时发现 xff0c 我经常使用的账号输入账号密码后屏幕闪一下又回到登录界面 xff0c 也就是所谓的循环登录 xff0c 其他的账号登录都是正常的 xff0c 烦了我有一段时间了 xff0
  • 百度ECharts地图 地名位置坐标微调

    百度ECharts地图 地名位置坐标微调 百度Echarts出现地市名字不居中或者重叠 下载的地图json数据里坐标位置导致出现这种问题 下载的地图json数据里坐标位置导致出现这种问题 xff0c 修改json数据中的cp 属性存储的是经
  • Java中抽象类 abstract和interface的区别

    abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制 xff0c 正是由于这两种机制的存在 xff0c 才赋予了Java强大的面向对象能力 abstract class和interface之间在对
  • Java Vue uni-app 三端实现,滑动拼图验证码

    一步一步实现 图片滑动验证码 项目中要使用 图片滑动验证码 xff0c 顾了解之 需要以下几步来完成 xff1a 1 后端随机计算抠图的距离 xff0c 生成背景与拼图块的图片 xff0c 缓存 拼图块需 滑动的距离像素 2 前端加载背景图
  • DES与3DES 加解密实例(c++)

    DES与3DES 加解密实例 xff08 c 43 43 xff09 DES原理 xff1a DES算法是一种对称密码算法 xff0c 也是一种分组加密的算法 xff0c 以64位分组对数 据加密的 xff0c 其密钥长度为64位 xff0
  • java打印杨辉三角形

    前言 xff0c 打印杨辉三角形对于初级的程序员来说并不难 xff0c 主要掌握几个核心的知识点就行了 xff0c 其运用到二维数组 for循环 if条件语句等 杨辉三角形的特性如下 xff1a 它的两条斜边都是由数字1组成的 xff0c
  • Windows server2019安装docker

    安装Docker Desktop Microsoft Windows Docker安装 一 安装Docker二 配置Docker1 Docker停止所有容器 清理缓存 xff1a 2 拉取镜像 EMQX 为例 xff1a 1 获取EMQX镜
  • threeJs 封装DRACOLoader加载

    项目使用到3D模型加载渲染 xff0c 故初学习了解之 xff0c 简单封装 代码如下 span class token keyword import span span class token operator span span cla
  • UReport2 多报表文件打印,ZIP下载实现

    项目中报表较多 xff0c 客户要求多报表 zip下载或打印 xff0c 查看ureport内部代码实现 xff0c 代码相对简单 xff0c 直接上代码 实现了多文件混合zip下载 xff0c 基于浏览器的打印和Lodop打印插件两种方式