FullSearchInput.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { AutoComplete, Badge, Input, Select, Space, Typography } from "antd";
  2. import type { SizeType } from "antd/lib/config-provider/SizeContext"
  3. import { useState } from "react";
  4. import { get } from "../../request";
  5. import type { ISearchView } from "./FullTextSearchResult"
  6. const { Text } = Typography;
  7. const { Option } = Select;
  8. export interface IWordIndexData {
  9. word: string;
  10. count: number;
  11. bold: number;
  12. }
  13. export interface IWordIndexListResponse {
  14. ok: boolean;
  15. message: string;
  16. data: {
  17. rows: IWordIndexData[];
  18. count: number;
  19. };
  20. }
  21. interface ValueType {
  22. key?: string;
  23. label: React.ReactNode;
  24. value: string | number;
  25. }
  26. interface IWidget {
  27. value?: string;
  28. tags?: string[];
  29. book?: number;
  30. para?: number;
  31. size?: SizeType;
  32. width?: string | number;
  33. view?: ISearchView;
  34. onSearch?: Function;
  35. onSplit?: Function;
  36. onPageTypeChange?: Function;
  37. }
  38. const FullSearchInputWidget = ({
  39. value,
  40. ___onSplit,
  41. tags,
  42. size = "middle",
  43. width,
  44. onSearch,
  45. view = "pali",
  46. onPageTypeChange,
  47. }: IWidget) => {
  48. const [options, setOptions] = useState<ValueType[]>([]);
  49. const [input, setInput] = useState<string | undefined>(value);
  50. const renderItem = (word: string, count: number, bold: number) => ({
  51. value: word,
  52. label: (
  53. <div>
  54. <div
  55. style={{
  56. display: "flex",
  57. justifyContent: "space-between",
  58. }}
  59. >
  60. <span>{bold > 0 ? <Text strong>{word}</Text> : word}</span>
  61. <Badge color="geekblue" count={count} />
  62. </div>
  63. </div>
  64. ),
  65. });
  66. const search = (value: string) => {
  67. console.log("search", value);
  68. if (value === "") {
  69. return;
  70. }
  71. let url: string = "";
  72. switch (view) {
  73. case "pali":
  74. url = `/v2/pali-word-index?view=key&key=${value}`;
  75. break;
  76. case "title":
  77. url = `/v2/search-title-index?&key=${value}`;
  78. break;
  79. default:
  80. break;
  81. }
  82. get<IWordIndexListResponse>(url).then((json) => {
  83. const words: ValueType[] = json.data.rows.map((item) => {
  84. return renderItem(item.word, item.count, item.bold);
  85. });
  86. setOptions(words);
  87. });
  88. };
  89. const selectBefore = (
  90. <Select
  91. defaultValue="P"
  92. size="large"
  93. style={{ width: 120 }}
  94. onChange={(value: string) => {
  95. if (typeof onPageTypeChange !== "undefined") {
  96. onPageTypeChange(value);
  97. }
  98. }}
  99. >
  100. <Option value="P">PTS</Option>
  101. <Option value="M">Myanmar</Option>
  102. <Option value="T">Thai</Option>
  103. <Option value="V">VRI</Option>
  104. <Option value="O">Other</Option>
  105. </Select>
  106. );
  107. return (
  108. <Space>
  109. {view === "page" ? selectBefore : undefined}
  110. <AutoComplete
  111. style={{ width: width }}
  112. value={input}
  113. popupClassName="certain-category-search-dropdown"
  114. dropdownMatchSelectWidth={400}
  115. options={options}
  116. onChange={(value: string, _option: ValueType | ValueType[]) => {
  117. console.log("input", value);
  118. setInput(value);
  119. }}
  120. onSearch={(value: string) => {
  121. console.log("auto complete on search", value, tags);
  122. if (value.indexOf(" ") >= 0 || value.indexOf(";") >= 0) {
  123. const valueLast = value.split(/[ ]|;/).slice(-1);
  124. search(valueLast[0]);
  125. } else {
  126. search(value);
  127. }
  128. }}
  129. onSelect={(value: string, _option: ValueType) => {
  130. if (typeof onSearch !== "undefined") {
  131. if (
  132. typeof input === "string" &&
  133. (input.indexOf(" ") >= 0 || input.indexOf(";") >= 0)
  134. ) {
  135. const last1 = input.lastIndexOf(" ");
  136. const last2 = input.lastIndexOf(";");
  137. let searchString = "";
  138. if (last1 > last2) {
  139. searchString = input.slice(0, last1 + 1) + value;
  140. } else {
  141. searchString = input.slice(0, last2 + 1) + value;
  142. }
  143. onSearch(searchString);
  144. setInput(searchString);
  145. } else {
  146. onSearch(value);
  147. }
  148. }
  149. }}
  150. >
  151. <Input.Search
  152. size={size}
  153. width={width}
  154. placeholder={
  155. view === "page"
  156. ? "输入页码数字,或者卷号.页码如 1.1"
  157. : "search here"
  158. }
  159. onSearch={(value: string) => {
  160. console.log("on search", value, tags);
  161. if (typeof onSearch !== "undefined") {
  162. onSearch(value);
  163. }
  164. }}
  165. />
  166. </AutoComplete>
  167. </Space>
  168. );
  169. };
  170. export default FullSearchInputWidget;