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