// 本文件由FirstUI授权予四川政采招投标咨询有限公司(会员ID:16 3,营业执照号: 9 1 5 1 01313 3200 6 1 93 K)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
/*!
|
* 工具类:常用数据处理工具
|
* Utils - v1.0.0 (2021/7/9, 11:07:14 AM)
|
* https://github.com/FirstUI/FirstUI | Released under Apache License 2.0
|
*
|
* 官网地址:https://firstui.cn/
|
* 文档地址:https://doc.firstui.cn/
|
*/
|
|
const utils = {
|
/**
|
* @desc 英文首字母大写:english=>English
|
* @param {String} value 需要处理的英文字符串
|
**/
|
titleCase(value) {
|
if (value == null || value.length === 0) return value;
|
return value.replace(/^[a-z]/, (matchStr) => {
|
return matchStr.toLocaleUpperCase();
|
});
|
},
|
/**
|
* 把连续出现多次的字母字符串进行压缩。aaabbbbcccccd=>3a4b5cd
|
* @param {String} value 需要压缩的字符串
|
* @param {Boolean} ignoreCase 是否忽略大小写
|
*/
|
compressLetter(value, ignoreCase) {
|
let pattern = new RegExp("([a-zA-Z])\\1+", ignoreCase ? "ig" : "g");
|
|
return value.replace(pattern, (matchStr, group_1) => {
|
return matchStr.length + group_1;
|
});
|
},
|
/**
|
* @desc 等待多少毫秒再执行 ,同步阻塞
|
* @param {String} millisecond 毫秒
|
**/
|
sleep(millisecond) {
|
let now = new Date();
|
let exitTime = now.getTime() + millisecond;
|
while (true) {
|
now = new Date();
|
if (now.getTime() > exitTime) return;
|
}
|
},
|
/**
|
* @desc 去左右空格
|
* @param {String} value 需要处理的字符串
|
**/
|
trim(value) {
|
return value.replace(/(^\s*)|(\s*$)/g, "");
|
},
|
/**
|
* @desc 去所有空格
|
* @param {String} value 需要处理的字符串
|
**/
|
trimAll(value) {
|
return value.replace(/\s+/g, "")
|
},
|
/**
|
* @desc 替换所有相同字符串
|
* @param {String} text 需要处理的字符串
|
* @param {String} repstr 被替换的字符
|
* @param {String} newstr 替换后的字符
|
**/
|
replaceAll(text, repstr, newstr) {
|
return text.replace(new RegExp(repstr, "gm"), newstr);
|
},
|
/**
|
* @desc 格式化手机号码
|
* @param {String} num 手机号码
|
**/
|
numberFormatter(num) {
|
return num.length === 11 ? num.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') : num;
|
},
|
/**
|
* @desc 金额格式化,保留两位小数
|
* @param {String | Number} money 金额值
|
**/
|
moneyFormatter(money) {
|
return parseFloat(money).toFixed(2).toString().split('').reverse().join('').replace(/(\d{3})/g, '$1,')
|
.replace(
|
/\,$/, '').split('').reverse().join('');
|
},
|
/**
|
* @desc 日期时间格式化
|
* @param date 需要格式化的日期
|
* @param format 格式化字符串(y-m-d h:i:s)
|
* @param type date的格式类型:1-日期字符串(2017/12/04 12:12:12) 2-时间戳(1603676514690) 3-日期字符串,无连接符(20171204121212)
|
* 4-new Date()时间格式(Thu Oct 01 2020 00:00:00 GMT+0800 (中国标准时间))
|
* @param isMs 时间戳精度是否为毫秒,默认为true(当精度为秒时传false),type=2时有效
|
**/
|
dateFormatter(date, format, type = 1, isMs = true) {
|
let formatDate = ""
|
if (type === 3) {
|
formatDate = utils._formatTimeStr(date, format)
|
} else {
|
formatDate = utils._formatDate(format, date, type, isMs)
|
}
|
return formatDate;
|
},
|
_formatDate(formatStr, fdate, type = 1, isMs) {
|
if (!fdate) return '';
|
let fTime, fStr = 'ymdhis';
|
if (type === 4) {
|
fTime = fdate;
|
} else {
|
fdate = fdate.toString()
|
if (~fdate.indexOf('.')) {
|
fdate = fdate.substring(0, fdate.indexOf('.'));
|
}
|
fdate = fdate.replace('T', ' ').replace(/\-/g, '/');
|
if (!formatStr)
|
formatStr = "y-m-d h:i:s";
|
if (fdate) {
|
if (type === 2) {
|
fdate = isMs ? Number(fdate) : Number(fdate) * 1000
|
}
|
fTime = new Date(fdate);
|
} else {
|
fTime = new Date();
|
}
|
}
|
let month = fTime.getMonth() + 1;
|
let day = fTime.getDate();
|
let hours = fTime.getHours();
|
let minu = fTime.getMinutes();
|
let second = fTime.getSeconds();
|
month = month < 10 ? '0' + month : month;
|
day = day < 10 ? '0' + day : day;
|
hours = hours < 10 ? ('0' + hours) : hours;
|
minu = minu < 10 ? '0' + minu : minu;
|
second = second < 10 ? '0' + second : second;
|
let formatArr = [
|
fTime.getFullYear().toString(),
|
month.toString(),
|
day.toString(),
|
hours.toString(),
|
minu.toString(),
|
second.toString()
|
]
|
for (let i = 0; i < formatArr.length; i++) {
|
formatStr = formatStr.replace(fStr.charAt(i), formatArr[i]);
|
}
|
return formatStr;
|
},
|
/**
|
* @desc 格式化时间
|
* @param timeStr 时间字符串 20191212162001
|
* @param formatStr 需要的格式 如 y-m-d h:i:s | y/m/d h:i:s | y/m/d | y年m月d日 等
|
**/
|
_formatTimeStr(timeStr, formatStr) {
|
if (!timeStr) return;
|
timeStr = timeStr.toString()
|
if (timeStr.length === 14) {
|
let timeArr = timeStr.split('')
|
let fStr = 'ymdhis'
|
if (!formatStr) {
|
formatStr = 'y-m-d h:i:s'
|
}
|
let formatArr = [
|
[...timeArr].splice(0, 4).join(''),
|
[...timeArr].splice(4, 2).join(''),
|
[...timeArr].splice(6, 2).join(''),
|
[...timeArr].splice(8, 2).join(''),
|
[...timeArr].splice(10, 2).join(''),
|
[...timeArr].splice(12, 2).join('')
|
]
|
for (let i = 0; i < formatArr.length; i++) {
|
formatStr = formatStr.replace(fStr.charAt(i), formatArr[i])
|
}
|
return formatStr
|
}
|
return timeStr
|
},
|
/**
|
* @desc RGB颜色转十六进制颜色
|
* @param r
|
* @param g
|
* @param b
|
**/
|
rgbToHex(r, g, b) {
|
return "#" + utils._toHex(r) + utils._toHex(g) + utils._toHex(b)
|
},
|
_toHex(n) {
|
n = parseInt(n, 10);
|
if (isNaN(n)) return "00";
|
n = Math.max(0, Math.min(n, 255));
|
return "0123456789ABCDEF".charAt((n - n % 16) / 16) +
|
"0123456789ABCDEF".charAt(n % 16);
|
},
|
/**
|
* @desc 十六进制颜色转RGB颜色
|
* @param hex 颜色值 #333 或 #333333
|
**/
|
hexToRGB(hex) {
|
if (hex.length === 4) {
|
let text = hex.substring(1, 4);
|
hex = '#' + text + text;
|
}
|
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
return result ? {
|
r: parseInt(result[1], 16),
|
g: parseInt(result[2], 16),
|
b: parseInt(result[3], 16)
|
} : null;
|
},
|
/**
|
* @desc 唯一标识,随机数
|
* @param n 随机数位数
|
**/
|
unique(n) {
|
n = n || 6;
|
let rnd = '';
|
for (let i = 0; i < n; i++)
|
rnd += Math.floor(Math.random() * 10);
|
return 'firstui_' + new Date().getTime() + rnd;
|
},
|
/**
|
* @desc 获取uuid
|
*/
|
getUUID() {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
|
})
|
},
|
/**
|
* @desc 简单数组合并去重
|
* @param arr1 数组1
|
* @param arr2 数组2 可不传
|
**/
|
distinctArray(arr1, arr2) {
|
arr1 = arr1 || []
|
arr2 = arr2 || []
|
return [...new Set([...arr1, ...arr2])]
|
},
|
|
/**
|
* @desc 获取日期时间段
|
* @param type 1-今天 2-昨天 3-本周 4-本月 5-本年
|
**/
|
getDateTimeSlot(type) {
|
let now = new Date()
|
let start = now.toDateString()
|
let end = now.toDateString()
|
switch (type) {
|
case 1:
|
start = `${start} 00:00:00`
|
end = `${end} 23:59:59`
|
break
|
case 2:
|
now.setTime(now.getTime() - 3600 * 1000 * 24 * 1)
|
start = `${now.toDateString()} 00:00:00`
|
end = `${now.toDateString()} 23:59:59`
|
break
|
case 3:
|
// 获取星期几,getDay()返回值是 0(周日) 到 6(周六) 之间的一个整数。0||7为7,即weekday的值为1-7
|
let weekday = now.getDay() || 7
|
// 往前算(weekday-1)天,年份、月份会自动变化
|
now.setDate(now.getDate() - weekday + 1)
|
start = `${now.toDateString()} 00:00:00`
|
end = `${end} 23:59:59`
|
break
|
case 4:
|
start = `${now.getFullYear()}-${now.getMonth() + 1}-01 00:00:00`
|
end = `${end} 23:59:59`
|
break
|
case 5:
|
start = `${now.getFullYear()}-01-01 00:00:00`
|
end = `${end} 23:59:59`
|
break
|
default:
|
break
|
}
|
|
return {
|
start: new Date(start.replace(/\-/g, '/')),
|
end: new Date(end.replace(/\-/g, '/'))
|
}
|
},
|
/*
|
* @desc 获取Url参数,返回一个对象
|
* @param url url地址
|
* ?a=1&b=2 ==> {a: "1", b: "2"}
|
*/
|
getUrlParam(url) {
|
let arrObj = url.split("?");
|
let params = {};
|
if (arrObj.length > 1) {
|
arrObj = arrObj[1].split("&");
|
arrObj.forEach(item => {
|
item = item.split("=");
|
params[item[0]] = item[1];
|
})
|
}
|
return params;
|
},
|
/**
|
* @method 函数防抖
|
* @desc 短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行。
|
* @param func 目标函数
|
* @param wait 延迟执行毫秒数
|
* @param immediate true - 立即执行, false - 延迟执行
|
*/
|
debounce(func, wait = 1000, immediate = true) {
|
let timer;
|
return function() {
|
let context = this,
|
args = arguments;
|
if (timer) clearTimeout(timer);
|
if (immediate) {
|
let callNow = !timer;
|
timer = setTimeout(() => {
|
timer = null;
|
}, wait);
|
if (callNow) func.apply(context, args);
|
} else {
|
timer = setTimeout(() => {
|
func.apply(context, args);
|
}, wait)
|
}
|
}
|
},
|
/**
|
* @method 函数节流
|
* @desc 指连续触发事件,但是在 n 秒内只执行一次函数。即 2n 秒内执行 2 次... 。会稀释函数的执行频率。
|
* @param func 函数
|
* @param wait 延迟执行毫秒数
|
* @param type 1 在时间段开始的时候触发 2 在时间段结束的时候触发
|
*/
|
throttle(func, wait = 1000, type = 1) {
|
let previous = 0;
|
let timeout;
|
return function() {
|
let context = this;
|
let args = arguments;
|
if (type === 1) {
|
let now = Date.now();
|
if (now - previous > wait) {
|
func.apply(context, args);
|
previous = now;
|
}
|
} else if (type === 2) {
|
if (!timeout) {
|
timeout = setTimeout(() => {
|
timeout = null;
|
func.apply(context, args)
|
}, wait)
|
}
|
}
|
}
|
},
|
/**
|
* @desc 日期时间格式化为多久之前 如:1分钟前
|
* @param date 需要格式化的日期
|
* @param type date的格式类型:1-日期字符串(2017/12/04 12:12:12) 2-时间戳(1603676514690) 3-日期字符串,无连接符(20171204121212)
|
* 4-new Date()时间格式(Thu Oct 01 2020 00:00:00 GMT+0800 (中国标准时间))
|
* @param isMs 时间戳精度是否为毫秒,默认为true(当精度为秒时传false),type=2时有效
|
* @param suffix 后缀,如:30小时+ 后缀。[刚刚、昨天、前天 等为固定文本,后缀无效]
|
* @param endUnit 转化截止单位,1-秒 2-分钟 3-小时 4-天 5-月 6-年,如传3(小时),则天,月,年不做转化直接返回空
|
* @param seconds 多少秒之前显示为刚刚,不可超过60
|
* @param fixedDay 是否需要天的固定文本,如昨天、前天
|
**/
|
formatTimeAgo(date, type = 1, isMs = true, suffix = '前', endUnit = 6, seconds = 10, fixedDay = true) {
|
const formatDate = utils.dateFormatter(date, 'y/m/d h:i:s', type, isMs)
|
const beforeStamp = new Date(formatDate).getTime()
|
const nowStamp = new Date().getTime();
|
let res = ''
|
const diff = nowStamp - beforeStamp
|
if (diff > 0) {
|
const _minute = 1000 * 60;
|
const _hour = _minute * 60;
|
const _day = _hour * 24;
|
//不精确
|
const _month = _day * 30
|
const _year = _month * 12
|
|
const year = Math.floor(diff / _year)
|
const month = Math.floor(diff / _month)
|
const day = Math.floor(diff / _day)
|
const hour = Math.floor(diff / _hour)
|
const minute = Math.floor(diff / _minute)
|
const second = Math.floor(diff / 1000)
|
let isEmpty = false
|
switch (endUnit) {
|
case 1:
|
isEmpty = (minute || hour || day || month || year) ? true : false
|
break;
|
case 2:
|
isEmpty = (hour || day || month || year) ? true : false
|
break;
|
case 3:
|
isEmpty = (day || month || year) ? true : false
|
break;
|
case 4:
|
isEmpty = (month || year) ? true : false
|
break;
|
case 5:
|
isEmpty = year ? true : false
|
break;
|
default:
|
break;
|
}
|
|
if (!isEmpty) {
|
if (year) {
|
res = `${year}年${suffix}`
|
} else if (month) {
|
res = `${month}个月${suffix}`
|
} else if (day) {
|
if (day === 1 && fixedDay) {
|
//1天前
|
res = "昨天";
|
} else if (day === 2 && fixedDay) {
|
//2天前
|
res = "前天";
|
} else {
|
res = `${day}天${suffix}`
|
}
|
} else if (hour) {
|
res = `${hour}小时${suffix}`
|
} else if (minute) {
|
res = `${minute}分钟${suffix}`
|
} else {
|
seconds = seconds < 60 ? seconds : 59;
|
res = second < seconds ? '刚刚' : `${second}秒${suffix}`
|
}
|
}
|
}
|
return res
|
},
|
/**
|
* @description 获取随机颜色
|
**/
|
getRandomHexColor() {
|
// return `#${Math.floor(Math.random() * 0xffffff).toString(16)}`
|
const arr = ['0', '1', '2', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
|
const a = Math.floor(Math.random() * arr.length);
|
const b = Math.floor(Math.random() * arr.length);
|
const c = Math.floor(Math.random() * arr.length);
|
const d = Math.floor(Math.random() * arr.length);
|
const e = Math.floor(Math.random() * arr.length);
|
const f = Math.floor(Math.random() * arr.length);
|
return `#${arr[a] + arr[b] + arr[c] + arr[d] + arr[e] + arr[f]}`
|
},
|
/**
|
* @description 人名币转大写
|
* @param {Number | String} money 金额
|
**/
|
convertCurrency(money) {
|
const amount = utils.trimAll(money.toString()).replace('¥', '').replace(',', '');
|
if (amount == '') return '';
|
const cny = parseFloat(amount)
|
//汉字的数字
|
const cnNums = new Array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
|
//基本单位
|
const cnIntRadice = new Array('', '拾', '佰', '仟');
|
//对应整数部分扩展单位
|
const cnIntUnits = new Array('', '万', '亿', '兆');
|
//对应小数部分单位
|
const cnDecUnits = new Array('角', '分', '毫', '厘');
|
//整数金额时后面跟的字符
|
const cnInteger = '整';
|
//整型完以后的单位
|
const cnIntLast = '元';
|
//最大处理的数字
|
const maxNum = 999999999999999.9999;
|
//金额整数部分
|
let integerNum = '';
|
//金额小数部分
|
let decimalNum = '';
|
//输出的中文金额字符串
|
let chineseStr = '';
|
//分离金额后用的数组,预定义
|
let parts = [];
|
//超出最大处理数字
|
if (cny >= maxNum) return '';
|
if (cny == 0) {
|
chineseStr = cnNums[0] + cnIntLast + cnInteger;
|
return chineseStr;
|
}
|
//转换为字符串
|
if (amount.indexOf('.') == -1) {
|
integerNum = amount;
|
decimalNum = '';
|
} else {
|
parts = amount.split('.');
|
integerNum = parts[0];
|
decimalNum = parts[1].substring(0, 4);
|
}
|
//获取整型部分转换
|
if (parseInt(integerNum, 10) > 0) {
|
let zeroCount = 0;
|
let IntLen = integerNum.length;
|
for (let i = 0; i < IntLen; i++) {
|
let n = integerNum.substring(i, i + 1);
|
let p = IntLen - i - 1;
|
let q = p / 4;
|
let m = p % 4;
|
if (n == '0') {
|
zeroCount++;
|
} else {
|
if (zeroCount > 0) {
|
chineseStr += cnNums[0];
|
}
|
//归零
|
zeroCount = 0;
|
chineseStr += cnNums[parseInt(n)] + cnIntRadice[m];
|
}
|
if (m == 0 && zeroCount < 4) {
|
chineseStr += cnIntUnits[q];
|
}
|
}
|
chineseStr += cnIntLast;
|
}
|
//小数部分
|
if (decimalNum != '') {
|
let decLen = decimalNum.length;
|
for (let i = 0; i < decLen; i++) {
|
let n = decimalNum.substring(i, i + 1);
|
if (n != '0') {
|
chineseStr += cnNums[parseInt(n)] + cnDecUnits[i];
|
}
|
}
|
}
|
if (chineseStr == '') {
|
chineseStr += cnNums[0] + cnIntLast + cnInteger;
|
} else if (decimalNum == '') {
|
chineseStr += cnInteger;
|
}
|
return chineseStr;
|
}
|
}
|
|
export default {
|
titleCase: utils.titleCase,
|
compressLetter: utils.compressLetter,
|
sleep: utils.sleep,
|
trim: utils.trim,
|
trimAll: utils.trimAll,
|
replaceAll: utils.replaceAll,
|
numberFormatter: utils.numberFormatter,
|
moneyFormatter: utils.moneyFormatter,
|
dateFormatter: utils.dateFormatter,
|
rgbToHex: utils.rgbToHex,
|
hexToRGB: utils.hexToRGB,
|
unique: utils.unique,
|
distinctArray: utils.distinctArray,
|
getDateTimeSlot: utils.getDateTimeSlot,
|
getUrlParam: utils.getUrlParam,
|
getUUID: utils.getUUID,
|
debounce: utils.debounce,
|
throttle: utils.throttle,
|
formatTimeAgo: utils.formatTimeAgo,
|
getRandomHexColor: utils.getRandomHexColor,
|
convertCurrency: utils.convertCurrency
|
}
|