WbwDetailRelation.tsx 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. import { Button, List, Select, Space } from "antd";
  2. import { useEffect, useState } from "react";
  3. import {
  4. DeleteOutlined,
  5. PlusOutlined,
  6. InfoCircleOutlined,
  7. } from "@ant-design/icons";
  8. import { useAppSelector } from "../../../hooks";
  9. import { getRelation } from "../../../reducers/relation";
  10. import { getGrammar } from "../../../reducers/term-vocabulary";
  11. import type { IWbw } from "./WbwWord"
  12. import { useIntl } from "react-intl";
  13. import store from "../../../store";
  14. import { add, relationAddParam } from "../../../reducers/relation-add";
  15. import type { IRelation } from "../../../pages/admin/relation/list"
  16. import { grammar } from "../../../reducers/command";
  17. import { openPanel } from "../../../reducers/right-panel";
  18. interface IOptions {
  19. value: string;
  20. label: JSX.Element;
  21. }
  22. export interface IWbwRelation {
  23. sour_id: string;
  24. sour_spell: string;
  25. dest_id: string;
  26. dest_spell: string;
  27. relation?: string;
  28. is_new?: boolean;
  29. }
  30. interface IWidget {
  31. data: IWbw;
  32. onChange?: Function;
  33. onAdd?: Function;
  34. onFromList?: Function;
  35. }
  36. const WbwDetailRelationWidget = ({
  37. data,
  38. onChange,
  39. onAdd,
  40. onFromList,
  41. }: IWidget) => {
  42. const getSourId = () => `${data.book}-${data.para}-` + data.sn.join("-");
  43. const intl = useIntl();
  44. const [relation, setRelation] = useState<IWbwRelation[]>([]);
  45. const [currRelation, setCurrRelation] = useState<IRelation[]>();
  46. const [relationOptions, setRelationOptions] = useState<IRelation[]>();
  47. const [newRelationName, setNewRelationName] = useState<string>();
  48. const [fromList, _setFromList] = useState<string[]>();
  49. const [options, setOptions] = useState<IOptions[]>();
  50. const terms = useAppSelector(getGrammar);
  51. const relations = useAppSelector(getRelation);
  52. const addParam = useAppSelector(relationAddParam);
  53. const newRelationRow: IWbwRelation = {
  54. sour_id: getSourId(),
  55. sour_spell: data.word.value,
  56. dest_id: "",
  57. dest_spell: "",
  58. relation: undefined,
  59. is_new: true,
  60. };
  61. useEffect(() => {
  62. if (typeof onFromList !== "undefined") {
  63. onFromList(fromList);
  64. }
  65. }, [fromList]);
  66. useEffect(() => {
  67. if (
  68. addParam?.command === "apply" &&
  69. addParam.src_sn === data.sn.join("-") &&
  70. addParam.target_spell
  71. ) {
  72. const newRelation: IWbwRelation = {
  73. sour_id: getSourId(),
  74. sour_spell: data.word.value,
  75. dest_id: addParam.target_id ? addParam.target_id : "",
  76. dest_spell: addParam.target_spell,
  77. relation: newRelationName,
  78. };
  79. setRelation((origin) => {
  80. origin.push(newRelation);
  81. if (typeof onChange !== "undefined") {
  82. onChange({
  83. field: "relation",
  84. value: JSON.stringify(origin),
  85. });
  86. }
  87. return origin;
  88. });
  89. setNewRelationName(undefined);
  90. }
  91. }, [addParam?.command]);
  92. useEffect(() => {
  93. if (typeof data.relation === "undefined") {
  94. return;
  95. }
  96. const arrRelation: IWbwRelation[] = JSON.parse(
  97. data.relation?.value ? data.relation?.value : "[]"
  98. );
  99. setRelation(arrRelation);
  100. }, [data.relation]);
  101. useEffect(() => {
  102. let grammar = data.case?.value
  103. ?.replace("v:ind", "v")
  104. .replace("#", "$")
  105. .replace(":", "$")
  106. .replaceAll(".", "")
  107. .split("$");
  108. if (data.grammar2?.value) {
  109. if (grammar) {
  110. grammar = [data.grammar2?.value.replaceAll(".", ""), ...grammar];
  111. } else {
  112. grammar = [data.grammar2?.value.replaceAll(".", "")];
  113. }
  114. }
  115. if (typeof grammar === "undefined") {
  116. return;
  117. }
  118. //找出符合条件的relation
  119. const filteredRelation = relations?.filter((value) => {
  120. let caseMatch = true;
  121. let spellMatch = true;
  122. if (!value.from) {
  123. return false;
  124. }
  125. if (value.from?.case) {
  126. let matchCount = 0;
  127. if (grammar) {
  128. for (const iterator of value.from.case) {
  129. if (grammar?.includes(iterator)) {
  130. matchCount++;
  131. }
  132. }
  133. }
  134. if (matchCount !== value.from.case.length) {
  135. caseMatch = false;
  136. }
  137. }
  138. if (value.from?.spell && data.real.value) {
  139. // 假设你有一个字符串表示的正则表达式
  140. const regexString = value.from?.spell.replaceAll("*", "\\w");
  141. // 创建正则表达式对象
  142. const regex = new RegExp(regexString);
  143. // 使用正则表达式
  144. spellMatch = regex.test(data.real.value);
  145. }
  146. return caseMatch && spellMatch;
  147. });
  148. setCurrRelation(filteredRelation);
  149. setRelationOptions(filteredRelation);
  150. const relationName = new Map<string, string>();
  151. const relationFrom: string[] = [];
  152. filteredRelation?.forEach((value) => {
  153. relationName.set(value.name, value.name);
  154. let from: string[] = [];
  155. if (value.from?.spell) {
  156. from.push(value.from.spell);
  157. }
  158. if (value.from?.case) {
  159. from = [...from, ...value.from.case];
  160. }
  161. if (!relationFrom.includes(from.join("."))) {
  162. relationFrom.push(from.join("."));
  163. }
  164. });
  165. const mRelation = Array.from(relationName.keys()).map((item) => {
  166. const localName = terms?.find((term) => term.word === item)?.meaning;
  167. return {
  168. value: item,
  169. label: (
  170. <Space>
  171. {item}
  172. {localName}
  173. </Space>
  174. ),
  175. };
  176. });
  177. setOptions(mRelation);
  178. if (typeof onFromList !== "undefined") {
  179. console.debug("relationFrom", relationFrom);
  180. onFromList(relationFrom);
  181. }
  182. }, [
  183. data.case?.value,
  184. data.grammar2?.value,
  185. data.real.value,
  186. relations,
  187. terms,
  188. ]);
  189. const addButton = (
  190. <Button
  191. type="dashed"
  192. icon={<PlusOutlined />}
  193. onClick={() => {
  194. if (typeof onAdd !== "undefined") {
  195. onAdd();
  196. }
  197. store.dispatch(
  198. add({
  199. book: data.book,
  200. para: data.para,
  201. src_sn: data.sn.join("-"),
  202. command: "add",
  203. relations: currRelation,
  204. })
  205. );
  206. }}
  207. >
  208. {intl.formatMessage({ id: "buttons.relate.to" })}
  209. </Button>
  210. );
  211. return (
  212. <List
  213. itemLayout="vertical"
  214. size="small"
  215. dataSource={[...relation, newRelationRow]}
  216. renderItem={(item, index) => (
  217. <List.Item>
  218. <Space>
  219. {item.is_new ? undefined : (
  220. <Button
  221. type="text"
  222. icon={<DeleteOutlined />}
  223. onClick={() => {
  224. const arrRelation: IWbwRelation[] = [...relation];
  225. arrRelation.splice(index, 1);
  226. setRelation(arrRelation);
  227. if (typeof onChange !== "undefined") {
  228. onChange({
  229. field: "relation",
  230. value: JSON.stringify(arrRelation),
  231. });
  232. }
  233. }}
  234. />
  235. )}
  236. <Select
  237. defaultValue={item.relation}
  238. placeholder={"请选择关系"}
  239. allowClear={item.is_new ? true : false}
  240. style={{ width: 180 }}
  241. onChange={(value: string) => {
  242. if (item.is_new) {
  243. setNewRelationName(value);
  244. return;
  245. }
  246. const currSelect = relationOptions?.filter(
  247. (rl) => rl.name === value
  248. );
  249. console.log("filteredRelation", currSelect);
  250. setCurrRelation(currSelect);
  251. console.log(`selected ${value}`);
  252. setRelation((origin) => {
  253. origin[index].relation = value;
  254. if (typeof onChange !== "undefined") {
  255. onChange({
  256. field: "relation",
  257. value: JSON.stringify(origin),
  258. });
  259. }
  260. return origin;
  261. });
  262. }}
  263. options={options}
  264. />
  265. <Button
  266. type="link"
  267. icon={<InfoCircleOutlined />}
  268. onClick={() => {
  269. store.dispatch(grammar(relation[index].relation));
  270. store.dispatch(openPanel("grammar"));
  271. }}
  272. />
  273. {item.dest_spell ? item.dest_spell : addButton}
  274. </Space>
  275. </List.Item>
  276. )}
  277. />
  278. );
  279. };
  280. export default WbwDetailRelationWidget;