UNPKG

@ozo/react-rock

Version:

React 移动端开发脚手架,基于CRA3,通用、开箱即用。

371 lines (339 loc) 10.7 kB
// 数据相关:Array和Map等 import { each, upperFirst, difference, isEmpty } from 'lodash-es'; /** * 对比扁平数组 * @param {array} newValue 新值,默认值[] * @param {array} oldValue 旧值,默认值[] * @returns {object} 返回结果,格式: {adds:[], dels:[]} */ export function diffFlatArray(newValue = [], oldValue = []) { if (!newValue.length) { return { adds: [], dels: oldValue, }; } const tNew = difference(newValue, oldValue); // 新增 return { adds: tNew, dels: difference(oldValue, difference(newValue, tNew)), // 删除 }; } // 清空对象的value export function initObjValue(obj) { return Object.keys(obj).reduce((result, key) => { if (obj[key] && Array.isArray(obj[key].slice())) { result[key] = []; } else { result[key] = ''; } return result; }, {}); } /** * 对象数组中按指定键值深度查找 * @param {array} data 数据源,格式:[{xxx:1,yyy:2,zzz:[{xxx:1,yyy:2,zzz:[{...}]}]}] * @param {object} {key:"",value:[] } 指定的key和value * @param {object} seed 遍历因子 * @returns {object} 找到的对象,没找到返回{} */ export function findDeepByKey(data, { key, value }, seed) { const result = []; function tFindDeepByKey(dataT, checkKey) { for (let i = 0; i < dataT.length; i++) { const item = dataT[i]; const tValue = item[key]; const tData = item[seed]; if (tValue === checkKey || (typeof tValue === 'object' && tValue[checkKey])) { result.push(item); // eslint-disable-next-line no-continue continue; } if (!isEmpty(tData)) { tFindDeepByKey(tData, checkKey); } } } value.forEach((val) => { tFindDeepByKey(data, val); }); return result; } /** * 查找叶子结点 * @param {array} arr 数据源,格式:[{xxx:1,yyy:2,zzz:[{xxx:1,yyy:2,zzz:[{...}]}]}] * @param {object} seed 遍历因子, 默认值:'data' * @returns {array} 叶子结点数组,格式:[{}] */ export function findLeafForMap(arr = [], seed = 'data') { // 选择对象片段 let tArr = []; (function tFindData(arr) { for (let i = 0; i < arr.length; i++) { let item = arr[i]; if (Object.prototype.hasOwnProperty.call(item, seed)) { tFindData(item[seed]); } else { tArr.push(item); } } })(arr); return tArr; } /** * 从集合中获取指定的key的值,返回数组 * @param {*} data 数据 * @param {string} [key='id'] 指定key * @returns {array} 返回指定key的value集合 [xx,xxx] */ export function getValuesForMap(data = [], key = 'id') { if (isEmpty(data) || data === null) { return []; } return data.map((item) => { return item[key]; }); } /** * tree组件data组装 * @param {array} arr 数据源,格式:[{xxx:1,yyy:2,zzz:[{xxx:1,yyy:2,zzz:[{...}]}]}] * @param {object} [keysMap={ id: 'key', name: 'label', data: 'children' }] 键值映射表,{原key: 目标key} * @param {object} [options={key:"",value:"", props:{}}] 操作项,扩展操作,用于筛选符合条件的子树 * @returns 组装后的数组,格式:[{}], key由keysMap映射 */ export function assembleData( arr = [], keysMap = { id: 'key', name: 'label', data: 'children' }, options = { key: '', value: '', props: {}, seed: 'data' } ) { const tMapKeys = Object.keys(keysMap); const { key: optKey, value: optValue, props, seed } = options; // 是否扩展的开关 let flag = false; // 选择对象片段 let tArr = []; return (function tAssembleData(arr) { if (arr === null) { return []; } return arr.map((item) => { if (optKey && optValue) { if (item[optKey] === optValue) { flag = true; } } // 获取满足options中key和value相等的子树 if (item[optKey] === optValue) { (function tMapResult(result) { return result.map((item) => { tArr.push(item[optKey]); const data = item[seed]; if (data && data.length) { return tMapResult(data); } return item[optKey]; }, []); })([item]); } // 根据keysMap条件组合数据 const tResult = tMapKeys.reduce((result, key) => { const tData = item[key]; if ( key === seed && tData !== null && typeof tData === 'object' && Array.isArray(tData) && tData.length > 0 ) { result[keysMap[key]] = tAssembleData(tData); } else { result[keysMap[key]] = item[key]; } return result; }, {}); // 对符合条件的树合并options中的props flag && tArr.includes(item[optKey]) && Object.assign(tResult, props); return tResult; }); })(arr); } /** * 给arr对象集合绑定key,值为子项中对应的seed的key * @param {array} data 数据源,格式:[{xxx:1,yyy:2}] * @param {object} [keysMap={ value: 'key' }] 键值映射表,{原key: 目标key} * @returns 组装后的数组,格式:[{}] */ export function bindKeyForData(data, keysMap = { value: 'key' }) { if (data !== null && typeof data === 'object' && Array.isArray(data) && data.length > 0) { const tKey = Object.keys(keysMap)[0]; data.forEach((item) => { item[keysMap[tKey]] = item[tKey]; }); return data; } } /** * 扁平对象key映射 * @param {string} [prefix=''] 前缀 * @param {*} [mapKeys=[]] 要映射的keys ['id', 'name', 'code', 'pid'] * @param {*} flatObj 操作对象 * @returns 映射对象 */ export function flatObjectMap(prefix = '', mapKeys = [], flatObj = {}) { if (mapKeys.length === 0) { return; } let tKeys = Object.keys(flatObj); if (tKeys.length === 0) { tKeys = mapKeys; } return tKeys.map((key) => { if (mapKeys.includes(key)) { return { [key]: `${this.prefix}${upperFirst(key)}`, }; } else { return { [key]: key }; } }); } export function flatDataToArr(data = [], seed = 'data') { if (isEmpty(data)) { return []; } const result = []; (function tFlatData(data) { data.forEach((item) => { const tArr = item[seed]; result.push(item); if (tArr !== null && !isEmpty(tArr)) { tFlatData(tArr); } }); })(data); return result; } //无限级分类格式化数据,供筛选逻辑使用, 格式:{根id:[{子id:text}],父id:[{子id:text}], 叶子id:{叶子id:text}} export function flatDataToObj(data, key = 'id', seed = 'data') { let results = {}; const mROOT = '0'; (function tFlatData(data) { let r = []; data.forEach((item) => { r.push(item); results[item[key]] = item; const tArr = item[seed]; if (tArr && tArr.length) { tFlatData(tArr); } else { return r; } }); if (data[key]) { results[data[key]] = r; } else { results[mROOT] = r; } })(data); return results; } /** * 重命名扁平对象 * @param {*} flatObj 操作对象 * @param {string} [prefix=''] 前缀 * @param {*} [renameKeys=[]] 要重命名的keys ['id', 'name', 'code', 'pid'] * @returns 重命名后的对象 */ export function renameFlatObject(flatObj, prefix = '', renameKeys = []) { if (renameKeys.length === 0) { return; } const tKeys = Object.keys(flatObj); return tKeys.map((key) => { if (renameKeys.includes(key)) { return { [`${this.prefix}${upperFirst(key)}`]: flatObj[key], }; } else { return { [key]: flatObj[key] }; } }); } // 分类阶层对应关系整理,格式:{子id:父id} // export function dataRank(data, key="id") { // var rank = {}; // data.forEach((item)=>{ // const tKey = item[key]; // const tVal = value; // if (Array.isArray(tVal)) { // tVal.forEach((item)=>{ // rank[item.value + ""] = tKey; // }); // } // }); // return rank; // } /** * @description 通过id获取其遗传基因链,顺序:[...,父id,当前id] * @param {*} data 源数据 * @param {*} id id * @param {*} reverse 是否反序 * @returns {array} */ export function getGenes(data, id, reverse = false) { let genes = []; const mROOT = '0'; if (!isEmpty(data)) { (function tGetGenes(data, id) { each(data, (value, key) => { if (id === key) { genes.push(Number(id)); if (id !== mROOT) { tGetGenes(data, value); } } }); })(data, id); } if (reverse) { return genes; } else { return genes.reverse(); } } /*** 以下为非通用方法 ***/ //根据传入的选中的ID,反查组织数据,返回对应的角色(树形的结构不一样,所以另外处理) export function getInitRoleArry(idsArry, dataSource) { const newArray = []; idsArry.forEach((item) => { newArray.push(dataSource.find((it) => it.id === item)); }); return newArray; } //穿梭框返回的是:key,label export function getInitArry(data) { const newPosArr = []; data.forEach((it) => { const obj = {}; obj.id = it.key; obj.name = it.label; obj.isCheck = it.disabled ? '' : 'Y'; newPosArr.push(obj); }); return newPosArr; } //根据数组对象,返回取对应的ID,字符串拼接 // param:一维数组 export function initIdsStr(param) { if (!param) { return; } const newArry = []; param.forEach((item) => { newArry.push(item.id); if (item.data && item.data.length > 0) { initIdsStr(item.data); } }); return newArry.join(','); }