ChapterInChannelList.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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";
  5. import { Button, Dropdown } from "antd";
  6. import { DeleteOutlined } from "@ant-design/icons";
  7. import { get } from "../../request";
  8. import type { IChapterListResponse } from "../../api/Corpus";
  9. import type { 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. created_at: string;
  22. updated_at: string;
  23. }
  24. interface IWidget {
  25. channelId?: string;
  26. onSelect?: Function;
  27. }
  28. const ChapterInChannelListWidget = ({ 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. tooltip: "过长会自动收缩",
  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. tooltip: "过长会自动收缩",
  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: "created_at",
  117. valueType: "date",
  118. sorter: false,
  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. return {
  174. sn: id + offset + 1,
  175. book: item.book,
  176. paragraph: item.para,
  177. view: item.view,
  178. title: item.title,
  179. subTitle: item.toc,
  180. summary: item.summary,
  181. path: item.path,
  182. progress: item.progress,
  183. created_at: item.created_at,
  184. updated_at: item.updated_at,
  185. };
  186. });
  187. return {
  188. total: res.data.count,
  189. succcess: true,
  190. data: items,
  191. };
  192. }}
  193. rowKey="id"
  194. bordered
  195. pagination={{
  196. showQuickJumper: true,
  197. showSizeChanger: true,
  198. }}
  199. search={false}
  200. options={{
  201. search: true,
  202. }}
  203. />
  204. );
  205. };
  206. export default ChapterInChannelListWidget;