/** * demo: * arr = [{name: "zhang", value: 2}] * key = "name" * return {zhang: {name: "zhang", value: 2}} * * @param {Array} arr * @param {String} key * @param {String} valueKey 需求的字段,不传则返回整个item * @returns {Object} */ export function arrToMap(arr, key, valueKey) { return (arr || []).reduce((target, item) => { if (valueKey) { target[item[key]] = item[valueKey]; } else { target[item[key]] = item; } return target; }, {}); } /** * 同 arrToMap, 返回的数据结构为Map * @param {Array} arr * @param {String} key * @param {String} valueKey 需求的字段,不传则返回整个item * @returns {Map} */ export function arrToRealMap(arr, key, valueKey) { const map = new Map(); (arr || []).forEach((item) => { if (valueKey) { map.set(item[key], item[valueKey]); } else { map.set(item[key], item); } }); return map; } // 基础数据类型的深拷贝 export function baseDeepClone(target) { return JSON.parse(JSON.stringify(target)); } /** * string 属性去前后空格 * @param { Object } obj */ export function objTrim(obj = {}) { const _trim = (root) => { for (let attr in root) { let value = root[attr]; if (typeof value === "string") { // string root[attr] = value.trim(); } else if (value && typeof value === "object") { // array, object _trim(root[attr]); } } }; _trim(obj); return obj; } /** * 排序 */ export function sortBy(arr = [], sortKey = "sortNo", ascDesc = "asc") { if (ascDesc === "asc") (arr || []).sort((a, b) => a[sortKey] - b[sortKey]); else (arr || []).sort((a, b) => b[sortKey] - a[sortKey]); } /** * string 校准页码 处理只有一条数据删除时或批量全删除方舟bug * @param { Object } el 实例 */ export function updateLastPage(el) { if ( (el.tableData.length === 1 && el.currentPage != 1) || (el.tableData.length === el.selectTableData.length && el.currentPage != 1) ) { const page = el.getCurrentPage(); el.setCurrentPage(page - 1); return; } return; } /** * 根据value查询树结构label * @param { Array } treeList 树结构数据 * @param { String, Number } value 对应value值 */ export function formatLabel(treeList, value) { let label = ""; const loop = (list) => { list.forEach((item) => { if (item.value === value) { label = item.label; } if (item.children) { loop(item.children); } }); }; loop(treeList); return label; } /** * 四舍五入, 与数学中的规则相同 * toFixed是银行家舍入法,与数学中的规则不同 * round是奇进偶舍,与数学中的规则不同 * @param num_ 数字 * @param decimals 位数 * @param intReplenish 整数后面是否补零 * @returns {string|string} */ export function ibfRound(num_, decimals = 2, intReplenish = false) { let num = num_ + ""; if (!~num.indexOf(".")) { if (intReplenish && decimals > 0) { num += "."; for (let i = 0; i < decimals; i++) { num += "0"; } return num; } else { return num_; } } let lis = num.split("."); let decimalPart = lis[1]; if (decimalPart.length > decimals) { if (Number(decimalPart[decimals] >= 5)) { let result = advOne(lis[0] + "." + decimalPart.substring(0, decimals)); return decimals === 0 ? result.replace(".", "") : result; } else { let result = lis[0] + "." + decimalPart.substring(0, decimals); return decimals === 0 ? result.replace(".", "") : result; } } else if (decimalPart.length === decimals) { return num; } else { let diff = decimals - decimalPart.length; let s = ""; for (let i = 0; i < diff; i++) { s += "0"; } return num + s; } } // 往前进一 function advOne(str) { let isIndex = -1; for (let i = str.length - 1; i >= 0; i--) { if (str[i] === ".") continue; if (Number(str[i]) !== 9) { isIndex = i; break; } } if (!~isIndex) { return "1" + str.replaceAll("9", "0"); } let listReverse = []; let done = false; function loop(idx) { if (idx < 0) { return; } if (done) { listReverse.push(str[idx]); } else if (str[idx] === ".") { listReverse.push("."); } else if (Number(str[idx]) === 9) { listReverse.push("0"); } else if (idx === isIndex) { listReverse.push(Number(str[idx]) + 1); done = true; } idx--; loop(idx); } loop(str.length - 1); return listReverse.reverse().join(""); } /** * 格式化字典项/业务参数项编码 * @param { String} code 字典项/业务参数项编码 */ export function formatCode(code) { if (code?.includes("-")) { const codelist = code.split("-"); return codelist[codelist.length - 1]; } else { return code; } } export function _throttle(fn, wait = 500) { let last, now; return function () { now = Date.now(); if (last && now - last < wait) { last = now; } else { last = now; fn.call(this, ...arguments); } }; } /** * 判断空 * */ export function empty(v) { switch (typeof v) { case "undefined": return true; case "string": if (v.trim().length == 0) return true; break; case "boolean": if (!v) return true; break; case "number": if (0 === v) return false; break; case "object": if (null === v) return true; if (undefined !== v.length && v.length == 0) return true; for (var k in v) { return false; } return true; } return false; } /** * 转换人员 * @param { list } 人员数组对象 * @param { idString } 人员名称长字符串 * @param { nameString } 人员id长字符串 * @param { list.id } 人员数组对象 代表id的字段名 * @param { list.name } 人员数组对象 代表name的字段名 * * */ export function formatUserList({ idString = "", nameString = "", list = [], id = "fd_username", name = "fd_display_name", }) { if (list && list.length > 0) { var userId = ""; var userName = ""; list.forEach((element) => { userId += `${element[id]},`; userName += `${element[name]},`; }); userId = userId.slice(0, userId.length - 1); userName = userName.slice(0, userName.length - 1); return { userId, userName, userList: [], }; } else if (idString && nameString) { var idList = idString.split(","); var nameList = nameString.split(","); const userList = []; idList.forEach((element, i) => { nameList.forEach((item, index) => { if (index === i) { userList.push({ fd_username: element, fd_display_name: item, }); } }); }); return { userList, userId: "", userName: "", }; } else { return { userList: [], userId: "", userName: "", }; } } // 判断是否是对象 export function isObject(value) { // * 判断是否是一个对象 const valueType = typeof value; // * 注意:null也是一个对象 return value !== null && (valueType == "object" || valueType == "function"); } // 复杂数据深拷贝 export function complexDeepClone(originValue) { // * 1. 判断是否是一个Set类型 if (originValue instanceof Set) { let set = new Set(); originValue.forEach((key) => { set.add(complexDeepClone(key)); }); return set; } // * 2. 判断是否是一个Map类型 if (originValue instanceof Map) { let map = new Map(); originValue.forEach((key, value) => { originValue.set(complexDeepClone(key), complexDeepClone(value)); }); return map; } // *3. 判断如果是Symbol的value,那么创建一个新的Symbol if (typeof originValue == "symbol") return Symbol(originValue.description); // * 4..判断如果是函数类型,那么直接使用同一个函数 if (typeof originValue == "function") return originValue; // 判断传入的originValue 是否是一个对象 // * 5. 如果不是一个对象,直接将值返回 if (!isObject(originValue)) return originValue; // * 6.判断对象是否为数组还是对象,如果为数组,初始为[],否则为{} const newObject = Array.isArray(originValue) ? [] : {}; for (const key in originValue) { newObject[key] = complexDeepClone(originValue[key]); } // * 对Symbol的key进行特殊处理 const symbolKeys = Object.getOwnPropertySymbols(originValue); for (const sKey of symbolKeys) { newObject[sKey] = complexDeepClone(originValue[sKey]); } return newObject; } // 树转平铺 export function setTreeFormatList(arr) { let data = JSON.parse(JSON.stringify(arr)); // 对传入的参数进行深拷贝 let newData = []; // 创建空数组用来接收操作后的新数组 const hasChildren = (item) => { // 递归遍历,把包含children的选项拿出来,push到之前新建的空数组内 (item.children || (item.children = [])).map((v) => { hasChildren(v); }); delete item.children; // 删除原children属性,可选项 newData.push(item); }; data.map((v) => hasChildren(v)); return newData; } // 初始化数组长度为n的记录 export function genTimesArray(times, callback) { let arr = []; for (let i = 0; i < times; i++) { arr.push(callback(i)); } return arr; } // 浅拷贝属性,但排除自定的字段 export function excludeAttr(target, attrKeys) { if (!target) return {}; const obj = {}; Object.keys(target).forEach((attrKey) => { if (!attrKeys.includes(attrKey)) { obj[attrKey] = target[attrKey]; } }); return obj; } // 浅拷贝属性,复制特定字段 export function copyAttr(target, attrKeys) { if (!target) return {}; const obj = {}; (attrKeys || []).forEach((attrKey) => { obj[attrKey] = target[attrKey]; }); return obj; } /** * 安全访问目标,若是函数则调用,否则直接转boolean * @param {Function|Boolean} target * @param {*} payload */ export function safeCallFuncBool(target, payload) { if (typeof target === "function") { return target(payload); } return !!target; } /** * 转换校验结果为Promise * @param {Function} validate * @param {Boolean} isCallbackMode 校验方法是否为回调模式,否则为直接返回true/false模式 * @returns */ export function resolveValidate(validate, isCallbackMode = true) { return new Promise((resolve, reject) => { const done = (valid) => { if (valid) return resolve(); reject(); }; if (!validate) return reject(); if (isCallbackMode) { validate(done); } else { done(validate()); } }); } // 金额千分位显示 export function getThousandsValue(value) { if (!value) return 0; return Number(value).toLocaleString("en-us"); }