SentTab.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. import { useEffect, useState } from "react";
  2. import { Badge, Space, Tabs, Typography, message } from "antd";
  3. import {
  4. TranslationOutlined,
  5. CloseOutlined,
  6. BlockOutlined,
  7. } from "@ant-design/icons";
  8. import SentTabButton from "./SentTabButton";
  9. import SentCanRead from "./SentCanRead";
  10. import SentSim from "./SentSim";
  11. import { useIntl } from "react-intl";
  12. import TocPath, { ITocPathNode } from "../../corpus/TocPath";
  13. import { IWbw } from "../Wbw/WbwWord";
  14. import RelaGraphic from "../Wbw/RelaGraphic";
  15. import SentMenu from "./SentMenu";
  16. import { ArticleMode } from "../../article/Article";
  17. import { IResNumber } from "../SentEdit";
  18. import SentTabCopy from "./SentTabCopy";
  19. import { fullUrl } from "../../../utils";
  20. import SentWbw from "./SentWbw";
  21. const { Text } = Typography;
  22. interface IWidget {
  23. id: string;
  24. book: number;
  25. para: number;
  26. wordStart: number;
  27. wordEnd: number;
  28. channelsId?: string[];
  29. path?: ITocPathNode[];
  30. layout?: "row" | "column";
  31. tranNum?: number;
  32. nissayaNum?: number;
  33. commNum?: number;
  34. originNum: number;
  35. simNum?: number;
  36. wbwData?: IWbw[];
  37. magicDictLoading?: boolean;
  38. compact?: boolean;
  39. mode?: ArticleMode;
  40. loadedRes?: IResNumber;
  41. onMagicDict?: Function;
  42. onCompact?: Function;
  43. onModeChange?: Function;
  44. }
  45. const SentTabWidget = ({
  46. id,
  47. book,
  48. para,
  49. wordStart,
  50. wordEnd,
  51. channelsId,
  52. path,
  53. tranNum = 0,
  54. nissayaNum = 0,
  55. commNum = 0,
  56. originNum,
  57. simNum = 0,
  58. wbwData,
  59. magicDictLoading = false,
  60. compact = false,
  61. mode,
  62. loadedRes,
  63. onMagicDict,
  64. onCompact,
  65. onModeChange,
  66. }: IWidget) => {
  67. const intl = useIntl();
  68. const [isCompact, setIsCompact] = useState(compact);
  69. const [hover, setHover] = useState(false);
  70. const [currKey, setCurrKey] = useState("close");
  71. const [currTranNum, setCurrTranNum] = useState(tranNum);
  72. const [currNissayaNum, setCurrNissayaNum] = useState(nissayaNum);
  73. const [currCommNum, setCurrCommNum] = useState(commNum);
  74. console.log("SentTabWidget render");
  75. useEffect(() => setIsCompact(compact), [compact]);
  76. const mPath = path
  77. ? [
  78. ...path,
  79. { book: book, paragraph: para, title: para.toString(), level: 100 },
  80. ]
  81. : [];
  82. if (typeof id === "undefined") {
  83. return <></>;
  84. }
  85. const sentId = id.split("_");
  86. const sId = sentId[0].split("-");
  87. const tabButtonStyle: React.CSSProperties | undefined = compact
  88. ? { visibility: hover || currKey !== "close" ? "visible" : "hidden" }
  89. : undefined;
  90. return (
  91. <Tabs
  92. onMouseEnter={() => setHover(true)}
  93. onMouseLeave={() => setHover(false)}
  94. activeKey={currKey}
  95. onChange={(activeKey: string) => {
  96. setCurrKey(activeKey);
  97. }}
  98. style={
  99. isCompact
  100. ? {
  101. position: currKey === "close" ? "absolute" : "unset",
  102. marginTop: -32,
  103. width: "100%",
  104. marginRight: 10,
  105. backgroundColor:
  106. hover || currKey !== "close"
  107. ? "rgba(128, 128, 128, 0.1)"
  108. : "unset",
  109. }
  110. : {
  111. padding: "0 8px",
  112. backgroundColor: "rgba(128, 128, 128, 0.1)",
  113. }
  114. }
  115. tabBarStyle={{ marginBottom: 0 }}
  116. size="small"
  117. tabBarGutter={0}
  118. tabBarExtraContent={
  119. <Space>
  120. <TocPath
  121. link="none"
  122. data={mPath}
  123. channels={channelsId}
  124. trigger={path ? path.length > 0 ? path[0].title : <></> : <></>}
  125. />
  126. <Text>{sentId[0]}</Text>
  127. <SentTabCopy wbwData={wbwData} text={`{{${sentId[0]}}}`} />
  128. <SentMenu
  129. book={book}
  130. para={para}
  131. loading={magicDictLoading}
  132. mode={mode}
  133. onMagicDict={(type: string) => {
  134. if (typeof onMagicDict !== "undefined") {
  135. onMagicDict(type);
  136. }
  137. }}
  138. onMenuClick={(key: string) => {
  139. switch (key) {
  140. case "compact" || "normal":
  141. if (typeof onCompact !== "undefined") {
  142. setIsCompact(true);
  143. onCompact(true);
  144. }
  145. break;
  146. case "normal":
  147. if (typeof onCompact !== "undefined") {
  148. setIsCompact(false);
  149. onCompact(false);
  150. }
  151. break;
  152. case "origin-edit":
  153. if (typeof onModeChange !== "undefined") {
  154. onModeChange("edit");
  155. }
  156. break;
  157. case "origin-wbw":
  158. if (typeof onModeChange !== "undefined") {
  159. onModeChange("wbw");
  160. }
  161. break;
  162. case "copy-id":
  163. const id = `{{${book}-${para}-${wordStart}-${wordEnd}}}`;
  164. navigator.clipboard.writeText(id).then(() => {
  165. message.success("编号已经拷贝到剪贴板");
  166. });
  167. break;
  168. case "copy-link":
  169. let link = `/article/para/${book}-${para}?mode=edit`;
  170. link += `&book=${book}&par=${para}`;
  171. if (channelsId) {
  172. link += `&channel=` + channelsId?.join("_");
  173. }
  174. link += `&focus=${book}-${para}-${wordStart}-${wordEnd}`;
  175. navigator.clipboard.writeText(fullUrl(link)).then(() => {
  176. message.success("链接地址已经拷贝到剪贴板");
  177. });
  178. break;
  179. default:
  180. break;
  181. }
  182. }}
  183. />
  184. </Space>
  185. }
  186. items={[
  187. {
  188. label: (
  189. <span style={tabButtonStyle}>
  190. <Badge size="small" count={0}>
  191. <CloseOutlined />
  192. </Badge>
  193. </span>
  194. ),
  195. key: "close",
  196. children: <></>,
  197. },
  198. {
  199. label: (
  200. <SentTabButton
  201. style={tabButtonStyle}
  202. icon={<TranslationOutlined />}
  203. type="translation"
  204. sentId={id}
  205. count={
  206. currTranNum
  207. ? currTranNum -
  208. (loadedRes?.translation ? loadedRes.translation : 0)
  209. : undefined
  210. }
  211. title={intl.formatMessage({
  212. id: "channel.type.translation.label",
  213. })}
  214. />
  215. ),
  216. key: "translation",
  217. children: (
  218. <SentCanRead
  219. book={parseInt(sId[0])}
  220. para={parseInt(sId[1])}
  221. wordStart={parseInt(sId[2])}
  222. wordEnd={parseInt(sId[3])}
  223. type="translation"
  224. channelsId={channelsId}
  225. onCreate={() => setCurrTranNum((origin) => origin + 1)}
  226. />
  227. ),
  228. },
  229. {
  230. label: (
  231. <SentTabButton
  232. style={tabButtonStyle}
  233. icon={<CloseOutlined />}
  234. type="nissaya"
  235. sentId={id}
  236. count={
  237. currNissayaNum
  238. ? currNissayaNum -
  239. (loadedRes?.nissaya ? loadedRes.nissaya : 0)
  240. : undefined
  241. }
  242. title={intl.formatMessage({
  243. id: "channel.type.nissaya.label",
  244. })}
  245. />
  246. ),
  247. key: "nissaya",
  248. children: (
  249. <SentCanRead
  250. book={parseInt(sId[0])}
  251. para={parseInt(sId[1])}
  252. wordStart={parseInt(sId[2])}
  253. wordEnd={parseInt(sId[3])}
  254. type="nissaya"
  255. channelsId={channelsId}
  256. onCreate={() => setCurrNissayaNum((origin) => origin + 1)}
  257. />
  258. ),
  259. },
  260. {
  261. label: (
  262. <SentTabButton
  263. style={tabButtonStyle}
  264. icon={<TranslationOutlined />}
  265. type="commentary"
  266. sentId={id}
  267. count={
  268. currCommNum
  269. ? currCommNum -
  270. (loadedRes?.commentary ? loadedRes.commentary : 0)
  271. : undefined
  272. }
  273. title={intl.formatMessage({
  274. id: "channel.type.commentary.label",
  275. })}
  276. />
  277. ),
  278. key: "commentary",
  279. children: (
  280. <SentCanRead
  281. book={parseInt(sId[0])}
  282. para={parseInt(sId[1])}
  283. wordStart={parseInt(sId[2])}
  284. wordEnd={parseInt(sId[3])}
  285. type="commentary"
  286. channelsId={channelsId}
  287. onCreate={() => setCurrCommNum((origin) => origin + 1)}
  288. />
  289. ),
  290. },
  291. /*{
  292. label: (
  293. <SentTabButton
  294. icon={<BlockOutlined />}
  295. type="original"
  296. sentId={id}
  297. count={originNum}
  298. title={intl.formatMessage({
  299. id: "channel.type.original.label",
  300. })}
  301. />
  302. ),
  303. key: "original",
  304. children: (
  305. <SentCanRead
  306. book={parseInt(sId[0])}
  307. para={parseInt(sId[1])}
  308. wordStart={parseInt(sId[2])}
  309. wordEnd={parseInt(sId[3])}
  310. type="original"
  311. />
  312. ),
  313. },*/
  314. {
  315. label: (
  316. <SentTabButton
  317. style={tabButtonStyle}
  318. icon={<BlockOutlined />}
  319. type="original"
  320. sentId={id}
  321. count={simNum}
  322. title={intl.formatMessage({
  323. id: "buttons.sim",
  324. })}
  325. />
  326. ),
  327. key: "sim",
  328. children: (
  329. <SentSim
  330. book={parseInt(sId[0])}
  331. para={parseInt(sId[1])}
  332. wordStart={parseInt(sId[2])}
  333. wordEnd={parseInt(sId[3])}
  334. channelsId={channelsId}
  335. limit={5}
  336. />
  337. ),
  338. },
  339. {
  340. label: (
  341. <span style={tabButtonStyle}>
  342. <span style={{ marginRight: 12 }}>
  343. {intl.formatMessage({
  344. id: "buttons.wbw",
  345. })}
  346. </span>
  347. </span>
  348. ),
  349. key: "wbw",
  350. children: (
  351. <SentWbw
  352. book={parseInt(sId[0])}
  353. para={parseInt(sId[1])}
  354. wordStart={parseInt(sId[2])}
  355. wordEnd={parseInt(sId[3])}
  356. channelsId={channelsId}
  357. />
  358. ),
  359. },
  360. {
  361. label: <span style={tabButtonStyle}>{"关系图"}</span>,
  362. key: "relation-graphic",
  363. children: <RelaGraphic wbwData={wbwData} />,
  364. },
  365. ]}
  366. />
  367. );
  368. };
  369. export default SentTabWidget;