From ebbd788fbb2c0b45d4473798efc57eec8ba74a25 Mon Sep 17 00:00:00 2001 From: Ben Lin <maobin001@msn.com> Date: 星期二, 18 六月 2024 14:51:16 +0800 Subject: [PATCH] 版本更新至2.11.5 --- src/components/Application/src/search/useMenuSearch.ts | 137 +++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 123 insertions(+), 14 deletions(-) diff --git a/src/components/Application/src/search/useMenuSearch.ts b/src/components/Application/src/search/useMenuSearch.ts index c938792..b9875a8 100644 --- a/src/components/Application/src/search/useMenuSearch.ts +++ b/src/components/Application/src/search/useMenuSearch.ts @@ -1,18 +1,20 @@ -import { type Menu } from '/@/router/types'; -import { type AnyFunction } from '@vben/types'; -import { ref, onBeforeMount, unref, Ref, nextTick } from 'vue'; -import { getMenus } from '/@/router/menus'; -import { cloneDeep } from 'lodash-es'; -import { filter, forEach } from '/@/utils/helper/treeHelper'; -import { useGo } from '/@/hooks/web/usePage'; +import { useI18n } from '@/hooks/web/useI18n'; +import { useGo } from '@/hooks/web/usePage'; +import { getMenus } from '@/router/menus'; +import { type Menu } from '@/router/types'; +import { filter, forEach } from '@/utils/helper/treeHelper'; import { useScrollTo } from '@vben/hooks'; +import { type AnyFunction } from '@vben/types'; import { onKeyStroke, useDebounceFn } from '@vueuse/core'; -import { useI18n } from '/@/hooks/web/useI18n'; +import { cloneDeep } from 'lodash-es'; +import { Ref, nextTick, onBeforeMount, ref, unref } from 'vue'; export interface SearchResult { name: string; path: string; icon?: string; + // 鎼滅储缁撴灉鍖呭惈鐨勫瓧绗︾潃鑹� + chars: { char: string; highlight: boolean }[]; } // Translate special characters @@ -42,21 +44,21 @@ const list = await getMenus(); menuList = cloneDeep(list); forEach(menuList, (item) => { - item.name = t(item.name); + item.name = t(item.meta?.title || item.name); }); }); function search(e: ChangeEvent) { e?.stopPropagation(); const key = e.target.value; - keyword.value = key.trim(); + keyword.value = key.trim().toLowerCase(); if (!key) { searchResult.value = []; return; } const reg = createSearchReg(unref(keyword)); const filterMenu = filter(menuList, (item) => { - return reg.test(item.name) && !item.hideMenu; + return reg.test(item.name?.toLowerCase()) && !item.hideMenu; }); searchResult.value = handlerSearchResult(filterMenu, reg); activeIndex.value = 0; @@ -66,9 +68,87 @@ const ret: SearchResult[] = []; filterMenu.forEach((item) => { const { name, path, icon, children, hideMenu, meta } = item; - if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) { + if ( + !hideMenu && + 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, }); @@ -77,7 +157,36 @@ 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 -- Gitblit v1.9.3