visuddhinanda 3 лет назад
Родитель
Сommit
7eac2af9de

+ 29 - 0
dashboard/src/components/api/Suggestion.ts

@@ -0,0 +1,29 @@
+import { IUserApiResponse } from "./Auth";
+import { IChannelApiData } from "./Channel";
+
+export interface ISuggestionData {
+  id: number;
+  book: number;
+  paragraph: number;
+  word_start: number;
+  word_end: number;
+  channel: IChannelApiData;
+  content: string;
+  html: string;
+  editor: IUserApiResponse;
+  created_at: string;
+  updated_at: string;
+}
+export interface ISuggestionResponse {
+  ok: boolean;
+  message: string;
+  data: ISuggestionData;
+}
+export interface ISuggestionListResponse {
+  ok: boolean;
+  message: string;
+  data: {
+    rows: ISuggestionData[];
+    count: number;
+  };
+}

+ 7 - 0
dashboard/src/components/template/SentEdit.tsx

@@ -5,7 +5,12 @@ import { IChannel } from "../channel/Channel";
 import SentContent from "./SentEdit/SentContent";
 import SentContent from "./SentEdit/SentContent";
 import SentMenu from "./SentEdit/SentMenu";
 import SentMenu from "./SentEdit/SentMenu";
 import SentTab from "./SentEdit/SentTab";
 import SentTab from "./SentEdit/SentTab";
+import { suggestion } from "../../reducers/suggestion";
 
 
+interface ISuggestiongCount {
+  suggestion?: number;
+  qa?: number;
+}
 export interface ISentence {
 export interface ISentence {
   content: string;
   content: string;
   html: string;
   html: string;
@@ -16,6 +21,7 @@ export interface ISentence {
   editor: IUser;
   editor: IUser;
   channel: IChannel;
   channel: IChannel;
   updateAt: string;
   updateAt: string;
+  suggestionCount?: ISuggestiongCount;
 }
 }
 
 
 export interface IWidgetSentEditInner {
 export interface IWidgetSentEditInner {
@@ -67,6 +73,7 @@ interface IWidgetSentEdit {
 }
 }
 const Widget = ({ props }: IWidgetSentEdit) => {
 const Widget = ({ props }: IWidgetSentEdit) => {
   const prop = JSON.parse(atob(props)) as IWidgetSentEditInner;
   const prop = JSON.parse(atob(props)) as IWidgetSentEditInner;
+  console.log("sent data", prop);
   return <SentEditInner {...prop} />;
   return <SentEditInner {...prop} />;
 };
 };
 
 

+ 46 - 0
dashboard/src/components/template/SentEdit/SuggestionAdd.tsx

@@ -0,0 +1,46 @@
+import { Button } from "antd";
+import { useState } from "react";
+import { Typography } from "antd";
+import { PlusOutlined } from "@ant-design/icons";
+
+import { ISentence } from "../SentEdit";
+import SentEditMenu from "./SentEditMenu";
+import SentCellEditable from "./SentCellEditable";
+
+interface ISentCell {
+  data: ISentence;
+}
+const Widget = ({ data }: ISentCell) => {
+  const [isEditMode, setIsEditMode] = useState(false);
+  const [sentData, setSentData] = useState<ISentence>(data);
+
+  return (
+    <>
+      <div style={{ display: isEditMode ? "none" : "block" }}>
+        <Button
+          type="dashed"
+          style={{ width: 300 }}
+          icon={<PlusOutlined />}
+          onClick={() => {
+            setIsEditMode(true);
+          }}
+        >
+          添加修改建议
+        </Button>
+      </div>
+      <div style={{ display: isEditMode ? "block" : "none" }}>
+        <SentCellEditable
+          data={sentData}
+          onClose={() => {
+            setIsEditMode(false);
+          }}
+          onDataChange={(data: ISentence) => {
+            setSentData(data);
+          }}
+        />
+      </div>
+    </>
+  );
+};
+
+export default Widget;

+ 51 - 0
dashboard/src/components/template/SentEdit/SuggestionList.tsx

@@ -0,0 +1,51 @@
+import { useEffect, useState } from "react";
+import { get } from "../../../request";
+import { ISuggestionListResponse } from "../../api/Suggestion";
+import { IChannel } from "../../channel/Channel";
+import { ISentence } from "../SentEdit";
+import SentCell from "./SentCell";
+interface IWidget {
+  book: number;
+  para: number;
+  wordStart: number;
+  wordEnd: number;
+  channel: IChannel;
+}
+const Widget = ({ book, para, wordStart, wordEnd, channel }: IWidget) => {
+  const [sentData, setSentData] = useState<ISentence[]>([]);
+
+  useEffect(() => {
+    get<ISuggestionListResponse>(
+      `/v2/sentpr?view=sent-info&book=${book}&para=${para}&start=${wordStart}&end=${wordEnd}&channel=${channel.id}`
+    ).then((json) => {
+      const newData: ISentence[] = json.data.rows.map((item) => {
+        return {
+          content: item.content,
+          html: item.html,
+          book: item.book,
+          para: item.paragraph,
+          wordStart: item.word_start,
+          wordEnd: item.word_end,
+          editor: {
+            id: item.editor.id,
+            nickName: item.editor.nickName,
+            realName: item.editor.userName,
+            avatar: item.editor.avatar,
+          },
+          channel: { name: item.channel.name, id: item.channel.id },
+          updateAt: item.updated_at,
+        };
+      });
+      setSentData(newData);
+    });
+  }, [book, para, wordStart, wordEnd, channel]);
+  return (
+    <div>
+      {sentData.map((item, id) => {
+        return <SentCell data={item} key={id} />;
+      })}
+    </div>
+  );
+};
+
+export default Widget;

+ 77 - 0
dashboard/src/components/template/SentEdit/SuggestionTabs.tsx

@@ -0,0 +1,77 @@
+import { useState } from "react";
+import { RadioChangeEvent, Space } from "antd";
+import { Radio } from "antd";
+import { ISentence } from "../SentEdit";
+import { SuggestionIcon } from "../../../assets/icon";
+import SuggestionAdd from "./SuggestionAdd";
+import SuggestionList from "./SuggestionList";
+
+interface IWidget {
+  data: ISentence;
+}
+const Widget = ({ data }: IWidget) => {
+  const [value, setValue] = useState("close");
+  const [showPanel, setShowPanel] = useState("none");
+  const [showSuggestion, setShowSuggestion] = useState("none");
+
+  const onChange = ({ target: { value } }: RadioChangeEvent) => {
+    console.log("radio1 checked", value);
+    switch (value) {
+      case "suggestion":
+        setShowSuggestion("block");
+        setShowPanel("block");
+        break;
+    }
+    setValue(value);
+  };
+  const closeAll = () => {
+    setShowPanel("none");
+  };
+
+  return (
+    <div>
+      <div>
+        <Radio.Group
+          size="small"
+          optionType="button"
+          buttonStyle="solid"
+          onChange={onChange}
+          value={value}
+        >
+          <Radio
+            value="suggestion"
+            onClick={() => {
+              if (value === "suggestion") {
+                setValue("close");
+                closeAll();
+              }
+            }}
+            style={{
+              border: "none",
+              backgroundColor: "wheat",
+              borderRadius: 5,
+            }}
+          >
+            <Space>
+              <SuggestionIcon />
+              {data.suggestionCount?.suggestion}
+            </Space>
+          </Radio>
+          <Radio value="close" style={{ display: "none" }}></Radio>
+        </Radio.Group>
+      </div>
+      <div style={{ display: showPanel }}>
+        <div style={{ display: showSuggestion, paddingLeft: "1em" }}>
+          <div>
+            <SuggestionAdd data={data} />
+          </div>
+          <div>
+            <SuggestionList {...data} />
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default Widget;

+ 72 - 0
dashboard/src/reducers/suggestion.ts

@@ -0,0 +1,72 @@
+/**
+ * 对资源的评论等信息
+ * 包括
+ * 1.修改建议
+ * 2.问答
+ * 3.评论
+ */
+import { createSlice, PayloadAction } from "@reduxjs/toolkit";
+
+import type { RootState } from "../store";
+
+export interface ISuggestionItem {
+  id: string;
+  type: "sent" | "lesson" | "article";
+  count: number;
+  text: string[];
+}
+
+interface IState {
+  suggestions?: ISuggestionItem[];
+  current?: ISuggestionItem;
+}
+
+const initialState: IState = {};
+
+const KEY = "suggestion";
+
+const set = (settings: ISuggestionItem[]) => {
+  sessionStorage.setItem(KEY, JSON.stringify(settings));
+};
+
+export const slice = createSlice({
+  name: "suggestion",
+  initialState,
+  reducers: {
+    refresh: (state, action: PayloadAction<ISuggestionItem[]>) => {
+      state.suggestions = action.payload;
+    },
+    onChange: (state, action: PayloadAction<ISuggestionItem>) => {
+      state.current = action.payload;
+      //将新的改变放入 store
+      if (typeof state.suggestions !== "undefined") {
+        const index = state.suggestions.findIndex(
+          (element) => element.id === action.payload.id
+        );
+        if (index >= 0) {
+          //找到旧的记录-更新
+          state.suggestions[index] = action.payload;
+        } else {
+          //没找到-新建
+          state.suggestions.push(action.payload);
+        }
+      } else {
+        state.suggestions = [action.payload];
+      }
+      set(state.suggestions);
+    },
+  },
+});
+
+export const { refresh, onChange } = slice.actions;
+
+export const suggestion = (state: RootState): IState => state.suggestion;
+
+export const allSuggestion = (
+  state: RootState
+): ISuggestionItem[] | undefined => state.suggestion.suggestions;
+
+export const current = (state: RootState): ISuggestionItem | undefined =>
+  state.suggestion.current;
+
+export default slice.reducer;