Răsfoiți Sursa

Merge pull request #2212 from visuddhinanda/agile

ai段落号传参
visuddhinanda 1 an în urmă
părinte
comite
20cf4801be

+ 44 - 7
dashboard/src/components/ai/AiTranslate.tsx

@@ -1,26 +1,61 @@
 import { Button, Typography } from "antd";
-import { useState } from "react";
+import { useEffect, useState } from "react";
 import { LoadingOutlined } from "@ant-design/icons";
 
 import Marked from "../general/Marked";
-import { post } from "../../request";
+import { get, post } from "../../request";
 import { IAiTranslateRequest, IAiTranslateResponse } from "../api/ai";
 
 const { Text } = Typography;
 
 interface IAiTranslateWidget {
   origin?: string;
+  paragraph?: string;
+  autoLoad?: boolean;
+  trigger?: boolean;
 }
 
-const AiTranslate = ({ origin }: IAiTranslateWidget) => {
+const AiTranslate = ({
+  origin,
+  paragraph,
+  autoLoad = false,
+  trigger = false,
+}: IAiTranslateWidget) => {
   const [loading, setLoading] = useState(false);
   const [translation, setTranslation] = useState<string>();
   const [error, setError] = useState<string>();
+  const url = "/v2/ai-translate";
+
+  useEffect(() => {
+    if (typeof paragraph === "undefined") {
+      return;
+    }
+    if (!autoLoad) {
+      return;
+    }
+    onTranslatePara();
+  }, [paragraph, autoLoad]);
+
+  const onTranslatePara = () => {
+    const _url = `${url}/${paragraph}`;
+    console.info("api request", _url);
+    setLoading(true);
+    get<IAiTranslateResponse>(_url)
+      .then((json) => {
+        console.debug("api response", json);
+        if (json.ok) {
+          setTranslation(json.data.choices[0].message.content);
+        } else {
+          setError(json.message);
+        }
+      })
+      .finally(() => setLoading(false));
+  };
+
   const onTranslate = (origin?: string) => {
     if (typeof origin === "undefined") {
       return;
     }
-    const url = "/v2/ai-translate";
     const data = { origin: origin };
     console.info("api request", url, data);
     setLoading(true);
@@ -44,17 +79,19 @@ const AiTranslate = ({ origin }: IAiTranslateWidget) => {
     return (
       <div>
         <Text type="danger">{error}</Text>
-        <Button type="link" onClick={() => onTranslate(origin)}>
+        <Button type="link" onClick={() => onTranslatePara()}>
           再试一次
         </Button>
       </div>
     );
-  } else {
+  } else if (trigger) {
     return (
-      <Button type="link" onClick={() => onTranslate(origin)}>
+      <Button type="link" onClick={() => onTranslatePara()}>
         AI 翻译
       </Button>
     );
+  } else {
+    return <></>;
   }
 };
 

+ 4 - 1
dashboard/src/components/fts/FullTextSearchResult.tsx

@@ -238,7 +238,10 @@ const FullTxtSearchResultWidget = ({
                   <Marked className="search_content" text={item.content} />
                 </div>
                 <div>
-                  <AiTranslate origin={item.content} />
+                  <AiTranslate
+                    paragraph={`${item.book}-${item.paragraph}`}
+                    trigger
+                  />
                 </div>
               </div>
             )}

+ 13 - 0
dashboard/src/components/template/ParaHandle.tsx

@@ -13,6 +13,7 @@ interface IWidgetParaHandleCtl {
   mode?: string;
   channels?: string[];
   sentences: string[];
+  onTranslate?: Function;
 }
 export const ParaHandleCtl = ({
   book,
@@ -20,6 +21,7 @@ export const ParaHandleCtl = ({
   mode = "read",
   channels,
   sentences,
+  onTranslate,
 }: IWidgetParaHandleCtl) => {
   const navigate = useNavigate();
   const [searchParams] = useSearchParams();
@@ -38,6 +40,12 @@ export const ParaHandleCtl = ({
         id: "labels.curr.paragraph.open",
       }),
     },
+    {
+      key: "ai-translate",
+      label: intl.formatMessage({
+        id: "buttons.ai.translate",
+      }),
+    },
     {
       type: "divider",
     },
@@ -140,6 +148,11 @@ export const ParaHandleCtl = ({
       case "mode-translate":
         store.dispatch(modeChange({ mode: "edit", id: `${book}-${para}` }));
         break;
+      case "ai-translate":
+        if (typeof onTranslate !== "undefined") {
+          onTranslate();
+        }
+        break;
       case "mode-wbw":
         store.dispatch(modeChange({ mode: "wbw", id: `${book}-${para}` }));
         break;

+ 6 - 0
dashboard/src/components/template/ParaShell.tsx

@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
 import { useAppSelector } from "../../hooks";
 import { currFocus } from "../../reducers/focus";
 import { ParaHandleCtl } from "./ParaHandle";
+import AiTranslate from "../ai/AiTranslate";
 
 interface IWidgetParaShellCtl {
   book: number;
@@ -21,6 +22,7 @@ const ParaShellCtl = ({
 }: IWidgetParaShellCtl) => {
   const focus = useAppSelector(currFocus);
   const [isFocus, setIsFocus] = useState(false);
+  const [aiTranslateParaId, setAiTranslateParaId] = useState<string>();
   useEffect(() => {
     if (focus) {
       if (focus.focus?.type === "para") {
@@ -71,8 +73,12 @@ const ParaShellCtl = ({
           mode={mode}
           channels={channels}
           sentences={sentences}
+          onTranslate={() => setAiTranslateParaId(`${book}-${para}`)}
         />
       </div>
+      <div>
+        <AiTranslate autoLoad paragraph={aiTranslateParaId} />
+      </div>
       {children}
     </div>
   );

+ 1 - 0
dashboard/src/locales/en-US/buttons.ts

@@ -94,6 +94,7 @@ const items = {
   "buttons.set.display.mode": "Display Mode",
   "buttons.manage": "Manage",
   "buttons.delete.wbw.sentence": "Delete Wbw",
+  "buttons.ai.translate": "AI Translate",
 };
 
 export default items;

+ 1 - 0
dashboard/src/locales/zh-Hans/buttons.ts

@@ -94,6 +94,7 @@ const items = {
   "buttons.set.display.mode": "显示模式",
   "buttons.manage": "管理",
   "buttons.delete.wbw.sentence": "删除整句逐词解析",
+  "buttons.ai.translate": "AI 翻译",
 };
 
 export default items;