Pārlūkot izejas kodu

优化搜索算法,更新图标

heweikang 1 gadu atpakaļ
vecāks
revīzija
3da5284a07

+ 59 - 41
app/components/search-chat.tsx

@@ -1,4 +1,4 @@
-import { useState, useEffect } from "react";
+import { useState, useEffect, useRef } from "react";
 import { ErrorBoundary } from "./error";
 import styles from "./mask.module.scss";
 import { useNavigate } from "react-router-dom";
@@ -25,63 +25,80 @@ export function SearchChatPage() {
 
   const [searchResults, setSearchResults] = useState<Item[]>([]);
 
-  const setDefaultItems = () => {
-    setSearchResults(
-      sessions.slice(1, 7).map((session, index) => {
-        console.log(session.messages[0]);
-        return {
-          id: index,
-          name: session.topic,
-          content: session.messages[0].content as string, //.map((m) => m.content).join("\n")
-        };
-      }),
-    );
-  };
-  useEffect(() => {
-    setDefaultItems();
-  }, []);
-
+  // const setDefaultItems = () => {
+  //   setSearchResults(
+  //     sessions.slice(1, 7).map((session, index) => {
+  //       return {
+  //         id: index,
+  //         name: session.topic,
+  //         content: session.messages[0].content as string, //.map((m) => m.content).join("\n")
+  //       };
+  //     }),
+  //   );
+  // };
+  // useEffect(() => {
+  //   setDefaultItems();
+  // }, []);
+
+  const previousValueRef = useRef<string>("");
+  const searchInputRef = useRef<HTMLInputElement>(null);
   const doSearch = (text: string) => {
-    // 分割关键词
-    const keywords = text.split(" ");
-
-    // 存储每个会话的匹配结果
-    const searchResults: Item[] = [];
+    const lowerCaseText = text.toLowerCase();
+    const results: Item[] = [];
 
     sessions.forEach((session, index) => {
-      let matchCount = 0;
-      const contents: string[] = [];
+      const fullTextContents: string[] = [];
 
       session.messages.forEach((message) => {
         const content = message.content as string;
         const lowerCaseContent = content.toLowerCase();
-        keywords.forEach((keyword) => {
-          const pos = lowerCaseContent.indexOf(keyword.toLowerCase());
-          if (pos !== -1) {
-            matchCount++;
-            // 提取关键词前后70个字符的内容
-            const start = Math.max(0, pos - 35);
-            const end = Math.min(content.length, pos + keyword.length + 35);
-            contents.push(content.substring(start, end));
-          }
-        });
+
+        // 全文搜索
+        let pos = lowerCaseContent.indexOf(lowerCaseText);
+        while (pos !== -1) {
+          const start = Math.max(0, pos - 35);
+          const end = Math.min(content.length, pos + lowerCaseText.length + 35);
+          fullTextContents.push(content.substring(start, end));
+          pos = lowerCaseContent.indexOf(
+            lowerCaseText,
+            pos + lowerCaseText.length,
+          );
+        }
       });
 
-      if (matchCount > 0) {
-        searchResults.push({
+      if (fullTextContents.length > 0) {
+        results.push({
           id: index,
           name: session.topic,
-          content: contents.join("... "), // 使用...连接不同消息中的内容
+          content: fullTextContents.join("... "), // 使用...连接不同消息中的内容
         });
       }
     });
 
-    // 按匹配数量排序,取前10个结果
-    return searchResults
-      .sort((a, b) => b.content.length - a.content.length)
-      .slice(0, 10);
+    // 按内容长度排序
+    results.sort((a, b) => b.content.length - a.content.length);
+
+    return results;
   };
 
+  useEffect(() => {
+    const intervalId = setInterval(() => {
+      if (searchInputRef.current) {
+        const currentValue = searchInputRef.current.value;
+        if (currentValue !== previousValueRef.current) {
+          if (currentValue.length > 0) {
+            const result = doSearch(currentValue);
+            setSearchResults(result);
+          }
+          previousValueRef.current = currentValue;
+        }
+      }
+    }, 1000);
+
+    // Cleanup the interval on component unmount
+    return () => clearInterval(intervalId);
+  }, []);
+
   return (
     <ErrorBoundary>
       <div className={styles["mask-page"]}>
@@ -115,6 +132,7 @@ export function SearchChatPage() {
               className={styles["search-bar"]}
               placeholder={Locale.SearchChat.Page.Search}
               autoFocus
+              ref={searchInputRef}
               onKeyDown={(e) => {
                 if (e.key === "Enter") {
                   e.preventDefault();

+ 2 - 2
app/components/sidebar.tsx

@@ -12,7 +12,7 @@ import DeleteIcon from "../icons/delete.svg";
 import MaskIcon from "../icons/mask.svg";
 import DragIcon from "../icons/drag.svg";
 import DiscoveryIcon from "../icons/discovery.svg";
-
+import SearchIcon from "../icons/zoom.svg";
 import Locale from "../locales";
 
 import { useAppConfig, useChatStore } from "../store";
@@ -251,7 +251,7 @@ export function SideBar(props: { className?: string }) {
             shadow
           />
           <IconButton
-            icon={<DiscoveryIcon />}
+            icon={<SearchIcon />}
             text={shouldNarrow ? undefined : Locale.SearchChat.Name}
             className={styles["sidebar-bar-button"]}
             onClick={() =>

+ 1 - 0
app/icons/zoom.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1.2rem" height="1.2rem" viewBox="0 0 24 24"><g fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></g></svg>

+ 1 - 1
app/locales/cn.ts

@@ -523,7 +523,7 @@ const cn = {
     Name: "搜索",
     Page: {
       Title: "搜索聊天记录",
-      Search: "输入多个关键词(空格分隔), 回车搜索",
+      Search: "输入搜索关键词",
       NoResult: "没有找到结果",
       NoData: "没有数据",
       Loading: "加载中",

+ 1 - 2
app/locales/en.ts

@@ -531,8 +531,7 @@ const en: LocaleType = {
     Name: "Search",
     Page: {
       Title: "Search Chat History",
-      Search:
-        "Enter multiple keywords (separated by spaces), press Enter to search",
+      Search: "Enter search query to search chat history",
       NoResult: "No results found",
       NoData: "No data",
       Loading: "Loading...",

+ 1 - 2
app/locales/jp.ts

@@ -248,8 +248,7 @@ const jp: PartialLocaleType = {
     Name: "検索",
     Page: {
       Title: "チャット履歴を検索",
-      Search:
-        "複数のキーワードを入力してください(スペースで区切る)、エンターキーを押して検索",
+      Search: "キーワードを入力してください",
       NoResult: "結果が見つかりませんでした",
       NoData: "データがありません",
       Loading: "読み込み中...",

+ 1 - 2
app/locales/ru.ts

@@ -196,8 +196,7 @@ const ru: PartialLocaleType = {
     Name: "Поиск",
     Page: {
       Title: "Поиск в истории чата",
-      Search:
-        "Введите несколько ключевых слов (разделенных пробелами), нажмите Enter для поиска",
+      Search: "Введите текст для поиска",
       NoResult: "Результаты не найдены",
       NoData: "Данные отсутствуют",
       Loading: "Загрузка...",