JS常用工具函数

/*
* 本文件存放【具体业务功能】公共函数
* 服务于具体业务场景
*/

import axios from 'axios'
import {cookies} from '../cookieUtils'
const baseURL =  require('../../../config/APIs').API
import {Message,Notice} from 'iview'

// 下载文件函数
const exportFile = (filePath, params, fileName, timeout) => {
  cookies.getAuthorization().then(res=>{
    const config = {
      baseURL: baseURL,
      timeout: timeout ? timeout : 300000,
      params: params,
      headers: {
        'Pragma': 'no-cache',
        'Content-type': 'application/json;charset=UTF-8',
        'X-Auth-Token': res || null
      },
      responseType: 'blob'
    }
    axios.get(filePath,config).then(res=>{
      let content = res.data
      let blob = new Blob([content])
  
      if('msSaveOrOpenBlob' in navigator){
        // Microsoft Edge and Microsoft Internet Explorer 10-11
        window.navigator.msSaveOrOpenBlob(blob, fileName)
      } else {
        if ('download' in document.createElement('a')) { // 非IE下载
          let elink = document.createElement('a')
          elink.download = fileName
          elink.style.display = 'none'
          elink.href = URL.createObjectURL(blob)  
          document.body.appendChild(elink)
          elink.click()
          URL.revokeObjectURL(elink.href) // 释放URL 对象
          document.body.removeChild(elink)
        } else { // IE10+下载
          navigator.msSaveOrOpenBlob(blob, fileName)
        }
      }
    }).catch((err)=>{
      let data = err.response.data
      if (err.request.responseType === 'blob') {
        var reader = new FileReader()
        reader.readAsText(data, 'utf-8')
        reader.onload = function () {
          data = JSON.parse(reader.result)
          Message.error({
            content: data.description,
            duration: 5,
            closable: true
          })
        }
      } else {
        Message.error({
          content: err,
          duration: 5,
          closable: true
        })
      }
      
    })
  })
}

// 上传文件函数
const uploadFile = (filePath, data,timeout) => {
  return cookies.getAuthorization().then(res=>{
    const config = {
      baseURL: baseURL,
      timeout: timeout ? timeout : 60000,
      headers: {
        'Pragma': 'no-cache',
        'Content-type': 'multipart/form-data',
        'X-Auth-Token': res || null
      },
    }
    return axios.post(filePath,data,config).then(res=>{
      return res.data
    },err=>{
      Notice.error({
        title: err.response.data.title,
        desc: err.response.data.description,
        duration: 15
      })
    })
  })
}

// 消抖函数
const debounce = function (callback, delay, immediate) {
  let timeout, result
  return function () {
    let context = this
    let args = arguments
    var later = function () {
      timeout = null
      if (!immediate) result = callback.apply(context, args)
    }
    var callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, delay)
    if (callNow) result = callback.apply(context, args)
    return result
  }
}
// 节流函数
const throttle = function (fn, delay) {
  let timer = null
  let remaining = 0
  let previous = new Date()
  return function () {
    let now = new Date()
    remaining = now - previous
    let args = arguments
    let context = this
    if (remaining >= delay) {
      if (timer) {
        clearTimeout(timer)
      }
      fn.apply(context, args)
      previous = now
    } else {
      if (!timer) {
        timer = setTimeout(function () {
          fn.apply(context, args)
        }, delay - remaining)
      }
    }
  }
}

export default {
  exportFile,
  uploadFile,
  debounce,
  throttle
}

上传文件实例:

 <input type="file" multiple @change="fileChange"  ref='upload'/>

//上传文件
      fileChange(){
        let files = this.$refs.upload.files
        if(!files){
          return
        }
        // 校验文件大小
        let filesSize = 0
        for (let index = 0; index < files.length; index++) {
          const element = files[index]
          if (element.size/1024/1024 > 10) {
            this.$Notice.warning({title:'单文件过大',desc:`单文件最大容量为10M,${element.name}文件大于10M,请重新上传!`})
            return
          }
          filesSize += element.size         
        }
        if (filesSize/1024/1024 > 20) {
          this.$Notice.warning({title:'多文件总容量最大为20M,请重新上传!'})
          return
        }        
        let formData = new FormData()
        for (let index = 0; index < files.length; index++) {
          const element = files[index]
          formData.append(`${element.name}`, element)
        }
        this.$publicMethod.uploadFile('/v1/upload/im-file',formData).then((resData)=>{
          this.firewall.attachment_list = resData
          this.$refs.upload.value = ''
        })
      },
validate.js
/*
* @describe:
* 该插件旨在提供公共表单验证插件,功能不断完善中......
*
 */
import $ from 'jquery'
import './animate.css'
import httpRequestEntrance from './httpRequestEntrance.js'
import Promise from 'promise'
import Set from 'es6-set'

/*
 * Func:单一验证字段是否为空并提示功能
 *
 * @param {String} className (提示信息装载位置的class名称)
 * @param {String} val (待校验字段值)
 * @return {Boolean}
 */
const isEmptyAndWarn = (className, val) =>{
  className = '.' + className
  $(className).empty()
  if (val === '' || val === null || val === undefined || JSON.stringify(val) === '{}' || JSON.stringify(val) === '[]') {
    $(className).append('字段不能为空!')
    return true
  }
  return false
}

/*
 * Func:批量验证字段是否为空并提示功能
 *
 * params: {host_name_w: "111", host_w: "222", os_family_w: "333", checkedEnv_w: "444"}
 * key: 代表提示信息装载位置的class名称(*_w),其中*表示字段名,_w为特殊标记
 * value: 代表待校验字段的值
 */
const isEmptyAndWarn_JSON = (params) =>{
  let res = true
  let key
  for(key in params){
    if (isEmptyAndWarn(key, params[key])) {
      res = false
      break
    }
  }
  return res
}

/*
 * Func:批量验证表单搜索条件
 *
 * params: {host_name: "111", host: "222", os_family: "333"}
 * key:
 * value: 代表待校验字段的值
 */
const isEmptyReturn_JSON = (param) =>{
  let params = Object.assign({},param)
  let key
  for(key in params){
    if (!isEmpty(params[key])) {
      delete params[key]
    }
  }
  return params
}
//对象内是否有值没填
const isEmptyInObj = (params) =>{
  let key
  for(key in params){
    if (!isEmpty(params[key])) {
      return true
    }
  }
  return false
}

/*
 * Func:单一验证字段是否
 *
 * val: 代表待校验字段的值
 *
 * return: boolean
 */
const isEmpty = (val) => {
  if (val === '' || val === null || val === undefined) {
    return false
  }
  if ((Object.prototype.toString.call(val) === '[object Object]' && !Object.keys(val).length) || (Object.prototype.toString.call(val) === '[object Array]' && !val.length)) {
    return false
  }
  return true
}

/*
 * Func:单一验证字段是否
 *
 * val: 代表待校验字段的值
 *
 * return: boolean
 */
const isEmpty_reset = (val) =>{
  if (val === '' || val === null || val === undefined || JSON.stringify(val) === '{}' || JSON.stringify(val) === '[]') {
    return true
  }
  return false
}


/*
 * Func:判断object/json 是否为空
 *
 * e: object/json
 *
 * return: boolean
 */
const isEmptyObject = (e) =>{
  let t
  for (t in e)
    return !1
  return !0
}

/*
 * Func: 判断字符串是否包含中文
 *
 * @param {String} str (待效验字符串)
 *
 * @return {Boolean} true: 包含; false: 不包含
 */
const isContainChina = (str) =>{
  const patrn=/[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/gi
  if(!patrn.exec(str)){
    return false
  }
  return true
}


/*
 *Func: 清空JSON中字段值,解决编辑和新增时页面缓存
 *
 */
const emptyJson = (j) =>{
  let k
  for (k in j)
    j[k] = null
  return j
}


/**
 * 深拷贝js对象
 * @param obj
 * @returns {{}}
 *  Created by fengjingyu on 2018/4/11.
 */
const deepCopy = (obj) =>{
  let newO = {}
  if (obj instanceof Array) {
    newO = []
  }
  for ( let key in obj) {
    let val = obj[key]
    if (val instanceof Date) {
      val = val.format('yyyy-MM-dd hh:mm:ss')
    }
    newO[key] = val
  }
  return newO
}

// 格式化时间
Date.prototype.format = function(fmt) {
  var o = {
    'M+' : this.getMonth()+1,                 // 月份
    'd+' : this.getDate(),                    // 日
    'h+' : this.getHours(),                   // 小时
    'm+' : this.getMinutes(),                 // 分
    's+' : this.getSeconds(),                 // 秒
    'q+' : Math.floor((this.getMonth()+3)/3), // 季度
    'S'  : this.getMilliseconds()             // 毫秒
  }
  if(/(y+)/.test(fmt)) {
    fmt=fmt.replace(RegExp.$1, (this.getFullYear()+'').substr(4 - RegExp.$1.length))
  }
  for(var k in o) {
    if(new RegExp('('+ k +')').test(fmt)){
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (('00'+ o[k]).substr((''+ o[k]).length)))
    }
  }
  return fmt
}

const modal_confirm_custom = (leader,title,fun) =>{
  let tip = title.length>0 ? '<p style="font-size:15px;transform: translateY(-3px);">'+ title +'</p>' :'确定删除吗?'
  leader.$Modal.confirm({
    content: tip,
    onOk: () => {
      fun()
    },
    onCancel: () => {
      leader.$store.commit('changeFlag',true)
    }
  })
}

const valueFromExpression = (item, expression, default_value='') =>{
  let expr=expression
  let item_tmp = item
  let attrs=expr.split('.')
  let n=0
  for (n in attrs){
    if (isEmpty(item_tmp) && attrs[n] in item_tmp){
      item_tmp = item_tmp[attrs[n]]
    }else{
      return default_value
    }
  }
  return item_tmp
}

/*
 *Func: 通过select选中值返回选中对象
 * @param {String} val (选中值)
 * @param {String} key (匹配字段)
 * @param {Object} options (待匹配对象集合)
 *
 */
const returnObjByValue = (val, key, options) =>{
  for (let no in options) {
    if (options[no][key] === val) {
      return options[no]
    }
  }
}

/*
 *Func: 后台获取select数据赋值公共方法
 * @param {Object} that (调用页面当前对象)
 * @param {String} API (匹配字段)
 * @param {Object} params (接口所需参数)
 * @param {String} receiveParams (接收数据字段层级关系)
 * @param {String} type (区分是获取租户还是项目)
 *
 */
const getSelectOptions = (that, API, params, receiveParams, type) => {
  return that.$httpRequestEntrance.httpRequestEntrance('GET', API, params, (responseData) => {
    let res = responseData.data
    if (res.length > 0) {
      let arr = receiveParams.split('.')
      let temp = that
      for(let i=0;i<arr.length ;i++){
        temp = temp[arr[i]]
      }
      res.forEach((item) => {
        let desc =  (item.desc === null)? '-':item.desc
        if (type === 'project') {
          desc =  (item.name_zh === null)? '-':item.name_zh
        }
        if (type === 'tenant') {
          desc =  (item.chinese_name_abbreviation === null)? '-':item.chinese_name_abbreviation
        }
        temp.push({
          name: item.name + '(' + desc + ')',
          id: item.id
        })
      })
    }
  })
}

const upgradePrice = (that, Api, params) => {
  // 初始化价格显示
  that.$httpRequestEntrance.httpRequestEntrance('POST', Api,
  params, (responseData) => {
    that.price.isInquiryPriceOK_else_isAllNull = false
    that.price.price = responseData.sum_price // 升级后价格
    that.price.beforeUpgradePrice = responseData.sum_before_upgrade_price ? responseData.sum_before_upgrade_price : 0 // 升级前价格
    that.price.productDetails = []
    that.price.discounts = []
    for (let item of responseData.data) {
      if (item.price !== null) {
        that.price.productDetails.push({
          productName: item.product.name,
          price:item.price_display,
          priceUnit: item.charging_pkg.measurement_display
        })
        for (let discountInfo of item.discounts) {
          that.price.discounts.push({
            started_date: discountInfo.started_date,
            ended_date: discountInfo.ended_date,
            discount_name: discountInfo.discount_config.name
          })
        }
      }
    }
    if (that.price.productDetails.length > 0) {
      that.price.isInquiryPriceOK = true
      that.price.isInquiryPriceOK_else_isAllNull = false
    } else {
      that.price.isInquiryPriceOK = false
      that.price.isInquiryPriceOK_else_isAllNull = true
    }
  }, {isNeedloading: false})
}

const inquiryPrice = (that, Api, params, method = 'POST') => {
  // 初始化价格显示
  that.price.isInquiryPriceOK = false
  return new Promise(function(resolve) {
    let resultPrice = managePrice(that, Api, params, method)
    resultPrice.then((result) => {
      resolve(result)
    })
  })  
}


const managePrice = (that, Api, params, method) => {
  return new Promise(function(resolve) {
    let xxPrice = {
      isInquiryPriceOK: false, // 是否获取价格成功
      isInquiryPriceOK_else_isAllNull: false,
      discounts: [], // 优惠活动信息
      cheapPrice: 0, // 节省价格
      totalPrice: 0, // 缓存优惠后价格
      productDetails: [], // 缓存产品价格详细信息
      wholeYearPrice: 0
    }
    that.$httpRequestEntrance.httpRequestEntrance(method, Api,
      params, (responseData) => {
        xxPrice.isInquiryPriceOK_else_isAllNull = false
        xxPrice.totalPrice = responseData.sum_price
        xxPrice.cheapPrice = responseData.cheap_price
        xxPrice.productDetails = []
        xxPrice.discounts = []
        xxPrice.wholeYearPrice = (responseData.whole_year_price === null ? 0: responseData.whole_year_price)
        for (let item of responseData.data) {
          if (item.price !== null) {
            xxPrice.productDetails.push({
              productName: item.product.name,
              price: item.price_display,
              priceUnit: item.charging_pkg.measurement_display
            })
            for (let discountInfo of item.discounts) {
              xxPrice.discounts.push({
                started_date: discountInfo.started_date,
                ended_date: discountInfo.ended_date,
                discount_name: discountInfo.discount_config.name
              })
            }
          }
        }
        if (xxPrice.productDetails.length > 0) {
          xxPrice.isInquiryPriceOK = true
          xxPrice.isInquiryPriceOK_else_isAllNull = false
        } else {
          xxPrice.isInquiryPriceOK = false
          xxPrice.isInquiryPriceOK_else_isAllNull = true
        }
        resolve(xxPrice)
      }, {isNeedloading: false})
  })
}

//订单产品可用区是否在该产品类型下可用
const  azIsAvailable = (productCode,azid,tip,global) =>{
  return httpRequestEntrance.httpRequestEntrance('GET', 'v1/azs',
  {enabled: true, product_code: productCode}, (responseData) => {
    let res = responseData.data
    let flag = false
    if (res.length > 0) {
      res.forEach((item) => {
        if(item.id === azid){
          flag = true
        }
      })
    }
    if(!flag&&tip){
      global.$Notice.warning({title:tip})
    }
    return flag
  })
}
//对象数组转对象
const switchFormat=(arr,key,value)=>{
  let obj = {}
  arr.map(item=>{
    obj[item[key]] = item[value]
  })
  return obj
}
//深度合并对象
const deepAssign = (obj1, obj2)=>{
  let obj = Array.isArray(obj1)?[]:{}
  let keys = [...new Set(Object.keys(obj1).concat(Object.keys(obj2)))]
  keys.map(key=>{
    if(typeof obj2[key] === 'object' && typeof obj1[key] === 'object'){
      obj[key] = deepAssign(obj1[key],obj2[key])
    }else{
      obj[key] = obj2[key]?obj2[key]:obj1[key]
      if(typeof obj2[key] === 'object'){
        if(Array.isArray(obj[key])){
          obj[key]=deepAssign([],obj[key])
        }else{
          obj[key]=deepAssign({},obj[key])
        }
      }
    }
  })
  return obj
}

//隐藏手机号码
const coverPhone=(area,phone)=>{
  let funcs={
    '86':()=>{
      return phone.slice(0,3)+'****'+phone.slice(7)
    },
    '852':()=>{
      return '****'+phone.slice(4)
    }
  }
  return funcs[area]()
}
//格式化json函数
const formatJson = function (text_value) {
  if (!text_value) {
    return ''
  } else if (text_value.indexOf('{') === -1) {
    return text_value
  } else {
    var json = eval('(' + text_value + ')')
    text_value = JSON.stringify(json)
    var res = ''
    for (var i = 0, j = 0, k = 0, ii, ele; i < text_value.length; i++) {//k:缩进,j:""个数
      ele = text_value.charAt(i)
      if (j % 2 == 0 && ele == '}') {
        k--
        for (ii = 0; ii < k; ii++) ele = '  ' + ele
        ele = '\n' + ele
      }
      else if (j % 2 == 0 && ele == '{') {
        ele += '\n'
        k++
        for (ii = 0; ii < k; ii++) ele += '  '
      }
      else if (j % 2 == 0 && ele == ',') {
        ele += '\n'
        for (ii = 0; ii < k; ii++) ele += '  '
      }
      else if (ele == '"') j++
      res += ele
    }
    return res
  }
}
// 补充Promise的allSettled方法
const allSettled = Promise.allSettled || function(arr) {
  // let P = this
  return new Promise((resolve, reject) => {
    if(Object.prototype.toString.call(arr) !== '[object Array]') {
      return reject(new TypeError(typeof arr + '' + arr + '' + 'is not iterable(cannot read property Symbol(Symbol.iterator))'))
    }
    var args = Array.prototype.slice.call(arr)
    if(args.length === 0) return resolve([])
    var arrCount = args.length

    function resolvePromise(index, value){
      if(typeof value === 'object') {
        var then = value.then
        if(typeof then === 'function') {
          then.call(value, function(val){
            args[index] = {status: 'fulfilled', value: val}
            if(--arrCount === 0) {
              resolve(args)
            }
          }, function(e) {
            args[index] = {status: 'rejected', reason: e}
            if(--arrCount === 0){
              resolve(args)
            }
          })
        }
      }
    }
    for(let i = 0; i < args.length; i++) {
      resolvePromise(i, args[i])
    }
  })
}

export const validate = {
  isEmpty,
  isEmpty_reset, // 为空效验新方法,计划替代isEmpty
  isEmptyAndWarn,
  isEmptyAndWarn_JSON,
  isEmptyReturn_JSON,
  isEmptyObject,
  isEmptyInObj,
  emptyJson, // 清空JSON对象中的值
  deepCopy, // JSON对象深拷贝
  isContainChina, //是否包含中文字符
  modal_confirm_custom,
  valueFromExpression, //多级表达式取值
  azIsAvailable,//该订单产品可用区是否在该产品类型下可用
  returnObjByValue, // 根据选中值返回选中对象
  getSelectOptions, // 获取租户
  inquiryPrice, // 产品询价
  upgradePrice, // 产品询价升级
  // formatNumber, // 精确格式化数字
  switchFormat,//对象数组转对象
  coverPhone,//隐藏手机号码
  deepAssign,//深度合并对象
  formatJson ,// 格式化json
  allSettled // 补充promise的allSettled方法
}


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容