| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- import { Link } from "react-router";
- import { Badge, Card, List, message, Modal, Skeleton } from "antd";
- import { get } from "../../request";
- import { useEffect, useState, type JSX } from "react";
- import TocPath, { type ITocPathNode } from "./TocPath";
- import store from "../../store";
- import { change } from "../../reducers/para-change";
- interface ITag {
- id?: string;
- name: string;
- color?: string;
- }
- interface IRelatedParaData {
- book: number;
- para: number[];
- book_title_pali: string;
- book_title?: string;
- cs6_para: number;
- path?: ITocPathNode[];
- tags?: ITag[];
- }
- interface IRelatedParaResponse {
- ok: boolean;
- message: string;
- data: {
- rows: IRelatedParaData[];
- count: number;
- };
- }
- interface IWidget {
- book?: number;
- para?: number;
- trigger?: JSX.Element;
- }
- const RelatedParaWidget = ({ book, para, trigger }: IWidget) => {
- const [isModalOpen, setIsModalOpen] = useState(false);
- const [tableData, setTableData] = useState<IRelatedParaData[]>([]);
- const [load, setLoad] = useState(true);
- const showModal = () => {
- setIsModalOpen(true);
- };
- const handleOk = () => {
- setIsModalOpen(false);
- };
- const handleCancel = () => {
- setIsModalOpen(false);
- };
- useEffect(() => {
- const fetchRelatedParagraphs = async () => {
- if (typeof book === "number" && typeof para === "number" && isModalOpen) {
- setLoad(true);
- try {
- const json = await get<IRelatedParaResponse>(
- `/v2/related-paragraph?book=${book}¶=${para}`
- );
- console.log("import", json);
- if (json.ok) {
- setTableData(json.data.rows);
- } else {
- message.error(json.message);
- }
- } catch (error) {
- message.error("请求失败,请稍后重试");
- console.error("获取相关段落失败:", error);
- } finally {
- setLoad(false);
- }
- }
- };
- fetchRelatedParagraphs();
- }, [book, para, isModalOpen]);
- return (
- <>
- <span onClick={showModal}>{trigger ? trigger : "相关段落"}</span>
- <Modal
- title="根本和注疏"
- open={isModalOpen}
- onOk={handleOk}
- onCancel={handleCancel}
- >
- {load ? (
- <Skeleton paragraph={{ rows: 4 }} active />
- ) : (
- <List
- itemLayout="vertical"
- size="small"
- split={false}
- dataSource={tableData}
- renderItem={(item) => {
- const isPali = item.tags?.find((tag) => tag.name === "pāḷi");
- const isAttha = item.tags?.find(
- (tag) => tag.name === "aṭṭhakathā"
- );
- const isTika = item.tags?.find((tag) => tag.name === "ṭīkā");
- const firstPara = item.para.length > 0 ? item.para[0] : 0;
- return (
- <List.Item>
- <Badge.Ribbon
- text={
- isPali
- ? "pāḷi"
- : isAttha
- ? "aṭṭhakathā"
- : isTika
- ? "ṭīkā"
- : undefined
- }
- color={
- isPali
- ? "volcano"
- : isAttha
- ? "green"
- : isTika
- ? "cyan"
- : undefined
- }
- >
- <Card
- title={
- <Link
- to={`/article/para/${item.book}-${firstPara}?book=${item.book}&par=${item.para}`}
- target="_blank"
- >
- {item.book_title_pali}
- </Link>
- }
- size="small"
- >
- <TocPath
- data={item.path}
- onChange={(node: ITocPathNode) => {
- if (node.book && node.paragraph) {
- const type = node.level
- ? node.level < 8
- ? "chapter"
- : "para"
- : "para";
- store.dispatch(
- change({
- book: node.book,
- para: node.paragraph,
- type: type,
- })
- );
- }
- }}
- />
- </Card>
- </Badge.Ribbon>
- </List.Item>
- );
- }}
- />
- )}
- </Modal>
- </>
- );
- };
- export default RelatedParaWidget;
|