| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- import { useIntl } from "react-intl";
- import { Button, Dropdown, Input, Space, Tooltip } from "antd";
- import { useEffect, useState } from "react";
- import {
- MoreOutlined,
- PlusOutlined,
- EditOutlined,
- CheckOutlined,
- SearchOutlined,
- CloseOutlined,
- } from "@ant-design/icons";
- import { useAppSelector } from "../../../hooks";
- import { inlineDict as _inlineDict } from "../../../reducers/inline-dict";
- import store from "../../../store";
- import { lookup } from "../../../reducers/command";
- import { openPanel } from "../../../reducers/right-panel";
- import { ItemType } from "antd/lib/menu/hooks/useItems";
- import { MergeIcon } from "../../../assets/icon";
- interface IWFMI {
- pali: string;
- meaning?: string;
- readonly?: boolean;
- onChange?: Function;
- }
- const WbwFactorMeaningItem = ({
- pali,
- readonly = false,
- meaning = "",
- onChange,
- }: IWFMI) => {
- const intl = useIntl();
- console.debug("WbwFactorMeaningItem meaning", meaning);
- const defaultMenu: ItemType[] = [
- {
- key: "_lookup",
- label: (
- <Space>
- <SearchOutlined />
- {intl.formatMessage({
- id: "buttons.lookup",
- })}
- </Space>
- ),
- },
- {
- key: "_edit",
- label: (
- <Space>
- <EditOutlined />
- {intl.formatMessage({
- id: "buttons.edit",
- })}
- </Space>
- ),
- },
- { key: pali, label: pali },
- ];
- const [items, setItems] = useState<ItemType[]>(defaultMenu);
- const [input, setInput] = useState<string>();
- const [editable, setEditable] = useState(false);
- const inlineDict = useAppSelector(_inlineDict);
- useEffect(() => {
- if (inlineDict.wordIndex.includes(pali)) {
- const result = inlineDict.wordList.filter((word) => word.word === pali);
- //查重
- //TODO 加入信心指数并排序
- const myMap = new Map<string, number>();
- const meanings: string[] = [];
- for (const it of result) {
- if (typeof it.mean === "string") {
- for (const meaning of it.mean.split("$")) {
- if (meaning !== "") {
- myMap.set(meaning, 1);
- }
- }
- }
- }
- myMap.forEach((_value, key, _map) => {
- meanings.push(key);
- });
- const menu = meanings.map((item) => {
- return { key: item, label: item };
- });
- setItems([...defaultMenu, ...menu]);
- }
- }, [pali, inlineDict]);
- const inputOk = () => {
- setEditable(false);
- if (typeof onChange !== "undefined") {
- onChange(input);
- }
- };
- const inputCancel = () => {
- setEditable(false);
- setInput(meaning);
- };
- const meaningInner = editable ? (
- <Input
- defaultValue={meaning}
- size="small"
- addonAfter={
- <>
- <CheckOutlined
- style={{ cursor: "pointer", marginRight: 4 }}
- onClick={() => inputOk()}
- />
- <CloseOutlined
- style={{ cursor: "pointer" }}
- onClick={() => inputCancel()}
- />
- </>
- }
- placeholder="Basic usage"
- style={{ width: 160 }}
- onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
- setInput(event.target.value);
- }}
- onPressEnter={(_event: React.KeyboardEvent<HTMLInputElement>) => {
- inputOk();
- }}
- onKeyDown={(event: React.KeyboardEvent<HTMLInputElement>) => {
- if (event.key === "Escape") {
- setEditable(false);
- }
- }}
- />
- ) : (
- <Button
- disabled={readonly}
- key={1}
- size="small"
- type="text"
- icon={meaning === "" ? <MoreOutlined /> : undefined}
- onClick={() => {
- setEditable(true);
- }}
- >
- {meaning}
- </Button>
- );
- return editable || readonly ? (
- meaningInner
- ) : (
- <Dropdown
- menu={{
- items: [
- ...items.filter((_value, index) => index <= 5),
- {
- key: "more",
- label: intl.formatMessage({ id: "buttons.more" }),
- disabled: items.length <= 5,
- children: items.filter((_value, index) => index > 5),
- },
- ],
- onClick: (e) => {
- switch (e.key) {
- case "_lookup":
- store.dispatch(lookup(pali));
- store.dispatch(openPanel("dict"));
- break;
- case "_edit":
- setEditable(true);
- break;
- default:
- if (typeof onChange !== "undefined") {
- onChange(e.key);
- }
- break;
- }
- },
- }}
- placement="bottomLeft"
- trigger={["hover"]}
- >
- {meaningInner}
- </Dropdown>
- );
- };
- const resizeArray = (input: string[], factors: string[]) => {
- const newFm = factors.map((_item, index) => {
- if (index < input.length) {
- return input[index];
- } else {
- return "";
- }
- });
- return newFm;
- };
- interface IWidget {
- factors?: string[];
- value?: string[];
- readonly?: boolean;
- onChange?: Function;
- onJoin?: Function;
- }
- const WbwDetailFmWidget = ({
- factors = [],
- value = [],
- readonly = false,
- onChange,
- onJoin,
- }: IWidget) => {
- console.debug("WbwDetailFmWidget render");
- const [factorInputEnable, setFactorInputEnable] = useState(false);
- const currValue = resizeArray(value, factors);
- const combine = (input: string): string => {
- let meaning = "";
- input
- .split("-")
- .forEach((value: string, index: number, _array: string[]) => {
- if (index === 0) {
- meaning += value;
- } else {
- if (value.includes("~")) {
- meaning = value.replace("~", meaning);
- } else {
- meaning += value;
- }
- }
- });
- console.debug("combine", meaning);
- return meaning;
- };
- return (
- <div className="wbw_word_item" style={{ width: "100%" }}>
- <div style={{ display: "flex", width: "100%" }}>
- <Input
- key="input"
- allowClear
- hidden={!factorInputEnable}
- value={currValue.join("+")}
- placeholder="请输入"
- onChange={(e) => {
- console.log(e.target.value);
- const newData = resizeArray(e.target.value.split("+"), factors);
- if (typeof onChange !== "undefined") {
- onChange(newData);
- }
- }}
- />
- {factorInputEnable ? (
- <Button
- key="input-button"
- type="text"
- icon={<CheckOutlined />}
- onClick={() => setFactorInputEnable(false)}
- />
- ) : undefined}
- </div>
- {!factorInputEnable ? (
- <Space size={0} key="space">
- {currValue.map((item, index) => {
- const fm = item.split("-");
- return (
- <span key={index} style={{ display: "flex" }}>
- {factors[index]?.split("-").map((item1, index1) => {
- return (
- <WbwFactorMeaningItem
- readonly={readonly}
- key={index1}
- pali={item1}
- meaning={fm[index1]}
- onChange={(value: string) => {
- const newData = [...currValue];
- const currFm = resizeArray(
- currValue[index].split("-"),
- factors[index].split("-")
- );
- currFm.forEach(
- (_value3: string, index3: number, array: string[]) => {
- if (index3 === index1) {
- array[index3] = value;
- }
- }
- );
- newData[index] = currFm.join("-");
- if (typeof onChange !== "undefined") {
- onChange(newData);
- }
- }}
- />
- );
- })}
- {index < currValue.length - 1 ? (
- <PlusOutlined disabled={readonly} key={`icon-${index}`} />
- ) : (
- <>
- <Tooltip title="在文本框中编辑">
- <Button
- disabled={readonly}
- key="EditOutlined"
- size="small"
- type="text"
- icon={<EditOutlined />}
- onClick={() => setFactorInputEnable(true)}
- />
- </Tooltip>
- <Tooltip title="合并后替换含义">
- <Button
- disabled={readonly}
- key="CheckOutlined"
- size="small"
- type="text"
- icon={<MergeIcon />}
- onClick={() => {
- if (typeof onJoin !== "undefined") {
- const newMeaning = currValue
- .map((item) => {
- return item
- .replaceAll("[[", "/*")
- .replaceAll("]]", "*/");
- })
- .filter((value) => !value.includes("["))
- .map((item) => {
- return item
- .replaceAll("/*", "[[")
- .replaceAll("*/", "]]");
- })
- .map((item) => {
- return combine(item);
- })
- .join("");
- onJoin(newMeaning);
- }
- }}
- />
- </Tooltip>
- </>
- )}
- </span>
- );
- })}
- </Space>
- ) : undefined}
- </div>
- );
- };
- export default WbwDetailFmWidget;
|