RecentList.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import { useIntl } from "react-intl";
  2. import { useEffect, useRef } from "react";
  3. import { Dropdown, Space, Typography } from "antd";
  4. import { SearchOutlined } from "@ant-design/icons";
  5. import { type ActionType, ProTable } from "@ant-design/pro-components";
  6. import { get } from "../../request";
  7. import type { ArticleType } from "../article/Article";
  8. import { useAppSelector } from "../../hooks";
  9. import { currentUser as _currentUser } from "../../reducers/current-user";
  10. import {
  11. ArticleOutlinedIcon,
  12. ChapterOutlinedIcon,
  13. ParagraphOutlinedIcon,
  14. } from "../../assets/icon";
  15. export interface IRecentRequest {
  16. type: ArticleType;
  17. article_id: string;
  18. param?: string;
  19. }
  20. interface IParam {
  21. book?: string;
  22. para?: string;
  23. channel?: string;
  24. mode?: string;
  25. }
  26. interface IRecentData {
  27. id: string;
  28. title: string;
  29. type: ArticleType;
  30. article_id: string;
  31. param: string | null;
  32. updated_at: string;
  33. }
  34. export interface IRecentResponse {
  35. ok: boolean;
  36. message: string;
  37. data: IRecentData;
  38. }
  39. interface IRecentListResponse {
  40. ok: boolean;
  41. message: string;
  42. data: {
  43. rows: IRecentData[];
  44. count: number;
  45. };
  46. }
  47. export interface IRecent {
  48. id: string;
  49. title: string;
  50. type: ArticleType;
  51. articleId: string;
  52. updatedAt: string;
  53. param?: IParam;
  54. }
  55. interface IWidget {
  56. onSelect?: Function;
  57. }
  58. const RecentWidget = ({ onSelect }: IWidget) => {
  59. const intl = useIntl();
  60. const user = useAppSelector(_currentUser);
  61. const ref = useRef<ActionType | null>(null);
  62. useEffect(() => {
  63. ref.current?.reload();
  64. }, [user]);
  65. return (
  66. <>
  67. <ProTable<IRecent>
  68. actionRef={ref}
  69. columns={[
  70. {
  71. title: intl.formatMessage({
  72. id: "dict.fields.sn.label",
  73. }),
  74. dataIndex: "sn",
  75. key: "sn",
  76. width: 50,
  77. search: false,
  78. },
  79. {
  80. title: intl.formatMessage({
  81. id: "forms.fields.title.label",
  82. }),
  83. dataIndex: "title",
  84. key: "title",
  85. tooltip: "过长会自动收缩",
  86. ellipsis: true,
  87. render: (_text, row, index, _action) => {
  88. let icon = <></>;
  89. switch (row.type) {
  90. case "article":
  91. icon = <ArticleOutlinedIcon />;
  92. break;
  93. case "chapter":
  94. icon = <ChapterOutlinedIcon />;
  95. break;
  96. case "para":
  97. icon = <ParagraphOutlinedIcon />;
  98. break;
  99. default:
  100. break;
  101. }
  102. return (
  103. <Space>
  104. {icon}
  105. <Typography.Link
  106. key={index}
  107. onClick={(event) => {
  108. if (typeof onSelect !== "undefined") {
  109. onSelect(event, row);
  110. }
  111. }}
  112. >
  113. {row.title}
  114. </Typography.Link>
  115. </Space>
  116. );
  117. },
  118. },
  119. {
  120. title: intl.formatMessage({
  121. id: "forms.fields.type.label",
  122. }),
  123. dataIndex: "type",
  124. key: "type",
  125. width: 100,
  126. search: false,
  127. filters: true,
  128. onFilter: true,
  129. valueEnum: {
  130. all: { text: "全部", status: "Default" },
  131. chapter: { text: "章节", status: "Success" },
  132. article: { text: "文章", status: "Success" },
  133. para: { text: "段落", status: "Success" },
  134. sent: { text: "句子", status: "Success" },
  135. },
  136. },
  137. {
  138. title: intl.formatMessage({
  139. id: "forms.fields.updated-at.label",
  140. }),
  141. key: "updated-at",
  142. width: 100,
  143. search: false,
  144. dataIndex: "updatedAt",
  145. valueType: "date",
  146. },
  147. {
  148. title: intl.formatMessage({ id: "buttons.option" }),
  149. key: "option",
  150. width: 120,
  151. valueType: "option",
  152. render: (_text, _row, index, _action) => [
  153. <Dropdown.Button
  154. type="link"
  155. key={index}
  156. trigger={["click", "contextMenu"]}
  157. menu={{
  158. items: [
  159. {
  160. key: "open",
  161. label: "在藏经阁中打开",
  162. icon: <SearchOutlined />,
  163. },
  164. {
  165. key: "share",
  166. label: "分享",
  167. icon: <SearchOutlined />,
  168. },
  169. {
  170. key: "delete",
  171. label: "删除",
  172. icon: <SearchOutlined />,
  173. },
  174. ],
  175. onClick: (e) => {
  176. switch (e.key) {
  177. case "share":
  178. break;
  179. case "delete":
  180. break;
  181. default:
  182. break;
  183. }
  184. },
  185. }}
  186. >
  187. {intl.formatMessage({ id: "buttons.edit" })}
  188. </Dropdown.Button>,
  189. ],
  190. },
  191. ]}
  192. request={async (params = {}, sorter, filter) => {
  193. console.log(params, sorter, filter);
  194. if (typeof user === "undefined") {
  195. return {
  196. total: 0,
  197. succcess: false,
  198. data: [],
  199. };
  200. }
  201. let url = `/v2/recent?view=user&id=${user?.id}`;
  202. const offset =
  203. ((params.current ? params.current : 1) - 1) *
  204. (params.pageSize ? params.pageSize : 10);
  205. url += `&limit=${params.pageSize}&offset=${offset}`;
  206. url += params.keyword ? "&search=" + params.keyword : "";
  207. console.log("url", url);
  208. const res = await get<IRecentListResponse>(url);
  209. console.log("article list", res);
  210. const items: IRecent[] = res.data.rows.map((item, id) => {
  211. return {
  212. sn: id + 1,
  213. id: item.id,
  214. title: item.title,
  215. type: item.type,
  216. articleId: item.article_id,
  217. param: item.param ? JSON.parse(item.param) : undefined,
  218. updatedAt: item.updated_at,
  219. };
  220. });
  221. return {
  222. total: res.data.count,
  223. succcess: true,
  224. data: items,
  225. };
  226. }}
  227. rowKey="id"
  228. bordered
  229. pagination={{
  230. showQuickJumper: true,
  231. showSizeChanger: true,
  232. }}
  233. search={false}
  234. options={{
  235. search: true,
  236. }}
  237. />
  238. </>
  239. );
  240. };
  241. export default RecentWidget;