list.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. import { useParams } from "react-router-dom";
  2. import { ProTable } from "@ant-design/pro-components";
  3. import { useIntl } from "react-intl";
  4. import { Link } from "react-router-dom";
  5. import { Layout, Space, Table } from "antd";
  6. import { PlusOutlined } from "@ant-design/icons";
  7. import type { MenuProps } from "antd";
  8. import { Button, Dropdown, Menu, Popover } from "antd";
  9. import { SearchOutlined } from "@ant-design/icons";
  10. import ChannelCreate from "../../../components/studio/channel/ChannelCreate";
  11. import { get } from "../../../request";
  12. import { IApiResponseChannelList } from "../../../components/api/Channel";
  13. import { PublicityValueEnum } from "../../../components/studio/table";
  14. const onMenuClick: MenuProps["onClick"] = (e) => {
  15. console.log("click", e);
  16. };
  17. const menu = (
  18. <Menu
  19. onClick={onMenuClick}
  20. items={[
  21. {
  22. key: "1",
  23. label: "在藏经阁中打开",
  24. icon: <SearchOutlined />,
  25. },
  26. {
  27. key: "2",
  28. label: "分享",
  29. icon: <SearchOutlined />,
  30. },
  31. {
  32. key: "3",
  33. label: "删除",
  34. icon: <SearchOutlined />,
  35. },
  36. ]}
  37. />
  38. );
  39. interface IItem {
  40. id: number;
  41. uid: string;
  42. title: string;
  43. summary: string;
  44. type: string;
  45. publicity: number;
  46. createdAt: number;
  47. }
  48. const Widget = () => {
  49. const intl = useIntl();
  50. const { studioname } = useParams();
  51. const channelCreate = <ChannelCreate studio={studioname} />;
  52. return (
  53. <>
  54. <Layout>{studioname}</Layout>
  55. <ProTable<IItem>
  56. columns={[
  57. {
  58. title: intl.formatMessage({
  59. id: "dict.fields.sn.label",
  60. }),
  61. dataIndex: "id",
  62. key: "id",
  63. width: 50,
  64. search: false,
  65. },
  66. {
  67. title: intl.formatMessage({
  68. id: "forms.fields.title.label",
  69. }),
  70. dataIndex: "title",
  71. key: "title",
  72. tip: "过长会自动收缩",
  73. ellipsis: true,
  74. render: (text, row, index, action) => {
  75. return (
  76. <Link
  77. to={`/studio/${studioname}/channel/${row.uid}/edit`}
  78. >
  79. {row.title}
  80. </Link>
  81. );
  82. },
  83. },
  84. {
  85. title: intl.formatMessage({
  86. id: "forms.fields.summary.label",
  87. }),
  88. dataIndex: "summary",
  89. key: "summary",
  90. tip: "过长会自动收缩",
  91. ellipsis: true,
  92. },
  93. {
  94. title: intl.formatMessage({
  95. id: "forms.fields.type.label",
  96. }),
  97. dataIndex: "type",
  98. key: "type",
  99. width: 100,
  100. search: false,
  101. filters: true,
  102. onFilter: true,
  103. valueEnum: {
  104. all: {
  105. text: intl.formatMessage({
  106. id: "channel.type.all.title",
  107. }),
  108. status: "Default",
  109. },
  110. translation: {
  111. text: intl.formatMessage({
  112. id: "channel.type.translation.title",
  113. }),
  114. status: "Success",
  115. },
  116. nissaya: {
  117. text: intl.formatMessage({
  118. id: "channel.type.nissaya.title",
  119. }),
  120. status: "Processing",
  121. },
  122. commentary: {
  123. text: intl.formatMessage({
  124. id: "channel.type.commentary.title",
  125. }),
  126. status: "Default",
  127. },
  128. original: {
  129. text: intl.formatMessage({
  130. id: "channel.type.original.title",
  131. }),
  132. status: "Default",
  133. },
  134. general: {
  135. text: intl.formatMessage({
  136. id: "channel.type.general.title",
  137. }),
  138. status: "Default",
  139. },
  140. },
  141. },
  142. {
  143. title: intl.formatMessage({
  144. id: "forms.fields.publicity.label",
  145. }),
  146. dataIndex: "publicity",
  147. key: "publicity",
  148. width: 100,
  149. search: false,
  150. filters: true,
  151. onFilter: true,
  152. valueEnum: PublicityValueEnum(),
  153. },
  154. {
  155. title: intl.formatMessage({
  156. id: "forms.fields.created-at.label",
  157. }),
  158. key: "created-at",
  159. width: 100,
  160. search: false,
  161. dataIndex: "createdAt",
  162. valueType: "date",
  163. sorter: (a, b) => a.createdAt - b.createdAt,
  164. },
  165. {
  166. title: intl.formatMessage({ id: "buttons.option" }),
  167. key: "option",
  168. width: 120,
  169. valueType: "option",
  170. render: (text, row, index, action) => {
  171. return [
  172. <Dropdown.Button
  173. key={index}
  174. type="link"
  175. overlay={menu}
  176. >
  177. <Link
  178. to={`/studio/${studioname}/channel/${row.uid}/edit`}
  179. >
  180. {intl.formatMessage({
  181. id: "buttons.edit",
  182. })}
  183. </Link>
  184. </Dropdown.Button>,
  185. ];
  186. },
  187. },
  188. ]}
  189. rowSelection={{
  190. // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
  191. // 注释该行则默认不显示下拉选项
  192. selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
  193. }}
  194. tableAlertRender={({
  195. selectedRowKeys,
  196. selectedRows,
  197. onCleanSelected,
  198. }) => (
  199. <Space size={24}>
  200. <span>
  201. {intl.formatMessage({ id: "buttons.selected" })}
  202. {selectedRowKeys.length}
  203. <Button
  204. type="link"
  205. style={{ marginInlineStart: 8 }}
  206. onClick={onCleanSelected}
  207. >
  208. {intl.formatMessage({ id: "buttons.unselect" })}
  209. </Button>
  210. </span>
  211. </Space>
  212. )}
  213. tableAlertOptionRender={() => {
  214. return (
  215. <Space size={16}>
  216. <Button type="link">
  217. {intl.formatMessage({
  218. id: "buttons.delete.all",
  219. })}
  220. </Button>
  221. </Space>
  222. );
  223. }}
  224. request={async (params = {}, sorter, filter) => {
  225. // TODO
  226. console.log(params, sorter, filter);
  227. const res: IApiResponseChannelList = await get(
  228. `/v2/channel?view=studio&name=${studioname}`
  229. );
  230. const items: IItem[] = res.data.rows.map((item, id) => {
  231. const date = new Date(item.created_at);
  232. return {
  233. id: id,
  234. uid: item.uid,
  235. title: item.name,
  236. summary: item.summary,
  237. type: item.type,
  238. publicity: item.status,
  239. createdAt: date.getTime(),
  240. };
  241. });
  242. return {
  243. total: res.data.count,
  244. succcess: true,
  245. data: items,
  246. };
  247. }}
  248. rowKey="id"
  249. bordered
  250. pagination={{
  251. showQuickJumper: true,
  252. showSizeChanger: true,
  253. }}
  254. search={false}
  255. options={{
  256. search: true,
  257. }}
  258. toolBarRender={() => [
  259. <Popover
  260. content={channelCreate}
  261. title="new channel"
  262. placement="bottomRight"
  263. >
  264. <Button
  265. key="button"
  266. icon={<PlusOutlined />}
  267. type="primary"
  268. >
  269. {intl.formatMessage({ id: "buttons.create" })}
  270. </Button>
  271. </Popover>,
  272. ]}
  273. />
  274. </>
  275. );
  276. };
  277. export default Widget;