@@ -63,7 +63,7 @@ export const urljoin = (fromPath, nowPath) => {
6363export const urljoin2 = urljoin
6464export const joinUrl = urljoin
6565
66-
66+ /*
6767export function naturalSort(arr, key, customOrder = []) {
6868 return arr.sort((a, b) => {
6969 const aValue = a[key];
@@ -88,3 +88,101 @@ export function naturalSort(arr, key, customOrder = []) {
8888 return aValue.localeCompare(bValue, undefined, {numeric: true, sensitivity: 'base'});
8989 });
9090}
91+ */
92+
93+ export function naturalSort ( arr , key , customOrder = [ ] ) {
94+ const collator = new Intl . Collator ( 'zh-Hans-CN' , {
95+ numeric : true ,
96+ sensitivity : 'base' ,
97+ } ) ;
98+
99+ return arr . sort ( ( a , b ) => {
100+ const x = a [ key ] || '' ;
101+ const y = b [ key ] || '' ;
102+
103+ // 1. 检查自定义顺序
104+ const xIndex = customOrder . findIndex ( ( item ) => x . startsWith ( item ) ) ;
105+ const yIndex = customOrder . findIndex ( ( item ) => y . startsWith ( item ) ) ;
106+
107+ if ( xIndex !== - 1 || yIndex !== - 1 ) {
108+ if ( xIndex === - 1 ) return 1 ; // x 不在自定义顺序中,y 在
109+ if ( yIndex === - 1 ) return - 1 ; // y 不在自定义顺序中,x 在
110+ return xIndex - yIndex ; // 两者都在自定义顺序中,按索引排序
111+ }
112+
113+ // 2. 使用 `Intl.Collator` 进行自然排序
114+ return collator . compare ( x , y ) ;
115+ } ) ;
116+ }
117+
118+ export function naturalSortAny ( arr , key , customOrder = [ ] ) {
119+ return arr . sort ( ( a , b ) => {
120+ const EQUAL = 0 ;
121+ const GREATER = 1 ;
122+ const SMALLER = - 1 ;
123+
124+ const options = { caseSensitive : false } ;
125+
126+ const re = / ( ^ - ? [ 0 - 9 ] + ( \. ? [ 0 - 9 ] * ) [ d f ] ? e ? [ 0 - 9 ] ? $ | ^ 0 x [ 0 - 9 a - f ] + $ | [ 0 - 9 ] + ) / gi;
127+ const sre = / ( ^ [ ] * | [ ] * $ ) / g;
128+ const dre = / ( ^ ( [ \w ] + , ? [ \w ] + ) ? [ \w ] + , ? [ \w ] + \d + : \d + ( : \d + ) ? [ \w ] ? | ^ \d { 1 , 4 } [ \/ \- ] \d { 1 , 4 } [ \/ \- ] \d { 1 , 4 } | ^ \w + , \w + \d + , \d { 4 } ) / ;
129+ const hre = / ^ 0 x [ 0 - 9 a - f ] + $ / i;
130+ const ore = / ^ 0 / ;
131+
132+ const normalize = function normalize ( value ) {
133+ const string = '' + value ;
134+ return options . caseSensitive ? string : string . toLowerCase ( ) ;
135+ } ;
136+
137+ const x = normalize ( a [ key ] ) . replace ( sre , '' ) || '' ;
138+ const y = normalize ( b [ key ] ) . replace ( sre , '' ) || '' ;
139+
140+ // Check custom order first
141+ const xIndex = customOrder . findIndex ( ( item ) => x . startsWith ( item ) ) ;
142+ const yIndex = customOrder . findIndex ( ( item ) => y . startsWith ( item ) ) ;
143+
144+ if ( xIndex !== - 1 || yIndex !== - 1 ) {
145+ if ( xIndex === - 1 ) return GREATER ; // x not in customOrder, y is
146+ if ( yIndex === - 1 ) return SMALLER ; // y not in customOrder, x is
147+ return xIndex - yIndex ; // Both in customOrder, compare their indices
148+ }
149+
150+ // chunk/tokenize
151+ const xN = x . replace ( re , '\0$1\0' ) . replace ( / \0 $ / , '' ) . replace ( / ^ \0 / , '' ) . split ( '\0' ) ;
152+ const yN = y . replace ( re , '\0$1\0' ) . replace ( / \0 $ / , '' ) . replace ( / ^ \0 / , '' ) . split ( '\0' ) ;
153+
154+ // Return immediately if at least one of the values is empty.
155+ if ( ! x && ! y ) return EQUAL ;
156+ if ( ! x && y ) return GREATER ;
157+ if ( x && ! y ) return SMALLER ;
158+
159+ // numeric, hex or date detection
160+ const xD = parseInt ( x . match ( hre ) ) || ( xN . length != 1 && x . match ( dre ) && Date . parse ( x ) ) ;
161+ const yD = parseInt ( y . match ( hre ) ) || ( xD && y . match ( dre ) && Date . parse ( y ) ) || null ;
162+ let oFxNcL , oFyNcL ;
163+
164+ // first try and sort Hex codes or Dates
165+ if ( yD ) {
166+ if ( xD < yD ) return SMALLER ;
167+ else if ( xD > yD ) return GREATER ;
168+ }
169+
170+ // natural sorting through split numeric strings and default strings
171+ for ( let cLoc = 0 , numS = Math . max ( xN . length , yN . length ) ; cLoc < numS ; cLoc ++ ) {
172+ oFxNcL = ! ( xN [ cLoc ] || '' ) . match ( ore ) && parseFloat ( xN [ cLoc ] ) || xN [ cLoc ] || 0 ;
173+ oFyNcL = ! ( yN [ cLoc ] || '' ) . match ( ore ) && parseFloat ( yN [ cLoc ] ) || yN [ cLoc ] || 0 ;
174+
175+ // handle numeric vs string comparison - number < string - (Kyle Adams)
176+ if ( isNaN ( oFxNcL ) !== isNaN ( oFyNcL ) ) return isNaN ( oFxNcL ) ? GREATER : SMALLER ;
177+
178+ // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
179+ else if ( typeof oFxNcL !== typeof oFyNcL ) {
180+ oFxNcL += '' ;
181+ oFyNcL += '' ;
182+ }
183+ if ( oFxNcL < oFyNcL ) return SMALLER ;
184+ if ( oFxNcL > oFyNcL ) return GREATER ;
185+ }
186+ return EQUAL ;
187+ } ) ;
188+ }
0 commit comments