html利用浏览器打印jquery.jqprint-0.3.js,制作票据通用模板js

公司产品项目,使用的架构是比较老的,使用打印插件工具是OCX,这个局限性比较大,只能使用IE浏览器,连EDGE浏览器都不支持,并且需要调整IE浏览器的安全配置。

基于以上的原因,项目决定更换打印的模式,使用html模板,研发进行编写模板。js的赋值处理,不需要重复编写,需要写的通用。主要js如下:

<script type="text/javascript">
	/*
	//step0 之前获取数据的,现在数据从参数中获取。以后的数据都是直接传递的
	EtcomWebAjax(getMessage, 222, 2, formData($("#list")), function(data) {
	}, function() {
	}); 
	console.log(digitUppercase(-109.41))
	console.log(digitUppercase(200.55))
	console.log(digitUppercase(87))
	//console.log(execMathExpress("20.1+0.88*5"))
	//console.log(execMathExpress("20.1"))
	//console.log(test("22+11"))
	//console.log(test("11.88/aa"))
	console.log(execMathExpress("20.1"))
	*/
	
	$(function() {
		//step1 准备使用浏览器的打印,前提已经引入jquery.jqprint-0.3.js。准备工作,用到的所有通用函数都在:yem.js中
		jQuery.browser={};
		(function(){
			jQuery.browser.msie=false; 
			jQuery.browser.version=0;
			if(navigator.userAgent.match(/MSIE ([0-9]+)./)){ 
				jQuery.browser.msie=true;
				jQuery.browser.version=RegExp.$1;
			}
		})();
		//console.log($(".mfee1*mfee2"))
		//step2 接收传递过来的数据
		var printData = getUrlParam('printData');
		data = printData;
		data={mfee1:10.8,mfee2:0.88};
		//step3 处理打印数据,如果数据为空进行提示,不为空,处理数据,执行进行打印
		if (data != "" && data != null && data != undefined && data != "null"   ) {
			//step4  处理页面中所有的h5标签的class。
			for(var i=0; i<$("#list h5").length; i++){
				var classAttr="";
				var classAttr2="";
				var classNum="";
				var bigFlag = false;//是否大写
				var orFlag = false;//数据中是否存在
				var timeFlag = false;//是否是固定的时间规则
				var classObj = null;
				classAttr = $.trim($($("#list h5")[i]).attr("class"));
				classObj = $($("#list h5")[i])
				//step4.5  处理几个固定的规则,时间和非数据库数据  
				if(classAttr==""){//规则之一如果是空的,则未绑定数据库数据
					continue;
				}
				//规则之一如果是sysdatetime 当前时间yyyy-mm-dd hh:nn:ss、sysdate yyyy-mm-dd、systime hh:nn:ss
				//sysyear yyyy、sysmonth  mm  、sysday dd
				var nowtime = new Date();
			    var year = nowtime.getFullYear();
			    var month = padleft0(nowtime.getMonth() + 1);
			    var day = padleft0(nowtime.getDate());
			    var hour = padleft0(nowtime.getHours());
			    var minute = padleft0(nowtime.getMinutes());
			    var second = padleft0(nowtime.getSeconds());
				if(classAttr=="sysdatetime"){
					timeFlag = true;
					classNum = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
				}else if(classAttr=="sysdate"){
					timeFlag = true;
					classNum = year + "-" + month + "-" + day;
				}else if(classAttr=="systime"){
					timeFlag = true;
					classNum = hour+":"+minute+":"+second;
				}else if(classAttr=="sysyear"){
					timeFlag = true;
					classNum = year;
				}else if(classAttr=="sysmonth"){
					timeFlag = true;
					classNum = month;
				}else if(classAttr=="sysday"){
					timeFlag = true;
					classNum = day;
				}
				if(timeFlag){
					var html = $("." + classAttr).html();
					$("." + classAttr).html(html + "  " + classNum);
					continue;
				}
				//step5  首先判断class中是否存在大写标识,如果存在标识,最后要将计算好的数字进行大写转换。
				if(classAttr.indexOf("^")>-1){
					bigFlag=true;
					//如果存在要将大写标识去除掉
					classAttr2 = classAttr.replace("^","");
				}else{
					classAttr2 = classAttr;
					bigFlag=false;
				}
				//step6  替换class中匹配结果集中的每一个字段。即:mfee1+mfee2 替换成 20.1+0.8
				for ( var key in data) {
					if(classAttr2.indexOf(key)>-1){
						if(classAttr2.indexOf(key.toString())==0){
							//防止某个字段包含另外一个字段,所以替换之前要判断该信息的前后必须是空或者是运算符
							var lastStr = classAttr2.substr(key.toString().length,classAttr2.length-1);
							if(lastStr=="" || lastStr.indexOf("+")==0 || lastStr.indexOf("-")==0 || lastStr.indexOf("*")==0 || lastStr.indexOf("/")==0){
								classAttr2 = classAttr2.replace(key.toString(),data[key].toString());
							}
						}else{
							var preStr = classAttr2.substr(0,classAttr2.indexOf(key.toString()));
							var lastStr = classAttr2.substr(classAttr2.indexOf(key.toString())+key.toString().length,classAttr2.length-1);
							if((lastStr=="" || lastStr.indexOf("+")==0 || lastStr.indexOf("-")==0 || lastStr.indexOf("*")==0 || lastStr.indexOf("/")==0) 
									&& (preStr=="" || preStr.indexOf("+")==preStr.length-1 || preStr.indexOf("-")==preStr.length-1 || preStr.indexOf("*")==preStr.length-1 || preStr.indexOf("/")==preStr.length-1)){
								classAttr2 = classAttr2.replace(key.toString(),data[key].toString());
							}
						}
					}
				}
				//step7  得到最后的计算表达式,先进行判断是否可以进行运算,然后进行解析四则运算
				if(test(classAttr2)){
					var returnRes = execMathExpress(classAttr2);
					classNum = accDivCoupon(returnRes["num"],returnRes["den"])
					//如果大写则进行大写
					if(bigFlag){
						classNum = digitUppercase(classNum)
					}
				}
				//step8  赋值页面内容。
				var html = classObj.html();
				classObj.html(html + "  " + classNum);
			}
			//$(".money").html($(".money").html()+"  "+data["mtotal"] + "  元")
		}
		
		$("#print").jqprint();
	})
	function print(){
		$("#print").jqprint();
	}
	</script>
	

其中比较重要的几个方法

1、准备工作几乎是必须的,js文件要引入;

2、getUrlParam获取url中参数的方法;

3、padleft0补全方法;

4、execMathExpress解析四则运算的方法;

5、accDivCoupon 除法,加减乘等方法;

6、digitUppercase将数据转成大写方法;

7、$("#print").jqprint(); 直接打印方法;

8、主要的验证是否可以进行四则运算的方法,test(classAttr2)

主要的方法js如下:
//获取url中的参数
function getUrlParam(name){
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
    var r = window.location.search.substr(1).match(reg);  //匹配目标参数
    if (r != null) return unescape(r[2]); return null; //返回参数值
}
/**
 * 将数字转换成人民币大写的方法
 */
function digitUppercase (n) {
    var fraction = ['角', '分'];
    var digit = [
        '零', '壹', '贰', '叁', '肆',
        '伍', '陆', '柒', '捌', '玖'
    ];
    var unit = [
        ['元', '万', '亿'],
        ['', '拾', '佰', '仟']
    ];
    var IsNum = Number(n);
    if (!isNaN(IsNum)) {
        var head = n < 0 ? '(负)' : '';
        n = Math.abs(n);
        var s = '';
        for (var i = 0; i < fraction.length; i++) {
            s += (digit[Math.floor(n * 100/10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');
        }
        s = s || '整';
        n = Math.floor(n);
        for (var i = 0; i < unit[0].length && n > 0; i++) {
            var p = '';
            for (var j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[n % 10] + unit[1][j] + p;
                n = Math.floor(n / 10);
            }
            s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
        }
        return head + s.replace(/(零.)*零元/, '元')
            .replace(/(零.)+/g, '零')
            .replace(/^整$/, '零元整');
    }
    else {
        return "";
    }

};
/**
 * 加法
 * @param arg1
 * @param arg2
 * @returns
 */
function accAdd(arg1,arg2){
     var r1,r2,m;
     try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0};
     try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0};
     m=Math.pow(10,Math.max(r1,r2));
     return (arg1*m+arg2*m)/m;
}
 
/**
 * 减法
 * @param arg1
 * @param arg2
 * @returns
 */
 function accSubtr(arg1,arg2){
    var r1,r2,m,n;
    try{r1=arg1.toString().split(".")[1].length;}catch(e){r1=0;}
    try{r2=arg2.toString().split(".")[1].length;}catch(e){r2=0;}
    m=Math.pow(10,Math.max(r1,r2));
    //动态控制精度长度
    n=(r1>=r2)?r1:r2;
    return ((arg1*m-arg2*m)/m).toFixed(n);
} 
 
/***
 * 乘法,获取精确乘法的结果值
 * @param arg1
 * @param arg2
 * @returns
 */
function accMul(arg1,arg2)
{
    var m=0,s1=arg1.toString(),s2=arg2.toString();
      try{m+=s1.split(".")[1].length}catch(e){};
      try{m+=s2.split(".")[1].length}catch(e){};
      return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
}
 
/***
 * 除法,获取精确乘法的结果值
 * @param arg1
 * @param arg2
 * @returns
 */
function accDivCoupon(arg1,arg2){
    var t1=0,t2=0,r1,r2;
    try{t1=arg1.toString().split(".")[1].length;}catch(e){}
    try{t2=arg2.toString().split(".")[1].length;}catch(e){}
    with(Math){
        r1=Number(arg1.toString().replace(".",""));
        r2=Number(arg2.toString().replace(".",""));
        return (r1/r2)*pow(10,t2-t1);
    }
}
/***
 * 判断是否可以做四则运算。
 */
function test(s){
    var reg=/[\d\.\+\-\*\/\(\)]+/;
    try{
        return reg.test(s)&&!isNaN(eval("("+s+")"));
    }catch(e){
        return false;
    }
}

//欧几里得算法 求两个数a、b的最大公约数
function gcd(a,b){
    return b===0?a:gcd(b,a%b)
}
//分数类 分子,分母
class Fraction{
    static create(num,den=1) {
        if(num instanceof Fraction){
            return num;
        }else if(/(-?\d+)\/(\d+)/.test(num)){
            return new Fraction(parseInt(RegExp.$1),parseInt(RegExp.$2))
        }else{
            if(/\.(\d+)/.test(num)){
                num=num*Math.pow(10,RegExp.$1.length);
                den=den*Math.pow(10,RegExp.$1.length);
            }
            if(/\.(\d+)/.test(den)){
                num=num*Math.pow(10,RegExp.$1.length);
                den=den*Math.pow(10,RegExp.$1.length);
            }
            return new Fraction(num,den)
        }
    }
    constructor(num=0,den=1){
        if(den<0){
            num=-num;
            den=-den;
        }
        if(den===0){
            throw '分母不能为0'
        }
        let g=gcd(Math.abs(num),den)
        this.num=num/g;
        this.den=den/g;
    }
    //加
    add(o){
        return new Fraction(this.num*o.den+this.den*o.num,this.den*o.den)
    }
    //减
    sub(o){
        return new Fraction(this.num*o.den-this.den*o.num,this.den*o.den)
    }
    //乘
    multiply(o){
        return new Fraction(this.num*o.num,this.den*o.den);
    }
    //除
    divide(o){
        return new Fraction(this.num*o.den,this.den*o.num);
    }
    //小于
    lessThan(o){
        return this.num*o.den<this.den*o.num;
    }
    //等于
    equal(o){
        return this.num*o.den===this.den*o.num;
    }
    toString() {
        return this.num+'/'+this.den;
    }
}

//解析数学表达式
function execMathExpress(formula,obj){
    //局部变量
    const tempObj=Object.assign({
        _0:0
    },obj);
    //计算缓存
    const keyCache={};
    let index=1;

    formula=formula.replace(/ /g,'');//清理空格
    //解析数字
    formula=formula.replace(/(^|[(*+/-])(\d+\.\d+|\d+)/g,function (m,p1,p2) {
        if(keyCache[p2]){
            return p1+keyCache[p2];
        }
        const key=keyCache[p2]='_'+index++;
        tempObj[key]=Fraction.create(p2);
        return p1+key;
    })

    function getKey(p1,p2,p3) {
        const keyC=p1+p2+p3;
        if(keyCache[keyC]){
            return keyCache[keyC];
        }
        const key=keyCache[keyC]='_'+index++;
        const fA=Fraction.create(tempObj[p1])
        const fB=Fraction.create(tempObj[p3])
        if(p2==='*'){
            tempObj[key]=fA.multiply(fB);
        }else if(p2==='/'){
            tempObj[key]=fA.divide(fB);
        }else if(p2==='+'){
            tempObj[key]=fA.add(fB);
        }else if(p2==='-'){
            tempObj[key]=fA.sub(fB);
        }
        return key;
    }
    function run(s) {

        //子表达式
        if(/\(([^\(]+?)\)/.test(s)){
            s=s.replace(/\(([^\(]+?)\)/g,function (m,p1,p2) {
                return run(p1);
            })
        }
        //负号
        s=s.replace(/([*/+]|^)-(\w+)/g,function (m,p1,p2) {
            return getKey('_0','-',p2);
        })
        //返回
        if(/(^\w+$)/.test(s)){
            return RegExp.$1;
        }
        //乘法、除法、加法、减法
        const expArr=['*','/','+','-'];
        for(let i=0;i<expArr.length;i++){
            const p=expArr[i];
            const reg=new RegExp('(\\w+)['+p+'](\\w+)');
            while (reg.test(s)){
                s=s.replace(reg,function (m,p1,p2) {
                    return getKey(p1,p,p2);
                })
            }
        }
        //返回
        if(/(^\w+$)/.test(s)){
            return RegExp.$1;
        }
        return run(s);
    }
    return tempObj[run(formula)]
}
//module.exports=execMathExpress;

附带模板html文件和配置的通用方法的js文件:

链接: https://pan.baidu.com/s/1Y2RJZQLxkSI83yHlkNAeVQ 提取码: 66m7 复制这段内容后打开百度网盘手机App,操作更方便哦
–来自百度网盘超级会员v3的分享

总结:

1、使用 ( " . m f e e 1 " ) 这 个 j q 的 获 取 对 象 的 时 候 , 是 不 允 许 的 , 最 后 处 理 : 使 用 的 是 档 期 要 赋 值 的 (".^mfee1")这个jq的获取对象的时候,是不允许的,最后处理:使用的是档期要赋值的 (".mfee1")jq使("#list h5")中的某一个对象。

2、注意处理,mfee12 等包含字段的情况。也就是说,if indexOf 是>-1.的 防止某个字段包含另外一个字段,所以替换之前要判断该信息的前后必须是空或者是运算符。

3、参数的printData的获取需要调整很多使用的页面的传值的方法,或者使用中间的一个页面去获取数据再传递。

**4、最后解析四则运算的方法,最后的结果是一个num den 的数组。计算结果=num/den **

5、shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。

最后附带参考的文章地址:

Js简单判断四则运算是否可用 https://www.iteye.com/blog/zzc1684-2003167 https://blog.csdn.net/zzc1684/article/details/84519582

js解析数学运算公式 https://www.cnblogs.com/caoke/p/11053253.html 最后使用的是这个。

https://blog.csdn.net/wcqwert/article/details/103166690 这个解析没有测试

https://www.cnblogs.com/liuyihao1456/articles/5658547.html 这个解析存在问题 getResult方法不存在,如果能写出这个方法,或者找到这个方法,这个也可以用。但是对于小数不友好

js 中加减乘除 比较精确的算法,js本身有些运算会出错,这里给出较精确的算法
https://blog.csdn.net/yucaifu1989/article/details/22670253

https://www.cnblogs.com/rockyan/p/10196640.html

js 将数字转换成人民币大写的方法 https://www.cnblogs.com/wangfuyou/p/7426472.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值