@ -13,6 +13,8 @@ export interface SearchResult {
name : string ;
path : string ;
icon? : string ;
// 搜索结果包含的字符着色
chars : { char : string ; highlight : boolean } [ ] ;
}
// Translate special characters
@ -68,11 +70,85 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref, emit: A
const { name , path , icon , children , hideMenu , meta } = item ;
if (
! hideMenu &&
reg . test ( name ? . toLowerCase ( ) ) &&
reg . test ( name ? . toLowerCase ( ) ? ? '' ) &&
( ! children ? . length || meta ? . hideChildrenInMenu )
) {
const chars : { char : string ; highlight : boolean } [ ] = [ ] ;
// 显示字符串
const label = ( parent ? . name ? ` ${ parent . name } > ${ name } ` : name ) ? ? '' ;
const labelChars = label . split ( '' ) ;
let labelPointer = 0 ;
const keywordChars = keyword . value . split ( '' ) ;
const keywordLength = keywordChars . length ;
let keywordPointer = 0 ;
// 用于查找完整关键词的匹配
let includePointer = 0 ;
// 优先查找完整关键词的匹配
if ( label . toLowerCase ( ) . includes ( keyword . value . toLowerCase ( ) ) ) {
while ( includePointer < labelChars . length ) {
if (
label . toLowerCase ( ) . slice ( includePointer , includePointer + keywordLength ) ===
keyword . value . toLowerCase ( )
) {
chars . push (
. . . label
. substring ( labelPointer , includePointer )
. split ( '' )
. map ( ( v ) = > ( {
char : v ,
highlight : false ,
} ) ) ,
) ;
chars . push (
. . . label
. slice ( includePointer , includePointer + keywordLength )
. split ( '' )
. map ( ( v ) = > ( {
char : v ,
highlight : true ,
} ) ) ,
) ;
includePointer += keywordLength ;
labelPointer = includePointer ;
} else {
includePointer ++ ;
}
}
}
// 查找满足关键词顺序的匹配
while ( labelPointer < labelChars . length ) {
keywordPointer = 0 ;
while ( keywordPointer < keywordChars . length ) {
if ( keywordChars [ keywordPointer ] !== void 0 && labelChars [ labelPointer ] !== void 0 ) {
if (
keywordChars [ keywordPointer ] . toLowerCase ( ) ===
labelChars [ labelPointer ] . toLowerCase ( )
) {
chars . push ( {
char : labelChars [ labelPointer ] ,
highlight : true ,
} ) ;
keywordPointer ++ ;
} else {
chars . push ( {
char : labelChars [ labelPointer ] ,
highlight : false ,
} ) ;
}
} else {
keywordPointer ++ ;
}
labelPointer ++ ;
}
}
ret . push ( {
name : parent?.name ? ` ${ parent . name } > ${ name } ` : name ,
name : label ,
chars ,
path ,
icon ,
} ) ;
@ -81,7 +157,36 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref, emit: A
ret . push ( . . . handlerSearchResult ( children , reg , item ) ) ;
}
} ) ;
return ret ;
// 排序
return ret . sort ( ( a , b ) = > {
if (
a . name . toLowerCase ( ) . includes ( keyword . value . toLowerCase ( ) ) &&
b . name . toLowerCase ( ) . includes ( keyword . value . toLowerCase ( ) )
) {
// 两者都存在完整关键词的匹配
// 匹配数量
const ca =
a . name . toLowerCase ( ) . match ( new RegExp ( keyword . value . toLowerCase ( ) , 'g' ) ) ? . length ? ? 0 ;
const cb =
b . name . toLowerCase ( ) . match ( new RegExp ( keyword . value . toLowerCase ( ) , 'g' ) ) ? . length ? ? 0 ;
// 匹配数量越多的优先显示,数量相同的按字符串排序
return ca === cb ? a . name . toLowerCase ( ) . localeCompare ( b . name . toLowerCase ( ) ) : cb - ca ;
} else {
if ( a . name . toLowerCase ( ) . includes ( keyword . value . toLowerCase ( ) ) ) {
// 完整关键词的匹配优先
return - 1 ;
} else if ( b . name . toLowerCase ( ) . includes ( keyword . value . toLowerCase ( ) ) ) {
// 完整关键词的匹配优先
return 1 ;
} else {
// 按字符串排序
return a . name . toLowerCase ( ) . localeCompare ( b . name . toLowerCase ( ) ) ;
}
}
} ) ;
}
// Activate when the mouse moves to a certain line