1
+ import React from "react" ;
2
+ import styles from "./QueryPage.module.less" ;
3
+
4
+ import { Tag , Empty , Skeleton , Input , Divider , Descriptions } from "antd" ;
5
+ import { useVal } from "use-value-enhancer" ;
6
+ import { PDFPageItem , QueryResult , QueryStore } from "../store" ;
7
+ import { PDFTagLink } from "./Link" ;
8
+ import { Text } from "./Text" ;
9
+
10
+ const { Search } = Input ;
11
+
12
+ export const QueryPage : React . FC < { } > = ( ) => {
13
+ const store = React . useMemo ( ( ) => new QueryStore ( ) , [ ] ) ;
14
+ const isQuerying = useVal ( store . $ . isQuerying ) ;
15
+ const queryResults = useVal ( store . $ . queryResult ) ;
16
+ const onSearch = React . useCallback (
17
+ ( query : string ) => store . query ( query ) ,
18
+ [ ] ,
19
+ ) ;
20
+ let tailView : React . ReactNode = null ;
21
+
22
+ if ( isQuerying ) {
23
+ tailView = < Skeleton active /> ;
24
+ } else if ( queryResults ) {
25
+ tailView = < ResultDisplay result = { queryResults } /> ;
26
+ }
27
+ return < >
28
+ < div className = { styles [ "query-box" ] } >
29
+ < Search
30
+ placeholder = "输入你要搜索的内容"
31
+ allowClear
32
+ onSearch = { onSearch } />
33
+ { tailView && < >
34
+ < Divider />
35
+ { tailView }
36
+ </ > }
37
+ </ div >
38
+ </ > ;
39
+ } ;
40
+
41
+ type ResultDisplayProps = {
42
+ readonly result : QueryResult ;
43
+ } ;
44
+
45
+ const ResultDisplay : React . FC < ResultDisplayProps > = ( { result } ) => {
46
+ const { keywords, items } = result ;
47
+ return (
48
+ < div className = { styles [ "query-result-box" ] } >
49
+ < div className = { styles [ "keywords-bar" ] } >
50
+ < label > 关键词:</ label >
51
+ { keywords . map ( ( keyword , index ) => (
52
+ < Tag key = { `${ index } ` } > { keyword } </ Tag >
53
+ ) ) }
54
+ </ div >
55
+ { items . length === 0 && (
56
+ < Empty
57
+ className = { styles . empty }
58
+ description = "没有搜索到内容" />
59
+ ) }
60
+ { items . map ( ( item , index ) => {
61
+ if ( ! ( "content" in item ) ) {
62
+ // TODO: 对 PDF Metadata 本身的搜索
63
+ return null ;
64
+ }
65
+ return (
66
+ < PDFPageCard key = { `${ index } ` } item = { item } />
67
+ ) ;
68
+ } ) }
69
+ </ div >
70
+ ) ;
71
+ } ;
72
+
73
+ type PDFPageCardProps = {
74
+ readonly item : PDFPageItem ;
75
+ } ;
76
+
77
+ const PDFPageCard : React . FC < PDFPageCardProps > = ( { item } ) => {
78
+ const { distance, pdf_files, content, segments } = item ;
79
+ return (
80
+ < div className = { styles [ "pdf-page-card" ] } >
81
+ < Descriptions
82
+ layout = "vertical"
83
+ items = { [ {
84
+ key : "1" ,
85
+ label : "文件" ,
86
+ children : pdf_files . map ( ( pdf , index ) => (
87
+ < PDFTagLink
88
+ key = { `${ index } ` }
89
+ path = { pdf . pdf_path }
90
+ page = { pdf . page_index } />
91
+ ) ) ,
92
+ } , {
93
+ key : "2" ,
94
+ label : "距离" ,
95
+ children : distance ,
96
+ } ] } />
97
+ < Text
98
+ className = { styles . text }
99
+ content = { content }
100
+ segments = { segments } />
101
+ </ div >
102
+ ) ;
103
+ } ;
0 commit comments