index.tsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import React, { ReactNode ,useEffect, useRef, useState} from 'react'
  2. import { Table, Tag, message } from 'antd';
  3. import { Excle } from '@/utils/Excle'
  4. import style from './index.less'
  5. import './index.less'
  6. import { Resizable } from 'react-resizable'
  7. import { SortOrder } from 'antd/lib/table/interface';
  8. const ResizableHeader = (props: { [x: string]: any; onResize: any; width: any }) => {
  9. const { onResize, width, ...restProps } = props;
  10. if (!width) {
  11. return <th {...restProps} />
  12. }
  13. return <Resizable width={width} height={0} onResize={onResize} draggableOpts={{enableUserSelectHack:false}}>
  14. <th {...restProps} />
  15. </Resizable>
  16. }
  17. /**
  18. * https://ant-design.gitee.io/components/table-cn/#API
  19. */
  20. interface Props {
  21. dataSource: any[],
  22. columns: any[],
  23. excle?: {
  24. fillName: string,//文件名称
  25. filter?: string[]//需要排除的数据,输入数据key
  26. },
  27. total?: number,
  28. current?: number,
  29. pageSize?: number,
  30. rowSelection?: any,//选择
  31. onRow?: {//行操作事件
  32. onClick?: (event?: any) => void, // 点击行
  33. onDoubleClick?: (event?: any) => void,
  34. onContextMenu?: (event?: any) => void,
  35. onMouseEnter?: (event?: any) => void, // 鼠标移入行
  36. onMouseLeave?: (event?: any) => void,
  37. }
  38. pageChange?: (page: number, pageSize?: number) => void,
  39. sizeChange?: (current: number, size?: number) => void,
  40. rowClassName?: string | ((record: any, index: any) => string),//样式
  41. expandedRowRender?: any,//子table
  42. scroll?: { x?: number, y?: number },
  43. summary?: (data: readonly any[]) => ReactNode,
  44. size?: 'small' | 'middle' | 'large',
  45. loading?: boolean,
  46. defaultPageSize?: 10 | 20 | 30 | 100,
  47. bordered?: boolean,
  48. onChange?: (pagination: any, filters: any, sorter: any) => void//服务端排序回调
  49. pagination?: boolean,
  50. showHeader?: boolean,
  51. hideOnSinglePage?: boolean,
  52. className?: string,
  53. handelResize?:(columns:any)=>void//当表头被拖动改变宽度时回调设置对应的本地保存
  54. sortDirections?: SortOrder[],
  55. isShowTotal?: boolean, // 是否展示总计
  56. }
  57. function Tables(props: Props) {
  58. // //导出数据
  59. let { columns, dataSource, excle, total,handelResize, rowSelection, onRow, isShowTotal = true, hideOnSinglePage, rowClassName, className, expandedRowRender, scroll, summary, showHeader = true, bordered, size = 'small', onChange, sortDirections, pagination, ...prop } = props
  60. let handleExcle = () => {
  61. if (dataSource.length < 1) {
  62. message.error('请先搜索再导出');
  63. return
  64. }
  65. let thName: any = {};
  66. let obj = columns;
  67. obj.forEach((item: any) => {
  68. thName[item.key] = item.title
  69. })
  70. let fillName = excle?.fillName || ''
  71. let filter = excle?.filter || []
  72. Excle(thName, dataSource, fillName, filter)
  73. }
  74. let ww = document.body.clientWidth < 415
  75. // 拖动宽逻辑
  76. const [cols,setCols] = useState<any>(columns)
  77. const colsRef = useRef<any[]>([])
  78. const components={
  79. header:{
  80. cell:ResizableHeader
  81. }
  82. }
  83. useEffect(()=>{
  84. setCols(columns)
  85. },[columns])
  86. const handleResize=(index:any)=>(e:any,{size}:any)=>{
  87. const nextColumns=[...cols]
  88. nextColumns[index]={
  89. ...nextColumns[index],
  90. width:size.width
  91. }
  92. setCols(nextColumns)
  93. handelResize && handelResize(nextColumns)
  94. }
  95. colsRef.current = (cols||[]).map((col:any,index:any)=>({
  96. ...col,
  97. onHeaderCell:(column:any)=>({
  98. width:column.width,
  99. onResize:handleResize(index)
  100. })
  101. }))
  102. return <div className='components-table-resizable-column'>
  103. {
  104. excle && <Tag color='#f50' style={{ margin: '10px 0', float: 'right' }} onClick={handleExcle}><a>导出数据</a></Tag>
  105. }
  106. <Table
  107. components={components}
  108. columns={colsRef?.current}
  109. sortDirections={sortDirections || ['descend', 'ascend', null]}
  110. onChange={(pagination, filters, sorter) => {
  111. onChange && onChange(pagination, filters, sorter)
  112. }}
  113. bordered={bordered ? bordered : false}
  114. dataSource={dataSource}
  115. showHeader={showHeader}
  116. scroll={scroll ? { ...scroll, scrollToFirstRowOnChange: true } : undefined}
  117. size={size}
  118. rowKey={(a: any) => {
  119. return (JSON.stringify(a?.id) || JSON.stringify(a?.key))
  120. }}
  121. rowSelection={rowSelection ? rowSelection : undefined}
  122. onRow={record => {
  123. return {
  124. onClick: onRow?.onClick && onRow?.onClick.bind('', record) || undefined,
  125. }
  126. }}
  127. // rowClassName={(record: any) => {
  128. // if (rowClassName && record[rowClassName as string] === 2) {
  129. // return style.unfollow
  130. // }
  131. // if (rowClassName && !record[rowClassName as string]) {
  132. // return style.unfollow
  133. // }
  134. // }
  135. // }
  136. // rowClassName={rowClassName}
  137. summary={summary}
  138. className={className}
  139. expandable={expandedRowRender ? {
  140. defaultExpandedRowKeys: ['0'],
  141. expandRowByClick: true, expandedRowRender: (data) => {
  142. return expandedRowRender(data)
  143. }
  144. } : {}}
  145. pagination={
  146. {
  147. total: total || 0,//总共多少条数据,服务器给,设置后分页自动计算页数
  148. current: props.current,//当前页数,需state控制配合翻页
  149. pageSize: props?.pageSize,
  150. defaultCurrent: 1,//默认初始的当前页数
  151. defaultPageSize: props?.defaultPageSize || 20,//默认初始的每页条数
  152. pageSizeOptions: ['10', '20', '30', '40', '50', '60', '70', '80', '90', '100'],
  153. showTotal: (total) => isShowTotal ? <Tag color="cyan">总共{total}数据</Tag> : null,
  154. showSizeChanger: true, //手动开启条数筛选器,默认超过50条开启
  155. // size:'small',//设置分页尺寸
  156. //responsive:true,//当 size 未指定时,根据屏幕宽度自动调整尺寸
  157. onChange: props.pageChange, //点击页码或条数筛选时触发获取当前页数和每页条数
  158. onShowSizeChange: props.sizeChange,//点击条数筛选器触发
  159. simple: ww ? true : false,//开启简单分页
  160. hideOnSinglePage: hideOnSinglePage ? hideOnSinglePage : false,//只有一页数据隐藏分页
  161. showLessItems: true
  162. }
  163. }
  164. {...prop}
  165. {...{
  166. rowClassName: typeof rowClassName === 'string' ? (record: any) => {
  167. if (rowClassName && record[rowClassName as string] === 2) {
  168. return style.unfollow
  169. }
  170. if (rowClassName && !record[rowClassName as string]) {
  171. return style.unfollow
  172. }
  173. } : rowClassName
  174. }
  175. }
  176. />
  177. </div>
  178. }
  179. export default Tables