tools.js 7.47 KB
/*
 * @Date: 2024-07-31 17:19:25
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2024-12-25 16:02:17
 * @FilePath: /data-table/src/utils/tools.js
 * @Description: 文件描述
 */
import dayjs from 'dayjs';

// 格式化时间
const formatDate = (date) => {
  return dayjs(date).format('YYYY-MM-DD HH:mm');
};

/**
 * @description 判断浏览器属于平台
 * @returns
 */
const wxInfo = () => {
  let u = navigator.userAgent;
  let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端或者uc浏览器
  let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  let isMobile = u.indexOf('Android') > -1 || u.indexOf('iPhone') > -1 || u.indexOf('iPad') > -1; // 移动端平台
  let isIpad = u.indexOf('iPad') > -1; // iPad平台
  let uAgent = navigator.userAgent.toLowerCase();
  let isWeiXin = (uAgent.match(/MicroMessenger/i) == 'micromessenger') ? true : false;
  let isPC = (uAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|micromessenger)/i)) ? false : true;
  return {
    isAndroid,
    isiOS,
    isWeiXin,
    isMobile,
    isIpad,
    isPC
  };
};

/**
 * @description 判断多行省略文本
 * @param {*} id 目标dom标签
 * @returns
 */
const hasEllipsis = (id) => {
  let oDiv = document.getElementById(id);
  let flag = false;
  if (oDiv.scrollHeight > oDiv.clientHeight) {
    flag = true
  }
  return flag
}

/**
 * @description 解析URL参数
 * @param {*} url
 * @returns
 */
const parseQueryString = url => {
  var json = {};
  var arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : [];
  arr.forEach(item => {
    var tmp = item.split('=');
    json[tmp[0]] = decodeURIComponent(tmp[1]);
  });
  return json;
}

/**
 * 字符串包含字符数组中字符的状态
 * @param {*} array 字符数组
 * @param {*} str 字符串
 * @returns 包含状态
 */
const strExist = (array, str) => {
  const exist = array.filter(arr => {
    if (str.indexOf(arr) >= 0) return str;
  })
  return exist.length > 0
}

/**
 * 自定义替换参数
 * @param {*} url
 * @param {*} arg
 * @param {*} arg_val
 * @returns
 */
const changeURLArg = (url, arg, arg_val) => {
  var pattern = arg + '=([^&]*)';
  var replaceText = arg + '=' + arg_val;
  if (url.match(pattern)) {
    var tmp = '/(' + arg + '=)([^&]*)/gi';
    tmp = url.replace(eval(tmp), replaceText);
    return tmp;
  } else {
    if (url.match('[\?]')) {
      return url + '&' + replaceText;
    } else {
      return url + '?' + replaceText;
    }
  }
  return url + '\n' + arg + '\n' + arg_val;
}

// 获取参数key/value值对
const getUrlParams = (url) => {
  // 没有参数处理
  if (url.split('?').length === 1) return false;
  let arr = url.split('?');
  let res = arr[1].split('&');
  let items = {};
  for (let i = 0; i < res.length; i++) {
    let [key, value] = res[i].split('=');
    items[key] = value;
  }
  return items
}

// 格式化URL参数为字符串
const stringifyQuery = (params) => {
  const queryString = [];
  Object.keys(params || {}).forEach((k) => {
    queryString.push(k + '=' + params[k]);
  });

  return '?' + queryString.join('&');
};

// 美化打印实现方法
const prettyLog = () => {
  const isProduction = import.meta.env.MODE === 'production';

  const isEmpty = (value) => {
      return value == null || value === undefined || value === '';
  };
  const prettyPrint = (title, text, color) => {
      if (isProduction) return;
      if (typeof text === 'object') {
        console.log(
          `%c ${title} %c`,
          `background:${color};border:1px solid ${color}; padding: 1px; border-radius: 2px 0 0 2px; color: #fff;`,'background:transparent',
          text
        )
        return
      }
      console.log(
          `%c ${title} %c ${text} %c`,
          `background:${color};border:1px solid ${color}; padding: 1px; border-radius: 2px 0 0 2px; color: #fff;`,
          `border:1px solid ${color}; padding: 1px; border-radius: 0 2px 2px 0; color: ${color};`,
          'background:transparent'
      );
  };
  const info = (textOrTitle, content = '') => {
      const title = isEmpty(content) ? 'Info' : textOrTitle;
      const text = isEmpty(content) ? textOrTitle : content;
      prettyPrint(title, text, '#909399');
  };
  const error = (textOrTitle, content = '') => {
      const title = isEmpty(content) ? 'Error' : textOrTitle;
      const text = isEmpty(content) ? textOrTitle : content;
      prettyPrint(title, text, '#F56C6C');
  };
  const warning = (textOrTitle, content = '') => {
      const title = isEmpty(content) ? 'Warning' : textOrTitle;
      const text = isEmpty(content) ? textOrTitle : content;
      prettyPrint(title, text, '#E6A23C');
  };
  const success = (textOrTitle, content = '') => {
      const title = isEmpty(content) ? 'Success ' : textOrTitle;
      const text = isEmpty(content) ? textOrTitle : content;
      prettyPrint(title, text, '#67C23A');
  };

  return {
      info,
      error,
      warning,
      success,
  };
};

const isInViewport = (el) => { // 判断元素是否在可视区域
  const rect = el.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
};

/**
 * 判断当前经纬度是否在目标经纬度的范围内
 * @param {number} currentLat - 当前纬度
 * @param {number} currentLng - 当前经度
 * @param {number} targetLat - 目标纬度
 * @param {number} targetLng - 目标经度
 * @param {number} radius - 半径(单位:米)
 * @returns {boolean} 是否在范围内
 */
// const isWithinRadius = (currentLat, currentLng, targetLat, targetLng, radius) => {
//   const EARTH_RADIUS = 6371000; // 地球半径(单位:米)

//   // 将角度转换为弧度
//   const toRadians = (degrees) => (degrees * Math.PI) / 180;

//   // 当前点和目标点的纬度差和经度差
//   const deltaLat = toRadians(targetLat - currentLat);
//   const deltaLng = toRadians(targetLng - currentLng);

//   // 转换为弧度
//   const radCurrentLat = toRadians(currentLat);
//   const radTargetLat = toRadians(targetLat);

//   // Haversine 公式计算两点间的距离
//   const a =
//     Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
//     Math.cos(radCurrentLat) *
//     Math.cos(radTargetLat) *
//     Math.sin(deltaLng / 2) *
//     Math.sin(deltaLng / 2);
//   const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
//   const distance = EARTH_RADIUS * c;

//   // 判断距离是否在范围内
//   return distance <= radius;
// }

function calculateDistance(lat1, lng1, lat2, lng2) {
  var that = this;
  let rad1 = lat1 * Math.PI / 180.0;
  let rad2 = lat2 * Math.PI / 180.0;
  let a = rad1 - rad2;
  let b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
  let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(rad1) * Math.cos(
    rad2) * Math.pow(
    Math.sin(b / 2), 2)));
  s = s * 6378137; // 地球半径改为米
  s = Math.round(s); // 四舍五入取整,直接返回米
  return s; // 返回距离,单位为米
}
function isWithinRadius(currentLat, currentLng, targetLat, targetLng, radius) {
  const distance = calculateDistance(currentLat, currentLng, targetLat, targetLng);
  return distance <= radius;
}

export {
  formatDate,
  wxInfo,
  hasEllipsis,
  parseQueryString,
  strExist,
  changeURLArg,
  getUrlParams,
  stringifyQuery,
  prettyLog,
  isInViewport,
  isWithinRadius,
};