Article.tsx 7.4 KB

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