TermItem.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { Button, Card, Dropdown, Space, Typography } from "antd";
  2. import {
  3. MoreOutlined,
  4. EditOutlined,
  5. TranslationOutlined,
  6. } from "@ant-design/icons";
  7. import type { ITermDataResponse } from "../../api/Term";
  8. import MdView from "../template/MdView";
  9. import TimeShow from "../general/TimeShow";
  10. import TermModal from "./TermModal";
  11. import { useEffect, useState } from "react";
  12. import StudioName from "../auth/Studio";
  13. import { Link, useNavigate } from "react-router";
  14. import { useAppSelector } from "../../hooks";
  15. import { click, clickedTerm } from "../../reducers/term-click";
  16. import store from "../../store";
  17. import "../article/article.css";
  18. import Discussion from "../discussion/Discussion";
  19. import { useIntl } from "react-intl";
  20. import User from "../auth/User";
  21. const { Text } = Typography;
  22. interface IWidget {
  23. data?: ITermDataResponse;
  24. onTermClick?: Function;
  25. }
  26. const TermItemWidget = ({ data, onTermClick }: IWidget) => {
  27. const [openTermModal, setOpenTermModal] = useState(false);
  28. const [showDiscussion, setShowDiscussion] = useState(false);
  29. const navigate = useNavigate();
  30. const termClicked = useAppSelector(clickedTerm);
  31. const intl = useIntl();
  32. useEffect(() => {
  33. console.debug("on redux", termClicked, data);
  34. if (typeof termClicked === "undefined") {
  35. return;
  36. }
  37. if (termClicked?.channelId === data?.channel?.id) {
  38. store.dispatch(click(null));
  39. if (typeof onTermClick !== "undefined") {
  40. onTermClick(termClicked);
  41. }
  42. }
  43. }, [data, termClicked]);
  44. return (
  45. <>
  46. <Card
  47. bodyStyle={{ padding: 8 }}
  48. title={
  49. <Space orientation="vertical" size={3}>
  50. <Space>
  51. <Link to={`/term/show/${data?.guid}`}>
  52. <Text strong>{data?.meaning}</Text>
  53. </Link>
  54. <Text type="secondary">{data?.other_meaning}</Text>
  55. </Space>
  56. <Space style={{ fontSize: "80%" }}>
  57. <StudioName data={data?.studio} />
  58. {data?.channel
  59. ? data.channel.name
  60. : intl.formatMessage({
  61. id: "term.general-in-studio",
  62. })}
  63. <Text type="secondary">
  64. <User {...data?.editor} showAvatar={false} />
  65. </Text>
  66. <TimeShow type="secondary" updatedAt={data?.updated_at} />
  67. </Space>
  68. </Space>
  69. }
  70. extra={
  71. <Dropdown
  72. key={1}
  73. trigger={["click"]}
  74. menu={{
  75. items: [
  76. {
  77. key: "edit",
  78. label: "edit",
  79. icon: <EditOutlined />,
  80. },
  81. {
  82. key: "translate",
  83. label: "translate",
  84. icon: <TranslationOutlined />,
  85. },
  86. ],
  87. onClick: (e) => {
  88. console.log("click ", e);
  89. switch (e.key) {
  90. case "edit":
  91. setOpenTermModal(true);
  92. break;
  93. case "translate":
  94. navigate(`/article/term/${data?.guid}`);
  95. break;
  96. default:
  97. break;
  98. }
  99. },
  100. }}
  101. placement="bottomRight"
  102. >
  103. <Button
  104. size="small"
  105. shape="circle"
  106. icon={<MoreOutlined />}
  107. ></Button>
  108. </Dropdown>
  109. }
  110. >
  111. <div className="pcd_article">
  112. <MdView html={data?.html} />
  113. </div>
  114. {showDiscussion ? (
  115. <Discussion resType="term" resId={data?.guid} />
  116. ) : (
  117. <div style={{ textAlign: "right" }}>
  118. <Button type="link" onClick={() => setShowDiscussion(true)}>
  119. 纠错
  120. </Button>
  121. </div>
  122. )}
  123. </Card>
  124. <TermModal
  125. id={data?.guid}
  126. open={openTermModal}
  127. onClose={() => setOpenTermModal(false)}
  128. />
  129. </>
  130. );
  131. };
  132. export default TermItemWidget;