| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- import { _Button, List, Skeleton, Space, Tag, Typography } from "antd";
- import { Link } from "react-router";
- import { _get } from "../../request";
- import TocPath, { type ITocPathNode } from "../corpus/TocPath";
- import type { TContentType } from "../discussion/DiscussionCreate"
- import Marked from "../general/Marked";
- import PaliText from "../template/Wbw/PaliText";
- import "./search.css";
- import AiTranslate from "../ai/AiTranslate";
- const { Title, Text } = Typography;
- export interface IFtsData {
- rank?: number;
- highlight?: string;
- book: number;
- paragraph: number;
- content?: string;
- content_type?: TContentType;
- title?: string;
- paliTitle?: string;
- path?: ITocPathNode[];
- }
- export interface IFtsResponse {
- ok: boolean;
- message: string;
- data: {
- rows: IFtsData[];
- count: number;
- };
- }
- export interface IFtsItem {
- book: number;
- paragraph: number;
- title?: string;
- paliTitle?: string;
- content?: string;
- path?: ITocPathNode[];
- rank?: number;
- }
- export type ISearchView = "pali" | "title" | "page" | "number";
- interface IWidget {
- view?: ISearchView;
- ftsData?: IFtsItem[];
- total?: number;
- loading: boolean;
- currPage: number;
- onChange?: (page: number, pageSize: number) => void;
- }
- const FullTxtSearchResultWidget = ({
- view,
- ftsData,
- total,
- loading = false,
- currPage = 1,
- onChange,
- }: IWidget) => {
- /*
- useEffect(
- () => setCurrPage(1),
- [view, keyWord, keyWords, tags, bookId, match, pageType, bold]
- );
- useEffect(() => {
- let words;
- let api = "";
- if (keyWord?.trim().includes(" ")) {
- api = "search";
- words = keyWord;
- } else {
- api = "search-pali-wbw";
- words = keyWords?.join();
- }
- let url = `/v2/${api}?view=${view}&key=${words}`;
- 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}`;
- }
- if (bold) {
- url += `&bold=${bold}`;
- }
- 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) {
- console.log("data", json.data);
- 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,
- rank: item.rank,
- };
- });
- setFtsData(result);
- setTotal(json.data.count);
- onFound && onFound(result);
- } else {
- console.error(json.message);
- }
- })
- .finally(() => setLoading(false));
- }, [
- bookId,
- currPage,
- keyWord,
- keyWords,
- match,
- orderBy,
- pageType,
- tags,
- view,
- bold,
- ]);
- */
- return (
- <List
- style={{ width: "100%" }}
- itemLayout="vertical"
- size="small"
- dataSource={ftsData}
- pagination={{
- onChange: onChange,
- showQuickJumper: true,
- showSizeChanger: false,
- current: currPage,
- 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>
- <AiTranslate
- paragraph={`${item.book}-${item.paragraph}`}
- trigger
- />
- </div>
- </div>
- )}
- </List.Item>
- );
- }}
- />
- );
- };
- export default FullTxtSearchResultWidget;
|