Article.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import { IArticleDataResponse } from "../api/Article";
  2. import TypeArticle from "./TypeArticle";
  3. import TypeAnthology from "./TypeAnthology";
  4. import TypeTerm from "./TypeTerm";
  5. import TypePali from "./TypePali";
  6. import "./article.css";
  7. import TypePage from "./TypePage";
  8. import TypeCSPara from "./TypeCSPara";
  9. import { ISearchParams } from "../../pages/library/article/show";
  10. import TypeCourse from "./TypeCourse";
  11. import { useEffect, useState } from "react";
  12. import { fullUrl } from "../../utils";
  13. export type ArticleMode = "read" | "edit" | "wbw";
  14. export type ArticleType =
  15. | "anthology"
  16. | "article"
  17. | "series"
  18. | "chapter"
  19. | "para"
  20. | "cs-para"
  21. | "sent"
  22. | "sim"
  23. | "page"
  24. | "textbook"
  25. | "exercise"
  26. | "exercise-list"
  27. | "sent-original"
  28. | "sent-commentary"
  29. | "sent-nissaya"
  30. | "sent-translation"
  31. | "term";
  32. /**
  33. * 每种article type 对应的路由参数
  34. * article/id?anthology=id&channel=id1,id2&mode=ArticleMode
  35. * chapter/book-para?channel=id1,id2&mode=ArticleMode
  36. * para/book?par=para1,para2&channel=id1,id2&mode=ArticleMode
  37. * cs-para/book-para?channel=id1,id2&mode=ArticleMode
  38. * sent/id?channel=id1,id2&mode=ArticleMode
  39. * sim/id?channel=id1,id2&mode=ArticleMode
  40. * textbook/articleId?course=id&mode=ArticleMode
  41. * exercise/articleId?course=id&exercise=id&username=name&mode=ArticleMode
  42. * exercise-list/articleId?course=id&exercise=id&mode=ArticleMode
  43. * sent-original/id
  44. */
  45. interface IWidget {
  46. type?: ArticleType;
  47. articleId?: string;
  48. mode?: ArticleMode | null;
  49. channelId?: string | null;
  50. book?: string | null;
  51. para?: string | null;
  52. anthologyId?: string | null;
  53. courseId?: string | null;
  54. exerciseId?: string;
  55. userName?: string;
  56. active?: boolean;
  57. focus?: string | null;
  58. onArticleChange?: Function;
  59. onFinal?: Function;
  60. onLoad?: Function;
  61. onAnthologySelect?: Function;
  62. onTitle?: Function;
  63. onArticleEdit?: Function;
  64. }
  65. const ArticleWidget = ({
  66. type,
  67. book,
  68. para,
  69. channelId,
  70. articleId,
  71. anthologyId,
  72. courseId,
  73. exerciseId,
  74. userName,
  75. mode = "read",
  76. active = false,
  77. focus,
  78. onArticleChange,
  79. onFinal,
  80. onLoad,
  81. onAnthologySelect,
  82. onTitle,
  83. onArticleEdit,
  84. }: IWidget) => {
  85. const [currId, setCurrId] = useState(articleId);
  86. useEffect(() => setCurrId(articleId), [articleId]);
  87. return (
  88. <div>
  89. {type === "article" ? (
  90. <TypeArticle
  91. type={type}
  92. articleId={onArticleChange ? articleId : currId}
  93. channelId={channelId}
  94. mode={mode}
  95. anthologyId={anthologyId}
  96. active={active}
  97. onArticleEdit={(value: IArticleDataResponse) => {
  98. if (typeof onArticleEdit !== "undefined") {
  99. onArticleEdit(value);
  100. }
  101. }}
  102. onArticleChange={(type: ArticleType, id: string, target: string) => {
  103. if (typeof onArticleChange !== "undefined") {
  104. onArticleChange(type, id, target);
  105. }
  106. }}
  107. onLoad={(data: IArticleDataResponse) => {
  108. if (typeof onLoad !== "undefined") {
  109. onLoad(data);
  110. }
  111. if (typeof onTitle !== "undefined") {
  112. onTitle(data.title);
  113. }
  114. }}
  115. onAnthologySelect={(id: string) => {
  116. if (typeof onAnthologySelect !== "undefined") {
  117. onAnthologySelect(id);
  118. }
  119. }}
  120. />
  121. ) : type === "anthology" ? (
  122. <TypeAnthology
  123. type={type}
  124. articleId={onArticleChange ? articleId : currId}
  125. channelId={channelId}
  126. mode={mode}
  127. onArticleChange={(type: ArticleType, id: string, target: string) => {
  128. if (typeof onArticleChange !== "undefined") {
  129. onArticleChange(type, id, target);
  130. }
  131. }}
  132. onTitle={(value: string) => {
  133. if (typeof onTitle !== "undefined") {
  134. onTitle(value);
  135. }
  136. }}
  137. />
  138. ) : type === "term" ? (
  139. <TypeTerm
  140. articleId={onArticleChange ? articleId : currId}
  141. channelId={channelId}
  142. mode={mode}
  143. onArticleChange={(type: ArticleType, id: string, target: string) => {
  144. if (typeof onArticleChange !== "undefined") {
  145. onArticleChange(type, id, target);
  146. }
  147. }}
  148. />
  149. ) : type === "chapter" || type === "para" ? (
  150. <TypePali
  151. type={type}
  152. articleId={onArticleChange ? articleId : currId}
  153. channelId={channelId}
  154. mode={mode}
  155. book={book}
  156. para={para}
  157. focus={focus}
  158. onArticleChange={(
  159. type: ArticleType,
  160. id: string,
  161. target: string,
  162. param: ISearchParams[]
  163. ) => {
  164. if (typeof onArticleChange !== "undefined") {
  165. onArticleChange(type, id, target, param);
  166. }
  167. }}
  168. onLoad={(data: IArticleDataResponse) => {
  169. if (typeof onLoad !== "undefined") {
  170. onLoad(data);
  171. }
  172. }}
  173. onTitle={(value: string) => {
  174. if (typeof onTitle !== "undefined") {
  175. onTitle(value);
  176. }
  177. }}
  178. />
  179. ) : type === "page" ? (
  180. <TypePage
  181. articleId={onArticleChange ? articleId : currId}
  182. channelId={channelId}
  183. focus={focus}
  184. mode={mode}
  185. onArticleChange={(type: ArticleType, id: string, target: string) => {
  186. if (typeof onArticleChange !== "undefined") {
  187. onArticleChange(type, id, target);
  188. } else {
  189. if (target === "_blank") {
  190. let url = `/article/page/${id}?mode=${mode}`;
  191. if (channelId) {
  192. url += `&channel=${channelId}`;
  193. }
  194. window.open(fullUrl(url), "_blank");
  195. } else {
  196. setCurrId(id);
  197. }
  198. }
  199. }}
  200. />
  201. ) : type === "cs-para" ? (
  202. <TypeCSPara
  203. articleId={onArticleChange ? articleId : currId}
  204. channelId={channelId}
  205. mode={mode}
  206. onArticleChange={(type: ArticleType, id: string, target: string) => {
  207. if (typeof onArticleChange !== "undefined") {
  208. onArticleChange(type, id, target);
  209. }
  210. }}
  211. />
  212. ) : type === "textbook" ? (
  213. <TypeCourse
  214. type={type}
  215. articleId={onArticleChange ? articleId : currId}
  216. channelId={channelId}
  217. courseId={courseId}
  218. mode={mode}
  219. onArticleChange={(
  220. newType: ArticleType,
  221. id: string,
  222. target: string
  223. ) => {
  224. if (typeof onArticleChange !== "undefined") {
  225. onArticleChange(type, id, target);
  226. }
  227. }}
  228. />
  229. ) : (
  230. <></>
  231. )}
  232. </div>
  233. );
  234. };
  235. export default ArticleWidget;