一、数据加密-AES和RSA
1、AES加密
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入 CDN Crypto.js 开始 AES加密 注意引入顺序 -->
<script type="text/javascript">
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/core.min.js
!function(t,n){"object"==typeof exports?module.exports=exports=n():"function"==typeof define&&define.amd?define([],n):t.CryptoJS=n()}(this,function(){var t=t||function(f){var t;if("undefined"!=typeof window&&window.crypto&&(t=window.crypto),!t&&"undefined"!=typeof window&&window.msCrypto&&(t=window.msCrypto),!t&&"undefined"!=typeof global&&global.crypto&&(t=global.crypto),!t&&"function"==typeof require)try{t=require("crypto")}catch(t){}function i(){if(t){if("function"==typeof t.getRandomValues)try{return t.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof t.randomBytes)try{return t.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")}var e=Object.create||function(t){var n;return r.prototype=t,n=new r,r.prototype=null,n};function r(){}var n={},o=n.lib={},s=o.Base={extend:function(t){var n=e(this);return t&&n.mixIn(t),n.hasOwnProperty("init")&&this.init!==n.init||(n.init=function(){n.$super.init.apply(this,arguments)}),(n.init.prototype=n).$super=this,n},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var n in t)t.hasOwnProperty(n)&&(this[n]=t[n]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},p=o.WordArray=s.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=null!=n?n:4*t.length},toString:function(t){return(t||c).stringify(this)},concat:function(t){var n=this.words,e=t.words,i=this.sigBytes,r=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o<r;o++){var s=e[o>>>2]>>>24-o%4*8&255;n[i+o>>>2]|=s<<24-(i+o)%4*8}else for(o=0;o<r;o+=4)n[i+o>>>2]=e[o>>>2];return this.sigBytes+=r,this},clamp:function(){var t=this.words,n=this.sigBytes;t[n>>>2]&=4294967295<<32-n%4*8,t.length=f.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var n=[],e=0;e<t;e+=4)n.push(i());return new p.init(n,t)}}),a=n.enc={},c=a.Hex={stringify:function(t){for(var n=t.words,e=t.sigBytes,i=[],r=0;r<e;r++){var o=n[r>>>2]>>>24-r%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join("")},parse:function(t){for(var n=t.length,e=[],i=0;i<n;i+=2)e[i>>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new p.init(e,n/2)}},u=a.Latin1={stringify:function(t){for(var n=t.words,e=t.sigBytes,i=[],r=0;r<e;r++){var o=n[r>>>2]>>>24-r%4*8&255;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var n=t.length,e=[],i=0;i<n;i++)e[i>>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new p.init(e,n)}},d=a.Utf8={stringify:function(t){try{return decodeURIComponent(escape(u.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return u.parse(unescape(encodeURIComponent(t)))}},h=o.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new p.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=d.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(t){var n,e=this._data,i=e.words,r=e.sigBytes,o=this.blockSize,s=r/(4*o),a=(s=t?f.ceil(s):f.max((0|s)-this._minBufferSize,0))*o,c=f.min(4*a,r);if(a){for(var u=0;u<a;u+=o)this._doProcessBlock(i,u);n=i.splice(0,a),e.sigBytes-=c}return new p.init(n,c)},clone:function(){var t=s.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),l=(o.Hasher=h.extend({cfg:s.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){h.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){return t&&this._append(t),this._doFinalize()},blockSize:16,_createHelper:function(e){return function(t,n){return new e.init(n).finalize(t)}},_createHmacHelper:function(e){return function(t,n){return new l.HMAC.init(e,n).finalize(t)}}}),n.algo={});return n}(Math);return t});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/enc-base64.min.js
!function(r,e){"object"==typeof exports?module.exports=exports=e(require("./core")):"function"==typeof define&&define.amd?define(["./core"],e):e(r.CryptoJS)}(this,function(r){var s;return s=r.lib.WordArray,r.enc.Base64={stringify:function(r){var e=r.words,t=r.sigBytes,a=this._map;r.clamp();for(var n=[],o=0;o<t;o+=3)for(var i=(e[o>>>2]>>>24-o%4*8&255)<<16|(e[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|e[o+2>>>2]>>>24-(o+2)%4*8&255,f=0;f<4&&o+.75*f<t;f++)n.push(a.charAt(i>>>6*(3-f)&63));var c=a.charAt(64);if(c)for(;n.length%4;)n.push(c);return n.join("")},parse:function(r){var e=r.length,t=this._map,a=this._reverseMap;if(!a){a=this._reverseMap=[];for(var n=0;n<t.length;n++)a[t.charCodeAt(n)]=n}var o=t.charAt(64);if(o){var i=r.indexOf(o);-1!==i&&(e=i)}return function(r,e,t){for(var a=[],n=0,o=0;o<e;o++)if(o%4){var i=t[r.charCodeAt(o-1)]<<o%4*2,f=t[r.charCodeAt(o)]>>>6-o%4*2,c=i|f;a[n>>>2]|=c<<24-n%4*8,n++}return s.create(a,n)}(r,e,a)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},r.enc.Base64});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/md5.min.js
!function(r,e){"object"==typeof exports?module.exports=exports=e(require("./core")):"function"==typeof define&&define.amd?define(["./core"],e):e(r.CryptoJS)}(this,function(i){return function(h){var r=i,e=r.lib,t=e.WordArray,n=e.Hasher,o=r.algo,b=[];!function(){for(var r=0;r<64;r++)b[r]=4294967296*h.abs(h.sin(r+1))|0}();var a=o.MD5=n.extend({_doReset:function(){this._hash=new t.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(r,e){for(var t=0;t<16;t++){var n=e+t,o=r[n];r[n]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8)}var a=this._hash.words,i=r[e+0],s=r[e+1],c=r[e+2],f=r[e+3],h=r[e+4],u=r[e+5],v=r[e+6],d=r[e+7],l=r[e+8],_=r[e+9],p=r[e+10],y=r[e+11],D=r[e+12],H=r[e+13],M=r[e+14],g=r[e+15],m=a[0],w=a[1],x=a[2],B=a[3];m=j(m,w,x,B,i,7,b[0]),B=j(B,m,w,x,s,12,b[1]),x=j(x,B,m,w,c,17,b[2]),w=j(w,x,B,m,f,22,b[3]),m=j(m,w,x,B,h,7,b[4]),B=j(B,m,w,x,u,12,b[5]),x=j(x,B,m,w,v,17,b[6]),w=j(w,x,B,m,d,22,b[7]),m=j(m,w,x,B,l,7,b[8]),B=j(B,m,w,x,_,12,b[9]),x=j(x,B,m,w,p,17,b[10]),w=j(w,x,B,m,y,22,b[11]),m=j(m,w,x,B,D,7,b[12]),B=j(B,m,w,x,H,12,b[13]),x=j(x,B,m,w,M,17,b[14]),m=k(m,w=j(w,x,B,m,g,22,b[15]),x,B,s,5,b[16]),B=k(B,m,w,x,v,9,b[17]),x=k(x,B,m,w,y,14,b[18]),w=k(w,x,B,m,i,20,b[19]),m=k(m,w,x,B,u,5,b[20]),B=k(B,m,w,x,p,9,b[21]),x=k(x,B,m,w,g,14,b[22]),w=k(w,x,B,m,h,20,b[23]),m=k(m,w,x,B,_,5,b[24]),B=k(B,m,w,x,M,9,b[25]),x=k(x,B,m,w,f,14,b[26]),w=k(w,x,B,m,l,20,b[27]),m=k(m,w,x,B,H,5,b[28]),B=k(B,m,w,x,c,9,b[29]),x=k(x,B,m,w,d,14,b[30]),m=q(m,w=k(w,x,B,m,D,20,b[31]),x,B,u,4,b[32]),B=q(B,m,w,x,l,11,b[33]),x=q(x,B,m,w,y,16,b[34]),w=q(w,x,B,m,M,23,b[35]),m=q(m,w,x,B,s,4,b[36]),B=q(B,m,w,x,h,11,b[37]),x=q(x,B,m,w,d,16,b[38]),w=q(w,x,B,m,p,23,b[39]),m=q(m,w,x,B,H,4,b[40]),B=q(B,m,w,x,i,11,b[41]),x=q(x,B,m,w,f,16,b[42]),w=q(w,x,B,m,v,23,b[43]),m=q(m,w,x,B,_,4,b[44]),B=q(B,m,w,x,D,11,b[45]),x=q(x,B,m,w,g,16,b[46]),m=z(m,w=q(w,x,B,m,c,23,b[47]),x,B,i,6,b[48]),B=z(B,m,w,x,d,10,b[49]),x=z(x,B,m,w,M,15,b[50]),w=z(w,x,B,m,u,21,b[51]),m=z(m,w,x,B,D,6,b[52]),B=z(B,m,w,x,f,10,b[53]),x=z(x,B,m,w,p,15,b[54]),w=z(w,x,B,m,s,21,b[55]),m=z(m,w,x,B,l,6,b[56]),B=z(B,m,w,x,g,10,b[57]),x=z(x,B,m,w,v,15,b[58]),w=z(w,x,B,m,H,21,b[59]),m=z(m,w,x,B,h,6,b[60]),B=z(B,m,w,x,y,10,b[61]),x=z(x,B,m,w,c,15,b[62]),w=z(w,x,B,m,_,21,b[63]),a[0]=a[0]+m|0,a[1]=a[1]+w|0,a[2]=a[2]+x|0,a[3]=a[3]+B|0},_doFinalize:function(){var r=this._data,e=r.words,t=8*this._nDataBytes,n=8*r.sigBytes;e[n>>>5]|=128<<24-n%32;var o=h.floor(t/4294967296),a=t;e[15+(64+n>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),e[14+(64+n>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(e.length+1),this._process();for(var i=this._hash,s=i.words,c=0;c<4;c++){var f=s[c];s[c]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return i},clone:function(){var r=n.clone.call(this);return r._hash=this._hash.clone(),r}});function j(r,e,t,n,o,a,i){var s=r+(e&t|~e&n)+o+i;return(s<<a|s>>>32-a)+e}function k(r,e,t,n,o,a,i){var s=r+(e&n|t&~n)+o+i;return(s<<a|s>>>32-a)+e}function q(r,e,t,n,o,a,i){var s=r+(e^t^n)+o+i;return(s<<a|s>>>32-a)+e}function z(r,e,t,n,o,a,i){var s=r+(t^(e|~n))+o+i;return(s<<a|s>>>32-a)+e}r.MD5=n._createHelper(a),r.HmacMD5=n._createHmacHelper(a)}(Math),i.MD5});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/evpkdf.min.js
!function(e,t){"object"==typeof exports?module.exports=exports=t(require("./core"),require("./sha1"),require("./hmac")):"function"==typeof define&&define.amd?define(["./core","./sha1","./hmac"],t):t(e.CryptoJS)}(this,function(e){var t,r,i,u,n,o,a;return r=(t=e).lib,i=r.Base,u=r.WordArray,n=t.algo,o=n.MD5,a=n.EvpKDF=i.extend({cfg:i.extend({keySize:4,hasher:o,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var r,i=this.cfg,n=i.hasher.create(),o=u.create(),a=o.words,c=i.keySize,f=i.iterations;a.length<c;){r&&n.update(r),r=n.update(e).finalize(t),n.reset();for(var s=1;s<f;s++)r=n.finalize(r),n.reset();o.concat(r)}return o.sigBytes=4*c,o}}),t.EvpKDF=function(e,t,r){return a.create(r).compute(e,t)},e.EvpKDF});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/cipher-core.min.js
!function(e,t){"object"==typeof exports?module.exports=exports=t(require("./core"),require("./evpkdf")):"function"==typeof define&&define.amd?define(["./core","./evpkdf"],t):t(e.CryptoJS)}(this,function(m){m.lib.Cipher||function(){var e=m,t=e.lib,r=t.Base,a=t.WordArray,i=t.BufferedBlockAlgorithm,n=e.enc,c=(n.Utf8,n.Base64),o=e.algo.EvpKDF,s=t.Cipher=i.extend({cfg:r.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,r){this.cfg=this.cfg.extend(r),this._xformMode=e,this._key=t,this.reset()},reset:function(){i.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){return e&&this._append(e),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(i){return{encrypt:function(e,t,r){return f(t).encrypt(i,e,t,r)},decrypt:function(e,t,r){return f(t).decrypt(i,e,t,r)}}}});function f(e){return"string"==typeof e?g:k}t.StreamCipher=s.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var p,d=e.mode={},h=t.BlockCipherMode=r.extend({createEncryptor:function(e,t){return this.Encryptor.create(e,t)},createDecryptor:function(e,t){return this.Decryptor.create(e,t)},init:function(e,t){this._cipher=e,this._iv=t}}),u=d.CBC=((p=h.extend()).Encryptor=p.extend({processBlock:function(e,t){var r=this._cipher,i=r.blockSize;_.call(this,e,t,i),r.encryptBlock(e,t),this._prevBlock=e.slice(t,t+i)}}),p.Decryptor=p.extend({processBlock:function(e,t){var r=this._cipher,i=r.blockSize,n=e.slice(t,t+i);r.decryptBlock(e,t),_.call(this,e,t,i),this._prevBlock=n}}),p);function _(e,t,r){var i,n=this._iv;n?(i=n,this._iv=void 0):i=this._prevBlock;for(var c=0;c<r;c++)e[t+c]^=i[c]}var l=(e.pad={}).Pkcs7={pad:function(e,t){for(var r=4*t,i=r-e.sigBytes%r,n=i<<24|i<<16|i<<8|i,c=[],o=0;o<i;o+=4)c.push(n);var s=a.create(c,i);e.concat(s)},unpad:function(e){var t=255&e.words[e.sigBytes-1>>>2];e.sigBytes-=t}},y=(t.BlockCipher=s.extend({cfg:s.cfg.extend({mode:u,padding:l}),reset:function(){var e;s.reset.call(this);var t=this.cfg,r=t.iv,i=t.mode;this._xformMode==this._ENC_XFORM_MODE?e=i.createEncryptor:(e=i.createDecryptor,this._minBufferSize=1),this._mode&&this._mode.__creator==e?this._mode.init(this,r&&r.words):(this._mode=e.call(i,this,r&&r.words),this._mode.__creator=e)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e,t=this.cfg.padding;return this._xformMode==this._ENC_XFORM_MODE?(t.pad(this._data,this.blockSize),e=this._process(!0)):(e=this._process(!0),t.unpad(e)),e},blockSize:4}),t.CipherParams=r.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}})),v=(e.format={}).OpenSSL={stringify:function(e){var t=e.ciphertext,r=e.salt;return(r?a.create([1398893684,1701076831]).concat(r).concat(t):t).toString(c)},parse:function(e){var t,r=c.parse(e),i=r.words;return 1398893684==i[0]&&1701076831==i[1]&&(t=a.create(i.slice(2,4)),i.splice(0,4),r.sigBytes-=16),y.create({ciphertext:r,salt:t})}},k=t.SerializableCipher=r.extend({cfg:r.extend({format:v}),encrypt:function(e,t,r,i){i=this.cfg.extend(i);var n=e.createEncryptor(r,i),c=n.finalize(t),o=n.cfg;return y.create({ciphertext:c,key:r,iv:o.iv,algorithm:e,mode:o.mode,padding:o.padding,blockSize:e.blockSize,formatter:i.format})},decrypt:function(e,t,r,i){return i=this.cfg.extend(i),t=this._parse(t,i.format),e.createDecryptor(r,i).finalize(t.ciphertext)},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}}),x=(e.kdf={}).OpenSSL={execute:function(e,t,r,i){i=i||a.random(8);var n=o.create({keySize:t+r}).compute(e,i),c=a.create(n.words.slice(t),4*r);return n.sigBytes=4*t,y.create({key:n,iv:c,salt:i})}},g=t.PasswordBasedCipher=k.extend({cfg:k.cfg.extend({kdf:x}),encrypt:function(e,t,r,i){var n=(i=this.cfg.extend(i)).kdf.execute(r,e.keySize,e.ivSize);i.iv=n.iv;var c=k.encrypt.call(this,e,t,n.key,i);return c.mixIn(n),c},decrypt:function(e,t,r,i){i=this.cfg.extend(i),t=this._parse(t,i.format);var n=i.kdf.execute(r,e.keySize,e.ivSize,t.salt);return i.iv=n.iv,k.decrypt.call(this,e,t,n.key,i)}})}()});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/aes.min.js
!function(e,r){"object"==typeof exports?module.exports=exports=r(require("./core"),require("./enc-base64"),require("./md5"),require("./evpkdf"),require("./cipher-core")):"function"==typeof define&&define.amd?define(["./core","./enc-base64","./md5","./evpkdf","./cipher-core"],r):r(e.CryptoJS)}(this,function(t){return function(){var e=t,r=e.lib.BlockCipher,i=e.algo,f=[],u=[],h=[],y=[],a=[],p=[],v=[],_=[],k=[],l=[];!function(){for(var e=[],r=0;r<256;r++)e[r]=r<128?r<<1:r<<1^283;var i=0,o=0;for(r=0;r<256;r++){var t=o^o<<1^o<<2^o<<3^o<<4;t=t>>>8^255&t^99,f[i]=t;var n=e[u[t]=i],c=e[n],s=e[c],d=257*e[t]^16843008*t;h[i]=d<<24|d>>>8,y[i]=d<<16|d>>>16,a[i]=d<<8|d>>>24,p[i]=d;d=16843009*s^65537*c^257*n^16843008*i;v[t]=d<<24|d>>>8,_[t]=d<<16|d>>>16,k[t]=d<<8|d>>>24,l[t]=d,i?(i=n^e[e[e[s^n]]],o^=e[e[o]]):i=o=1}}();var S=[0,1,2,4,8,16,32,64,128,27,54],o=i.AES=r.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var e=this._keyPriorReset=this._key,r=e.words,i=e.sigBytes/4,o=4*(1+(this._nRounds=6+i)),t=this._keySchedule=[],n=0;n<o;n++)n<i?t[n]=r[n]:(d=t[n-1],n%i?6<i&&n%i==4&&(d=f[d>>>24]<<24|f[d>>>16&255]<<16|f[d>>>8&255]<<8|f[255&d]):(d=f[(d=d<<8|d>>>24)>>>24]<<24|f[d>>>16&255]<<16|f[d>>>8&255]<<8|f[255&d],d^=S[n/i|0]<<24),t[n]=t[n-i]^d);for(var c=this._invKeySchedule=[],s=0;s<o;s++){n=o-s;if(s%4)var d=t[n];else d=t[n-4];c[s]=s<4||n<=4?d:v[f[d>>>24]]^_[f[d>>>16&255]]^k[f[d>>>8&255]]^l[f[255&d]]}}},encryptBlock:function(e,r){this._doCryptBlock(e,r,this._keySchedule,h,y,a,p,f)},decryptBlock:function(e,r){var i=e[r+1];e[r+1]=e[r+3],e[r+3]=i,this._doCryptBlock(e,r,this._invKeySchedule,v,_,k,l,u);i=e[r+1];e[r+1]=e[r+3],e[r+3]=i},_doCryptBlock:function(e,r,i,o,t,n,c,s){for(var d=this._nRounds,f=e[r]^i[0],u=e[r+1]^i[1],h=e[r+2]^i[2],y=e[r+3]^i[3],a=4,p=1;p<d;p++){var v=o[f>>>24]^t[u>>>16&255]^n[h>>>8&255]^c[255&y]^i[a++],_=o[u>>>24]^t[h>>>16&255]^n[y>>>8&255]^c[255&f]^i[a++],k=o[h>>>24]^t[y>>>16&255]^n[f>>>8&255]^c[255&u]^i[a++],l=o[y>>>24]^t[f>>>16&255]^n[u>>>8&255]^c[255&h]^i[a++];f=v,u=_,h=k,y=l}v=(s[f>>>24]<<24|s[u>>>16&255]<<16|s[h>>>8&255]<<8|s[255&y])^i[a++],_=(s[u>>>24]<<24|s[h>>>16&255]<<16|s[y>>>8&255]<<8|s[255&f])^i[a++],k=(s[h>>>24]<<24|s[y>>>16&255]<<16|s[f>>>8&255]<<8|s[255&u])^i[a++],l=(s[y>>>24]<<24|s[f>>>16&255]<<16|s[u>>>8&255]<<8|s[255&h])^i[a++];e[r]=v,e[r+1]=_,e[r+2]=k,e[r+3]=l},keySize:8});e.AES=r._createHelper(o)}(),t.AES});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/pad-pkcs7.min.js
!function(e,r){"object"==typeof exports?module.exports=exports=r(require("./core"),require("./cipher-core")):"function"==typeof define&&define.amd?define(["./core","./cipher-core"],r):r(e.CryptoJS)}(this,function(e){return e.pad.Pkcs7});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/mode-ecb.min.js
!function(e,o){"object"==typeof exports?module.exports=exports=o(require("./core"),require("./cipher-core")):"function"==typeof define&&define.amd?define(["./core","./cipher-core"],o):o(e.CryptoJS)}(this,function(e){var o;return e.mode.ECB=((o=e.lib.BlockCipherMode.extend()).Encryptor=o.extend({processBlock:function(e,o){this._cipher.encryptBlock(e,o)}}),o.Decryptor=o.extend({processBlock:function(e,o){this._cipher.decryptBlock(e,o)}}),o),e.mode.ECB});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/enc-utf8.min.js
!function(e,o){"object"==typeof exports?module.exports=exports=o(require("./core")):"function"==typeof define&&define.amd?define(["./core"],o):o(e.CryptoJS)}(this,function(e){return e.enc.Utf8});
//https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/enc-hex.min.js
!function(e,o){"object"==typeof exports?module.exports=exports=o(require("./core")):"function"==typeof define&&define.amd?define(["./core"],o):o(e.CryptoJS)}(this,function(e){return e.enc.Hex});
</script>
<!-- 引入 CDN Crypto.js 结束 -->
</head>
<body>
<p>AES简介:</p>
<p>高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法,</p>
<p>也就是加密和解密用相同的密钥</p>
<p>微信小程序加密传输就是用这个加密算法的</p>
<p>我们公司禁止使用简易加密,如MD5编码、Base64编码、URL编码。</p>
<p>后台加密步骤为:对象=>JSON字符串=>加密=>JSON字符串=>前端</p>
<p>前端解密步骤为:解密=>JSON对象</p>
</body>
</html>
<script>
function getCrypt(){
var crypt_key = '049d65f30e854b08';//由后台提供
var crypt_iv = '98da515e3935c342';//由后台提供
var aes_key = CryptoJS.enc.Utf8.parse(crypt_key); //解析后的key
var new_iv = CryptoJS.enc.Utf8.parse(crypt_iv); //解析后的iv
var obj = {
iv: new_iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
function encrypt(data) {//以下加密
encrypted = CryptoJS.AES.encrypt(data, aes_key, obj);
return encrypted.toString()
}
function decrypt(data) {//以下解密
decrypted = CryptoJS.AES.decrypt(data, aes_key, obj);
return decrypted.toString(CryptoJS.enc.Utf8)
}
return{
encrypt:encrypt,
decrypt:decrypt
}
}
var crypt= getCrypt();
var strCrypt = 'zhangqiang,你好';
var getEncrypt = crypt.encrypt(strCrypt);
console.log(getEncrypt);
var getDecrypt = crypt.decrypt(getEncrypt);
console.log(getDecrypt);
//可以通过正则匹配将非JSON格式的字符串getDecrypt转化为JSON格式的字符串,再通过JSON.parse转化为JSON格式的对象,供页面使用。
//如果内层的某个对象需要以单引号字符串的形式展示在页面上,那么可以通过JSON.stringify将该对象转化为JSON格式的字符串,再通过正则匹配将双引号换成单引号
</script>
2、RSA加密
(1)jsencrypt.min.js
/*! For license information please see jsencrypt.min.js.LICENSE.txt */
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.JSEncrypt=e():t.JSEncrypt=e()}(window,(()=>(()=>{var t={155:t=>{var e,i,r=t.exports={};function n(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function o(t){if(e===setTimeout)return setTimeout(t,0);if((e===n||!e)&&setTimeout)return e=setTimeout,setTimeout(t,0);try{return e(t,0)}catch(i){try{return e.call(null,t,0)}catch(i){return e.call(this,t,0)}}}!function(){try{e="function"==typeof setTimeout?setTimeout:n}catch(t){e=n}try{i="function"==typeof clearTimeout?clearTimeout:s}catch(t){i=s}}();var h,a=[],u=!1,c=-1;function f(){u&&h&&(u=!1,h.length?a=h.concat(a):c=-1,a.length&&l())}function l(){if(!u){var t=o(f);u=!0;for(var e=a.length;e;){for(h=a,a=[];++c<e;)h&&h[c].run();c=-1,e=a.length}h=null,u=!1,function(t){if(i===clearTimeout)return clearTimeout(t);if((i===s||!i)&&clearTimeout)return i=clearTimeout,clearTimeout(t);try{i(t)}catch(e){try{return i.call(null,t)}catch(e){return i.call(this,t)}}}(t)}}function p(t,e){this.fun=t,this.array=e}function g(){}r.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var i=1;i<arguments.length;i++)e[i-1]=arguments[i];a.push(new p(t,e)),1!==a.length||u||o(l)},p.prototype.run=function(){this.fun.apply(null,this.array)},r.title="browser",r.browser=!0,r.env={},r.argv=[],r.version="",r.versions={},r.on=g,r.addListener=g,r.once=g,r.off=g,r.removeListener=g,r.removeAllListeners=g,r.emit=g,r.prependListener=g,r.prependOnceListener=g,r.listeners=function(t){return[]},r.binding=function(t){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(t){throw new Error("process.chdir is not supported")},r.umask=function(){return 0}}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var s=e[r]={exports:{}};return t[r](s,s.exports,i),s.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";function t(t){return"0123456789abcdefghijklmnopqrstuvwxyz".charAt(t)}function e(t,e){return t&e}function n(t,e){return t|e}function s(t,e){return t^e}function o(t,e){return t&~e}function h(t){if(0==t)return-1;var e=0;return 0==(65535&t)&&(t>>=16,e+=16),0==(255&t)&&(t>>=8,e+=8),0==(15&t)&&(t>>=4,e+=4),0==(3&t)&&(t>>=2,e+=2),0==(1&t)&&++e,e}function a(t){for(var e=0;0!=t;)t&=t-1,++e;return e}i.d(r,{default:()=>ot});var u,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function f(t){var e,i,r="";for(e=0;e+3<=t.length;e+=3)i=parseInt(t.substring(e,e+3),16),r+=c.charAt(i>>6)+c.charAt(63&i);for(e+1==t.length?(i=parseInt(t.substring(e,e+1),16),r+=c.charAt(i<<2)):e+2==t.length&&(i=parseInt(t.substring(e,e+2),16),r+=c.charAt(i>>2)+c.charAt((3&i)<<4));(3&r.length)>0;)r+="=";return r}function l(e){var i,r="",n=0,s=0;for(i=0;i<e.length&&"="!=e.charAt(i);++i){var o=c.indexOf(e.charAt(i));o<0||(0==n?(r+=t(o>>2),s=3&o,n=1):1==n?(r+=t(s<<2|o>>4),s=15&o,n=2):2==n?(r+=t(s),r+=t(o>>2),s=3&o,n=3):(r+=t(s<<2|o>>4),r+=t(15&o),n=0))}return 1==n&&(r+=t(s<<2)),r}var p,g={decode:function(t){var e;if(void 0===p){var i="= \f\n\r\t \u2028\u2029";for(p=Object.create(null),e=0;e<64;++e)p["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(e)]=e;for(p["-"]=62,p._=63,e=0;e<i.length;++e)p[i.charAt(e)]=-1}var r=[],n=0,s=0;for(e=0;e<t.length;++e){var o=t.charAt(e);if("="==o)break;if(-1!=(o=p[o])){if(void 0===o)throw new Error("Illegal character at offset "+e);n|=o,++s>=4?(r[r.length]=n>>16,r[r.length]=n>>8&255,r[r.length]=255&n,n=0,s=0):n<<=6}}switch(s){case 1:throw new Error("Base64 encoding incomplete: at least 2 bits missing");case 2:r[r.length]=n>>10;break;case 3:r[r.length]=n>>16,r[r.length]=n>>8&255}return r},re:/-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,unarmor:function(t){var e=g.re.exec(t);if(e)if(e[1])t=e[1];else{if(!e[2])throw new Error("RegExp out of sync");t=e[2]}return g.decode(t)}},d=1e13,v=function(){function t(t){this.buf=[+t||0]}return t.prototype.mulAdd=function(t,e){var i,r,n=this.buf,s=n.length;for(i=0;i<s;++i)(r=n[i]*t+e)<d?e=0:r-=(e=0|r/d)*d,n[i]=r;e>0&&(n[i]=e)},t.prototype.sub=function(t){var e,i,r=this.buf,n=r.length;for(e=0;e<n;++e)(i=r[e]-t)<0?(i+=d,t=1):t=0,r[e]=i;for(;0===r[r.length-1];)r.pop()},t.prototype.toString=function(t){if(10!=(t||10))throw new Error("only base 10 is supported");for(var e=this.buf,i=e[e.length-1].toString(),r=e.length-2;r>=0;--r)i+=(d+e[r]).toString().substring(1);return i},t.prototype.valueOf=function(){for(var t=this.buf,e=0,i=t.length-1;i>=0;--i)e=e*d+t[i];return e},t.prototype.simplify=function(){var t=this.buf;return 1==t.length?t[0]:this},t}(),m=/^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/,y=/^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;function b(t,e){return t.length>e&&(t=t.substring(0,e)+"…"),t}var T,S=function(){function t(e,i){this.hexDigits="0123456789ABCDEF",e instanceof t?(this.enc=e.enc,this.pos=e.pos):(this.enc=e,this.pos=i)}return t.prototype.get=function(t){if(void 0===t&&(t=this.pos++),t>=this.enc.length)throw new Error("Requesting byte offset ".concat(t," on a stream of length ").concat(this.enc.length));return"string"==typeof this.enc?this.enc.charCodeAt(t):this.enc[t]},t.prototype.hexByte=function(t){return this.hexDigits.charAt(t>>4&15)+this.hexDigits.charAt(15&t)},t.prototype.hexDump=function(t,e,i){for(var r="",n=t;n<e;++n)if(r+=this.hexByte(this.get(n)),!0!==i)switch(15&n){case 7:r+=" ";break;case 15:r+="\n";break;default:r+=" "}return r},t.prototype.isASCII=function(t,e){for(var i=t;i<e;++i){var r=this.get(i);if(r<32||r>176)return!1}return!0},t.prototype.parseStringISO=function(t,e){for(var i="",r=t;r<e;++r)i+=String.fromCharCode(this.get(r));return i},t.prototype.parseStringUTF=function(t,e){for(var i="",r=t;r<e;){var n=this.get(r++);i+=n<128?String.fromCharCode(n):n>191&&n<224?String.fromCharCode((31&n)<<6|63&this.get(r++)):String.fromCharCode((15&n)<<12|(63&this.get(r++))<<6|63&this.get(r++))}return i},t.prototype.parseStringBMP=function(t,e){for(var i,r,n="",s=t;s<e;)i=this.get(s++),r=this.get(s++),n+=String.fromCharCode(i<<8|r);return n},t.prototype.parseTime=function(t,e,i){var r=this.parseStringISO(t,e),n=(i?m:y).exec(r);return n?(i&&(n[1]=+n[1],n[1]+=+n[1]<70?2e3:1900),r=n[1]+"-"+n[2]+"-"+n[3]+" "+n[4],n[5]&&(r+=":"+n[5],n[6]&&(r+=":"+n[6],n[7]&&(r+="."+n[7]))),n[8]&&(r+=" UTC","Z"!=n[8]&&(r+=n[8],n[9]&&(r+=":"+n[9]))),r):"Unrecognized time: "+r},t.prototype.parseInteger=function(t,e){for(var i,r=this.get(t),n=r>127,s=n?255:0,o="";r==s&&++t<e;)r=this.get(t);if(0==(i=e-t))return n?-1:0;if(i>4){for(o=r,i<<=3;0==(128&(+o^s));)o=+o<<1,--i;o="("+i+" bit)\n"}n&&(r-=256);for(var h=new v(r),a=t+1;a<e;++a)h.mulAdd(256,this.get(a));return o+h.toString()},t.prototype.parseBitString=function(t,e,i){for(var r=this.get(t),n="("+((e-t-1<<3)-r)+" bit)\n",s="",o=t+1;o<e;++o){for(var h=this.get(o),a=o==e-1?r:0,u=7;u>=a;--u)s+=h>>u&1?"1":"0";if(s.length>i)return n+b(s,i)}return n+s},t.prototype.parseOctetString=function(t,e,i){if(this.isASCII(t,e))return b(this.parseStringISO(t,e),i);var r=e-t,n="("+r+" byte)\n";r>(i/=2)&&(e=t+i);for(var s=t;s<e;++s)n+=this.hexByte(this.get(s));return r>i&&(n+="…"),n},t.prototype.parseOID=function(t,e,i){for(var r="",n=new v,s=0,o=t;o<e;++o){var h=this.get(o);if(n.mulAdd(128,127&h),s+=7,!(128&h)){if(""===r)if((n=n.simplify())instanceof v)n.sub(80),r="2."+n.toString();else{var a=n<80?n<40?0:1:2;r=a+"."+(n-40*a)}else r+="."+n.toString();if(r.length>i)return b(r,i);n=new v,s=0}}return s>0&&(r+=".incomplete"),r},t}(),E=function(){function t(t,e,i,r,n){if(!(r instanceof w))throw new Error("Invalid tag value.");this.stream=t,this.header=e,this.length=i,this.tag=r,this.sub=n}return t.prototype.typeName=function(){switch(this.tag.tagClass){case 0:switch(this.tag.tagNumber){case 0:return"EOC";case 1:return"BOOLEAN";case 2:return"INTEGER";case 3:return"BIT_STRING";case 4:return"OCTET_STRING";case 5:return"NULL";case 6:return"OBJECT_IDENTIFIER";case 7:return"ObjectDescriptor";case 8:return"EXTERNAL";case 9:return"REAL";case 10:return"ENUMERATED";case 11:return"EMBEDDED_PDV";case 12:return"UTF8String";case 16:return"SEQUENCE";case 17:return"SET";case 18:return"NumericString";case 19:return"PrintableString";case 20:return"TeletexString";case 21:return"VideotexString";case 22:return"IA5String";case 23:return"UTCTime";case 24:return"GeneralizedTime";case 25:return"GraphicString";case 26:return"VisibleString";case 27:return"GeneralString";case 28:return"UniversalString";case 30:return"BMPString"}return"Universal_"+this.tag.tagNumber.toString();case 1:return"Application_"+this.tag.tagNumber.toString();case 2:return"["+this.tag.tagNumber.toString()+"]";case 3:return"Private_"+this.tag.tagNumber.toString()}},t.prototype.content=function(t){if(void 0===this.tag)return null;void 0===t&&(t=1/0);var e=this.posContent(),i=Math.abs(this.length);if(!this.tag.isUniversal())return null!==this.sub?"("+this.sub.length+" elem)":this.stream.parseOctetString(e,e+i,t);switch(this.tag.tagNumber){case 1:return 0===this.stream.get(e)?"false":"true";case 2:return this.stream.parseInteger(e,e+i);case 3:return this.sub?"("+this.sub.length+" elem)":this.stream.parseBitString(e,e+i,t);case 4:return this.sub?"("+this.sub.length+" elem)":this.stream.parseOctetString(e,e+i,t);case 6:return this.stream.parseOID(e,e+i,t);case 16:case 17:return null!==this.sub?"("+this.sub.length+" elem)":"(no elem)";case 12:return b(this.stream.parseStringUTF(e,e+i),t);case 18:case 19:case 20:case 21:case 22:case 26:return b(this.stream.parseStringISO(e,e+i),t);case 30:return b(this.stream.parseStringBMP(e,e+i),t);case 23:case 24:return this.stream.parseTime(e,e+i,23==this.tag.tagNumber)}return null},t.prototype.toString=function(){return this.typeName()+"@"+this.stream.pos+"[header:"+this.header+",length:"+this.length+",sub:"+(null===this.sub?"null":this.sub.length)+"]"},t.prototype.toPrettyString=function(t){void 0===t&&(t="");var e=t+this.typeName()+" @"+this.stream.pos;if(this.length>=0&&(e+="+"),e+=this.length,this.tag.tagConstructed?e+=" (constructed)":!this.tag.isUniversal()||3!=this.tag.tagNumber&&4!=this.tag.tagNumber||null===this.sub||(e+=" (encapsulates)"),e+="\n",null!==this.sub){t+=" ";for(var i=0,r=this.sub.length;i<r;++i)e+=this.sub[i].toPrettyString(t)}return e},t.prototype.posStart=function(){return this.stream.pos},t.prototype.posContent=function(){return this.stream.pos+this.header},t.prototype.posEnd=function(){return this.stream.pos+this.header+Math.abs(this.length)},t.prototype.toHexString=function(){return this.stream.hexDump(this.posStart(),this.posEnd(),!0)},t.decodeLength=function(t){var e=t.get(),i=127&e;if(i==e)return i;if(i>6)throw new Error("Length over 48 bits not supported at position "+(t.pos-1));if(0===i)return null;e=0;for(var r=0;r<i;++r)e=256*e+t.get();return e},t.prototype.getHexStringValue=function(){var t=this.toHexString(),e=2*this.header,i=2*this.length;return t.substr(e,i)},t.decode=function(e){var i;i=e instanceof S?e:new S(e,0);var r=new S(i),n=new w(i),s=t.decodeLength(i),o=i.pos,h=o-r.pos,a=null,u=function(){var e=[];if(null!==s){for(var r=o+s;i.pos<r;)e[e.length]=t.decode(i);if(i.pos!=r)throw new Error("Content size is not correct for container starting at offset "+o)}else try{for(;;){var n=t.decode(i);if(n.tag.isEOC())break;e[e.length]=n}s=o-i.pos}catch(t){throw new Error("Exception while decoding undefined length content: "+t)}return e};if(n.tagConstructed)a=u();else if(n.isUniversal()&&(3==n.tagNumber||4==n.tagNumber))try{if(3==n.tagNumber&&0!=i.get())throw new Error("BIT STRINGs with unused bits cannot encapsulate.");a=u();for(var c=0;c<a.length;++c)if(a[c].tag.isEOC())throw new Error("EOC is not supposed to be actual content.")}catch(t){a=null}if(null===a){if(null===s)throw new Error("We can't skip over an invalid tag with undefined length at offset "+o);i.pos=o+Math.abs(s)}return new t(r,h,s,n,a)},t}(),w=function(){function t(t){var e=t.get();if(this.tagClass=e>>6,this.tagConstructed=0!=(32&e),this.tagNumber=31&e,31==this.tagNumber){var i=new v;do{e=t.get(),i.mulAdd(128,127&e)}while(128&e);this.tagNumber=i.simplify()}}return t.prototype.isUniversal=function(){return 0===this.tagClass},t.prototype.isEOC=function(){return 0===this.tagClass&&0===this.tagNumber},t}(),D=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],x=(1<<26)/D[D.length-1],R=function(){function i(t,e,i){null!=t&&("number"==typeof t?this.fromNumber(t,e,i):null==e&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,e))}return i.prototype.toString=function(e){if(this.s<0)return"-"+this.negate().toString(e);var i;if(16==e)i=4;else if(8==e)i=3;else if(2==e)i=1;else if(32==e)i=5;else{if(4!=e)return this.toRadix(e);i=2}var r,n=(1<<i)-1,s=!1,o="",h=this.t,a=this.DB-h*this.DB%i;if(h-- >0)for(a<this.DB&&(r=this[h]>>a)>0&&(s=!0,o=t(r));h>=0;)a<i?(r=(this[h]&(1<<a)-1)<<i-a,r|=this[--h]>>(a+=this.DB-i)):(r=this[h]>>(a-=i)&n,a<=0&&(a+=this.DB,--h)),r>0&&(s=!0),s&&(o+=t(r));return s?o:"0"},i.prototype.negate=function(){var t=I();return i.ZERO.subTo(this,t),t},i.prototype.abs=function(){return this.s<0?this.negate():this},i.prototype.compareTo=function(t){var e=this.s-t.s;if(0!=e)return e;var i=this.t;if(0!=(e=i-t.t))return this.s<0?-e:e;for(;--i>=0;)if(0!=(e=this[i]-t[i]))return e;return 0},i.prototype.bitLength=function(){return this.t<=0?0:this.DB*(this.t-1)+C(this[this.t-1]^this.s&this.DM)},i.prototype.mod=function(t){var e=I();return this.abs().divRemTo(t,null,e),this.s<0&&e.compareTo(i.ZERO)>0&&t.subTo(e,e),e},i.prototype.modPowInt=function(t,e){var i;return i=t<256||e.isEven()?new O(e):new A(e),this.exp(t,i)},i.prototype.clone=function(){var t=I();return this.copyTo(t),t},i.prototype.intValue=function(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]},i.prototype.byteValue=function(){return 0==this.t?this.s:this[0]<<24>>24},i.prototype.shortValue=function(){return 0==this.t?this.s:this[0]<<16>>16},i.prototype.signum=function(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1},i.prototype.toByteArray=function(){var t=this.t,e=[];e[0]=this.s;var i,r=this.DB-t*this.DB%8,n=0;if(t-- >0)for(r<this.DB&&(i=this[t]>>r)!=(this.s&this.DM)>>r&&(e[n++]=i|this.s<<this.DB-r);t>=0;)r<8?(i=(this[t]&(1<<r)-1)<<8-r,i|=this[--t]>>(r+=this.DB-8)):(i=this[t]>>(r-=8)&255,r<=0&&(r+=this.DB,--t)),0!=(128&i)&&(i|=-256),0==n&&(128&this.s)!=(128&i)&&++n,(n>0||i!=this.s)&&(e[n++]=i);return e},i.prototype.equals=function(t){return 0==this.compareTo(t)},i.prototype.min=function(t){return this.compareTo(t)<0?this:t},i.prototype.max=function(t){return this.compareTo(t)>0?this:t},i.prototype.and=function(t){var i=I();return this.bitwiseTo(t,e,i),i},i.prototype.or=function(t){var e=I();return this.bitwiseTo(t,n,e),e},i.prototype.xor=function(t){var e=I();return this.bitwiseTo(t,s,e),e},i.prototype.andNot=function(t){var e=I();return this.bitwiseTo(t,o,e),e},i.prototype.not=function(){for(var t=I(),e=0;e<this.t;++e)t[e]=this.DM&~this[e];return t.t=this.t,t.s=~this.s,t},i.prototype.shiftLeft=function(t){var e=I();return t<0?this.rShiftTo(-t,e):this.lShiftTo(t,e),e},i.prototype.shiftRight=function(t){var e=I();return t<0?this.lShiftTo(-t,e):this.rShiftTo(t,e),e},i.prototype.getLowestSetBit=function(){for(var t=0;t<this.t;++t)if(0!=this[t])return t*this.DB+h(this[t]);return this.s<0?this.t*this.DB:-1},i.prototype.bitCount=function(){for(var t=0,e=this.s&this.DM,i=0;i<this.t;++i)t+=a(this[i]^e);return t},i.prototype.testBit=function(t){var e=Math.floor(t/this.DB);return e>=this.t?0!=this.s:0!=(this[e]&1<<t%this.DB)},i.prototype.setBit=function(t){return this.changeBit(t,n)},i.prototype.clearBit=function(t){return this.changeBit(t,o)},i.prototype.flipBit=function(t){return this.changeBit(t,s)},i.prototype.add=function(t){var e=I();return this.addTo(t,e),e},i.prototype.subtract=function(t){var e=I();return this.subTo(t,e),e},i.prototype.multiply=function(t){var e=I();return this.multiplyTo(t,e),e},i.prototype.divide=function(t){var e=I();return this.divRemTo(t,e,null),e},i.prototype.remainder=function(t){var e=I();return this.divRemTo(t,null,e),e},i.prototype.divideAndRemainder=function(t){var e=I(),i=I();return this.divRemTo(t,e,i),[e,i]},i.prototype.modPow=function(t,e){var i,r,n=t.bitLength(),s=H(1);if(n<=0)return s;i=n<18?1:n<48?3:n<144?4:n<768?5:6,r=n<8?new O(e):e.isEven()?new V(e):new A(e);var o=[],h=3,a=i-1,u=(1<<i)-1;if(o[1]=r.convert(this),i>1){var c=I();for(r.sqrTo(o[1],c);h<=u;)o[h]=I(),r.mulTo(c,o[h-2],o[h]),h+=2}var f,l,p=t.t-1,g=!0,d=I();for(n=C(t[p])-1;p>=0;){for(n>=a?f=t[p]>>n-a&u:(f=(t[p]&(1<<n+1)-1)<<a-n,p>0&&(f|=t[p-1]>>this.DB+n-a)),h=i;0==(1&f);)f>>=1,--h;if((n-=h)<0&&(n+=this.DB,--p),g)o[f].copyTo(s),g=!1;else{for(;h>1;)r.sqrTo(s,d),r.sqrTo(d,s),h-=2;h>0?r.sqrTo(s,d):(l=s,s=d,d=l),r.mulTo(d,o[f],s)}for(;p>=0&&0==(t[p]&1<<n);)r.sqrTo(s,d),l=s,s=d,d=l,--n<0&&(n=this.DB-1,--p)}return r.revert(s)},i.prototype.modInverse=function(t){var e=t.isEven();if(this.isEven()&&e||0==t.signum())return i.ZERO;for(var r=t.clone(),n=this.clone(),s=H(1),o=H(0),h=H(0),a=H(1);0!=r.signum();){for(;r.isEven();)r.rShiftTo(1,r),e?(s.isEven()&&o.isEven()||(s.addTo(this,s),o.subTo(t,o)),s.rShiftTo(1,s)):o.isEven()||o.subTo(t,o),o.rShiftTo(1,o);for(;n.isEven();)n.rShiftTo(1,n),e?(h.isEven()&&a.isEven()||(h.addTo(this,h),a.subTo(t,a)),h.rShiftTo(1,h)):a.isEven()||a.subTo(t,a),a.rShiftTo(1,a);r.compareTo(n)>=0?(r.subTo(n,r),e&&s.subTo(h,s),o.subTo(a,o)):(n.subTo(r,n),e&&h.subTo(s,h),a.subTo(o,a))}return 0!=n.compareTo(i.ONE)?i.ZERO:a.compareTo(t)>=0?a.subtract(t):a.signum()<0?(a.addTo(t,a),a.signum()<0?a.add(t):a):a},i.prototype.pow=function(t){return this.exp(t,new B)},i.prototype.gcd=function(t){var e=this.s<0?this.negate():this.clone(),i=t.s<0?t.negate():t.clone();if(e.compareTo(i)<0){var r=e;e=i,i=r}var n=e.getLowestSetBit(),s=i.getLowestSetBit();if(s<0)return e;for(n<s&&(s=n),s>0&&(e.rShiftTo(s,e),i.rShiftTo(s,i));e.signum()>0;)(n=e.getLowestSetBit())>0&&e.rShiftTo(n,e),(n=i.getLowestSetBit())>0&&i.rShiftTo(n,i),e.compareTo(i)>=0?(e.subTo(i,e),e.rShiftTo(1,e)):(i.subTo(e,i),i.rShiftTo(1,i));return s>0&&i.lShiftTo(s,i),i},i.prototype.isProbablePrime=function(t){var e,i=this.abs();if(1==i.t&&i[0]<=D[D.length-1]){for(e=0;e<D.length;++e)if(i[0]==D[e])return!0;return!1}if(i.isEven())return!1;for(e=1;e<D.length;){for(var r=D[e],n=e+1;n<D.length&&r<x;)r*=D[n++];for(r=i.modInt(r);e<n;)if(r%D[e++]==0)return!1}return i.millerRabin(t)},i.prototype.copyTo=function(t){for(var e=this.t-1;e>=0;--e)t[e]=this[e];t.t=this.t,t.s=this.s},i.prototype.fromInt=function(t){this.t=1,this.s=t<0?-1:0,t>0?this[0]=t:t<-1?this[0]=t+this.DV:this.t=0},i.prototype.fromString=function(t,e){var r;if(16==e)r=4;else if(8==e)r=3;else if(256==e)r=8;else if(2==e)r=1;else if(32==e)r=5;else{if(4!=e)return void this.fromRadix(t,e);r=2}this.t=0,this.s=0;for(var n=t.length,s=!1,o=0;--n>=0;){var h=8==r?255&+t[n]:q(t,n);h<0?"-"==t.charAt(n)&&(s=!0):(s=!1,0==o?this[this.t++]=h:o+r>this.DB?(this[this.t-1]|=(h&(1<<this.DB-o)-1)<<o,this[this.t++]=h>>this.DB-o):this[this.t-1]|=h<<o,(o+=r)>=this.DB&&(o-=this.DB))}8==r&&0!=(128&+t[0])&&(this.s=-1,o>0&&(this[this.t-1]|=(1<<this.DB-o)-1<<o)),this.clamp(),s&&i.ZERO.subTo(this,this)},i.prototype.clamp=function(){for(var t=this.s&this.DM;this.t>0&&this[this.t-1]==t;)--this.t},i.prototype.dlShiftTo=function(t,e){var i;for(i=this.t-1;i>=0;--i)e[i+t]=this[i];for(i=t-1;i>=0;--i)e[i]=0;e.t=this.t+t,e.s=this.s},i.prototype.drShiftTo=function(t,e){for(var i=t;i<this.t;++i)e[i-t]=this[i];e.t=Math.max(this.t-t,0),e.s=this.s},i.prototype.lShiftTo=function(t,e){for(var i=t%this.DB,r=this.DB-i,n=(1<<r)-1,s=Math.floor(t/this.DB),o=this.s<<i&this.DM,h=this.t-1;h>=0;--h)e[h+s+1]=this[h]>>r|o,o=(this[h]&n)<<i;for(h=s-1;h>=0;--h)e[h]=0;e[s]=o,e.t=this.t+s+1,e.s=this.s,e.clamp()},i.prototype.rShiftTo=function(t,e){e.s=this.s;var i=Math.floor(t/this.DB);if(i>=this.t)e.t=0;else{var r=t%this.DB,n=this.DB-r,s=(1<<r)-1;e[0]=this[i]>>r;for(var o=i+1;o<this.t;++o)e[o-i-1]|=(this[o]&s)<<n,e[o-i]=this[o]>>r;r>0&&(e[this.t-i-1]|=(this.s&s)<<n),e.t=this.t-i,e.clamp()}},i.prototype.subTo=function(t,e){for(var i=0,r=0,n=Math.min(t.t,this.t);i<n;)r+=this[i]-t[i],e[i++]=r&this.DM,r>>=this.DB;if(t.t<this.t){for(r-=t.s;i<this.t;)r+=this[i],e[i++]=r&this.DM,r>>=this.DB;r+=this.s}else{for(r+=this.s;i<t.t;)r-=t[i],e[i++]=r&this.DM,r>>=this.DB;r-=t.s}e.s=r<0?-1:0,r<-1?e[i++]=this.DV+r:r>0&&(e[i++]=r),e.t=i,e.clamp()},i.prototype.multiplyTo=function(t,e){var r=this.abs(),n=t.abs(),s=r.t;for(e.t=s+n.t;--s>=0;)e[s]=0;for(s=0;s<n.t;++s)e[s+r.t]=r.am(0,n[s],e,s,0,r.t);e.s=0,e.clamp(),this.s!=t.s&&i.ZERO.subTo(e,e)},i.prototype.squareTo=function(t){for(var e=this.abs(),i=t.t=2*e.t;--i>=0;)t[i]=0;for(i=0;i<e.t-1;++i){var r=e.am(i,e[i],t,2*i,0,1);(t[i+e.t]+=e.am(i+1,2*e[i],t,2*i+1,r,e.t-i-1))>=e.DV&&(t[i+e.t]-=e.DV,t[i+e.t+1]=1)}t.t>0&&(t[t.t-1]+=e.am(i,e[i],t,2*i,0,1)),t.s=0,t.clamp()},i.prototype.divRemTo=function(t,e,r){var n=t.abs();if(!(n.t<=0)){var s=this.abs();if(s.t<n.t)return null!=e&&e.fromInt(0),void(null!=r&&this.copyTo(r));null==r&&(r=I());var o=I(),h=this.s,a=t.s,u=this.DB-C(n[n.t-1]);u>0?(n.lShiftTo(u,o),s.lShiftTo(u,r)):(n.copyTo(o),s.copyTo(r));var c=o.t,f=o[c-1];if(0!=f){var l=f*(1<<this.F1)+(c>1?o[c-2]>>this.F2:0),p=this.FV/l,g=(1<<this.F1)/l,d=1<<this.F2,v=r.t,m=v-c,y=null==e?I():e;for(o.dlShiftTo(m,y),r.compareTo(y)>=0&&(r[r.t++]=1,r.subTo(y,r)),i.ONE.dlShiftTo(c,y),y.subTo(o,o);o.t<c;)o[o.t++]=0;for(;--m>=0;){var b=r[--v]==f?this.DM:Math.floor(r[v]*p+(r[v-1]+d)*g);if((r[v]+=o.am(0,b,r,m,0,c))<b)for(o.dlShiftTo(m,y),r.subTo(y,r);r[v]<--b;)r.subTo(y,r)}null!=e&&(r.drShiftTo(c,e),h!=a&&i.ZERO.subTo(e,e)),r.t=c,r.clamp(),u>0&&r.rShiftTo(u,r),h<0&&i.ZERO.subTo(r,r)}}},i.prototype.invDigit=function(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var e=3&t;return(e=(e=(e=(e=e*(2-(15&t)*e)&15)*(2-(255&t)*e)&255)*(2-((65535&t)*e&65535))&65535)*(2-t*e%this.DV)%this.DV)>0?this.DV-e:-e},i.prototype.isEven=function(){return 0==(this.t>0?1&this[0]:this.s)},i.prototype.exp=function(t,e){if(t>4294967295||t<1)return i.ONE;var r=I(),n=I(),s=e.convert(this),o=C(t)-1;for(s.copyTo(r);--o>=0;)if(e.sqrTo(r,n),(t&1<<o)>0)e.mulTo(n,s,r);else{var h=r;r=n,n=h}return e.revert(r)},i.prototype.chunkSize=function(t){return Math.floor(Math.LN2*this.DB/Math.log(t))},i.prototype.toRadix=function(t){if(null==t&&(t=10),0==this.signum()||t<2||t>36)return"0";var e=this.chunkSize(t),i=Math.pow(t,e),r=H(i),n=I(),s=I(),o="";for(this.divRemTo(r,n,s);n.signum()>0;)o=(i+s.intValue()).toString(t).substr(1)+o,n.divRemTo(r,n,s);return s.intValue().toString(t)+o},i.prototype.fromRadix=function(t,e){this.fromInt(0),null==e&&(e=10);for(var r=this.chunkSize(e),n=Math.pow(e,r),s=!1,o=0,h=0,a=0;a<t.length;++a){var u=q(t,a);u<0?"-"==t.charAt(a)&&0==this.signum()&&(s=!0):(h=e*h+u,++o>=r&&(this.dMultiply(n),this.dAddOffset(h,0),o=0,h=0))}o>0&&(this.dMultiply(Math.pow(e,o)),this.dAddOffset(h,0)),s&&i.ZERO.subTo(this,this)},i.prototype.fromNumber=function(t,e,r){if("number"==typeof e)if(t<2)this.fromInt(1);else for(this.fromNumber(t,r),this.testBit(t-1)||this.bitwiseTo(i.ONE.shiftLeft(t-1),n,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(e);)this.dAddOffset(2,0),this.bitLength()>t&&this.subTo(i.ONE.shiftLeft(t-1),this);else{var s=[],o=7&t;s.length=1+(t>>3),e.nextBytes(s),o>0?s[0]&=(1<<o)-1:s[0]=0,this.fromString(s,256)}},i.prototype.bitwiseTo=function(t,e,i){var r,n,s=Math.min(t.t,this.t);for(r=0;r<s;++r)i[r]=e(this[r],t[r]);if(t.t<this.t){for(n=t.s&this.DM,r=s;r<this.t;++r)i[r]=e(this[r],n);i.t=this.t}else{for(n=this.s&this.DM,r=s;r<t.t;++r)i[r]=e(n,t[r]);i.t=t.t}i.s=e(this.s,t.s),i.clamp()},i.prototype.changeBit=function(t,e){var r=i.ONE.shiftLeft(t);return this.bitwiseTo(r,e,r),r},i.prototype.addTo=function(t,e){for(var i=0,r=0,n=Math.min(t.t,this.t);i<n;)r+=this[i]+t[i],e[i++]=r&this.DM,r>>=this.DB;if(t.t<this.t){for(r+=t.s;i<this.t;)r+=this[i],e[i++]=r&this.DM,r>>=this.DB;r+=this.s}else{for(r+=this.s;i<t.t;)r+=t[i],e[i++]=r&this.DM,r>>=this.DB;r+=t.s}e.s=r<0?-1:0,r>0?e[i++]=r:r<-1&&(e[i++]=this.DV+r),e.t=i,e.clamp()},i.prototype.dMultiply=function(t){this[this.t]=this.am(0,t-1,this,0,0,this.t),++this.t,this.clamp()},i.prototype.dAddOffset=function(t,e){if(0!=t){for(;this.t<=e;)this[this.t++]=0;for(this[e]+=t;this[e]>=this.DV;)this[e]-=this.DV,++e>=this.t&&(this[this.t++]=0),++this[e]}},i.prototype.multiplyLowerTo=function(t,e,i){var r=Math.min(this.t+t.t,e);for(i.s=0,i.t=r;r>0;)i[--r]=0;for(var n=i.t-this.t;r<n;++r)i[r+this.t]=this.am(0,t[r],i,r,0,this.t);for(n=Math.min(t.t,e);r<n;++r)this.am(0,t[r],i,r,0,e-r);i.clamp()},i.prototype.multiplyUpperTo=function(t,e,i){--e;var r=i.t=this.t+t.t-e;for(i.s=0;--r>=0;)i[r]=0;for(r=Math.max(e-this.t,0);r<t.t;++r)i[this.t+r-e]=this.am(e-r,t[r],i,0,0,this.t+r-e);i.clamp(),i.drShiftTo(1,i)},i.prototype.modInt=function(t){if(t<=0)return 0;var e=this.DV%t,i=this.s<0?t-1:0;if(this.t>0)if(0==e)i=this[0]%t;else for(var r=this.t-1;r>=0;--r)i=(e*i+this[r])%t;return i},i.prototype.millerRabin=function(t){var e=this.subtract(i.ONE),r=e.getLowestSetBit();if(r<=0)return!1;var n=e.shiftRight(r);(t=t+1>>1)>D.length&&(t=D.length);for(var s=I(),o=0;o<t;++o){s.fromInt(D[Math.floor(Math.random()*D.length)]);var h=s.modPow(n,this);if(0!=h.compareTo(i.ONE)&&0!=h.compareTo(e)){for(var a=1;a++<r&&0!=h.compareTo(e);)if(0==(h=h.modPowInt(2,this)).compareTo(i.ONE))return!1;if(0!=h.compareTo(e))return!1}}return!0},i.prototype.square=function(){var t=I();return this.squareTo(t),t},i.prototype.gcda=function(t,e){var i=this.s<0?this.negate():this.clone(),r=t.s<0?t.negate():t.clone();if(i.compareTo(r)<0){var n=i;i=r,r=n}var s=i.getLowestSetBit(),o=r.getLowestSetBit();if(o<0)e(i);else{s<o&&(o=s),o>0&&(i.rShiftTo(o,i),r.rShiftTo(o,r));var h=function(){(s=i.getLowestSetBit())>0&&i.rShiftTo(s,i),(s=r.getLowestSetBit())>0&&r.rShiftTo(s,r),i.compareTo(r)>=0?(i.subTo(r,i),i.rShiftTo(1,i)):(r.subTo(i,r),r.rShiftTo(1,r)),i.signum()>0?setTimeout(h,0):(o>0&&r.lShiftTo(o,r),setTimeout((function(){e(r)}),0))};setTimeout(h,10)}},i.prototype.fromNumberAsync=function(t,e,r,s){if("number"==typeof e)if(t<2)this.fromInt(1);else{this.fromNumber(t,r),this.testBit(t-1)||this.bitwiseTo(i.ONE.shiftLeft(t-1),n,this),this.isEven()&&this.dAddOffset(1,0);var o=this,h=function(){o.dAddOffset(2,0),o.bitLength()>t&&o.subTo(i.ONE.shiftLeft(t-1),o),o.isProbablePrime(e)?setTimeout((function(){s()}),0):setTimeout(h,0)};setTimeout(h,0)}else{var a=[],u=7&t;a.length=1+(t>>3),e.nextBytes(a),u>0?a[0]&=(1<<u)-1:a[0]=0,this.fromString(a,256)}},i}(),B=function(){function t(){}return t.prototype.convert=function(t){return t},t.prototype.revert=function(t){return t},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i)},t.prototype.sqrTo=function(t,e){t.squareTo(e)},t}(),O=function(){function t(t){this.m=t}return t.prototype.convert=function(t){return t.s<0||t.compareTo(this.m)>=0?t.mod(this.m):t},t.prototype.revert=function(t){return t},t.prototype.reduce=function(t){t.divRemTo(this.m,null,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}(),A=function(){function t(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<<t.DB-15)-1,this.mt2=2*t.t}return t.prototype.convert=function(t){var e=I();return t.abs().dlShiftTo(this.m.t,e),e.divRemTo(this.m,null,e),t.s<0&&e.compareTo(R.ZERO)>0&&this.m.subTo(e,e),e},t.prototype.revert=function(t){var e=I();return t.copyTo(e),this.reduce(e),e},t.prototype.reduce=function(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var e=0;e<this.m.t;++e){var i=32767&t[e],r=i*this.mpl+((i*this.mph+(t[e]>>15)*this.mpl&this.um)<<15)&t.DM;for(t[i=e+this.m.t]+=this.m.am(0,r,t,e,0,this.m.t);t[i]>=t.DV;)t[i]-=t.DV,t[++i]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}(),V=function(){function t(t){this.m=t,this.r2=I(),this.q3=I(),R.ONE.dlShiftTo(2*t.t,this.r2),this.mu=this.r2.divide(t)}return t.prototype.convert=function(t){if(t.s<0||t.t>2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var e=I();return t.copyTo(e),this.reduce(e),e},t.prototype.revert=function(t){return t},t.prototype.reduce=function(t){for(t.drShiftTo(this.m.t-1,this.r2),t.t>this.m.t+1&&(t.t=this.m.t+1,t.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);t.compareTo(this.r2)<0;)t.dAddOffset(1,this.m.t+1);for(t.subTo(this.r2,t);t.compareTo(this.m)>=0;)t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}();function I(){return new R(null)}function N(t,e){return new R(t,e)}var P="undefined"!=typeof navigator;P&&"Microsoft Internet Explorer"==navigator.appName?(R.prototype.am=function(t,e,i,r,n,s){for(var o=32767&e,h=e>>15;--s>=0;){var a=32767&this[t],u=this[t++]>>15,c=h*a+u*o;n=((a=o*a+((32767&c)<<15)+i[r]+(1073741823&n))>>>30)+(c>>>15)+h*u+(n>>>30),i[r++]=1073741823&a}return n},T=30):P&&"Netscape"!=navigator.appName?(R.prototype.am=function(t,e,i,r,n,s){for(;--s>=0;){var o=e*this[t++]+i[r]+n;n=Math.floor(o/67108864),i[r++]=67108863&o}return n},T=26):(R.prototype.am=function(t,e,i,r,n,s){for(var o=16383&e,h=e>>14;--s>=0;){var a=16383&this[t],u=this[t++]>>14,c=h*a+u*o;n=((a=o*a+((16383&c)<<14)+i[r]+n)>>28)+(c>>14)+h*u,i[r++]=268435455&a}return n},T=28),R.prototype.DB=T,R.prototype.DM=(1<<T)-1,R.prototype.DV=1<<T,R.prototype.FV=Math.pow(2,52),R.prototype.F1=52-T,R.prototype.F2=2*T-52;var M,L,j=[];for(M="0".charCodeAt(0),L=0;L<=9;++L)j[M++]=L;for(M="a".charCodeAt(0),L=10;L<36;++L)j[M++]=L;for(M="A".charCodeAt(0),L=10;L<36;++L)j[M++]=L;function q(t,e){var i=j[t.charCodeAt(e)];return null==i?-1:i}function H(t){var e=I();return e.fromInt(t),e}function C(t){var e,i=1;return 0!=(e=t>>>16)&&(t=e,i+=16),0!=(e=t>>8)&&(t=e,i+=8),0!=(e=t>>4)&&(t=e,i+=4),0!=(e=t>>2)&&(t=e,i+=2),0!=(e=t>>1)&&(t=e,i+=1),i}R.ZERO=H(0),R.ONE=H(1);var F,U,K=function(){function t(){this.i=0,this.j=0,this.S=[]}return t.prototype.init=function(t){var e,i,r;for(e=0;e<256;++e)this.S[e]=e;for(i=0,e=0;e<256;++e)i=i+this.S[e]+t[e%t.length]&255,r=this.S[e],this.S[e]=this.S[i],this.S[i]=r;this.i=0,this.j=0},t.prototype.next=function(){var t;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,t=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=t,this.S[t+this.S[this.i]&255]},t}(),k=null;if(null==k){k=[],U=0;var _=void 0;if("undefined"!=typeof window&&window.crypto&&window.crypto.getRandomValues){var z=new Uint32Array(256);for(window.crypto.getRandomValues(z),_=0;_<z.length;++_)k[U++]=255&z[_]}var Z=0,G=function(t){if((Z=Z||0)>=256||U>=256)window.removeEventListener?window.removeEventListener("mousemove",G,!1):window.detachEvent&&window.detachEvent("onmousemove",G);else try{var e=t.x+t.y;k[U++]=255&e,Z+=1}catch(t){}};"undefined"!=typeof window&&(window.addEventListener?window.addEventListener("mousemove",G,!1):window.attachEvent&&window.attachEvent("onmousemove",G))}function $(){if(null==F){for(F=new K;U<256;){var t=Math.floor(65536*Math.random());k[U++]=255&t}for(F.init(k),U=0;U<k.length;++U)k[U]=0;U=0}return F.next()}var Y=function(){function t(){}return t.prototype.nextBytes=function(t){for(var e=0;e<t.length;++e)t[e]=$()},t}(),J=function(){function t(){this.n=null,this.e=0,this.d=null,this.p=null,this.q=null,this.dmp1=null,this.dmq1=null,this.coeff=null}return t.prototype.doPublic=function(t){return t.modPowInt(this.e,this.n)},t.prototype.doPrivate=function(t){if(null==this.p||null==this.q)return t.modPow(this.d,this.n);for(var e=t.mod(this.p).modPow(this.dmp1,this.p),i=t.mod(this.q).modPow(this.dmq1,this.q);e.compareTo(i)<0;)e=e.add(this.p);return e.subtract(i).multiply(this.coeff).mod(this.p).multiply(this.q).add(i)},t.prototype.setPublic=function(t,e){null!=t&&null!=e&&t.length>0&&e.length>0?(this.n=N(t,16),this.e=parseInt(e,16)):console.error("Invalid RSA public key")},t.prototype.encrypt=function(t){var e=this.n.bitLength()+7>>3,i=function(t,e){if(e<t.length+11)return console.error("Message too long for RSA"),null;for(var i=[],r=t.length-1;r>=0&&e>0;){var n=t.charCodeAt(r--);n<128?i[--e]=n:n>127&&n<2048?(i[--e]=63&n|128,i[--e]=n>>6|192):(i[--e]=63&n|128,i[--e]=n>>6&63|128,i[--e]=n>>12|224)}i[--e]=0;for(var s=new Y,o=[];e>2;){for(o[0]=0;0==o[0];)s.nextBytes(o);i[--e]=o[0]}return i[--e]=2,i[--e]=0,new R(i)}(t,e);if(null==i)return null;var r=this.doPublic(i);if(null==r)return null;for(var n=r.toString(16),s=n.length,o=0;o<2*e-s;o++)n="0"+n;return n},t.prototype.setPrivate=function(t,e,i){null!=t&&null!=e&&t.length>0&&e.length>0?(this.n=N(t,16),this.e=parseInt(e,16),this.d=N(i,16)):console.error("Invalid RSA private key")},t.prototype.setPrivateEx=function(t,e,i,r,n,s,o,h){null!=t&&null!=e&&t.length>0&&e.length>0?(this.n=N(t,16),this.e=parseInt(e,16),this.d=N(i,16),this.p=N(r,16),this.q=N(n,16),this.dmp1=N(s,16),this.dmq1=N(o,16),this.coeff=N(h,16)):console.error("Invalid RSA private key")},t.prototype.generate=function(t,e){var i=new Y,r=t>>1;this.e=parseInt(e,16);for(var n=new R(e,16);;){for(;this.p=new R(t-r,1,i),0!=this.p.subtract(R.ONE).gcd(n).compareTo(R.ONE)||!this.p.isProbablePrime(10););for(;this.q=new R(r,1,i),0!=this.q.subtract(R.ONE).gcd(n).compareTo(R.ONE)||!this.q.isProbablePrime(10););if(this.p.compareTo(this.q)<=0){var s=this.p;this.p=this.q,this.q=s}var o=this.p.subtract(R.ONE),h=this.q.subtract(R.ONE),a=o.multiply(h);if(0==a.gcd(n).compareTo(R.ONE)){this.n=this.p.multiply(this.q),this.d=n.modInverse(a),this.dmp1=this.d.mod(o),this.dmq1=this.d.mod(h),this.coeff=this.q.modInverse(this.p);break}}},t.prototype.decrypt=function(t){var e=N(t,16),i=this.doPrivate(e);return null==i?null:function(t,e){for(var i=t.toByteArray(),r=0;r<i.length&&0==i[r];)++r;if(i.length-r!=e-1||2!=i[r])return null;for(++r;0!=i[r];)if(++r>=i.length)return null;for(var n="";++r<i.length;){var s=255&i[r];s<128?n+=String.fromCharCode(s):s>191&&s<224?(n+=String.fromCharCode((31&s)<<6|63&i[r+1]),++r):(n+=String.fromCharCode((15&s)<<12|(63&i[r+1])<<6|63&i[r+2]),r+=2)}return n}(i,this.n.bitLength()+7>>3)},t.prototype.generateAsync=function(t,e,i){var r=new Y,n=t>>1;this.e=parseInt(e,16);var s=new R(e,16),o=this,h=function(){var e=function(){if(o.p.compareTo(o.q)<=0){var t=o.p;o.p=o.q,o.q=t}var e=o.p.subtract(R.ONE),r=o.q.subtract(R.ONE),n=e.multiply(r);0==n.gcd(s).compareTo(R.ONE)?(o.n=o.p.multiply(o.q),o.d=s.modInverse(n),o.dmp1=o.d.mod(e),o.dmq1=o.d.mod(r),o.coeff=o.q.modInverse(o.p),setTimeout((function(){i()}),0)):setTimeout(h,0)},a=function(){o.q=I(),o.q.fromNumberAsync(n,1,r,(function(){o.q.subtract(R.ONE).gcda(s,(function(t){0==t.compareTo(R.ONE)&&o.q.isProbablePrime(10)?setTimeout(e,0):setTimeout(a,0)}))}))},u=function(){o.p=I(),o.p.fromNumberAsync(t-n,1,r,(function(){o.p.subtract(R.ONE).gcda(s,(function(t){0==t.compareTo(R.ONE)&&o.p.isProbablePrime(10)?setTimeout(a,0):setTimeout(u,0)}))}))};setTimeout(u,0)};setTimeout(h,0)},t.prototype.sign=function(t,e,i){var r=function(t,e){if(e<t.length+22)return console.error("Message too long for RSA"),null;for(var i=e-t.length-6,r="",n=0;n<i;n+=2)r+="ff";return N("0001"+r+"00"+t,16)}((X[i]||"")+e(t).toString(),this.n.bitLength()/4);if(null==r)return null;var n=this.doPrivate(r);if(null==n)return null;var s=n.toString(16);return 0==(1&s.length)?s:"0"+s},t.prototype.verify=function(t,e,i){var r=N(e,16),n=this.doPublic(r);return null==n?null:function(t){for(var e in X)if(X.hasOwnProperty(e)){var i=X[e],r=i.length;if(t.substr(0,r)==i)return t.substr(r)}return t}(n.toString(16).replace(/^1f+00/,""))==i(t).toString()},t}(),X={md2:"3020300c06082a864886f70d020205000410",md5:"3020300c06082a864886f70d020505000410",sha1:"3021300906052b0e03021a05000414",sha224:"302d300d06096086480165030402040500041c",sha256:"3031300d060960864801650304020105000420",sha384:"3041300d060960864801650304020205000430",sha512:"3051300d060960864801650304020305000440",ripemd160:"3021300906052b2403020105000414"},Q={};Q.lang={extend:function(t,e,i){if(!e||!t)throw new Error("YAHOO.lang.extend failed, please check that all dependencies are included.");var r=function(){};if(r.prototype=e.prototype,t.prototype=new r,t.prototype.constructor=t,t.superclass=e.prototype,e.prototype.constructor==Object.prototype.constructor&&(e.prototype.constructor=e),i){var n;for(n in i)t.prototype[n]=i[n];var s=function(){},o=["toString","valueOf"];try{/MSIE/.test(navigator.userAgent)&&(s=function(t,e){for(n=0;n<o.length;n+=1){var i=o[n],r=e[i];"function"==typeof r&&r!=Object.prototype[i]&&(t[i]=r)}})}catch(t){}s(t.prototype,i)}}};var W={};void 0!==W.asn1&&W.asn1||(W.asn1={}),W.asn1.ASN1Util=new function(){this.integerToByteHex=function(t){var e=t.toString(16);return e.length%2==1&&(e="0"+e),e},this.bigIntToMinTwosComplementsHex=function(t){var e=t.toString(16);if("-"!=e.substr(0,1))e.length%2==1?e="0"+e:e.match(/^[0-7]/)||(e="00"+e);else{var i=e.substr(1).length;i%2==1?i+=1:e.match(/^[0-7]/)||(i+=2);for(var r="",n=0;n<i;n++)r+="f";e=new R(r,16).xor(t).add(R.ONE).toString(16).replace(/^-/,"")}return e},this.getPEMStringFromHex=function(t,e){return hextopem(t,e)},this.newObject=function(t){var e=W.asn1,i=e.DERBoolean,r=e.DERInteger,n=e.DERBitString,s=e.DEROctetString,o=e.DERNull,h=e.DERObjectIdentifier,a=e.DEREnumerated,u=e.DERUTF8String,c=e.DERNumericString,f=e.DERPrintableString,l=e.DERTeletexString,p=e.DERIA5String,g=e.DERUTCTime,d=e.DERGeneralizedTime,v=e.DERSequence,m=e.DERSet,y=e.DERTaggedObject,b=e.ASN1Util.newObject,T=Object.keys(t);if(1!=T.length)throw"key of param shall be only one.";var S=T[0];if(-1==":bool:int:bitstr:octstr:null:oid:enum:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":"+S+":"))throw"undefined key: "+S;if("bool"==S)return new i(t[S]);if("int"==S)return new r(t[S]);if("bitstr"==S)return new n(t[S]);if("octstr"==S)return new s(t[S]);if("null"==S)return new o(t[S]);if("oid"==S)return new h(t[S]);if("enum"==S)return new a(t[S]);if("utf8str"==S)return new u(t[S]);if("numstr"==S)return new c(t[S]);if("prnstr"==S)return new f(t[S]);if("telstr"==S)return new l(t[S]);if("ia5str"==S)return new p(t[S]);if("utctime"==S)return new g(t[S]);if("gentime"==S)return new d(t[S]);if("seq"==S){for(var E=t[S],w=[],D=0;D<E.length;D++){var x=b(E[D]);w.push(x)}return new v({array:w})}if("set"==S){for(E=t[S],w=[],D=0;D<E.length;D++)x=b(E[D]),w.push(x);return new m({array:w})}if("tag"==S){var R=t[S];if("[object Array]"===Object.prototype.toString.call(R)&&3==R.length){var B=b(R[2]);return new y({tag:R[0],explicit:R[1],obj:B})}var O={};if(void 0!==R.explicit&&(O.explicit=R.explicit),void 0!==R.tag&&(O.tag=R.tag),void 0===R.obj)throw"obj shall be specified for 'tag'.";return O.obj=b(R.obj),new y(O)}},this.jsonToASN1HEX=function(t){return this.newObject(t).getEncodedHex()}},W.asn1.ASN1Util.oidHexToInt=function(t){for(var e="",i=parseInt(t.substr(0,2),16),r=(e=Math.floor(i/40)+"."+i%40,""),n=2;n<t.length;n+=2){var s=("00000000"+parseInt(t.substr(n,2),16).toString(2)).slice(-8);r+=s.substr(1,7),"0"==s.substr(0,1)&&(e=e+"."+new R(r,2).toString(10),r="")}return e},W.asn1.ASN1Util.oidIntToHex=function(t){var e=function(t){var e=t.toString(16);return 1==e.length&&(e="0"+e),e},i=function(t){var i="",r=new R(t,10).toString(2),n=7-r.length%7;7==n&&(n=0);for(var s="",o=0;o<n;o++)s+="0";for(r=s+r,o=0;o<r.length-1;o+=7){var h=r.substr(o,7);o!=r.length-7&&(h="1"+h),i+=e(parseInt(h,2))}return i};if(!t.match(/^[0-9.]+$/))throw"malformed oid string: "+t;var r="",n=t.split("."),s=40*parseInt(n[0])+parseInt(n[1]);r+=e(s),n.splice(0,2);for(var o=0;o<n.length;o++)r+=i(n[o]);return r},W.asn1.ASN1Object=function(){this.getLengthHexFromValue=function(){if(void 0===this.hV||null==this.hV)throw"this.hV is null or undefined.";if(this.hV.length%2==1)throw"value hex must be even length: n="+"".length+",v="+this.hV;var t=this.hV.length/2,e=t.toString(16);if(e.length%2==1&&(e="0"+e),t<128)return e;var i=e.length/2;if(i>15)throw"ASN.1 length too long to represent by 8x: n = "+t.toString(16);return(128+i).toString(16)+e},this.getEncodedHex=function(){return(null==this.hTLV||this.isModified)&&(this.hV=this.getFreshValueHex(),this.hL=this.getLengthHexFromValue(),this.hTLV=this.hT+this.hL+this.hV,this.isModified=!1),this.hTLV},this.getValueHex=function(){return this.getEncodedHex(),this.hV},this.getFreshValueHex=function(){return""}},W.asn1.DERAbstractString=function(t){W.asn1.DERAbstractString.superclass.constructor.call(this),this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(this.s)},this.setStringHex=function(t){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&("string"==typeof t?this.setString(t):void 0!==t.str?this.setString(t.str):void 0!==t.hex&&this.setStringHex(t.hex))},Q.lang.extend(W.asn1.DERAbstractString,W.asn1.ASN1Object),W.asn1.DERAbstractTime=function(t){W.asn1.DERAbstractTime.superclass.constructor.call(this),this.localDateToUTC=function(t){return utc=t.getTime()+6e4*t.getTimezoneOffset(),new Date(utc)},this.formatDate=function(t,e,i){var r=this.zeroPadding,n=this.localDateToUTC(t),s=String(n.getFullYear());"utc"==e&&(s=s.substr(2,2));var o=s+r(String(n.getMonth()+1),2)+r(String(n.getDate()),2)+r(String(n.getHours()),2)+r(String(n.getMinutes()),2)+r(String(n.getSeconds()),2);if(!0===i){var h=n.getMilliseconds();if(0!=h){var a=r(String(h),3);o=o+"."+(a=a.replace(/[0]+$/,""))}}return o+"Z"},this.zeroPadding=function(t,e){return t.length>=e?t:new Array(e-t.length+1).join("0")+t},this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(t)},this.setByDateValue=function(t,e,i,r,n,s){var o=new Date(Date.UTC(t,e-1,i,r,n,s,0));this.setByDate(o)},this.getFreshValueHex=function(){return this.hV}},Q.lang.extend(W.asn1.DERAbstractTime,W.asn1.ASN1Object),W.asn1.DERAbstractStructured=function(t){W.asn1.DERAbstractString.superclass.constructor.call(this),this.setByASN1ObjectArray=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array=t},this.appendASN1Object=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array.push(t)},this.asn1Array=new Array,void 0!==t&&void 0!==t.array&&(this.asn1Array=t.array)},Q.lang.extend(W.asn1.DERAbstractStructured,W.asn1.ASN1Object),W.asn1.DERBoolean=function(){W.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},Q.lang.extend(W.asn1.DERBoolean,W.asn1.ASN1Object),W.asn1.DERInteger=function(t){W.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(t){this.hTLV=null,this.isModified=!0,this.hV=W.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t)},this.setByInteger=function(t){var e=new R(String(t),10);this.setByBigInteger(e)},this.setValueHex=function(t){this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.bigint?this.setByBigInteger(t.bigint):void 0!==t.int?this.setByInteger(t.int):"number"==typeof t?this.setByInteger(t):void 0!==t.hex&&this.setValueHex(t.hex))},Q.lang.extend(W.asn1.DERInteger,W.asn1.ASN1Object),W.asn1.DERBitString=function(t){if(void 0!==t&&void 0!==t.obj){var e=W.asn1.ASN1Util.newObject(t.obj);t.hex="00"+e.getEncodedHex()}W.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(t){this.hTLV=null,this.isModified=!0,this.hV=t},this.setUnusedBitsAndHexValue=function(t,e){if(t<0||7<t)throw"unused bits shall be from 0 to 7: u = "+t;var i="0"+t;this.hTLV=null,this.isModified=!0,this.hV=i+e},this.setByBinaryString=function(t){var e=8-(t=t.replace(/0+$/,"")).length%8;8==e&&(e=0);for(var i=0;i<=e;i++)t+="0";var r="";for(i=0;i<t.length-1;i+=8){var n=t.substr(i,8),s=parseInt(n,2).toString(16);1==s.length&&(s="0"+s),r+=s}this.hTLV=null,this.isModified=!0,this.hV="0"+e+r},this.setByBooleanArray=function(t){for(var e="",i=0;i<t.length;i++)1==t[i]?e+="1":e+="0";this.setByBinaryString(e)},this.newFalseArray=function(t){for(var e=new Array(t),i=0;i<t;i++)e[i]=!1;return e},this.getFreshValueHex=function(){return this.hV},void 0!==t&&("string"==typeof t&&t.toLowerCase().match(/^[0-9a-f]+$/)?this.setHexValueIncludingUnusedBits(t):void 0!==t.hex?this.setHexValueIncludingUnusedBits(t.hex):void 0!==t.bin?this.setByBinaryString(t.bin):void 0!==t.array&&this.setByBooleanArray(t.array))},Q.lang.extend(W.asn1.DERBitString,W.asn1.ASN1Object),W.asn1.DEROctetString=function(t){if(void 0!==t&&void 0!==t.obj){var e=W.asn1.ASN1Util.newObject(t.obj);t.hex=e.getEncodedHex()}W.asn1.DEROctetString.superclass.constructor.call(this,t),this.hT="04"},Q.lang.extend(W.asn1.DEROctetString,W.asn1.DERAbstractString),W.asn1.DERNull=function(){W.asn1.DERNull.superclass.constructor.call(this),this.hT="05",this.hTLV="0500"},Q.lang.extend(W.asn1.DERNull,W.asn1.ASN1Object),W.asn1.DERObjectIdentifier=function(t){var e=function(t){var e=t.toString(16);return 1==e.length&&(e="0"+e),e},i=function(t){var i="",r=new R(t,10).toString(2),n=7-r.length%7;7==n&&(n=0);for(var s="",o=0;o<n;o++)s+="0";for(r=s+r,o=0;o<r.length-1;o+=7){var h=r.substr(o,7);o!=r.length-7&&(h="1"+h),i+=e(parseInt(h,2))}return i};W.asn1.DERObjectIdentifier.superclass.constructor.call(this),this.hT="06",this.setValueHex=function(t){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=t},this.setValueOidString=function(t){if(!t.match(/^[0-9.]+$/))throw"malformed oid string: "+t;var r="",n=t.split("."),s=40*parseInt(n[0])+parseInt(n[1]);r+=e(s),n.splice(0,2);for(var o=0;o<n.length;o++)r+=i(n[o]);this.hTLV=null,this.isModified=!0,this.s=null,this.hV=r},this.setValueName=function(t){var e=W.asn1.x509.OID.name2oid(t);if(""===e)throw"DERObjectIdentifier oidName undefined: "+t;this.setValueOidString(e)},this.getFreshValueHex=function(){return this.hV},void 0!==t&&("string"==typeof t?t.match(/^[0-2].[0-9.]+$/)?this.setValueOidString(t):this.setValueName(t):void 0!==t.oid?this.setValueOidString(t.oid):void 0!==t.hex?this.setValueHex(t.hex):void 0!==t.name&&this.setValueName(t.name))},Q.lang.extend(W.asn1.DERObjectIdentifier,W.asn1.ASN1Object),W.asn1.DEREnumerated=function(t){W.asn1.DEREnumerated.superclass.constructor.call(this),this.hT="0a",this.setByBigInteger=function(t){this.hTLV=null,this.isModified=!0,this.hV=W.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t)},this.setByInteger=function(t){var e=new R(String(t),10);this.setByBigInteger(e)},this.setValueHex=function(t){this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.int?this.setByInteger(t.int):"number"==typeof t?this.setByInteger(t):void 0!==t.hex&&this.setValueHex(t.hex))},Q.lang.extend(W.asn1.DEREnumerated,W.asn1.ASN1Object),W.asn1.DERUTF8String=function(t){W.asn1.DERUTF8String.superclass.constructor.call(this,t),this.hT="0c"},Q.lang.extend(W.asn1.DERUTF8String,W.asn1.DERAbstractString),W.asn1.DERNumericString=function(t){W.asn1.DERNumericString.superclass.constructor.call(this,t),this.hT="12"},Q.lang.extend(W.asn1.DERNumericString,W.asn1.DERAbstractString),W.asn1.DERPrintableString=function(t){W.asn1.DERPrintableString.superclass.constructor.call(this,t),this.hT="13"},Q.lang.extend(W.asn1.DERPrintableString,W.asn1.DERAbstractString),W.asn1.DERTeletexString=function(t){W.asn1.DERTeletexString.superclass.constructor.call(this,t),this.hT="14"},Q.lang.extend(W.asn1.DERTeletexString,W.asn1.DERAbstractString),W.asn1.DERIA5String=function(t){W.asn1.DERIA5String.superclass.constructor.call(this,t),this.hT="16"},Q.lang.extend(W.asn1.DERIA5String,W.asn1.DERAbstractString),W.asn1.DERUTCTime=function(t){W.asn1.DERUTCTime.superclass.constructor.call(this,t),this.hT="17",this.setByDate=function(t){this.hTLV=null,this.isModified=!0,this.date=t,this.s=this.formatDate(this.date,"utc"),this.hV=stohex(this.s)},this.getFreshValueHex=function(){return void 0===this.date&&void 0===this.s&&(this.date=new Date,this.s=this.formatDate(this.date,"utc"),this.hV=stohex(this.s)),this.hV},void 0!==t&&(void 0!==t.str?this.setString(t.str):"string"==typeof t&&t.match(/^[0-9]{12}Z$/)?this.setString(t):void 0!==t.hex?this.setStringHex(t.hex):void 0!==t.date&&this.setByDate(t.date))},Q.lang.extend(W.asn1.DERUTCTime,W.asn1.DERAbstractTime),W.asn1.DERGeneralizedTime=function(t){W.asn1.DERGeneralizedTime.superclass.constructor.call(this,t),this.hT="18",this.withMillis=!1,this.setByDate=function(t){this.hTLV=null,this.isModified=!0,this.date=t,this.s=this.formatDate(this.date,"gen",this.withMillis),this.hV=stohex(this.s)},this.getFreshValueHex=function(){return void 0===this.date&&void 0===this.s&&(this.date=new Date,this.s=this.formatDate(this.date,"gen",this.withMillis),this.hV=stohex(this.s)),this.hV},void 0!==t&&(void 0!==t.str?this.setString(t.str):"string"==typeof t&&t.match(/^[0-9]{14}Z$/)?this.setString(t):void 0!==t.hex?this.setStringHex(t.hex):void 0!==t.date&&this.setByDate(t.date),!0===t.millis&&(this.withMillis=!0))},Q.lang.extend(W.asn1.DERGeneralizedTime,W.asn1.DERAbstractTime),W.asn1.DERSequence=function(t){W.asn1.DERSequence.superclass.constructor.call(this,t),this.hT="30",this.getFreshValueHex=function(){for(var t="",e=0;e<this.asn1Array.length;e++)t+=this.asn1Array[e].getEncodedHex();return this.hV=t,this.hV}},Q.lang.extend(W.asn1.DERSequence,W.asn1.DERAbstractStructured),W.asn1.DERSet=function(t){W.asn1.DERSet.superclass.constructor.call(this,t),this.hT="31",this.sortFlag=!0,this.getFreshValueHex=function(){for(var t=new Array,e=0;e<this.asn1Array.length;e++){var i=this.asn1Array[e];t.push(i.getEncodedHex())}return 1==this.sortFlag&&t.sort(),this.hV=t.join(""),this.hV},void 0!==t&&void 0!==t.sortflag&&0==t.sortflag&&(this.sortFlag=!1)},Q.lang.extend(W.asn1.DERSet,W.asn1.DERAbstractStructured),W.asn1.DERTaggedObject=function(t){W.asn1.DERTaggedObject.superclass.constructor.call(this),this.hT="a0",this.hV="",this.isExplicit=!0,this.asn1Object=null,this.setASN1Object=function(t,e,i){this.hT=e,this.isExplicit=t,this.asn1Object=i,this.isExplicit?(this.hV=this.asn1Object.getEncodedHex(),this.hTLV=null,this.isModified=!0):(this.hV=null,this.hTLV=i.getEncodedHex(),this.hTLV=this.hTLV.replace(/^../,e),this.isModified=!1)},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.tag&&(this.hT=t.tag),void 0!==t.explicit&&(this.isExplicit=t.explicit),void 0!==t.obj&&(this.asn1Object=t.obj,this.setASN1Object(this.isExplicit,this.hT,this.asn1Object)))},Q.lang.extend(W.asn1.DERTaggedObject,W.asn1.ASN1Object);var tt,et,it=(tt=function(t,e){return tt=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i])},tt(t,e)},function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function i(){this.constructor=t}tt(t,e),t.prototype=null===e?Object.create(e):(i.prototype=e.prototype,new i)}),rt=function(t){function e(i){var r=t.call(this)||this;return i&&("string"==typeof i?r.parseKey(i):(e.hasPrivateKeyProperty(i)||e.hasPublicKeyProperty(i))&&r.parsePropertiesFrom(i)),r}return it(e,t),e.prototype.parseKey=function(t){try{var e=0,i=0,r=/^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/.test(t)?function(t){var e;if(void 0===u){var i="0123456789ABCDEF",r=" \f\n\r\t \u2028\u2029";for(u={},e=0;e<16;++e)u[i.charAt(e)]=e;for(i=i.toLowerCase(),e=10;e<16;++e)u[i.charAt(e)]=e;for(e=0;e<r.length;++e)u[r.charAt(e)]=-1}var n=[],s=0,o=0;for(e=0;e<t.length;++e){var h=t.charAt(e);if("="==h)break;if(-1!=(h=u[h])){if(void 0===h)throw new Error("Illegal character at offset "+e);s|=h,++o>=2?(n[n.length]=s,s=0,o=0):s<<=4}}if(o)throw new Error("Hex encoding incomplete: 4 bits missing");return n}(t):g.unarmor(t),n=E.decode(r);if(3===n.sub.length&&(n=n.sub[2].sub[0]),9===n.sub.length){e=n.sub[1].getHexStringValue(),this.n=N(e,16),i=n.sub[2].getHexStringValue(),this.e=parseInt(i,16);var s=n.sub[3].getHexStringValue();this.d=N(s,16);var o=n.sub[4].getHexStringValue();this.p=N(o,16);var h=n.sub[5].getHexStringValue();this.q=N(h,16);var a=n.sub[6].getHexStringValue();this.dmp1=N(a,16);var c=n.sub[7].getHexStringValue();this.dmq1=N(c,16);var f=n.sub[8].getHexStringValue();this.coeff=N(f,16)}else{if(2!==n.sub.length)return!1;if(n.sub[0].sub){var l=n.sub[1].sub[0];e=l.sub[0].getHexStringValue(),this.n=N(e,16),i=l.sub[1].getHexStringValue(),this.e=parseInt(i,16)}else e=n.sub[0].getHexStringValue(),this.n=N(e,16),i=n.sub[1].getHexStringValue(),this.e=parseInt(i,16)}return!0}catch(t){return!1}},e.prototype.getPrivateBaseKey=function(){var t={array:[new W.asn1.DERInteger({int:0}),new W.asn1.DERInteger({bigint:this.n}),new W.asn1.DERInteger({int:this.e}),new W.asn1.DERInteger({bigint:this.d}),new W.asn1.DERInteger({bigint:this.p}),new W.asn1.DERInteger({bigint:this.q}),new W.asn1.DERInteger({bigint:this.dmp1}),new W.asn1.DERInteger({bigint:this.dmq1}),new W.asn1.DERInteger({bigint:this.coeff})]};return new W.asn1.DERSequence(t).getEncodedHex()},e.prototype.getPrivateBaseKeyB64=function(){return f(this.getPrivateBaseKey())},e.prototype.getPublicBaseKey=function(){var t=new W.asn1.DERSequence({array:[new W.asn1.DERObjectIdentifier({oid:"1.2.840.113549.1.1.1"}),new W.asn1.DERNull]}),e=new W.asn1.DERSequence({array:[new W.asn1.DERInteger({bigint:this.n}),new W.asn1.DERInteger({int:this.e})]}),i=new W.asn1.DERBitString({hex:"00"+e.getEncodedHex()});return new W.asn1.DERSequence({array:[t,i]}).getEncodedHex()},e.prototype.getPublicBaseKeyB64=function(){return f(this.getPublicBaseKey())},e.wordwrap=function(t,e){if(!t)return t;var i="(.{1,"+(e=e||64)+"})( +|$\n?)|(.{1,"+e+"})";return t.match(RegExp(i,"g")).join("\n")},e.prototype.getPrivateKey=function(){var t="-----BEGIN RSA PRIVATE KEY-----\n";return(t+=e.wordwrap(this.getPrivateBaseKeyB64())+"\n")+"-----END RSA PRIVATE KEY-----"},e.prototype.getPublicKey=function(){var t="-----BEGIN PUBLIC KEY-----\n";return(t+=e.wordwrap(this.getPublicBaseKeyB64())+"\n")+"-----END PUBLIC KEY-----"},e.hasPublicKeyProperty=function(t){return(t=t||{}).hasOwnProperty("n")&&t.hasOwnProperty("e")},e.hasPrivateKeyProperty=function(t){return(t=t||{}).hasOwnProperty("n")&&t.hasOwnProperty("e")&&t.hasOwnProperty("d")&&t.hasOwnProperty("p")&&t.hasOwnProperty("q")&&t.hasOwnProperty("dmp1")&&t.hasOwnProperty("dmq1")&&t.hasOwnProperty("coeff")},e.prototype.parsePropertiesFrom=function(t){this.n=t.n,this.e=t.e,t.hasOwnProperty("d")&&(this.d=t.d,this.p=t.p,this.q=t.q,this.dmp1=t.dmp1,this.dmq1=t.dmq1,this.coeff=t.coeff)},e}(J),nt=i(155),st=void 0!==nt?null===(et=nt.env)||void 0===et?void 0:"3.3.1":void 0;const ot=function(){function t(t){void 0===t&&(t={}),t=t||{},this.default_key_size=t.default_key_size?parseInt(t.default_key_size,10):1024,this.default_public_exponent=t.default_public_exponent||"010001",this.log=t.log||!1,this.key=null}return t.prototype.setKey=function(t){this.log&&this.key&&console.warn("A key was already set, overriding existing."),this.key=new rt(t)},t.prototype.setPrivateKey=function(t){this.setKey(t)},t.prototype.setPublicKey=function(t){this.setKey(t)},t.prototype.decrypt=function(t){try{return this.getKey().decrypt(l(t))}catch(t){return!1}},t.prototype.encrypt=function(t){try{return f(this.getKey().encrypt(t))}catch(t){return!1}},t.prototype.sign=function(t,e,i){try{return f(this.getKey().sign(t,e,i))}catch(t){return!1}},t.prototype.verify=function(t,e,i){try{return this.getKey().verify(t,l(e),i)}catch(t){return!1}},t.prototype.getKey=function(t){if(!this.key){if(this.key=new rt,t&&"[object Function]"==={}.toString.call(t))return void this.key.generateAsync(this.default_key_size,this.default_public_exponent,t);this.key.generate(this.default_key_size,this.default_public_exponent)}return this.key},t.prototype.getPrivateKey=function(){return this.getKey().getPrivateKey()},t.prototype.getPrivateKeyB64=function(){return this.getKey().getPrivateBaseKeyB64()},t.prototype.getPublicKey=function(){return this.getKey(). getPublicKey()},t.prototype.getPublicKeyB64=function(){return this.getKey().getPublicBaseKeyB64()},t.version=st,t}()})(),r.default})()));
(2)封装
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
//密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSKLqzcWmOzbfj64K8ZIgOdH\n' +
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4jvbuccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey = 'MIIBVAIBADANBgFAddddgggggAAkEAqhHyZfSsYourNxaY\n' +
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'UP8iWi1Qw0Y='
//加密
export function encrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) //设置公钥
return encryptor.encrypt(txt) //对数据进行加密
}
//解密
export function decrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) //设置私钥
return encryptor.decrypt(txt) //对数据进行解密
}
(3)使用
import { encrypt, decrypt } from "@/utils/jsencrypt";
function handleLogin() {
proxy.$refs.loginRef.validate((valid) => {
if (valid) {
loading.value = true;
//勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.name, { expires: 30 });
Cookies.set("password", encrypt(loginForm.value.pwd), {
expires: 30,
});
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
} else {
//否则移除
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
}
//调用action的登录方法
userStore
.login(loginForm.value)
.then(() => {
router.push({ path: redirect.value || "/" });
})
.catch((error) => {
console.log(error)
loading.value = false;
//重新获取验证码
});
}
});
}
二、js编码与解码,
附、前后台数据交换,
A、前端先把自己能收集到的数据格式“转化”为后台所需要的数据格式,然后发给后台
B、前端接到后台返回的数据格式后,先“转化”成前端能读取的数据格式,然后插到页面
1、基本概念,位->字节->字符->字符集
(1)bit,位,1个bit有2种状态,0或1,比特
(2)byte,字节,1个字节由8个位构成
(3)字符,文字或符号,1个字符消耗1--2个字节,1个英文字符消耗1个字节,1个汉字字符消耗2个字节
(4)字符集,字符的集合,字符集的读取规则,内置于计算机,用户在html或img标签中指明使用哪种字符集,如ASCII、base64、Unicode、gb-2312
2、ASCII字符集,八位二进制,共256个字符,1967年第一次发表
(1)状态,1个二进制位2个状态、8个二进制位256个状态(从0000000到11111111)
(2)字符,1个状态对应1个字符,256个状态对应256个字符,以0开始的128个状态对应128个英文字符,以1开始的128个状态对应128个非英文字符
(3)128个英文字符包含,33个控制字符或通信专用字符、64个base64字符、31个其它字符!"#$%&'()*,-.:;<=>?@[\]^_`{|}~空
(4)应用,这256个字符能够描述所有格式的数据,如文字、符号、图像、音频、视频
(5)ASCII定义,American Standard Code for Information Interchange,美国信息交换标准代码,是最通用的信息交换标准
3、base64字符集,六位二进制,共64个字符,1987年,第一次提及
(1)状态,1个二进制位2个状态、6个二进制位64个状态(从00000到111111)
(2)字符,1个状态对应1个字符,64个状态对应64个字符,
(3)64个字符包含,52个大小写字母、10个数字、1个+、1个/,另有第65个填充字符=
(4)应用,这64个字符能够描述所有格式的数据,如文字、符号、图像、音频、视频
4、Unicode字符集,1990年开始研发,1994年正式发布1.0版本,2022年9月13日发布15.0版本
来源,https://c.runoob.com/front-end/3602/
(1)该字符集的1个字符用1个编码对应,100多万个字符对应100多万个编码,可以容纳世界上所有的字符
(2)该字符集的编码规则有,UTF-8、UTF-16、UTF-32等嗯
(3)str.charCodeAt,获取字符的Unicode编码,是十进制数字
来源,https://www.w3cschool.cn/typescript/typescript_string_charcodeat.html
A、参数为字符串索引,如果参数不在0到字符串长度之间,返回NaN
B、返回值字符的Unicode编码,是十进制数字,0到1114111(7位,百万级)之间,可以通过toString(n)转换为n进制
C、例如console.log('中国'.charCodeAt(0));console.log('中国'.charCodeAt(0).toString(16))
(4)String.fromCharCode,获取Unicode编码对应的字符,
来源,https://www.runoob.com/jsref/jsref-fromcharcode.html
A、参数,可以多个,每个都是Unicode编码,都是十进制数字,console.log(String.fromCharCode(104,101,108,108,111))
B、返回值为字符,可以多个
C、例如console.log(String.fromCharCode(20013));console.log(String.fromCharCode(parseInt('4e2d',16)));M
5、window编码与解码--ASCII和base64之间的转换
注、URI,统一资源标识符
(1)window.atob,base64字符转换为ASCII字符
(2)window.btoa,ASCII字符转换为base64字符
(3)window.escape,将字符串转换为Unicode编码的字符串
(4)window.unescape,将escape编码的字符串恢复为原始字符串
(5)window.encodeURIComponent,将URI组件的字符串转换为UTF-8编码的字符串,如空格会被转换为%20
const data = { userId:123, username:"JohnDoe", email:"john@example.com" };
const jsonData = JSON.stringify(data);
const encodedData = encodeURIComponent(jsonData);
const url = `https://example.com?data=${encodedData}`;
(6)window.decodeURIComponent,将encodeURIComponent编码的UTF-8字符串解码回原始的字符串形式
const encodedAndDecoded = () => {
const data = { userId:123, username:"JohnDoe" };
const jsonData = JSON.stringify(data);
const encodedData = encodeURIComponent(jsonData);
const decodedData = decodeURIComponent(encodedData);
console.log( jsonData );
console.log( encodedData );
console.log( decodedData );
}
(7)btoa和atob编码和解码,以非中文示例
var encodedData = window.btoa(123456);//'MTIzNDU2'
var decodedData = window.atob(encodedData);//'123456'
(8)btoa和atob编码和解码,以中文示例
var encodedData = window.btoa(window.escape(window.encodeURIComponent('你好')));//JTI1RTQlMjVCRCUyNUEwJTI1RTUlMjVBNSUyNUJE
var decodedData = window.decodeURIComponent(window.unescape(window.atob(encodedData)));//你好
console.log( encodedData );
console.log( decodedData );
6、常见的JS二进制“数据格式”之ArrayBuffer和Uint8Array(建立在ArrayBuffer上)数据的介绍
来源,https://www.w3cschool.cn/qoyhx/qoyhx-8h5w3q7u.html
来源,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
(1)new ArrayBuffer(11),创建一个长度为11的buffer
A、参数是一个数字
B、ArrayBuffer,二进制数组,对固定长度的连续内存空间的引用
(2)new Uint8Array(length),是存储二进制数据的
A、参数为1个数组,数组的每1项都是1个Unicode编码,1个汉字需要3个编码
B、字符-字节(数字)
C、Uint8Array.from,参数为(字符串,函数),返回值Uint8Array数组,
7、常见的JS二进制“数据格式”之Blob和File(继承了Blob)数据的介绍
来源,https://www.w3cschool.cn/qoyhx/qoyhx-l63p3q7x.html
(1)Blob,二进制大对象(binary large object),1970年代出现,是一种数据格式
(2)File,继承了Blob
(3)Blob和File数据读取方法
A、readAsArrayBuffer,读-取为二进制格式的ArrayBuffer
B、readAsBinaryString,读-取为二进制字符串
C、readAsDataURL,读-取为base64的url,常用于img标签的src属性,
D、readAsText,读-取为给定编码(默认为utf-8编码)的文本字符串,
(4)Blob和File数据读取为文字
var reader = new FileReader();
reader.readAsText(thisBlob, 'utf8'); //把后台的blob字符串转化为最初的文字
reader.onload = function() {
console.log( '原文:' + this.result )
}
(5)Blob和File数据,在浏览器中,读取为url-小文件,不适合读视频
change(file) {
const reader = new FileReader()
reader.readAsDataURL(file.raw) //把file.raw原始文件对象(如File或Blob),转换为Base64编码的DataURL
reader.onload = (event) => {
this.option.clientImg = event.target.result
this.cutDialogVisible = true
}
}
(6)Blob和File数据,在浏览器中,读取为url-大文件,适合读视频
change(file) {
const URL = window.URL||window.webkitURL;
this.option.clientImg = URL.createObjectURL(file.raw); //根据file.raw原始文件对象(如File或Blob),生成一个临时URL
this.cutDialogVisible = true;
}
(7)将Base64编码的Data URL转换(转化)成浏览器可操作的File对象,可用于上传canvas图片给后台
function dataURLtoBlob(dataUrl, filename) {
var array = dataUrl.split(','); //src="data:image/png;base64,iVBOGBHNR"
var mime = array[0].match(/:(.*?);/)[1];
var bstr = atob(array[1]); //1、将“base64编码”的图片,转化为“ASCII编码”的图片
var num = bstr.length;
var array8 = new Uint8Array(num);
while (num--) {
array8[num] = bstr.charCodeAt(num); //2、将ASCII编码的字符,转化为Unicode编码,并用Uint8Array存储
}
return new File([array8], filename, { type: mime }); //3、将Unicode编码,转化为“Blob编码”,type指定blob的类型
}
8、数据格式互转
(1)原文与uint8Array互转,用到TextEncoder和TextDecoder
function utf8ToUint8Array(text) {
//以下,原文转uint8Array,将字符串编码为UTF-8字节序列,返回一个Uint8Array对象
var uint8Array = new TextEncoder().encode(text);
//以下,uint8Array转原文,将二进制数据(如Uint8Array)解码为字符串,返回一个字符串
var text = new TextDecoder().decode(uint8Array);
console.log(text);
}
var text1 = "Hello,你好!";
utf8ToUint8Array(text1);
(2)原文与base64互转
function fromTextToText1(text) {
//正转换,base64<--(Unicode编码对应的ASCII)字符<--Uint8Array<--原文(text)
var before = btoa(String.fromCharCode(...new TextEncoder().encode(text)));
//反转换,原文<--Uint8Array<--(Unicode编码对应的ASCII)字符<--base64(before)
var after = new TextDecoder().decode(
Uint8Array.from(atob(before), function(item){
return item.charCodeAt(0)
})
)
console.log(before, after);
}
var text1 = "Hello,你好!";
fromTextToText1(text1);
(3)原文与blob互转
function stringToBlob(str) {
//以下,原文转blob
const encoder = new TextEncoder();
const uint8Array = encoder.encode(str);
const thisBlob = new Blob([uint8Array], { type: 'text/plain' });
console.log(thisBlob);
//以下,blob转原文
var reader = new FileReader();
reader.readAsText(thisBlob, 'utf8');
reader.onload = function() {
console.log('原文:' + this.result )
}
}
const myString = "Hello, Blob!";
stringToBlob(myString);
(4)base64与blob互转
function fromTextToText2(text) {
//以下,生成base64
var base64Str = btoa(String.fromCharCode(...new TextEncoder().encode(text)))
//以下,base64生成blob
var atobStr = atob(base64Str); //1、把base64字符串转化为ASCII字符串
var length = atobStr.length;
var uint8Array = new Uint8Array(length);//也可以写成new Array(length);
while (length--) {
uint8Array[length] = atobStr.charCodeAt(length); //2、把ASCII字符串转化为Unicode编码,存储在Uint8Array里
}
var thisBlob = new Blob([uint8Array], { type: 'text/plain' }); //3、把ASCII字符串转化为blob字符串
//以下,blob生成base64
var reader = new FileReader();
reader.onload = function() {
const base64String = reader.result.split(',');
console.log(uint8Array)
console.log(thisBlob)
console.log(base64String)
};
reader.readAsDataURL(thisBlob);
}
var text2 = "Hello,你好2!";
fromTextToText2(text2);
三、数据上传
来源,https://blog.csdn.net/zyx042299/article/details/128008334
来源,https://www.w3school.com.cn/tags/att_label_for.asp
附1、label标签的for属性,与表单元素的id属性绑定,点击label标签内的文本,就会触发绑定的表单元素
显式的联系,<label for="SSN">身份证号码:</label><input type="text" name="IdNum" id="SSN" />
隐式的联系,<label>生日:<input type="text" name="DofB" /></label>
附2、通过onchange事件,获取要上传的(二进制)数据 <input type="file" onchange="changeFile(value)" v-model="value"/>
附3、FormData是JS中用于创建FormData对象的构造函数,对象提供的键值对可以模拟表单数据的格式
var formData = new FormData();//创建一个空对象
formData.set('key', 'data1');//用新值覆盖已有的值
formData.append('key', 'data2');//新增一组name相同,value不同的键值对
formData.append('file', element.raw)
console.log(formData);
for (var pair of formData.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
// FormData {
// [Symbol(state)]: [ { name: 'key', value: 'data1' }, { name: 'key', value: 'data2' } ]
// }
// key: data1
// key: data2
附4、new FormData()与new Object()的区别,注意下5行的编码规则enctype
A、new FormData(),专为表单和文件上传设计,适合上传二进制文件
B、new Object(),通用数据容器,适合JSON格式的数据交互
1、数据上传-普通上传
(1)自动上传
<form
name="myForm"//new formData(document.forms["myForm"]).set('value', 'value')
action="demo_form.php"//提交表单时,服务器的接收地址
enctype="multipart/form-data"
//(1)application/x-www-form-urlencoded 在发送前编码所有字符(默认)
//(2)multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
//(3)text/plain 空格转换为 "+" 加号,但不对特殊字符编码。
>
<input name="myInput" type="text"/> //input标签的name属性需要与它的type属性同时使用,
<input name="inputFile" type="file"/> //type的取值可以是text、password、radio、checkbox
<select name="mySelect"></select> //设置了name属性的表单元素,才能在提交表单时,自动传递它们的值
<input type="submit" value="默认提交"/> //点击就上传数据
</form>
(2)手动上传
A、为空追加
<form>
<input v-model="value" type="file"/>
<input type="button" value="自定义提交" @click="submitForm()">
</form>
function submitForm() {
var formData = new formData();
formData.set('key', 'data1');
formData.append('key', 'data2');
$.ajax({
url: '',
type: 'post',
data: formData,
});
}
B、非空追加
<form
name="myForm"
>//document.forms["myForm"]
<input name="inputValue" type="text"/>
<select name="mySelect"></select>
<input name="inputFile" type="file"/>
<input name="protocolScript" type="file"/> //这是angular1的相关内容
<input type="button" value="自定义提交" onclick="submitForm()">
<input type="button" value="自定义提交" ng-click="submitForm()">
</form>
function submitForm() {
var myForm = document.forms["myForm"];
var formData= new formData(myForm);//格式化具有name属性的字段
formData.set('key', 'data1');
formData.append('key', 'data2');
$.ajax({
url: '',
type: 'post',
data: formData,
});
}
C、angular1示例
<input name="protocolScript" type="file" //这是angular1的相关内容
onchange="angular.element(this).scope().onChangeFile(this)" //原生事件,实参this是input上传的内容
on-change="ngChangeFile(value)" //非原生事件,value为空
/>
$scope.ngChangeFile = function (ele) {
$scope.files_list = ele.files;
$scope.$apply();
};
D、elementUI/Plus</input>上传(PC端)
注意、不要配置:before-upload="beforeUpload",因为连续点击,可能造成并发。非常重要!!!
<el-upload :on-change="uploadChange" :show-file-list="false" :auto-upload="false" accept=".jpg,.jpeg,.png">
<el-button icon="plus" type="primary">上传证照</el-button>
<span style="color:gray;padding-left: 6px">请上传jpg、jpeg、png格式图片</span>
</el-upload>
function uploadChange(file){
const regex = /\.(jpg|jpeg|png)$/i;
if (regex.test(file.name)) {
isShowRedText.value = false;
}else{
return isShowRedText.value = true;
}
if(file.size > 20 * 1024 * 1024){
return ElMessage({
message: '上传文件大小不超过20M',
type: 'warning',
})
}
//以下,上传图片
isUploading.value = true;
uploadFileTool(file,'license').then(res => {
uploadForm.imageUrl = res.data.fullUrl;
uploadName.value = file.name;
uploadFormRef.value.validateField('imageUrl');
isUploading.value = false;
})
}
function uploadFileTool(file, type){
const formData = new FormData();
formData.append('objectType',type)
formData.append('file',file.raw)
return uploadFile(formData)
}
function uploadFile(data){
return request({
url: baseUrl+'fileInfo/upload',
method: 'post',
data
})
}
E、vantUI上传(移动端)
<van-uploader accept=".doc, .docx" accept="*" :before-read="uploadVideo">
<van-button icon="plus" type="primary">上传文档</van-button>
</van-uploader>
<van-uploader accept=".doc, .docx" accept="*">
<van-button icon="plus" type="primary" @click="uploadFile">上传文档</van-button>
</van-uploader>
说明,before-read、after-read,
a、事件的回调函数接收一个参数,包含文件名、文件大小、文件类型,后者还包含文件的临时URL
b、可以在这两个事件里或按钮的点击事件里,手动上传数据
var uploadVideo = function(file, detail) {
console.log( fileInfo.raw );
//首先根据文件的大小和后缀来判断,是否拦截上传并提出提示
}
2、数据上传-单图片先裁切后上传
(1)裁切裁剪图片
A、依赖
"dependencies": {
"vue-cropperjs": "^4.2.0",
},
B、使用
<template>
<div>
<el-upload
action=""
accept=".jpg,.png"
class="poster-uploader"
:auto-upload="false"
:show-file-list="false"
:on-change="uploadChange"
>
<img v-if="isShow" :src="serverImg" class="poster" />
<i v-else class="el-icon-plus poster-uploader-icon"></i>
</el-upload>
<el-dialog title="裁切/裁剪" :append-to-body='true' :visible.sync="cutDialogVisible" width="800px">
<div class="cropper-content">
<div class="cropper" style="text-align: center">
<vueCropper
ref="cropper"
:img="option.clientImg"
/>
</div>
<div v-if="previews.div" class="show-preview">
<div
:style="{
width: previews.div.width,
height: previews.div.height,
transformOrigin: '0 0',
transform: 'scale(' + 150 / previews.w + ')',
overflow: 'hidden',
}"
>
<img :src="previews.url" :style="previews.img">
</div>
</div>
</div>
<div slot="footer" class="poster-uploader-footer dialog-footer">
<div class="upload-form-cropper">
<el-button size="mini" @click="cutDialogVisible = false" >取 消</el-button>
<el-button type="primary" size="mini" @click="cutImg">确认</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
(2)获取裁后图片!!!
uploadChange(file) {
const reader = new FileReader()
reader.readAsDataURL(file.raw) //把file.raw原始文件对象(如File或Blob),转换为Base64编码的DataURL
reader.onload = (event) => {
this.option.clientImg = event.target.result
this.cutDialogVisible = true
}
}
cutImg() {
this.$refs.cropper.getCropData((data) => {
// getCropData,data,获取图片的base64数据
})
this.$refs.cropper.getCropBlob((data) => {
// getCropBlob,data,获取图片的blob数据
// 以下,上传示例
// const file = new File([blob], 'cropped-image.png', { type: blob.type }); //转换为File对象(可选)
// const formData = new FormData();
// formData.append('file', file);
})
}
3、数据上传-多文件上传,批量大视频列表
来源,online-class-manage
<template>
<div class="content-container">
<el-breadcrumb separator="/">
<el-breadcrumb-item>课程管理</el-breadcrumb-item>
<el-breadcrumb-item>内容管理</el-breadcrumb-item>
</el-breadcrumb>
<div class="content-table">
<div class="content-table-header">
<div class="content-table-header_title">上传视频</div>
</div>
<div class="form-wrap">
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="上传文件" prop="mediaUrl">
<div
:class="[
'uploadHeader',
mediaName === '' ? 'baseLine' : 'centerLine',
]"
>
<el-upload
class="upload-video"
action=""
multiple
accept="video/*"
:limit="10"
:disabled="isDisabled"
:file-list="fileList"
:on-change="mediaUpload"
:show-file-list="false"
:auto-upload="false"
>
<el-button
size="small"
type="primary"
:disabled="isDisabled"
plain
>
<i class="el-icon-upload2"></i>选择文件
</el-button>
</el-upload>
</div>
</el-form-item>
<el-form-item label="" prop="">
<el-table :data="tableData" style="width: 100%">/* 批量大视频列表,表格展示明细 */
<el-table-column label="封面图" width="120" prop="coverImgUrl">
<template slot-scope="scope">
<img
v-if="scope.row.coverImgUrl"
:src="scope.row.coverImgUrl"
alt=""
width="100"
height="56"
/>
<span v-else>上传后显示</span>
</template>
</el-table-column>
<el-table-column prop="oldTitle" label="文件名称" width="180">
</el-table-column>
<el-table-column label="视频大小" width="90">
<template slot-scope="scope"> {{ scope.row.size }}MB </template>
</el-table-column>
<el-table-column label="视频名称" width="200">
<template slot-scope="scope">
<el-input
v-model="scope.row.title"
size="mini"
style="width: 100%"
></el-input>
</template>
</el-table-column>
<el-table-column label="上传进度" width="80">
<template slot-scope="scope">
<el-progress v-if="scope.row.uploadPercent" type="circle" :width="56" :percentage="scope.row.uploadPercent"></el-progress>
<div class="uploadStatus">
<span v-if="scope.row.uploadStatus === 1">上传中</span>
<span v-if="scope.row.uploadStatus === 2">上传完成</span>
<span v-if="scope.row.uploadStatus === 3" style="color: #d54949">上传失败</span>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="140">
<template slot-scope="scope">
<change-img :size="3" @getUrl="getImgUrl" :uid="scope.row.uid"></change-img>
<el-button type="text" size="small" @click="delItem(scope.row.uid)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="选择课程合集" prop="collectionId">
<el-select
v-model="ruleForm.collectionId"
placeholder="请所属课程合"
>
<el-option
:label="item.title"
:value="item.sid"
v-for="item in collectionList"
:key="item.sid"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">保存</el-button>
<el-button @click="toContent">返回</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
const COS = require("cos-js-sdk-v5");
const TcVod = require("vod-js-sdk-v6"); //腾讯
import { getCosImg } from "@/api/upload.js";
import { getCollectionList,createCourse } from "@/api/course";
import ChangeImg from "@/components/upload/changeImg"
export default {
components: {
ChangeImg
},
data() {
return {
isDisabled:false,
COS: {},
collectionList: [],
fileList: [],
tableData: [
],
ruleForm: {
collectionId:''
},
rules: {
},
videoType: ["mp4", "mov", "avi"],
uploadPercent: 0, //上传进度
progressFlag: false,
mediaName: "", //文件名
changeCoveimg: false,
changeIndex: 0,
coverimgTime: [],
isVideo: false,
totalTime: "",
ruleFromt: {},
changeLoading: "",
loading: "",
type: 0, //类型:0=视频;1=音频
};
},
created() {
this.getCollectionList();
this.initCOS()
},
mounted() {},
methods: {
initCOS() {
getCosImg().then((res) => {
/* eslint-disable */
this.COS = new COS({
getAuthorization: (options, callback) => {
var credentials = res.data && res.data.credentials;
if (!res || !credentials)
return console.error("credentials invalid");
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
// 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
StartTime: res.data.startTime, // 时间戳,单位秒,如:1580000000
ExpiredTime: res.data.expiredTime, // 时间戳,单位秒,如:1580000900
// ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用
});
},
});
});
},
getImgUrl(data){
this.tableData = this.tableData.map((item)=>{
if(item.uid === data.uid){
item.coverImgUrl = data.url
}
return item
})
},
mediaUpload(fileInfo) {
if (fileInfo.status !== "ready") return;
//如果标题为空,将上传的文件名作为标题
let fileType = fileInfo.name
.substring(fileInfo.name.lastIndexOf(".") + 1)
.toLowerCase();
if (!this.videoType.includes(fileType)) {
this.$message({
type: "warning",
message: `不支持上传${fileType}格式文件!`,
});
this.fileList = [];
return false;
}
let fileSize = 500;
let sizeBlen = fileInfo.size / 1024 / 1024 < fileSize;
if (!sizeBlen) {
this.$message({
type: "warning",
message: `上传文件大小不能超过 ${fileSize}MB!`,
});
this.fileList = [];
return false;
}
let itemObj = {
collectionId: '',
coverImgUrl: '',
duration: '',
oldTitle: fileInfo.name,
size: (fileInfo.size / 1024 / 1024).toFixed(2),
title: fileInfo.name.substring(0, fileInfo.name.lastIndexOf(".") - 1),
type: 0,
uid: fileInfo.uid,
uploadPercent: 0,
uploadStatus: 0,
url: ''
};
this.tableData.push(itemObj)//增加表格数据!!!
this.getDuration(fileInfo)//生成缩略图并上传
this.handelUploadFile(fileInfo)//上传文件并监控进度
},
getDuration(fileInfo) {
new Promise((resolve, reject) => { //生成缩略图
let video = document.createElement('video');
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
let imgSrc;
video.src = URL.createObjectURL(fileInfo.raw); //reader.readAsDataURL(file.raw),适合读取小文件
video.currentTime = 3; //第3秒视频抽帧
video.setAttribute('width', 100);
video.setAttribute('height', 100);
canvas.setAttribute("width", 100);
canvas.setAttribute("height", 100);
video.oncanplay = () => { //以上设置视频宽高、画布宽高,以下设置绘制宽高
ctx.drawImage(video, 0, 0, video.width, video.height);//将第3秒视频绘制到canvas里
// drawImage(image, x, y, w, h),在canvas的上下文中绘制图像
// image:必填,图像源。这可以是一个
// HTMLImageElement,创建方式为new Image()和document.getElementById("myImage")
// HTMLCanvasElement,创建方式为document.createElement("canvas")和document.getElementById("myCanvas")
// HTMLVideoElement,创建方式为document.createElement("video")和document.getElementById("myVideo")
// x和y:必填,图像在画布上的起始坐标。坐标原点(0,0)位于canvas的左上角
// w和h:选填,绘制宽高。默认为image的渲染宽高,可通过image.width获取,取值优先级为:CSS宽高>HTML属性的宽高>原图的宽高
imgSrc = canvas.toDataURL('image/png');//将canvas转化为base64图片
resolve({
duration: parseInt(video.duration),//得到整数的视频时长
imgSrc: imgSrc,//base64的缩略图图片路径
width: video.videoWidth,
height: video.videoHeight,
videoName: fileInfo.name
});
URL.revokeObjectURL(video.src);//释放URL对象
};
// 上面是实际项目中(通过document.createElement('video')进行)的视频抽帧,
// 下面是播放视频并(通过document.getElementById("myVideo"))绘制到Canvas,来自deepseek
// const video = document.getElementById("myVideo");
// 播放视频并绘制到 Canvas
// video.addEventListener("play", () => {
// function drawFrame() {
// ctx.drawImage(video, 0, 0, 300, 150);
// if (!video.paused) {
// requestAnimationFrame(drawFrame); //持续绘制每一帧
// }
// }
// drawFrame();
// });
}).then(res => { //上传缩略图
this.tableData = this.tableData.map((item) => {
if (item.uid === fileInfo.uid) {
item.duration = String(res.duration);
//将Base64编码的Data URL转换(转化)成浏览器可操作的File对象,可用于上传canvas图片给后台
let blob = this.dataURLtoBlob(res.imgSrc);
let fileType = fileInfo.name;
let fileUrl = `zxkt/img/${new Date().getTime()}-${fileInfo.uid}.${fileType}.png`;
this.COS.sliceUploadFile(
{
Bucket: "sharepool-1257784922",
Region: "ap-beijing",
Key: fileUrl,
StorageClass: "STANDARD",
Body: blob,
},
(err, data) => {
if (!err) {
this.COS.getObjectUrl(
{
Method: "PUT",
Key: fileUrl,
Bucket: "sharepool-1257784922",
Region: "ap-beijing",
Sign: false,
},
(err, data) => {
let res = err || data;
this.tableData = this.tableData.map((item) => {
if (item.uid === fileInfo.uid) {
item.coverImgUrl = "https://sharepool-1257784922.cos.ap-beijing.myqcloud.com/" + fileUrl;
}
return item;
});
}
);
}
}
);
}
return item;
});
});
},
handelUploadFile(fileInfo){
let fileType = fileInfo.name
let fileUrl = `zxkt/video/${new Date().getTime()}-${fileInfo.uid}.${fileType}`;
this.COS.sliceUploadFile(//切片
{
Bucket: "sharepool-1257784922" /* 必须 */,
Region: "ap-beijing" /* 存储桶所在地域,必须字段 */,
Key: fileUrl /* 必须 */,
StorageClass: "STANDARD",
Body: fileInfo.raw, // 上传文件对象
onProgress: (progressData) => {
this.tableData = this.tableData.map((item)=>{
if(item.uid === fileInfo.uid){
item.uploadStatus = 1
item.uploadPercent = Math.round(progressData.percent * 100);
}
return item
})
},
},
(err, data) => {
if (!err) {
this.COS.getObjectUrl(
{ // 获取文件访问地址
Method: "PUT",
Key: fileUrl,
Bucket: "sharepool-1257784922",
Region: "ap-beijing",
Sign: false,
},
(err, data) => {
let res = err || data;
this.tableData = this.tableData.map((item)=>{
if(item.uid === fileInfo.uid){
item.uploadStatus = 2
item.url = "https://sharepool-1257784922.cos.ap-beijing.myqcloud.com/" + fileUrl;
}
return item
})
}
);
} else {
this.tableData = this.tableData.map((item)=>{
if(item.uid === fileInfo.uid){
item.uploadStatus = 3
}
return item
})
}
}
);
},
/*
来源,https://cloud.tencent.com/developer/ask/260695
//以下,用插件vod-js-sdk-v6上传视频时,发生了异常
1、报错
“Error: ugc upload | signature verify forbidden”,
2、原因,
你向后台索要签名,后台用小权限“腾讯账户”向腾-讯索要签名,
腾-讯给后台小权限签名,后台给你小权限签名,你将小权限签名发给腾-讯,腾-讯给你报错
3、解决办法,
让后台换用大权限“腾-讯账户”
*/
},
};
</script>
<style scoped lang="scss">
</style>
4、数据上传-大文件分片上传,带上传进度,切片
(1)webuploader.js,PC端,分片上传,带上传进度
//在上传本地完成后,此插件自动获取、切片数据并根据配置上传至服务器并监听上传过程
<script src="./common/webuploader.js"></script>
<style>
#updataButton input[type="file"] {
display: none;
}
</style>
$scope.up_file = function () {
var files;
var task_id = WebUploader.Base.guid();
var uploader = WebUploader.create({
server: './system/devinfo/upload',
pick: '#updataButton',//webuploader.js插件给此元素内添加了<input type="file"/>,点击此元素手动出现上传弹窗,点击内部的input直接出现上传弹窗
auto: false,//需要手动上传
chunked: true,//需要分片
chunkSize: 20 * 1024 * 1024,//每片大小
chunkRetry: 3,//如果某个分片由于网络问题出错,允许自动重传3次
threads: 1,//允许同时最大上传进程数为1
duplicate: true,//需要去重
formData: {//文件上传请求的参数表,每次发送都会发送此对象中的参数
task_id: task_id,
},
headers: {
business_resource: 156
},
fileVal:'rule'//设置文件上传域的name
});
uploader.on('fileQueued', function (file) {
$scope.file_.file = file;
//交互一:列队完成,告知后台,准备接收数据
auditApi
.query({
method: 'get',
root: 'set',
url: '/maintain/verify_file',
data: {
filename: file.name
}
})
.then(function () {
$scope.file_.uploader.upload();//交互二:开始上传到server配置指向的服务器
})
.catch(function () {
$scope.file_.uploader.removeFile($scope.file_.file);
});
}).on('fileDequeued', function () {
//console.log('remove queue success.');
}).on('startUpload', function () {
$scope.updata();//无前后台交互,出现弹窗,告知正在上传
}).on('uploadProgress', function (file, percentage) {
//上传中,出现进度条,无前后台交互,插件自己计算进度的百分比
}).on('uploadSuccess', function (file) {
//交互三、告知后台,数据发送完毕
auditApi
.query({
method: 'get',
root: 'set',
url: '/maintain/complete',
params: {
task_id: task_id,
filename: file.source['name']
},
timeout: 1000 * 60 * 3
})
.then(function () {
$scope.updating(); //交互四、定时询问后台,是否更新完毕
})
}).on('uploadError', function () {
//上传出错
});
}
$scope.up_file();
//说明,
//A、页面初始化时执行$scope.up_file();
//B、根据pick配置,找到“升级”按钮,并初始化
//C、点击“升级”后,插件调出window系统自身的弹窗,用户选中文件,点击确定,开始上传至初始化时的服务器,依次执行监听函数
(2)ali-oss,移动端,分片上传,内含上传进度的功能,videoUploadPercent,
A、依赖,来源,https://help.aliyun.com/document_detail/383952.html
ali-oss,阿里OSS存储,开放存储服务(open storage service,OSS),另见“腾讯”
"dependencies": {
"ali-oss": "^6.16.0"
},
B、html
<van-form @submit="beforeSubmit" ref="form" >
<template v-for="(item,idx) in formList" >
<div class="sign-form" :key="idx" v-if="item.inputType == 5">
<div class="van-form_card">
<div class="field__label">{{item.topicName}}</div>
<div class="field__desc">支持扩展名:avi、MP4、rmvb</div>
</div>
<van-field name="name" type="hidden" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" v-model="formData[idx]" >
<template #input >
<div class="flex-col">
<div class="video-upload" v-if="showUpload">
<span>视频上传中...</span>
<van-progress :show-pivot="false" :percentage="videoUploadPercent" />
</div>
<span class="link" v-if="formData[idx]" @click="href(idx)">{{videoName[idx]}}</span>
<van-uploader accept="*" v-if="!showUpload" :name="idx" :before-read="uploadVideo">
<van-button icon="plus" type="primary">上传视频</van-button>
</van-uploader>
</div>
</template>
</van-field>
</div>
</template>
<div class="vt-foot ">
<van-button native-type="submit" :disabled="!promise" :loading="loading" loading-text="保存中..." block color="#fdb235">提交</van-button>
</div>
</van-form>
C、js
import OSS from "ali-oss";
uploadVideo(file,detail){//file,二进制数据
let type = file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase()
if(this.videoType.indexOf(type) < 0 || file.type.indexOf("video") < 0){
this.$dialog.alert({
title: '提示',
message: '仅支持 .avi, .mp4, .rmvb, .mov 格式的视频',
theme: 'round-button',
});
return;
}
let max = 1024*1024*1024;
if(file.size > max){
this.$dialog.alert({
title: '提示',
message: '上传视频大小不能超过 1G!',
theme: 'round-button',
}).then(() => {});
return;
}
getALiYunOSSToken({ //交互一:告知后台,准备接收数据
tokenName: "ios",
}).then(data=>{ //后台同意后,给出同意参数
let oss = new OSS({ //前端根据同意参数new出传输实例
region: "oss-cn-beijing",
accessKeyId: data.data.data.accessKeyId,
accessKeySecret: data.data.data.accessKeySecret,
bucket: data.data.data.bucketName,
stsToken: data.data.data.securityToken,
});
const suffix = file.name.substr(file.name.indexOf("."));
let fileUrl = `test/${new Date().getTime()}${suffix}`;
oss.multipartUpload( //交互二:开始上传到fileUrl指向的服务器。不用告知后台,数据发送完毕;不用向后台询问,是否更新完毕
fileUrl, //文件在服务器的存储位置
file, //文件自身
{
progress: (p) => { //配置上传进度
this.videoUploadPercent = Math.round(p * 100);
this.showUpload = true;
},
partSize: 1024*100, //切片大小
}
)
.then((res) => {
this.showUpload = false;
this.videoName[detail.name] = res.name;
let url = res.res.requestUrls[0];
this.formData[detail.name] = url.substring(0,url.indexOf("?"));
let temp = this.formData[detail.name];
this.formData.splice(detail.name,1,temp);
})
.catch((err) => {
this.showUpload = false;
console.log(err);
this.$dialog.alert({
title: '提示',
message: '上传失败',
theme: 'round-button',
})
});
})
},
const getALiYunOSSToken=(params)=>{
return axios.request({
url:"https://mpapi.app.cctv.com/comm/file/getALiYunOSSToken",
params,
method: 'get'
})
}
beforeSubmit(){
if(this.loading){
return;
}
this.loading = true;
this.onSubmit();
},
onSubmit(){
this.$ajaxPost(url,data).then(res=>{})
},
(3)腾讯cos-js-sdk-v5,PC端,分片上传,带上传进度
A、cctv-chose定义
<template>
<el-upload
action=""
:auto-upload="false"
:accept="accept"
:show-file-list="false"
:on-change="upload"
:http-request="up"
ref="upload"
>
<div class="cctv-chose">
<span class="cctv-chose-add">+</span>
<div class="cctv-chose-footer" v-if="false">
<svg-icon icon-class="upload" class-name="cctv-chose-upload" />
<i></i>
<svg-icon icon-class="su" @click="selectSource" class-name="cctv-chose-su" />
</div>
</div>
</el-upload>
</template>
methods: {
upload(fileInfo) {
this.COS.putObject(//切片
{
Bucket: "gongweiedu-1257784922", // 必须
Region: "ap-beijing", // 必须,存储桶所在地域
Key: fileInfo.fileUrl, // 必须
StorageClass: "STANDARD",
Body: fileInfo.raw, // 上传文件对象
onProgress: (progressData) => { // 此处配置上传进度
let percent = Math.round(progressData.percent * 100)
this.$emit('pro',progressData)
this.$emit('progress',percent)//告诉父级上传进度
}
},
(err, data) => {
if (!err) {
cosObject.getObjectUrl(
{
// 获取文件访问地址
Method: "PUT",
Key: fileInfo.fileUrl,
Bucket: "gongweiedu-1257784922",
Region: "ap-beijing",
Sign: false
},
(err, data) => {
if(err){
console.log( err );
}else {
console.log( data.Url );
this.$emit('backUrl', data.Url)
}
// data.Url = data.Url
}
)
} else {
console.log( err );
}
}
)
},
},
B、cctv-chose调用,上传多张图片,带列表展示
<el-form-item
label="上传图片"
prop="image"
class="dynamic-form-image"
>
<div class="dynamic-warp">
<div class="dynamic-img" v-for="(item,index) in dynamicForm.images" :key="index">
<img :src="item|parseUrl">
<i class="el-icon-error" @click="remove(index)" />
</div>
<CctvChose :limit="5"
v-if="dynamicForm.images && dynamicForm.images.length<15"
@backUrl="catchUrl"
class="dynamic-chose"
@selectSource="showDynamic"
/>
</div>
<div class="dynamic-tip">图片格式bmp、png、webp、jpeg,图片大小5MB以内</div>
</el-form-item>
C、cctv-chose调用,上传单个视频,带进度条
<div class="produce-form-header">
<div v-show="!fileInfo">
<CctvChose
class="produce-chose"
@selectFile="selectFile"
@selectSource="selectSource"
:limit="800"
@backUrl="setUrl"
@progress="changePercent"
@pro="getProgressData"
:type="1"
></CctvChose>
<div class="produce-tip">请添加文件上传 支持MP4、MOV格式</div>
</div>
<div class="produce-form-info" v-if="fileInfo">
<div class="produce-form-info-title">
{{ fileInfo.name }}
</div>
<div class="produce-form-delete" v-if="percent==100">
<el-button type="text" @click="reUpload">删除</el-button>
</div>
</div>
<div v-if="fileInfo">
<el-progress //使用上传进度
class="produce-form-progress-bar"
:percentage="percent"
:show-text="false"
:stroke-width="26"
/>
</div>
</div>
methods: {
changePercent(per) {
this.percent = per;//父级接收上传进度
if(this.percent==100){
this.loading = false;
this.$refs.audioForm.form.videoTitle = this.fileInfo.name.split('.')[0].slice(0,40);
}else {
this.loading = true
}
},
},//数据上传-结束
四、数据下载
1、直接下载
(1)示例:
<a download="test.pdf" href="https://cdn.shopify.com/s/Manaul.pdf">下载</a>
(2)说明:
A、下载属性(download)的优先级高于预览属性(href)
B、点击上面链接,只会下载,不会跳转页面
(3)问答:
问:把.png图片命名为.jpg,为什么也能下载
答:浏览器不校验扩展名与内容的匹配性,实际格式始终由数据本身决定
2、文件下载
function download(res, title, isLoading){
var titleIn = res.headers['download-filename'];
if (!title && !titleIn) {
ElMessage({ message: '暂无数据', type: 'error' })
return
}
let filename = title || decodeURIComponent(titleIn)
const url = window.URL.createObjectURL(res.data);
const link = document.createElement('a');
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
setTimeout(() => {
document.body.removeChild(link);
window.URL.revokeObjectURL(url); //防止内存泄漏!!!
if(isLoading) isLoading.value = false
}, 100);
};
3、图片下载
(1)a标签。仅下载图片
function downImg(item) {
var a = document.createElement('a');
a.download = '广播电视频道许可证-' + item.channelName+ '.jpg';
a.href = http+item.imageUrl;
a.click();
};
(2)a标签。还能展示图片
function downImg(item) {
var a = document.createElement('a');
document.body.appendChild(a);
a.download = '广播电视频道许可证-' + item.channelName+ '.jpg';
a.href = http+item.imageUrl;
a.click();
a.remove()
};
(3)a标签+canvas标签。仅下载图片。没必要用这种方式下载图片
const http = import.meta.env.VITE_APP_BASE_API ; //previewImg
function downImg(item) {
var url_ = http+item.imageUrl;
const image = new Image();
image.onload = function () {
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const context = canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
const url = canvas.toDataURL('image/png');
const a = document.createElement('a');
const event = new MouseEvent('click');
a.download = '广播电视频道许可证-' + item.channelName;
a.href = url;
a.dispatchEvent(event);
ElMessage.success("下载成功!");
};
image.src = url_;
};
4、把后台返回的JSON数据插到Excel里并下载
附、在微信群里,下面在线协作工具与Excel在外观和功能上都极为相似,允许多人实时直接编辑它们,填写后自动保存,数据实时同步
A、腾讯文档-在线表格
B、金山文档-协作表格
<html>
<head>
<script type="text/javascript" src="https://cdn.bootcss.com/xlsx/0.12.7/xlsx.core.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/alasql/0.0.50/alasql.min.js"></script>
</head>
<body>
<button onclick="down()">数据下载</button>
</body>
</html>
<script>
function down(){
var tableTh = ["times [时间]", "user [用户]", "ip [IP地址]", "result [登录结果]"];
var title = "文件名.xlsx";
// Excel文件的后缀(扩展名)的格式(先后顺序):
// .csv,80版本,是纯文本格式,简单、通用、轻量、经久不衰
// .xls,97-03版本,
// .xlsx,07版本以后,
var dataArray=[
{
times: "2003-03-04",//0
user: "张三",//1
ip: "216.94.168.85",//2
result: 0,//3
ServiceType: "yhzuu",
id: 1,
operation: "刷新页面",
},{
times: "2003-03-05",//0
user: "李四",//1
ip: "216.94.168.85",//2
result: 1,//3
ServiceType: "yhzuu",
id: 2,
operation: "刷新页面",
}
];
dataArray.forEach(function(item,index){
item.result = ["失败","成功"][item.result]
});
alasql('SELECT '+tableTh+' INTO XLSX("'+title+'",{headers:true}) FROM ?'/*第1参数*/ , [dataArray]/*第2参数*/);
//选择tableTh注入到XLSX;文件名为title.xlsx;包含表头(列名);数据来源为?,是占位符,由第二个参数[dataArray]替换
//tableTh与其前后的字符串必须用“空格”隔开,否则会报错
}
</script>
五、数据展示
附、3个媒体元素
(1)标签
A、audio
<audio controls>
<source src="horse.ogg" type="audio/ogg">
<source src="horse.mp3" type="audio/mpeg">
您的浏览器不支持 audio 元素。
</audio>
B、picture
<picture>
<source media="(min-width:650px)" srcset="img_pink_flowers.jpg">
<source media="(min-width:465px)" srcset="img_white_flower.jpg">
<img src="img_orange_flowers.jpg" alt="Flowers" style="width:auto;">
</picture>
C、video
<video width="320" height="240" controls>
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
您的浏览器不支持 video 标签。
</video>
(2)audio和video的标签的共有属性
A、autoplay,autoplay,在就绪后马上播放
B、controls,controls,向用户显示控件(比如播放/暂停按钮)
C、loop,loop,每当播放结束时重新开始播放
D、muted,muted,输出为静音
E、preload,auto/metadata/none,是否默认被加载以及如何被加载
F、src,URL,规定文件的URL
(3)video的标签专有属性
A、width,pixels,设置视频播放器的宽度
B、height,pixels,设置视频播放器的高度
C、poster,URL,规定视频正在下载时显示的图像,直到用户点击播放按钮
(4)source标签,为媒体元素指定多个媒体资源
来源,https://www.w3school.com.cn/tags/tag_source.asp
来源,https://www.w3school.com.cn/tags/att_source_srcset.asp
A、src,用于指定媒体文件的URL
B、srcset,用于指定在不同情况下使用的图像的URL,<source srcset="https://static.noob-logo.png"></source>
C、media,媒体查询,<source media="(min-width:650px)"></source>
D、type,规定资源的MIME类型,<source type="video/mp4"></source>
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,指定浏览器用哪个应用程序打开文件
1、数据展示-图片展示-共1种,图片预览
(1)页面“有”小图片占位的预览
<el-image
style="width: 100px; height: 100px"
:src="url"
:preview-src-list="srcList">
</el-image>
(2)页面“无”小图片占位的预览
<el-image-viewer @close="imgVisible = false" :url-list="[imgSrc]" v-if="imgVisible" />
.el-image-viewer__canvas img{//让图片显示为圆角且描白边
border-radius:10px;
border:1px solid #fff
}
(3)图标-宽固定,高自适应
<svg-icon :icon-class="scope.row.docType" style="font-size: 24px" v-show="scope.row.docType !== 'image'" />
<div style="display: inline-block; width:24px" v-show="scope.row.docType == 'image'">
<img :src="scope.row.publicUrl" style="width: 100%" />
</div>
2、数据展示-视频展示-共2种(附、videojs插件使用实例)
(1)弹窗内播放视频
//ElMessageBox.alert、ElMessageBox.confirm、ElMessageBox.prompt的第一个参数支持传入HTML标签(字符串形式)
import { MessageBox } from 'element-ui';
export default function player(option){
MessageBox.alert(
'<video id="video" width="600" controls height="337" autoplay muted src="'+option.url+'" ></video>',
option.title,
{
dangerouslyUseHTMLString: true,
showConfirmButton: false,
customClass: 'video-warp',
beforeClose: ()=>{
let video = document.getElementById('video');
video.pause();
video.load();
MessageBox.close();
}
}
)
}
(2)页面内视频播放
A、依赖
"dependencies": {
"video.js": "^7.20.3",
},
B、使用
附、deepseek,给我一个在elementplus中使用video.js插件的完整示例,其中js代码写在<script setup></script>里面
<template>
<div class="video-container">
<!-- 视频播放器容器 -->
<div class="video-wrapper">
<video
ref="videoPlayer"
class="video-js vjs-big-play-centered"
controls
preload="auto"
:poster="posterUrl"
></video>
</div>
<!-- Element Plus 控制面板 -->
<el-card class="control-panel" shadow="hover">
<div class="controls">
<el-button-group>
<el-button type="primary" @click="handlePlay">
<el-icon><VideoPlay /></el-icon> 播放
</el-button>
<el-button @click="handlePause">
<el-icon><VideoPause /></el-icon> 暂停
</el-button>
<el-button @click="handleMute">
<el-icon><MuteNotification /></el-icon> 静音
</el-button>
</el-button-group>
<div class="slider-group">
<span class="slider-label">音量</span>
<el-slider
v-model="volume"
:min="0"
:max="1"
:step="0.1"
@input="handleVolumeChange"
style="width: 150px"
/>
</div>
<el-select
v-model="currentSource"
placeholder="选择视频源"
@change="handleSourceChange"
style="width: 200px"
>
<el-option
v-for="source in videoSources"
:key="source.src"
:label="source.label"
:value="source.src"
/>
</el-select>
</div>
</el-card>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
import { VideoPlay, VideoPause, MuteNotification } from '@element-plus/icons-vue'
// 视频播放器引用
const videoPlayer = ref(null)
const player = ref(null)
// 状态管理
const volume = ref(0.6)
const isMuted = ref(false)
const currentSource = ref('')
const posterUrl = ref('https://vjs.zencdn.net/v/oceans.png')
// 视频源列表
const videoSources = ref([
{
src: 'https://vjs.zencdn.net/v/oceans.mp4',
label: '海洋示例视频'
},
{
src: 'https://vjs.zencdn.net/v/big-buck-bunny.mp4',
label: 'Big Buck Bunny'
},
{
src: 'https://vjs.zencdn.net/v/elephants-dream.mp4',
label: 'Elephants Dream'
}
])
// 初始化播放器
const initPlayer = () => {
currentSource.value = videoSources.value[0].src
player.value = videojs(
videoPlayer.value,
{
autoplay: false,
controls: true,
fluid: true,
sources: [
{
src: currentSource.value,
type: 'video/mp4'
}
],
html5: {
vhs: {
overrideNative: true
}
}
},
() => {
console.log('播放器已初始化')
player.value.volume(volume.value)
setupPlayerEvents()
}
)
}
// 设置播放器事件
const setupPlayerEvents = () => {
player.value.on('play', () => {
console.log('视频开始播放')
})
player.value.on('pause', () => {
console.log('视频已暂停')
})
player.value.on('ended', () => {
console.log('视频播放结束')
})
player.value.on('error', (error) => {
console.error('播放器错误:', error)
})
player.value.on('volumechange', () => {
volume.value = player.value.volume()
isMuted.value = player.value.muted()
})
}
// 播放控制方法
const handlePlay = () => {
if (player.value) {
player.value.play()
}
}
const handlePause = () => {
if (player.value) {
player.value.pause()
}
}
const handleMute = () => {
if (player.value) {
player.value.muted(!isMuted.value)
}
}
const handleVolumeChange = (val) => {
if (player.value) {
player.value.volume(val)
player.value.muted(val === 0)
}
}
// 切换视频源
const handleSourceChange = (src) => {
if (player.value) {
player.value.src({
src,
type: 'video/mp4'
})
player.value.poster(posterUrl.value)
player.value.load() // 重新加载视频
}
}
// 生命周期钩子
onMounted(() => {
initPlayer()
})
onBeforeUnmount(() => {
if (player.value) {
player.value.dispose()
}
})
</script>
<style scoped>
.video-container {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.video-wrapper {
position: relative;
padding-bottom: 56.25%; /* 16:9 比例 */
height: 0;
overflow: hidden;
background-color: #000;
border-radius: 4px;
}
.video-wrapper video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.control-panel {
margin-top: 20px;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 15px;
align-items: center;
}
.slider-group {
display: flex;
align-items: center;
gap: 10px;
}
.slider-label {
font-size: 14px;
color: var(--el-text-color-regular);
}
</style>
3、数据展示-PDF展示-共3种
(1)页外展示,<a :href="item.url" target="_blank">避免跨域</a>
(2)jquery-media.js
A、类库:jquery.js、jquery-media.js
B、前端用Jinja2语法把总变量分散插进HTML里,交给后台
C、后台给总变量赋值,然后把HTML渲染成PDF,
D、CSS分页:此前分页page-break-before: always;此后分页page-break-after: always;
$('#pdf').media({
width: '100%',
height: '680px',
autoplay: true,
src: '/flow_audit/media?file_name=myNAme'
});
(3)vue3-pdf-app
附、相关链接,https://www.npmjs.com/package/vue3-pdf-app
A、依赖
"dependencies": {
"vue3-pdf-app": "^1.0.3",
},
B、使用
附、deepseek,项目中使用elementplus组件,现在要用vue3-pdf-app在弹窗中展示pdf文件,请给我示例代码,谢谢
<template>
<el-button @click="showPdfDialog">点击预览PDF</el-button>
<el-dialog
v-model="dialogVisible"
title="PDF预览"
width="80%"
top="5vh"
>
<div class="pdf-container">
<vue3-pdf-app
v-if="dialogVisible"
:pdf="pdfUrl"
style="height: 70vh;"
/>
</div>
<template #footer>
<el-button @click="dialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { ref } from 'vue';
import Vue3PdfApp from 'vue3-pdf-app';
import 'vue3-pdf-app/dist/icons/main.css'; // 引入默认样式
const dialogVisible = ref(false);
const pdfUrl = ref('/api/sample.pdf'); // 开发时,实际请求会被代理到后端;上线后,在根目录查找对应文件
const showPdfDialog = () => {
dialogVisible.value = true;
};
</script>
<style scoped>
.pdf-container {
height: 100%;
overflow: auto;
}
</style>
4、数据展示-docx展示-共1种
A、依赖
"dependencies": {
"docx-preview": "^0.1.20",//该插件提供的renderAsync方法,实现了docx文档展示
},
B、使用
附、deepseek,根据我提供的代码进行完善
<script setup>
import { renderAsync } from "docx-preview"
import { ref, watch, defineProps, defineEmits } from 'vue'
const props = defineProps({
fileVisible: {
type: Boolean,
default: false,
},
item: {
type: Object,
default: () => ({})
}
})
const emit = defineEmits(['close'])
const show = ref(false)
const loading = ref(false)
const docxDiv = ref(null)
const heightValue = 'calc(100vh - 200px)'
watch(() => props.fileVisible, (val) => {
show.value = val
if (val) previewfile()
})
watch(() => props.item, () => {
if (show.value) previewfile()
})
const close = () => {
emit('close')
}
const previewfile = () => {
if (!props.item?.url) return
loading.value = true
fetch(props.item.url) // '/api/sample.docx'。开发时,实际请求会被代理到后端;上线后,在根目录查找对应文件
.then((response) => response.blob())
.then((blob) => {
return renderAsync(blob, docxDiv.value, null, {
inWrapper: false, // 启用围绕文档内容渲染包装器
ignoreWidth: false, // 禁止页面渲染宽度
ignoreHeight: false, // 禁止页面渲染高度
ignoreFonts: false, // 禁止字体渲染
breakPages: true, // 在分页符上启用分页
ignoreLastRenderedPageBreak: true, //禁用lastRenderedPageBreak元素的分页
experimental: false, //启用实验性功能(制表符停止计算)
trimXmlDeclaration: true, //如果为真,xml声明将在解析之前从xml文档中删除
debug: false,
})
})
.then(() => {
loading.value = false
})
.catch((error) => {
console.error('文档预览失败:', error)
loading.value = false
})
}
</script>
<template>
<el-dialog
v-model="show"
top="5vh"
title="文档预览"
width="992px"
@close="close"
>
<div
ref="docxDiv"
class="docx-container"
:style="{ height: heightValue }"
v-loading="loading"
element-loading-text="文档加载中..."
></div>
</el-dialog>
</template>
<style scoped>
.docx-container {
width: 100%;
overflow: auto;
border: 1px solid #eee;
}
</style>
5、数据展示-json展示-共3种
(1)用node包实现
A、依赖
"dependencies": {
"vue-json-viewer": "^2.2.19",
},
B、组件调用
import JsonViewer from "vue-json-viewer";
<json-viewer
:value="JSON.parse(logInfo.responseParam)"
:expand-depth="5"
:copyable="{
copyText: '复制',
copiedText: '复制成功',
timeout: 2000
}"
boxed
sort
></json-viewer>
(2)原生JS实现
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>JSON展示</title>
<style>
.fontSize20{
font-size: 20px;
}
.result{
width: 400px;
padding: 40px;
font-size: 12px;
background: rgb(231, 228, 228);
}
</style>
</head>
<body>
<div class="fontSize20">JSON格式在线校验,https://www.bejson.com/</div>
<div id='div' class="result"></div>
</body>
</html>
<script>
function isArray(value) { return {}.toString.call(value) === "[object Array]"; }
function isObject(value) { return {}.toString.call(value) === "[object Object]"; }
function addLine(num) {//添加换行
var str ='\n';
for(var i = 0; i < num; i++) str +='\n'
return str;
}
function addSpace(num) {//添加空格
var str ='\xa0';
for(var i = 0; i < num; i++) str +='\xa0'
return str;
}
function addStr(data, num, isAddDot) {//添加字符串
var str = '';
if (isObject(data)) {
str += '{' + addLine(1);
var i = 0;
var strIn = ',';
var length = Object.keys(data).length;
for(var attr in data){
var value = data[attr];
i++;
if(i == length) strIn = '';
str += addSpace(4*num) + JSON.stringify(attr) + ":" + addStr(value, num+1) + strIn + addLine(1);
}
str += addSpace(4*(num-1)) + '}';
if(isAddDot) str += ',';
} else if (isArray(data)) {
str += '[';
for(var i=0;i<data.length;i++){
var value = data[i];
var isHasDot = i<data.length-1;
str += addStr(value, num, isHasDot);
}
str += ']';
if(isAddDot) str += ',';
} else {
str += JSON.stringify(data);
if(isAddDot) str += ',';
}
return str;
}
var data= {
"aaa":200,
"bbb":"42465",
"ccc":false,
"ddd":[{
"title":"治车山志",
"status":"失败"
},{
"title":"需酸老",
"status":"失败"
}],
"eee":{
"省级1":"吉林省",
"省级3":{
"河北省":"临夏回族自治州",
"河南省":{
"信阳市":{
"固始县":["A",[1,2],"B",["3","4"]]
//把数组某项换成'省级3'对象,看效果
}
}
}
},
"fff":"★★★"
}
document.getElementById('div').innerText = addStr(data, 1);
</script>
(3)jQuery实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<style >
.json-document {
padding: 1em 2em;
}
ul.json-dict, ol.json-array {
list-style-type: none;
margin: 0 0 0 1px;
border-left: 1px dotted #ccc;
padding-left: 2em;
}
.json-string {
color: #0B7500;
}
.json-literal {
color: #1A01CC;
font-weight: bold;
}
a.json-toggle {
position: relative;
color: inherit;
text-decoration: none;
}
a.json-toggle:focus {
outline: none;
}
a.json-toggle:before {
font-size: 1.1em;
color: #c0c0c0;
content: "\25BC";/* https://unicode-table.com/cn/ */
position: absolute;
display: inline-block;
width: 1em;
text-align: center;
line-height: 1em;
left: -1.2em;
}
a.json-toggle:hover:before {
color: #aaa;
}
a.json-toggle.collapsed:before {
transform: rotate(-90deg);
}
a.json-placeholder {
color: #aaa;
padding: 0 1em;
text-decoration: none;
}
a.json-placeholder:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="aaa"></div>
</body>
</html>
<script>
(function ($) {
function isCollapsable(arg) {
return arg instanceof Object && Object.keys(arg).length > 0;
}
function isUrl(string) {
var urlRegexp = /^(https?:\/\/|ftps?:\/\/)?([a-z0-9%-]+\.){1,}([a-z0-9-]+)?(:(\d{1,5}))?(\/([a-z0-9\-._~:/?#[\]@!$&'()*+,;=%]+)?)?$/i;
return urlRegexp.test(string);
}
function json2html(json, options) {
var html = '';
if (typeof json === 'string') {
json = json
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/'/g, '')
.replace(/"/g, '"');
if (options.withLinks && isUrl(json)) {
html +=
'<a href="' +
json +
'" class="json-string" target="_blank">' +
json +
'</a>';
} else {
if (json.indexOf('RED_SELF') > -1) {
json = json.replace('RED_SELF', '');
html +=
'<span class="json-literal" style="color:red">' + json + '</span>';
} else if (json.indexOf('RED_parent') > -1) {
json = json.replace('RED_parent', '');
html += '<span class="json-literal RED_parent">' + json + '</span>';
} else {
json = json.replace(/"/g, '\\"');
html += '<span class="json-string">"' + json + '"</span>';
}
}
} else if (typeof json === 'number') {
html += '<span class="json-literal">' + json + '</span>';
} else if (typeof json === 'boolean') {
html += '<span class="json-literal">' + json + '</span>';
} else if (json === null) {
html += '<span class="json-literal">null</span>';
} else if (json instanceof Array) {
if (json.length > 0) {
html += '[<ol class="json-array">';
for (var i = 0; i < json.length; ++i) {
html += '<li>';
if (isCollapsable(json[i])) {
html += '<a href class="json-toggle"></a>';
}
html += json2html(json[i], options);
if (i < json.length - 1) {
html += ',';
}
html += '</li>';
}
html += '</ol>]';
} else {
html += '[]';
}
} else if (typeof json === 'object') {
var keyCount = Object.keys(json).length;
if (keyCount > 0) {
html += '{<ul class="json-dict">';
for (var key in json) {
if (Object.prototype.hasOwnProperty.call(json, key)) {
html += '<li>';
var keyRepr = options.withQuotes
? '<span class="json-string">"' + key + '"</span>'
: key;
if (isCollapsable(json[key])) {
html += '<a href class="json-toggle">' + keyRepr + '</a>';
} else {
html += keyRepr;
}
html += ': ' + json2html(json[key], options);
if (--keyCount > 0) {
html += ',';
}
html += '</li>';
}
}
html += '</ul>}';
} else {
html += '{}';
}
}
return html;
}
$.fn.jsonViewer = function (json, options) {
options = Object.assign(
{},
{
collapsed: false,
rootCollapsable: true,
withQuotes: false,
withLinks: true
},
options
);
return this.each(function () {
var html = json2html(json, options);
if (options.rootCollapsable && isCollapsable(json)) {
html = '<a href class="json-toggle"></a>' + html;
}
$(this).html(html);
$(this).addClass('json-document');
$(this).off('click');
$(this).on('click', 'a.json-toggle', function () {
var target = $(this)
.toggleClass('collapsed')
.siblings('ul.json-dict, ol.json-array');
target.toggle();
if (target.is(':visible')) {
target.siblings('.json-placeholder').remove();
} else {
var count = target.children('li').length;
var placeholder = count + (count > 1 ? ' items' : ' item');
target.after(
'<a href class="json-placeholder">' + placeholder + '</a>'
);
}
return false;
});
$(this).on('click', 'a.json-placeholder', function () {
$(this).siblings('a.json-toggle').click();
return false;
});
if (options.collapsed == true) {
$(this).find('a.json-toggle').click();
}
});
};
})(jQuery);
var obj={
"id": 1001,
"type": "donut",
"name": "Cake",
"description": "https://en.wikipedia.org/wiki/Doughnut",
"price": 2.55,
"available": {
"store": 42,
"warehouse": 600
},
"toppings": [
{ "id": 5001, "type": "None" },
{ "id": 5002, "type": "Glazed" },
{ "id": 5005, "type": "Sugar" },
{ "id": 5003, "type": "Chocolate" },
{ "id": 5004, "type": "Maple" }
],
"uuids": [
"826b23ce-2669-4122-981f-3e2e4429159d",
"e32111a0-6a87-49ab-b58f-a01bf8d28ba0",
"c055a894-698e-41c0-b85f-7510a7351d9d",
],
};
$('#aaa').jsonViewer(obj);
</script>
六、数据复制
说明:用下列方法复制数据至剪贴板,然后用ctrl+v粘贴(或用js赋值)到其他地方
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三种复制方法演示</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0 auto;
padding: 20px;
}
.outer {
display: flex;
}
.container {
padding: 15px;
border: 1px solid #ddd;
border-radius: 5px;
flex: 1;
}
.copy-div {
padding: 15px;
margin: 10px 0;
border: 1px solid #4CAF50;
border-radius: 4px;
cursor: pointer;
background-color: #f8f8f8;
}
.copy-div:hover {
background-color: #e8e8e8;
}
textarea {
width: 100%;
height: 300px;
margin: 10px 0;
padding: 8px;
box-sizing: border-box;
}
button {
background-color: #2196F3;
color: white;
border: none;
padding: 10px 15px;
margin: 5px 0;
cursor: pointer;
border-radius: 4px;
}
button:hover {
background-color: #0b7dda;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 10px 15px;
background-color: #4CAF50;
color: white;
border-radius: 4px;
display: none;
z-index: 1000;
}
p {
color: #333;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
</style>
</head>
<body>
<h1>三种复制方法演示</h1>
<div class="outer">
<div class="container">
<p>方法1:</p>
<p>使用现代API</p>
<p>把textContent复制到剪贴板navigator.clipboard</p>
<p>保留HTML元素中的空格和换行</p>
<div class="copy-div" id="modernCopyDiv">
点击此处,使用-方法1-复制这段文字。textContent,保留HTML元素中的空格和换行。
</div>
</div>
<div class="container">
<p>方法2:</p>
<p>使用传统方法</p>
<p>把innerText复制到剪贴板e.clipboardData</p>
<p>会移除HTML元素中的空格和换行</p>
<div class="copy-div" id="eventCopyDiv">
点击此处,使用-方法2-复制这段文字。innerText,忽略HTML元素中的空格和换行。
</div>
</div>
<div class="container">
<p>方法3:</p>
<p>使用传统方法,</p>
<p>创造元素、插入文字、选中文字、复制文字select,</p>
<p>保留HTML元素中的空格和换</p>
<textarea id="textToCopy">点击下方按钮,使用方法3复制这段文字。</textarea>
<button id="legacyCopyBtn">点击此处,使用方法3复制上面文字</button>
<button id="legacyClearBtn">点击此处,清除上面文字</button>
</div>
</div>
<div class="notification" id="notification">已复制到剪贴板!</div>
<script>
// 通用显示通知函数
function showNotification(message = '已复制到剪贴板!') {
const notification = document.getElementById('notification');
notification.textContent = message;
notification.style.display = 'block';
setTimeout(() => {
notification.style.display = 'none';
}, 2000);
}
// 方法1: 使用现代API,把textContent复制到剪贴板navigator.clipboard,保留HTML元素中的空格和换行
document.getElementById('modernCopyDiv').addEventListener('click', async function() {
try {
await navigator.clipboard.writeText(this.textContent);
showNotification('方法1: 现代API。使用navigator.clipboard复制成功');
} catch (err) {
console.error('方法1复制失败:', err);
showNotification('方法1复制失败,请尝试其他方法');
}
});
// 方法2: 使用传统方法,把innerText复制到剪贴板e.clipboardData,会移除HTML元素中的空格和换行
document.addEventListener('copy', function(e) {
if (window.currentCopyText) {
e.clipboardData.setData('text/plain', window.currentCopyText);
e.preventDefault();
showNotification('方法2: 传统方法。使用e.clipboardData复制成功');
window.currentCopyText = null;
}
});
document.getElementById('eventCopyDiv').addEventListener('click', function() {
window.currentCopyText = this.innerText;
document.execCommand('copy');
});
// 方法3: 使用传统方法,创造元素、插入文字、选中文字、复制文字select,保留HTML元素中的空格和换
document.getElementById('legacyCopyBtn').addEventListener('click', function() {
const textarea = document.getElementById('textToCopy');
const tempTextarea = document.createElement('textarea');
tempTextarea.value = textarea.value;
tempTextarea.style.position = 'fixed';
document.body.appendChild(tempTextarea);
tempTextarea.select(); //选中文本
try {
const successful = document.execCommand('copy'); //触发copy
if (successful) {
showNotification('方法3: 使用textarea.select复制成功');
} else {
showNotification('方法3复制失败');
}
} catch (err) {
console.error('方法3复制失败:', err);
showNotification('方法3复制失败');
} finally {
document.body.removeChild(tempTextarea);
}
});
document.getElementById('legacyClearBtn').addEventListener('click', function() {
document.getElementById('textToCopy').value = '';
});
</script>
</body>
</html>
七、文档编辑
附、2024年在线智能编辑器,Edivator,核心功能是实现了大小模型协同工作
附、唯一相关资料,https://download.csdn.net/download/qq_46187594/89737609
1、文档编辑-editormd
说明,中国厦门Pandao开发的富文本编辑器
(1)下载依赖包editormd并导入 git clone https://github.com/pandao/editor.md.git
<script src="./common/editor.md/editormd.min.js"></script>
(2)如果编辑后台返回的数据,那么向后台发送请求,获取数据serverData
(3)相关代码
html代码
<div id="editormd" style="height: 580px">
<textarea style="display: none"></textarea>
</div>
js代码,在请求成功后,执行下列代码
that.testEditor = editormd("editormd", {
width: "100%",
height: "720",
watch: false, //关闭分栏
toolbar: false, //关闭工具栏
value: serverData||'', //字符串
path: "./common/editor.md/lib/",//依赖存放路径
});
setTimeout(function () {
var value = that.testEditor.getValue();
//这是前同事的代码,获取编辑前的数据,方便与编辑后的数据作比对,我以为没必要这样写
//编辑前的数据就是字符串serverData,在定时器外存储一下即可,如var value = serverData
}, 500);
(4)详细使用教程,百度“editor.md使用教程”
2、文档编辑-vue-ueditor-wrap(用于open-cctv项目,合集-文章编辑)
说明:
A、百度Web前端研发部开发的一款开源富文本编辑器
B、UEditor全称是“Your Editor”
(1)依赖
"dependencies": {
"vue-ueditor-wrap": "^2.5.6",
},
(2)使用组件
<el-form-item label="文章内容" prop="region" class="article-form-editor">
<vue-ueditor-wrap v-model="html" :config="myConfig" @ready="ueditorReady"></vue-ueditor-wrap>
</el-form-item>
(3)配置组件
import VueUeditorWrap from "vue-ueditor-wrap";
export default {
name: 'Article',
components: {
VueUeditorWrap,
}
data() {
return {
html: '',
myConfig: {
//按钮
toolbars: [
[
'source', //源代码
//'anchor', //锚点
'undo', //撤销
'redo', //重做
'bold', //加粗
'indent', //首行缩进
'italic', //斜体
'underline', //下划线
'strikethrough', //删除线
'superscript', //上标
'subscript', //下标
'fontborder', //字符边框
'formatmatch', //格式刷
'blockquote', //引用
'pasteplain', //纯文本粘贴模式
'selectall', //全选
'removeformat', //清除格式
'time', //时间
'date', //日期
'unlink', //取消链接
'link', //超链接
'cleardoc', //清空文档
'touppercase', //字母大写
'tolowercase', //字母小写
'fontfamily', //字体
'fontsize', //字号
'paragraph', //段落格式
'searchreplace', //查询替换
'justifyleft', //居左对齐
'justifyright', //居右对齐
'justifycenter', //居中对齐
'justifyjustify', //两端对齐
'forecolor', //字体颜色
'directionalityltr', //从左向右输入
'directionalityrtl', //从右向左输入
'rowspacingtop', //段前距
'rowspacingbottom', //段后距
'lineheight', //行间距
'horizontal', //分隔线
'clears', //分隔线
'simpleupload', //单图上传
//'backcolor', //背景色
//'customstyle', //自定义标题
//'pagebreak', //分页
//'imageleft', //左浮动
//'imageright', //右浮动
//'imagecenter', //居中
//'insertrow', //前插入行
//'insertcol', //前插入列
//'deleterow', //删除行
//'deletecol', //删除列
//'splittorows', //拆分成行
//'splittocols', //拆分成列
//'edittip ', //编辑提示
//'imagenone', //默认
//'insertcode', //代码语言
//'snapscreen', //截图
//'print', //打印
//'preview', //预览
//'mergeright', //右合并单元格
//'mergedown', //下合并单元格
//'splittocells', //完全拆分单元格
//'deletecaption', //删除表格标题
//'inserttitle', //插入标题
//'insertparagraphbeforetable', //"表格前插入行"
//'mergecells', //合并多个单元格
//'deletetable', //删除表格
'generateImage', //多图上传
//'edittable', //表格属性
//'edittd', //单元格属性
//'emotion', //表情
//'spechars', //特殊字符
//'map', //Baidu地图
//'gmap', //Google地图
//'insertvideo', //视频
//'help', //帮助
//'insertorderedlist', //有序列表
//'insertunorderedlist', //无序列表
//'fullscreen', //全屏
//'insertframe', //插入Iframe
//'attachment', //附件
//'wordimage', //图片转存
//'autotypeset', //自动排版
//'webapp', //百度应用
//'background', //背景
//'template', //模板
//'scrawl', //涂鸦
//'music', //音乐
//'inserttable', //插入表格
//'drafts', //从草稿箱加载
//'charts', //图表
],
],
labelMap: {
simpleupload: "插入图片",
},
//编辑器不自动被内容撑高
autoHeightEnabled: false,
//初始容器高度
initialFrameHeight: 300,
//初始容器宽度
initialFrameWidth: "95%",
elementPathEnabled: false,
//wordCount: false,
wordCount: true, //是否开启字数统计
maximumWords: 200000, //允许的最大字符数
//字数统计提示,{#count}代表当前字数,{#leave}代表还可以输入多少字符数,留空支持多语言自动切换,否则按此配置显示
wordCountMsg:
"当前已输入 {#count} 个字符,您还可以输入 {#leave} 个字符", //当前已输入 {#count} 个字符,您还可以输入{#leave} 个字符
serverUrl:process.env.VUE_APP_BASE_API +"ueditor/ueditorUpload",
UEDITOR_HOME_URL: "./UEditor/",
zIndex: 1,
},
}
},
methods: {
ueditorReady(editorInstance) {
this.ueditorOject = editorInstance;
//console.log(`编辑器实例${editorInstance.key}: `, editorInstance)
}
},
}
3、文档编辑-editor-for-vue(来源于ai-web项目)
说明:
A、wangEditor(王福朋,网名“前端双越”)是一款基于JS开发的轻量级、高扩展性的开源富文本编辑器
B、editor-for-vue是其官方提供的适用于Vue框架的组件
(1)createApp用法
a、基本语法
import { createApp } from 'vue';
const app = createApp(rootComponent, rootProps);
b、参数说明1,rootComponent(必选),Object或Component,根组件(通常是一个Vue组件选项对象或单文件组件)
const RootComponent = {
template: '<div>Hello, {{ name }}!</div>',
data() {
return { name: 'Vue 3' };
}
};
const app = createApp(RootComponent);
c、参数说明2,rootProps(可选),Object传递给根组件的props数据(键值对形式)
const RootComponent = {
props: ['message'],
template: '<div>{{ message }}</div>'
};
const app = createApp(RootComponent, {
message: 'Hello from props!'
});
d、返回值
const app = createApp(RootComponent)
.use(router)//使用插件
.use(store)//使用状态管理
.component('MyButton', MyButton)//注册全局组件
.mount('#app');
e、挂载到DOM
app.mount(document.getElementById('app'))
(2)真实案例。handleCreated,非常重要!!!
<script setup>
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import { onBeforeUnmount, ref, shallowRef, defineExpose, h as vueH, reactive, watch } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { Boot, DomEditor } from '@wangeditor/editor'
import { ftime } from '@/utils/util.js'
import { v1 as uuidv1 } from 'uuid';
import { h } from 'snabbdom'
import cctvRender from "@/components/editor/cctv-node.vue";
import CctvImgRender from "@/components/editor/cctv-img-render.vue";
import CctvTitleRender from '@/components/editor/cctv-title-render.vue'
import CctvExcerptRender from '@/components/editor/cctv-excerpt-render.vue'
import CctvKeywordsRender from '@/components/editor/cctv-keywords-render.vue'
import config from '@/config/index.js'
import useSettingsStore from '@/store/modules/settings';
const settingsStore = useSettingsStore()
const emit = defineEmits(['deliverInfo', 'exchange', 'stopCreat', 'adoptP', 'disuseP', 'resultIntervene','goldenSentenceVerificationEmi'])
const editorRef = shallowRef();//编辑器实例,必须用shallowRef
//浅层响应式,只对数据的顶层值进行响应式处理,不会递归处理嵌套的对象或数组
const valueHtml = ref('');
const domId = ref('');
const title = ref('');
const response = ref('');
const mold = ref(1); //1:分步生成、直接生成 2:智能配图 3:生成标题
const aiApp = ref(null)
const keywords = ref('');
const toolbarConfig = config.toolbarConfig;
const editorConfig = { placeholder: '请输入内容...' }
const menuStyle = ref({});
const editorScrollTop = ref(0);
const menuShow = ref(false);
const selectionText = ref('');
const jinjuyanzhengSelection = ref('');
const props = defineProps({
syllabusResult:{
default:null,
type:Object
}
})
watch(settingsStore.isStopOperate, newValue => {
if (newValue) {
editorRef.value.disable();
} else {
editorRef.value.enable();
}
})
function renderCctv(elem) {
const cctvVnode = h('span',
{
props: { contentEditable: false, id: elem.id },
style: { display: 'inline-block', },
},
)
return cctvVnode
}
function withCctv(refEditor) {
const { isInline, isVoid } = refEditor
const newEditor = refEditor
newEditor.isInline = elem => {
const type = DomEditor.getNodeType(elem)
if (type === 'cctv') return true
return isInline(elem)
}
newEditor.isVoid = elem => {
const type = DomEditor.getNodeType(elem)
if (type === 'cctv') return true
return isVoid(elem)
}
return newEditor
}
const renderElemConf = {
type: 'cctv',
renderElem: renderCctv,
}
Boot.registerRenderElem(renderElemConf);
Boot.registerPlugin(withCctv);
const insertPlugin = (type, params) => {
mold.value = type
if (domId.value !== '') {
let pluginDiv = document.getElementById(domId.value);
pluginDiv.parentNode.removeChild(pluginDiv);
domId.value = '';
}
if (aiApp.value) {
aiApp.value.unmount()
}
let id = uuidv1();
domId.value = id;
const node = { type: 'cctv', id: id, children: [{ text: '' }] }// 生成节点
if (type === config.MOLD.TITLE || type === config.MOLD.EXCERPT) {
editorRef.value.focus();
editorRef.value.moveReverse(editorRef.value.getText().length + 1000)
} else if (type === config.MOLD.KEYWORDS || type === config.MOLD.CONTINUATION) {
editorRef.value.move(editorRef.value.getText().length);
} else {
editorRef.value.focus();
}
editorRef.value.insertNode(node);// 在编辑区,插入节点。非常重要!!!
editorRef.value.disable();
setTimeout(() => {
let render = cctvRender
if (type == config.MOLD.IMAGE) {
render = CctvImgRender
}
if (type == config.MOLD.TITLE) {
render = CctvTitleRender
}
if (type == config.MOLD.EXCERPT || type == config.MOLD.CONTINUATION) {
render = CctvExcerptRender
}
if (type == config.MOLD.KEYWORDS) {
render = CctvKeywordsRender
}
aiApp.value = createApp(render,
{
originalParam: params,
mold: type,
},
)
aiApp.value.mount(document.getElementById(id));// 把应用,挂载到节点
}, 10)
return;
}
const insertContent = (type, params) => {
insertPlugin(type, params);
return
}
const setContent = (res) => {
if (typeof res === 'string') {
response.value = JSON.parse(res);
} else {
response.value = res;
}
}
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
if (editorRef.value == null) return
editorRef.value.destroy()
})
const handleCreated = (editorEle) => {
editorRef.value = editorEle; //把编辑区交给工具区,此后代码和工具区按钮都能操作编辑区。非常重要!!!
document.querySelector('#editor-content .w-e-scroll').addEventListener('scroll', editorScrollHandle);
}
// 父组件发起保存操作
const getEditorData = () => {
title.value = (title.value === '' ? ftime(new Date().getTime()) : title.value)
let deliverInfoObj = {
title: title.value,
content: editorRef.value.getHtml(),
contentText: editorRef.value.getText(),
keywords: [keywords.value],
}
emit("deliverInfo", deliverInfoObj)
}
const setEditorData = (obj) => {
title.value = obj.title;
editorRef.value.setHtml(obj.content);
}
// 插入素材
const insertMaterial = (content) => {
editorRef.value.focus();
let material = {
type: 'paragraph', children: [{ text: content }]
}
editorRef.value.insertNode(material);
}
//金句验证插入内容
const jinjuyanzhengInsertContent = (content) => {
editorRef.value.select(jinjuyanzhengSelection.value);
editorRef.value.insertText(content.trim());
}
const clearEditor = () => {
title.value = "";
editorRef.value.clear();
}
const editorSelectedHandler = ()=>{
if(editorRef.value.getSelectionText()!==''){
selectionText.value = editorRef.value.getSelectionText();
const sel = window.getSelection();
const range = sel.getRangeAt(0);
let copyRange = range.cloneRange();
sel.addRange(copyRange);
range.collapse();
jinjuyanzhengSelection.value = editorRef.value.selection;
const span = document.createElement('span');
range.insertNode(span);
// 计算绝对定位
// 文档
const dPos = document
.getElementById('editor-content')
?.getBoundingClientRect();
//划选落点
const pos = span.getBoundingClientRect();
//内容滚动的高度
let editorScrollTop = document.querySelector('#editor-content .w-e-scroll').scrollTop;
menuStyle.value = {
top: pos.top - dPos.top-4 + editorScrollTop,
left: pos.left - dPos.left,
};
menuShow.value = true;
span.remove();
range.setEnd(copyRange.endContainer, copyRange.endOffset);
range.setStart(copyRange.startContainer, copyRange.startOffset);
}else{
menuShow.value = false;
return false;
}
}
const editorScrollHandle = (event)=>{
editorScrollTop.value = event.target.scrollTop;
}
const editorEnable = ()=>{
editorRef.value.select(jinjuyanzhengSelection.value);
editorRef.value.enable()
}
defineExpose({
insertContent,
setContent,
getEditorData,
setEditorData,
insertMaterial,
jinjuyanzhengInsertContent,
clearEditor,
editorEnable,
})
</script>
<template>
<div class="editor-container">
<div class="editor-toolbar" id="editor-tool-bar-wrapper">
<div>
<Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" />
</div>
</div>
<div class="article-container">
<div class="article-content">
<div id="editor-content" class="editor-content">
<Editor
style="height: calc(100vh - 260px); overflow-y: hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
mode="simple"
@mouseup="editorSelectedHandler"
@onCreated="handleCreated" />
</div>
</div>
</div>
</div>
</template>
八、算法知识|编程绝句|显示屏尺寸|丈母娘要彩礼|国王付米|股票盈亏
1、算法知识
(1)查找算法:
A、通过和文件中的关键字进行比较来实现的,都采用平均查找长度来衡量算法的优劣。
B、那么能否有一种方法,不必进行与关键字的比较而达到查找的目的,这样平均查找长度就为0。
C、哈希查找的基本思想是:通过对给定值作某种运算,直接求得(((关键字等于给定值的)记录)在文件中的)位置。
(2)八种数据结构:
A、数组、栈、队列、链表、集合、字典、树、图(一组由边连接的顶点)!
B、以数组作为数组元素的数组,叫做二维数组,又叫做矩阵。
C、行数、列数相等的矩阵称为方阵。
D、元素以主对角线为对称轴对应相等的方阵叫做对称矩阵。
E、主对角线外都是零元素的方阵叫做对角矩阵。
F、将矩阵的行列互换得到的新矩阵称为转置矩阵。
G、存放图顶点间关系的矩阵叫做邻接矩阵。
(3)树与二叉树:
A、由有限节点组成,具有层级关系的数据结构叫做树;
B、每个节点最多有两个子节点的树叫做二叉树。
2、编程绝句
(1)我国清朝彭端淑曰:天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。
(2)吾本史学科班出身,为生计和兴趣计,经多次转行,最终以“必为”之心做了程序员。
(3)余自转行程序员以来,
A、别妻、离子、抛清明、弃五一、丧端午、失中秋、沦国庆、陷元旦、缺周六、损周日。
B、天明起床、半夜入睡,四季更替,周而复始,专心致志于公司、心无旁骛于陋室。希冀以勤补拙,技上层楼。
(4)编程艰途如攻山,拼上老命向上攀;满身创伤终登顶,无边群峰在眼前。
(5)目视夕阳缓缓落,心盼技术速速升。周遭高楼依次亮,谁知我在中关村?
(6)十年之前论古今,誓改人间换乾坤。如今只为生计计,犹落风尘做编程。
(7)当年悟空五行山,腾云驾雾难施展。而今吾身无负重,苦无神技助冲天。
(8)编程艰途如攻山,拼上性命向上攀。满身创伤终至顶,还有更高在眼前。
3、显示屏尺寸
function displayScreen(width,height,inch){
//以下,既是真假对角线的比例,也是真假宽、真假高的比例
var radio = inch/Math.sqrt(width*width+height*height);
//以下,真宽 = 真假宽的比例*假宽
var trueWidth = (radio*width*2.54).toFixed(2);
//以下,真高 = 真假高的比例*假高
var trueHeight = (radio*height*2.54).toFixed(2);
var line = (inch*2.54).toFixed(2);
var last = "";
last += inch + "寸" + width + ":" + height + "的显示屏,";
last += "宽" + trueWidth + "厘米;";
last += "高" + trueHeight + "厘米;"
last += "对角线" + line + "厘米!";
console.log(last);
}
for(var inch=10; inch<=80; inch+=1){displayScreen(16,9,inch)}
4、丈母娘要彩礼
function payMoney(startYuan, dayNum, time) {
startYuan = startYuan || 0.01;
dayNum = dayNum || 30;
time = time || 2;
//以下算出每天钱数
var dayMoney = '';
dayMoney += '丈母娘要彩礼' + '\n';
dayMoney += '第1天给' + startYuan + '元' + '\n';
dayMoney += '以后每天给前一天的' + time + '倍\n';
dayMoney += '连续给' + dayNum + '天\n';
for (var i = 1; i <= dayNum; i++) {
var money = startYuan * Math.pow(time, i - 1);
dayMoney += '第' + i + '天应该给丈母娘:' + money + '元' + '\n';
}
//以下算出所有天钱数
var total = 0;
for (var i = 1; i <= dayNum; i++) {
total += startYuan * Math.pow(time, i - 1);
}
//以下抛出最终结果
return dayMoney + dayNum + '天共计:' + total + '元';
}
console.log(payMoney())
5、国王付米
附、数字说明
(1)普通数字范围是正负2^53-1,即9007199254740991,是16位数字
(2)下面最终totalRice=2^64-1,即18446744073709551615,是20位数字
(3)BigInt可以表示任意大的整数,数字后面n表示这是一个BigInt类型的数值
(4)BigInt类型不能和Number类型运算,转化为相同类型才可以运算,前者转为后者可能会损失精度
(5)BigInt类型不能和小数(浮点数)运算,可通过“乘以10的几次方、运算、除以10的几次方”进行运算
function getTons() {
let india = "";
let pay = '';
let index = 64;
let currRice = 1n; //BigInt类型1/2
let totalRice = 0n; //BigInt类型2/2
let year = 2024;
let num = 5.36;
let tons = 0;
india += "印度国王与大臣下象棋,\n";
india += "国王输后,\n";
india += "大臣希望国王的赏赐如下\n";
india += "棋盘的第1个小格放1粒大米,\n";
india += "以后每个小格放前1个小格的2倍,\n";
india += "直到填满全部64个小格,\n";
india += "国王爽快答应,\n";
india += "但随着事情的发展,\n";
india += "情况越来越不对劲,\n";
india += "国王找人一算,\n";
india += "得出如下结论:\n";
for (let i = 1; i <= index; i++) {
pay += `第${i}个小格应放${currRice}粒大米\n`; //此时的currRice,是本次大米粒数
totalRice += currRice;
currRice *= 2n; //此时的currRice,是下次大米粒数!!!
}
//下面,获取克数并换算为亿吨,Number(totalRice)会损失精度
tons = Number(totalRice)*0.02/1000/1000/100000000;
pay += `全部64个小格应放${totalRice}粒大米\n`;
pay += `按照1粒大米0.02克算,`;
pay += `共计约${tons.toFixed(2)}亿吨\n`;
pay += `国王要赏赐的大米应为${year}年全球大米\n`;
pay += `总产量(${num}亿吨)的${(tons/num).toFixed(2)}倍\n`;
return india + pay;
}
console.log( getTons() );
6、股票盈亏计算器
<!DOCTPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>股票盈亏计算器</title>
<style>
.container {
margin: 50px;
}
.input-group {
margin: 20px 0;
}
input {
padding: 8px;
width: 146px;
}
button {
padding: 8px 16px;
border: none;
cursor: pointer;
width: 200px;
margin-bottom: 15px;
}
</style>
</head>
<body>
<div class="container">
<div>股票盈亏计算器</div>
<div class="input-group">
<label for="xInput11">本金:</label>
<input type="number" id="xInput1" placeholder="输入本金">
<span>万元</span>
</div>
<div class="input-group">
<label for="yInput1">市值:</label>
<input type="number" id="yInput1" placeholder="输入市值">
<span>万元</span>
</div>
<button id="btnId1">计算</button>
<div id="resId1"></div>
</div>
<div class="container">
<div>大盘涨跌计算器</div>
<div class="input-group">
<label for="xInput2">指数:</label>
<input type="number" id="xInput2" placeholder="输入大盘指数">
<span>点</span>
</div>
<div class="input-group">
<label for="yInput2">涨跌:</label>
<input type="number" id="yInput2" placeholder="输入涨跌比率">
<span>%</span>
</div>
<button id="btnId2">计算</button>
<div id="resId2"></div>
</div>
</body>
</html>
<script>
document.getElementById('btnId1').addEventListener('click', function() {
const xInput1 = document.getElementById('xInput1');
const yInput1 = document.getElementById('yInput1');
const resEle1 = document.getElementById('resId1');
const cost = parseFloat(xInput1.value);
const market = parseFloat(yInput1.value);
if (isNaN(cost) || isNaN(market)) {
resEle1.innerHTML = '请输入有效的数字';
return;
}
const profit = (market - cost).toFixed(2);
var text1 = '本金' + cost + '万元,市值' + '' + market + '万元,' ;
var rate1 = (profit / cost * 100).toFixed(2); // 先计算数字,再保留4位小数
if (profit >0) {
text1 += '盈利' + profit + '万元,盈利率为' + rate1 +'%';
}else if (profit == 0) {
text1 += '既没有盈利,也没有亏损!';
}else if (profit < 0){
rate1 = -rate1;
var up = (100 * rate1) / (100 - rate1);
text1 += '亏损' + (-profit) + '万元,<br/>';
text1 += '亏损率为' + rate1 +'%,上涨' + up.toFixed(2) +'%,才可以回本';
}
resEle1.innerHTML = text1;
});
document.getElementById('btnId2').addEventListener('click', function() {
const xInput2 = document.getElementById('xInput2');
const yInput2 = document.getElementById('yInput2');
const resEle2 = document.getElementById('resId2');
const currDot = parseFloat(xInput2.value);
const rate2 = parseFloat(yInput2.value);
if (isNaN(currDot) || isNaN(rate2)) {
resEle1.innerHTML = '请输入有效的数字';
return;
}
const result = currDot * (1 + rate2 / 100);
const furtDot = result - currDot;
const absRate2 = Math.abs(rate2);
var text2 = `大盘从${currDot}点,`;
if (rate2 > 0) {
text2 += `上涨${absRate2.toFixed(2)}%,为${result.toFixed(2)}点`;
/* text2 += `,上涨点数,为${furtDot.toFixed(2)}点`; */
} else if (rate2 == 0) {
text2 += `没有变化,仍为${currDot.toFixed(2)}点`;
} else if (rate2 < 0) {
text2 += `下降${absRate2.toFixed(2)}%,为${result.toFixed(2)}点`;
/* text2 += `,下跌点数,为${-furtDot.toFixed(2)}点`; */
}
resEle2.innerHTML = text2;
});
</script>
九、在线工具之AI网址
1、在线工具之AI网址-综合网址(包含AI与非AI)
附、其它
A、在线代码对比,https://www.bejson.com/others/comparecode/
B、在线文件转换(文档、视频),https://convertio.co/zh/download
C、在线bootcdn,https://www.bootcdn.cn/</head>
D、在线MDN,https://developer.mozilla.org/zh-CN/docs/Learn_web_development
E、历史天气,https://tianqi.2345.com/wea_history/54511.htm
F、4千行网页存为图片,
a、截取步骤:IE浏览器--ctrl+shift+s--捕获整页--接近1600行
b、高度说明:这个高度大于其它一切浏览器的保存网页为图片的高度
c、截取范围:当前位置向上向下各800行,上不足部分向下补,下不足部分向上补
(1)在线代码转图片
A、Carbon,https://carbon.now.sh/
B、codeimg,https://codeimg.io/
C、Chalk.ist,https://chalk.ist/
D、CodeKeep,https://codekeep.io/screenshot
E、Purple Photo Editor,https://purple-photo.web.app/code-editor
F、Code to lmage,https://codetoimg.com/
G、10015,https://10015.io/tools/code-to-image-converter
H、snappify(疑坏),https://snappify.com/
I、Ray.so,https://ray.so/
J、以上导航,https://flowus.cn/sagima/share/c3cfbdf1-8086-4164-a66c-6a73ec957679
K、独特工具箱,https://www.dute.org/code-snapshot
(2)微工具,https://www.wetools.com/
A、热门工具
B、开发工具,JS在线运行工具、CSS代码压缩工具、JSON格式化校验工具、YAML转JSON、.gitignore生成工具、LESS转CSS
C、站长工具,爬虫模拟抓取工具、User Agent分析工具、网页Meta标签生成器
D、常用对照表,常用AI写作提示词、常用Linux命令、常见MimeType参考表
E、编码&解码,URL编码/解码、Punycode编码/解码、摩尔斯电码
F、加密&解密,DES加密/解密、RIPEMD160哈希加密、RC4加密/解密
G、通用查询,身份证信息查询、商品保质期计算器、银行卡信息查询工具
H、换算工具,UNIX时间戳转换、人民币大小写转换、IP转数字
I、语言工具,繁简转换、汉字转拼音、拼音字母表
J、图片工具,图片转ASCII字符、图片转Base64、图片占位符
K、生成工具,艺术二维码生成器、在线二维码生成器、密码生成器、条形码生成器、PornHub风格Logo生成器、UUID生成器
(3)在线工具,https://tool.lu/
A、文本类,
a、智能文案撰稿、违禁词检测、asciidoc编辑器、markdown编辑器、mermaid编辑器、文字加密解密、hex转字符串、汉字转拼音五笔、
b、中文简繁体转换、ascii table生成、谐音梗、数字转大写、ascii画、字数统计、对比归并、摩斯电码、中文拆字
B、文档类,
a、文件批量重命名、合并图片为pdf、pdf合并、pdf调整、pdf加页码、pdf分割
C、图像类,
a、一键抠图、图片高清放大、证件照打印排版、图片转latex、图片信息查看工具、电子签名图片、拼图、gif裁剪、gif缩放、gif分割、
b、节日头像制作、图片加水印、favicon在线制作、图片base64编码、占位图片、email图片生成、图片压缩、二维码生成、
c、app icon制作、图片文字识别、条形码生成、图片格式转换、证件照裁剪、图片规格、切图工具
D、音频类,
a、音频剪辑
E、视频类,
a、字幕翻译器、字幕格式转换
F、开发类,
a、ui代码生成、代码反混淆、javascript工具、css工具、python工具、php工具、html工具、websocket测试工具、正则测试工具、
b、sql工具、json工具、xml工具、crontab时间计算、进制转换、在线运行代码、useragent分析、时间戳转换、java在线工具、字体、
c、代码着色、htpasswd在线生成、Html特殊字符表、UUID生成器、包管理、http状态码、查看网页源码、curl命令转代码、yaml工具、
d、csr证书生成、crx下载解压、随机字符串生成、网页头信息查看、Shell工具、Linux命令、MagicBytes、Shield
G、运维类,
a、dns查询、htaccess转nginx、Punycode编码转换、whois查询、顶级域名后缀、整数分区计算工具
H、设计类,
a、格子纸、颜色工具
I、学术类,
a、字帖生成器、化学元素周期表、分数计算器、计算器、歇后语、成语词典、各国首都列表、历史朝代表、单位转换、高校查询
J、查询类,
a、IP地址查询、日期时间计算器、取名大师、历史上的今天、手机号归属地、邮编区号查询、汇率计算、今天吃什么、血型遗传规律表、
b、车牌查询、亲戚称谓计算器、标准纸箱尺寸计算、纸张尺寸查询、生肖查询、cidr计算器、键盘符号英文对照表、尺码对照表、
c、计算机词汇发音、放假安排
K、音乐类,
a、节拍器、吉他调音器
b、抛硬币、地图坐标系转换、手持弹幕、下载链接转换、种子文件分析、文件hash计算
L、其它,
(4)即时工具,https://www.67tool.com/
A、视频工具,
a、视频剪切、视频去水印、视频格式转换、在线录屏、视频提取音频、视频编辑、视频压缩、视频分辨率转换、视频转gif、视频倒放、
b、视频裁切、视频拼接、视频加文字、视频修改分辨率、视频转mp4、视频加水印、视频截帧、视频批量调速、视频调整比例、
c、视频调整音量、视频静音、视频添加音频、视频旋转、视频批量缩放、视频批量翻转、视频缩放、视频调速、视频转avi、视频转webm、
d、视频转mov、视频转flv、视频转mpg、视频转mkv、视频转wmv、视频转3gp、视频旋转、视频翻转
B、音频工具,
a、音频剪切、音频格式转换、音频转mp3、音频转文字、音频倒放、音频修改音量、音频拼接、音频压缩、音频调速、音频转pcm、
b、音频转wav、音频循环、音频批量调速、音频转flac、音频转ogg、音频转m4a、音频转aac、音频转opus、音频转ac3、批量调整音量、
c、音频合并
C、图片工具,
a、图片压缩、智能抠图、图片拼接、图片放大、图片编辑、图片分割、图片水印、图片转JPG、图片调整大小、图片Base64互转、
b、图片转ICO、图片调色、照片转油画、GIF制作、颜色吸取器、图片无损放大、图片格式转换、图片转PNG、图片圆角、GIF压缩、
c、图片裁切、照片转铅笔画、图片加边框、图片调整、头像挂饰生成、SVG编辑器、通道混合器、商品抠图、图片毛玻璃效果、GIF分割、
d、图片离线压缩、GIF裁切、SVG转PNG、图片转WEBP、GIF合并、图片转AVIF、图像转TIFF
D、文档处理,
a、PDF合并、PDF拆分、PDF压缩、PDF提取、PDF删除、PDF排序、PDF解锁、PDF添加水印、PDF加密、PDF旋转、PDF添加页码、Excel合并、
b、Excel分割
E、文档转换,
a、图片转PDF、PDF转Word、PDF转文本、JSON转Excel、Word转PDF、PDF转图片、PDF转Excel、PDF格式转换、Word转Markdown、
b、Excel转JSON、PDF转PPT、Excel转PDF、PPT转PDF、HTML转Word、图片转Excel、Word转TXT、Word转HTML、Word格式转换、
c、html转markdown、markdown转html、Excel格式转换、Excel转Markdown、Excel转HTML、Excel转Csv、Csv转Excel、Excel转TXT
F、数据图表,
a、柱状图、雷达图、折线图、饼图、南丁格尔玫瑰图、河流图、K线图、环形图、散点图、漏斗图、分组柱状图、分组折线图、
b、条形柱状图、瀑布图、堆叠柱状图、堆叠条形图、阶梯折线图、正负条形图、层叠面积图、堆叠面积图、分组条形图
G、智能文本,
a、标点符号纠错、短视频脚本、种草文案、标题生成、文本优化、周报、日报、广告文案、朋友圈营销、直播带货脚本、创意点子、
b、电商营销、添加标点符号、商品卖点、产品介绍、广告标题、探店点评、购物点评、OKR计划、PPT大纲生成、节日营销
H、办公辅助,
a、条形码生成、二维码生成、思维导图、吃什么、文字转图片、Unix时间戳转换、Markdown编辑器、图片OCR、番茄钟、小决定、
b、设计配色、在线画板、在线解压、多语言OCR、在线压缩、二维码解析、色值互转、搜图导航、随机生成密码、JSON编辑器、
c、二维码批量生成、条形码解析
I、文本工具,
a、文本提取URL、unicode转文本、文本比对、换行转空格、文本转摩尔斯电码、文本转unicode、文本反转、空格转回车、
b、摩尔斯电码转文本、分割文本、词频统计、字数统计、文本工具、文本替换、删除所有空格、字频统计、文本提取数字、简体转繁体、
c、繁体转简体、删除空行、文本提取邮箱、删除重复行、文本大写、单词转大写、大小写反向、空格转tab、tab转空格、文本标题大写、
d、文本小写
J、数字工具,
a、十六进制转文本、数字工具、十六进制转十进制、随机数、文本转十六进制、文本转二进制、二进制转十进制、十进制转十六进制、
b、二进制转文本、十进制转二进制、数字转中文、十六进制转二进制、十进制转文本、二进制转十六进制、数字转金额大写、
c、文本转十进制、数字转英文、ASCII转文本、英文转数字、文本转ASCII、八进制转文本、十进制转八进制、八进制转十六进制、
d、八进制转十进制、二进制转八进制、文本转八进制、十六进制转八进制、十进制转罗马数字、八进制转二进制、罗马数字转十进制
K、加密工具,
a、加密工具、URL解码、Base64解码、MD5编码、SHA256编码、Base64编码、URL编码、UTF8解码、SHA1编码、UTF8编码、SHA512编码、
b、MD2编码
L、单位转换,
a、字节转换器、长度转换器、时间转换器、角度转换器、能量转换器、压力转换器、速度转换器、电源转换器、质量转换器、配速转换器、
b、面积转换器、电流转换器、频率转换器、体积转换器、温度转换器、电压转换器、现有功率转换器、体积流量转换器、光照度转换器、
c、无功能量转换器
(5)菜鸟工具,https://www.jyshare.com/
A、热门工具
B、搜索资源
C、常用工具,
a、HTML压缩/解压工具、JS压缩/解压工具、CSS压缩/解压工具、JSON在线解析、RGB转16进制工具、在线进制转换器、图片转BASE64编码、
b、HTML/CSS/JS在线工具、随机密码生成器、HTML编码/解码、Base64编码/解码、URL编码/解码、SQL格式化/压缩工具、MD5在线加密工具、
c、SHA在线加密工具、XML/JSON在线转换、在线XML格式化、Markdown在线编辑器、HTML转JavaScript在线工具、时间戳转换器、
d、正则表达式在线测试、RGBHSV转换、RGBCMYK转换工具、HEXCMYK转换工具、HEXHSV转换工具、HSVCMYK转换工具、在线二维码生成器、
e、在线Unicode编码转换、IP地址查询、HTML取色器、汉字转拼音、代码在线高亮、长度单位换算、在线繁体字转换器、在线字数统计工具、
f、今日日期、取色器、图片取色器/拾色器、CSS按钮生成器、PNG/JPEG图片压缩、ASCII表、调色板、图片加水印、颜色选择器、
g、随机数生成器、在线涂鸦画板、在线计算器、JavaScript混淆/加密、pdf转图片(jpg,png)、代码生成图片、在线JSON解析、
h、在线图片转PDF工具、正则表达式可视化工具、JSON转义/去除转义、HTML表格生成器、在线汇率换算器、在线文本比对工具、世界地图、
i、中国地图、AI解析正则表达式、随机颜色生成器、随机字符串生成器、AI对话提示词(prompt)、存储单位换算、AI解析代码、AI注释代码、
j、AI编程助理、SQL在线测试工具、字母大小写转换、在线占位图生成工具、在线UUID生成器、BMI计算器、在线图片合并工具、
k、在线图片转文字工具、Crontab在线生成器、测试数据在线生成、日期计算器、JSON差异对比、程序员变量名助手、AI代码转换工具、
l、工作日计算器、User-Agent解析工具、Markdown思维导图工具、Latex数学公式编辑器、PDF在线阅读器、在线倒计时器、
m、Mermaid在线绘图工具、AI在线翻译工具、在线MAC地址生成器、在线颜色选择器、CSS在线渐变色生成器、房贷计算器、秒表、
n、图片转A4、A3、A5、图片尺寸修改
D、编译工具,
a、PHP在线工具、Python2在线工具、Python3在线工具、Java在线工具、C在线工具、C++在线工具、Ruby在线工具、C#在线工具、
b、Scala在线工具、Erlang在线工具、Perl在线工具、Bash在线工具、RUST在线工具、Swift在线工具、Go在线工具、Node.js在线工具、
c、Lua在线工具、Pascal在线工具、Kotlin在线工具、TypeScript在线工具、VB.NET在线工具、R在线工具、Assembly在线工具、
d、Groovy在线工具
E、在线工具,
a、RegExr、在线编译工具、rextester、Ideone、GDB online Debugger、JSFiddle、CodePen、JSON 解析器、Postman、
b、API文档 & Mock工具、Redis 在线测试、Paiza、Learn Git Branching、JS Bin、正则可视化工具、代码转图片工具、
c、算法可视化学习、asciiflow、codelf、Desmos、SQL OnLine IDE、regex101、WebVM、Jsitor、Playcode、Jseditor、Liveweave、
d、Replit、Codesandbox、Jdoodle、Stackblitz、Apipost、drawDB、API 工具 Hoppscotch、DeepSite、DeeWiki
F、技术学习,
a、Stack Overflow、技术学习路线、DevDocs、MDN Web Docs、掘金、前端开发、DEV Community、InfoQ-极客邦、免费编程书籍、
b、编程测验、Hello 算法、V2EX、CNode、Linux 公社、MSDN、developerWork、力扣、Reddit、Hacker News、FreeBuf、W3School、
c、51CTO、Dzone、博客园、CSDN、开源中国、Algorithms、编程书籍、中国大学 MOOC、OSS Insight、Smashing Magazine、InfoQ、
d、数据可视化、Cybernews、Product Hunt、DataCamp、CodeGeeX 编程助手、Ollama、Dify、AnythingLLM、阿里云百炼、
e、Cherry Studio、Chatbox AI、APILayer、Indie Hackers、Levels.fyi
G、AI应用,
a、ChatGPT、DeepSeek、Midjourney、Runway、通义灵码、秘塔AI搜索、Perplexity、Hugging Face、Character AI、Grammarly、
b、Cursor、通义千问、讯飞星火、Adobe Firefly、Galileo AI、Fitten Code、RemoveBG、Clipdrop、Quillbot、Writesonic、
c、Notion AI、getimg.ai、Phygital+、Autodraw、文心一言、GitHub Copilot、Stable Diffusion、Civitai、Genmo、Kimi、
d、Copilot X、Suno、Liner、JanitorAI、SpicyChat、Gamma AI、扣子 (Coze)、Gemini、豆包、腾讯元宝、Bing Copilop、
e、Grok AI、天工 AI、YouChat、即梦 AI、ima copilot、智谱清言、Sora、Anthropic、Trae
H、多媒体工具,
a、TinyPNG、图片无损压缩、Convertio、Online converter、PDF to Word Converter、PDF24、在线文件转换器、在线绘图工具、
b、思维导图工具、SketchBoard、ProcessOn、思维导图工具、Gliffy、幕布、在线画图工具、SVG 编辑器、PDF 编辑器、PDF 转图片、
c、DeepL、图片转 PDF、草料二维码、XMind、MindLine、Pixlr、Lucid Chart、剪映、ChatMind、Excalidraw、Mermaid - 图表工具、
d、cobalt 视频下载工具、PlantUM、tldraw、Obsidian
I、原型工具,
a、Figma、Adobe XD、Sketch、Axure、即时设计、墨刀、Framer、ProtoPie、Proto.lo、Fluid、Marvel、UXPin、Pixso、MasterGo、
b、码前、摹客、Invision、flinto、Principle、Origami、MockFlow、Balsamiq、Zeplin
J、社区媒体,
K、图库&色彩,
a、谷歌以图搜图、百度识图、iLoveIMG、图片转 PDF 工具、图片加水印、搜狗图片、片刻抠图、图片背景消除、AI 智能抠图、
b、稿定抠图、PicWish、在线 PS 软件、图怪兽、图贴士、Logo 设计、在线 SVG 制作、图片转 ICO、Pixabay、Pxhere、PhotoMosh、
c、百度图片、在线 PS 工具、必应图库、必应视觉搜寻、图片去水印、大作、Everypixel、Depositphotos、稿定设计、图虫、花瓣、
d、Fotor、图司机、创客贴、Instagram、Canva、微词云、词云文字、鸭力巨大、镝数图表、图可丽、改图宝、图好快、背景图制作、
e、Blobmaker、智绘证件照、在线 PS 编辑、ARC Lab、美图秀秀、爱设计、文心一格、比格设计、即梦 AI、免费图标、千图网
L、科技媒体,
M、其他推荐,
(6)锤子在线工具网,https://www.toolhelper.cn/
A、JSON,
a、JSON格式化、JSON转义、JSON生成实体类
B、格式化,
a、HTML格式化、JavaScript格式化、CSS格式化、JSON格式化、XML格式化、SQL格式化、C格式化、C++格式化、C#格式化、
b、Java格式化、PHP格式化、Python格式化
C、URL,
a、URL参数格式化、URL参数与JSON互转、URL编码/解码
D、编码与解码,
a、字符编码/解码、URL编码/解码、Base64编码/解码、Base16、Base32、Base58、Base62、Base85、Base91编码/解码、
b、Unicode与中文编码/解码、Punycode编码/解码、Quoted-Printable编码/解码、进制转换(单字节)、字节数组有无符号数互转、
c、GzipDeflate压缩/解压缩、JWT解析器
E、编码查询,
a、编码列表ASCII编码表、GB2312编码表、GBK编码表、GB18030编码规则、Big5编码表、Unicode编码规则、UTF-16编码表、Emoji表情符号、
b、特殊符号大全
F、数字工具,
a、进制转换(正整数)、进制转换(负整数)、IEEE754浮点数转换、进制转换(BigInt)、原码/反码/补码、计算器、十六进制计算器、
b、模幂计算器、计算器、商和余数计算器、chmod计算器、房贷计算器、屏幕PPI计算器、IPv4转IPv6、人民币大写转换、单位换算、
c、大小端转换、二进制逆序、数组逆序、数字排序
G、文本工具,
a、文本对比、文本处理、文本去重/排序、文本分割、文本合并、文本转义、文本逆序、文本美化、标点符号转换、文本行长度过滤、
b、文本行定长、键值对转代码、字数统计、正则表达式、英文字母大小写转换、汉语拼音转换、汉字简体繁体转换
H、日期工具,
a、Unix时间戳、Cron表达式、世界时间表、在线秒表、日期计算器、年龄计算器、万年历、公历农历转换、公历闰年查询、农历闰月查询
I、HTML工具,
a、HTML下载、MetaTag提取、HTML标签过滤、HTML格式化、文本转HTML表格、HTML在线运行、Markdown在线编辑、HTML转义字符
J、HTTP工具,
a、我的公网IP地址、我的浏览器指纹、HTTP模拟请求、服务器端口开放检测、SSL证书检测、域名Whois查询、域名DNS查询、HTTP状态查询、
b、HTTP请求方式、HTTPMimeType
K、图片工具,
a、RGB颜色代码转换、调色板工具、屏幕颜色拾取、图片颜色拾取、图片转ico图标、九宫格图片裁剪、图片大小裁剪、图片自定义大小、
b、图片压缩、图片格式转换、图片与Base64转换、在线Photoshop、SVG编辑器、涂鸦画板、文字生成图片
L、条形码和二维码工具,
a、条形码和二维码识别、二维码生成、条形码生成
M、SSL证书,
a、SSL证书检测、SSL证书解析、PfxToPEM、SSL证书生成
N、摘要算法,
a、MD5加密、SHA加密、HMAC-MD5加密、HMAC-SHA加密、SM3加密、RIPEMD加密、CRC校验、BCCLRC校验
O、对称加密/解密,
a、SM4加密/解密、DES加密/解密、TripleDES加密/解密、AES加密/解密、RC2加密/解密、RC4加密/解密、RC5加密/解密、RC6加密/解密、
b、Blowfish加密/解密、Rabbit加密/解密、异或加密/解密、摩斯密码、凯撒密码加密/解密
P、非对称加密/解密,
a、RSASM2
Q、随机数工具,
a、随机数生成器、随机密码生成器、GUID生成器
R、设备辅助测试,
a、键盘按键测试、键盘KeyCode值、鼠标按键测试、麦克风测试、摄像头测试、屏幕测试
S、其他工具,
T、娱乐工具,
2、在线工具之AI网址-中文AI导航类网站
(1)总
A、AI导航集合,https://ai-dh.cn/
(2)不可用
A、ai321,https://www.ai-321.cn/AI/153.html
B、AI指南,https://aizhinan.cn
C、神器集,https://hao.logosc.cn
D、未来百科,https://www.huntagi.com
E、未道帮AI导航,https://nav.aiwave.cc
F、一起用AI,https://17yongai.com
(3)可用
A、360AI导航,https://ai.hao.360.com
B、AIBase,https://top.aibase.com
C、AIGC导航,https://www.aigc.cn
D、AIHub,https://www.aihub.cn
E、AI工具箱,https://aitoolbox.cn
F、AI大师,https://www.aidashi.cn
G、AI导航,https://www.jyshare.com/ai/</html>
H、AI工具集,https://ai-bot.cn
I、AI工具站,https://www.aixxq.com
J、AI聚合网,https://www.aijhw.com
K、AI旋风,https://www.aixuanfeng.com
L、AI之旅导航,https://www.aijourney.vip
M、OpenIAI时代,https://openi.cn
N、办公人导航,https://www.bgrdh.com
O、非猪AI导航,https://feizhuke.com
P、考拉新媒体导航,https://www.kaolamedia.com
Q、老北鼻AI工具箱,https://lbbai.com
R、深度AI导航,https://www.deepdhai.com
S、图钉AI导航,https://ai.tboxn.com
T、无峰网址导航,https://www.8kmm.com/type/ai
U、新媒派,https://pidoutv.com
V、映技派,https://www.yjpoo.com/
W、在线工具,https://tool.lu/nav/
X、一流导航,https://16map.com/ai
Y、AI导航,https://aidh.net/
Z、别摸鱼导航,https://biemoyu.com/#term-222
3、在线工具之AI网址-重要网站示例
(1)国内AI编程助手,
A、智能编程助手,https://codegeex.cn/zh-CN/playground
B、文心快码,https://comate.baidu.com/en
C、通义灵码,https://lingma.aliyun.com/lingma/
(2)chatGPT,http://chat.178le.net/index
A、2022年11月30日,美国OpenAI发布的聊天机器人程序
B、全名:Chat Generative Pre-trained Transformer
C、汉译:人工智能技术驱动的自然语言处理工具
D、直译:聊天生成的、经过训练的、改革者
E、Copilot Hub:基于ChatGPT创建个人的知识库AI,app.copilothub.co
(3)deepseek,https://chat.deepseek.com/
A、2023年7月,DeepSeek公司成立并开始研发大模型
B、2024年1月,推出DeepSeek-V2模型,性能显著提升
C、2024年6月,推出DeepSeek-V3版本,进一步优化代码
D、2024年8月,发布DeepSeek-V3.5,在逻辑推理、编程和复杂任务处理上大幅改进
E、2024年9月,DeepSeek推出V2.5版本,着重强化了数学推理、创作及写作能力,还增添联网搜索功能
F、2024年11月20日,DeepSeek发布R1-Lite系列,作为国产推理模型对标OpenAI o1,在数学、代码及逻辑推理任务中表现优异
G、2024年12月26日,DeepSeek-V3正式上线并开源,性能与顶尖闭源模型相当
H、2025年1月20日,DeepSeek基于R1模型推出DeepSeek聊天机器人,免费面向iOS和安卓用户开放
---2025年1月27日16时05分,马小林在钉钉群-前端-说,https://chat.deepseek.com/,这个是最近火的AI编程,确实很好用,大家可以试试
I、2025年2月,DeepSeek-V3广泛上架各大云平台,如百度智能云千帆平台、京东云、中国电子云、阿里云等
(4)豆包,https://www.doubao.com/chat
A、2023年8月,字节跳动的人工智能机器人“豆包”开始测试
B、2023年11月,在字节跳动旗下产品(如今日头条、抖音等)中逐步开放入口,提供问答、创作等基础功能
C、2024年1月,支持图片生成、理解,增强对复杂指令的响应能力
D、2024年3月,“豆包Pro”发布,提供更高性能的模型,支持更长上下文,并优化代码生成和逻辑推理能力
E、2024年5月,字节跳动宣布豆包大模型正式开启对外服务,相比同行便宜99.3%
---2024年8月27日16时59分,章星华在微信群-蕾蕾的那些花儿-说,那你用国内的豆包吧
F、2024年10月,字节跳动豆包发布首款AI智能体耳机Ola Friend
G、2024年11月,豆包推出视频生成内测功能,支持图片文字一键成片、动态运镜等
H、2024年12月,豆包上线图片理解功能,在App及PC端新增按钮,可精准识别图片元素、特征
I、2025年1月20日,豆包App的7.2.0新春版上线实时语音通话功能
J、2025年3月5日,豆包宣布上线「深度思考」推理模式,覆盖问答、搜索、写作和阅读场景
(5)问答类AI
A、讯飞星火(科大讯飞),https://xinghuo.xfyun.cn/desk,2023年5月6日
B、智谱清言(智谱AI),https://chatglm.cn/main/alltoolsdetail,2023年8月30日
C、文心一言(百度),https://yiyan.baidu.com/,2023年8月31日
D、百小应(百川智能),https://ying.baichuan-ai.com/chat,2023年9月6日
E、通义千问(阿里云),https://qianwen.aliyun.com/,2023年9月13日
F、Kimi Chat(月之暗面),https://kimi.moonshot.cn/,2023年10月10日
G、问小白,https://www.wenxiaobai.com/,2023年11月
H、DeepSeek Chat(深度求索),https://chat.deepseek.com/,2024年1月
I、360智脑(360集团),https://ai.360.cn/,2023年9月
J、腾讯混元助手(腾讯),https://hunyuan.tencent.com/,2023年9月
K、天工AI(昆仑万维),https://www.tiangong.cn/,2023年4月
L、元宝AI(腾讯),https://yuanbao.qq.com/,2024年9月
M、豆包(字节跳动),https://www.doubao.com/,2023年8月
N、言犀(京东),https://yanxi.jd.com/,2023年2月
O、盘古大模型助手(华为云),https://www.huaweicloud.com/product/pangu.html,2023年7月
P、MiniMax(MiniMax AI),https://www.minimaxi.com/,2023年6月
Q、阶跃星辰(阶跃星辰),https://step.star/,2024年3月
4、在线工具之AI网址-图片和视频类网站
(1)既能生成图片又能生成视频的
A、Runway ML,2018 年(2022 年推图像生成),视频 & 图片 AI 生成与编辑,https://runwayml.com
B、Pika Labs,2023 年 4 月,文本 / 图像转 3D 风格视频,https://pika.art
C、可灵 AI,图生视频最强
D、海螺 AI,创意 / 视觉效果更佳,https://hailuoai.com/
E、Vidu,速度快成本低
F、Viggle(换人物保留动作),可通过网页或社交平台直接使用(如抖音 / 海外平台)
G、MiniMax(文字转视频),提供网页端和 API(部分高级功能可能需本地部署)
H、runway,静态图片变静态
(2)只能生成图片的
A、图片生成
a、Adobe Firefly,Adobe 家族 AI,与 PS 深度整合,https://www.adobe.com/sensei
b、Canva AI,内置 AI 生成图片、设计模板,https://www.canva.com/
c、ClipDrop,AI 抠图、产品图生成,https://clipdrop.co/
d、DALL・E3 (OpenAI),文本生成精准细节图像,https://openai.com/dall-e
e、Bing ImageCreator,微软免费 AI 绘画(DALL・E3 驱动),https://www.bing.com/create
f、Ideogram,文字融合图像生成,https://ideogram.ai
g、Leonardo.AI,游戏 / 设计专用 AI 生图平台,https://leonardo.ai
h、MidJourney,高质量艺术风格图像生成,https://www.midjourney.com
i、Stable Diffusion Online,开源 AI 绘画支持自定义模型,https://stablediffusionweb.com
j、WHEE(百度),手机端 AI 绘画应用,https://whee.baidu.com,图生海报 / 修图
k、通义万相(阿里),阿里云 AI 绘画工具,https://wanxiang.aliyun.com,中国元素理解更强
l、文心一格(百度),中文 AI 绘画多艺术风格,https://yige.baidu.com
m、盗梦师,小程序 / 网页版,二次元风格,微信搜索 “盗梦师”
n、即梦 AI,文生图能力更强
o、emoAI,让照片开口唱歌
p、magic studio,去除图片中的任何元素
q、veoAI,https://veo2.pro/zh
r、智小象,https://hidreamai.com/studio
B、图片处理
a、Remini,老照片修复、高清化,https://remini.ai/
b、Magnific AI,图片超分辨率放大,https://magnific.ai/
c、腾讯 ARC 实验室图象增强工具:https://arc.tencent.com/zh/ai-demos/faceRestoration
d、Bigjpg 中文站:https://www.ai-321.cn/AI/153.html
e、佐糖图片无损放大(picwish):https://picwish.cn/image-enlarger
f、cappuccino 无损放大:https://cappuccino.moe/
g、waifu2x 无损放大:https://www.waifu2x.net
h、MagicEraser.pro(删除多余物体),完全基于网页操作
i、Magnific(换背景),部分功能可能需要订阅
j、Demo Sacing(去马赛克),部分功能需安装本地软件(依赖算法性能)
C、去除图片背景(照片抠图)
a、豆包(屏黄政),https://www.doubao.com/chat/create-image
b、可画,https://www.canva.cn/features/remove-background/
c、REMOVE.BG(在线抠图):https://www.remove.bg/,线上去背景,全自动 AI,速好,有免费额度及多平台支持
d、搞定设计,https://www.gaoding.com/koutu
e、鲜艺AI抠图,https://kt.94xy.com/
f、FOCOCLIPPING:https://www.fococlipping.com/,免费线上去背,支持手动编辑、高清、批量处理
g、SLAZZER:https://www.slazzer.com/,5 秒速去背,支持手动编辑、背景模糊及合成
h、PHOTOSCISSORS:https://photoscissors.com/,老牌去背,支持多格式,限 10MB,可标记范围
i、TRACEBYSTICKERMULE:https://www.stickermule.com/trace,自动去背,支持两格式,可套色或图
j、BGERASER:https://bgeraser.com/,AI 去背,5 秒完成,注册后支持 1080×1080 像素
k、REMOVAL.AI:https://removal.ai/,自动处理,免费低解析,注册可下高解析
l、INPIXIO:https://www.inpixio.com/remove-background/,免费自动去背,可手动标记,输原大小
m、PROFILEPICMAKER:https://pfpmaker.com/,免费大头贴工具,支持去背、滤镜及编辑
n、AIBACKGROUNDREMOVER(ICONS8):https://icons8.com/bgremover,Icons8 免费去背,限 5MB,不压缩
o、BACKGROUNDCUT:https://backgroundcut.co/,AI 自动去背,注册有额度,可转透明或套色
p、DESIGNIFY:https://www.designify.com/,免费全自动去背,支持拖曳或贴网址,含编辑器
q、BGREMOVER:https://www.aigei.com/bgremover,中国去底工具,转纯色背景为透明,可调容差
r、PHOTOROOM:https://www.photoroom.com/background-remover/,免费去背,支持多端,可转透明或套色
D、其它
a、菜鸟工具-图库 & 色彩,https://www.jyshare.com/imglibs/
b、即时工具-图片工具,https://www.67tool.com/category/5f56fb0164935e78271fd5a1
c、锤子在线工具网-“图片工具”,https://tool.lu/
d、在线工具-图像类,https://tool.lu/c/image/
(3)只能生成视频的
A、Fliki,文本转视频 + AI 配音,https://fliki.ai
B、HeyGen,AI 多语言口型视频,https://www.heygen.com
C、InVideoAI,模板化 AI 短视频生成,https://invideo.io/ai
D、Kaiber,音乐同步 AI 动画生成,https://kaiber.ai
E、Sora (OpenAI),(未开放),高保真文本生成视频,https://openai.com/sora
F、Synthesia,AI 数字人视频制作,https://www.synthesia.io
G、DreamMachine,实时文本生成动态视频,https://labs.luma.ai/dream-machine
H、Stable Video,开源 AI 视频生成模型,https://stability.ai/stable-video
I、闪剪(数字人),通常需安装桌面端或移动端 APP(如国内数字人工具)
J、剪映,https://www.capcut.cn/
K、菜鸟工具 - 视频剪辑,https://www.jyshare.com/office/#runoob-goto-141
L、即时工具 - 视频工具,https://www.67tool.com/category/5f56fb0664935e78271fd5a2
M、UNSCREEN:https://www.unscreen.com/,主要针对影片进行去背,100% 自动且免费,支持 MP4、WebM、OGG、MOV 和 GIF 格式,可让背景变成透明或加入其他图片、影片、单一颜色作为新背景
5、AI相关概念
(1)大模型(deepseek,大模型是什么东西)
附、大模型是指参数量可达数千亿的-基于人工神经网络的-机器深度学习模型
A、定义,大模型是指参数量可达数千亿的-深度学习模型,通常基于Transformer架构,广泛应用于自然语言处理(NLP)、计算机视觉(CV)等领域
B、参数量,大模型的参数量通常在数十亿到数千亿之间,例如GPT-3有1750亿参数
C、架构,主要基于Transformer,依赖自注意力机制处理长距离依赖关系
D、应用领域
a、自然语言处理:如文本生成、翻译、问答等
b、计算机视觉:如图像分类、目标检测等
c、多模态任务:如结合文本和图像处理
E、训练数据,需要海量数据,通常来自互联网,如网页、书籍等
F、计算资源,训练和推理需要高性能计算设备,如GPU、TPU等
G、代表性模型,
a、GPT系列:如GPT-3,用于文本生成
b、BERT:用于文本分类、问答等
c、T5:适用于多种NLP任务
d、Vision Transformers (ViT):用于图像分类
H、挑战
a、计算成本:训练和推理资源消耗大
b、数据需求:需要大量高质量数据
c、可解释性:模型复杂,难以解释其决策过程
I、未来方向
a、模型压缩:减少参数量和计算需求
b、高效训练:提高训练效率
c、多模态融合:处理多种类型数据的融合任务
J、总结来说,大模型通过大量参数和数据,基于人工神经网络的机器学习模型
(2)深度学习模型(deepseek,深度学习模型又是什么意思)
A、定义,深度学习模型是一类基于人工神经网络的机器学习模型,能够从大量数据中自动学习特征并完成复杂任务
B、基本概念
a、人工神经网络:模仿生物神经网络,由多层神经元组成
b、深度学习:使用多层神经网络进行学习,能够自动提取数据中的多层次特征
C、主要组成部分
a、输入层:接收原始数据
b、隐藏层:进行特征提取和转换,层数越多,模型越深
c、输出层:生成最终结果,如分类标签或回归值
D、常见类型
a、前馈神经网络(FNN):信息单向流动,适用于简单任务
b、卷积神经网络(CNN):用于图像处理,通过卷积核提取特征
c、循环神经网络(RNN):处理序列数据,如时间序列、文本
d、Transformer:基于自注意力机制,适用于NLP任务
E、训练过程
a、前向传播:输入数据通过各层生成输出
b、损失计算:比较输出与真实标签,计算误差
c、反向传播:根据误差调整模型参数
d、优化算法:如梯度下降,用于更新参数
F、应用领域
a、计算机视觉:图像分类、目标检测等
b、自然语言处理:文本生成、翻译等
c、语音识别:语音转文本
d、推荐系统:个性化推荐
G、优势
a、自动特征提取:无需手动设计特征
b、高精度:在大数据上表现优异
c、广泛应用:适用于多种任务
H、挑战
a、数据需求:需要大量标注数据
b、计算资源:训练和推理需要高性能硬件
c、可解释性:模型复杂,难以解释决策过程
I、未来方向
a、模型压缩:减少参数量和计算需求
b、自监督学习:减少对标注数据的依赖
c、多模态学习:处理多种类型数据的融合任务
J、总结来说,深度学习模型通过多层神经网络自动学习数据特征,广泛应用于多个领域,但也面临数据需求大、计算资源消耗高等挑战
十、web前端初级、中级、高级对应什么技能水平
1、初级前端开发(1-2年经验)
(1)核心定位:能独立完成基础页面开发,依赖指导解决问题
(2)技能水平
A、技术基础
a、熟练掌握 HTML5、CSS3(包括 Flex/Grid 布局、响应式设计)、原生 JavaScript(ES6+ 基础语法、DOM/BOM 操作)
b、能使用主流框架(如 React/Vue)完成简单组件开发,理解基本概念(如 props、state、生命周期)
c、会使用打包工具(如 Webpack)的基础配置,能处理简单的资源打包
B、业务能力
a、能根据设计稿(Figma/PSD)还原页面,保证基础兼容性(如 PC 端主流浏览器、移动端常见机型)
b、能完成简单交互逻辑(如表单验证、弹窗切换),依赖文档或同事指导解决问题
C、工程能力
a、掌握Git基本操作(clone、commit、push、pull),能参与团队代码管理
b、了解前端工程化基础(如模块化、代码规范),但缺乏深入实践
D、典型产出
a、静态页面、简单交互组件(如按钮、表单)、配合后端完成基础数据渲染
2、中级前端开发(2-5年经验)
(1)核心定位:能独立负责业务模块开发,解决复杂交互和性能问题,推动团队效率提升
(2)技能水平
A、技术深度
a、深入理解JS核心原理(原型链、闭包、异步编程、事件循环),能手写常见工具函数(如防抖节流、深拷贝)
b、精通至少一个主流框架(React/Vue/Angular)的高级特性(如React-Hooks性能优化、Vue自定义指令/插件、状态管理Redux/Vuex)
c、掌握工程化工具进阶配置(Webpack 优化、Vite 原理、ESLint/Prettier 定制规则),能搭建基础项目脚手架
d、熟悉前端性能优化手段(如图片懒加载、代码分割、缓存策略、首屏加载优化),能通过 Lighthouse 等工具定位并解决性能问题
B、业务能力
a、能独立负责中型业务模块(如用户中心、商品列表页),理解业务逻辑并转化为技术方案
b、处理复杂交互场景(如拖拽、动画、多端适配),解决跨浏览器兼容性问题(如IE特殊处理、移动端手势冲突)
c、能与后端协作设计接口,理解 RESTful/GraphQL 规范,独立调试接口问题(使用 Axios、Postman)
C、工程能力
a、掌握 Git 进阶操作(分支管理、冲突解决、Cherry-pick),参与制定团队代码规范
b、了解自动化测试(Jest、Cypress),能为核心组件编写单元测试
c、能排查线上问题(通过 Console、SourceMap、监控工具如 Sentry 定位 bug)
D、典型产出
a、完整业务模块、可复用组件库、基础性能优化方案、项目脚手架
3、高级前端开发(5年+经验)
(1)核心定位:负责技术架构设计、攻克技术难点、驱动团队技术成长,参与业务决策
(2)技能水平
A、技术广度与深度
a、深入理解前端底层原理(浏览器渲染机制、JS引擎工作原理、HTTP/HTTPS协议、WebSocket),能从根源解决复杂问题(如内存泄漏、跨域方案设计)
b、精通多种框架/技术栈,能根据业务场景选择合适技术(如 SSR 与 CSR 选型、微前端架构设计)
c、掌握前端架构设计(如微前端、模块化设计、状态管理方案、组件库设计原则),能搭建高可用、可扩展的前端体系
d、了解后端/全栈技术(Node.js、数据库基础、Docker),能独立开发 BFF(Backend For Frontend)层,协调前后端资源
B、业务与工程能力
a、能主导大型项目(如电商平台、管理系统)的技术方案设计,评估技术风险并制定应对策略
b、推动前端工程化体系落地(如 CI/CD 流程、自动化测试覆盖率提升、性能监控体系搭建),提升团队研发效率
c、参与业务需求评审,从技术角度优化业务流程,平衡用户体验与开发成本
C、团队与影响力
a、指导初级/中级开发,参与代码评审,输出技术文档(如架构设计稿、最佳实践)
b、跟踪行业前沿技术(如 WebAssembly、Server Components、AI 与前端结合),并在团队内落地实践
c、能跨团队协作(与产品、设计、后端、运维沟通),推动跨部门技术方案落地
D、典型产出
a、前端架构设计方案、微前端/组件库体系、全链路性能优化方案、技术团队培训体系
4、总结
(1)初级:“会用”—— 掌握基础工具和语法,完成指定任务。
(2)中级:“能用好”—— 深入技术细节,独立解决复杂问题,支撑业务落地。
(3)高级:“会设计”—— 从全局视角规划技术方向,驱动效率与质量提升,影响团队与业务