目录
获取数据类型
getType() {
var obj = Array.prototype.shift.apply(arguments);
var toString = Object.prototype.toString;
var map = {
"[object Boolean]": "boolean",
"[object Number]": "number",
"[object String]": "string",
"[object Function]": "function",
"[object Array]": "array",
"[object Date]": "date",
"[object RegExp]": "regExp",
"[object Undefined]": "undefined",
"[object Null]": "null",
"[object Map]": "map",
"[object Object]": "object"
};
if (obj instanceof Element) {
return "element";
}
return map[toString.call(obj)];
},
// 调用
var type = this.getType(data);
深拷贝
deepClone() {
var data = Array.prototype.shift.apply(arguments);
var type = this.getType(data);
var obj;
if (type === "array") {
obj = [];
for (var i = 0, len = data.length; i < len; i++) {
obj.push(this.deepClone(data[i]));
}
} else if (type === "object") {
obj = {};
for (var key in data) {
obj[key] = this.deepClone(data[key]);
}
} else if (type === "map") {
obj = new Map();
data.forEach((item, key) => {
obj.set(key, this.deepClone(item));
});
} else {
return data;
}
return obj;
},
格式化金额
/**
* 格式化金额
* 1000 => '1000.00'
*/
export const moneyFormat = x => {
let f = parseFloat(x)
if (isNaN(f)) {
return 0.0
}
f = Math.round(x * 100) / 100
let s = f.toString()
let rs = s.indexOf('.')
if (rs < 0) {
rs = s.length
s += '.'
}
while (s.length <= rs + 2) {
s += '0'
}
return s
}
/**
* 10000 => "10,000"
*/
export const toThousandFilter = num => {
return (+num || 0)
.toString()
.replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
}
/**
* 大数值转换为万,亿函数
*
* @param {Number} 大数
* @param {Number} 保留几位小数
*/
export const numConversion = (num, point = 2) => {
const numStr = num.toString().split('.')[0] // 去掉小数点后的数值字符串
const numLen = numStr.length
if (numLen < 6) {
return numStr
} else if (numLen >= 6 && numLen <= 8) {
const decimal = numStr.substring(numLen - 4, numLen - 4 + point)
const res = parseInt(num / 10000) + '.' + decimal + '万'
return res
} else if (numLen > 8) {
const decimal = numStr.substring(numLen - 8, numLen - 8 + point)
const res = parseInt(num / 100000000) + '.' + decimal + '亿'
return res
}
}
/**
* 大金额转换
* @param {*} money 金额
* @returns
*/
export function formatMoney (money) {
if (money !== undefined && money !== null && money !== ''){
let s
let m = parseFloat(money);
if (m < 10000){
s = '元';
} else if (m >= 10000 && m < 100000000){
s = '万元';
m = m / 10000;
} else {
s = '亿';
m = m / 100000000;
}
let result = m.toFixed(`${m}`.includes('.') ? 2 : 0) + s;
return result;
} else {
return '/';
}
}
图片压缩
需安装 lrz:npm i lrz
import lrz from 'lrz'
/**
* 图片压缩
*
* @export
* @param {*} file 通过 input:file 得到的文件,或者直接传入图片路径
* @param {number} [width=1200] 图片最大不超过的宽度,默认为1200
* @param {number} [height=1200] 同上
* @param {number} [quality=0.7] 图片压缩质量,取值 0 - 1,默认为0.7
* @returns 返回值是一个promise对象
* rst.formData 后端可处理的数据
* rst.file 压缩后的file对象(默认已经丢在rst.formData有一份了),需要注意的是如果压缩率太低的话,这个会是原始的file对象
* rst.fileLen 生成后的图片的大小,后端可以通过此值来校验是否传输完整
* rst.base64 生成后的图片base64,后端可以处理此字符串为图片,也直接用于img.src = base64
* rst.base64Len 生成后的base64的大小,后端可以通过此值来校验是否传输完整 (如果采用base64上传方式)
* rst.origin 也就是原始的file对象,里面存了一些原始文件的信息,例如大小,日期等。
*
*/
export default async function compress(file, width = 1200, height = 1200, quality = 0.7) {
return await lrz(file, { width, height, quality })
}
获取随机16进制颜色
/**
* 随机16进制颜色 hexColor
* return string str 带#号的随机16进制颜色
*/
export const hexColor = () => {
let str = '#'
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F']
for (let i = 0; i < 6; i++) {
const index = Number.parseInt(Math.random() * 16)
str += arr[index]
}
return str
}
节流,防抖函数
/**
* 节流,当持续触发事件时,在规定时间段内只能调用一次回调函数。
* 用Vue.prototype.$deb=Debounce; 这种方式做导入时 只能导入一个
*/
export const Throttle = (fn, interval = 500) => {
let last
let timer
return function() {
const th = this
const args = arguments
const 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)
}
}
}
/**
* 防抖,指触发事件后在规定时间内回调函数只能执行一次,
* 如果在规定时间内又触发了该事件,则会重新开始算规定时间
*/
export default function Debounce(fn,delay = 500) {
let timer
return function() {
const th = this
const args = arguments
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(function() {
timer = null
fn.apply(th, args)
}, delay)
}
}
证件号脱敏
export const stringEncrypt = (str) => {
if (!str) return
const len = str.length
if (len < 8) return str
const center = str.slice(4, len - 4)
const b = center.replace(/\w/gi, '*')
str = str.slice(0, 4) + b + str.slice(len - 4, len)
return str
}
uniapp小程序开发u-toast封装
export const uUnits= {
uToast({ refs, msg, zIndex = 10079}) {
let platForm = ""
// #ifdef H5
platForm = "H5"
// #endif
let tipRef = null
if (platForm === 'H5') {
tipRef = this.$refs[refs]
} else {
tipRef = this.$children.find(item => item.$options.name === 'u-toast')
}
tipRef.show({
message: msg || '',
duration: 2000,
zIndex: zIndex
})
}
}
// 调用
uUnits.uToast.call(this, {
refs: 'tipRef',
msg: '报名成功',
})
获取身份证有效期限
/**
* 计算身份证有效期限
* @param {*} idCardNo 身份证号
* @param {*} startTime 身份证有效期开始日期
*/
function getRightSpanTime(idCardNo,startTime) {
let valid = 5;
const year = +idCardNo.substring(6, 10);
const month = +idCardNo.substring(10,12);
const day = +idCardNo.substring(12,14);
// 领证年份
const getLiceDate = new Date(startTime.replace(/-/g,'/'));
const getLiceYear = getLiceDate.getFullYear();
const getLiceMonth = getLiceDate.getMonth() + 1;
const getLiceDay = getLiceDate.getDate();
// 领证年龄(领证年龄取整岁)
let getLicenseAge = getLiceYear - year;
if(getLiceMonth < month) {
getLicenseAge--
} else if(getLiceMonth === month) {
if(getLiceDay < day) {
getLicenseAge--
}
}
/* 年龄小于16,有效期5年
年龄大于等于16,小于等于25,有效期10年
年龄大于等于26,小于等于45,有效期20年
年龄大于等于46,长期 */
if(getLicenseAge < 0) {
valid = 0;
} else if(getLicenseAge < 16) {
valid = 5;
} else if(getLicenseAge >= 16 && getLicenseAge <=25) {
valid = 10;
} else if(getLicenseAge >= 26 && getLicenseAge <= 45) {
valid = 20;
} else {
// 长期
valid = 21
}
return valid
}
// 获取身份证表单起止时间间隔
function getIDFormTimeSpan(startTime,endTime) {
let year;
const sTime = startTime.replace(/-/g,'/');
const eTime = endTime.replace(/-/g,'/');
let sYear = new Date(sTime).getFullYear();
let eYear = new Date(eTime).getFullYear();
let sMonth = new Date(sTime).getMonth() + 1;
let eMonth = new Date(eTime).getMonth() + 1;
let sDay = new Date(sTime).getDate();
let eDay = new Date(eTime).getDate();
year = eYear - sYear;
// 计算年间距后,保证月份日期相等
const IsEquel = sMonth === eMonth && sDay === eDay;
return {year,IsEquel}
}
文件下载
/**
* 下载文件
* @param res 必传,服务端返回的响应
* @param fileName 生成文件名称,可不传,使用响应头content-disposition设置
* @param type 文件媒体类型,可匹配默认值,也可传其他值
*/
export const downloadFile = function({ res, fileName, type }) {
// find more in https://www.iana.org/assignments/media-types/media-types.xhtml
const mimeTypeMap = {
doc: 'application/msword',
pdf: 'application/pdf',
excel: 'application/vnd.ms-excel'
}
let name = fileName
const contentDisposition = res.response.headers['content-disposition']
if (!fileName && contentDisposition) {
name = decodeURIComponent(contentDisposition.replace(/attachment;\s?filename=/g, ''))
}
const typeVale = mimeTypeMap[type] || type
const blob = new Blob([res], { typeVale })
if ('download' in document.createElement('a')) {
const link = document.createElement('a')
link.download = name
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
document.body.appendChild(link)
link.click()
URL.revokeObjectURL(link.href)
document.body.removeChild(link)
} else {
navigator.msSaveBlob(blob, name)
}
}
银行卡手机号添加空格
// 银行卡号
// 添加空格
card.replace(/\s/g, '').replace(/[^\d]/g, '').replace(/(\d{4})(?=\d)/g, '$1 ');
// 取消空格
card.replace(/[, ]/g,'')
// 手机号
// 添加空格
phone.replace(/\D/g,'').replace(/^/,'$& ').replace(/....(?!$)/g,'$& ')
地球坐标转高德坐标
const PI = 3.1415926535897932384626;
const a = 6378245.0;
const ee = 0.00669342162296594323;
function transformLat(lng, lat) {
let ret =
-100.0 +
2.0 * lng +
3.0 * lat +
0.2 * lat * lat +
0.1 * lng * lat +
0.2 * Math.sqrt(Math.abs(lng));
ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0;
ret += ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 3.0;
ret += ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) * 2.0) / 3.0;
return ret;
}
function transformLng(lng, lat) {
let ret =
300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0;
ret += ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 3.0;
ret += ((150.0 * Math.sin((lng / 12.0) * PI) + 300.0 * Math.sin((lng / 30.0) * PI)) * 2.0) / 3.0;
return ret;
}
function outOfChina(lng, lat) {
return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271 || false;
}
export default function (lng, lat) {
if (outOfChina(lng, lat)) {
return [lng, lat];
} else {
let dlat = transformLat(lng - 105.0, lat - 35.0);
let dlng = transformLng(lng - 105.0, lat - 35.0);
const radlat = (lat / 180.0) * PI;
let magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
const sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
const mglat = lat + dlat;
const mglng = lng + dlng;
return [+mglng.toFixed(6), +mglat.toFixed(6)];
}
}
// 使用
import wgs84ToGCJ02 from '/@/utils/map/wgs84ToGCJ02';
const [longitude, latitude] = wgs84ToGCJ02(+item.longitude, +item.latitude);
div获取焦点和失去焦点问题
默认情况下 div 标签是没有获得焦点 focus() 和失去焦点 blur() 事件的。
如果想要 div 可以拥有这两个事件,可以给 div 标签加上 tabindex="-1" 属性,如下:
<div tabindex="-1">...</div>
这样就可以给 div 加上焦点事件了。
同理,利用tabindex="-1" 也可以给其他不支持焦点事件的标签添加焦点事件。