/*
 * @Descripttion:
 * @Author: zenghua.wang
 * @Date: 2022-02-23 21:12:37
 * @LastEditors: zenghua.wang
 * @LastEditTime: 2025-02-11 17:18:36
 */
import lodash from 'lodash';
import dayjs from 'dayjs';
import { Base64 } from 'js-base64';

/**
 * @Title 防抖：指在一定时间内，多次触发同一个事件，只执行最后一次操作
 * @param {*} fn
 * @param {*} delay
 * @returns
 */
export function debounce(fn, delay) {
  let timer = null;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}
/**
 * @Title 节流：指在一定时间内，多次触发同一个事件，只执行第一次操作
 * @param {*} fn
 * @param {*} delay
 * @returns
 */
export function throttle(fn, delay) {
  let timer = null;
  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args);
        timer = null;
      }, delay);
    }
  };
}
/**
 * @Title  判断是否 empty,返回ture
 * @param {*} val:null 'null' undefined 'undefined' 0 '0' "" 返回true
 * @returns
 */
export const isEmpty = (val) => {
  if (val && parseInt(val) === 0) return false;
  if (typeof val === 'undefined' || val === 'null' || val == null || val === 'undefined' || val === undefined || val === '') {
    return true;
  } else if (typeof val === 'object' && Object.keys(val).length === 0) {
    return true;
  } else if (val instanceof Array && val.length === 0) {
    return true;
  } else {
    return false;
  }
};
/**
 * @Title 深度拷贝对象
 * @param {*} obj
 * @returns
 */
export const deepClone = (obj = {}) => {
  return lodash.cloneDeep(obj);
};
/**
 * @Title 将number转换为px
 * @param {*} val
 * @returns
 */
export const setPx = (val) => {
  if (isEmpty(val)) return '';
  val = val + '';
  if (val.indexOf('%') === -1) {
    val = val + 'px';
  }
  return val;
};
/**
 * @Tilte 设置属性默认值
 * @param {*} options
 * @param {*} prop
 * @param {*} defaultVal
 * @returns
 */
export const setDefaultOption = (options, prop, defaultVal) => {
  return options[prop] === undefined ? defaultVal : options.prop;
};
/**
 * @Title 设置字典值
 * @param {*} columns
 * @param {*} key
 * @param {*} data
 * @returns
 */
export const setDicData = (columns, key, data = []) => {
  if (isEmpty(data)) return;
  const len = columns.length;
  for (let i = 0; i < len; i++) {
    if (columns[i]?.prop === key) {
      columns[i]['dicData'] = data;
      break;
    }
  }
};
/**
 * @Title 求字段lable
 * @param {*} tree
 * @returns
 */
export const setDicLabel = (dicData, value) => {
  let label = value;
  if (isEmpty(dicData)) return label;
  const len = dicData.length;
  for (let i = 0; i < len; i++) {
    if (dicData[i]?.value === value) {
      label = dicData[i].label;
      break;
    }
  }
  return label;
};
/**
 * @Title 数组交集
 * @param {*} arr1
 * @param {*} arr2
 * @returns
 */
export const intersectionArray = (arr1 = [], arr2 = []) => {
  return arr1.filter((item) => arr2.includes(item));
};
/**
 * @Title 数组并集
 * @param {*} arr1
 * @param {*} arr2
 * @returns
 */
export const unionArray = (arr1 = [], arr2 = []) => {
  return Array.from(new Set([...arr1, ...arr2]));
};
/**
 * @Title 数组差集
 * @param {*} arr1
 * @param {*} arr2
 * @returns
 */
export const differenceArray = (arr1 = [], arr2 = []) => {
  const s = new Set(arr2);
  return arr1.filter((x) => !s.has(x));
};
/**
 * @Title 加密
 * @param {*} n
 * @returns
 */
export const encode = (n, flag = false) => {
  if (flag) {
    return (
      ((e) => {
        let t = e.length.toString();
        for (let n = 10 - t.length; n > 0; n--) t = '0' + t;
        return t;
      })(n) +
      ((e) => {
        const t = Base64.encode(e).split('');
        for (let n = 0; n < Math.floor(e.length / 100 + 1); n++) t.splice(100 * n + 1, 0, 3);
        return t.join('');
      })(n)
    );
  }
  return n;
};
/**
 * @Title 解密
 * @param {*} e
 * @returns
 */
export const decode = (e, flag = false) => {
  if (flag) {
    try {
      const t = Number(e.substr(0, 10));
      const n = e.substr(10).split('');
      for (let i = 0, s = 0; s < Math.floor(t / 100) + 1; s++) {
        n.splice(100 * s + 1 - i, 1);
        i++;
      }
      const o = Base64.decode(n.join(''));
      return o;
    } catch (error) {
      return e;
    }
  }
  return e;
};
/**
 * @Title 图片转base64
 * @param {*} file
 * @returns
 */
export const imageToBase64 = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      resolve(reader.result);
    };
    reader.onerror = reject;
  });
};
/**
 * @Title bufferToBase64
 * @param {*} buffer
 * @returns
 */
export const bufferToBase64 = (buffer) => {
  return 'data:image/jpeg;base64,' + window.btoa(new Uint8Array(buffer).reduce((data, byte) => data + String.fromCharCode(byte), ''));
};
/**
 * @Title blob转json
 * @param {*} file
 * @returns
 */
export const blobToJSON = (blob) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsText(blob, 'utf-8');
    reader.onload = () => {
      const res = !isEmpty(reader.result) ? JSON.parse(reader.result) : reader.result;
      resolve(res);
    };
    reader.onerror = reject;
  });
};
/**
 * @Title 将array转化为树
 * @param tree
 * @returns
 */
export const getTree = (tree = []) => {
  tree.forEach((item) => {
    delete item.children;
  });
  const map = {};
  tree.forEach((item) => {
    map[item.id] = item;
  });
  const arr = [];
  tree.forEach((item) => {
    const parent = map[item.parentId];
    if (parent) {
      (parent.children || (parent.children = [])).push(item);
    } else {
      arr.push(item);
    }
  });
  return arr;
};
/**
 * @Title 获取路由中的参数
 * @param name
 * @returns
 */
export const getUrlQuery = (name) => {
  const url = window.location.href;
  const hash = url.substring(url.indexOf('#') + 1);
  const searchIndex = hash.indexOf('?');
  const search = searchIndex !== -1 ? hash.substring(searchIndex + 1) : '';
  const usp = new URLSearchParams(search);
  return usp.get(name);
};
/**
 * @Title 将Object参数转换为字符串
 * @param {*} json
 * @returns
 */
export const obj2Param = (json) => {
  if (!json) return '';
  return Object.keys(json)
    .map((key) => {
      if (isEmpty(json[key])) return '';
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]);
    })
    .join('&');
};
/**
 * @Title 获取静态资源文件
 * @param {*} url
 * @returns
 */
export const getAssetsFile = (url) => {
  return new URL(`../assets/${url}`, import.meta.url);
};
/**
 * @Title 替换图片url字段值
 * @param {*} url
 * @returns
 */
export const setUploadField = (url) => {
  // if (isEmpty(url) || url.includes('http')) return null;
  return isEmpty(url) ? null : url;
};
/**
 * @Title: 下载文件
 * @param {void} url:
 * @param {void} fileName:
 * @param {void} fileType:
 * @return {void}
 */
export const downloadFile = async (url, fileName, fileType) => {
  let blob = null;
  try {
    switch (fileType) {
      case 'image': {
        const img = new Image();
        img.crossOrigin = 'Anonymous';
        img.src = url;
        await new Promise((resolve, reject) => {
          img.onload = resolve;
          img.onerror = reject;
        });
        const canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0);
        blob = await new Promise((resolve) => {
          canvas.toBlob(resolve, 'image/jpeg');
        });
        break;
      }
      case 'blob':
      case 'arraybuffer': {
        blob = new Blob([url]);
        break;
      }
    }
    if ('download' in document.createElement('a')) {
      const elink = document.createElement('a');
      elink.download = fileName;
      elink.style.display = 'none';
      elink.href = blob ? URL.createObjectURL(blob) : url;
      document.body.appendChild(elink);
      elink.click();
      blob && URL.revokeObjectURL(elink.href);
      document.body.removeChild(elink);
    } else {
      navigator.msSaveBlob(blob, fileName);
    }
  } catch (error) {
    console.error('下载出错:', error);
  }
};
/**
 * @Title 模拟休眠
 * @param {*} duration
 * @returns
 */
export const sleep = (duration = 0) =>
  new Promise((resolve) => {
    setTimeout(resolve, duration);
  });
/**
 * @Title 创建id
 * @param {*} prefix
 * @returns
 */
export const createId = (prefix) => {
  const val = Date.now() + Math.ceil(Math.random() * 99999);
  return isEmpty(prefix) ? val : prefix + '-' + val;
};
/**
 * @Title 生成数据
 * @param {*} duration
 * @returns
 */
export const mockData = (item = {}, len = 1) => {
  const list = [];
  for (let i = 0; i < len; i++) {
    let temp = { ...item, id: createId() };
    list.push(temp);
  }
  return list;
};
/**
 * @Title 日期格式化
 * @param {*} date
 * @param {*} format
 * @returns
 */
export const dateFormat = (datetime, formater = 'YYYY-MM-DD hh:mm:ss') => {
  if (datetime instanceof Date || datetime) {
    return dayjs(datetime).format(formater);
  } else {
    return null;
  }
};
/**
 * @Title 字符串转日期
 * @param {*} str
 * @returns
 */
export const toDate = (str) => {
  return !isEmpty(str) ? dayjs(str) : dayjs();
};
/**
 * @Title 字符串转日期
 * @param {*} str
 * @returns
 */
export const getDate = (num, type, formater = 'YYYY-MM-DD', start = true) => {
  const date = dayjs().subtract(num, type);
  return start ? date.startOf(type).format(formater) : date.endOf(type).format(formater);
};
/**
 * @Title: 获取时间差
 * @param start
 * @param end
 * @param type
 * @returns
 */
export const getDiffTime = (start, end, type) => {
  const startTime = dayjs(start);
  const endTime = dayjs(end);
  const duration = endTime.diff(startTime);
  let diff = 0;
  switch (type) {
    case 'DD': {
      diff = duration / (1000 * 60 * 60 * 24);
      break;
    }
    case 'HH': {
      diff = duration / (1000 * 60 * 60);
      break;
    }
    case 'mm': {
      diff = duration / (1000 * 60);
      break;
    }
  }
  return Math.round(diff);
};
/**
 * @Title: 开始日期
 * @param last
 * @param type
 * @param formater
 * @returns
 */
export const startDate = (num, type = 'month', formater = 'YYYY-MM-DD HH:mm:ss') => {
  if (num === 'now') return dayjs().format(formater);
  if (typeof num === 'string') return dayjs(num).startOf(type).format(formater);
  return num === 0 ? dayjs().startOf(type).format(formater) : dayjs().subtract(num, type).startOf(type).format(formater);
};
/**
 * @Title: 结束日期
 * @param num
 * @param type
 * @param formater
 * @returns
 */
export const endDate = (num = 0, type = 'month', formater = 'YYYY-MM-DD HH:mm:ss') => {
  if (num === 'now') return dayjs().format(formater);
  if (typeof num === 'string') return dayjs(num).endOf(type).format(formater);
  return num === 0 ? dayjs().endOf(type).format(formater) : dayjs().subtract(num, type).endOf(type).format(formater);
};

/**
 * @Title: 生成随机数
 * @param len
 * @returns
 */
export const randomNumber = (len) => {
  let randomlen = len ? len : 10;
  const chars = '0123456789';
  let result = '';
  for (let i = 0; i < randomlen; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return result;
};
