/* * @Descripttion: * @Author: zenghua.wang * @Date: 2022-02-23 21:12:37 * @LastEditors: wzh 1048523306@qq.com * @LastEditTime: 2024-12-17 11:55:31 */ import dayjs from 'dayjs'; import { cloneDeep } from 'lodash'; import { Base64 } from 'js-base64'; import JsZip from 'jszip'; import JsZipUtils from 'jszip-utils'; import { saveAs } from 'file-saver'; /** * @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 cloneDeep(obj); }; /** * @Title 将number转换为px * @param {*} val * @returns */ export const setPx = (val) => { if (isEmpty(val)) return ''; return typeof val === 'number' ? `${val}px` : val; }; /** * @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 将字符串url参数转换为Object * @param {*} url * @returns */ export const param2Obj = (url) => { return (url) => Object.fromEntries(new URLSearchParams(url)); }; /** * @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/images/${url}`, import.meta.url); }; /** * 文件下载 * @param {*} url * @param {*} fileName * @returns */ export const dowloadFile = async (options = { url: '', files: null, fileName: '' }) => { const { url, files, fileName } = options; const chunkSize = 1 * 1024 * 1024; const jszip = new JsZip(); function chunkFile(file, chunkSize) { let chunks = []; let fileSize = file.size; let currentPos = 0; while (currentPos < fileSize) { let endPos = currentPos + chunkSize; if (endPos > fileSize) { endPos = fileSize; } chunks.push(file.slice(currentPos, endPos)); currentPos = endPos; } return chunks; } function dowloadLink(content, fileName) { const blob = new Blob([content]); if ('download' in document.createElement('a')) { const 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); document.body.removeChild(elink); } else { navigator.msSaveBlob(blob, fileName); } } return new Promise((resolve, reject) => { if (!isEmpty(options?.url)) { JsZipUtils.getBinaryContent(url, (err, file) => { if (err) { return reject(err); } jszip .loadAsync(file) .then((zip) => { return zip.generateAsync({ type: 'blob' }); }) .then((blob) => { saveAs(blob, `${fileName}.zip`); }); }); } else { // if (files.type === 'binary/octet-stream') { // dowloadLink(files, fileName); // return; // } let chunks = null; if (files.size > chunkSize) { chunks = chunkFile(files, chunkSize); } const fileType = files.type.split('/')[1]; const newFile = files.type === 'binary/octet-stream' ? fileName : `${fileName}.${fileType}`; if (chunks) { let count = 1; chunks.forEach(function (chunk) { jszip.file(newFile, chunk, { binary: true }); count++; }); } else { jszip.file(`${fileName}.${fileType}`, files, { binary: true }); } jszip.generateAsync({ type: 'blob' }).then((blob) => { saveAs(blob, `${fileName}.zip`); resolve(true); }); } }); }; /** * @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); };