记录一些自己用的前端工具函数

Posted 魔芋药丸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录一些自己用的前端工具函数相关的知识,希望对你有一定的参考价值。

import _ from \'lodash\';
import { toThousands } from \'@mx/util/to-thousands\';

/**
 * toThousands千分位格式化
 *
 * ### Example
 * ```
 * const n = \'12344.33\'
 * toThousands(n); // 12,344.33
 * ```
 */

// 时间格式化
export function getTimeStr (date) {
  if (typeof date === \'number\') {
    date = new Date(date);
  }
  let hours = `${date.getHours()}`;
  let minutes = `${date.getMinutes()}`;
  let secodes = `${date.getSeconds()}`;
  if (hours.length < 2) {
    hours = `0${hours}`;
  }
  if (minutes.length < 2) {
    minutes = `0${minutes}`;
  }
  if (secodes.length < 2) {
    secodes = `0${secodes}`;
  }
  return `${hours}:${minutes}:${secodes}`;
}

// 日期格式化
export function getDateStr (date, flag = \'-\') {
  if (!date) {
    return \'\';
  }
  if (typeof date === \'number\') {
    date = new Date(date);
  }
  let year = `${date.getFullYear()}`;
  let month = `${date.getMonth() + 1}`;
  let day = `${date.getDate()}`;
  if (month.length < 2) {
    month = `0${month}`;
  }
  if (day.length < 2) {
    day = `0${day}`;
  }
  return `${year}${flag}${month}${flag}${day}`;
}

// 综合时间格式化
export function formatDate (date) {
  if (!date) {
    return \'--\';
  }
  return `${getDateStr(date)} ${getTimeStr(date)}`;
}

// 数字格式保留指定位小数,返回字符串格式
export function fixedNumber (num, count = 2) {
  if (typeof num !== \'number\') {
    num = Number(num);
  }
  return num.toFixed(count);
}

// 金额 分=>元
export function amountCentToYuan (cent) {
  if (typeof cent !== \'number\' || Number.isNaN(cent)) {
    return null;
  }
  return round(cent / 100, 2);
}

// 金额 元=>分
export function amountYuanToCent (yuan) {
  if (typeof yuan !== \'number\' || Number.isNaN(yuan)) {
    return null;
  }
  return round(yuan * 100, 2);
}

// 小数四舍五入
export function round (number, precision) {
  return Math.round(+number + \'e\' + precision) / Math.pow(10, precision);
}

// 千分位格式化,可选择金额单位为分
export function amountToThousands (amount, isCent = false) {
  if (!amount && amount !== 0) {
    return \'\';
  }
  if (isCent) {
    amount = Number.parseFloat(amount) / 100;
  }
  // 产品要强制带小数点两位
  let amountStr = toThousands(`${amount}`);
  if (!amountStr.includes(\'.\')) {
    amountStr += \'.00\';
  } else {
    // 小数点后只有一位的话,还需要补齐
    if (amountStr.split(\'.\')[1].length < 2) {
      amountStr += \'0\';
    }
  }
  return amountStr;
}

// 数字大写格式映射
export function getNumberCap (num) {
  num = num.trim();
  if (!num) {
    return \'\';
  }
  if (!/^(0|[1-9]\\d*)(\\.\\d+)?$/.test(num)) {
    return \'异常金额\';
  }
  let unit = \'千百拾亿千百拾万千百拾元角分\';
  let str = \'\';
  num += \'00\';
  const p = num.indexOf(\'.\');
  if (p >= 0) {
    num = num.substring(0, p) + num.substr(p + 1, 2);
  }
  unit = unit.substr(unit.length - num.length);
  for (let i = 0; i < num.length; i++) {
    str += \'零壹贰叁肆伍陆柒捌玖\'.charAt(num.charAt(i)) + unit.charAt(i);
  }
  return str.replace(/零(千|百|拾|角)/g, \'零\')
    .replace(/(零)+/g, \'零\')
    .replace(/零(万|亿|元)/g, \'$1\')
    .replace(/(亿)万|壹(拾)/g, \'$1$2\')
    .replace(/^元零?|零分/g, \'\')
    .replace(/元$/g, \'元整\');
}

// 根据正则剔除字符串指定内容,默认剔除非数字
export function replaceByRex (val, rex = /^[0-9]*$/) {
  if (!val) {
    return \'\';
  }
  return Array.from(val).filter(str => Array.isArray(str.match(rex))).join(\'\');
}

// 剔除字符串中非数字部分并返回
export function replaceNotNum (val) {
  return replaceByRex(val, /^[0-9]*$/);
}

// 提出字符串中非数字和字母的部分并返回
export function replaceNotNumAndLetter (val) {
  return replaceByRex(val, /^[0-9a-zA-Z]*$/);
}

// 函数节流,多用于提交接口,默认2s
export function throttle (fn, wait = 2000) {
  return _.throttle(fn, wait);
}

// 对象深拷贝
export function deepCopy (obj) {
  return JSON.parse(JSON.stringify(obj));
}

// 截取字符串中的数字部分并返回,返回值是字符串格式
// 卡号等不太适用,非常大的数字计算会有问题
export function getNumberByString (str, isFloat = false, precision = 2) {
  str = str.trim();
  if (!str) {
    return \'\';
  }
  const reg = isFloat ? /[0-9.]*/g : /[0-9]*/g;
  const resultArr = str.match(reg);
  let resultStr = \'\';
  if (Array.isArray(resultArr)) {
    resultStr = resultArr.join(\'\');
  }
  if (!isFloat) {
    // 为了保险起见,先转成数字再转回来
    return `${Number.parseInt(resultStr)}`;
  } else {
    // 小数可能存在多个小数点存在,小数点也可能在开头或者结尾,都需要处理
    // 结尾的小数点暂不处理,因为输入小数输一半是必然会经过这一过程的
    if (resultStr.startsWith(\'.\')) {
      // 开头的小数点会处理成0.
      resultStr = \'0\' + resultStr;
    }
    if (resultStr.indexOf(\'.\') !== resultStr.lastIndexOf(\'.\')) {
      // 如果有多个小数点,则第二个小数点及之后的内容将会被舍弃
      const arr = resultStr.split(\'.\');
      resultStr = `${arr[0]}.${arr[1]}`;
    }
    // 小数位数限制
    if (typeof precision === \'number\' && precision >= 0) {
      if (resultStr.includes(\'.\')) {
        let [int, float] = resultStr.split(\'.\');
        if (float.length > precision) {
          float = float.substring(0, precision);
        }
        resultStr = `${int}.${float}`;
      }
    }
    // 保险起见,先转成数字再转回来
    // 不过只要有小数点,就可能不适用
    if (resultStr.includes(\'.\')) {
      return resultStr;
    }
    return `${Number.parseFloat(resultStr)}`;
  }
}

// 银行卡号展示,开始三位有一个空格,之后每四位会有一空格
export function showBankNo (bankCardNo) {
  if (!bankCardNo) {
    return \'\';
  }
  let showCardNo = \'\';
  for (let i = 1; i <= bankCardNo.length; i++) {
    showCardNo += bankCardNo[i - 1];
    if (i === 3) {
      showCardNo += \' \';
    } else if (i > 4) {
      if ((i % 4) === 0 && i !== bankCardNo.length) {
        showCardNo += \' \';
      }
    }
  }
  return showCardNo;
}

function compareNumbers (a, b) {
  a = Number(a);
  b = Number(b);
  return a === b ? 0
    : a > b ? 1
      : -1;
}

export function formatCommaSeparatedNumbersToNumberArray (v = \'\') {
  if (v === null) { return []; }
  let values = v.split(\',\')
    .map(value => { const num = Number(value); if (num) { return num; } })
    .filter(v => typeof v === \'number\')
    .filter(value => {
      const v = Number(value);
      return v > 0 && Number.isInteger(v);
    });
  if (values.length === 0) { return []; }
  return Array.from(new Set(values)).sort(compareNumbers);
}

export function formatCommaSeparatedNumbersToArray (v = \'\') {
  if (v === null) { return []; }
  let values = v.split(\',\').filter((value = \'\') => {
    if (value === \'\') { return false; }

    const v = Number(value);
    return v > 0 && Number.isInteger(v);
  });
  if (values.length === 0) { return []; }
  return Array.from(new Set(values)).sort(compareNumbers);
}

// 当前环境区分
export function getEnvRuntime () {
  if (/\\.dev\\.sankuai\\.com/.test(location.host)) {
    return \'dev\';
  } else if (/\\.test\\.sankuai\\.com/.test(location.host)) {
    return \'test\';
  } else if (/\\.st\\.(sankuai|meituan)\\.com/.test(location.host)) {
    return \'st\';
  } else if (/(promomis-promotion|promo)\\.(sankuai|meituan)\\.com/.test(location.host)) {
    return \'prod\';
  } else {
    return \'local\';
  }
}

// 获取协议模板
export function getAgreementTemplate (no, params) {
  let agreementTemplate = \'\';
  if (no) {
    agreementTemplate = require(`client/business/agreements/${no}.html`);
  }
  if (agreementTemplate) {
    // 协议里存在变量,需要分别填充,具体运算规则不在公共方法中处理,而是由外部传入数据决定
    const variable = _.template(agreementTemplate);
    return params ? variable(params) : variable();
  }
  console.warn(`协议${no}不存在`);
  return \'没有对应协议\';
}

// 递归合并对象,只合并同级字段
export function meargeObject (base, opt, copyBase = true) {
  if (!base || typeof base !== \'object\') {
    return opt || {};
  }
  if (copyBase) {
    base = deepCopy(base);
  }
  if (!opt || typeof opt !== \'object\') {
    return base;
  }
  // 递归遍历对比,需要根据typeof来判断
  for (const [optKey, optVal] of Object.entries(opt)) {
    let val = null;
    for (const [baseKey, baseVal] of Object.entries(base)) {
      if (baseKey === optKey) {
        if (Array.isArray(baseVal)) {
          val = baseVal.concat(optVal);
        } else if (Array.isArray(optVal)) {
          // 这种很奇怪了,原数据不是数组,但新数据是,我就先按照完全替换处理了
          val = optVal;
        } else if (typeof baseVal === typeof optVal === \'object\') {
          val = meargeObject(baseVal, optVal, false);
        } else {
          val = optVal;
        }
      }
    }
    if (!val) {
      base[optKey] = optVal;
    } else {
      base[optKey] = val;
    }
  }
  return base;
}

// JS下载指定url文件
export function downFile (url) {
  const iframe = document.createElement(\'iframe\');
  iframe.src = url;
  iframe.style.display = \'none\';
  document.body.appendChild(iframe);
}

以上是关于记录一些自己用的前端工具函数的主要内容,如果未能解决你的问题,请参考以下文章

前端框架怎么用??用的好处是什么?

创建自己的代码片段(CodeSnippet)

前端开发工具vscode如何快速生成代码片段

前端开发工具vscode如何快速生成代码片段

前端啥样的代码开发工具好用?

前端框架Vue学习的心得记录(工具)