visuddhinanda 1 месяц назад
Родитель
Сommit
7a09e5175a

+ 4 - 40
dashboard-v6/src/api/sentence.ts

@@ -1,9 +1,7 @@
-import type { IntlShape } from "react-intl";
 import type { ArticleMode, TContentType } from "./article";
 
 import { get, put } from "../request";
-import { message } from "antd";
-import { toISentence } from "../components/sentence/utils";
+
 import type { IStudio, IUser } from "./Auth";
 import type { IChannel } from "./channel";
 import type { ISuggestionCount } from "./Suggestion";
@@ -148,11 +146,8 @@ export interface ISentEditData {
 // ─── 原有函数,保持不动,重构完成后再删除 ──────────────────────────────────────
 
 export const sentSave = async (
-  sent: ISentence,
-  intl: IntlShape,
-  ok?: (res: ISentence) => void,
-  finish?: () => void
-): Promise<ISentenceData | null> => {
+  sent: ISentence
+): Promise<ISentenceResponse | null> => {
   //FIXME
   //store.dispatch(statusChange({ status: "loading" }));
   const id = `${sent.book}_${sent.para}_${sent.wordStart}_${sent.wordEnd}_${sent.channel.id}`;
@@ -171,41 +166,10 @@ export const sentSave = async (
       channels: sent.translationChannels?.join(),
       token: sessionStorage.getItem(sent.channel.id),
     });
-    if (res.ok) {
-      if (ok) {
-        console.debug("sent save ok", res.data);
-        const newData: ISentence = toISentence(res.data);
-        ok(newData);
-      }
-      /** 
-       * FIXME 
-      store.dispatch(
-        statusChange({
-          status: "success",
-          message: intl.formatMessage({ id: "flashes.success" }),
-        })
-      );
-      */
-      return res.data;
-    } else {
-      message.error(res.message);
-      /**
-       * FIXME
-             store.dispatch(
-        statusChange({
-          status: "fail",
-          message: res.message,
-        })
-      );
-       */
-
-      return null;
-    }
+    return res;
   } catch (e) {
     console.error("catch", e);
     return null;
-  } finally {
-    finish?.();
   }
 };
 

+ 5 - 5
dashboard-v6/src/components/sentence/SentCell.tsx

@@ -223,11 +223,11 @@ const SentCellWidget = ({
               navigator.clipboard.readText().then((value: string) => {
                 if (sentData && value !== "") {
                   sentData.content = value;
-                  const newSent = sentSave(sentData, intl);
+                  const newSent = sentSave(sentData);
                   newSent.then((value) => {
                     //发布句子的改变,让同样的句子更新
-                    if (value) {
-                      const newData: ISentence = toISentence(value);
+                    if (value?.ok) {
+                      const newData: ISentence = toISentence(value.data);
                       store.dispatch(accept([newData]));
                       if (typeof onChange !== "undefined") {
                         onChange(newData);
@@ -335,7 +335,7 @@ const SentCellWidget = ({
                 newData.contentType = "json";
                 newData.content = JSON.stringify(wbw);
                 setSentData(newData);
-                sentSave(newData, intl);
+                sentSave(newData);
               }
 
               setIsEditMode(true);
@@ -364,7 +364,7 @@ const SentCellWidget = ({
                       .join("\n");
                     newData.content = newContent;
                     newData["contentType"] = "markdown";
-                    sentSave(newData, intl);
+                    sentSave(newData);
                     setSentData(newData);
                   }
                   setIsEditMode(true);

+ 15 - 3
dashboard-v6/src/components/sentence/SentCellEditable.tsx

@@ -16,6 +16,7 @@ import type {
   ISentencePrRequest,
   ISentencePrResponse,
 } from "../../api/sentence-pr";
+import { toISentence } from "./utils";
 
 const { Text } = Typography;
 
@@ -30,6 +31,7 @@ interface IWidget {
 }
 const SentCellEditable = ({
   data,
+  onSave,
   onPrSave,
   onClose,
   onCreate,
@@ -48,14 +50,24 @@ const SentCellEditable = ({
       return;
     }
     setSaving(true);
-    sentSave({ ...data, content: value }, intl)
-      .then((value) => {
-        if (value) {
+    sentSave({ ...data, content: value })
+      .then((json) => {
+        if (json?.ok) {
           message.success(intl.formatMessage({ id: "flashes.success" }));
+          if (typeof onSave !== "undefined") {
+            const newData: ISentence = toISentence(json.data);
+            onSave(newData);
+          }
+        } else {
+          message.error(json?.message);
         }
       })
       .finally(() => {
         setSaving(false);
+      })
+      .catch((e) => {
+        console.error("catch", e);
+        message.error(e.message);
       });
   };
 

+ 12 - 5
dashboard-v6/src/components/sentence/SentEdit.tsx

@@ -62,6 +62,7 @@ export interface IWidgetSentEditInner {
   wbwScore?: number;
 
   onTranslationChange?: (data: ISentence) => void;
+  onModeChange?: (mode: ArticleMode) => void;
 }
 
 export const SentEditInner = ({
@@ -86,6 +87,7 @@ export const SentEditInner = ({
   readonly = false,
   commentaries,
   onTranslationChange,
+  onModeChange,
 }: IWidgetSentEditInner) => {
   const [wbwData, setWbwData] = useState<IWbw[]>();
   const [magicDict, setMagicDict] = useState<string>();
@@ -99,6 +101,8 @@ export const SentEditInner = ({
   const divRef = useRef<HTMLDivElement>(null);
   const rootFixed = useSetting("setting.layout.root.fixed");
 
+  const currMode = mode ?? articleMode;
+
   // ✅ 从 settings 派生 commentaryLayout,无需 state + effect
   const commentaryLayout = useMemo<string>(() => {
     const layoutCommentary = GetUserSetting(
@@ -167,7 +171,7 @@ export const SentEditInner = ({
       layout={layout}
       magicDict={magicDict}
       compact={isCompact}
-      mode={articleMode}
+      mode={currMode}
       wbwProgress={showWbwProgress}
       readonly={readonly}
       onWbwChange={(data: IWbw[]) => {
@@ -221,15 +225,18 @@ export const SentEditInner = ({
             origin={origin}
             magicDictLoading={magicDictLoading}
             compact={isCompact}
-            mode={articleMode}
+            mode={currMode}
             onMagicDict={(type: string) => {
               setMagicDict(type);
               setMagicDictLoading(true);
             }}
             onCompact={(value: boolean) => setIsCompact(value)}
-            onModeChange={(value: ArticleMode | undefined) =>
-              setArticleMode(value)
-            }
+            onModeChange={(value: ArticleMode | undefined) => {
+              if (value) {
+                setArticleMode(value);
+                onModeChange?.(value);
+              }
+            }}
             onAffix={() => setAffix(!affix)}
           />
         </div>

+ 2 - 2
dashboard-v6/src/components/sentence/SentWbwEdit.tsx

@@ -50,10 +50,10 @@ const SentWbwEditWidget = ({ data, onSave, onClose }: IWidget) => {
         onChange={(wbwData: IWbw[]) => {
           const newSent = { ...data };
           newSent.content = JSON.stringify(wbwData);
-          sentSave(newSent, intl)
+          sentSave(newSent)
             .then((value) => {
               if (value) {
-                newSent.html = value.html;
+                newSent.html = value.data.html;
                 onSave?.(newSent);
               } else {
                 console.error("返回数据失败");

+ 3 - 115
dashboard-v6/src/components/template/Paragraph.tsx

@@ -1,117 +1,5 @@
-import { useMemo } from "react";
-import { EditOutlined, EyeOutlined } from "@ant-design/icons";
-
-import { useAppSelector } from "../../hooks";
-import { currFocus } from "../../reducers/focus";
-import { ParaHandleCtl } from "./ParaHandle";
-import { SentEditInner } from "../sentence/SentEdit";
-import { Button } from "antd";
-import type { ArticleMode } from "../../api/article";
-import ParagraphRead from "../tipitaka/components/ParagraphRead";
-import type { IParagraphNode } from "../../api/pali-text";
-
-interface IParagraphProps extends IParagraphNode {
-  loading?: boolean;
-  onModeChange?: (mode: ArticleMode) => void;
-}
-
-export const ParagraphCtl = ({
-  book,
-  para,
-  mode,
-  channels,
-  sentenceIds,
-  children,
-  loading,
-  onModeChange,
-}: IParagraphProps) => {
-  const focus = useAppSelector(currFocus);
-  console.debug("para children", book, para, children?.length);
-  console.debug("para children", children);
-
-  const isFocus = useMemo(() => {
-    if (focus) {
-      if (focus.focus?.type === "para") {
-        if (focus.focus.id) {
-          const arrId = focus.focus.id.split("-");
-          if (arrId.length > 1) {
-            const focusBook = parseInt(arrId[0]);
-            const focusPara = arrId[1].split(",").map((item) => parseInt(item));
-            if (focusBook === book && focusPara.includes(para)) {
-              return true;
-            }
-          }
-        } else {
-          return false;
-        }
-      }
-    } else {
-      return false;
-    }
-  }, [book, focus, para]);
-
-  const borderColor = isFocus ? "#e35f00bd " : "rgba(128, 128, 128, 0.3)";
-
-  const border = mode === "read" ? "" : "2px solid " + borderColor;
-
-  return (
-    <div
-      style={{
-        border: border,
-        borderRadius: 6,
-        marginTop: 20,
-        marginBottom: 28,
-        padding: 4,
-      }}
-    >
-      <div
-        style={{
-          display: "flex",
-          justifyContent: "space-between",
-        }}
-      >
-        <ParaHandleCtl
-          book={book}
-          para={para}
-          mode={mode}
-          channels={channels}
-          sentences={sentenceIds}
-        />
-        <div>
-          {mode === "edit" && (
-            <Button
-              loading={loading}
-              type="link"
-              icon={<EyeOutlined />}
-              onClick={() => {
-                if (onModeChange) {
-                  onModeChange("read");
-                }
-              }}
-            />
-          )}
-          {mode === "read" && (
-            <Button
-              loading={loading}
-              type="link"
-              icon={<EditOutlined />}
-              onClick={() => {
-                if (onModeChange) {
-                  onModeChange("edit");
-                }
-              }}
-            />
-          )}
-        </div>
-      </div>
-      <div>
-        {mode === "edit" &&
-          children?.map((item) => <SentEditInner {...item} />)}
-        {mode === "read" && <ParagraphRead data={children} />}
-      </div>
-    </div>
-  );
-};
+import type { IParagraphProps } from "../tipitaka/components/Paragraph";
+import Paragraph from "../tipitaka/components/Paragraph";
 
 interface IWidget {
   props: string;
@@ -121,7 +9,7 @@ const Widget = ({ props }: IWidget) => {
   const prop = JSON.parse(atob(props)) as IParagraphProps;
   return (
     <>
-      <ParagraphCtl {...prop} />
+      <Paragraph {...prop} />
     </>
   );
 };

+ 2 - 2
dashboard-v6/src/components/tipitaka/ParagraphNode.tsx

@@ -1,6 +1,6 @@
 import { useState } from "react";
 import { fetchParaNodeChunk, type IParagraphNode } from "../../api/pali-text";
-import { ParagraphCtl } from "../template/Paragraph";
+import Paragraph from "./components/Paragraph";
 
 interface IWidget {
   initData: IParagraphNode;
@@ -12,7 +12,7 @@ const ParagraphNode = ({ initData }: IWidget) => {
   return (
     <>
       {currData && (
-        <ParagraphCtl
+        <Paragraph
           loading={loading}
           {...currData}
           onModeChange={async (mode) => {

+ 129 - 0
dashboard-v6/src/components/tipitaka/components/Paragraph.tsx

@@ -0,0 +1,129 @@
+import { useMemo, useState } from "react";
+import { EditOutlined, EyeOutlined } from "@ant-design/icons";
+
+import type { ArticleMode } from "../../../api/article";
+import type { IParagraphNode } from "../../../api/pali-text";
+import { useAppSelector } from "../../../hooks";
+import { currFocus } from "../../../reducers/focus";
+import { ParaHandleCtl } from "../../template/ParaHandle";
+import { Button, Space, Switch, Typography } from "antd";
+import { SentEditInner } from "../../sentence/SentEdit";
+import ParagraphRead from "./ParagraphRead";
+
+const { Text } = Typography;
+
+export interface IParagraphProps extends IParagraphNode {
+  loading?: boolean;
+  onModeChange?: (mode: ArticleMode) => void;
+}
+
+const Paragraph = ({
+  book,
+  para,
+  mode,
+  channels,
+  sentenceIds,
+  children,
+  loading,
+  onModeChange,
+}: IParagraphProps) => {
+  const [wbw, setWbw] = useState(false);
+  const focus = useAppSelector(currFocus);
+  console.debug("para children", book, para, children?.length);
+  console.debug("para children", children);
+
+  const isFocus = useMemo(() => {
+    if (focus) {
+      if (focus.focus?.type === "para") {
+        if (focus.focus.id) {
+          const arrId = focus.focus.id.split("-");
+          if (arrId.length > 1) {
+            const focusBook = parseInt(arrId[0]);
+            const focusPara = arrId[1].split(",").map((item) => parseInt(item));
+            if (focusBook === book && focusPara.includes(para)) {
+              return true;
+            }
+          }
+        } else {
+          return false;
+        }
+      }
+    } else {
+      return false;
+    }
+  }, [book, focus, para]);
+
+  const borderColor = isFocus ? "#e35f00bd " : "rgba(128, 128, 128, 0.3)";
+
+  const border = mode === "read" ? "" : "2px solid " + borderColor;
+
+  const onWbw = (checked: boolean) => {
+    setWbw(checked);
+  };
+
+  return (
+    <div
+      style={{
+        border: border,
+        borderRadius: 6,
+        marginTop: 20,
+        marginBottom: 28,
+        padding: 4,
+      }}
+    >
+      <div
+        style={{
+          display: "flex",
+          justifyContent: "space-between",
+        }}
+      >
+        <ParaHandleCtl
+          book={book}
+          para={para}
+          mode={mode}
+          channels={channels}
+          sentences={sentenceIds}
+        />
+        <div>
+          {mode === "edit" && (
+            <Space>
+              <Text>wbw</Text>
+              <Switch onChange={onWbw} size="small" />
+              <Button
+                loading={loading}
+                type="link"
+                icon={<EyeOutlined />}
+                onClick={() => {
+                  if (onModeChange) {
+                    onModeChange("read");
+                  }
+                }}
+              />
+            </Space>
+          )}
+          {mode === "read" && (
+            <Button
+              loading={loading}
+              type="link"
+              icon={<EditOutlined />}
+              onClick={() => {
+                if (onModeChange) {
+                  onModeChange("edit");
+                }
+              }}
+            />
+          )}
+        </div>
+      </div>
+      <div>
+        {mode === "edit" &&
+          children?.map((item) => (
+            <SentEditInner {...item} mode={wbw ? "wbw" : "edit"} />
+          ))}
+        {mode === "read" && <ParagraphRead data={children} />}
+      </div>
+    </div>
+  );
+};
+
+export default Paragraph;

+ 2 - 2
dashboard-v6/src/components/tipitaka/components/ParagraphReadSent.tsx

@@ -8,7 +8,7 @@ import CommentaryPad from "./CommentaryPad";
 interface IWidget {
   data?: IWidgetSentEditInner[];
 }
-const ParagraphRead = ({ data }: IWidget) => {
+const ParagraphReadSent = ({ data }: IWidget) => {
   const direction = useSetting("setting.layout.direction");
   const layoutCommentary = useSetting("setting.layout.commentary");
   console.debug("direction", direction);
@@ -69,4 +69,4 @@ const ParagraphRead = ({ data }: IWidget) => {
   );
 };
 
-export default ParagraphRead;
+export default ParagraphReadSent;