2019-06-21 | 功能需求 | UNLOCK | 更新时间:2023-4-13 14:24

功能与样式的参考和奇思妙想

样式的处理参考

内容进行强制换行

浏览器需要容器的一个宽度用于内容的换行操作,但是当浏览器判断某些内容为一个单词的时候会拒绝换行

word-break: break-word; /*对单词进行强制拆分*/
white-space:pre-line;   /*保证中文的换行,在碰到边后换行*/

禁止复制页面文字

当你需要长按操作的时候,或者单纯的不想出现复制文本的时候,你可以选择禁止用户复制页面上的文字

效果预览

注意,这可以复制

抱歉,这不能复制

<body onselectstart="return false"></body>
*{
   -o-user-select: none;
   -ms-user-select: none;
   -moz-user-select: none;
   -webkit-user-select: none;
   user-select: none;
}

对内容进行缩放处理

很多时候,当页面字体太大(最小字体限制12px),会导致页面难看,需要使用缩放对内容进行缩放

.div{
    transform: scale(0.5);
    transform-origin: 0 0;
    width: 200%;
}
// 获取元素高度,将margin-bottom 设为原先高度的一半的负值
$('.set-li').map(function(e,a){
  var height=$(a).height()/2
  $(a).css('margin-bottom',-height)
})

点击获取焦点和tab获取焦点

默认只有表单类元素可以编辑,但是我们也可以让 p标签获取焦点和编辑,和快捷键tab获取光标

效果预览

我可以被编辑

按下tab键,光标聚焦于我,索引是tab按下依次的顺序

<p contenteditable="true">我可以被编辑</p>

<p tabindex="0">按下tab键,光标聚焦于我,索引是tab按下依次的顺序</p>

单行多行文本的省略

在很多时候,我们需要实现单行文本省略和多行文本省略,但多平台的兼容却一直存在

/* 单行文本省略 兼容性:IE7+ */
.textOver{
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 多行文本省略 仅兼容 webkit 内核浏览器 */
.text{
  word-wrap: break-word;
  white-space: pre-line;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

但是对于多平台兼容,还是有办法的,可能并不是特别完美 兼容性:IE8+

<div class="wrap"> <p>asdaasdadas</p> </div>
.wrap {height: 40px;line-height: 20px;overflow: hidden;}
.wrap .text {float: right;margin-left:-20px;width:100%;word-break:break-all;}
.wrap:before{float: left;width:20px;content: '';height: 40px;}
.wrap:after {
  float: right;
  content: "...";
  height: 20px;
  line-height: 20px;
  width: 3em;/* 为三个省略号的宽度 */
  margin-left: -3em;/* 使盒子不占位置 */
  position: relative;/* 移动省略号位置 */
  left: 100%;
  top: -20px;
  padding-left: 20px;
  background-image:url('透明渐变图片'); /*用于覆盖尾部文本的透明渐变图片*/
  background-repeat: repeat-y;
  background-size: 100%;
}

毛玻璃的样式效果

效果预览

注意,这不是演习,重复,这不是演习!

div {
  backdrop-filter: saturate(50%) blur(8px);
  background: rgba(255,255,255,.7);
}

字体颜色渐变效果

效果预览

公告,注意这个! 通缉令

div{
    background-image: linear-gradient(90deg,#7209d4,#2832d4 33%,#00a5b2);
    -webkit-background-clip: text;
    color: transparent;
}

动画的相关参考

旋转卡片

@keyframes flip {
  0% {
    transform: perspective(2000px) rotateY(0)
  }
  100% {
    transform: perspective(2000px) rotateY(90deg)
  }
}
@keyframes flip_out {
  0% {
    transform: perspective(2000px) rotateY(-90deg)
  }
  100% {
    transform: perspective(2000px) rotateY(0)
  }
}

.switching {
  -webkit-transform: perspective(2000px) rotateY(-90deg);
  -webkit-animation: flip .4s linear,flip_out .4s .41s linear;
  transform: perspective(2000px) rotateY(-90deg);
  animation: flip .4s linear,flip_out .4s .41s linear
}

// 点击后,给当前卡片添加 class "switching" ,0.4s 后将将新卡片的背面显示,旧的隐藏。0.8s 后 将"switching" 去除。

暂停效果

@keyframes play-state {
  0% {margin-left: 0;}
  100% {margin-left: 200px;}
}
.play-state {
  width: 100px;height: 100px;margin: 40px;text-align: center;
  line-height: 94px;border: 3px solid #e1efde;border-radius: 50%;
  animation: play-state 3s linear infinite;cursor: pointer;
}

.play-state:hover {
  animation-play-state: paused; /*关键*/
}

图片的相关处理

图片的上传预览

<input id="upload" type="file" />
<img id="preview" src="" alt="预览"/>

<script>
const upload = document.querySelector("#upload");
const preview = document.querySelector("#preview");
upload.onchange = function() {
  const file = upload.files[0]; //File对象
  const src = URL.createObjectURL(file); 
  preview.src = src;
};
</script>

大图从模糊到清晰

但图片过大的时候,网速慢的时候,图片会呈现断片式加载一截一截的显示,显的比较难看。可以先显示压缩过的模糊的预览图片,在通过new Image() 的方式加载图片,当图片加载好后在替换页面上的图片

<img src="19.img"/ data-url="http://xianbin.cf/img/banner/191105.jpg" class="vague">
.vague{filter:blur(2px);transition:all 0.7s;width:100%;}
function set(a){
    var url=$(a).attr('data-url')
    var img=new Image();
    img.src=url;
    img.onload=function(){
        $(a).attr('src',url)
        $(a).removeClass('vague')
    }
}
set('.vague')

图片动态加载loading

设置图片加载中的时候以loading 替代

function load(view,src){
    setTimeout(function(){
        let img=new Image()
        img.src=src
        img.onload=function(){
            let box=document.getElementById(view)
            box.src=src
        }
    },0)
}
load('2018A','https://clubimg..jpg')

滚动条相关参考

滚动条在鼠标悬浮状态才会显示

滚动条只有鼠标悬浮在上的时候出现,且元素不出现缩放,重点在于子元素宽度需要比父级小,且使用 margin来处理距离

效果预览

公告,注意这个! 滚动条

.div1{/* 父级 */ width:100%; height:50px; overflow:hidden; }
.div1:hover{ overflow-y:auto }
.div2{ /* 子级 */ width:100%; margin-left:20px; height:2000px; }

通过overflow:hidden隐藏滚动条

隐藏竖直滚动条,但页面依然可以滚动 兼容性:兼容 IE9及以上

/* PC端 隐藏滚轮*/
html,body {height: 100%;}
html {overflow: hidden;}
body {overflow: auto;width: calc(100vw + 20px);}

/* PE端 隐藏滚轮*/
::-webkit-scrollbar { display: none; }

蒙版弹窗滚动条不滚动

通过点击出现弹窗后,通过js设置外部滚动条为隐藏

// 点击显示弹窗,设置外部 `css`为 `hidden`
$('.buttom').click(function(){
  $('.shadow_box').show()
  $(document.body).css({"overflow-x":"hidden","overflow-y":"hidden"});
})

// 点击蒙版,设置外部 `css` 为 `auto`
$('.shadow').click(function(){
    $('.shadow_box').hide()
  $(document.body).css({"overflow-x":"auto","overflow-y":"auto"});
})

通过禁止滚动条响应事件,在关闭弹窗后再响应

function handleStopWheel(e) {
  e.preventDefault();
}
$('.buttom').click(()=>{
  window.addEventListener("wheel",handleStopWheel,{passive: false})
})
$('#site-toLogin').click(() => {
  window.removeEventListener("wheel",handleStopWheel)
});

设备分类的参考

关于手机和 PC 的判断

//如果是手机端则去百度,不是则去新闻
window.location.href = /Android|webOS|iPhone|ipod|ipad|BlackBerry/i.test(navigator.userAgent) ? "https://www.baidu.com/" :  "http://news.baidu.com/";

关于屏幕大小属性参考

# 浏览器窗口大小(包括工具栏)
window.outerHeight
window.outerWidth

# 窗口文档显示区(不包含滚动条)
window.innerWidth
window.innerHeight

# 元素级内部大小(不包含滚动条)
clientWidth
clientHeight

关于手机横竖屏的判断

通过 window.orientation 属性进行判断, PC 端为 undefined,90或-90为横屏幕,剩下则是竖屏

功能的相关参考

禁止用户使用页面后退

不支持IE
//防止页面后退 history.pushState(null, null, document.URL); window.addEventListener('popstate', function () { history.pushState(null, null, document.URL); });

js控制点击关闭当前页面

浏览器出于安全策略的考虑,只允许Javascript 关闭由Javascript 打开的页面,所以当我们需要关闭当前页面的时候,你可以这样

<a onClick="window.opener=null;window.open('','_self');window.close();">关闭</a>

window.opener是一个可读可写的属性,返回对创建该窗口的 Window 对象的引用
window.opener.lose()可以关闭父级窗口
思路,先设置opener为空,当打开一个空的新窗口,关闭父级窗口,因为打开的是空,所有新的子页面不会出现

表单自动填入功能

在部分浏览器中,会默认开启自动完成功能。注意 属性 name 和 id 会影响改功能;

<input type="text"/> 
// 当不存在name 或 id 的时候,自动完成不会开启,只有当其中一个出现的时候才会启动。

<form>
<input type="email" name="email" autocomplete="off" />
// 也可以通过 autocomplate 进行控制。
// 自动填写功能默认为黄色,下面的样式会重置它
input:-webkit-autofill,
input:-webkit-autofill:hover, 
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
  border: 1px solid green;
  -webkit-text-fill-color: green;
  -webkit-box-shadow: 0 0 0px 1000px #000 inset;
  transition: background-color 5000s ease-in-out 0s;
}

html动态加载 js文件

function loadScript(url,callback){
    var script=document.createElement("script");
    script.type="text/javascript";
    if(script.readyState){
        script.onreadystatechange=function(){
            if(script.readyState=="load"||script.readyState=="complete"){
                script.onreadystatechange=null;
                callback();
            };
        }
    }else{
        script.onload=function(){
            callback();
        }
    }
    script.src=url;
}

loadScript("jquery.js",function(){
    console.log('加载完成')
})

prototype 原型改造

// 通过全局属性进行定义

var a=document.getElementById("en")
a.addClass=function(name){
    var a=this.getAttribute("class")
    if(a){
        a=a+" "+name;
        this.setAttribute("class",a)
    }else{
        console.log(this)
    }
}
a.addClass("name")

// 通过prototype进行定义

String.prototype.lengths=function(name){
    console.log(this.length)
}
"lenght".lengths()

页面打印及4A大小的设置

let dom="<!DOCTYPE html>...</html>"
function doPrint3(dom){

    //判断iframe是否存在,不存在则创建iframe
    var iframe=document.getElementById("print-iframe");
    if(!iframe){  
        var el = document.getElementById("printcontent");
        iframe = document.createElement('IFRAME');
        iframe.setAttribute("id", "print-iframe");

        // 需要预览就添加大小。A4的内容大小。不需要就隐藏
        iframe.setAttribute('style', 'width:794px;height:1090px;'); 
        document.body.appendChild(iframe);

        // 如果传入dom,则打印dom
        iframe.contentWindow.document.documentElement.innerHTML=dom
        var doc = iframe.contentWindow.document;

        //这里可以自定义打印样式
        doc.write("<LINK rel="stylesheet" type="text/css" href="css/print.css">");

        //如果不传dom 需要单独打印部分内容
        //doc.write('<div>' + el.innerHTML + '</div>');
        //doc.close();
        //iframe.contentWindow.focus();            
    }
    iframe.contentWindow.print();
    if (navigator.userAgent.indexOf("MSIE") > 0){ // IE浏览器
      document.body.removeChild(iframe);
    }
}
// 打印
doPrint3(dom){

    //判断iframe是否存在,不存在则创建iframe
    var iframe=document.getElementById("print-iframe");
    if(!iframe){
      iframe = document.createElement('IFRAME');
      iframe.setAttribute("id", "print-iframe");

      // 需要预览就添加大小。A4的内容大小。不需要就隐藏
      iframe.setAttribute('style', 'width:794px;height:1090px;'); 
      document.body.appendChild(iframe);
      iframe.contentWindow.document.documentElement.innerHTML=dom  
    }
    setTimeout(function(){
      iframe.contentWindow.print();
      var doc = iframe.contentWindow.document;
      doc.close();
      iframe.contentWindow.focus(); 
      document.body.removeChild(iframe);
    },10)
},

手机和电脑长按的混合处理

let isAndroid=/Android|webOS|iPhone|ipod|ipad|BlackBerry/i.test(navigator.userAgent)
let set1,set2,isLong=0,start=false
let dom=document.getElementById('aaa')
  dom.removeEventListener('touchstart',a)
  dom.removeEventListener('touchmove',b)
  dom.removeEventListener('touchend',c)
  dom.removeEventListener('mousedown',a)
  dom.removeEventListener('mousemove',b)
  dom.removeEventListener('mouseup',c)
if(isAndroid){
  dom.addEventListener('touchstart',a)
  dom.addEventListener('touchmove',b)
  dom.addEventListener('touchend',c) 
}else{
  dom.addEventListener('mousedown',a)
  dom.addEventListener('mousemove',b)
  dom.addEventListener('mouseup',c)
}
function a(){
  //多次触发
  start=true
  set1=setTimeout(function(){
    console.log('这次是长按')
    isLong=1
  },800)
}
function b(){
  //移动
  if(start){
    isLong=2
    clearTimeout(set1)
  }
}
function c(){
  //离开
  if(isLong==0){
    clearTimeout(set1)
    console.log('这次是单击')
  }
  isLong=0
  start=false
}

数据表格和固定头部的样式

React 代码
import * as React from 'react' var $ = require('jquery') export class LTable extends React.Component<any,any>{ constructor(props:any) { super(props); this.resize=this.resize.bind(this) this.state = { id:this.props.id||'l_'+new Date().getTime(), clas:this.props.className||'', height:this.props.height||'300px', } } static contextTypes={      router: function(){ return null }  } mounted = false; componentWillMount(){ this.mounted = true; } componentDidMount() { window.addEventListener('resize', this.resize) this.resize() } componentDidUpdate(){ this.resize() } componentWillUnmount(){ window.removeEventListener('resize',this.resize); this.mounted = false; } resize(){ let id=this.state.id let tbody=this.props.tbody if(tbody.length>0){ let ltable=document.getElementById(id)!.getElementsByTagName('table') let thead0=ltable[0].getElementsByTagName('thead')[0] let thead1=ltable[1].getElementsByTagName('thead')[0] let ltbody=document.getElementById(id)!.getElementsByClassName('l_table_body')[0] let th0=thead0.getElementsByTagName('th') let th1=thead1.getElementsByTagName('th') thead0.style.minWidth=thead1.offsetWidth+'px' ltable[0].style.width=ltable[1].offsetWidth+'px' for(let i=0;i<th1.length;i++){ th0[i].style.width=th1[i].offsetWidth+'px' } $(ltbody).scroll(function(e:any){ let div=document.getElementById(id)!.getElementsByClassName('l_table_head')[0] div.scrollLeft=e.target.scrollLeft }) } } render(){ let thead=this.props.thead,tbody=this.props.tbody return ( <div id={this.state.id} className={"l_table "+this.state.clas}> {this.props.title? <h3 className="l_table_title">{this.props.title}</h3>:'' } <div className="l_table_head l_scroll_hide"> <table> <thead> <tr> {thead.map((e:any,i:any)=> <th key={i}>{e.title}</th> )} </tr> </thead> </table> </div> <div className="l_table_body" style={{height:this.state.height}}> {tbody.length>0? <table> <thead> <tr> {thead.map((e:any,i:any)=> <th key={i}>{e.title}</th> )} </tr> </thead> <tbody> {tbody.map((tr:any,a:any)=> <tr key={a}> {thead.map((td:any,b:any)=>{ if(td.render){ return <td key={b}>{td.render(tr)}</td> }else{ return <td key={b}>{td.title}</td> } })} </tr> )} </tbody> </table>: <div className="l_nodata"> <span>No Date</span> </div> } </div> </div> ) } }
.l_table{border: 1px solid #c3c3c3;background: #fff;margin-bottom:20px;}
.l_table table{width:100%}
.l_table th,.l_table td{word-break:keep-all;overflow:hidden;white-space:nowrap;-o-text-overflow:ellipsis;text-overflow:ellipsis;}
.l_table table,.l_table th,.l_table td{border:0;border-spacing:0;}
.l_table td{padding: 6px 10px;max-width: 150px;}
.l_table_title{text-align:center;font-weight:700;margin:0;padding:16px 0;position:relative;top:1px;font-size:14px;color:rgba(0,0,0,0.65);padding-right:17px;}
.l_scroll_hide::-webkit-scrollbar{background:transparent}
.l_scroll_hide{scrollbar-color: transparent transparent;}
.l_table th{background:#fafafa;position:relative;z-index:1;box-sizing:border-box;padding:0px 10px;text-align:left}
.l_table .l_table_head{border-top:1px solid #e8e8e8;}
.l_table .l_table_body td,.l_table_head th,.l_table .l_table_body th{border-right: 1px solid #e8e8e8;border-bottom: 1px solid #e8e8e8}
.l_table .l_table_head{overflow-x:hidden;overflow-y:scroll;}
.l_table .l_table_body{overflow-y:scroll;margin-top: -35px;}
.l_table_head,.l_table_body thead{line-height:34px}
.l_table_body thead{visibility:hidden;}
.l_nodata{position:relative;height:100%}
.l_nodata span{position:absolute;top:calc(50% + 10px);left:50%;transform:translate(-25%);}

自动化填充的样式修改

无论浏览器的元素默认样式设置的再怎么绚丽,我们都希望有足够的自由(修改所有的一切);更何况自动填写那一块黄色的背景和我们设置的风格完全无法融合;

/* 这是谷歌浏览器的样式更改 */
input:-webkit-autofill,
input:-webkit-autofill:hover, 
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
  border: 1px solid green;
  -webkit-text-fill-color: green;
  -webkit-box-shadow: 0 0 0px 1000px #000 inset;
  transition: background-color 5000s ease-in-out 0s;
}

/* 通过盒子内阴影将背景颜色遮盖;将背景颜色的过渡时间设长 */

浏览器开发调试

CONSOLE 各种提示信息的集合

// 输出信息
console.log('文字信息');
console.info('提示信息');
console.warn('警告信息');
console.error('错误信息');
throw new Error('这是一个错误提示');
throw { name: '参数错误', message: 'data[0]不存在'}

//当第一参数为false时,输出警告信息第二参数
console.assert(false,'看不见')

//输出样式 (IE 不支持)
console.log("%c我要变色了","color:blue;font-size:20px")

/*分组输出:可折叠*/
console.group('第一个组');
    console.log("1-1");
    console.log("1-2");
    console.log("1-3");
console.groupEnd();

/*分组输出:可嵌套*/
console.group('第一个组');
    console.group("1-1");
        console.group("1-1-1");
            console.log('内容');
        console.groupEnd();
    console.groupEnd();
    console.group("1-2");
        console.log('内容');
        console.log('内容');
        console.log('内容');
    console.groupEnd();
console.groupEnd();

// 表格输出
var Obj = {
    Obj1: {
        a: "aaa",
        b: "bbb",
        c: "ccc"
    },
    Obj2: {
        a: "aaa",
        b: "bbb",
        c: "ccc"
    }
}
var Arr = [
    ["aa","bb","cc"],
    ["dd","ee","ff"],
    ["gg","hh","ii"],
]
console.table(Obj);
console.table(Arr);

// 追踪堆栈调用
console.trace('调用')

// 计时
console.time("Chrome中循环1000次的时间");
for(var i = 0; i < 1000; i++){ }
console.timeEnd("Chrome中循环1000次的时间");

通信数据的加密

一般现在的项目,为了通信安全,会考虑信息加密的方案,通过使用AES对传输的内容进行加密,再通过RSA对AES的秘钥进行加密。最后将AES密文和RSA密文传输到后端。

AES对称加密

像AES对称加密,是通过一个秘钥进行的加密和解密的,所以这个秘钥的安全性极为重要。

  • 字符串文本的加密和解密
import CryptoJS from "crypto-js"

// AES加密文本
const AesString=(SymmetricKey,ivString,text)=>{、

  // 转换为 WordArray 类型
  const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
  const iv = CryptoJS.enc.Utf8.parse(ivString);

  // 加密
  let encrypted = CryptoJS.AES.encrypt(text, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })

  // 密文(Base64 编码)
  let ciphertext = encrypted.toString();
  return ciphertext
}

//AES解密文本
const AesDcString=(SymmetricKey,ivString,text)=>{

  // 转换为 WordArray 类型
  const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
  const iv = CryptoJS.enc.Utf8.parse(ivString);

  // 解密
  let encrypted = CryptoJS.AES.decrypt(text, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })

  // 明文(UTF-8 编码)
  let message = decrypted.toString(CryptoJS.enc.Utf8);
  return message
}
  • 读取文件的内容进行加密和解密
import CryptoJS from "crypto-js"

//AES加密文件
const AesFile=(SymmetricKey,ivString,file)=>{

  // 转换为 WordArray 类型
  const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
  const iv = CryptoJS.enc.Utf8.parse(ivString);

  // 创建 FileReader 对象
  let reader = new FileReader();
  // 设置读取方式为 ArrayBuffer
  reader.readAsArrayBuffer(file);
  // 监听 loadend 事件
  reader.onloadend = function () {
    // 获取读取结果(ArrayBuffer)
    let buffer = reader.result;
    // 将 ArrayBuffer 转换为 WordArray 
    let wordArray = CryptoJS.lib.WordArray.create(buffer);

    // 加密
    let encrypted = CryptoJS.AES.encrypt(wordArray, key, {
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7,
    });
    // 密文(Base64 编码)
    let ciphertext = encrypted.toString();
    return ciphertext
  };
}

//AES解密文件
const AesDcFile=(SymmetricKey,ivString,fileText,filename)=>{

  // 转换为 WordArray 类型
  const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
  const iv = CryptoJS.enc.Utf8.parse(ivString);

  // 解密
  var decrypted = CryptoJS.AES.decrypt(fileText, key,{
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })
  // 将解密后的结果转换为ArrayBuffer格式
  var buffer = new ArrayBuffer(decrypted.sigBytes);
  var view = new Uint8Array(buffer);
  for (var i = 0; i < decrypted.sigBytes; i++) {
      view[i] = decrypted.words[i >>> 2] >>> (24 - (i % 4) * 8) & 0xff;
  }
  // 将ArrayBuffer转换为Blob对象,并指定文件类型(根据实际情况修改)
  var blob = new Blob([buffer]);
  // 使用FileSaver.js库来保存Blob对象为文件,并指定文件名(根据实际情况修改)
  saveAs(blob,filename);
}
  • 将多个文件添加为zip压缩包的加密和解密
import { saveAs } from "file-saver";
import CryptoJS from "crypto-js"
import JSZip from 'jszip'


//AES加密文件(将多个文件添加为zip压缩包)
const AesFileZip=(SymmetricKey,ivString,fileList,save=false,name='encryption.txt')=>{

  // 转换为 WordArray 类型
  const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
  const iv = CryptoJS.enc.Utf8.parse(ivString);

  //添加文件进zip压缩包
  const zip = new JSZip()
  for(let i in fileList){
    zip.file(fileList[i].name, fileList[i].raw)
  }

  //对zip压缩包进行加密
  zip.generateAsync({type:"uint8array"}).then(function(zipData) {
    // 使用AES CBC Pkcs7模式进行加密
    const encryptedData = CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(zipData), key, {
      iv:iv,
      padding: CryptoJS.pad.Pkcs7,
      mode: CryptoJS.mode.CBC
    });
    // 将加密后的数据转换为Base64字符串或其他格式
    const encryptedBase64 = encryptedData.toString();
    if(save){ //是否将加密后的密文导出为文件
      let str = new Blob([encryptedBase64], {type: 'text/plain;charset=utf-8'});
      saveAs(str,encryption.txt);
    }
    return encryptedBase64
  });
}

//AES解密String到文件(解密压缩包的密文并导出压缩包文件)
const AesDcStrToZip=(SymmetricKey,ivString,text,save=true,name='deciphering.zip')=>{

  // 转换为 WordArray 类型
  const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
  const iv = CryptoJS.enc.Utf8.parse(ivString);

  //解密
  var decrypted = CryptoJS.AES.decrypt(text, key,{
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })

  //是否导出
  if(save){
    // 将解密后的结果转换为ArrayBuffer格式
    var buffer = new ArrayBuffer(decrypted.sigBytes);
    var view = new Uint8Array(buffer);
    for (var i = 0; i < decrypted.sigBytes; i++) {
        view[i] = decrypted.words[i >>> 2] >>> (24 - (i % 4) * 8) & 0xff;
    }
    // 将ArrayBuffer转换为Blob对象,并指定文件类型(根据实际情况修改)
    var blob = new Blob([buffer], {type: "text/plain"});
    // 使用FileSaver.js库来保存Blob对象为文件,并指定文件名(根据实际情况修改)
    saveAs(blob,name);
  }
  return decrypted
}

//AES解密文本文件到zip文件(将之前加密后导出的密文文件解密导出内容)
const AesDcStrFileToZip=(SymmetricKey,ivString,file,save=true,name='deciphering.zip')=>{

  // 转换为 WordArray 类型
  const key = CryptoJS.enc.Utf8.parse(SymmetricKey);
  const iv = CryptoJS.enc.Utf8.parse(ivString);

  //创建一个FileReader对象
  let reader = new FileReader();
  //设置编码方式为UTF-8
  reader.readAsText(file, "UTF-8");
  //监听load事件
  reader.onload = function() {
    //获取读取结果并解密
    let ciphertext = this.result;
    var decrypted = CryptoJS.AES.decrypt(ciphertext, key,{
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    })
    if(save){
      // 将解密后的结果转换为ArrayBuffer格式
      var buffer = new ArrayBuffer(decrypted.sigBytes);
      var view = new Uint8Array(buffer);
      for (var i = 0; i < decrypted.sigBytes; i++) {
          view[i] = decrypted.words[i >>> 2] >>> (24 - (i % 4) * 8) & 0xff;
      }
      // 将ArrayBuffer转换为Blob对象,并指定文件类型(根据实际情况修改)
      var blob = new Blob([buffer], {type: "text/plain"});
      // 使用FileSaver.js库来保存Blob对象为文件,并指定文件名(根据实际情况修改)
      saveAs(blob,name);
    }
    return decrypted
  };
}

RSA非对称加密

非对称加密

import forge from 'node-forge';

//RSA加密
const encrypt=(key,text)=>{ //参数:公钥,原文
  var privateKey = forge.pki.publicKeyFromPem(key); //设置公钥
  // 加密
  var encrypted = privateKey.encrypt(text, 'RSA-OAEP', {
    md: forge.md.sha256.create(),
    mgf1: {
      md: forge.md.sha1.create()
    }
  })
  return btoa(encrypted) //进行btoa是因为后台需要进行一次base64转码
}

//RSA解密
const decrypt=(key,text)=>{ //参数:私钥,密文
  var privateKey = forge.pki.privateKeyFromPem(key); //设置私钥
  //解密
  var encrypted = privateKey.decrypt(atob(text), 'RSA-OAEP', {
    md: forge.md.sha256.create(),
    mgf1: {
      md: forge.md.sha1.create()
    }
  })
  return encrypted
}
const decryptFile=(file,text)=>{ //.key私钥,密文
  return new Promise(function(resolve, reject) {
    let reader = new FileReader();
    reader.readAsText(file, "UTF-8");
    reader.onload = function() {
      let ciphertext = this.result;
      console.log(ciphertext)
      let privateKey = forge.pki.privateKeyFromPem(ciphertext);
      try{
        let encrypted = privateKey.decrypt(atob(text), 'RSA-OAEP', {
          md: forge.md.sha256.create(),
          mgf1: {
            md: forge.md.sha1.create()
          }
        });
        resolve(encrypted);
      }catch(err){
        reject(err)
      }
    }
  })
}

数据的处理参考

数组去除符合条件的子元素

如果直接使用 for 循环去除,那么会出现错误,原因是函数在不断的去除,而索引没变

var arr = [0,1,2,3,4,5,1,2,3]
for (let i=0;i<arr.length;i++) {
    if(arr[i] == 2){
        arr.splice(i--,1)
    }
}

JS 浮点数精确度问题

当js进行浮点型计算的时候,会导致计算出错。例:0.6910=6.8999999999999995,因为js作为解释性语言,同其他语言一样在计算小数的时候将小数转二进制不好转换
解决办法:将小数转换成整数,计算完成后转换成小数。0.69
100*10/100

//处理数字后两位(四舍五入)
5.324.toFixed(2)==5.32

数字转成每隔3位加逗号

var num_s = "1232134456.546 ";
var num=parseFloat(num_s).toLocaleString();

本地时间规则化

new Date.toLocaleTimeString()
// 下午 2:30:12

获取当前时间及前半个小时

// 设置年月日 时分
var a= new Date();
var y=a.getFullYear();
var m=a.getMonth()+1;
var d=a.getDate();
var h=a.getHours();
var f=a.getMinutes();
h<10?h="0"+h:h=h;
f<10?f="0"+f:f=f;
$scope.end_time=y+"-"+m+"-"+d+" "+h+":"+f

//获取前半个小时的时间挫
var b= new Date(a.getTime()-1000*60*30);
y=b.getFullYear();
m=b.getMonth()+1;
d=b.getDate();
h=b.getHours();
f=b.getMinutes();
$scope.start_time=y+"-"+m+"-"+d+" "+h+":"+f

请求的处理参考

同请求关闭重复请求