SentTab.tsx 9.2 KB

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