SentCanRead.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { Button, message } from "antd";
  2. import { useCallback, useEffect, useState } from "react";
  3. import { ReloadOutlined } from "@ant-design/icons";
  4. import { get } from "../../request";
  5. import type { IChannel, TChannelType } from "../../api/channel";
  6. import type { ISentence, ISentenceListResponse } from "../../api/sentence";
  7. import SentCell from "./SentCell";
  8. import SentAdd from "./SentAdd";
  9. import { useAppSelector } from "../../hooks";
  10. import { currentUser as _currentUser } from "../../reducers/current-user";
  11. import { toISentence } from "../sentence/utils";
  12. import type { IWbw } from "../../types/wbw";
  13. interface IWidget {
  14. book: number;
  15. para: number;
  16. wordStart: number;
  17. wordEnd: number;
  18. type: TChannelType;
  19. channelsId?: string[];
  20. origin?: ISentence[];
  21. onReload?: () => void;
  22. onCreate?: () => void;
  23. }
  24. const SentCanReadWidget = ({
  25. book,
  26. para,
  27. wordStart,
  28. wordEnd,
  29. type,
  30. channelsId,
  31. origin,
  32. onReload,
  33. onCreate,
  34. }: IWidget) => {
  35. const [sentData, setSentData] = useState<ISentence[]>([]);
  36. const [channels, setChannels] = useState<string[]>();
  37. const user = useAppSelector(_currentUser);
  38. const load = useCallback(() => {
  39. const sentId = `${book}-${para}-${wordStart}-${wordEnd}`;
  40. let url = `/api/v2/sentence?view=sent-can-read&sentence=${sentId}&type=${type}&mode=edit&html=true`;
  41. url += channelsId ? `&excludes=${channelsId.join()}` : "";
  42. if (type === "commentary" || type === "similar") {
  43. url += channelsId ? `&channels=${channelsId.join()}` : "";
  44. }
  45. console.info("ai request", url);
  46. get<ISentenceListResponse>(url)
  47. .then((json) => {
  48. if (json.ok) {
  49. const channels: string[] = json.data.rows.map(
  50. (item) => item.channel.id
  51. );
  52. setChannels(channels);
  53. const newData: ISentence[] = json.data.rows.map((item) =>
  54. toISentence(item, channelsId)
  55. );
  56. setSentData(newData);
  57. } else {
  58. message.error(json.message);
  59. }
  60. })
  61. .finally(() => {
  62. onReload?.();
  63. });
  64. }, [book, para, wordStart, wordEnd, type, channelsId, onReload]);
  65. useEffect(() => {
  66. load();
  67. }, [load]);
  68. return (
  69. <div>
  70. <div style={{ display: "flex", justifyContent: "space-between" }}>
  71. <span></span>
  72. <Button
  73. type="link"
  74. shape="round"
  75. icon={<ReloadOutlined />}
  76. onClick={() => load()}
  77. />
  78. </div>
  79. <div style={{ textAlign: "center" }}>
  80. <SentAdd
  81. disableChannels={channels}
  82. type={type}
  83. onSelect={(channel: IChannel) => {
  84. if (typeof user === "undefined") {
  85. return;
  86. }
  87. const newSent: ISentence = {
  88. content: "",
  89. contentType: "markdown",
  90. html: "",
  91. book: book,
  92. para: para,
  93. wordStart: wordStart,
  94. wordEnd: wordEnd,
  95. editor: {
  96. id: user.id,
  97. nickName: user.nickName,
  98. userName: user.realName,
  99. },
  100. channel: channel,
  101. translationChannels: channelsId,
  102. updateAt: "",
  103. openInEditMode: true,
  104. };
  105. setSentData((origin) => {
  106. return [newSent, ...origin];
  107. });
  108. setChannels((origin) => {
  109. if (origin) {
  110. if (!origin.includes(newSent.channel.id)) {
  111. origin.push(newSent.channel.id);
  112. return origin;
  113. }
  114. } else {
  115. return [newSent.channel.id];
  116. }
  117. });
  118. if (typeof onCreate !== "undefined") {
  119. onCreate();
  120. }
  121. }}
  122. />
  123. </div>
  124. {sentData.map((item, id) => {
  125. let diffText: string | null = null;
  126. if (origin) {
  127. diffText = origin[0].html;
  128. if (origin[0].contentType === "json" && origin[0].content) {
  129. const wbw = JSON.parse(origin[0].content) as IWbw[];
  130. console.debug("wbw data", wbw);
  131. diffText = wbw
  132. .filter((value) => {
  133. if (value.style && value.style.value === "note") {
  134. return false;
  135. } else if (value.type && value.type.value === ".ctl.") {
  136. return false;
  137. } else {
  138. return true;
  139. }
  140. })
  141. .map(
  142. (item) =>
  143. `${item.word.value
  144. .replaceAll("{", "**")
  145. .replaceAll("}", "**")}`
  146. )
  147. .join(" ");
  148. }
  149. console.debug("origin", origin);
  150. }
  151. return (
  152. <SentCell
  153. value={item}
  154. key={id}
  155. isPr={false}
  156. diffText={diffText}
  157. showDiff={origin ? true : false}
  158. editMode={item.openInEditMode}
  159. onChange={(value: ISentence) => {
  160. console.debug("onChange", value);
  161. setSentData((origin) => {
  162. origin.forEach((value1, index, array) => {
  163. if (value1.id === value.id) {
  164. array[index] = value;
  165. }
  166. });
  167. return origin;
  168. });
  169. }}
  170. />
  171. );
  172. })}
  173. </div>
  174. );
  175. };
  176. export default SentCanReadWidget;