2
0

RelatedPara.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { Link } from "react-router";
  2. import { Badge, Card, List, message, Modal, Skeleton } from "antd";
  3. import { get } from "../../request";
  4. import { useEffect, useState, type JSX } from "react";
  5. import TocPath, { type ITocPathNode } from "./TocPath";
  6. import store from "../../store";
  7. import { change } from "../../reducers/para-change";
  8. interface ITag {
  9. id?: string;
  10. name: string;
  11. color?: string;
  12. }
  13. interface IRelatedParaData {
  14. book: number;
  15. para: number[];
  16. book_title_pali: string;
  17. book_title?: string;
  18. cs6_para: number;
  19. path?: ITocPathNode[];
  20. tags?: ITag[];
  21. }
  22. interface IRelatedParaResponse {
  23. ok: boolean;
  24. message: string;
  25. data: {
  26. rows: IRelatedParaData[];
  27. count: number;
  28. };
  29. }
  30. interface IWidget {
  31. book?: number;
  32. para?: number;
  33. trigger?: JSX.Element;
  34. }
  35. const RelatedParaWidget = ({ book, para, trigger }: IWidget) => {
  36. const [isModalOpen, setIsModalOpen] = useState(false);
  37. const [tableData, setTableData] = useState<IRelatedParaData[]>([]);
  38. const [load, setLoad] = useState(true);
  39. const showModal = () => {
  40. setIsModalOpen(true);
  41. };
  42. const handleOk = () => {
  43. setIsModalOpen(false);
  44. };
  45. const handleCancel = () => {
  46. setIsModalOpen(false);
  47. };
  48. useEffect(() => {
  49. const fetchRelatedParagraphs = async () => {
  50. if (typeof book === "number" && typeof para === "number" && isModalOpen) {
  51. setLoad(true);
  52. try {
  53. const json = await get<IRelatedParaResponse>(
  54. `/v2/related-paragraph?book=${book}&para=${para}`
  55. );
  56. console.log("import", json);
  57. if (json.ok) {
  58. setTableData(json.data.rows);
  59. } else {
  60. message.error(json.message);
  61. }
  62. } catch (error) {
  63. message.error("请求失败,请稍后重试");
  64. console.error("获取相关段落失败:", error);
  65. } finally {
  66. setLoad(false);
  67. }
  68. }
  69. };
  70. fetchRelatedParagraphs();
  71. }, [book, para, isModalOpen]);
  72. return (
  73. <>
  74. <span onClick={showModal}>{trigger ? trigger : "相关段落"}</span>
  75. <Modal
  76. title="根本和注疏"
  77. open={isModalOpen}
  78. onOk={handleOk}
  79. onCancel={handleCancel}
  80. >
  81. {load ? (
  82. <Skeleton paragraph={{ rows: 4 }} active />
  83. ) : (
  84. <List
  85. itemLayout="vertical"
  86. size="small"
  87. split={false}
  88. dataSource={tableData}
  89. renderItem={(item) => {
  90. const isPali = item.tags?.find((tag) => tag.name === "pāḷi");
  91. const isAttha = item.tags?.find(
  92. (tag) => tag.name === "aṭṭhakathā"
  93. );
  94. const isTika = item.tags?.find((tag) => tag.name === "ṭīkā");
  95. const firstPara = item.para.length > 0 ? item.para[0] : 0;
  96. return (
  97. <List.Item>
  98. <Badge.Ribbon
  99. text={
  100. isPali
  101. ? "pāḷi"
  102. : isAttha
  103. ? "aṭṭhakathā"
  104. : isTika
  105. ? "ṭīkā"
  106. : undefined
  107. }
  108. color={
  109. isPali
  110. ? "volcano"
  111. : isAttha
  112. ? "green"
  113. : isTika
  114. ? "cyan"
  115. : undefined
  116. }
  117. >
  118. <Card
  119. title={
  120. <Link
  121. to={`/article/para/${item.book}-${firstPara}?book=${item.book}&par=${item.para}`}
  122. target="_blank"
  123. >
  124. {item.book_title_pali}
  125. </Link>
  126. }
  127. size="small"
  128. >
  129. <TocPath
  130. data={item.path}
  131. onChange={(node: ITocPathNode) => {
  132. if (node.book && node.paragraph) {
  133. const type = node.level
  134. ? node.level < 8
  135. ? "chapter"
  136. : "para"
  137. : "para";
  138. store.dispatch(
  139. change({
  140. book: node.book,
  141. para: node.paragraph,
  142. type: type,
  143. })
  144. );
  145. }
  146. }}
  147. />
  148. </Card>
  149. </Badge.Ribbon>
  150. </List.Item>
  151. );
  152. }}
  153. />
  154. )}
  155. </Modal>
  156. </>
  157. );
  158. };
  159. export default RelatedParaWidget;