diff --git a/src/utils/commons.js b/src/utils/commons.js index a66419b..7c5fffa 100644 --- a/src/utils/commons.js +++ b/src/utils/commons.js @@ -1,238 +1,5 @@ -// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart import { Tag } from "antd"; import { CaretUpOutlined, CaretDownOutlined } from "@ant-design/icons"; -import moment from "moment"; - -if (!String.prototype.padStart) { - String.prototype.padStart = function padStart(targetLength, padString) { - targetLength = targetLength >> 0; // floor if number or convert non-number to 0; - padString = String(typeof padString !== "undefined" ? padString : " "); - if (this.length > targetLength) { - return String(this); - } else { - targetLength = targetLength - this.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); // append to original to ensure we are longer than needed - } - return padString.slice(0, targetLength) + String(this); - } - }; -} - -if (!Object.fromEntries) { - Object.fromEntries = function(entries) { - const obj = {}; - for (let i = 0; i < entries.length; ++i) { - const entry = entries[i]; - if (entry && entry.length === 2) { - obj[entry[0]] = entry[1]; - } - } - return obj; - }; -} - -export function copy(obj) { - return JSON.parse(JSON.stringify(obj)); -} - -export function named(value) { - return function (target) { - target.definedName = value; - }; -} - -export function formatCurrency(name) { - if (name === "USD") { - return "$"; - } else if (name === "RMB") { - return "¥"; - } else if (name === "EUR") { - return "€"; - } else if (name === "GBP") { - return "£"; - } else { - return name + " "; - } -} - -export function formatPrice(price) { - return Math.ceil(price).toLocaleString(); -} - -// 千分符的金额转成数字,默认为0 -export function price_to_number(price) { - const num_string = (price + "").replace(/,/g, ""); - const number = parseFloat(num_string); - return isNaN(number) ? 0 : number; -} - -export function formatPercent(number) { - return Math.round(number * 100) + "%"; -} - -export function formatPercentToFloat(number) { - return parseFloat((number * 100).toFixed(2)) + "%"; -} - -export function percentToDecimal(number) { - return parseFloat(number) / 100; -} - -export function formatDate(date) { - if (isEmpty(date)) { - return "NaN"; - } - - const year = date.getFullYear(); - const month = date.getMonth() + 1; - const day = date.getDate(); - - const monthStr = ("" + month).padStart(2, 0); - const dayStr = ("" + day).padStart(2, 0); - const formatted = year + "-" + monthStr + "-" + dayStr; - - return formatted; -} - -export function formatTime(date) { - const hours = date.getHours(); - const minutes = date.getMinutes(); - - const hoursStr = ("" + hours).padStart(2, 0); - const minutesStr = ("" + minutes).padStart(2, 0); - const formatted = hoursStr + ":" + minutesStr; - - return formatted; -} - -export function formatDatetime(date) { - const year = date.getFullYear(); - const month = date.getMonth() + 1; - const day = date.getDate(); - - const monthStr = ("" + month).padStart(2, 0); - const dayStr = ("" + day).padStart(2, 0); - - const hours = date.getHours(); - const minutes = date.getMinutes(); - - const hoursStr = ("" + hours).padStart(2, 0); - const minutesStr = ("" + minutes).padStart(2, 0); - - const formatted = year + "-" + monthStr + "-" + dayStr + " " + hoursStr + ":" + minutesStr; - - return formatted; -} - -export function mixins(...list) { - return function (target) { - list.forEach(val => { - const mixinObj = Object.create(val.prototype, {}); - const name = Object.getPrototypeOf(mixinObj).constructor.name; - const camelCase = name.substr(0, 1).toLowerCase() + name.substr(1); - Object.assign(target.prototype, { [camelCase]: mixinObj }); - }); - }; -} - -export function camelCase(name) { - return name.substr(0, 1).toLowerCase() + name.substr(1); -} - -export class UrlBuilder { - constructor(url) { - this.url = url; - this.paramList = []; - } - - append(name, value) { - if (isNotEmpty(value)) { - this.paramList.push({ name, value }); - } - return this; - } - - build() { - this.paramList.forEach((e, i, a) => { - if (i === 0) { - this.url += "?"; - } else { - this.url += "&"; - } - this.url += e.name + "=" + e.value; - }); - return this.url; - } -} - -export function isNotEmpty(val) { - return val !== undefined && val !== null && val !== ""; -} - -/** - * ! 不支持计算 Set 或 Map - * @param {*} val - * @example - * true if: 0, [], {}, null, '', undefined - * false if: 'false', 'undefined' - */ -export function isEmpty(val) { - // return val === undefined || val === null || val === ""; - return [Object, Array].includes((val || {}).constructor) && !Object.entries((val || {})).length; -} - -/** - * @example - * empty(0) => false - */ -export function empty(a) { - if (a === "") return true; // 检验空字符串 - if (a === "null") return true; // 检验字符串类型的null - if (a === "undefined") return true; // 检验字符串类型的 undefined - if (!a && a !== 0 && a !== "") return true; // 检验 undefined 和 null - if (Array.prototype.isPrototypeOf(a) && a.length === 0) return true; // 检验空数组 - if (Object.prototype.isPrototypeOf(a) && Object.keys(a).length === 0) return true; // 检验空对象 - return false; -} - -export function prepareUrl(url) { - return new UrlBuilder(url); -} - -export function debounce(fn, delay = 500) { - let timer; - return e => { - e.persist(); - clearTimeout(timer); - timer = setTimeout(() => { - fn(e); - }, delay); - }; -} - -export function throttle(fn, delay, atleast) { - let timeout = null; - let startTime = new Date(); - return function () { - const curTime = new Date(); - clearTimeout(timeout); - if (curTime - startTime >= atleast) { - fn(); - startTime = curTime; - } else { - timeout = setTimeout(fn, delay); - } - }; -} - -export function clickUrl(url) { - const httpLink = document.createElement("a"); - httpLink.href = url; - httpLink.target = "_blank"; - httpLink.click(); -} export function show_vs_tag(vs, vs_diff, data1, data2) { let tag = "-"; @@ -258,340 +25,3 @@ export function show_vs_tag(vs, vs_diff, data1, data2) { ); } - -// 数组去掉重复 -export function unique(arr) { - const x = new Set(arr); - return [...x]; -} -export const uniqWith = (arr, fn) => arr.filter((element, index) => arr.findIndex((step) => fn(element, step)) === index); -export function getWeek(date) { - // 参数时间戳 - const week = moment(date).day(); - switch (week) { - case 1: - return "周一"; - case 2: - return "周二"; - case 3: - return "周三"; - case 4: - return "周四"; - case 5: - return "周五"; - case 6: - return "周六"; - case 0: - return "周日"; - } -} - -// 把非数字下标的数组设置下标,因为非数字数组的length为0导致读取失败 -export function set_array_index(result) { - const result_array = []; - const result_keys = Object.keys(result); - result_keys.sort(); // 必须做一次排序,用for in循环会导致顺序错误 - for (const key of result_keys) { - result_array.push(result[key]); - } - return result_array; -} - -/** - * 数组排序 - */ -export const sortBy = (key) => { - return (a, b) => (a[key] > b[key]) ? 1 : ((b[key] > a[key]) ? -1 : 0); -}; - -export const sortDescBy = (key) => { - return (a, b) => (a[key] < b[key]) ? 1 : ((b[key] < a[key]) ? -1 : 0); -}; - -/** - * Object排序keys - */ -export const sortKeys = (obj) => - Object.keys(obj) - .sort() - .reduce((a, k2) => ({...a, [k2]: obj[k2]}), {}); - -/** - * 数组排序, 给定排序数组 - * @param {array} items 需要排序的数组 - * @param {array} keyName 排序的key - * @param {array} keyOrder 给定排序 - * @returns - */ -export const sortArrayByOrder = (items, keyName, keyOrder) => { - return items.sort((a, b) => { - return keyOrder.indexOf(a[keyName]) - keyOrder.indexOf(b[keyName]); - }); -}; -/** - * 合并Object, 递归地 - */ -export function merge(...objects) { - const isDeep = objects.some(obj => obj !== null && typeof obj === 'object'); - - const result = objects[0] || (isDeep ? {} : objects[0]); - - for (let i = 1; i < objects.length; i++) { - const obj = objects[i]; - - if (!obj) continue; - - Object.keys(obj).forEach(key => { - const val = obj[key]; - - if (isDeep) { - if (Array.isArray(val)) { - result[key] = [].concat(Array.isArray(result[key]) ? result[key] : [result[key]], val); - } else if (typeof val === 'object') { - result[key] = merge(result[key], val); - } else { - result[key] = val; - } - } else { - result[key] = typeof val === 'boolean' ? val : result[key]; - } - }); - } - - return result; -} - -/** - * 数组分组 - * - 相当于 lodash 的 _.groupBy - * @see https://www.lodashjs.com/docs/lodash.groupBy#_groupbycollection-iteratee_identity - */ -export function groupBy(array, callback) { - return array.reduce((groups, item) => { - const key = typeof callback === 'function' ? callback(item) : item[callback]; - - if (!groups[key]) { - groups[key] = []; - } - - groups[key].push(item); - return groups; - }, {}); -} - -/** - * 创建一个从 object 中选中的属性的对象。 - * @param {*} object - * @param {array} keys - */ -export function pick(object, keys) { - return keys.reduce((obj, key) => { - if (object && Object.prototype.hasOwnProperty.call(object, key)) { - obj[key] = object[key]; - } - return obj; - }, {}); -} - -/** - * 返回对象的副本,经过筛选以省略指定的键。 - * @param {*} object - * @param {string[]} keysToOmit - * @returns - */ -export function omit(object, keysToOmit) { - return Object.fromEntries( - Object.entries(object).filter( - ([key]) => !keysToOmit.includes(key) - ) - ); -} - -/** - * 深拷贝 - */ -export function cloneDeep(value) { - if (typeof value !== 'object' || value === null) { - return value; - } - - const result = Array.isArray(value) ? [] : {}; - - for (const key in value) { - if (Object.prototype.hasOwnProperty.call(value, key)) { - result[key] = cloneDeep(value[key]); - } - } - - return result; -} - -/** - * 向零四舍五入, 固定精度设置 - */ -function curriedFix(precision = 0) { - return function(number) { - // Shift number by precision places - const shift = Math.pow(10, precision); - const shiftedNumber = number * shift; - - // Round to nearest integer - const roundedNumber = Math.round(shiftedNumber); - - // Shift back decimal place - return roundedNumber / shift; - }; -} -/** - * 向零四舍五入, 保留2位小数 - */ -export const fixTo2Decimals = curriedFix(2); -/** - * 向零四舍五入, 保留4位小数 - */ -export const fixTo4Decimals = curriedFix(4); - -export const fixTo1Decimals = curriedFix(1); -export const fixToInt = curriedFix(0); - -/** - * 映射 - * @example - * const keyMap = { - a: [{key: 'a1'}, {key: 'a2', transform: v => v * 2}], - b: {key: 'b1'} - }; - const result = objectMapper({a: 1, b: 3}, keyMap); - // result = {a1: 1, a2: 2, b1: 3} - * - */ -export function objectMapper(input, keyMap) { - // Loop through array mapping - if (Array.isArray(input)) { - return input.map((obj) => objectMapper(obj, keyMap)); - } - - if (typeof input === 'object') { - const mappedObj = {}; - - Object.keys(input).forEach((key) => { - // Keep original keys not in keyMap - if (!keyMap[key]) { - mappedObj[key] = input[key]; - } - // Handle array of maps - if (Array.isArray(keyMap[key])) { - keyMap[key].forEach((map) => { - let value = input[key]; - if (map.transform) value = map.transform(value); - mappedObj[map.key] = value; - }); - - // Handle single map - } else { - const map = keyMap[key]; - if (map) { - let value = input[key]; - if (map.transform) value = map.transform(value); - if (typeof map === 'string') mappedObj[map] = value; - mappedObj[map.key || key] = value; - } - } - }); - - return mappedObj; - } - - return input; -} - -/** - * 创建一个对应于对象路径的值数组 - */ -export function at(obj, path) { - let result; - if (Array.isArray(obj)) { - // array case - const indexes = path.split('.').map((i) => parseInt(i)); - result = []; - for (let i = 0; i < indexes.length; i++) { - result.push(obj[indexes[i]]); - } - } else { - // object case - const indexes = path.split('.').map((i) => i); - result = [obj]; - for (let i = 0; i < indexes.length; i++) { - result = [result[0][indexes[i]]]; - } - } - return result; -} -/** - * 删除 null/undefined - */ -export function flush(collection) { - let result, len, i; - if (!collection) { - return undefined; - } - if (Array.isArray(collection)) { - result = []; - len = collection.length; - for (i = 0; i < len; i++) { - const elem = collection[i]; - if (elem != null) { - result.push(elem); - } - } - return result; - } - if (typeof collection === 'object') { - result = {}; - const keys = Object.keys(collection); - len = keys.length; - for (i = 0; i < len; i++) { - const key = keys[i]; - const value = collection[key]; - if (value != null) { - result[key] = value; - } - } - return result; - } - return undefined; -} - -/** - * 千分位 格式化数字 - */ -export const numberFormatter = (number) => { - return new Intl.NumberFormat().format(number); -}; - -/** - * @example - * const obj = { a: { b: 'c' } }; - * const keyArr = ['a', 'b']; - * getNestedValue(obj, keyArr); // Returns: 'c' - */ -export const getNestedValue = (obj, keyArr) => { - return keyArr.reduce((acc, curr) => { - return acc && acc.hasOwnProperty(curr) ? acc[curr] : undefined; - // return acc && acc[curr]; - }, obj); -}; - -/** - * 计算笛卡尔积 - */ -export const cartesianProductArray = (arr, sep = '_', index = 0, prefix = '') => { - let result = []; - if(index === arr.length){ - return [prefix]; - } - arr[index].forEach(item => { - result = result.concat(cartesianProductArray(arr, sep, index+1, prefix ? `${prefix}${sep}${item}` : `${item}`)); - }); - return result; -}; diff --git a/src/utils/request.js b/src/utils/request.js deleted file mode 100644 index d954743..0000000 --- a/src/utils/request.js +++ /dev/null @@ -1,95 +0,0 @@ -import { HT_HOST }from "../config"; - -function checkStatus(response) { - if (response.status >= 200 && response.status < 300) { - return response; - } else { - const message = - 'Fetch error: ' + response.url + ' ' + response.status + ' (' + - response.statusText + ')'; - const error = new Error(message); - error.response = response; - throw error; - } -} - -export function fetchText(url) { - return fetch(url) - .then(checkStatus) - .then(response => response.text()) - .catch(error => { - throw error; - }); -} - -export function fetchJSON(url, data) { - let params = ''; - let ifp = ''; - if (data) { - params = new URLSearchParams(data).toString(); - ifp = params ? '?' : ifp; - } - ifp = url.includes('?') ? '' : ifp; - const host = /^https?:\/\//i.test(url) ? '': HT_HOST; - return fetch(`${host}${url}${ifp}${params}`) - .then(checkStatus) - .then(response => response.json()) - .catch(error => { - throw error; - }); -} - -export function postForm(url, data) { - return fetch(url, { - method: 'POST', - body: data - }).then(checkStatus) - .then(response => response.json()) - .catch(error => { - throw error; - }); -} - -export function postJSON(url, obj) { - const host = /^https?:\/\//i.test(url) ? '': HT_HOST; - return fetch(`${host}${url}`, { - method: 'POST', - body: JSON.stringify(obj), - headers: { - 'Content-type': 'application/json; charset=UTF-8' - } - }).then(checkStatus) - .then(response => response.json()) - .catch(error => { - throw error; - }); -} - -export function postStream(url, obj) { - return fetch(url, { - method: 'POST', - body: JSON.stringify(obj), - headers: { - 'Content-type': 'application/octet-stream' - } - }).then(checkStatus) - .then(response => response.json()) - .catch(error => { - throw error; - }); -} - -export function delJSON(url, obj) { - const host = /^https?:\/\//i.test(url) ? '': HT_HOST; - return fetch(`${host}${url}`, { - method: 'DELETE', - body: JSON.stringify(obj), - headers: { - 'Content-type': 'application/json; charset=UTF-8' - } - }).then(checkStatus) - .then(response => response.json()) - .catch(error => { - throw error; - }); -}