resizable.jsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import React, { useState, useMemo } from 'react';
  2. import { Table, Avatar } from '@douyinfe/semi-ui';
  3. import { DndProvider, DragSource, DropTarget } from 'react-dnd';
  4. import HTML5Backend from 'react-dnd-html5-backend';
  5. let draggingIndex = -1;
  6. const PAGE_SIZE = 5;
  7. const DAY = 24 * 60 * 60 * 1000;
  8. const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
  9. function BodyRow(props) {
  10. const { isOver, connectDragSource, connectDropTarget, moveRow, currentPage, ...restProps } = props;
  11. const style = { ...restProps.style, cursor: 'move' };
  12. let { className } = restProps;
  13. if (isOver) {
  14. console.log('true');
  15. if (restProps.index > draggingIndex) {
  16. className += ' drop-over-downward';
  17. }
  18. if (restProps.index < draggingIndex) {
  19. className += ' drop-over-upward';
  20. }
  21. }
  22. return connectDragSource(connectDropTarget(<tr {...restProps} className={className} style={style} />));
  23. }
  24. const rowSource = {
  25. beginDrag(props) {
  26. draggingIndex = props.index;
  27. return {
  28. index: props.index,
  29. };
  30. },
  31. };
  32. const rowTarget = {
  33. drop(props, monitor) {
  34. const dragIndex = monitor.getItem().index;
  35. const hoverIndex = props.index;
  36. if (dragIndex === hoverIndex) {
  37. return;
  38. }
  39. props.moveRow(dragIndex, hoverIndex);
  40. monitor.getItem().index = hoverIndex;
  41. },
  42. };
  43. const DraggableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
  44. connectDropTarget: connect.dropTarget(),
  45. isOver: monitor.isOver(),
  46. }))(
  47. DragSource('row', rowSource, connect => ({
  48. connectDragSource: connect.dragSource(),
  49. }))(BodyRow)
  50. );
  51. const columns = [
  52. {
  53. title: '标题',
  54. dataIndex: 'name',
  55. width: 400,
  56. render: (text, record, index) => {
  57. return (
  58. <div>
  59. <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
  60. {text}
  61. </div>
  62. );
  63. },
  64. filters: [
  65. {
  66. text: 'Semi Design 设计稿',
  67. value: 'Semi Design 设计稿',
  68. },
  69. {
  70. text: 'Semi Pro 设计稿',
  71. value: 'Semi Pro 设计稿',
  72. },
  73. ],
  74. onFilter: (value, record) => record.name.includes(value),
  75. },
  76. {
  77. title: '大小',
  78. dataIndex: 'size',
  79. width: 200,
  80. sorter: (a, b) => a.size - b.size > 0 ? 1 : -1,
  81. render: (text) => `${text} KB`
  82. },
  83. {
  84. title: '所有者',
  85. width: 200,
  86. dataIndex: 'owner',
  87. render: (text, record, index) => {
  88. return (
  89. <div>
  90. <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>{typeof text === 'string' && text.slice(0, 1)}</Avatar>
  91. {text}
  92. </div>
  93. );
  94. }
  95. },
  96. {
  97. title: '更新日期',
  98. dataIndex: 'updateTime',
  99. sorter: (a, b) => a.updateTime - b.updateTime > 0 ? 1 : -1,
  100. render: (value) => {
  101. return dateFns.format(new Date(value), 'yyyy-MM-dd');
  102. }
  103. }
  104. ];
  105. const initData = [];
  106. for (let i = 0; i < 46; i++) {
  107. const isSemiDesign = i % 2 === 0;
  108. const randomNumber = (i * 1000) % 199;
  109. initData.push({
  110. key: '' + i,
  111. name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi Pro 设计稿${i}.fig`,
  112. owner: isSemiDesign ? '姜鹏志' : '郝宣',
  113. size: randomNumber,
  114. updateTime: new Date().valueOf() + randomNumber * DAY,
  115. avatarBg: isSemiDesign ? 'grey' : 'red'
  116. });
  117. }
  118. function DragSortingTableDemo(props) {
  119. const [data, setData] = useState([...initData]);
  120. const [currentPage, setCurrentPage] = useState(1);
  121. const [pageData, setPageData] = useState(data.slice(0, PAGE_SIZE));
  122. const components = useMemo(() => ({
  123. body: {
  124. row: DraggableBodyRow,
  125. },
  126. }), []);
  127. const moveRow = (dragIndex, hoverIndex) => {
  128. const totalDragIndex = (currentPage - 1) * PAGE_SIZE + dragIndex;
  129. const totalHoverIndex = (currentPage - 1) * PAGE_SIZE + hoverIndex;
  130. const dragRow = data[totalDragIndex];
  131. const newData = [...data];
  132. newData.splice(totalDragIndex, 1);
  133. newData.splice(totalHoverIndex, 0, dragRow);
  134. setData(newData);
  135. setPageData(newData.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE));
  136. };
  137. const handlePageChange = (pageNum) => {
  138. console.log(pageNum);
  139. setCurrentPage(pageNum);
  140. setPageData(data.slice((pageNum - 1) * PAGE_SIZE, pageNum * PAGE_SIZE));
  141. };
  142. return (
  143. <div id="components-table-demo-drag-sorting">
  144. <DndProvider backend={HTML5Backend}>
  145. <Table
  146. columns={columns}
  147. dataSource={pageData}
  148. pagination={{
  149. pageSize: PAGE_SIZE,
  150. total: data.length,
  151. currentPage,
  152. onPageChange: handlePageChange
  153. }}
  154. components={components}
  155. onRow={(record, index) => ({
  156. index,
  157. moveRow,
  158. })}
  159. />
  160. </DndProvider>
  161. </div>
  162. );
  163. }
  164. render(DragSortingTableDemo);