WbwMeaningSelect.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /**
  2. * 逐词解析意思选择菜单
  3. * 基本算法:
  4. * 从redux 获取单词列表。找到与拼写完全相同的单词。按照词典渲染单词意思列表
  5. * 词典相同语法信息不同的单独一行
  6. * 在上面的单词数据里面 找到 base 列表,重复上面的步骤
  7. * 菜单显示结构:
  8. * 拼写1
  9. * 词典1 词性 意思1 意思2
  10. * 词典2 词性 意思1 意思2
  11. * 拼写2
  12. * 词典1 词性 意思1 意思2
  13. * 词典2 词性 意思1 意思2
  14. *
  15. */
  16. import { useEffect, useState } from "react";
  17. import { useIntl } from "react-intl";
  18. import { Button, Collapse, Tag, Typography } from "antd";
  19. import type { IWbw } from "./WbwWord"
  20. import { useAppSelector } from "../../../hooks";
  21. import { inlineDict as _inlineDict } from "../../../reducers/inline-dict";
  22. const { Panel } = Collapse;
  23. const { Text } = Typography;
  24. interface IMeaning {
  25. text: string;
  26. count: number;
  27. }
  28. interface ICase {
  29. name: string;
  30. local: string;
  31. meaning: IMeaning[];
  32. }
  33. interface IDict {
  34. id: string;
  35. name?: string;
  36. case: ICase[];
  37. }
  38. interface IParent {
  39. word: string;
  40. dict: IDict[];
  41. }
  42. interface IWidget {
  43. data: IWbw;
  44. onSelect?: Function;
  45. }
  46. const WbwMeaningSelectWidget = ({ data, onSelect }: IWidget) => {
  47. const intl = useIntl();
  48. const inlineDict = useAppSelector(_inlineDict);
  49. const [parent, setParent] = useState<IParent[]>();
  50. useEffect(() => {
  51. //判断单词列表里面是否有这个词
  52. if (typeof data.real === "undefined" || data.real.value === null) {
  53. return;
  54. }
  55. if (inlineDict.wordIndex.includes(data.real.value)) {
  56. const baseRemind: string[] = [];
  57. const baseDone: string[] = [];
  58. baseRemind.push(data.real.value);
  59. const mParent: IParent[] = [];
  60. while (baseRemind.length > 0) {
  61. const word1 = baseRemind.pop();
  62. if (typeof word1 === "undefined") {
  63. break;
  64. }
  65. baseDone.push(word1);
  66. const result1 = inlineDict.wordList.filter(
  67. (word) => word.word === word1
  68. );
  69. mParent.push({ word: word1, dict: [] });
  70. const indexParent = mParent.findIndex((item) => item.word === word1);
  71. result1.forEach((value, _index, _array) => {
  72. if (
  73. value.parent &&
  74. value.parent !== "" &&
  75. !baseRemind.includes(value.parent) &&
  76. !baseDone.includes(value.parent)
  77. ) {
  78. baseRemind.push(value.parent);
  79. }
  80. let indexDict = mParent[indexParent].dict.findIndex(
  81. (item) => item.id === value.dict_id
  82. );
  83. if (indexDict === -1) {
  84. //没找到,添加一个dict
  85. mParent[indexParent].dict.push({
  86. id: value.dict_id,
  87. name: value.shortname,
  88. case: [],
  89. });
  90. indexDict = mParent[indexParent].dict.findIndex(
  91. (item) => item.id === value.dict_id
  92. );
  93. }
  94. const wordType = value.type
  95. ? value.type === ""
  96. ? "null"
  97. : value.type.replaceAll(".", "")
  98. : "null";
  99. let indexCase = mParent[indexParent].dict[indexDict].case.findIndex(
  100. (item) => item.name === wordType
  101. );
  102. if (indexCase === -1) {
  103. //没找到,新建
  104. mParent[indexParent].dict[indexDict].case.push({
  105. name: wordType,
  106. local: intl.formatMessage({
  107. id: `dict.fields.type.${wordType}.short.label`,
  108. defaultMessage: wordType,
  109. }),
  110. meaning: [],
  111. });
  112. indexCase = mParent[indexParent].dict[indexDict].case.findIndex(
  113. (item) => item.name === wordType
  114. );
  115. }
  116. if (value.mean && value.mean.trim() !== "") {
  117. for (const valueMeaning of value.mean.trim().split("$")) {
  118. if (valueMeaning.trim() !== "") {
  119. const mValue = valueMeaning.trim();
  120. const indexMeaning = mParent[indexParent].dict[indexDict].case[
  121. indexCase
  122. ].meaning.findIndex(
  123. (itemMeaning) => itemMeaning.text === mValue
  124. );
  125. let indexM: number;
  126. const currMeanings =
  127. mParent[indexParent].dict[indexDict].case[indexCase].meaning;
  128. for (indexM = 0; indexM < currMeanings.length; indexM++) {
  129. if (currMeanings[indexM].text === mValue) {
  130. break;
  131. }
  132. }
  133. if (indexMeaning === -1) {
  134. mParent[indexParent].dict[indexDict].case[
  135. indexCase
  136. ].meaning.push({
  137. text: mValue,
  138. count: 1,
  139. });
  140. } else {
  141. mParent[indexParent].dict[indexDict].case[indexCase].meaning[
  142. indexMeaning
  143. ].count++;
  144. }
  145. }
  146. }
  147. }
  148. });
  149. }
  150. setParent(mParent);
  151. }
  152. }, [data.real?.value, inlineDict]);
  153. return (
  154. <div>
  155. <Collapse defaultActiveKey={["0"]}>
  156. {parent?.map((item, id) => {
  157. return (
  158. <Panel header={item.word} style={{ padding: 0 }} key={id}>
  159. {item.dict.map((itemDict, idDict) => {
  160. return (
  161. <div key={idDict} style={{ display: "flex" }}>
  162. <Text strong style={{ whiteSpace: "nowrap" }}>
  163. {itemDict.name}
  164. </Text>
  165. <div>
  166. {itemDict.case.map((itemCase, idCase) => {
  167. return (
  168. <div key={idCase}>
  169. <Tag>{itemCase.local}</Tag>
  170. <span>
  171. {itemCase.meaning.map(
  172. (itemMeaning, idMeaning) => {
  173. return (
  174. <Button
  175. type="text"
  176. size="middle"
  177. key={idMeaning}
  178. onClick={(
  179. e: React.MouseEvent<HTMLAnchorElement>
  180. ) => {
  181. e.preventDefault();
  182. if (typeof onSelect !== "undefined") {
  183. onSelect(itemMeaning.text);
  184. }
  185. }}
  186. >
  187. {itemMeaning.text}
  188. </Button>
  189. );
  190. }
  191. )}
  192. </span>
  193. </div>
  194. );
  195. })}
  196. </div>
  197. </div>
  198. );
  199. })}
  200. </Panel>
  201. );
  202. })}
  203. </Collapse>
  204. </div>
  205. );
  206. };
  207. export default WbwMeaningSelectWidget;