项目常用函数封装总结

41 篇文章 0 订阅
22 篇文章 0 订阅

文章目录

元素滚动到可视化区域

  document.getElementById('id')?.scrollIntoView({
    behavior: 'smooth',
    // 定义动画过渡效果, "auto"或 "smooth" 之一。默认为 "auto"
    // 指定滚动行为是否应该平滑地进行。'smooth' 表示平滑滚动,而 'auto' 表示默认行为(通常是瞬间跳转)。
    block: 'center',
    // 定义垂直方向的对齐, "start", "center", "end", 或 "nearest"之一。默认为 "start"
    // 指定垂直方向上的对齐方式。'start' 表示对齐到顶部,'center' 表示对齐到中间,'end' 表示对齐到底部,'nearest' 表示对齐到最接近的边缘。
    inline: 'nearest',
    // 定义水平方向的对齐, "start", "center", "end", 或 "nearest"之一。默认为 "nearest"
    // 指定水平方向上的对齐方式。与 block 属性类似,但用于水平方向。
  });

检测服务器上是否存在某个文件

    fetch(
      'http://192.168.11.105:8102/outputs/fea4bd3f-9c46-440f-b529-8c83801ba03e/4.tracing/sample_clustermap.png',
    ).then((res) => {
      console.log(res.status);
    });

检测当前电脑是否存在某个文件

注意这里用fs的话,只能检测项目部署的那台电脑(即,项目部署到那台电脑,检测那台电脑)

    const fs = require('fs');
    let path = 'F:\\xi1a.ico';

    if (fs.existsSync(path)) {
      console.log('存在');
    } else {
      console.log('不存在');
    }

Vue3 项目中,纯前端如何实现跨标签通信:

下面介绍了第三个,其他的自行百度,很简单的

  • BroadCast Channel
  • Service Worker
  • LocalStorage + storage
  • open + postMessage

监听localstorage的变化

注意:这里只能监听同源不同窗口的localStorage变化或者iframe与父级的localStorage 变化
可以通过监听storage事件来监控localStorage的变化
请注意,storage事件只会在其他页面(相同域下的不同页面)修改localStorage时触发,如果是在当前页面进行修改,监听函数不会被触发,因为当前页面本身就是修改的一部分。

window.addEventListener('storage', function (e) {
  console.log('Key:', e.key);
  console.log('Old Value:', e.oldValue);
  console.log('New Value:', e.newValue);
  console.log('URL:', e.url);
  console.log('Storage area:', e.storageArea);
});

在这里插入图片描述

多数组取交集

  const intersection = (arr: Array<any>, ...arr2: Array<any>) =>
    [...new Set(arr)].filter((v) => arr2.every((b) => b.includes(v)));

  let result = intersection([1, 2, 3, 4], [2, 3, 4, 7, 8], [1, 3, 4, 9]);
  console.log(result); //[3,4]

判断两个数组是否有相同元素 返回相同元素(数组)

//判断两个数组是否有相同元素
export const ishasSameElement = (arr1: string[], arr2: string[]) => {
  // 使用Set数据结构来存储数组的唯一元素
  let set1 = new Set(arr1);
  let set2 = new Set(arr2);
  // 使用Intersection方法找出两个集合的交集,如果交集不为空,那么就存在共享的元素
  let commonElements = new Set([...set1].filter((x) => set2.has(x)));

  return Array.from(commonElements);
};

如果上面看不懂话的就用for循环遍历吧
在这里插入图片描述

判断hex颜色值是深色还是浅色

注意这里一定要是128,不要写0.5,仔细看看下面的公式,就不会相信0.5了, 1*0.5=0.5了,哈哈哈

export const hexIsDark = (hex: string) => {
  // 将Hex颜色转换为RGB颜色
  let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  let rgb = result
    ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16),
      }
    : null;

  let brightness: number = 0;
  if (rgb) brightness = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b;
  return brightness < 128;
};

随机生成深浅样色

const randomColor = () => {

  let deepColor = [];
  let lightColor = [];

  for (let i = 0; i < 100; i++) {
    let color = '#' + parseInt(Math.random() * 0xffffff).toString(16);
    if (hexIsDark(color)) {
      deepColor.push(color);
    } else {
      lightColor.push(color);
    }
  }
  console.log('deepColor', deepColor);
  console.log('lightColor', lightColor);

};

js判断是手机端还是移动端

推荐使用UA去判断

使用UA判断

UA(UserAgent)是指HTTP请求头中的一部分,用于标识客户端的一些信息,比如用户的设备类型、浏览器型号等等。因此,我们可以通过判断UA中的关键字来确定页面访问者的设备类型。下面是实现的代码:

      const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
      if (isMobile) {
        console.log('当前在手机端');
      } else {
        console.log('当前在PC端');
      }



	//判断是否在微信浏览器
    var ua = navigator.userAgent.toLowerCase();
    var isWeixin = ua.indexOf("micromessenger") != -1;
    if (isWeixin) { 
    // 微信浏览器
    
    }else{ 
      //普通浏览器
      if (isMobile) {
        console.log('当前在手机端');
      } else {
        console.log('当前在PC端');
      }

    }

使用媒体查询判断

获取当前浏览器的屏幕宽度

  if (window.innerWidth <= 1023) {
    console.log('当前在手机端');
  } else {
    console.log('当前在PC端');
  }

fetch直接读文件内容,解决乱码问题

 fetch(‘文件路径’).then(async (r) => {
      const text = await r.text();
      console.log(text);
  
    });

前端导出文件

将表格导出xlsx文件

import xlsx from 'node-xlsx';
import { saveAs } from 'file-saver';
/**
 * 下载xlsx文件
 * @param data 表格数据 [{},{}]
 * @param name 文件名
 */

export const downloadXlsx = (data: any, fileName: string) => {
  let headerArr: string[] = [];
  let data2 = data.map((item: any, index: number) => {
    let arr2 = [];
    for (let key in item) {
      if (index == 0) headerArr.push(key);
      arr2.push(item[key]);
    }
    return arr2;
  });
  data2.unshift(headerArr);
  //如果你已经将需要下载数据处理成二维数据的话,上面的操作可以不要,上面我是为了把table中的data处理成二维数组
  let result = xlsx.build([{ name: 'sheet1', data: data2 }]);
  const ab = Buffer.from(result, 'binary');
  const blob = new Blob([ab]);
  //可以 file-saver 直接下载,也可以用下面注释掉的创建a链接去下载
  saveAs(blob, fileName);

  // const blobUrl = URL.createObjectURL(blob);
  // const a = document.createElement('a');
  // a.href = blobUrl;
  // a.download = fileName;
  // a.click();
  // window.URL.revokeObjectURL(blobUrl);
};

将表格导出 txt fasta fa csv tsv等文本文件

注意
TSV是用制表符(Tab,’\t’)作为字段值的分隔符,以此转换的格式生成的文件;
CSV是用半角逗号(’,’)作为字段值的分隔符,以此转换的格式生成的文件;

import Papa from 'papaparse';
import { saveAs } from 'file-saver';
/**
 * 下载csv文件
 * @param origin 列表数据对象 [{},{}]
 * @param fileName 文件名
 */

export const downloadCSV = (origin: any, fileName: string) => {
  let result = '';
  if (fileName.includes('.tsv')) {
    result = Papa.unparse(origin).replace(/,/g, '\t');
  } else {
    result = Papa.unparse(origin);
  }
  const blob = new Blob(['\uFEFF' + result], { type: 'text/plain;charset=utf-8' });
  saveAs(blob, fileName);
};

js将二维数组转为 txt tsv csv fasta fa 等文本文件

//数组导出CSV文件
    const exportCSV = (jsonData: Array<string[]>, fileName: string) => {
      if (!jsonData || jsonData.length == 0) {
        console.log('暂无数据');
        return;
      }
      if (!fileName) {
        fileName = 'exportCSV.csv';
      }
      let csvText = '';

      //增加\t为了不让表格显示科学计数法或者其他格式
      for (let i = 0; i < jsonData.length; i++) {
        let row = '';
        for (let item in jsonData[i]) {
          row += `${jsonData[i][item]},`;
        }
        csvText += trim(row, ',') + '\n';
      }
      //encodeURIComponent解决中文乱码
      let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(csvText);
      //通过创建a标签实现
      let link = document.createElement('a');
      link.href = uri;
      //对下载的文件命名
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    };
    //js实现类似php trim函数
    const trim = (str: string, char: string) => {
      if (char) {
        str = str.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
      }
      return str.replace(/^\s+|\s+$/g, '');
    };
    const data = [
      ['士大夫', 'dfg', 'fgh'],
      ['要让他', '取完', '和'],
      ['士大夫', 'dfg', 'fgh'],
      ['要让他', '取完', '和'],
    ];
    exportCSV(data, 'test.tsv');

将字符串下载保存为 txt fasta fa csv tsv等文本文件

/**
 * 下载txt fasta fa等文本文件
 * @param text 文本内容
 * @param fileName 文件名
 */
export const saveTextAsFile = (text: any, filename: string) => {
  const blob = new Blob([text], { type: 'text/plain' });
  const url = URL.createObjectURL(blob);

  const a = document.createElement('a');
  a.href = url;
  a.download = filename;

  document.body.appendChild(a);
  a.click();

  document.body.removeChild(a);
  URL.revokeObjectURL(url);
};


//或者  

/**
 * 下载文件
 * @param url 文件路径
 * @param fileName 文件名称
 */
import { saveAs } from 'file-saver';
//安装一下 file-saver包
export const downloadTxt = (url: string, fileName: string) => {
 const fileBlob = fetch(url).then((r) => r.blob())
  const blob = new Blob(['\uFEFF'+fileBlob ], { type: 'text/plain;charset=utf-8' });
  saveAs(blob, fileName);
};

下载文件

/**
 * 下载文件
 * @param content 文件内容
 * @param fileName 文件名称
 */
export const download = (content: string, fileName: string) => {
  const link = document.createElement('a');
  link.href = encodeURI(content);
  link.download = fileName;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};

文件链接转文件流下载–主要针对pdf 解决谷歌浏览器a标签下载pdf直接打开的问题 还有excel下载

import { saveAs } from 'file-saver';


/**
 * 文件链接转文件流下载--主要针对pdf 解决谷歌浏览器a标签下载pdf直接打开的问题 还有excel下载
 * @param url  :文件链接
 * @param fileName  :文件名;
 * @param type  :文件类型;
 * @param fn  :进度回调方法;
 */

export const saveFileToLink = (url: string, fileName: string) => {
  let xhr = new XMLHttpRequest();
  url = url.includes('https:') ? url.replace('https:', '') : url.replace('http:', ''); //资源路径动态获取请求的方式HTTPS或HTTP
  xhr.open('get', url, true);
  xhr.setRequestHeader('Content-Type', 'application/');
  xhr.setRequestHeader('If-Modified-Since', '0'); //解决缓存问题,每次请求都去请求服务器获取最新数据
  xhr.responseType = 'blob';
  xhr.onprogress = function (e) {
    //文件下载进度
    // if (fn && typeof fn == 'function') {
    //   fn(e); //监听文件下载进度;
    // }
  };
  xhr.onload = function () {
    if (this.status == 200) {
      //接受二进制文件流
      let blob = this.response;
      saveAs(blob, fileName);
    }
  };
  xhr.send();
};

移动端和pc端js判断手指的上滑,下滑,左滑,右滑,事件监听 和 判断鼠标滚轮向上滚动滑轮向下滚动

const scrollFunc = (e) => {
  e = e || window.event;
  let wheelDelta = e.wheelDelta ? e.wheelDelta : -e.detail * 50;
  if (wheelDelta > 0) {
    console.log(wheelDelta + '滑轮向上滚动');
    let dom = document.querySelector('.header-contanier');
    dom.style.display = 'flex';

    let dom2 = document.querySelector('.navNull');
    dom2.style.display = 'block';
  }
  if (wheelDelta < 0) {
    console.log(wheelDelta + '滑轮向下滚动');
    let dom = document.querySelector('.header-contanier');
    let dom2 = document.querySelector('.navNull');
    dom.style.display = 'none';
    dom2.style.display = 'none';
  }
};
if (document.addEventListener) {
  //火狐使用DOMMouseScroll绑定
  document.addEventListener('DOMMouseScroll', scrollFunc, false);
}
//其他浏览器直接绑定滚动事件
window.onmousewheel = document.onmousewheel = scrollFunc; //IE/Opera/Chrome


// touchstart:     //手指放到屏幕上时触发
// touchmove:      //手指在屏幕上滑动式触发
// touchend:    //手指离开屏幕时触发
// touchcancel:     //系统取消touch事件的时候触发,这个好像比较少用
let startX: number = 0;
let startY: number = 0;
document.addEventListener(
  'touchstart',
  (e) => {
    e.preventDefault();
    // console.log(e);
    startX = e.changedTouches[0].pageX;
    startY = e.changedTouches[0].pageY;
  },
  false,
);
// document.addEventListener(
//   'touchend',
//   (e) => {
// e.preventDefault();
//     console.log(e);
//   },
//   false,
// );
document.addEventListener(
  'touchmove',
  (e) => {
    // e.preventDefault();
    let moveEndX = e.changedTouches[0].pageX;
    let moveEndY = e.changedTouches[0].pageY;
    let X = moveEndX - startX;
    let Y = moveEndY - startY;

    if (Math.abs(X) > Math.abs(Y) && X > 0) {
      console.log('right');
    } else if (Math.abs(X) > Math.abs(Y) && X < 0) {
      console.log('left');
    } else if (Math.abs(Y) > Math.abs(X) && Y > 0) {
      console.log('bottom');
    } else if (Math.abs(Y) > Math.abs(X) && Y < 0) {
      console.log('top');
    } else {
      alert('just touch');
    }
  },
  false,
);

vue2、vue3全局挂载

vue3全局挂载
推荐使用(provide/inject),不推荐使用globalProperties:最新版本的已经弃用了

main.ts中

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { store } from './store';
import ant from 'ant-design-vue';

import { ObjAscend, ObjDescend } from './utils/utils';

const app = createApp(App);
//在这里挂载 这里挂载的是两个函数
app.provide('ObjAscend', ObjAscend);
app.provide('ObjDescend', ObjDescend);
//不推荐这种挂载方式了,最新版本已经弃用了
app.config.globalProperties.window = window;
app.use(router).use(store).use(ant).mount('#app');

组件中

import { defineComponent, inject } from 'vue';

let ObjAscend:(parm:string)=>any = inject('ObjAscend')
let ObjDescend:any = inject('ObjDescend')

vue2全局挂载
main.ts中

import Vue from 'vue'
import App from './App'
import wLoading from "@/component/w-loading.vue";
import store from './store'
import {
    showToastOrNavTo,
    scanCode
} from '@/utils/util'
Vue.prototype.$store = store;
Vue.prototype.showToastOrNavTo = showToastOrNavTo;

页面中 :直接this就好了

    mounted() {
      this.showToastOrNavTo()
      this.scanCode()
    }

js点击按钮复制文本方法

	//方法一:
    clickCopy(text) {
      const save = function (evn) {
        evn.clipboardData.setData("text/plain", text);
        evn.preventDefault(); // 阻止默认行为
      };
      document.addEventListener("copy", save); // 添加一个copy事件
      document.execCommand("copy"); // 执行copy方法
      this.$message({ message: "复制成功", type: "success" });
    }
    //方法二:
    clickCopy(code) {
      let oInput = document.createElement('input');
      oInput.value = code;
      document.body.appendChild(oInput);
      oInput.select(); // 选择对象;
      document.execCommand("Copy"); // 执行浏览器复制命令
      this.$message({ message: '复制成功', type: 'success' });
      oInput.remove()
    }

vite vue3 遍历图片不显示问题

官网:vite官网参考

<div
        class="header-menu-list flex ac"
        v-for="(item, i) in header"
        :key="item.title"
      >
        <div class="header-img">
          <img :src="getimg(i)" alt="" />
        </div>
</div>
<script>
 methods: {
    // 图片
    getimg(e) {
      let path1 = [
        "/src/assets/img/guangfu1.png",
        "/src/assets/img/day.png",
        "/src/assets/img/sum.png",
        "/src/assets/img/yongshuiliang.png",
        "/src/assets/img/leijiyongshui.png",
      ];                                         
       //属性是href,正好是函数的返回值   
       //(我测试的,打包后就不能用了,绝对路径可以:(E:/img/sum.png))
       // 是在不行也可以用 import url1 from '/@/assets/img/shamen.jpg';  最后吧rul1放到数组里面再去遍历
      return new URL(path1[e],import.meta.url).href   //import.meta 对象包含关于当前模块的信息。
    },
}
<script/>

@keyup.enter.native不生效问题解决

el-form表单中的el-input回车刷新页面,@keyup.enter.native不生效问题解决
表单中只有一个input,键盘回车会刷新页面,@keyup.enter就会失效
解决方案:
1:在表单里加一个不显示的input(不推荐此写法)
2:在el-form上添加@submit.native.prevent(推荐)

    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px" @submit.native.prevent>
      <el-form-item label="客户id" prop="customerId">
        <el-input v-model="queryParams.customerId" placeholder="请输入客户id" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

js将一维数组转为二维数组

如果多维数组转以为数组用 flat() arr.flat()

//推荐使用 convertTo2DArray 
  const convertTo2DArray = (arr: Array<any>, chunkSize: number) => {
    var result = [];
    //slice:截取,返回新数组,不改变原数组
    for (var i = 0; i < arr.length; i += chunkSize) {
      result.push(arr.slice(i, i + chunkSize));
    }
    return result;
  }
  
const arrToMatrix = (arr: Array<any>, num: number) => {
  var matrix = [], i, k;
  for (i = 0, k = -1; i < arr.length; i++) {
    if (i % num === 0) {
      k++;
      matrix[k] = [];
    }
    matrix[k].push(arr[i]);
  }
  return matrix;
}

electron中指定默认下载路径和名称


const { BrowserWindow} = require('electron');
    // 触发下载
    let win = BrowserWindow.getFocusedWindow();
    win.webContents.downloadURL(args.download)

    //监听下载动作
    win.webContents.session.on('will-download', (event, item, webContents) => {
      /* 
      args.localPath:下载的资源连接  url
      args.saveName:下载名字
      */
      var zipFile = path.join(args.localPath, args.saveName)
      // console.log(zipFile)
      item.setSavePath(zipFile)

      //监听下载过程
      item.on('updated', (event, state) => {
        //下载意外中断,可以恢复
        if (state === 'interrupted') {
          console.log('Download is interrupted but can be resumed')
        } else if (state === 'progressing') {
          //下载正在进行中
          if (item.isPaused()) {
            //下载暂停中
            console.log('Download is paused')
          } else {
            //下载进行中 下载进度
            console.log(`complete:${(item.getReceivedBytes() / item.getTotalBytes() * 100).toFixed(2)}%`)
            //任务栏进度条 -1不展示
            win.setProgressBar(item.getReceivedBytes() / item.getTotalBytes())
          }
        }
      })

      //监听完成
      item.once('done', (event, state) => {
        console.log('下载完成下载完成')

        //读取一个Buffer
        var buffer = fs.readFileSync(zipFile);
        var fsHash = crypto.createHash('sha1');

        fsHash.update(buffer);
        var sha1 = fsHash.digest('hex');
        console.log("文件的MD5是:%s", args.hash + ',' + sha1);

        if (sha1 == args.hash) {
          shell.openPath(zipFile)
        }
        // console.log(getFileSha1(zipFile))
        // win.webContents.send('onFileSHA1', zipFile)
        // shell.openPath(zipFile)
      })


    })

TypeScript 中?: 、??、?. 、!. 、&&= 、??= 、||= 含义解析

  • ?: 是指可选参数,可以理解为参数自动加上undefined
  • ?? ?? 和 || 的意思有点相似,但是又有点区别,??相较||比较严谨, 当值等于0的时候||就把他给排除了,但是?? 不会.
  • ?. ?.的意思基本和 && 是一样的
  • !. !.的意思是断言,告诉ts你这个对象里一定有某个值
  • &&= 如果第一个表达式的值为 true,则执行第二个表达式,并将结果赋值给第一个表达式;如果第一个表达式的值为 false,则不执行第二个表达式,第一个表达式的值不变。
  • ||= 如果左侧的操作数(表达式)为真(即非零、非空或非undefined),则返回左侧的操作数(表达式);否则,返回右侧的操作数(表达式)。
  • ??= 如果左侧的操作数(表达式)是 null 或 undefined,那么返回右侧的操作数(表达式);否则,将右侧的操作数(表达式)赋值给左侧的操作数(表达式)。

看下面的例子

a = a && b 
a = a || b
a = a ?? b

//等效于下面的方法

a &&= b;
a ||= b;
a ??= b;

input框中输入的值,需要导出pdf或者打印出来为空的问题

原理:利用 setAttribute()方法添加value属性,并为其赋值

      
      let allInput = document.querySelectorAll('input')   //先获取所有的input 的dom对象
      allInput.forEach((item, index) => {
        if (index != 0) {
	        //利用 setAttribute()方法天骄value属性,并为其赋值   allInput[index].value:对应input中输入的值
          allInput[index].setAttribute('value', allInput[index].value)
        }

      })

js写货币格式(每三位一个逗号分隔)

注意:每个组件库中都有:Statistic 统计数值,可以参考一下,直接应用
在这里插入图片描述

  const convertNum = (val: number) => {
    return val.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
  };

大数值转换为 K,M,G,T或者KB,MB,GB,TB

// 转换文件大小格式
export const convertSizeFormat = (size: number): string => {
	if (!size) return '0 Bytes' // 处理size为0的特殊情况
	const unit = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
	let index = Math.floor(Math.log(size) / Math.log(1024))
	let newSize = size / Math.pow(1024, index)
	// 保留的小数位数
	return newSize.toFixed(2) + ' ' + unit[index]
}

export default function convertNumber(number: any) {
  if (number < 10 ** 3) {
    return number;
  }
  if (10 ** 3 <= number && number < 10 ** 6) {
    return `${(number / 10 ** 3).toFixed(1)} K`;
  }
  if (10 ** 6 <= number && number < 10 ** 9) {
    return `${(number / 10 ** 6).toFixed(1)} M`;
  }
  if (10 ** 9 <= number && number < 10 ** 12) {
    return `${(number / 10 ** 9).toFixed(1)} G`;
  }
  return `${(number / 10 ** 12).toFixed(1)} T`;
}

export function convertBase(number: any) {
  if (number < 10 ** 3) {
    return number;
  }
  if (10 ** 3 <= number && number < 10 ** 6) {
    return `${(number / 10 ** 3).toFixed(1)} Kb`;
  }
  if (10 ** 6 <= number && number < 10 ** 9) {
    return `${(number / 10 ** 6).toFixed(1)} Mb`;
  }
  if (10 ** 9 <= number && number < 10 ** 12) {
    return `${(number / 10 ** 9).toFixed(1)} Gb`;
  }
  return `${(number / 10 ** 12).toFixed(1)} Tb`;
}

数组包对象,同时对多个属性进行筛选(搜索查询)

html页面的input

    <div class="search">
      <!-- orderName geneName   similar  length  evalue  score-->
      <a-space>
        <a-input v-model:value="tableConfig.orderName" placeholder="请输入序列名称" @keyup.enter.native="search" allowClear />
        <a-input v-model:value="tableConfig.geneName" placeholder="请输入参考基因组名称" @keyup.enter.native="search" allowClear />
        <a-input v-model:value="tableConfig.similar" placeholder="请输入相似性" @keyup.enter.native="search" allowClear />
        <a-button type="primary" @click="search">查询</a-button>
        <a-button type="default" @click="reset">重置</a-button>
      </a-space>
    </div>

这里是需要筛选的数据 方法在下面写

 let tableConfig.SearchtotalData = [
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "98.489",
      "id": "1",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "98.857",
      "id": "2",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "id": "3",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "98.386",
      "id": "4",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "97.522",
      "id": "5",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "98.889",
      "id": "6",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "99.048",
      "id": "7",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "98.706",
      "id": "8",
    },
    {
      "序列名称": "contig_1",
      "参考基因组名称": "AJ938182",
      "相似性(%)": "98.085",
      "id": "9",
    }
  ]

筛选的方法

  const search = () => {

    if (!tableConfig.orderName && !tableConfig.geneName && !tableConfig.similar && !tableConfig.length && !tableConfig.evalue && !tableConfig.score) {
      message.info('请输入筛选条件!')
    } else {
      let tempArray = [];

      tableConfig.SearchtotalData.forEach(item => {
        let flag = false;
        let flag2 = false;
        let flag3 = false;
        if (tableConfig.orderName) {

          if (item.序列名称.includes(tableConfig.orderName)) {
            flag = true;
          } else {
            flag = false;
          }

        } else {
          flag = true;
        }

        if (tableConfig.geneName) {
          if (flag && item.参考基因组名称.includes(tableConfig.geneName)) {
            flag2 = true;
          } else {
            flag2 = false;
          }
        } else {
          flag2 = true;
        }

        let isSimilar = parseFloat(item['相似性(%)']) > parseFloat(tableConfig.similar)
        if (tableConfig.similar) {
          if (flag && flag2 && isSimilar) {
            flag3 = true;
          } else {
            flag3 = false;
          }
        } else {
          flag3 = true;
        }


       

        if (flag && flag2 && flag3 ) {
          tempArray.push(item);
        }


        tableConfig.totalData = tempArray;
        tableConfig.totalNumber = tableConfig.totalData.length

      })


    }

  }

字符串中混合数字,按照部分数字排序

在这里插入图片描述

/**
 * string和number混合,的字符串,按照部分数字排序 如:
 * var arr = ['sample1', 'sample10', 'sample2', 'sample12', 'sample5'];
 * 输出:  ['sample1', 'sample2', 'sample5', 'sample10', 'sample12']
 * @param val1
 * @param val2
 * @returns
 */
export const stringNumberMixSort = (a: string | number, b: string | number) =>
  a - b || a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });



export const compareSort = (a: string | number, b: string | number) => {
  if (typeof a === 'number') {
    return a - b;
  } else {
    return a?.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
  }
};

数组包对象,按照对象的某一属性去重

推荐方法一

  /**
   *  根据唯一值对数组进行去重
   * @param list 要去去重的数组
   * @param key  按照对象某一属性(key)去重
   */
  const deWeightThree = (list: Array<any>, key: string) => [
    ...list.reduce((prev, cur) => prev.set(cur[key], cur), new Map()).values(),
  ];
  console.log(deWeightThree(tempArr, 'name'));

方法二:

		//arr: 要去重的数组, attribute:按照对象的属性去重
        let deWeightThree = (arr: Array<any>, attribute: string) => {
          let map = new Map();
          for (let item of arr) {
            if (!map.has(item[attribute])) {
              map.set(item[attribute], item);
            }
          }
          return [...map.values()];
        }
        //得到的新数组 
        tempArray2 = deWeightThree(tempArray, 'sample');

数组包对象,以对象的某一个属性排序

首相要了解数组的sort方法

对象的属性是 number类型

let  arr = [{name: "zlw", age: 24}, {name: "wlz", age: 25}];
//降序
let ObjDescend= function (prop) {
    return function (obj1, obj2) {
        var val1 = obj1[prop];
        var val2 = obj2[prop];
        if (val1 < val2) {
            return -1;
        } else if (val1 > val2) {
            return 1;
        } else {
            return 0;
        }            
    } 
}

//如果想以 age,进行排序:arr.sort(ObjDescend('age'))


//或者直接用sort方法:
arr.sort(function(a, b) {
  return a.age - b.age;//升序
  //return b.age - a.age;//降序
});

如果 age 的值为字符串 (age:“24”),还用上面的方法则会按照ASCII排序(按照字符串排序)

对象的属性是字符串的类型

let  arr = [{name: "zlw", age: 24}, {name: "wlz", age: 25}];
//升序
let ObjAscend= function (prop) {
    return function (obj1, obj2) {
        var val1 = obj1[prop];
        var val2 = obj2[prop];
        if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
            val1 = Number(val1);
            val2 = Number(val2);
        }
        if (val1 > val2) {
            return -1;
        } else if (val1 < val2) {
            return 1;
        } else {
            return 0;
        }            
    } 
}
如果想以 age,进行排序:arr.sort(ObjAscend('age'))


getCookie、setCookie、removeCookie

function getCookie(key){
    var arr1 = document.cookie.split('; ');//这里是分号+空格分隔
    for( var i = 0 , len = arr1.length ; i < len ; i++ ){
        var arr2 = arr1[i].split('=');
        if( arr2[0] == key ){
            return decodeURI(arr2[1]);
        }
    }
}
getCookie('age');//21


		

function setCookie(key,value,time){
    var oDate = new Date();
    oDate.setDate( oDate.getDate() + time );
    document.cookie = key +'=' + value + ';expires=' + oDate.toGMTString();
}
setCookie('sex','男',10);//sex='男'存cookie十天


//封装一个删除cookie的方法,就是将cookie的有效时间更改为昨天而已。
function removeCookie(key){
    setCookie(key,'',-1);//调用上面的setCookie方法
}
removeCookie('sex');


防抖:n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

// 防抖:n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
function _debounce(func,delay) {
    let timeout;
	var delay = delay || 200;
    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);

        let callNow = !timeout;
        timeout = setTimeout(() => {
            timeout = null;
        }, delay)

        if (callNow) func.apply(context, args)
    }
}

//防抖
let timer_debounce: any;
export const debounce = (func: Function, wait?: number) => {
  wait = wait || 500;
  clearTimeout(timer_debounce);
  timer_debounce = setTimeout(() => {
    func.apply(this);
  }, wait);
};

节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

// 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
function _throttle(fn, interval) {
    var last;
    var timer;
    var interval = interval || 200;
    return function () {
        var th = this;
        var args = arguments;
        var now = +new Date();
        if (last && now - last < interval) {
            clearTimeout(timer);
            timer = setTimeout(function () {
                last = now;
                fn.apply(th, args);
            }, interval);
        } else {
            last = now;
            fn.apply(th, args);
        }
    }
}
let timer_throttle: any;
export const throttle = (func: Function, wait?: number) => {
  wait = wait || 500;
  if (!timer_throttle) {
    timer_throttle = setTimeout(() => {
      func.apply(this);
      timer_throttle = null;
    }, wait);
  }
};

不想自己写,也可以用 lodash 库去实现

_.throttle(func, [wait=0], [options=])//节流
//说明:
//func (Function): 要节流的函数。
//[wait=0] (number): 需要节流的毫秒。
//[options=] (Object): 选项对象。
//[options.leading=true] (boolean): 指定调用在节流开始前。
//[options.trailing=true] (boolean): 指定调用在节流结束后。
 
_.debounce(func, [wait=0], [options=])//防抖
//说明:
//func (Function): 要防抖动的函数。
//[wait=0] (number): 需要延迟的毫秒数。
//[options=] (Object): 选项对象。
//[options.leading=false] (boolean): 指定在延迟开始前调用。
//[options.maxWait] (number): 设置 func 允许被延迟的最大值。
//[options.trailing=true] (boolean): 指定在延迟结束后调用。



//记得安装
//引入
import _ from "lodash";
//使用
_.debounce(() => {
  console.log("防抖");
}, 500);

_.throttle(() => {
  console.log("节流");
}, 500);

将文件类型转换成字符串数组

// 将文件类型转换成字符串数组
export const filesToStringArrary = function (list: any) {
  if (typeof list === 'string') return list;
  if (list === null) return [];
  const _list: { fileName: any; fileType: any; fileId: any }[] = [];
  const _ids_list: any[] = [];
  list.length > 0 &&
    list.map(function (
      item: { response: { data: any[] }; name: any; type: any; contentType: any; uid: any },
    ) {
      if (item.response) {
        _list.push({
          fileName: item.name,
          fileType: item.type,
          fileId: item.response.data[0],
        });
        _ids_list.push(item.response.data[0]);
      } else {
        _list.push({
          fileName: item.name,
          fileType: item.contentType,
          fileId: item.uid,
        });
        _ids_list.push(item.uid);
      }
    });

  return { _list, _ids_list };
};

将对象转化为URL的查询字符串(对象转化为地址栏问号传参)

在这里插入图片描述

常用语get请求传参,将对象格式转换为?+&的情况

/**
 * 将对象转化为URL的查询字符串
 * @param q 查询对象
 * @returns URL的查询字符串
 */

export const formatQuery = (q: any) => {
  let query = '';
  Object.keys(q).forEach((key) => {
    if (q[key] !== '' && q[key] !== undefined) {
      query += `${key}=${q[key]}&`;
    }
  });
  return query.substring(0, query.length - 1);
};

vue3中解构地址栏参数 (比下面getUrlParams好用)

	import { useRouter } from 'vue-router';

    const router = useRouter();
    const query = JSON.parse(JSON.stringify(router.currentRoute.value.query));
    const { taskId, barcodeId, sampleId, generation, barcodeName } = query;  //{}里面直接结构参数

截取地址栏参数

// 获取数组的params字段默认用来获取rbacToken;
export const getUrlParams = function (name: string) {
  const url2 = window.location.href;
  const temp2 = url2.split('?')[1];
  const pram2 = new URLSearchParams(`?${temp2}`);
  let data = pram2.get(name);
  if (!data) return '';
  if (data.indexOf('#/') >= 0) {
    data = data.split('#/')[0];
  }
  return data;
};

如果需要传值过多,推荐使用下列方法,类似于vue3中的vue-router

	//将地址栏参数返回一个对象直接结构出来就好了,类似于上面的vue3获取地址栏参数
    export const getUrlParamsObj = function () {
      var s = location.href.indexOf("?");
      var t = location.href.substring(s + 1);
      let arr = t.split('\&')
      let paramsObj: any = {}
      arr.forEach((item: string, index: number) => paramsObj[item.split('=')[0]] = item.split('=')[1])
      return paramsObj;
    };
	//使用方法
    //let { taskId ,barcodeId } = getUrlParamsObj()
    //console.log(taskId ,barcodeId);

dom节点删除 删除子节点 removeChild

在同一个div中话echart是,需要清除画布,重回绘制,否则会重叠,这里我用了删除dom在添加一个div进去

	 /**
   	 * 要删除的父div id
     * 要删除的div  id
     */
     resetDom('mapParent', 'map')

	 const resetDom = (parentId: string, childId: string) => {
            let parentsDom = document.getElementById(parentId);
            // clear
            let childDom = document.getElementById(childId);
            if (childDom) {
                parentsDom.removeChild(childDom)
            }
            // create
            var littleBox = document.createElement('div')
            littleBox.style.width = "100%";
            littleBox.style.height = "100%";
            littleBox.setAttribute("id", childId)
            parentsDom.appendChild(littleBox) 
        }

如何隐藏滚动条 滚动条的样式修改


  overflow: auto;
  overflow-x: hidden;
  overflow-y: scroll;
  scrollbar-width: none;		/* firefox */
  -ms-overflow-style: none;    /* IE 10+ */

  /* 设置滚动条的样式 */
  &::-webkit-scrollbar {
   	display: none; 
    //width: 12px;
    //height:12px;
  }

  /* 滚动槽 */
  &::-webkit-scrollbar-track {
    background-color: #fdffeb;
    border-radius: 10px;
  }

  /* 滚动条滑块 */
  &::-webkit-scrollbar-thumb {
    border-radius: 10px;
    background: rgba(173, 247, 89, 0.6);
  }

  &::-webkit-scrollbar-thumb:window-inactive {
    background: rgba(255, 0, 0, 0.4);
  }

获取系统时间日期, 返回:日期,星期

/** 获取系统时间日期, 返回:
 * @returns dateNum: 日期, dayStr: 星期
 */
const getNowDateStr = () => {
  const nowDate = new Date();
  const dayStrs = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六",];

  const dateNum = nowDate.getDate();
  const dayStr = dayStrs[nowDate.getDay()];

  return {
    dateNum,
    dayStr
  }
}

将rangepick 时间选择的数据进行过滤

//将rangepick 时间选择的数据进行过滤
export const filterKeys = function (data) {
  const filterData = {};
  for (let key in data) {
    if (key.indexOf('-') >= 0) {
      key.split('-').map(function (item, idx) {
        if (!data[key]) {
          filterData[item] = undefined;
        } else {
          if (typeof data[key][idx] === 'object') {
            //目前只针对时间做了优化 未出现有其他是对象的值
            filterData[item] = data[key][idx].format('YYYY-MM-DD 00:00:00');
          } else {
            filterData[item] = data[key][idx];
          }
        }
      });
    } else {
      filterData[key] = data[key];
    }
  }
  return filterData;
};

字符串超出长度显示省略号 css方法

word-break: break-all; 只对英文起作用,以字母作为换行依据。
word-wrap: break-word; 只对英文起作用,以单词作为换行依据。
white-space: pre-wrap; 只对中文起作用,强制换行。

一行显示

// 这样只能显示一行,多出的省略号显示
white-space: nowrap;/* 强制在一行显示 */
text-overflow: ellipsis;  /* 超过最小宽度后,超过部分用省略号显示 */
overflow: hidden; /* 超过最小宽度后,自动隐藏 */

多行显示

  text-overflow: ellipsis;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;  //这里控制行数
  -webkit-box-orient: vertical;

字符串超出长度显示省略号 js截取方法

// 字符串超出长度显示省略号
const lineOmit = function (str, breakLength) {
    if (!breakLength) breakLength = 3;
    if (str.length <= breakLength) return str;
    return str.slice(0, breakLength) + '...';
};

input 取消默认提示框

autocomplete="off"    // 添加这个属性

<input autocomplete="off"  /> //这样获取焦点的时候就没有提示框了

利用@media与@media screen进行响应式布局

在这里插入图片描述
在这里插入图片描述


<style>
//一种是直接在link中判断设备的尺寸,然后引用不同的css文件:
<link rel="stylesheet" type="text/css" href="styleA.css" media="screen and (min-width: 400px)">

//另一种方式,即是直接写在 style 标签里:
@media screen and (max-width: 1919px) {
  @import './styles/small.less';

}

@media screen and (min-width: 1920px) {
  @import './styles/big.less';
}


// 参考下面的例子:

//我们用min-width时,小的放上面大的在下面,同理如果是用max-width那么就是大的在上面,小的在下面
@media (min-width: 1200){ //>=1200的设备 }
@media (min-width: 992px){ //>=992的设备 }
@media (min-width: 768px){ //>=768的设备 }
//注意下顺序,如果你把@media (min-width: 768px)写在了上面那么就是错误的!!!

@media (max-width: 1199){ //<=1199的设备 }
@media (max-width: 991px){ //<=991的设备 }
@media (max-width: 767px){ //<=768的设备 }

//混合使用
 @media screen and (min-width:1200px){} 
 @media screen and (min-width: 960px) and (max-width: 1199px) {  }
 @media screen and (min-width: 768px) and (max-width: 959px) {  }
 @media only screen and (min-width: 480px) and (max-width: 767px){  } 
 @media only screen and (max-width: 479px) {  }
</style>




表格时间格式化

/**
 * 表格时间格式化
 */
export function formatDate(cellValue) {
  if (cellValue == null || cellValue == "") return "";
  var date = new Date(cellValue)
  var year = date.getFullYear()
  var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
  var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
  return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
}







/**
 * @param {number} time
 * @param {string} option
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000
  } else {
    time = +time
  }
  const d = new Date(time)
  const now = Date.now()

  const diff = (now - d) / 1000

  if (diff < 30) {
    return '刚刚'
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + '分钟前'
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前'
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
  }
  if (option) {
    return parseTime(time, option)
  } else {
    return (
      d.getMonth() +
      1 +
      '月' +
      d.getDate() +
      '日' +
      d.getHours() +
      '时' +
      d.getMinutes() +
      '分'
    )
  }
}

日期格式化

// 日期格式化
export function parseTime(time, pattern) {
  if (arguments.length === 0 || !time) {
    return null
  }
  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
      time = parseInt(time)
    } else if (typeof time === 'string') {
      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

获取设备信息方法

//获取设备信息方法
const getClientInfo = () => {
    var cid, getClientInfo;
    return new Promise(function (resolve) {
        try {
            if (window && window.plus) {
            } else {
                if (plus) {
                    //#ifdef APP-PLUS
                    getClientInfo = plus.push.getClientInfo();
                    cid = getClientInfo.clientid;
                    console.log(cid);
                    console.log(getClientInfo);
                    resolve({
                        cid,
                        getClientInfo
                    })
                    //#endif
                } else {
                    plus.globalEvent.addEventListener('plusready', function () {
                        if (cid && cid != 'undefind' && cid != '' && cid != 'null') {
                            return;
                        }
                        //#ifdef APP-PLUS
                        getClientInfo = plus.push.getClientInfo();
                        //#endif
                        cid = getClientInfo.clientid;
                        console.log(cid);
                        console.log(getClientInfo);
                        resolve({
                            cid,
                            getClientInfo
                        })
                    });

                }

            }
        } catch (e) {
            //#ifdef H5
            resolve({})
            //#endif
            //TODO handle the exception
        }
    })
}

封装公共路径跳转的方法

//封装公共路径跳转的方法
const navTo = function (url, params) {
    if (!isNaN(parseInt(url))) {
        uni.navigateBack({
            delta: Number(url)
        })
        return;
    }
    let _params = "";
    params ?
        Object.keys(params).map(function (key, idx) {
            _params = _params + `${idx == 0 ? '?' : '&'}${key}=${params[key]}`;
        }) : null;
    uni.navigateTo({
        url: url + _params,
    })
}
//提示文字+路径跳转方法
//如果没有传navTo对象 则不进行跳转 只进行提示
const showToastOrNavTo = function (conf) {
    const { title, duration, icon, image, navTo: _navTo } = conf;
    uni.showToast({
        //icon 类型 success error loading none
        //none 不显示图标,此时 title 文本在小程序最多可显示两行,App仅支持单行显示。
        icon: icon ? icon : 'success',
        //自定义图标路径
        image: image ? image : null,
        mask: true,
        title: title || "操作成功",
        duration: Number(duration) || 1500,
        complete: function () {
            _navTo ?
                setTimeout(function () {
                    navTo(_navTo.url, _navTo.params)
                }, duration || 1500) : null
        }
    });

}

扫码的方法 h5 不兼容

//扫码的方法 h5 不兼容
const scanCode = (conf) => {
    const { onlyFromCamera, scanType } = conf || {};
    return new Promise(function (resolve) {
        uni.scanCode({
            //是否只能从相机扫码,不允许从相册选择图片
            onlyFromCamera: onlyFromCamera || true,
            //扫码类型,参数类型是数组,二维码是'qrCode',一维码是'barCode',DataMatrix是‘datamatrix’,pdf417是‘pdf417’。
            scanType: scanType || ['qrCode'],
            success: function (...data) {
                resolve(...data)
            },
            fail: function (err) {
                if (err.errMsg.includes("cancel")) {
                    return;
                } else {
                    showToastOrNavTo({
                        icon: "error",
                        title: "扫码失败",
                    })
                }
            },
            complete: function () {
            }
        })
    })

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜空孤狼啸

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值