visuddhinanda 9 miesięcy temu
rodzic
commit
56e994c767

+ 218 - 63
dashboard-v4/dashboard/src/pages/library/search/search.tsx

@@ -1,8 +1,10 @@
 import { useNavigate, useParams, useSearchParams } from "react-router-dom";
 import { useEffect, useState } from "react";
-import { Row, Col, Breadcrumb, Space, Tabs, Select } from "antd";
+import { Row, Col, Breadcrumb, Space, Tabs, Select, Button, Affix } from "antd";
 import FullSearchInput from "../../../components/fts/FullSearchInput";
 import FullTextSearchResult, {
+  IFtsItem,
+  IFtsResponse,
   ISearchView,
 } from "../../../components/fts/FullTextSearchResult";
 import FtsBookList from "../../../components/fts/FtsBookList";
@@ -12,16 +14,26 @@ import PageNumberList from "../../../components/fts/PageNumberList";
 import { Key } from "antd/es/table/interface";
 
 import BookTreeWithTags from "../../../components/corpus/BookTreeWithTags";
+import AIChatComponent from "../../../components/chat/AiChat";
+import { get } from "../../../request";
 
 const Widget = () => {
   const { key } = useParams();
   const [searchParams, setSearchParams] = useSearchParams();
-  const [bookRoot, setBookRoot] = useState("default");
   const [bookPath, setBookPath] = useState<string[]>([]);
   const navigate = useNavigate();
   const [pageType, setPageType] = useState("P");
   const [view, setView] = useState<ISearchView | undefined>("pali");
   const [caseWord, setCaseWord] = useState<string[]>();
+  const [prompt, setPrompt] = useState<string>();
+  const [sysPrompt, setSysPrompt] = useState<string>();
+
+  const [ftsData, setFtsData] = useState<IFtsItem[]>();
+  const [total, setTotal] = useState<number>();
+  const [loading, setLoading] = useState(false);
+  const [currPage, setCurrPage] = useState<number>(1);
+
+  const [chat, setChat] = useState(false);
 
   useEffect(() => {
     const v = searchParams.get("view");
@@ -30,19 +42,112 @@ const Widget = () => {
     }
   }, [key, searchParams]);
 
+  const sTags = searchParams.get("tags")?.split(",");
+  const bookId = searchParams.get("book");
+  const orderBy = searchParams.get("orderby");
+  const match = searchParams.get("match");
+  const bold = searchParams.get("bold");
+
+  useEffect(
+    () => setCurrPage(1),
+    [view, key, caseWord, sTags, bookId, match, pageType, bold]
+  );
+
   useEffect(() => {
-    let currRoot: string | null;
-    currRoot = localStorage.getItem("pali_path_root");
-    if (currRoot === null) {
-      currRoot = "default";
+    /**
+     * 搜索引擎选择逻辑
+     * 如果 keyWord 包涵空格 使用 tulip
+     * 如果 keyWord 不包涵空格 使用 wbw
+     */
+    let words;
+    let api = "";
+    if (key?.trim().includes(" ")) {
+      api = "search";
+      words = key;
+    } else {
+      api = "search-pali-wbw";
+      words = caseWord?.join();
+    }
+
+    let url = `/v2/${api}?view=${view}&key=${words}`;
+    if (typeof sTags !== "undefined") {
+      url += `&tags=${sTags}`;
+    }
+    if (bookId) {
+      url += `&book=${bookId}`;
+    }
+    if (orderBy) {
+      url += `&orderby=${orderBy}`;
+    }
+    if (match) {
+      url += `&match=${match}`;
     }
-    setBookRoot(currRoot);
-  }, []);
+    if (pageType) {
+      url += `&type=${pageType}`;
+    }
+    if (bold) {
+      url += `&bold=${bold}`;
+    }
+    const offset = (currPage - 1) * 10;
+    url += `&limit=10&offset=${offset}`;
+    console.log("fetch url", url);
+    setLoading(true);
+    get<IFtsResponse>(url)
+      .then((json) => {
+        if (json.ok) {
+          console.log("data", json.data);
+          const result: IFtsItem[] = json.data.rows.map((item) => {
+            return {
+              book: item.book,
+              paragraph: item.paragraph,
+              title: item.title ? item.title : item.paliTitle,
+              paliTitle: item.paliTitle,
+              content: item.highlight
+                ? item.highlight.replaceAll("** ti ", "**ti ")
+                : item.content,
+              path: item.path,
+              rank: item.rank,
+            };
+          });
+          setFtsData(result);
+          setTotal(json.data.count);
+          if (result && result.length > 0) {
+            const chat = result
+              .map((item) => {
+                return `## ${item.title}-${item.paliTitle} \n\n${item.content}\n\n`;
+              })
+              .join("");
+            setSysPrompt(`${chat}\n\n请根据上述巴利文本内容,回答用户的问题`);
+          }
+        } else {
+          console.error(json.message);
+        }
+      })
+      .finally(() => setLoading(false));
+  }, [
+    bold,
+    bookId,
+    caseWord,
+    currPage,
+    key,
+    match,
+    orderBy,
+    pageType,
+    sTags,
+    view,
+  ]);
+
+  let bookRoot = "default";
+  const currRoot = localStorage.getItem("pali_path_root");
+  if (currRoot) {
+    bookRoot = currRoot;
+  }
+
   return (
     <>
       <Row>
         <Col flex="auto"></Col>
-        <Col flex="1440px">
+        <Col>
           <Row>
             <Col xs={0} sm={6} md={5}>
               <BookTreeWithTags
@@ -65,7 +170,7 @@ const Widget = () => {
                 }}
               />
             </Col>
-            <Col xs={24} sm={18} md={13}>
+            <Col xs={24} sm={18} md={12}>
               <Space direction="vertical" style={{ padding: 10 }}>
                 <Space>
                   <FullSearchInput
@@ -167,65 +272,115 @@ const Widget = () => {
                     },
                   ]}
                 />
-                <FullTextSearchResult
-                  view={view as ISearchView}
-                  pageType={pageType}
-                  keyWord={key}
-                  keyWords={caseWord}
-                  tags={searchParams.get("tags")?.split(",")}
-                  bookId={searchParams.get("book")}
-                  orderBy={searchParams.get("orderby")}
-                  match={searchParams.get("match")}
-                  bold={searchParams.get("bold")}
+                <AIChatComponent
+                  initMessage={prompt}
+                  systemPrompt={sysPrompt}
+                  onChat={() => setChat(true)}
                 />
+                <div>
+                  <Space>
+                    <Button
+                      onClick={() =>
+                        setPrompt(
+                          `写一个关于**${key}**的概要,概要中的观点应该引用上述巴利文经文,并逐条列出每个巴利原文每个段落的摘要`
+                        )
+                      }
+                    >
+                      概要
+                    </Button>
+                    <Button
+                      onClick={() =>
+                        setPrompt(
+                          `写一个介绍**${key}**的百科词条,词条中的观点应该引用巴利文经文,并给出引用的巴利原文和译文`
+                        )
+                      }
+                    >
+                      术语
+                    </Button>
+                  </Space>
+                </div>
+                {chat ? (
+                  <></>
+                ) : (
+                  <FullTextSearchResult
+                    view={view}
+                    ftsData={ftsData}
+                    total={total}
+                    loading={loading}
+                    currPage={currPage}
+                    onChange={(page) => {
+                      console.log(page);
+                      setCurrPage(page);
+                    }}
+                  />
+                )}
               </Space>
             </Col>
-            <Col xs={0} sm={0} md={6}>
-              {key && parseInt(key) ? (
-                <PageNumberList
-                  keyWord={key}
-                  onSelect={(selectedKeys: Key[]) => {
-                    console.log("selectedKeys", selectedKeys);
-                    if (selectedKeys.length > 0) {
-                      if (typeof selectedKeys[0] === "string") {
-                        const queryString = selectedKeys[0].split("-");
-                        if (queryString.length === 3) {
-                          setCaseWord(queryString[1].split(","));
-                          if (parseInt(queryString[2]) === 0) {
-                            searchParams.delete("book");
-                          } else {
-                            searchParams.set("book", queryString[2]);
+            <Col xs={0} sm={0} md={7}>
+              <Affix offsetTop={0}>
+                <div style={{ height: "100vh", overflowY: "auto" }}>
+                  {key && parseInt(key) ? (
+                    <PageNumberList
+                      keyWord={key}
+                      onSelect={(selectedKeys: Key[]) => {
+                        console.log("selectedKeys", selectedKeys);
+                        if (selectedKeys.length > 0) {
+                          if (typeof selectedKeys[0] === "string") {
+                            const queryString = selectedKeys[0].split("-");
+                            if (queryString.length === 3) {
+                              setCaseWord(queryString[1].split(","));
+                              if (parseInt(queryString[2]) === 0) {
+                                searchParams.delete("book");
+                              } else {
+                                searchParams.set("book", queryString[2]);
+                              }
+                              setSearchParams(searchParams);
+                            }
                           }
-                          setSearchParams(searchParams);
                         }
-                      }
-                    }
-                  }}
-                />
-              ) : (
-                <CaseList
-                  word={key}
-                  lines={5}
-                  onChange={(value: string[]) => setCaseWord(value)}
-                />
-              )}
+                      }}
+                    />
+                  ) : (
+                    <CaseList
+                      word={key}
+                      lines={5}
+                      onChange={(value: string[]) => setCaseWord(value)}
+                    />
+                  )}
 
-              <FtsBookList
-                view={view}
-                keyWord={key}
-                keyWords={caseWord}
-                tags={searchParams.get("tags")?.split(",")}
-                match={searchParams.get("match")}
-                bookId={searchParams.get("book")}
-                onSelect={(bookId: number) => {
-                  if (bookId !== 0) {
-                    searchParams.set("book", bookId.toString());
-                  } else {
-                    searchParams.delete("book");
-                  }
-                  setSearchParams(searchParams);
-                }}
-              />
+                  <FtsBookList
+                    view={view}
+                    keyWord={key}
+                    keyWords={caseWord}
+                    tags={searchParams.get("tags")?.split(",")}
+                    match={searchParams.get("match")}
+                    bookId={searchParams.get("book")}
+                    onSelect={(bookId: number) => {
+                      if (bookId !== 0) {
+                        searchParams.set("book", bookId.toString());
+                      } else {
+                        searchParams.delete("book");
+                      }
+                      setSearchParams(searchParams);
+                    }}
+                  />
+                  {chat ? (
+                    <FullTextSearchResult
+                      view={view}
+                      ftsData={ftsData}
+                      total={total}
+                      loading={loading}
+                      currPage={currPage}
+                      onChange={(page) => {
+                        console.log(page);
+                        setCurrPage(page);
+                      }}
+                    />
+                  ) : (
+                    <></>
+                  )}
+                </div>
+              </Affix>
             </Col>
           </Row>
         </Col>