TermTextAreaMenu.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. const parents: string[] = [];
  40. let mWords: IWordWithEn[] = [];
  41. //本句单词
  42. if (items) {
  43. mWords = items?.map((item) => {
  44. return {
  45. word: item,
  46. en: PaliToEn(item),
  47. };
  48. });
  49. //计算这些单词的base
  50. items?.forEach((value) => {
  51. getPaliBase(value).forEach((base) => {
  52. if (!parents.includes(base) && !items.includes(base)) {
  53. parents.push(base);
  54. }
  55. });
  56. });
  57. }
  58. const term = sysTerms ? sysTerms?.map((item) => item.word) : [];
  59. //本句单词parent
  60. const parentTerm = parents?.map((item) => {
  61. const inSystem = term.includes(item);
  62. return {
  63. word: item,
  64. en: PaliToEn(item),
  65. isBase: !inSystem,
  66. isTerm: inSystem,
  67. };
  68. });
  69. //社区术语
  70. const sysTerm = term
  71. .filter((value) => !parents.includes(value))
  72. .sort((a, b) => a.length - b.length)
  73. .map((item) => {
  74. return {
  75. word: item,
  76. en: PaliToEn(item),
  77. isTerm: true,
  78. };
  79. });
  80. setWordList([...parentTerm, ...mWords, ...sysTerm]);
  81. //此处千万不能加其他dependency 否则会引起无限循环
  82. }, [items]);
  83. useEffect(() => {
  84. const filteredItems =
  85. searchKey !== ""
  86. ? wordList?.filter(
  87. (value) => value.en.slice(0, searchKey.length) === searchKey
  88. )
  89. : wordList;
  90. setFiltered(filteredItems);
  91. }, [wordList, searchKey]);
  92. useEffect(() => {
  93. if (filtered && filtered.length > 0 && typeof onChange !== "undefined") {
  94. if (currIndex < filtered.length) {
  95. onChange(filtered[currIndex].word);
  96. } else {
  97. onChange(filtered[filtered.length - 1].word);
  98. }
  99. }
  100. }, [currIndex, filtered]);
  101. if (visible) {
  102. return (
  103. <>
  104. <div className="term_at_menu_input" key="head">
  105. {`${searchKey}|`}
  106. </div>
  107. <ul className="term_at_menu_ul">
  108. {filtered?.slice(0, maxItem).map((item, index) => {
  109. return (
  110. <li
  111. key={index}
  112. className={index === currIndex ? "term_focus" : undefined}
  113. onClick={() => {
  114. if (typeof onSelect !== "undefined") {
  115. onSelect(item.word);
  116. }
  117. }}
  118. >
  119. <Space
  120. style={{ width: "100%", justifyContent: "space-between" }}
  121. >
  122. <Text strong={item.isBase || item.isTerm}>{item.word}</Text>
  123. {item.isTerm ? (
  124. <TermIcon />
  125. ) : item.isBase ? (
  126. <RobotOutlined />
  127. ) : undefined}
  128. </Space>
  129. </li>
  130. );
  131. })}
  132. </ul>
  133. </>
  134. );
  135. } else {
  136. return <></>;
  137. }
  138. };
  139. export default TermTextAreaMenuWidget;