export interface IObjectSortArgs { /** 排序的 Key */ key: string /** 是否升序 */ isAsc?: boolean /** 排序类型 */ type?: "string" | "number" | "date" | "boolean" /** 匹配用来排序的部分 */ matcher?: (value?: any) => any | RegExp /** 顺序表。排序的值会按此顺序 */ orderRanks?: string[] } /** * 排序对象数组 * @param list * @param options * @returns */ export function sortObjectArray>( list: T[], sortArgs: IObjectSortArgs[] | IObjectSortArgs, options?: { /** 就地替换(默认会返回一个新数组) */ inPlace?: boolean } ) { if (!list || list.length === 0) return list let sortedList = options?.inPlace ? list : list.slice() let sortArgsArray = Array.isArray(sortArgs) ? sortArgs : [sortArgs] sortArgsArray = sortArgsArray.map((arg) => { arg = Object.assign({}, arg) if (!arg.type) { arg.type = typeof list[0][arg.key] } return arg }) let lang = typeof navigator !== "undefined" ? navigator.language : "zh-CN" let intlCompare = new Intl.Collator(lang, { numeric: true, }).compare // // console.log("sortArgsArray", sortArgsArray) sortedList = sortedList.sort((a, b) => { for (const { key, isAsc, type, matcher, orderRanks } of sortArgsArray) { let aValue = a[key] let bValue = b[key] let result if (matcher) { aValue = getValueByMatcher(aValue, matcher) bValue = getValueByMatcher(bValue, matcher) } if (orderRanks) { aValue = orderRanks.indexOf(aValue) bValue = orderRanks.indexOf(bValue) result = isAsc ? aValue - bValue : bValue - aValue } else if (type === "number") { result = isAsc ? aValue - bValue : bValue - aValue } else if (type === "date") { if (!(aValue instanceof Date)) aValue = new Date(aValue) if (!(bValue instanceof Date)) bValue = new Date(bValue) aValue = aValue.getTime() bValue = bValue.getTime() result = isAsc ? aValue - bValue : bValue - aValue } else if (type === "boolean") { result = isAsc ? (aValue ? 1 : 0) - (bValue ? 1 : 0) : (bValue ? 1 : 0) - (aValue ? 1 : 0) } // type === "string" else { result = isAsc ? intlCompare(aValue, bValue) : intlCompare(bValue, aValue) } if (result !== 0) return result } return 0 }) return sortedList } function getValueByMatcher(value: any, matcher: (value?: any) => any | RegExp) { if (matcher instanceof RegExp) { let match = value.match(matcher) return match ? match[0] : value } else if (typeof matcher === "function") { return matcher(value) } return value }