| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- import { List, Skeleton, Space, Tag, Typography } from "antd";
- import { useEffect, useState } from "react";
- import { Link } from "react-router-dom";
- import { get } from "../../request";
- import TocPath, { ITocPathNode } from "../corpus/TocPath";
- import { TContentType } from "../discussion/DiscussionCreate";
- import Marked from "../general/Marked";
- import PaliText from "../template/Wbw/PaliText";
- import "./search.css";
- const { Title, Text } = Typography;
- interface IFtsData {
- rank?: number;
- highlight?: string;
- book: number;
- paragraph: number;
- content?: string;
- content_type?: TContentType;
- title?: string;
- paliTitle?: string;
- path?: ITocPathNode[];
- }
- interface IFtsResponse {
- ok: boolean;
- message: string;
- data: {
- rows: IFtsData[];
- count: number;
- };
- }
- interface IFtsItem {
- book: number;
- paragraph: number;
- title?: string;
- paliTitle?: string;
- content?: string;
- path?: ITocPathNode[];
- }
- export type ISearchView = "pali" | "title" | "page";
- interface IWidget {
- keyWord?: string;
- tags?: string[];
- bookId?: string | null;
- book?: number;
- para?: number;
- orderBy?: string | null;
- match?: string | null;
- keyWord2?: string;
- view?: ISearchView;
- pageType?: string;
- }
- const FullTxtSearchResultWidget = ({
- keyWord,
- tags,
- bookId,
- book,
- para,
- orderBy,
- match,
- keyWord2,
- view = "pali",
- pageType,
- }: IWidget) => {
- const [ftsData, setFtsData] = useState<IFtsItem[]>();
- const [total, setTotal] = useState<number>();
- const [loading, setLoading] = useState(false);
- const [currPage, setCurrPage] = useState<number>(1);
- useEffect(() => {
- let url = `/v2/search?view=${view}&key=${keyWord}`;
- if (typeof tags !== "undefined") {
- url += `&tags=${tags}`;
- }
- if (bookId) {
- url += `&book=${bookId}`;
- }
- if (orderBy) {
- url += `&orderby=${orderBy}`;
- }
- if (match) {
- url += `&match=${match}`;
- }
- if (pageType) {
- url += `&type=${pageType}`;
- }
- const offset = (currPage - 1) * 10;
- url += `&limit=10&offset=${offset}`;
- console.log("fetch url", url);
- setLoading(true);
- get<IFtsResponse>(url)
- .then((json) => {
- if (json.ok) {
- const result: IFtsItem[] = json.data.rows.map((item) => {
- return {
- book: item.book,
- paragraph: item.paragraph,
- title: item.title ? item.title : item.paliTitle,
- paliTitle: item.paliTitle,
- content: item.highlight
- ? item.highlight.replaceAll("** ti ", "**ti ")
- : item.content,
- path: item.path,
- };
- });
- setFtsData(result);
- setTotal(json.data.count);
- } else {
- console.error(json.message);
- }
- })
- .finally(() => setLoading(false));
- }, [bookId, currPage, keyWord, match, orderBy, pageType, tags, view]);
- return (
- <List
- style={{ width: "100%" }}
- itemLayout="vertical"
- size="small"
- dataSource={ftsData}
- pagination={{
- onChange: (page) => {
- console.log(page);
- setCurrPage(page);
- },
- showQuickJumper: true,
- showSizeChanger: false,
- pageSize: 10,
- total: total,
- position: "both",
- showTotal: (total) => {
- return `结果: ${total}`;
- },
- }}
- renderItem={(item) => {
- let paragraph: number[];
- if (view === "title") {
- paragraph = [item.paragraph, item.paragraph + 1, item.paragraph + 2];
- } else {
- paragraph = [item.paragraph - 1, item.paragraph, item.paragraph + 1];
- }
- let link: string = "";
- switch (view) {
- case "pali":
- link = `/article/para/${item.book}-${item.paragraph}?book=${item.book}&par=${paragraph}&focus=${item.paragraph}`;
- break;
- case "title":
- link = `/article/chapter/${item.book}-${item.paragraph}`;
- break;
- case "page":
- link = `/article/chapter/${item.book}-${item.paragraph}`;
- break;
- default:
- break;
- }
- let title = "unnamed";
- if (item.paliTitle) {
- if (item.paliTitle.length > 0) {
- title = item.paliTitle;
- }
- }
- return (
- <List.Item>
- {loading ? (
- <div style={{ width: "100%" }}>
- <Skeleton active />
- </div>
- ) : (
- <div>
- <div>
- <PaliText text={item.path ? item.path[0].title : ""} />
- </div>
- <div>
- <Space style={{ color: "gray", fontSize: "80%" }}>
- <TocPath
- data={item.path?.slice(1)}
- style={{ fontSize: "80%" }}
- />
- {"/"}
- <Tag style={{ fontSize: "80%" }}>{item.paragraph}</Tag>
- </Space>
- </div>
- <Title level={4} style={{ fontWeight: 500 }}>
- <Link to={link} target="_blank">
- {item.title ? item.title : title}
- </Link>
- </Title>
- <div style={{ display: "none" }}>
- <Text type="secondary">{item.paliTitle}</Text>
- </div>
- <div>
- <Marked className="search_content" text={item.content} />
- </div>
- </div>
- )}
- </List.Item>
- );
- }}
- />
- );
- };
- export default FullTxtSearchResultWidget;
|