设备、浏览器
url
根据name获取url参数
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
获取URL参数列表
export const GetRequest = () => {
let url = location.search;
const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来
const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中
let paramsObj = {};
// 将 params 存到对象中
paramsArr.forEach(param => {
if (/=/.test(param)) { // 处理有 value 的参数
let [key, val] = param.split('='); // 分割 key 和 value
val = decodeURIComponent(val); // 解码
val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字
if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则添加一个值
paramsObj[key] = [].concat(paramsObj[key], val);
} else { // 如果对象没有这个 key,创建 key 并设置值
paramsObj[key] = val;
}
} else { // 处理没有 value 的参数
paramsObj[param] = true;
}
})
return paramsObj;
};
检测URL是否有效
export const getUrlState = (URL) => {
let xmlhttp = new ActiveXObject("microsoft.xmlhttp");
xmlhttp.Open("GET", URL, false);
try {
xmlhttp.Send();
} catch (e) {
} finally {
let result = xmlhttp.responseText;
if (result) {
if (xmlhttp.Status == 200) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
键值对拼接成URL参数
export const params2Url = (obj) => {
let params = []
for (let key in obj) {
params.push(`${key}=${obj[key]}`);
}
return encodeURIComponent(params.join('&'))
}
修改URL中的参数
export const replaceParamVal => (paramName, replaceWith) {
const oUrl = location.href.toString();
const re = eval('/('+ paramName+'=)([^&]*)/gi');
location.href = oUrl.replace(re,paramName+'='+replaceWith);
return location.href;
}
删除URL中指定参数
export const funcUrlDel = (name) => {
const baseUrl = location.origin + location.pathname + "?";
const query = location.search.substr(1);
if (query.indexOf(name) > -1) {
const obj = {};
const arr = query.split("&");
for (let i = 0; i < arr.length; i++) {
arr[i] = arr[i].split("=");
obj[arr[i][0]] = arr[i][1];
}
delete obj[name];
return baseUrl + JSON.stringify(obj).replace(/[\"\{\}]/g,"").replace(/\:/g,"=").replace(/\,/g,"&");
}
}
窗口
刘海屏安全距离解决方案
在 iOS11 新增特性中,Webkit 包含了两个新的函数 env() 和 constant(),以及四个预定义的常量:
safe-area-inset-top:安全区域距离顶部边界距离,状态栏+导航栏大约为88px。safe-area-inset-left:安全区域距离左边边界距离,竖屏时为0。safe-area-inset-right:安全区域距离右边边界距离,竖屏时为0。safe-area-inset-bottom:安全区域距离底部边界距离,大约高度为34px。
我们可以这样子使用它们:
/*注意:constant必须写在前面,env写在后面。*/
body{
/* 兼容 iOS < 11.2 */
padding-top: constant(safe-area-inset-top);
padding-left: constant(safe-area-inset-left);
padding-right: constant(safe-area-inset-right);
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 iOS >= 11.2 */
padding-top: env(safe-area-inset-top);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
}
// 当然,你也可以在某个固定(fixed)在底部的元素上单独使用
div{
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
滚动到页面顶部
export const scrollToTop = () => {
const height = document.documentElement.scrollTop || document.body.scrollTop;
if (height > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, height - height / 8);
}
}
滚动到页面底部
export const scrollToBottom = () => {
window.scrollTo(0, document.documentElement.clientHeight);
}
滚动到指定元素区域
export const smoothScroll = (element) => {
document.querySelector(element).scrollIntoView({
behavior: 'smooth'
});
};
获取可视窗口高度
export const getClientHeight = () => {
let clientHeight = 0;
if (document.body.clientHeight && document.documentElement.clientHeight) {
clientHeight = (document.body.clientHeight < document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
}
else {
clientHeight = (document.body.clientHeight > document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
}
return clientHeight;
}
获取可视窗口宽度
export const getPageViewWidth = () => {
return (document.compatMode == "BackCompat" ? document.body : document.documentElement).clientWidth;
}
打开浏览器全屏
export const toFullScreen = () => {
let element = document.body;
if (element.requestFullscreen) {
element.requestFullscreen()
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen()
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen()
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullScreen()
}
}
退出浏览器全屏
export const exitFullscreen = () => {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.msExitFullscreen) {
document.msExitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen()
}
}
滚动窗口回调
export function handleScrollHeader(callback) {
let timer = 0
let beforeScrollTop = window.pageYOffset
callback = callback || function() {}
window.addEventListener(
'scroll',
event => {
clearTimeout(timer)
timer = setTimeout(() => {
let direction = 'up'
const afterScrollTop = window.pageYOffset
const delta = afterScrollTop - beforeScrollTop
if (delta === 0) {
return false
}
direction = delta > 0 ? 'down' : 'up'
callback(direction)
beforeScrollTop = afterScrollTop
}, 50)
},
false
)
}
自动打开新窗口下载
export function download(url: string, name ? : string) {
const a = document.createElement('a');
const isSupportDownload = 'download' in a;
if (isSupportDownload) {
a.href = url;
if (name) {
a.download = name;
}
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
window.open(url);
}
}
判断功能支持
浏览器是否支持全屏 全屏状态
export function supportFullScreen() {
const doc = document.documentElement
return ('requestFullscreen' in doc) ||
('mozRequestFullScreen' in doc && document.mozFullScreenEnabled) ||
('msRequestFullscreen' in doc && document.msFullscreenEnabled) ||
('webkitRequestFullScreen' in doc)
}
export function fullScreenStatus() {
if (document.fullscreen ||
document.mozFullScreen ||
document.fullscreenElement ||
document.msFullscreenElement ||
document.webkitIsFullScreen) {
return true
} else {
return false
}
}
判断环境
获取浏览器型号和版本
export const getExplorerInfo = () => {
let t = navigator.userAgent.toLowerCase();
return 0 <= t.indexOf("msie") ? { //ie < 11
type: "IE",
version: Number(t.match(/msie ([\d]+)/)[1])
} : !!t.match(/trident\/.+?rv:(([\d.]+))/) ? { // ie 11
type: "IE",
version: 11
} : 0 <= t.indexOf("edge") ? {
type: "Edge",
version: Number(t.match(/edge\/([\d]+)/)[1])
} : 0 <= t.indexOf("firefox") ? {
type: "Firefox",
version: Number(t.match(/firefox\/([\d]+)/)[1])
} : 0 <= t.indexOf("chrome") ? {
type: "Chrome",
version: Number(t.match(/chrome\/([\d]+)/)[1])
} : 0 <= t.indexOf("opera") ? {
type: "Opera",
version: Number(t.match(/opera.([\d]+)/)[1])
} : 0 <= t.indexOf("Safari") ? {
type: "Safari",
version: Number(t.match(/version\/([\d]+)/)[1])
} : {
type: t,
version: -1
}
}
判断是移动还是PC设备
export const isMobile = () => {
if ((navigator.userAgent.match(/(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i))) {
return 'mobile';
}
return 'desktop';
}
判断是否是isIE
export function isIE() {
const bw = window.navigator.userAgent
const compare = (s) => bw.indexOf(s) >= 0
const ie11 = (() => 'ActiveXObject' in window)()
return compare('MSIE') || ie11
}
判断是Windows还是Mac系统
export const osType = () => {
const agent = navigator.userAgent.toLowerCase();
const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
const isWindows = agent.indexOf("win64") >= 0 || agent.indexOf("wow64") >= 0 || agent.indexOf("win32") >= 0 || agent.indexOf("wow32") >= 0;
if (isWindows) {
return "windows";
}
if(isMac){
return "mac";
}
}
判断是否是微信/QQ内置浏览器
export const broswer = () => {
const ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
return "weixin";
} else if (ua.match(/QQ/i) == "qq") {
return "QQ";
}
return false;
}
判断是否是苹果还是安卓移动设备
export const isAppleMobileDevice = () => {
let reg = /iphone|ipod|ipad|Macintosh/i;
return reg.test(navigator.userAgent.toLowerCase());
}
分辨率/像素
当前设备分辨率 像素/英寸
/**
* 当前设备分辨率 像素/英寸
* @return {Array}
*/
function getDPI(){
var arrDPI = new Array;
// IE支持此属性
if (window.screen.deviceXDPI) {
arrDPI[0] = window.screen.deviceXDPI;
arrDPI[1] = window.screen.deviceYDPI;
} else {
var tmpNode = document.createElement("DIV");
tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
document.body.appendChild(tmpNode);
arrDPI[0] = parseInt(tmpNode.offsetWidth);
arrDPI[1] = parseInt(tmpNode.offsetHeight);
tmpNode.parentNode.removeChild(tmpNode);
}
return arrDPI;
}
获取A4纸在屏幕中的像素宽高
/**
* 获取A4纸在屏幕中的像素宽高
* @return {Object}
*/
function getA4PixelSize() {
var deviceXDPI = this.getDPI()[0];
var a4_PixelWidth = 210 / 25.4 * deviceXDPI;
var a4_PixelHeight = 297 / 25.4 * deviceXDPI;
return {
width: a4_PixelWidth,
height: a4_PixelHeight
};
}
格式/类型
类型转换\判断
数据类型判断
export const getType = (value) => {
if (value === null) {
return value + "";
}
// 判断数据是引用类型的情况
if (typeof value === "object") {
let valueClass = Object.prototype.toString.call(value),
type = valueClass.split(" ")[1].split("");
type.pop();
return type.join("").toLowerCase();
} else {
// 判断数据是基本数据类型的情况和函数的情况
return typeof value;
}
}
映射表转数组
function mapToArray(map, nameKey = "label", valueKey = "value") {
//缺少一个map为非for循环值的判断
const reval = []
for (const key in map) {
const label = map[key];
reval.push({
[nameKey]: label,
[valueKey]: key,
})
}
return reval
}
blob类型转换到dataURL数据
/**
* blob类型转换到dataURL数据
* @param {Object} blob
* @param {Function} callback 转换完成后回调方法,参数:转换后的结果
*/
blobToDataURL: function(blob, callback) {
var a = new FileReader();
a.onload = function(e) {
callback(e.target.result);
}
a.readAsDataURL(blob);
}
格式/单位转换
转浮点数
/**
* 保留小数位数
* @param value 值
* @param dec 小数位数
* @param divisor 倍数
* @param defaultValue 无数据时返回值
*/
export function fixNumber(value: any, dec = 2, divisor = 1, defaultValue = '--') {
if (isNil(value) || Number.isNaN(+value)) return defaultValue;
return (+value / divisor).toFixed(dec);
}
转百分比
export function fixPercentage(value, dec = 1, defaultValue = '--') {
if (_.isNil(value) || Number.isNaN(+value) || (typeof value === 'string' && value.length === 0)) return defaultValue;
const n = (+value).toFixed(dec);
return `${n}%`;
}
金额逢3逗号切割 例如1, 100, 000.23
/*
* @description: 金额格式化 例如1,100,000.23
* @param: value:金额 dec:小数点后位数
* @author: Waker
*/
amountFormat(value: string | number, dec: number = 0) {
const s = Number(value).toFixed(dec);
const l = s.split(".")[0].split("").reverse()
const r = '.' + s.split(".")[1];
let t = "";
for (let i = 0; i < l.length; i++) {
t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : "");
}
const reStr = dec === 0 ?
t.split("").reverse().join("") :
t.split("").reverse().join("") + r
return reStr;
}
隐私字段用*转换
/*
* @description: 隐私字段用*转换 例如aaaa****bbbb
* @param: value:文本
* @author: Waker
*/
hideString(value, before, after) {
if (!value) {
return;
}
value = String(value);
let beforeStr = value.substr(0, before);
let afterStr = after ? value.substr(-after) : '';
let hideLen = value.length - before - after;
let reVal = beforeStr + '*'.repeat(hideLen) + afterStr;
return reVal; //将格式化后的字符串输出到前端显示
},
格式化银行卡号 目前规则为 4个字符加一个空格
/**
* 格式化银行卡号 目前规则为 4个字符加一个空格
*
* @param bankCardCode 银行卡号
*/
function fomartBankCardCode(bankCardCode) {
//遍历账户
let spaceStr = "";
for (let i = 0, len = bankCardCode.length; i < len; i++) {
//每4个字符加一个空格
if (i % 4 === 0) {
spaceStr += " " + bankCardCode[i];
} else {
spaceStr += bankCardCode[i];
}
}
return spaceStr;
}
金额转大写
/**
* 毫秒转 天时分秒
* @param mss
* @return {string}
*/
function changeMoneyToChinese(n) {
var fraction = ['角', '分'];
var digit = [
'零', '壹', '贰', '叁', '肆',
'伍', '陆', '柒', '捌', '玖'
];
var unit = [
['元', '万', '亿'],
['', '拾', '佰', '仟']
];
var head = n < 0 ? '欠' : '';
n = Math.abs(n);
var s = '';
for (var i = 0; i < fraction.length; i++) {
s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');
}
s = s || '整';
n = Math.floor(n);
for (var i = 0; i < unit[0].length && n > 0; i++) {
var p = '';
for (var j = 0; j < unit[1].length && n > 0; j++) {
p = digit[n % 10] + unit[1][j] + p;
n = Math.floor(n / 10);
}
s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
}
return head + s.replace(/(零.)*零元/, '元')
.replace(/(零.)+/g, '零')
.replace(/^整$/, '零元整');
}
数字转化为中文数字
export const intToChinese = (value) => {
const str = String(value);
const len = str.length-1;
const idxs = ['','十','百','千','万','十','百','千','亿','十','百','千','万','十','百','千','亿'];
const num = ['零','一','二','三','四','五','六','七','八','九'];
return str.replace(/([1-9]|0+)/g, ( $, $1, idx, full) => {
let pos = 0;
if($1[0] !== '0'){
pos = len-idx;
if(idx == 0 && $1[0] == 1 && idxs[len-idx] == '十'){
return idxs[len-idx];
}
return num[$1[0]] + idxs[len-idx];
} else {
let left = len - idx;
let right = len - idx + $1.length;
if(Math.floor(right / 4) - Math.floor(left / 4) > 0){
pos = left - left % 4;
}
if( pos ){
return idxs[pos] + num[$1[0]];
} else if( idx + $1.length >= len ){
return '';
}else {
return num[$1[0]]
}
}
});
}
金额单位转成:元/万元/亿元等
/**
* 金额格式化方法 只有万元
* @param {*} value //要格式化的值
* @param {*} pos //小数点位数
*/
export function numberFormat(value, k = 10000) {
if (!value) {
return {
value: 0,
unit: '元',
}
}
var param = {}
var sizes = ['元', '万元', '亿元', '万亿元']
if (value < k) {
param.value = toFixed(value)
param.unit = '元'
} else {
let i = Math.floor(Math.log(value) / Math.log(k))
param.value = ((value / Math.pow(k, i))).toFixed(2)
param.unit = sizes[i]
}
return param
}
空间/坐标/地理操作
反查省市区
//反查省市区
reAreaCode(val) {
if (!val) {
return;
}
let a = val.slice(0, 2) + '0000';
let b = val.slice(0, 4) + '00';
let c = val;
let code;
// a === '820000' ? code = [a, c] : code = [a, b, c];
return [a, b, c];
},
已知两点坐标, 求中心点垂直线的顶点坐标(常用来做贝塞尔曲线的顶点)
function computedP3(p1, p2) {
// 短轴半径
const P1X = p1[0];
const P1Y = p1[1];
const P2X = p2[0];
const P2Y = p2[1];
// n为垂直线到顶点的距离 0.3为系数,可修改,系数越大贝塞尔曲线的弧度越大
const n = Math.sqrt(Math.pow((P2X - P1X), 2) + Math.pow((P2Y - P1Y), 2)) * 0.3;
// tan角度
const TANangle = (P1X - P2X) / (P2Y - P1Y);
// 计算点 相对中心点的高度
const Fed = Math.sqrt(Math.pow(TANangle, 2) / (Math.pow(TANangle, 2) + 1)) * n;
const Fec = Math.sqrt(1 / (Math.pow(TANangle, 2) + 1)) * n;
let P3X = ((P1X + P2X) / 2) + Fec;
let P3Y = ((P1Y + P2Y) / 2) + Fed;
return [P3X, P3Y];
}
判断坐标范围是否超出中国范围
/**
* 判断坐标范围是否超出中国范围
*
* @param {Number} lon 经度
* @param {Number} lat 纬度
*
* @return {Boolean}
*/
outOfChina: function(lon, lat) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
},
地理坐标系转换
/**
* wgs84坐标转火星坐标(偏差坐标)
* @param {float} wgLon wgs经度
* @param {float} wgLat wgs纬度
* @return {Array} 加了偏差后的坐标
*/
convertLonLatToGCJ: function(wgLon, wgLat) {
var a = 6378245.0;
var ee = 0.00669342162296594323;
var mgLat, mgLon;
if (util.outOfChina(wgLon, wgLat)) {
mgLon = wgLon;
mgLat = wgLat;
return;
}
var dLat = util.transformLat(wgLon - 105.0, wgLat - 35.0);
var dLon = util.transformLon(wgLon - 105.0, wgLat - 35.0);
var radLat = wgLat / 180.0 * Math.PI;
var magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
var sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI);
mgLat = wgLat + dLat;
mgLon = wgLon + dLon;
return [mgLon, mgLat];
},
/**
* 墨卡托坐标转纬度函数
* @param {Number} x 横坐标
* @param {Number} y 纵坐标
* @return {Number} 纬度
*/
transformLat: function(x, y) {
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
return ret;
},
/**
* 墨卡托坐标转经度函数
* @param {Number} x 横坐标
* @param {Number} y 纵坐标
* @return {Number} 经度
*/
transformLon: function(x, y) {
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
return ret;
},
cookie\存储操作
获取cookie
// 获取cookie
export function getCookie(cname) {
var name = cname + '='
var decodedCookie = decodeURIComponent(document.cookie)
var ca = decodedCookie.split(';')
for (var i = 0; i < ca.length; i++) {
var c = ca[i]
while (c.charAt(0) === ' ') {
c = c.substring(1)
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length)
}
}
return ''
}
存储loalStorage
export const loalStorageSet = (key, value) => {
if (!key) return;
if (typeof value !== 'string') {
value = JSON.stringify(value);
}
window.localStorage.setItem(key, value);
};
时间操作
时长转换单位
/**
* @description: 时长转换单位
* @param: preUnit,afterUnit =>moment时长单位 seconds,minutes,hours,days,weeks,months,years
* @author: Waker
*/
export function durationUnitChange(time, preUnit, afterUnit) {
const map = {
years: '年',
months: '月',
days: '日',
hours: '时',
minutes: '分',
seconds: '秒'
}
const momentDuration = moment.duration(time, preUnit)._data
let formatTime = '';
for (const key in map) {
const unit = map[key];
const time = momentDuration[key];
if (time > 0) {
formatTime = formatTime + time + unit
}
}
return formatTime
}
获取下个制定周几的日期
/**
* @description: 计算下个入职日期
* @param: 每周二、四是入职日
* @author: Waker
@use: joinDay('2021-02-27')
*/
function joinDay(date?: any) {
// 获取日期是星期几
const week = computedWeekDay({ date: date })
const weekDate: any = {
1: computedWeekDay({ date, weekDay: 2 }),
2: computedWeekDay({ date, weekDay: 4 }),
3: computedWeekDay({ date, weekDay: 4 }),
4: computedWeekDay({ date, weekDay: 9 }),
5: computedWeekDay({ date, weekDay: 9 }), //2+7 9为下个星期2
6: computedWeekDay({ date, weekDay: 9 }),
7: computedWeekDay({ date, weekDay: 9 }),
}
console.log(weekDate[week]);
return weekDate[week]
}
设置|获取日期的周几
/**
* @description: 设置|获取日期的周几
* @param: date:日期(空为当天),weekDay:日期当前周的星期几
* @author: Waker
*/
function computedWeekDay({ date, weekDay }: any) {
// 有weekDay表示想获取日期的所在周的某天日期
if (weekDay) {
return moment(date).day(weekDay).format('YYYY-MM-DD')
}
return moment(date).day()
}
当前时间
export const nowTime = () => {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth();
const date = now.getDate() >= 10 ? now.getDate() : ('0' + now.getDate());
const hour = now.getHours() >= 10 ? now.getHours() : ('0' + now.getHours());
const miu = now.getMinutes() >= 10 ? now.getMinutes() : ('0' + now.getMinutes());
const sec = now.getSeconds() >= 10 ? now.getSeconds() : ('0' + now.getSeconds());
return +year + "年" + (month + 1) + "月" + date + "日 " + hour + ":" + miu + ":" + sec;
}
格式化时间
export const dateFormater = (formater, time) => {
let date = time ? new Date(time) : new Date(),
Y = date.getFullYear() + '',
M = date.getMonth() + 1,
D = date.getDate(),
H = date.getHours(),
m = date.getMinutes(),
s = date.getSeconds();
return formater.replace(/YYYY|yyyy/g, Y)
.replace(/YY|yy/g, Y.substr(2, 2))
.replace(/MM/g,(M<10 ? '0' : '') + M)
.replace(/DD/g,(D<10 ? '0' : '') + D)
.replace(/HH|hh/g,(H<10 ? '0' : '') + H)
.replace(/mm/g,(m<10 ? '0' : '') + m)
.replace(/ss/g,(s<10 ? '0' : '') + s)
}
// dateFormater('YYYY-MM-DD HH:mm:ss')
// dateFormater('YYYYMMDDHHmmss')
时间段重合
/**
* 判断是否有重叠的日期区间 如果想确定时间区间请在传来的数据前加上一个固定日期如'1970-01-01 00:00' -- wangwei
* @param timeList 日期区域
* @param mateTimeArr 匹配日期区域集合
*/
export function isTimeOver(timeList: any[], timeArr: any[], type = 'day') {
if (!timeArr || timeArr.length === 0) {
return false
}
if (type === 'time') {
timeList = timeList.map((item) => {
return moment(item, 'HH:mm')
})
timeArr = timeArr.map(item => {
return [moment(item[0], 'HH:mm'), moment(item[1], 'HH:mm')]
});
}
for (let i = 0; i < timeArr.length; i++) {
const item = timeArr[i];
if (moment(timeList[0]).isBetween(item[0], item[1]) || moment(timeList[1]).isBetween(item[0], item[1])) {
return true
} else {
// 在匹配的左边 或者 右边
if (!(moment(timeList[0]).isSameOrBefore(item[0]) && moment(timeList[1]).isSameOrBefore(item[0])) &&
!(moment(timeList[0]).isSameOrAfter(item[1]) && moment(timeList[1]).isSameOrAfter(item[1]))) {
return true
}
}
}
}
数据/值操作
数组操作
数组乱序
export const arrScrambling = (arr) => {
for (let i = 0; i < arr.length; i++) {
const randomIndex = Math.round(Math.random() * (arr.length - 1 - i)) + i;
[arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];
}
return arr;
}
扁平化数组
/**
* @description: 扁平化数组
* @param: value:值
* @author: Waker
*/
function flatArray(array: any[], childrenKey = "children", _level = 0) {
_level = _level + 1
return array.reduce((total: any[], item: any) => {
total.push({
...item,
_level,
})
// 是否有子菜单,并递归处理
if (item[childrenKey]?.length > 0) {
total.push(...flatArray(item[childrenKey], childrenKey, _level))
}
return total
}, [])
}
扁平化树=>匹配option的字段
/**
* @description: 根据option扁平化树
* @param: data:array=数据,childrenKey=子节点的key,option:string[]=需要导出的字段集合
* @author: Waker
*/
function flatArrayToOption({ data, childrenKey = "children", options }: any) {
return data.reduce((total: any[], item: any) => {
const it: any = {}
options.forEach((key: any) => {
it[key] = item[key]
});
total.push(it)
// 是否有子菜单,并递归处理
if (item[childrenKey]?.length > 0) {
total.push(...flatArrayToOption({ data: item[childrenKey], options }))
}
return total
}, [])
}
将树的某个key组成数组取出,可过滤
/**
* @description: 将树的某个key组成数组取出
* @param: data:array=数据,childrenKey=子节点的key,key:string=需要取出的key,filterMethod:Boolean = 过滤方法,返回假值会过滤掉
* @author: Waker
*/
function flatArrayToKey({ data, childrenKey = "children", key, filterMethod }: any) {
return data.reduce((total: any[], item: any) => {
// 是否有过滤条件
if (filterMethod) {
if (typeof (filterMethod) !== 'function') {
throw 'filterMethod必须是个函数'
}
const isOK = filterMethod(item)
if (isOK) {
total.push(item[key])
}
} else {
total.push(item[key])
}
// 是否有子菜单,并递归处理
if (item[childrenKey]?.length > 0) {
total.push(...flatArrayToKey({ data: item[childrenKey], key, filterMethod }))
}
return total
}, [])
}
对象操作
import { isEmpty, get } from 'lodash';
/**
* @description: 路径取值: 空值、空对象、空集合,空映射或者set 返回默认值
* @param: ob:对象,路径:在ob内的路径,例子:'a[0].b.c',defaultVal:默认值
* @author: Waker
*/
function readProp(ob: any, path: string, defaultVal: any = '') {
const value = get(ob, path);
return emptyDefault(value, defaultVal)
}
/**
* @description: 空值默认 : 空值、空对象、空集合,空映射或者set 返回默认值
* @param: value:值,defaultVal:默认值
* @author: Waker
*/
function emptyDefault(value: any, defaultVal: any = '') {
// 空值
if (!value && value !== 0) return defaultVal;
// 空对象、空集合,空映射或者set
if (value instanceof Object && isEmpty(value)) return defaultVal;
return value
}
字符串操作
字符串首字母大写
export const fistLetterUpper = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
驼峰命名转换成短横线命名
export const getKebabCase = (str) => {
return str.replace(/[A-Z]/g, (item) => '-' + item.toLowerCase())
}
短横线命名转换成驼峰命名
export const getCamelCase = (str) => {
return str.replace( /-([a-z])/g, (i, item) => item.toUpperCase())
}
全角转换为半角
export const toCDB = (str) => {
let result = "";
for (let i = 0; i < str.length; i++) {
code = str.charCodeAt(i);
if (code >= 65281 && code <= 65374) {
result += String.fromCharCode(str.charCodeAt(i) - 65248);
} else if (code == 12288) {
result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32);
} else {
result += str.charAt(i);
}
}
return result;
}
半角转换为全角
export const toDBC = (str) => {
let result = "";
for (let i = 0; i < str.length; i++) {
code = str.charCodeAt(i);
if (code >= 33 && code <= 126) {
result += String.fromCharCode(str.charCodeAt(i) + 65248);
} else if (code == 32) {
result += String.fromCharCode(str.charCodeAt(i) + 12288 - 32);
} else {
result += str.charAt(i);
}
}
return result;
}
随机数生成
export const randomNum = (start, end, dec = 2) => +(start + (Math.random() * (end - start))).toFixed(dec);
图片
/**
* @description: 校验图片尺寸
* @param:
* @author: Waker
*/
function validateImageSize({ file, width, height }: any) {
if (!file|| !height || !width) {
console.error('校验图片尺寸时,文件、宽、高必填');
return file;
}
return new Promise(function (resolve, reject) {
const _URL = window.URL || window.webkitURL;
const image = new Image();
image.onload = function () {
const valid = image.width == width && image.height == height;
valid ? resolve(valid) : reject();
};
image.src = _URL.createObjectURL(file);
})
.then(() => {
return file;
})
.catch(() => {
return Promise.reject(`上传图片尺寸必须为800*800`);
});
}
数组操作
vue专属
跳转锚点与路由冲突
/**
* @description: 跳转锚点与路由冲突
* @param:
* @author: Waker
*/
skipModel(id: string) {
const dom: any = document.querySelector("#" + id);
dom.scrollIntoView({ behavior: "smooth" });
}