ph-utils
Version:
js 开发工具集,前后端都可以使用(commonjs和es module)
240 lines (239 loc) • 7.92 kB
JavaScript
/**
* node 和 web 通用的工具类
*/
/** 包含字母+数字的随机数字符 */
const RANDOM_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
/** 只包含字母的随机数字符 */
const NUMBER_RANDOM_CHARTS = "0123456789";
/**
* 验证参数是否为空
* @param str 待验证的参数
* @param ignoreWhitespace 如果是字符串是否忽略空格(包括空白字符串以及[\r\t\n]之类的制表符),默认为true
*/
export function isBlank(str, ignoreWhitespace = true) {
if (str == null) {
return true;
}
return ((ignoreWhitespace && typeof str === "string"
? str.trim().length
: str.length) === 0);
}
/**
* 屏蔽手机号,中间部分用 * 展示
* @param mobile 待屏蔽的手机号
* @returns 屏蔽后的手机号,例如:123 **** 1234
*/
export function shieldMobile(mobile) {
const x1 = Math.floor(mobile.length / 2);
const x2 = Math.ceil(x1 / 2);
const shields = [" "];
for (let i = 0; i < x1 - 1; i++) {
shields.push("*");
}
shields.push(" ");
return (mobile.substring(0, x2) + shields.join("") + mobile.substring(x2 + x1 - 1));
}
/**
* 验证参数是否是数字
* @param str 待验证的字符串
* @param numericParam 通过参数标记是否包含小数、正数
* @param numericParam.isPositive 是否是正数, 默认: false
* @param numericParam.isFloat 是否是小数, 默认: true
* @returns true 是数字, false 不是数字
*/
export function isNumeric(str, numericParam) {
numericParam = { isPositive: false, isFloat: true, ...numericParam };
const symbol = numericParam.isPositive ? "[+]?" : "[+-]?";
const main = numericParam.isFloat ? "([0-9]*[.])?[0-9]+" : "[0-9]+";
return new RegExp("^" + symbol + main + "$").test(str);
}
/**
* 验证参数是否是Boolean 类型
* @param str 待验证的字符串
* @returns
*/
export function isBoolean(str) {
return ["true", "false"].indexOf(str) >= 0;
}
export function random(opts) {
if (typeof opts === "object" && opts.min != null && opts.max != null) {
const randomNum = Math.random();
/* 生成两个数字之间的随机数(number) */
const end = opts.hasEnd ? 1 : 0;
const resRandom = randomNum * (opts.max - opts.min + end) + opts.min;
return opts.isInteger !== false ? Math.floor(resRandom) : resRandom;
}
else {
if (typeof opts === "object" && opts.length == null) {
throw new Error("random_length_cannot_null");
}
let len = typeof opts === "object" ? opts.length : opts;
/* 生成指定长度的随机数 */
let chars = RANDOM_CHARS;
if (typeof opts === "object" && opts.hasLetter === false) {
chars = NUMBER_RANDOM_CHARTS;
}
const resRandom = Array.from({ length: len }, () => chars.charAt(random({ min: 0, max: chars.length - 1, hasEnd: true }))).join("");
if (typeof opts === "object" &&
opts.firstIsZero === false &&
resRandom.indexOf("0") === 0) {
return random(opts);
}
else {
return resRandom;
}
}
}
/**
* 带有错误名称标记的错误类型
*/
export class BaseError extends Error {
constructor() {
if (arguments.length === 1) {
super(arguments[0]);
this.name = "BaseError";
}
else {
super(arguments[1]);
this.name = arguments[0];
}
}
}
/**
* 将金额数字格式化为金额格式显示并且会保留两位小数[去除多余的位数,不是四舍五入,而是直接舍去] 1234523432.23 => 123,123,123.23
* @param {number} number 待转换的金额数字
* @return string
*/
export function formatMoney(number) {
if (typeof Intl.NumberFormat !== "undefined") {
const formatter = new Intl.NumberFormat("zh-CN", {
style: "decimal",
maximumFractionDigits: 2,
});
return formatter.format(number);
}
else {
number = number || 0;
const negative = "";
const base = String(parseInt(number, 10)); // 获取数字整数部分
const mod = base.length > 3 ? base.length % 3 : 0;
/*
* 利用 正则前瞻 (?=) 将3位数字后面还紧跟一位数字的三位数字替换为 数字, 的形式
*/
const numberStr = String(number);
const usePrecision = numberStr.indexOf(".");
let dotStr = usePrecision > 0 ? numberStr.slice(usePrecision + 1) : "00";
dotStr = dotStr.length > 2 ? dotStr.slice(0, 2) : dotStr;
return (negative +
(mod ? base.slice(0, mod) + "," : "") +
base.slice(mod).replace(/(\d{3})(?=\d)/g, "$1,") +
"." +
dotStr);
}
}
/**
* 将风格由大写风格转换为下划线风格: HelloWorld -> hello-world
* @param name 命名, 例如: HelloWorld
* @param connector 连接符, 默认为: _
*/
export function snakeCaseStyle(name, connector = "-") {
return name.replace(/([A-Z])/g, (match, p1, offset) => (offset > 0 ? connector : "") + match.toLowerCase());
}
/**
* 对数字进行四舍五入处理
* @param num 需要进行四舍五入的数字
* @param precision 精度,默认为2,即保留小数点后两位
* @param roundType 舍入类型,默认为0,提供三种取值:
* 0: 标准四舍五入
* 1: 向上取整
* 2: 向下取整
* @returns 返回经过指定方式舍入后的数字
*/
export function round(num, precision = 2, roundType = 0) {
// 计算精度因子,用于后续四舍五入计算
const factor = Math.pow(10, precision);
switch (roundType) {
case 0:
// 标准四舍五入
return Math.round(num * factor) / factor;
case 1:
// 向上取整
return Math.ceil(num * factor) / factor;
case 2:
// 向下取整
return Math.floor(num * factor) / factor;
default:
// 如果传入的roundType不是预期的值,则直接返回原始数字
return num;
}
}
/**
* 反转字符串
*/
export function reverseStr(str) {
return str.split("").reverse().join("");
}
function getObjKeyValue(data, key) {
if (data == null)
return null;
return data[key];
}
/**
* 嵌套的 json 指定 key 数据
* @param data JSON格式数据
* @param keys 待获取的数据 key, 可以通过 [.] 获取嵌套数据, 例如: a.b.c
* @returns
*/
export function getJSONValue(data, keystr) {
if (data == null)
return null;
const keys = keystr.split(".");
let res = data;
for (const key of keys) {
res = getObjKeyValue(res, key);
if (res == null)
break;
}
return res;
}
/**
* 数据格式化主要用于数据类型转换
* @param data 待转换数据类型的数据
* @param config 转换配置
* @returns
*/
export function formatData(data, config) {
const cfg = {
numberFields: [],
stringFields: [],
formatter: {},
...config,
};
const res = {};
for (const key in data) {
let value = getJSONValue(data, key);
let formater;
if (key in cfg.formatter) {
formater = cfg.formatter[key];
}
if (cfg.numberFields.includes(key)) {
formater = "number";
}
if (cfg.stringFields.includes(key)) {
formater = "string";
}
if (formater != null) {
if (typeof formater == "function") {
value = formater(value);
}
else if (formater == "number") {
value = Number(value);
}
else if (formater == "string") {
value = String(value);
}
}
res[key] = value;
}
return res;
}