/** * 辅助函数 */ import dayjs from 'dayjs'; import gcoord from "gcoord"; /** * 等待异步结果 * @param checker 检测函数,返回值为truthy时表示得到想要的结果,否则反之 * @param timeout 指定时间内没有得到想要的结果则超时 */ export function until(checker = () => true, timeout = 2000) { return new Promise((resolve) => { let pollingTimer = null; const timeoutTimer = setTimeout(() => { clearInterval(pollingTimer); resolve(false); }, timeout); pollingTimer = setInterval(() => { const result = checker(); if (result) { clearTimeout(timeoutTimer); clearInterval(pollingTimer); resolve(result); } }, 10); }); } /** * 根据restful的uri构建实际url * @param uri uri模版 * @param argv 插入到uri中的参数列表,按顺序插入 * @returns url */ export function buildURL(uri, ...argv) { return uri.replace(/{\w+}|:[a-zA-Z]+/g, () => { const res = argv.shift(); if (res === undefined) { throw new Error('URI 参数不足'); } return res; }); } /** * 选取原object指定属性,构成新的object * @param originObject * @param pickKeys */ export function pick(originObject, pickKeys = []) { const newObject = {}; pickKeys.forEach((key) => { if (Object.prototype.hasOwnProperty.call(originObject, key)) { newObject[key] = originObject[key]; } }); return newObject; } /** * 更新target对象的键值,使用source对象里的数据 * @param target * @param source */ export function update(target, source) { const result = { ...target }; Object.keys(target).forEach((key) => { if (Object.prototype.hasOwnProperty.call(source, key)) { result[key] = source[key]; } }); return result; } /** * 将对象的部分key重命名 * @param originObject 原始对象(也可以是相同结构的对象构成的数组) * @param keysMapping 新keys映射(如{ name: 'username', sex: 'gender' },表示把原始对象中的name重命名为username、把sex重命名为gender,原始对象其他key不变) * @returns {{}|*} 新对象 */ export function renameKeys(originObject, keysMapping = {}) { if (!Array.isArray(originObject)) { const kvList = Object.keys(originObject).map((key) => { const newKey = keysMapping[key] || key; return { [newKey]: originObject[key] }; }); return Object.assign({}, ...kvList); } return originObject.map((obj) => renameKeys(obj, keysMapping)); } /** * 随机数 */ export function rand(min, max, fraction = 0) { const res = (Math.random() * ((max - min) + 1)) + min; return res.toFixed(fraction) - 0; } /** * 将input当着数字处理,若不是数字则返回代替字符 * @param input * @param substitution * @returns {string|number} */ export function numeric(input, substitution = '-') { const type = typeof input; if (type !== 'number' && type !== 'string') return substitution; const output = Number(input); return !Number.isNaN(output) ? output : substitution; } // 保留小数位(是整数则不保留) export const toFixed = (num, digits = 2) => (Number(num || 0).toFixed(digits)) - 0; export const falsyTo = (fv, to = '-') => (fv || fv === 0 ? fv : to); /** * 格式化时间戳 * @param timestamp * @param format * @returns {string} */ export function formatTime(timestamp, format = 'YYYY-MM-DD HH:mm:ss') { return (timestamp || timestamp === 0) && dayjs(timestamp).isValid() ? dayjs(timestamp).format(format) : '-'; } /** * 将总秒数格式化为“x时y分z秒”形式 * @param sec * @param precision * @param isChinese * @returns {string} */ export function popularTime(sec, precision = 0, isChinese = false) { const { HOUR, MINUTE, SECOND } = isChinese ? { HOUR: '时', MINUTE: '分', SECOND: '秒' } : { HOUR: 'h', MINUTE: 'm', SECOND: 's' }; let remainingSec = sec; const hours = Math.floor(remainingSec / 3600); remainingSec -= hours * 3600; const minutes = Math.floor(remainingSec / 60); remainingSec -= minutes * 60; return `${hours ? `${hours}${HOUR}` : ''}${minutes ? `${minutes}${MINUTE}` : ''}${remainingSec ? `${remainingSec.toFixed(precision)}${SECOND}` : ''}`; } /** * 将秒转化为小时 * @param sec * @returns {number} */ export function toHour(sec) { return (sec / 3600).toFixed(2) - 0; } /** * 对数组中的每个元素进行偏移计算,返回计算后的数组 * @param originArray 原数组(有数字构成) * @param offsetArray 偏移量数组(与原数组元素一一对应) * @returns {*[]} 计算后的新数组 */ export function arrOffset(originArray = [], offsetArray = []) { return originArray.map((item, index) => +item + (offsetArray[index] || 0)); } /** * 范围时间内,生成连续时间戳(按步长连续) * @param startTs 起始时间戳 * @param endTs 结束时间戳 * @param step 步长(year | month | week | day | hour | minute | second | millisecond) * @returns {*[]} 连续时间戳 */ export function rangeTimestamps(startTs, endTs, step = 'day') { const s = dayjs(startTs).startOf(step); const eTs = dayjs(endTs).startOf(step).valueOf(); const result = []; for (; s.valueOf() <= eTs;) { result.push(s.valueOf()); s.add(1, step); } return result; } /** * 计算出数组中最多的元素 * @param array * @returns {*} */ export function mostCommonElement(array) { return array.reduce((max, element) => { const count = array.filter((e) => e === element).length; return count > array.filter((e) => e === max).length ? element : max; }, ''); } /** * 将gps坐标,转换为国测局坐标 * @param point 经纬度构成的数组[经度, 纬度] */ export function GPS2GCJ(point) { return gcoord.transform(point, gcoord.WGS84, gcoord.GCJ02); } /** * 将国测局坐标,转换为gps坐标 * @param point 经纬度构成的数组[经度, 纬度] */ export function GCJ2GPS(point) { return gcoord.transform(point, gcoord.GCJ02, gcoord.WGS84); }