金融行业常用的js轮子-脱敏,金额格式化,特殊字符等

65 阅读17分钟

filter.js

import { isArray } from 'util';

function accMul(arg1,arg2,fix) {
  if(!parseInt(fix)==fix)
  {
      return;
  }
   var m=0,s1=arg1.toString(),s2=arg2.toString();
   try{m+=s1.split(".")[1].length}catch(e){}
   try{m+=s2.split(".")[1].length}catch(e){}
   if(m>fix){
      return (Math.round(Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m-fix))/Math.pow(10,fix));
   }else if(m<=fix){
       return (Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)).toFixed(fix);
   }else{
      return (arg1*arg2).toFixed(fix);
   }
}

export default {
  formatAmount(v) {
    if(v === '' || v < 0) {
      v = 0;
    }
    v = parseFloat(v).toFixed(2);
    if (typeof v === 'number') {
      v = v.toString();
    }

    if (v.indexOf('.') < 0) {
      v = `${v}.00`;
    } else if (v.split('.')[1].length === 1) {
      v = `${v}0`;
    }

    return v.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
  },
  // 基于formatAmount,负数不转为 0.00
  checkAmount(o){
    if(o==0 || o=="" || isNaN(o)){
      return "0.00"
    }
    if(o<0){
      return "-"+this.formatAmount(0-o)
    }
    return this.formatAmount(o)
  },
  /**
   *
   * @param {date}} dt
   * 返回格式:2018-10-11 14:36:41
   */
  formateDateTime(dt) {
    const y = dt.getFullYear();
    const m = (dt.getMonth() + 1 + '').padStart(2, '0');
    const d = (dt.getDate() + '').padStart(2, '0');
    const hh = dt.getHours();
    const mm = dt.getMinutes();
    const ss = dt.getSeconds();
    let ret = `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
    return ret;
  },
  /**
   *
   * @param {date}} dt 20181214153953
   * 返回格式:2018-10-11 14:36:41
   */
  formateDateTimeTwo(dt) {
    return dt.toString().replace(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/,"$1-$2-$3 $4:$5:$6");
  },
  formateDateTimeThree(dt) {
    return dt.toString().replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/g,"$1-$2-$3 $4:$5");
  },
  /**
   *
   * 处理逻辑:除以10000000
   * @param {*} val  现汇买入价 现钞买入价 等
   */
  formateFXdata(val) {
    let ret = val / 10000000;
    return ret;
  },
  formatAmountW(v) {
    v = parseFloat(v);

    let n = v / 10000;
    if (n >= 1) {
      return `${n}万`;
    }
    return `${this.formatAmount(v)}元`;
  },
  formatCardNo(v, repeat = 1) {
    if (!v || typeof v !== 'string') {
      return '';
    }
    return v.replace(/^(\d{4})\d+(\d{4})$/, `$1${'****'.repeat(repeat)}$2`);
  },
  /**
   * 卡号脱敏
   * @param {data} 623170010000012121
   * 返回格式:6231 **** **** 2121
   */
  formatCardNoSpace(v) {
    if (!v || typeof v !== 'string') {
      return '';
    }
    return v.replace(/^(\d{4})\d+(\d{4})|(\d{4}\/.*)$/, '$1 **** $2');
  },

  /**
   * 卡号加空格
   * @param {data} v
   */
  formatCardSpace(v) {
    if (!v || typeof v !== 'string') {
      return '';
    }
    return v.replace(/(\d{4})(?=\d)/g,'$1 ');
  },




  /**
   *
   * @param {data} 15511112222
   * 返回格式:155 **** 2222
   */
  formatMobileSpace(v) {
    if (!v || typeof v !== 'string') {
      return '';
    }
    return v.replace(/^(\d{3})(\d{4})(\d{4})$/, '$1 **** $3');
  },
  //身份证星号处理
  formatIdCard(v) {
    if (!v || typeof v !== 'string') {
      return '';
    }
    //return v.replace(/^(\d{4})\d+(\d{4})$/, '$1****$2');
    return v.substring(0,4) + '****'+ v.substring(v.length - 4)
  },
  formatDate(v) {
    if (!v) {
      return '-';
    }
    return v.substr(0, 8).replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
  },
  formatsDate(v) {
    if (!v) {
      return '-';
    }
    return v.substr(0, 8).replace(/(\d{4})(\d{2})(\d{2})/, '$1年$2月$3日');
  },
  formatAccountType(v) {
    if (v == 'AT00') {
      return '单位银行结算账户';
    } else if (v == 'AT01') {
      return '个人借记卡(存折)';
    } else if (v == 'AT02') {
      return '个人贷记卡账户';
    } else {
      return oct;
    }
  },
  formatAmountUpper(n) {
    if (!n || n == null || n == '') {
      return '';
    }

    /*
        *@desc - 输入的整数大于10位提示
        */
    let num = /\d+(?=.)/.exec(n);
    if (isArray(num)) {
      if (num[0].length > 11) {
        return '输入字符不支持大写展示';
      }
    }

    var fraction = ['角', '分'];
    var digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
    var unit = [['元', '万', '亿'], ['', '拾', '佰', '仟']];
    var head = n < 0 ? '欠' : '';
    n = Math.abs(n);
    var s = '';
    for (var i = 0; i < fraction.length; i++) {
      var sum = accMul(n , 10, 2);
      s += (
        digit[Math.floor(sum * 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;
    }

    var r =
      head +
      s
        .replace(/(零.)*零元/, '元')
        .replace(/(零.)+/g, '零')
        .replace(/^整$/, '零元整');
    return r === '元整' ? '输入字符不支持大写展示' : r;
  },
  CURRENCY_MAPS(res) {
    //  标识符 转换金额单位中文名
    let content = {
      RMB: '人民币',
      CNY: '人民币',
      '156': '人民币',
      USD: '美元',
      '840': '美元',
      AUD: '澳大利亚元',
      CHF: '瑞士法郎',
      EUR: '欧元',
      GBP: '英镑',
      HKD: '港币',
      JPY: '日元',
      SGD: '新加坡元',
      CAD: '加拿大元',
      KRW: '韩元'
    };
    return content[res];
  },
  getZJtype(zjKey) {
    if (zjKey == 'IC' || zjKey == 'Ind01' || zjKey == 'ind01') {
      return '身份证';
    } else if (zjKey == 'PP' || zjKey == 'Ind03' || zjKey == 'ind03') {
      return '护照';
    } else if (zjKey == 'IA' || zjKey == 'Ind04' || zjKey == 'ind04') {
      return '军官证';
    } else if (zjKey == 'Ind05' || zjKey == 'ind05') {
      return '士兵证';
    } else if (zjKey == 'IF') {
      return '户口本';
    } else if (zjKey == 'IR' || zjKey == 'Ind06' || zjKey == 'ind06') {
      return '港澳通行证';
    } else if (zjKey == 'IW' || zjKey == 'Ind07' || zjKey == 'ind07') {
      return '台胞通行证';
    } else if (zjKey == 'IP' || zjKey == 'Ind10' || zjKey == 'ind10') {
      return '警官证';
    } else if (zjKey == 'OT') {
      return '其他';
    } else {
      return '';
    }
  },
  nums(res) {
    //   字符串转换数字金额    //  未完成
    res = parseFloat(res / 100).toFixed(2);
    return res;
  },
  //   字符串转换数字金额,默认2位小数
  numz(res, num = 2) {
    if (typeof num !== 'number' || num < 0) return '';
    if (res === undefined || res === null) return '';
    if (res === '') res = '0';
    res = res + '';
    if (res.indexOf('.') > -1) {
      // res = parseFloat(res).toFixed(num);
      if (num === 0) {
        return res.split('.')[0];
      } else {
        let num1 = num - res.split('.')[1].length;
        if (num1 < 1) {
          return `${res.split('.')[0]}.${res.split('.')[1].substr(0, num)}`
        } else {
          for (let index = 0; index < num1; index++) {
            res += '0'
          }
          return res;
        }
      }
    } else {
      for (let index = 0; index < num; index++) {
        res += index === 0 ? '.0' : '0'
      }
      return res;
    }
    return res;
  },
  // 手机号脱敏
  formatPhone(v) {
    return v.replace(/(\d{3})\d*(\d{4})/, '$1****$2');
  },
  //日期 2022.04.13  =>  2022-04-13
  formatDateThree(v){
    if(!v){
      return '-'
    }
    return v.substr(0,4)+'-'+ v.substr(5,2)+'-'+ v.substr(8,2)
  },
  // 2000年3月16日 => 20000316
  formatDateFour(v){
    let str = '';
    if(!v){
      str = '-v';
    }else{
      v = v.substr(0,v.length-1)
      let arr = v.split(/\D/)
      let arrBth = arr.map((item,index) => {
        if(item.length < 2){
          return item = '0'+item
        }else{
          return item
        }
      })
      str = arrBth.join('');
    }
    return str;
  },
  formatDate(v) {
    if (!v) {
      return '-';
    }
    return v.substr(0, 8).replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
  },
  /**
   *
   * @param {*} res 姓名 收款姓名
   * 返回格式: *名 收**名
   */
  formatName(res) {
    if(/^[\u4E00-\u9FA5]{2}$/.test(res)) {
      return res.replace(/^[\u4e00-\u9fa5]/,'*');
    }else {
      let len = res.replace(/^(.{1})(.*)(.{1})$/,'$2').length;
      let star = '*'.repeat(len);
      return res.replace(/^(.{1})(.*)(.{1})$/,`$1${star}$3`);
    }
  },
  //科学展示金额 每三位加逗号 除100
  toThousands(num) {
    num = parseFloat(num / 100).toFixed(2);
    num += '';
    let x = num.split('.');
    let x1 = x[0];
    let x2 = x.length > 1 ? '.' + x[1] : '';
    let rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
      x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
  },
  //科学展示金额 每三位加逗号 不除100
  toThousandz(num) {
    if(num === '') {
      return '--';
    }
    num = parseFloat(num).toFixed(2);
    num += '';
    let x = num.split('.');
    let x1 = x[0];
    let x2 = x.length > 1 ? '.' + x[1] : '';
    let rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
      x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
  },
  /**
   *
   * @param {*} idtTp 证件类型
   * 返回格式:
   */
  idtTp(data) {
    switch (data) {
      case 'IC':
        return 'IC00'; //身份证
      case 'PP':
        return 'IC01'; //护照
      // case 'IA':
      //   return 'IC02';
      // case 'IW':
      //   return 'IC02';
      // case 'IP':
      //   return 'IC03';
      case 'IR':
        return 'IC04'; //港澳台往来通行证
      case 'IW':
        return 'IC04';
      case 'IT':
        return 'IC05'; //临时身份证
      case 'IF':
        return 'IC06'; //户口簿
      // case 'IC':
      //   return 'IC07';
      // case 'IC':
      //   return 'IC08';
      // case 'IC':
      //   return 'IC09';
      case 'RG':
        return 'IC10'; //组织机构代码证
      case 'RC':
        return 'IC11'; //营业执照
      // case 'IC':
      //   return 'IC12';
      case 'RD':
        return 'IC13'; //政府机构/公共机构批文
      // case 'IC':
      //   return 'IC14';
      // case 'IC':
      //   return 'IC15';
      // case 'IC':
      //   return 'IC16';
      // case 'IC':
      //   return 'IC17';
      // case 'IC':
      //   return 'IC18';
      // case 'IC':
      //   return 'IC19';
    }
  },
  /**
   *
   * @param {*} num 100000 => 1,000.00 || 1000.0 => 1,000.00
   */
  toThousandzDelEnd(num) {
    if(!/\./.test(num)) {
      num = num.replace(/\d{2}$/,'');
    }
    num = parseFloat(num).toFixed(2);
    num += '';
    let x = num.split('.');
    let x1 = x[0];
    let x2 = x.length > 1 ? '.' + x[1] : '';
    let rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
      x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
  },
  /**
   * @desc 时间戳转日期
   * @example timeStamp(1565257150000) || timeStamp(new Date())
   * @return '2019-08-08 09:00:00'
   *
  */
  timeStamp(str = '') {
    console.log('365====',str);
    if(!str) return '';
    const date = new Date(str);
    const Y = date.getFullYear() + '-';
    const M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
    const D = date.getDate().toString().padStart(2,'0');
    const h = ' ' + date.getHours() + ':';
    const m = date.getMinutes() + ':';
    const s = date.getSeconds();
    console.log('374===',Y + M + D + h + m + s) ;
    return Y + M + D + h + m + s;
  },

  /**
   * @desc 格式化座机号码
   * @example formatLandline(0532888899999)
   * @return '0532-88889999'
   *
  */
  formatLandline(str = '') {
    if(!str) return '';
    return str.replace(/^(\d{4})(\d+)$/, '$1-$2');
  },
  //结算方式
  toSettleWay(status){
    const statusObj = {
      '1': '存折',
      '2': '内转',
      '3': '汇款',
      '4': '划付',
      '5': '联名卡',
      '6': '转账',
      '7': '内转调账',
      '8': '网厅支取',
      '9': '借记卡',
      '10': '转账到单位',
      '11': '转账到法院',
    };
    return statusObj[status] || status;
  },
  //提取类型
  toWdwCls: function(status){
    const statusObj = {
      '11': '一般提取',
      '12': '销户提取',
    };
    return statusObj[status] || status;
  },
   //单据状态
  toWdwDocStat(status){
    const statusObj = {
      '1': '已登记',
      '2': '已审核',
      '3': '已结算',
      '4': '已入账',
    };
    return statusObj[status] || status;
  },
  toWdwDocStatPlus(status){
    const statusObj = {
      '12': '未结算',
      '21': '已结算',
      '22': '已入账'
    };
    return statusObj[status] || status;
  },
   //支付状态
  toPayDtar(status){
    const statusObj = {
      '1': '已支付',
      '2': '未支付',
      '3': '已退票',
    };
    return statusObj[status] || status;
  },
    //日期 202204  =>  2022-04
  formatDateTwo(v){
    if(!v){
      return '-'
    }
    return v.substr(0,4)+'-'+ v.substr(4,2)
  },
  toloanRela: function(status){//参贷关系
    const statusObj = {
      '01': '本人',
      '02': '配偶',
      '03': '共有人',
      '04': '共有人配偶'
    };
    return statusObj[status] || status;
  },
  /**
     * @desc 搜索关键字变色
     * @example changeColor('中证白酒指数基金','基金')
     * @return str
     *
    */
  changeColor(str = '', queryName = '',color = '#FF6000') {
    if(!str) {
      return str;
    }

    queryName = queryName.replace(/\s/g,''); //删除空格
    let query = queryName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); //转义特殊字符
    let regExp = new RegExp(query,'gm');
    return str.replace(regExp, `<span style="color:#FF6000;">${queryName}</span>`);
  },
  /**
   * @desc 文字溢出变...
   * @example textOverflow(20, ...) 20个字节
   * @return str
   *
  */
  textOverflow(str = '', len = 20, text = '...') {
    if(!str) {
      return '';
    }
    var realLength = 0;
    for (var i = 0; i < str.length; i++) {
      var charCode = str.charCodeAt(i);
      if(charCode >= 0 && charCode <= 128) {
        realLength += 1;
      }else {
        realLength += 2;
      }
      if(realLength > len) {
        str = str.substr(0, i) + text;
        return str;
      }
    }
    return str;
  },
  /**
   * @description MYD展示转换
   * @param {String} item
   */
  dataFormat(item) {
    let reg = /[a-z,A-Z]/g;
    let str = item.match(reg);
    if (str[0] == 'M') {
      return parseInt(item) + '个月';
    } else if (str[0] == 'Y') {
      return parseInt(item) + '年';
    } else if (str[0] == 'D') {
      return parseInt(item) + '天';
    }
  },
  /**
   * @desc - 格式化日期
   * @param {date: string} - 需要格式化的日期
   */
  dateFormat(date) {
    return date.replace(
      /(\d{4})(\d{2})(\d{2})/,
      '$1' + '/' + '$2' + '/' + '$3'
    );
  },
  /**
   * @desc - 格式化卡号
   * @param {date: string} - 需要格式化的卡号空格,然后去掉空格
   */
  spaceFormat(card) {
    return card.replace(/\s+/g, '');
  },
  /**
   * @desc - 千分位 增加人民币符号
   * @param {date: string}
   */
  formatAmountAdd(v) {
    if(v === '' || v < 0) {
      v = 0;
    }
    v = parseFloat(v).toFixed(2);
    if (typeof v === 'number') {
      v = v.toString();
    }

    if (v.indexOf('.') < 0) {
      v = `${v}.00`;
    } else if (v.split('.')[1].length === 1) {
      v = `${v}0`;
    }

    return '¥ '+ v.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
  },
  /**
   * @desc - 格式化卡类型
   * @param {date: string} - 需要格式化的卡类型
   */
  cardTypeFormat(type) {
    const allType = {
      '0': '借记卡',
      '1': '信用卡',
      '2': '公务卡',
      '3': '电子账户',
      'Y': '信用卡',
    };
    //  '1' 信用卡
    //  '2' 公务卡
    //  '3' 电子账户
    if(!type) {
      return '青岛银行借记卡'
    } else {
      return '青岛银行' + allType[type] || type;
    }
  },
  /**
   * @desc - 格式化年龄
   * @param {date: string} - 需要格式化的日期19910101
   */
  ageFormat(certNo) {
    let returnAge;
    let age;
    age = certNo.substr(6,8);
    let birthYear = age.substr(0, 4);
    let birthMonth = age.substr(4, 2);
    let birthDay = age.substr(6, 2);
    let d = new Date();
    let nowYear = d.getFullYear();
    let nowMonth = d.getMonth() + 1;
    let nowDay = d.getDate();
    if(nowYear == birthYear) {
      returnAge = 0;//同年 则为0岁
    } else {
      let ageDiff = nowYear - birthYear ; //年之差
      if(ageDiff > 0) {
        if(nowMonth == birthMonth) {
          let dayDiff = nowDay - birthDay;//日之差
          if(dayDiff < 0) {
            returnAge = ageDiff - 1;
          } else {
            returnAge = ageDiff ;
          }
        } else {
          let monthDiff = nowMonth - birthMonth;//月之差
          if(monthDiff < 0) {
            returnAge = ageDiff - 1;
          } else {
            returnAge = ageDiff ;
          }
        }
      } else {
        returnAge = -1;//返回-1 表示出生日期输入错误 晚于今天
      }
    }
    return returnAge;//返回周岁年龄
  },
  getFullTime(str = '') {
    if(!str) return '';
    const date = new Date(str);
    const Y = date.getFullYear() + '-';
    const M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
    const D = date.getDate().toString().padStart(2,'0');
    const h = ' ' + (date.getHours() < 10? '0' + date.getHours() : date.getHours()) + ':';
    const m = (date.getMinutes() < 10 ? '0' + date.getMinutes(): date.getMinutes()) + ':';
    const s = date.getSeconds() < 10? '0' + date.getSeconds():  date.getSeconds();
    return Y + M + D + h + m + s;
  }
};

App.js

/*
 * @Description: In User Settings Edit
 * @Author: your name
 * @Date: 2019-06-03 09:54:15
 * @LastEditTime: 2019-06-03 09:54:15
 * @LastEditors: your name
 */
import { dateFormat, numberComma } from 'vux';
import _ from 'lodash';
import Native from './Native';
import { __isUndefined } from './helper';
import { checkUrl } from './modules/checkUrl';
import {
  __showLoading,
  __hideLoading
} from '@/common/js/helper';
window.App = {
  Native,
  _emitHook(vm, hook) {
    const _emit = _vm => {
      const child = _vm.$children;
      const handlers = _vm.$options[hook];
      if (handlers) {
        if (handlers.apply) {
          handlers.call(_vm, ...[...arguments].slice(2));
        } else {
          for (let i = 0, j = handlers.length; i < j; i++) {
            handlers[i].call(_vm, ...[...arguments].slice(2));
          }
        }
      }
      if (_vm._hasHookEvent) {
        _vm.$emit('hook:' + hook);
      }
      if (child.length) {
        for (let i = 0, j = child.length; i < j; i++) {
          _emit(child[i]);
        }
      }
    };
    _emit(vm);
  },
  // 获取scroller组件的高度
  getScrollerHeight() {
    let headerHeight = $('.tabs-header').outerHeight();
    let oHeight = $(window).height() - $(document.body).outerHeight();

    return '-' + (headerHeight + oHeight);
  },
  /**
   * @desc - 获取 url 上的全部传参并转成对象
   * @example App.parseQueryString() => {}
   */
  parseQueryString(queryString = window.location.search) {
    let kv;
    let result = {};
    let bool = {
      true: true,
      false: false
    };
    let searchStr =
      queryString.indexOf('?') === 0 ? queryString.substr(1) : queryString;
    searchStr = searchStr ? searchStr.split('&') : '';
    for (let i = 0; i < searchStr.length; i++) {
      let index = searchStr[i].indexOf('=');
      kv = [searchStr[i].substring(0,index), searchStr[i].substring(Number(index)+1)];
      kv[1] = decodeURIComponent(kv[1]);
      kv[1] = __isUndefined(bool[kv[1]]) ? kv[1] : bool[kv[1]];
      result[kv[0]] = kv[1];
    }
    return result;
  },

  /**
   * @desc - 全局绑定事件
   * @param  {String}   evts 事件类型,多个事件用空格分隔
   * @example App.on('xxxx', fn)
   */
  on(evts, fn) {
    evts.split(/\s+/g).forEach(eventName => {
      document.addEventListener(eventName, fn, false);
    });
  },

  /**
   * @desc - 全局移除事件
   * @param  {String}   evt    事件类型
   * @example App.off('xxxx', fn)
   */
  off(evt, fn) {
    document.removeEventListener(evt, fn, false);
  },

  /**
   * @desc - 全局触发绑定事件
   * @param  {String}   evt    事件名
   * @param  {Object}   data   需要传递的参数
   * @example App.trigger('xxxx', {})
   */
  trigger(evtName, data = {}) {
    let evt = document.createEvent('Events');
    evt.initEvent(evtName, false, true);
    evt.data = data;
    document.dispatchEvent(evt);
    return evt;
  },

  /**
   * @desc - 获取当前的系统及所支持的css前缀
   * @example App.device => { cssPre: webkit || '', os: ios ||  android}
   */
  device: {
    alipayClient: navigator.userAgent.indexOf('AlipayClient') >= 0|| navigator.userAgent.indexOf('BQDMobileBank') >= 0,
    cssPre: document.body.style.webkitBorderImage !== undefined ? 'webkit' : '',
    os: (navigator.userAgent.indexOf('iPhone') > -1 || navigator.userAgent.indexOf('iPad') > -1) ? 'ios' : 'android'
  },
  /**
   * @desc - 脱敏账号、手机号、证件号或者中文名字
   * @param {val: string} - 要转换的字符串
   * @example App.protect('13800138000') => 138****8000
   * @example App.protect('张三') => 张**
   */
  protect(val) {
    const REGEXP_MOBILE = /^(13[0-9]|15[7-9]|15[0-6]|18[5-9]|180|1[6-7]6)[0-9]{8}$/;
    const REGEXP_CNINA = /[\u4e00-\u9fa5]+$/;
    const MATCH_ACCOUNT = /^(\d{4})\d+(\d{4}|\d{3}[a-zA-Z])$/;
    const MATCH_MOBILE = /^(\d{3})\d+(\d{4}$)/;
    const MATCH_CNINA = /^([\u4e00-\u9fa5])[\u4e00-\u9fa5]+$/;

    if (val.length > 8) {
      return String(val).replace(
        REGEXP_MOBILE.test(val) ? MATCH_MOBILE : MATCH_ACCOUNT,
        ($1, $2, $3) => $2 + '****' + $3
      );
    } else if (REGEXP_CNINA.test(val)) {
      return val.replace(MATCH_CNINA, ($1, $2, $3) => $2 + '**');
    } else {
      return val;
    }
  },

  /**
   * @desc - 格式化日期
   * @param {date: string} - 要转换时间戳
   * @param {fmt: string} - 要转换成的格式
   * @example App.dateFormat(new Date().getTime(), 'YYYY-MM-DD HH:mm:ss') => 2017-12-19 11:30:16
   */
  dateFormat,
  /**
   * @desc - 获取n个月前的日期
   * @param {startDate: string} - 起始日期对象
   * @param {n: number} - 月数
   * @example App.getDateByMonth(new Date(), 3)
   */
  getDateByMonth(startDate, n) {
    let year = startDate.getFullYear();
    let month = startDate.getMonth() - n;
    let date = startDate.getDate();

    if (month < 0) {
      year = year - 1;
      month = month + 12;
    }

    return new Date(year, month, date);
  },
  /**
   * @desc - 跳转到结果页
   * @param {opts.docTitle: String} - 页面标题,默认取document.title
   * @param {opts.type: String} - 结果页类型,默认success, 取值有success,error
   * @param {opts.title: String} - 结果标题,默认值'恭喜您,操作成功'
   * @param {opts.code: String} - 错误码,type为error时传
   * @param {opts.msg: String} - 成功或失败信息
   * @param {opts.backUrl: String} - 点击返回按钮回到的页面url, 不写默认返回上一级
   * @example App.pushResult({type: 'error', title: '操作失败', code: 'EF2345', 'msg': ''})
   */
  pushResult(opts) {
    const defaults = {
      docTitle: document.title,
      type: 'success',
      title: '',
      code: '',
      msg: '',
      backUrl: '',
    };

    opts = Object.assign({}, defaults, opts);

    Native.pushWindow({
      url: '/result/index/index.html',
      data: opts,
      param: {
        defaultTitle: opts.docTitle
      }
    });
  },

  /*
   * @desc - 跳转协议页面
   * @param {opts.type} 协议类型
   * @param {opts.prdCde} 产品代码
   *
   */
  pushProtocol(opts) {
    return new Promise(resolve => {
      App.Native.rpc({
        operationType: 'com.MB309009',
        data: {
          prdCode: opts.prdCde,
          financeFileType: opts.type
        }
      }).then(r => {
        console.log(r.data);
        if(r.errorCode === 'ECPC2016') {
          App.Native.alert('该产品暂无此文件。');
          return;
        }
        if (r.errorCode !== '0') {
          App.Native.alert(r.errorMsg);
          return;
        }
        let latterName = r.data.fasDFStUrl.substring(r.data.fasDFStUrl.length-5);
        console.log(latterName+123123);
        console.log(/\.(htm|html?)$/.test(latterName));
        if(/\.(htm|html?)$/.test(latterName)){
          App.Native.pushWindowOnline({
            url: r.data.fasDFStUrl,
            param: {
              defaultTitle: opts.title || document.title,
              readTitle: false
            }
          });
        }else{
          var agent = navigator.userAgent.toLowerCase();
          var android = agent.indexOf('android');
          var iphone = agent.indexOf('iphone');
          var ipad = agent.indexOf('ipad');
          if (android != -1) {
            App.Native.pushWindow({
              url: '/sale_assets/sale/pdf_page.html',
              data: {
                Url: r.data.fasDFStUrl,
              },
              param: {
                defaultTitle: opts.title || document.title,
                readTitle: false
              }
            });
          }
          if (iphone != -1 || ipad != -1) {
            checkUrl(r.data.fasDFStUrl).then(()=>{
              App.Native.pushWindowOnline({
                url: r.data.fasDFStUrl,
                param: {
                  defaultTitle: opts.title || document.title,
                  readTitle: false
                }
              });
            });
          }
        }
      });
    });
  },
  /**
   * @desc - 安卓和ios打开pdf文件处理并展示
   * @param opts.url pdf地址
   * @param opts.title 页面标题
   * @example App.showPdf({url:"https:www.abc.com/a.pdf",title:"基金协议"})
   */
  showPdf(opts){
    var agent = navigator.userAgent.toLowerCase();
    var android = agent.indexOf('android');
    var iphone = agent.indexOf('iphone');
    var ipad = agent.indexOf('ipad');
    if (android != -1) {
      App.Native.pushWindow({
        url: '/sale_assets/sale/pdf_page.html',
        data: {
          Url: opts.url,
        },
        param: {
          defaultTitle: opts.title || document.title,
          readTitle: false
        }
      });
    }
    if (iphone != -1 || ipad != -1) {
      checkUrl(opts.url).then(()=>{
        App.Native.pushWindowOnline({
          url:  opts.url,
          param: {
            defaultTitle: opts.title || document.title,
            readTitle: false
          }
        });
      });
    }

  },
  /**
   * @desc - 安卓和ios打开pdf文件处理并展示,方法2:兼容部分安卓机型打开pdf时内存溢出
   * @param opts.url pdf地址
   * @param opts.title 页面标题
   * @example App.showPdf2({url:"https:www.abc.com/a.pdf",title:"基金协议"})
   */
  showPdf2(opts){
    var agent = navigator.userAgent.toLowerCase();
    var android = agent.indexOf('android');
    var iphone = agent.indexOf('iphone');
    var ipad = agent.indexOf('ipad');
    if (android != -1) {
      App.Native.pushWindow({
        url: '/fund/pdf/index.html',
        data: {
          Url: opts.url,
        },
        param: {
          defaultTitle: opts.title || document.title,
          readTitle: false
        }
      });
    }
    if (iphone != -1 || ipad != -1) {
      checkUrl(opts.url).then(()=>{
        App.Native.pushWindowOnline({
          url:  opts.url,
          param: {
            defaultTitle: opts.title || document.title,
            readTitle: false
          }
        });
      });
    }

  },

    /**
   * @desc - 安卓和ios打开pdf文件处理并展示,方法2:兼容部分安卓机型打开pdf时内存溢出
   * @param opts.url pdf地址
   * @param opts.title 页面标题
   * @example App.nobleMetalShowPdf({url:"https:www.abc.com/a.pdf",title:"贵金属协议"})
   */
    nobleMetalShowPdf(opts){
      var agent = navigator.userAgent.toLowerCase();
      var android = agent.indexOf('android');
      var iphone = agent.indexOf('iphone');
      var ipad = agent.indexOf('ipad');
      if (android != -1) {
        App.Native.pushWindow({
          url: '/nobleMetal/pdf/index.html',
          data: {
            Url: opts.url,
          },
          param: {
            defaultTitle: opts.title || document.title,
            readTitle: false
          }
        });
      }
      if (iphone != -1 || ipad != -1) {
        checkUrl(opts.url).then(()=>{
          App.Native.pushWindowOnline({
            url:  opts.url,
            param: {
              defaultTitle: opts.title || document.title,
              readTitle: false
            }
          });
        });
      }
  
    },

   /*
   * @desc - 基金海融宝跳转协议页面************
   * @param res=>2  基金风险提示函 ;
   * @param res=>3  投资人权益须知 ;
   *
   */
  loadMB309007(res) {
    App.Native.rpc({
      operationType: 'com.MB309009',
      data: {
        prdCode: '000001',
        financeFileType: res
      }
    }).then(r => {
      if (r.errorCode == 0) {
        let title;
        if(res == '2'){
          title = '基金风险提示函';
        }else{
          title = '投资人权益须知';
        }
        // r.data.fasDFStUrl = 'http://wx.qdccb.cn/M00/06/37/CgFRWFx96S6AY2BBAAUXOugBzJ4715.pdf'
        let latterName = r.data.fasDFStUrl.substring(r.data.fasDFStUrl.length-5);
        console.log(latterName+123123, title);
        console.log(/\.(htm|html?)$/.test(latterName));
        if(/\.(htm|html?)$/.test(latterName)){
          App.Native.pushWindowOnline({
            url: r.data.fasDFStUrl,
            param: {
              defaultTitle: title,
              readTitle: false
            }
          });
        }else{
          var agent = navigator.userAgent.toLowerCase();
          var android = agent.indexOf('android');
          var iphone = agent.indexOf('iphone');
          var ipad = agent.indexOf('ipad');
          if (android != -1) {
            console.log(title, 888);
            App.Native.pushWindow({
              url: '/sale_assets/sale/pdf_page.html',
              data: {
                Url: r.data.fasDFStUrl,
              },
              param: {
                defaultTitle: title,
                readTitle: false
              }
            });
          }
          if (iphone != -1 || ipad != -1) {
            App.Native.pushWindowOnline({
              url: r.data.fasDFStUrl,
              param: {
                defaultTitle: title,
                readTitle: false
              }
            });
          }
        }
      } else {
        App.Native.alert(r.errorMsg);
      }
    });
  },
  /*
   * @desc - 跳转协议页面   **********资管请求PDF文件************
   * @param {opts.type} 协议类型
   * @param {opts.prdCde} 产品代码
   *
   */
  salepushProtocol(opts) {
    return new Promise(resolve => {
      App.Native.rpc({
        operationType: 'com.MB706634',
        data: {
          zgProCode: opts.zgProCode,
          turnPageBeginPos: opts.turnPageBeginPos,
          turnPageShowNum: opts.turnPageShowNum,
          zgDate: opts.zgDate,
          zgFiletype: opts.zgFiletype,
          zgFileId: opts.zgFileId
        }
      }).then(r => {
        if (r.errorCode !== '0') {
          App.Native.alert(r.errorMsg);
          return;
        } else if (r.data.zgUrlList.length > 0) {
          this.data = r.data.zgUrlList;
        }
      });
    });
  },
  /**
   * @desc - 格式化数字
   * @param {no: string} - 需要格式化的数字
   * @param {split: string} - 需要分割的标志 默认是空格
   * @example App.numberFormat('19990102', '/') => 1999/01/02
   * @example App.numberFormat('6222023301231050271') => 6222 0233 0123 1050 271
   */
  numberFormat(no = '', split = ' ') {
    if (!no) return;

    if (no.length == 8) {
      return no.replace(
        /(\d{4})(\d{2})(\d{2})/,
        '$1' + split + '$2' + split + '$3'
      );
    } else {
      return no.replace(/(\d{4})(?=\d)/g, '$1' + split);
    }
  },

  /**
   * @desc - 格式化金额,保留2位小数,四舍五入,长度不够自动补0
   * @param { cash: string } - 需要格式化的金额
   * @example App.cashFormat(9527.127) => 9527.13
   * @example App.cashFormat(9527) => 9527.00
   */
  cashFormat(cash = 0, len = 2) {
    return App.numberRound(cash, len);
  },

  /**
   * @desc  检查字符串是否为合法的手机号码
   * @param {number: string }  - 需要检验的手机号码
   * @returns {boolean}  是否为合法手机号码
   * @example let m1 = '13112345678';
   * App.legalMobile(m1) => true;
   * let m2 = '15312345678';
   * App.legalMobile(m2) => false;
   */
  legalMobile(string) {
    // let REGEXP_PHONE = new RegExp(/^(13[0-9]|15[5-9]|15[0-2]|18[4-9])[0-9]{8}$/)
    let REGEXP_PHONE = new RegExp(/^1\d{10}$/);
    return REGEXP_PHONE.test(string);
  },

  /**
   * @desc  检查字符串是否为正整数
   * @param { number: string }  - 需要检验的字符串
   * @example let number = '32';
   * App.legalInteger(number) => true;
   */
  legalInteger(string) {
    let REGEXP_INTEGER = new RegExp(/^[0-9]+$/);
    return REGEXP_INTEGER.test(string);
  },
  /**
   * @desc  检查字符串是否为合法的身份证号码
   * @param {id: string} 需要校验的身份证号码
   * @example let id = '430421197710177894';
   * App.legalIDNumber(id) => true;
   */
  legalIdNumber(id) {
    let AREA_CODE = {
      11: '北京',
      12: '天津',
      13: '河北',
      14: '山西',
      15: '内蒙古',
      21: '辽宁',
      22: '吉林',
      23: '黑龙江',
      31: '上海',
      32: '江苏',
      33: '浙江',
      34: '安徽',
      35: '福建',
      36: '江西',
      37: '山东',
      41: '河南',
      42: '湖北',
      43: '湖南',
      44: '广东',
      45: '广西',
      46: '海南',
      50: '重庆',
      51: '四川',
      52: '贵州',
      53: '云南',
      54: '西藏',
      61: '陕西',
      62: '甘肃',
      63: '青海',
      64: '宁夏',
      65: '新疆',
      71: '台湾',
      81: '香港',
      82: '澳门',
      91: '国外'
    };

    switch (id.length) {
    case 15:
    case 18: {
      break;
    }
    default: {
      return false;
    }
    }

    let testInt = id.length == 15 ? id : id.substr(0, 17);
    if (!_.isInteger(Number(testInt))) {
      return false;
    }

    let areaCode = parseInt(id.substr(0, 2));
    if (!AREA_CODE[areaCode]) {
      return false;
    }

    let birthDay = id.length == 15 ? '19' + id.substr(6, 6) : id.substr(6, 8);
    if (!_.isInteger(Number(birthDay))) {
      return false;
    }

    if (id.length == 18) {
      let testNumber =
        (parseInt(id.charAt(0)) + parseInt(id.charAt(10))) * 7 +
        (parseInt(id.charAt(1)) + parseInt(id.charAt(11))) * 9 +
        (parseInt(id.charAt(2)) + parseInt(id.charAt(12))) * 10 +
        (parseInt(id.charAt(3)) + parseInt(id.charAt(13))) * 5 +
        (parseInt(id.charAt(4)) + parseInt(id.charAt(14))) * 8 +
        (parseInt(id.charAt(5)) + parseInt(id.charAt(15))) * 4 +
        (parseInt(id.charAt(6)) + parseInt(id.charAt(16))) * 2 +
        parseInt(id.charAt(7)) * 1 +
        parseInt(id.charAt(8)) * 6 +
        parseInt(id.charAt(9)) * 3;
      if (id.charAt(17) != '10X98765432'.charAt(testNumber % 11)) {
        return false;
      }
    }

    return true;
  },

  /**
   * @desc  密码检验,检验的规则是,数字,字母,特殊字符至少两种以上,长度8 - 12位之间
   * @param {paw: string} 需要校验的密码
   * @example App.legalPassword(paw) => true || false
   */
  legalPassword(paw) {
    let specialWord = /[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]+?/;
    let numberWord = /\d+?/;
    let englishWord = /[a-zA-Z]+?/;
    paw = paw.replace(/\s+/, '');

    if (paw.length < 8 || paw.length > 12) return false;
    let res = [specialWord, numberWord, englishWord].filter(item =>
      item.test(paw)
    );
    return res.length >= 2;
  },

  /**
   * @desc  格式化数字,并且四舍五入,长度不够的自动补0
   * @param {num: string, default:0} 需要转格式的数字
   * @param {len: number, default:2} 需要保留多少位小数
   */
  numberRound(num = 0, len = 2) {
    const pow = Math.pow(10, len + 1);
    const abs = p => Math.abs(p);
    const s = p => String(p);
    const f = p => p / pow;
    const tf = p => Number(p).toFixed(len);
    const minus = /^\-/.test(s(num));
    let [integer, point] = s(num).split('.');

    if (!+point || point.length <= len) return tf(num);

    point = s(point).substr(0, len + 1);

    if (point.length <= len) {
      let pre = point.length - len < 0 ? point.length - len : 1;
      point = point + '0'.repeat(abs(pre));
    }

    point =
      abs(integer) + (point[point.length - 1] >= 5 ? f(+point + 1) : f(point));

    return tf(minus ? 0 - point : point);
  },
  /*
     @desc 获取设备id
    */
  getDeviceId(type) {
    return new Promise(resolve => {
      Native.getDeviceInfo().then(res => {
        let androidVersion = res.androidVersion;
        let newDeviceId = res.newDeviceId;
        App.Native.getUserInfo(info => {
          let deviceStr;
          // 第一次进入App,info没有userInfo对象,会报错
          if (!info.userInfo) {
            info.userInfo = {};
          }
          if (this.device.os == 'android') {
            if (type == 'old') {
              deviceStr = res.imei.split(':')[0];
            } else {
              if(androidVersion >= 29) {
                deviceStr = `${newDeviceId}|${info.userInfo.session_cifNo || ''}|`;
                resolve(deviceStr);
                return;
              }
              deviceStr = `${res.imei}|${
                res.androidId == '' ||
                  res.androidId == '9774d56d682e549c' ||
                  res.androidId.length < 16
                  ? '0'
                  : res.androidId.toUpperCase()
                }|${
                res.mac == '' ||
                  res.mac == '000000000000' ||
                  res.mac == '020000000000'
                  ? '0'
                  : res.mac.toUpperCase()
                }|${info.userInfo.session_cifNo || ''}|`;
            }
          } else {
            deviceStr = `${res.deviceId}${info.userInfo.session_cifNo}`;
          }
          resolve(deviceStr);
        });
      });
    });
  },
  /**
   * @method getNoCifDeviceId
   * @desc 获取未拼接设备号
   */
  getNoCifDeviceId() {
    return new Promise(resolve => {
      AlipayJSBridge.call('bqdGetNoCifDeviceId', result => {
        resolve(result);
      });
    });
  },
  /**
   * @desc 验证邮箱格式
   *
   */
  checkEmail(res) {
    let ab = /^([0-9a-zA-Z\.])+[@]{1}([0-9a-zA-Z])+[\.]{1}([0-9a-zA-Z\.])*?([0-9a-zA-Z])+$/;
    return ab.test(res);
  },
  /**
   * @method checkMobile
   * @desc 验证手机号格式
   * @param {res}
   */
  checkMobile(res='') {
    const reg = /^1\d{10}$/;
    return reg.test(res);
  },
  /**
   * @desc 过滤非法字符
   */
  // checkName(res) {
  //   let ab = /[\` \. \~ \¥ \( \! \? \— \:\,\。\;\“ \” \‘ \、\《 \》 \| \@ \# \$ \% \^ \& \* \( \) \_ - = \+ \< \> \? \: \" \{ \} \, \.\/ \; \' \【 \】 \[ \] \\\$ \\\n \\\r \\\^ \\\* \\\( \\\)  \\\[ \\\] \\ \\\| \\\? \\\\  \\\+  \\\. 鈡泒沎沒沕]/;
  //   return ab.test(res);
  // },
  /**
   * @desc 过滤姓名非法字符
   */
  checkName(res) {
    // let ab = /[(\`)(\.)(\~)(\¥)(\!)(\?)(\—)(\:)(\,)(\。)(\;)(\“)(\”)(\‘)(\、)(\《)(\》)(\|)(\@)(\#)(\$)(\%)(\^)(\&)(\*)(\_)(-)(=)(\+)(\<)(\>)(\?)(\:)(\")(\{)(\})(\,)(\.)(\/)(\;)(\')(\【)(\】)(\[)(\])(\\\$)(\\\n)(\\\r)(\\\^)(\\\*)(\\\[)(\\\])(\\)(\\\|)(\\\?)(\\\\)(\\\+)(\\\.)鈡泒沎沒沕]/;
    // let ab = new RegExp(/[(\鈡)(\泒)(\沎)(\沒)(\沕)(\~)(\$)(\%)(\^)(\&)(\*)(\*)(\()(\))(\+)(\=)(\[)(\])(\{)(\})(\|)(\\)(\:)(\')(\`)(\")(\,)(\.)(\/)(\<)(\>)(\?)(\!)(\\\$)(\\\n)(\\\r)(\\\^)(\\\*)(\\\[)(\\\])(\\)(\\\|)(\\\?)(\\\\)(\\\+)(\\\.)]+/);
    // let checkSpace = /^\s+|^[\u4e00-\u9fa5]+\s+[\u4e00-\u9fa5]+$|\s+$/;
    // return ab.test(res) || checkSpace.test(res);

    let ab = new RegExp(/[(\鈡)(\泒)(\沎)(\沒)(\沕)(\~)(\~)(\$)(\$)(\¥)(\¥)(\%)(\%)(\^)(\&)(\#)(\+)(\=)(\|)(\\)(\/)(\@)(\[)(\])(\<)(\>)(\〈)(\〉)(\‘)(\’)(\“)(\”)(\^)(\&)(\*)(\*)(\@)(\#)(\+)(\=)(\[)(\])(\【)(\】)(\{)(\})(\{)(\})(\|)(\\)(\:)(\:)(\')(\')(\`)(\`)(\、)(\")(\")(\,)(\,)(\/)(\<)(\>)(\?)(\?)(\!)(\!)(\\\$)(\\\n)(\\\r)(\\\^)(\\\*)(\\\[)(\\\])(\\)(\\\|)(\\\?)(\\\\)(\\\+)]+/);
    // 以上匹配会匹配上英文小括号(),故引用的地方进行了手动去除
    let checkSpace = /^\s+$/;
    //允许输入空格 但不能全部为空格
    let ellipsis1 = /\.{3}/;
    let ellipsis2 = /\…/;

    return ab.test(res) || checkSpace.test(res) ||ellipsis1.test(res)||ellipsis2.test(res);
  },
  /**
   * @desc 过滤备注非法字符
   */
  checkRemarks(res) {
    let ab = /[\`  \~ \¥  \! \? \— \:\;\“ \” \‘ \、\《 \》 \| \@ \# \$ \% \^ \& \*  \_ - = \+ \< \> \? \: \" \{ \}  \/ \; \' \【 \】 \[ \] \\\$ \\\n \\\r \\\^ \\\* \\\[ \\\] \\ \\\| \\\? \\\\  \\\+   鈡泒沎沒沕]/;
    return ab.test(res);
  },
  /**
   * @description: 转账模块备注非法字符过滤
   * @param {type}
   * @return:
   */
  characterFiltering(res){
    // let ab = /[\`  \~  \!  \#   \\\$  \%   \\\^  \&  \\\*  \\\(  \\\)  \{  \}  \\\[  \\\]  \:  \;    \\"  \'  \\\|  \\\?  \_  \/  \<  \>  \@  \\\\\  \-  \\\+  \=  \\\.  \,    鈡泒沎沒沕  \n  \r]/;
    let ab = /[\`\~\!\#\\\$\%\\\^\&\\\*\\\(\\\)\{\}\\\[\\\]\:\;\\"\'\\\|\\\?\_\/\<\>\@\\\\\\-\\\+\=\\\.\,鈡泒沎沒沕\n\r]/;  // 不校验空格
    return ab.test(res);
  },
  // 转账模块备注非法字符过滤  26702去除非法字符过滤,以程序要求为准 保留五个特殊字符
  characFilteringTransUse(res){
    let ab = /[\&\>\<\"\"\'\'\|\|]/;
    return ab.test(res);
  },
  /**
   * @method verify
   * @desc 弹出账号核实框
   * @param {cardNo: string, backUrl: string} //cardNo为必填项
   * @param {} 跳转成功页面,点击关闭要跳转的页面
   * @example App.verify({cardNo: ''}).then( r => {暂不核实}).catch(err => {没有需要核实的卡号})
   *
   */
  verify(opts) {
    const { session_customerId, cardNo } = this.vm.$store.getters.getUserInfo;
    const defaults = {
      session_customerId: session_customerId,
      cardNo: cardNo,
      backUrl: ''
    };
    opts = Object.assign({}, defaults, opts);

    let p = new Promise((resolve, reject) => {
      Native.rpc({
        operationType: 'com.MB610006',
        showError: true,
        data: {
          cardNo: '',
          custNo: opts.session_customerId //网银客户号
        }
      }).then(s => {
        //需要身份验证
        console.log(opts.cardNo + '交易账号');
        let Arr = s.data.suppressedCardList;
        let isExit = Arr.some(item => {
          return item.cardNo == opts.cardNo;
        });
        console.log(isExit);
        if (isExit) {
          console.log('为了保证账户安全,需加强身份验');
          Native.confirm({
            title: '提示',
            message:
              '您的账户长时间未进行交易,为了保证账户安全,需加强身份验证,请对以下信息进行核实。',
            okButton: '现在核实',
            cancelButton: '暂不核实'
          }).then(ok => {
            console.log('123');
            console.log(ok);
            let cardNoArr = JSON.stringify(s.data.suppressedCardList);
            resolve([ok, cardNoArr]);
          });
        } else {
          reject();
        }
      }).catch((err)=>{
        if(opts.tradeFlag=='transfer'){
          //转账交易时,无网络时的异常处理
          resolve([{ok:false}])
        }
      });
    });
    let p2 = new Promise((resolve, reject) => {
      p.then(([r, cardNoArr]) => {
        if (r.ok == true) {
          console.log('现在核实' + cardNoArr);
          if(opts.tradeFlag=='transfer'){
            resolve();
          }
          App.Native.pushWindow({
            url: '/financing/financialPurchase/identityVerification.html',
            data: {
              list: cardNoArr,
              backUrl: opts.backUrl
            },
            param: {
              defaultTitle: '身份验证'
            }
          });
        } else {
          console.log('暂不核实');
          resolve();
        }
      }).catch(() => {
        console.log('88');
        reject();
      });
    });
    return p2;
  },
  remoteLog(eventId, params = {}) {
    const keys = Object.keys(params);
    const paramStr = keys
      .map(el => {
        return `${el}=${params[el]}`;
      })
      .join('^');
    Native.remoteLog(eventId, paramStr);
  },
  // picType, '00'-身份证正面 '01'-身份证反面 '02'-银行卡
  startOCR(faceTransCode, picType = '02') {
    return new Promise((resolve, reject) => {
      App.Native.rpc({
        operationType: 'com.MB100005',
        data: {
          session_customerId: 'PB100001508365',
          sessionId: 'cifNo8efef35426c644d6a43e1fa80f2624071535450953443certNo',
          deviceID: '357052090185893',
          transCode: 'IMGB10000003',
          picType,
          cstClient: App.device.os == 'android' ? 'ANDROID' : 'IOS',
          faceTransCode,
          session_cifNo: '7700021857',
          requestChannel: 'AC10000008'
        }
      }).then(res => {
        if (res.errorCode == 0) {
          res.data.channelNo = res.data.requestChannel;
          App.Native.ocrScan(res.data).then(result => {
            resolve(result.ocrback);
          });
        } else {
          App.Native.alert(res.errorMsg);
        }
      });
    });
  },
  //ALM00018616增加root判断
  getDeviceRoot() {
    return new Promise((resolve, reject) => {
      App.Native.getDeviceRoot().then(result => {
        resolve(result);
      });
    });
  },
  //ALM00018616增加root,改变人脸流程。 兼容原先代码
  startOldFaceWay(opts,opts1) {
    //将原先流程提取出来未做改变
    const { session_customerId, sessionId, session_cifNo  } = App.vm.$store.getters.getUserInfo || {};
    const { getDeviceId } = App.vm.$store.getters;

    const defaults = {
      session_customerId,
      sessionId,
      deviceID: getDeviceId,
      transCode: 'IMGB10000003',
      picType: '20',
      cstClient: App.device.os == 'android' ? 'ANDROID' : 'IOS',
      faceTransCode: '0602',
      session_cifNo,
      requestChannel: 'AC10000008'
    };

    const data = Object.assign({}, defaults, opts);

    return new Promise((resolve, reject) => {
      App.Native.rpc({
        operationType: 'com.MB100005',
        data
      }).then(res => {
        if (res.errorCode == 0) {
          res.data.faceUsedType = '00';
          res.data.channelNo = res.data.requestChannel;
          if(res.data.faceType == 'checkPersonEx'){
            res.data.cstCertNoImageId = opts.busiSerialNo;
          }
          //原先人脸识别的方法,增加这块内容就是六个月无交易的方法,
          // 在ALM00018616整改的时候,整合一下。
          if (opts1) {
            if (res.data.custName == '') {
              res.data.custName = data.name;
            }
            res.data.cstName = data.name;
          }
          console.log('人脸流水号=>',res);
          // 调起成功正式进入人脸识别交互流程埋点数据准备
          res.data.dealId = opts.dealId;
          App.Native.getFace(res.data).then(result => {
            console.log(result, 333444);
            // 得自己新增result新增参数transferFlowNo
            result.transferFlowNo = '';
            resolve([result,res]);
            // 人脸识别成功埋点改为客户端做
            if(result.status) {
              // Native.remoteLog('mb_FaceAuth_04', {dealId: opts.dealId});
            } else {
              // Native.remoteLog('mb_FaceAuth_04', {dealId: opts.dealId, Errorcode: result.faceResultCode});
            }
          });
        } else {
          App.Native.alert(res.errorMsg);
          reject(res);
        }
      });
    });
  },
  //ALM00018616增加root,改变人脸流程。
  startNewFaceWay(opts, opts1) {
    let tradeFlag = opts&&opts.tradeFlag?opts.tradeFlag:"";//转账交易标识
    return new Promise((resolve, reject) => {
      //为了兼容原先人脸传递的参数,在这补充为空,
      // 根据各个交易中需要传递的参数
      const addArray = {
        data: {
          faceUsedType:'00',
          //相同
          requestChannel:'',
          //以上
          channelNo:'',
          //相同
          //以上
          faceType:'',
          cstCertNoImageId:'',
          certNo:'',
          channelSeriaNo:'',
          cstClient:'',
          accessLogo:'',
        }
      }
      //六个月无交易增加姓名传递
      if (opts1) {
        opts.cstName = opts.name;
      }
      if(opts && !opts.sceneId) {
        opts.sceneId = 'MBBPublic';
      }
        App.Native.getFace(opts).then((result)=> {
          // result新增参数transferFlowNo
          if(result && result.error == 1) {
            Native.alert('为了您的资金安全,请升级使用最新版APP').then(()=>{
              //转账交易异常情况抛出
              if(tradeFlag =='transfer'){
                resolve({errorCode:'1'});
              }
            });
            __hideLoading();//因为之后有逻辑中有loading需要隐藏一下
            return
          } else {
            resolve([result,addArray]);
          }
        });
    });
  },
  startFace(opts = {}) {
    let tradeFlag = opts&&opts.tradeFlag?opts.tradeFlag:"";//转账交易标识
    // root 触发人脸识别埋点
    Native.remoteLog('mb_FaceAuth_01', {dealId: opts.dealId});
    return new Promise((resolve, reject) => {
      //增加root判断,
      //root方法不存在则证明为旧客户端,走原先的人脸识别流程,
      //root方法存在证明为新客户端,则走新人脸流程。
      //客户端升级为新人脸方法
      this.getDeviceRoot().then((result) => {
        if(result && result.error == 1) {
            // this.startOldFaceWay(opts).then((res1)=> {
            //   resolve(res1);
            // });
          Native.alert('为了您的资金安全,请升级使用最新版APP').then(()=>{
            //转账交易异常情况抛出
            if(tradeFlag =='transfer'){
              resolve({errorCode:'1'});
            }
          })
        } else {
          if(result.isRoot == '0') {
            this.startNewFaceWay(opts).then((res2) => {
              resolve(res2);
            });
          } else if (result.isRoot == '1') {
            // 调起人脸识别失败(因手机被root)埋点
            __hideLoading();
            Native.remoteLog('mb_FaceAuth_02', {dealId: opts.dealId});
            App.Native.alert('系统检测到您的设备被root,交易存在风险,为保证您的资金安全,请更换安全的设备进行交易');
            reject();
          } else {
            App.Native.alert(result.error).then(()=>{
              //转账交易异常情况抛出
              if(tradeFlag =='transfer'){
                resolve({errorCode:'1'});
              }
            });
          }
        }
      })
    })
  },
  /**
   * @desc - 六个月无交易人脸识别 引100005接口数据name字段没有数据
   * @param {name: string} - 对象
   * @example App.startFaceNoName(opts = {})
   */
  startFaceNoName(opts = {},opts1 = true) {
    return new Promise((resolve, reject) => {
      //增加root判断,
      //root方法不存在则证明为旧客户端,走原先的人脸识别流程,
      //root方法存在证明为新客户端,则走新人脸流程。
      this.getDeviceRoot().then((result) => {
        if(result && result.error == 1) {
          // this.startOldFaceWay(opts, opts1).then((res1)=> {
          //   resolve(res1);
          // });
          Native.alert('为了您的资金安全,请升级使用最新版APP')
        } else {
          if(result.isRoot == '0') {
            this.startNewFaceWay(opts, opts1).then((res2) => {
              resolve(res2);
            });
          } else if (result.isRoot == '1') {
            App.Native.alert('系统检测到您的设备被root,交易存在风险,为保证您的资金安全,请更换安全的设备进行交易');
            reject();
          } else {
            App.Native.alert(result.error);
          }
        }
      })
    })
  },
  /**
   * @desc - 获取n个月后的日期
   * @param {startDate: string} - 起始日期对象
   * @param {n: number} - 月数
   * @example App.getDateAfterMonth(new Date(), 3)
   */
  getDateAfterMonth(startDate, n){
    let year = startDate.getFullYear();
    let month = startDate.getMonth() + n;
    let date = startDate.getDate();

    if (month >= 12) {
      year = year + parseInt(month / 12);
      month = month - parseInt(month / 12) * 12;

    }

    if(date > App.mGetDate(year, month+1)){
      date = App.mGetDate(year, month+1);
    }

    return new Date(year, month, date);
  },
  /**
   * @desc - 返回当月的天数
   * @param {startDate: string} - 起始日期对象
   * @param {n: number} - 月数
   * @example App.mGetDate(2019, 2)
   */
  mGetDate(year, month){
    var d = new Date(year, month, 0);
    return d.getDate();
  },
  /**
   * @description 比较版本号大小
   * @param {number} limitVersion 版本号
   * @example 版本限制为4.4.6 || 4.4.6.0时 limitVersion传入4460 保证limitVersion为四位数字
   */
  compareVersionSize(limitVersion) {
    return new Promise((resolve, reject) => {
      App.Native.getDeviceInfo().then(res => {
        let MinVersion = limitVersion;
        let version = res.appVersion.replace(/\./g, '');
        if(version.length < 4) {
          version += '0';
        }
        version = Number(version);
        if(version >= MinVersion) {
          resolve(true);
        } else {
          resolve(false);
        }
      }).catch(err => {
        reject(false);
        console.log('compareVersionSize Error:', err);
      });
    });
  },
  /**
   * @desc - 获取当前时间 | 时间戳转日期
   * @example App.time.getTime()
   */
  time: {
    date: new Date(+new Date() + 8 * 3600 * 1000), //北京时间加8小时
    getTime() { //return 20200923182051
      return this.date.toJSON().substr(0, 19).replace(/-|T|:/g, '');
    },
    getYearMonDay() { //return 20200923
      return this.date.toJSON().substr(0, 10).replace(/-/g,'');
    },
  },
  /*
   * @description 浮点数相加
   * @example console.log(0.1+0.2);        // 输出 0.30000000000000004
   *          console.log(floatingAdd(0.1, 0.2));  // 输出 0.3
   */
  floatingAdd(a, b) {
    var c, d, e;
    try {
      c = a.toString().split('.')[1].length;
    } catch (f) {
      c = 0;
    }
    try {
      d = b.toString().split('.')[1].length;
    } catch (f) {
      d = 0;
    }
    return e = Math.pow(10, Math.max(c, d)), (this.floatingMul(a, e) + this.floatingMul(b, e)) / e;
  },
  /**
   * @description 浮点数相减
   */
  floatingSub(a, b) {
    var c, d, e;
    try {
      c = a.toString().split('.')[1].length;
    } catch (f) {
      c = 0;
    }
    try {
      d = b.toString().split('.')[1].length;
    } catch (f) {
      d = 0;
    }
    return e = Math.pow(10, Math.max(c, d)), (this.floatingMul(a, e) - this.floatingMul(b, e)) / e;
  },
  /**
   * @description 浮点数相乘
   * @example console.log(0.3*3);          // 输出 0.8999999999999999
   *          console.log(floatingMul(0.3, 3));    // 输出 0.9
   */
  floatingMul(a, b) {
    var c = 0,
      d = a.toString(),
      e = b.toString();
    try {
      c += d.split('.')[1].length;
    } catch (f) {}
    try {
      c += e.split('.')[1].length;
    } catch (f) {}
    return Number(d.replace('.', '')) * Number(e.replace('.', '')) / Math.pow(10, c);
  },
  /**
   * @description 浮点数相除
   */
  floatingDiv(a, b) {
    var c, d, e = 0,
      f = 0;
    try {
      e = a.toString().split('.')[1].length;
    } catch (g) {}
    try {
      f = b.toString().split('.')[1].length;
    } catch (g) {}
    return c = Number(a.toString().replace('.', '')), d = Number(b.toString().replace('.', '')), this.floatingMul(c / d, Math.pow(10, f - e));
  },
  /**
   * @description 19016推荐人代码校验
   * @param {str} code 推荐人代码
   *  1.进入页面时输入框保持不变,不必实现加入QD;
      2.输入框最多输入10位,多了不可输入;输入框只可输入英文和数字,弹窗提示“您输入的员工号格式错误”。
      3.输入框输入,提交时,判断,如果输入的位数不是8位或者10位,弹窗提示“您输入的员工号格式错误”,点击【确定】弹窗消失;
      4.输入10位时判断第一位和第二位是否为QD,若不是,弹窗提示“您请输入的员工号格式错误”,点击【确定】弹窗消失
      5.输入10位时,若客户第一位输入的小写的qd,需转换为大写QD;
      6.输入8位时,上送后台,直接补全QD,上送后台;
   */
  checkRecommendQD(code) {
    return new Promise(resolve => {
      if(!code) {
        resolve(code);
        return;
      }
      let ruler = /^[0-9a-zA-Z]+$/;
      let firstLetter = code.substr(0, 1).toLocaleUpperCase();
      let nextLetter = code.substr(1, 1).toLocaleUpperCase();
      if(!ruler.test(code)) {
        Native.alert('您输入的员工号格式错误');
        return;
      };
      if(code.length !== 8 && code.length !== 10) {
        Native.alert('您输入的员工号格式错误');
        return;
      }
      if(code.length == 10) {
        if(firstLetter !== 'Q' || nextLetter !== 'D') {
          Native.alert('您输入的员工号格式错误');
          return;
        }
        resolve('QD' + code.substr(2));
        return;
      }
      if(code.length == 8) {
        resolve('QD' + code);
        return;
      }
      resolve(code);
    });
  },
  /**
   * @description 页面停留时间
   * @param {number} startTime
   * @returns 秒/s
   */
  stayTime(startTime) {
    if(!startTime) {
      return 0;
    }
    const endTime = new Date().getTime();
    return (endTime - startTime) / 1000;
  },
  /**
   * @description 基金列表类型转义
   * @param {*} key
   * @returns
   */
  FundInvestTypeEnum(key) {
    switch (key) {
      case '股票型':
        return 'stock';
        break;
      case '债券型':
        return 'bond';
        break;
      case '混合型':
        return 'mixed';
        break;
      case '货币型':
        return 'currency';
        break;
      default:
        return 'other';
        break;
    }
  },
};