WbwMeaningSelect.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 { Collapse, Tag, Typography } from "antd";
  19. import { 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 Widget = ({ data, onSelect }: IWidget) => {
  47. const intl = useIntl();
  48. const inlineDict = useAppSelector(_inlineDict);
  49. const [parent, setParent] = useState<IParent[]>();
  50. useEffect(() => {
  51. //判断单词列表里面是否有这个词
  52. if (inlineDict.wordIndex.includes(data.word.value)) {
  53. let baseRemind: string[] = [];
  54. let baseDone: string[] = [];
  55. baseRemind.push(data.word.value);
  56. let mParent: IParent[] = [];
  57. while (baseRemind.length > 0) {
  58. const word1 = baseRemind.pop();
  59. if (typeof word1 === "undefined") {
  60. break;
  61. }
  62. baseDone.push(word1);
  63. const result1 = inlineDict.wordList.filter(
  64. (word) => word.word === word1
  65. );
  66. mParent.push({ word: word1, dict: [] });
  67. const indexParent = mParent.findIndex((item) => item.word === word1);
  68. result1.forEach((value, index, array) => {
  69. if (
  70. value.parent !== "" &&
  71. !baseRemind.includes(value.parent) &&
  72. !baseDone.includes(value.parent)
  73. ) {
  74. baseRemind.push(value.parent);
  75. }
  76. let indexDict = mParent[indexParent].dict.findIndex(
  77. (item) => item.id === value.dict_id
  78. );
  79. if (indexDict === -1) {
  80. //没找到,添加一个dict
  81. mParent[indexParent].dict.push({
  82. id: value.dict_id,
  83. name: value.dict_shortname,
  84. case: [],
  85. });
  86. indexDict = mParent[indexParent].dict.findIndex(
  87. (item) => item.id === value.dict_id
  88. );
  89. }
  90. const wordType =
  91. value.type === "" ? "null" : value.type.replaceAll(".", "");
  92. let indexCase = mParent[indexParent].dict[indexDict].case.findIndex(
  93. (item) => item.name === wordType
  94. );
  95. if (indexCase === -1) {
  96. //没找到,新建
  97. mParent[indexParent].dict[indexDict].case.push({
  98. name: wordType,
  99. local: intl.formatMessage({
  100. id: `dict.fields.type.${wordType}.short.label`,
  101. }),
  102. meaning: [],
  103. });
  104. indexCase = mParent[indexParent].dict[indexDict].case.findIndex(
  105. (item) => item.name === wordType
  106. );
  107. }
  108. console.log("indexCase", indexCase, value.mean);
  109. if (value.mean && value.mean.trim() !== "") {
  110. for (const valueMeaning of value.mean.trim().split("$")) {
  111. if (valueMeaning.trim() !== "") {
  112. const mValue = valueMeaning.trim();
  113. let indexMeaning = mParent[indexParent].dict[indexDict].case[
  114. indexCase
  115. ].meaning.findIndex(
  116. (itemMeaning) => itemMeaning.text === mValue
  117. );
  118. let indexM: number;
  119. const currMeanings =
  120. mParent[indexParent].dict[indexDict].case[indexCase].meaning;
  121. for (indexM = 0; indexM < currMeanings.length; indexM++) {
  122. if (currMeanings[indexM].text === mValue) {
  123. break;
  124. }
  125. }
  126. if (indexMeaning === -1) {
  127. mParent[indexParent].dict[indexDict].case[
  128. indexCase
  129. ].meaning.push({
  130. text: mValue,
  131. count: 1,
  132. });
  133. } else {
  134. mParent[indexParent].dict[indexDict].case[indexCase].meaning[
  135. indexMeaning
  136. ].count++;
  137. }
  138. }
  139. }
  140. }
  141. });
  142. }
  143. setParent(mParent);
  144. }
  145. }, [inlineDict]);
  146. return (
  147. <div>
  148. <Collapse defaultActiveKey={["0"]}>
  149. {parent?.map((item, id) => {
  150. return (
  151. <Panel header={item.word} style={{ padding: 0 }} key={id}>
  152. {item.dict.map((itemDict, idDict) => {
  153. return (
  154. <div key={idDict} style={{ display: "flex" }}>
  155. <Text keyboard strong style={{ whiteSpace: "nowrap" }}>
  156. {itemDict.name}
  157. </Text>
  158. <div>
  159. {itemDict.case.map((itemCase, idCase) => {
  160. return (
  161. <div key={idCase}>
  162. <Text italic>{itemCase.local}</Text>
  163. <span>
  164. {itemCase.meaning.map(
  165. (itemMeaning, idMeaning) => {
  166. return (
  167. <Tag
  168. key={idMeaning}
  169. onClick={(
  170. e: React.MouseEvent<HTMLAnchorElement>
  171. ) => {
  172. e.preventDefault();
  173. if (typeof onSelect !== "undefined") {
  174. onSelect(itemMeaning.text);
  175. }
  176. }}
  177. >
  178. {itemMeaning.text}-{itemMeaning.count}
  179. </Tag>
  180. );
  181. }
  182. )}
  183. </span>
  184. </div>
  185. );
  186. })}
  187. </div>
  188. </div>
  189. );
  190. })}
  191. </Panel>
  192. );
  193. })}
  194. </Collapse>
  195. </div>
  196. );
  197. };
  198. export default Widget;