ChapterInChannelList.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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 { Button, Dropdown } from "antd";
  6. import { DeleteOutlined } from "@ant-design/icons";
  7. import { get } from "../../request";
  8. import { IChapterListResponse } from "../../components/api/Corpus";
  9. import { IArticleParam } from "../../pages/studio/recent/list";
  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. onSelect?: Function;
  27. }
  28. const ChpaterInChannelListWidget = ({ channelId, onSelect }: 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. <Button
  55. type="link"
  56. onClick={(event) => {
  57. if (typeof onSelect !== "undefined") {
  58. const chapter: IArticleParam = {
  59. type: "chapter",
  60. articleId: `${row.book}-${row.paragraph}`,
  61. mode: "read",
  62. channelId: channelId,
  63. };
  64. onSelect(event, chapter);
  65. }
  66. }}
  67. >
  68. {row.title ? row.title : row.subTitle}
  69. </Button>
  70. </div>
  71. <Text type="secondary" key={2}>
  72. {row.subTitle}
  73. </Text>
  74. </div>
  75. );
  76. },
  77. },
  78. {
  79. title: intl.formatMessage({
  80. id: "forms.fields.summary.label",
  81. }),
  82. dataIndex: "summary",
  83. key: "summary",
  84. tip: "过长会自动收缩",
  85. ellipsis: true,
  86. },
  87. {
  88. title: intl.formatMessage({
  89. id: "forms.fields.publicity.label",
  90. }),
  91. dataIndex: "progress",
  92. key: "progress",
  93. width: 100,
  94. search: false,
  95. render: (text, row, index, action) => {
  96. const per = Math.round(row.progress * 100);
  97. return <Progress percent={per} size="small" key={index} />;
  98. },
  99. },
  100. {
  101. title: intl.formatMessage({
  102. id: "forms.fields.publicity.label",
  103. }),
  104. dataIndex: "view",
  105. key: "view",
  106. width: 100,
  107. search: false,
  108. },
  109. {
  110. title: intl.formatMessage({
  111. id: "forms.fields.created-at.label",
  112. }),
  113. key: "created-at",
  114. width: 100,
  115. search: false,
  116. dataIndex: "createdAt",
  117. valueType: "date",
  118. sorter: (a, b) => a.createdAt - b.createdAt,
  119. },
  120. {
  121. title: intl.formatMessage({ id: "buttons.option" }),
  122. key: "option",
  123. width: 120,
  124. valueType: "option",
  125. render: (text, row, index, action) => {
  126. let editLink = `/article/chapter/${row.book}-${row.paragraph}?mode=edit`;
  127. editLink += channelId ? `&channel=${channelId}` : "";
  128. return [
  129. <Dropdown.Button
  130. key={index}
  131. type="link"
  132. menu={{
  133. items: [
  134. {
  135. key: "remove",
  136. disabled: true,
  137. danger: true,
  138. label: intl.formatMessage({
  139. id: "buttons.delete",
  140. }),
  141. icon: <DeleteOutlined />,
  142. },
  143. ],
  144. onClick: (e) => {
  145. switch (e.key) {
  146. case "remove":
  147. break;
  148. default:
  149. break;
  150. }
  151. },
  152. }}
  153. >
  154. <Link to={editLink}>
  155. {intl.formatMessage({
  156. id: "buttons.translate",
  157. })}
  158. </Link>
  159. </Dropdown.Button>,
  160. ];
  161. },
  162. },
  163. ]}
  164. request={async (params = {}, sorter, filter) => {
  165. // TODO
  166. console.log(params, sorter, filter);
  167. const offset = (params.current || 1 - 1) * (params.pageSize || 20);
  168. const res = await get<IChapterListResponse>(
  169. `/v2/progress?view=chapter&channel=${channelId}&progress=0.01&offset=${offset}`
  170. );
  171. console.log(res.data.rows);
  172. const items: IItem[] = res.data.rows.map((item, id) => {
  173. const createdAt = new Date(item.created_at);
  174. const updatedAt = new Date(item.updated_at);
  175. return {
  176. sn: id + offset + 1,
  177. book: item.book,
  178. paragraph: item.para,
  179. view: item.view,
  180. title: item.title,
  181. subTitle: item.toc,
  182. summary: item.summary,
  183. path: item.path,
  184. progress: item.progress,
  185. createdAt: createdAt.getTime(),
  186. updatedAt: updatedAt.getTime(),
  187. };
  188. });
  189. return {
  190. total: res.data.count,
  191. succcess: true,
  192. data: items,
  193. };
  194. }}
  195. rowKey="id"
  196. bordered
  197. pagination={{
  198. showQuickJumper: true,
  199. showSizeChanger: true,
  200. }}
  201. search={false}
  202. options={{
  203. search: true,
  204. }}
  205. />
  206. );
  207. };
  208. export default ChpaterInChannelListWidget;