ChapterInChannelList.tsx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import { useIntl } from "react-intl";
  2. import { Progress, Typography } from "antd";
  3. import { ProTable } from "@ant-design/pro-components";
  4. import { Link } from "react-router-dom";
  5. import { Space, Table } from "antd";
  6. import { Button, Dropdown } from "antd";
  7. import { DeleteOutlined } from "@ant-design/icons";
  8. import { get } from "../../request";
  9. import { IChapterListResponse } from "../../components/api/Corpus";
  10. const { Text } = Typography;
  11. interface IItem {
  12. sn: number;
  13. title: string;
  14. subTitle: string;
  15. summary: string;
  16. book: number;
  17. paragraph: number;
  18. path: string;
  19. progress: number;
  20. view: number;
  21. createdAt: number;
  22. updatedAt: number;
  23. }
  24. interface IWidget {
  25. channelId?: string;
  26. onChange?: Function;
  27. }
  28. const Widget = ({ channelId, onChange }: IWidget) => {
  29. const intl = useIntl();
  30. return (
  31. <ProTable<IItem>
  32. columns={[
  33. {
  34. title: intl.formatMessage({
  35. id: "dict.fields.sn.label",
  36. }),
  37. dataIndex: "sn",
  38. key: "sn",
  39. width: 50,
  40. search: false,
  41. },
  42. {
  43. title: intl.formatMessage({
  44. id: "forms.fields.title.label",
  45. }),
  46. dataIndex: "title",
  47. key: "title",
  48. tip: "过长会自动收缩",
  49. ellipsis: true,
  50. render: (text, row, index, action) => {
  51. return (
  52. <div key={index}>
  53. <div key={1}>
  54. <Link
  55. to={
  56. `/article/chapter/${row.book}-${row.paragraph}` +
  57. channelId
  58. ? `?channel=${channelId}`
  59. : ""
  60. }
  61. >
  62. {row.title ? row.title : row.subTitle}
  63. </Link>
  64. </div>
  65. <Text type="secondary" key={2}>
  66. {row.subTitle}
  67. </Text>
  68. </div>
  69. );
  70. },
  71. },
  72. {
  73. title: intl.formatMessage({
  74. id: "forms.fields.summary.label",
  75. }),
  76. dataIndex: "summary",
  77. key: "summary",
  78. tip: "过长会自动收缩",
  79. ellipsis: true,
  80. },
  81. {
  82. title: intl.formatMessage({
  83. id: "forms.fields.publicity.label",
  84. }),
  85. dataIndex: "progress",
  86. key: "progress",
  87. width: 100,
  88. search: false,
  89. render: (text, row, index, action) => {
  90. const per = Math.round(row.progress * 100);
  91. return <Progress percent={per} size="small" key={index} />;
  92. },
  93. },
  94. {
  95. title: intl.formatMessage({
  96. id: "forms.fields.publicity.label",
  97. }),
  98. dataIndex: "view",
  99. key: "view",
  100. width: 100,
  101. search: false,
  102. },
  103. {
  104. title: intl.formatMessage({
  105. id: "forms.fields.created-at.label",
  106. }),
  107. key: "created-at",
  108. width: 100,
  109. search: false,
  110. dataIndex: "createdAt",
  111. valueType: "date",
  112. sorter: (a, b) => a.createdAt - b.createdAt,
  113. },
  114. {
  115. title: intl.formatMessage({ id: "buttons.option" }),
  116. key: "option",
  117. width: 120,
  118. valueType: "option",
  119. render: (text, row, index, action) => {
  120. return [
  121. <Dropdown.Button
  122. key={index}
  123. type="link"
  124. menu={{
  125. items: [
  126. {
  127. key: "remove",
  128. disabled: true,
  129. danger: true,
  130. label: intl.formatMessage({
  131. id: "buttons.delete",
  132. }),
  133. icon: <DeleteOutlined />,
  134. },
  135. ],
  136. onClick: (e) => {
  137. switch (e.key) {
  138. case "remove":
  139. break;
  140. default:
  141. break;
  142. }
  143. },
  144. }}
  145. >
  146. <Link
  147. to={
  148. `/article/chapter/${row.book}-${row.paragraph}/edit` +
  149. channelId
  150. ? `?channel=${channelId}`
  151. : ""
  152. }
  153. >
  154. {intl.formatMessage({
  155. id: "buttons.edit",
  156. })}
  157. </Link>
  158. </Dropdown.Button>,
  159. ];
  160. },
  161. },
  162. ]}
  163. rowSelection={{
  164. // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
  165. // 注释该行则默认不显示下拉选项
  166. selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
  167. }}
  168. tableAlertRender={({
  169. selectedRowKeys,
  170. selectedRows,
  171. onCleanSelected,
  172. }) => (
  173. <Space size={24}>
  174. <span>
  175. {intl.formatMessage({ id: "buttons.selected" })}
  176. {selectedRowKeys.length}
  177. <Button
  178. type="link"
  179. style={{ marginInlineStart: 8 }}
  180. onClick={onCleanSelected}
  181. >
  182. {intl.formatMessage({ id: "buttons.unselect" })}
  183. </Button>
  184. </span>
  185. </Space>
  186. )}
  187. tableAlertOptionRender={() => {
  188. return (
  189. <Space size={16}>
  190. <Button type="link">
  191. {intl.formatMessage({
  192. id: "buttons.delete.all",
  193. })}
  194. </Button>
  195. </Space>
  196. );
  197. }}
  198. request={async (params = {}, sorter, filter) => {
  199. // TODO
  200. console.log(params, sorter, filter);
  201. const offset = (params.current || 1 - 1) * (params.pageSize || 20);
  202. const res = await get<IChapterListResponse>(
  203. `/v2/progress?view=chapter&channel=${channelId}&progress=0.01&offset=${offset}`
  204. );
  205. console.log(res.data.rows);
  206. const items: IItem[] = res.data.rows.map((item, id) => {
  207. const createdAt = new Date(item.created_at);
  208. const updatedAt = new Date(item.updated_at);
  209. return {
  210. sn: id + offset + 1,
  211. book: item.book,
  212. paragraph: item.para,
  213. view: item.view,
  214. title: item.title,
  215. subTitle: item.toc,
  216. summary: item.summary,
  217. path: item.path,
  218. progress: item.progress,
  219. createdAt: createdAt.getTime(),
  220. updatedAt: updatedAt.getTime(),
  221. };
  222. });
  223. return {
  224. total: res.data.count,
  225. succcess: true,
  226. data: items,
  227. };
  228. }}
  229. rowKey="id"
  230. bordered
  231. pagination={{
  232. showQuickJumper: true,
  233. showSizeChanger: true,
  234. }}
  235. search={false}
  236. options={{
  237. search: true,
  238. }}
  239. />
  240. );
  241. };
  242. export default Widget;