TermTextAreaMenu.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import { Space, Typography } from "antd";
  2. import { useEffect, useState } from "react";
  3. import { RobotOutlined } from "@ant-design/icons";
  4. import { TermIcon } from "../../assets/icon";
  5. import { useAppSelector } from "../../hooks";
  6. import { getTerm } from "../../reducers/term-vocabulary";
  7. import { PaliToEn } from "../../utils";
  8. import { getPaliBase } from "./PaliEnding";
  9. const { Text } = Typography;
  10. interface IWordWithEn {
  11. word: string;
  12. en: string;
  13. isBase?: boolean;
  14. isTerm?: boolean;
  15. }
  16. interface IWidget {
  17. items?: string[];
  18. searchKey?: string;
  19. maxItem?: number;
  20. visible?: boolean;
  21. currIndex?: number;
  22. onChange?: Function;
  23. onSelect?: Function;
  24. }
  25. const TermTextAreaMenuWidget = ({
  26. items = [],
  27. searchKey = "",
  28. maxItem = 10,
  29. visible = false,
  30. currIndex = 0,
  31. onChange,
  32. onSelect,
  33. }: IWidget) => {
  34. const [filtered, setFiltered] = useState<IWordWithEn[]>();
  35. const [wordList, setWordList] = useState<IWordWithEn[]>();
  36. const sysTerms = useAppSelector(getTerm);
  37. console.log("items", items);
  38. useEffect(() => {
  39. //本句单词
  40. const mWords = items?.map((item) => {
  41. return {
  42. word: item,
  43. en: PaliToEn(item),
  44. };
  45. });
  46. //计算这些单词的base
  47. let parents: string[] = [];
  48. items?.forEach((value) => {
  49. getPaliBase(value).forEach((base) => {
  50. if (!parents.includes(base) && !items.includes(base)) {
  51. parents.push(base);
  52. }
  53. });
  54. });
  55. const term = sysTerms ? sysTerms?.map((item) => item.word) : [];
  56. //本句单词parent
  57. const parentTerm = parents?.map((item) => {
  58. const inSystem = term.includes(item);
  59. return {
  60. word: item,
  61. en: PaliToEn(item),
  62. isBase: !inSystem,
  63. isTerm: inSystem,
  64. };
  65. });
  66. //社区术语
  67. const sysTerm = term
  68. .filter((value) => !parents.includes(value))
  69. .sort((a, b) => a.length - b.length)
  70. .map((item) => {
  71. return {
  72. word: item,
  73. en: PaliToEn(item),
  74. isTerm: true,
  75. };
  76. });
  77. setWordList([...parentTerm, ...mWords, ...sysTerm]);
  78. //此处千万不能加其他dependency 否则会引起无限循环
  79. }, [items]);
  80. useEffect(() => {
  81. const filteredItems =
  82. searchKey !== ""
  83. ? wordList?.filter(
  84. (value) => value.en.slice(0, searchKey.length) === searchKey
  85. )
  86. : wordList;
  87. setFiltered(filteredItems);
  88. }, [wordList, searchKey]);
  89. useEffect(() => {
  90. if (filtered && filtered.length > 0 && typeof onChange !== "undefined") {
  91. if (currIndex < filtered.length) {
  92. onChange(filtered[currIndex].word);
  93. } else {
  94. onChange(filtered[filtered.length - 1].word);
  95. }
  96. }
  97. }, [currIndex, filtered]);
  98. if (visible) {
  99. return (
  100. <>
  101. <div className="term_at_menu_input" key="head">
  102. {`${searchKey}|`}
  103. </div>
  104. <ul className="term_at_menu_ul">
  105. {filtered?.slice(0, maxItem).map((item, index) => {
  106. return (
  107. <li
  108. key={index}
  109. className={index === currIndex ? "term_focus" : undefined}
  110. onClick={() => {
  111. if (typeof onSelect !== "undefined") {
  112. onSelect(item.word);
  113. }
  114. }}
  115. >
  116. <Space
  117. style={{ width: "100%", justifyContent: "space-between" }}
  118. >
  119. <Text strong={item.isBase || item.isTerm}>{item.word}</Text>
  120. {item.isTerm ? (
  121. <TermIcon />
  122. ) : item.isBase ? (
  123. <RobotOutlined />
  124. ) : undefined}
  125. </Space>
  126. </li>
  127. );
  128. })}
  129. </ul>
  130. </>
  131. );
  132. } else {
  133. return <></>;
  134. }
  135. };
  136. export default TermTextAreaMenuWidget;