You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
8.5 KiB

12 months ago
  1. import React, {
  2. useState,
  3. forwardRef,
  4. useImperativeHandle,
  5. useRef,
  6. ReactNode,
  7. FC
  8. } from 'react'
  9. import { Table } from 'antd'
  10. import useService from '@/utils/tableHook'
  11. import SearchView from '@/components/SearchForm'
  12. /**
  13. *
  14. * @param {RefType} ref
  15. * @param {object[]} columns
  16. * @param {function} apiFun
  17. * @param {object[]} searchConfigList
  18. * @param {function} beforeSearch
  19. * @param {function} onFieldsChange
  20. * @param {object} extraProps
  21. * @param {function} onSelectRow
  22. * @param {string} rowKey key
  23. * @param {function} sortConfig
  24. * @param {function} expandedRowRender
  25. * @param {function} onExpand
  26. * @param {string} rowClassName
  27. * @param {boolean} small
  28. * @param {string[]} extraPagation
  29. */
  30. interface TableProps {
  31. columns: object[];
  32. apiFun: (arg0?: unknown[]) => Promise<{}>;
  33. ref?: RefType;
  34. searchConfigList?: object[];
  35. extraProps?: object;
  36. rowKey?: string;
  37. rowClassName?: string;
  38. small?: boolean;
  39. showHeader?: boolean;
  40. extraPagation?: string[];
  41. beforeSearch?: (arg0?: unknown) => void;
  42. onSelectRow?: (arg0?: string[], arg1?: string[]) => void;
  43. onFieldsChange?: (arg0?: unknown, arg1?: unknown) => void;
  44. sortConfig?: (arg0?: object) => any;
  45. expandedRowRender?: () => ReactNode;
  46. onExpand?: () => void;
  47. header?: JSX.Element
  48. }
  49. const MyTable: FC<TableProps> = forwardRef(
  50. (props: TableProps, ref: RefType) => {
  51. /**
  52. * @forwardRef
  53. * ref实例
  54. * ref绑定到子组件自身的节点上.
  55. */
  56. const searchForm: RefType = useRef(null)
  57. const {
  58. columns,
  59. apiFun,
  60. searchConfigList,
  61. extraProps,
  62. rowKey,
  63. rowClassName,
  64. small,
  65. showHeader,
  66. extraPagation,
  67. beforeSearch,
  68. onSelectRow,
  69. onFieldsChange,
  70. sortConfig,
  71. expandedRowRender,
  72. onExpand,
  73. header
  74. } = props
  75. // 搜索参数,如果有特殊需要处理的参数,就处理
  76. const searchObj = searchConfigList.reduce(
  77. (prev: CommonObjectType, next: CommonObjectType) => {
  78. return Object.assign(prev, {
  79. [next.key]: next.fn ? next.fn(next.initialValue) : next.initialValue
  80. })
  81. },
  82. {}
  83. )
  84. // 初始参数
  85. const initParams = {
  86. ...searchObj,
  87. ...extraProps,
  88. page: 1,
  89. page_size: 20
  90. }
  91. // 多选框的选择值
  92. const [selectedKeys, setSelectedKeys] = useState([])
  93. // 列表所有的筛选参数(包括搜索、分页、排序等)
  94. const [tableParams, setTableParams] = useState(initParams)
  95. // 列表搜索参数
  96. const [searchParams, setSearchParams] = useState(searchObj)
  97. // 列表排序参数
  98. const [sortParams, setSortParams] = useState({})
  99. // 列表分页参数
  100. const [curPageNo, setCurPageNo] = useState(initParams.page)
  101. const [curPageSize, setCurPageSize] = useState(initParams.page_size)
  102. const { loading = false, response = {} }: CommonObjectType = useService(
  103. apiFun,
  104. tableParams
  105. );
  106. let tableData = [];
  107. let total = 0;
  108. const validData = response?.data ? response.data : [];
  109. if (Array.isArray(validData) && validData.length >= 0) {
  110. tableData = validData;
  111. total = validData.length;
  112. }
  113. if (validData.rows) {
  114. tableData = validData.rows;
  115. total = validData.total;
  116. }
  117. // const validData = response?.data ? response.data : {}
  118. // const { rows: tableData = [], total } = validData
  119. // 执行搜索操作
  120. const handleSearch = (val: CommonObjectType): void => {
  121. if (val.login) {
  122. val.login = Number(val.login)
  123. }
  124. const obj = {
  125. ...val
  126. }
  127. if (Array.isArray(obj.chain_id)) {
  128. obj.chain_id = Number(obj.chain_id[0])
  129. }
  130. setSearchParams(obj)
  131. setTableParams({ ...tableParams, ...obj, page: 1 })
  132. }
  133. // 重置列表部分状态
  134. const resetAction = (page?: number): void => {
  135. setSelectedKeys([])
  136. const nextPage = page || curPageNo
  137. const nextParmas = page === 1 ? {} : { ...searchParams, ...sortParams }
  138. setCurPageNo(nextPage)
  139. setTableParams({
  140. ...initParams,
  141. ...nextParmas,
  142. page: nextPage,
  143. page_size: curPageSize
  144. })
  145. }
  146. // 列表复选框选中变化
  147. const onSelectChange = (
  148. selectedRowKeys: any[],
  149. selectedRows: any[]
  150. ): void => {
  151. setSelectedKeys(selectedRowKeys)
  152. onSelectRow(selectedRowKeys, selectedRows)
  153. }
  154. // 复选框配置
  155. const rowSelection = {
  156. selectedRowKeys: selectedKeys,
  157. onChange: onSelectChange
  158. }
  159. // 判断是否有复选框显示
  160. const showCheckbox = onSelectRow ? { rowSelection } : {}
  161. // 展开配置
  162. const expendConfig = {
  163. expandedRowRender,
  164. onExpand,
  165. rowClassName
  166. }
  167. // 判断是否有展开行
  168. const showExpend = expandedRowRender ? expendConfig : {}
  169. // 表格和分页的大小
  170. const tableSize = small ? 'small' : 'middle'
  171. const pagationSize = small ? 'small' : 'default'
  172. // 分页、筛选、排序变化时触发
  173. const onTableChange = (
  174. pagination: CommonObjectType,
  175. filters: CommonObjectType,
  176. sorter: object
  177. ): void => {
  178. // 如果有sort排序并且sort参数改变时,优先排序
  179. const sortObj = sortConfig ? sortConfig(sorter) : {}
  180. setSortParams(sortObj)
  181. const { current: page, pageSize } = pagination
  182. setCurPageNo(page)
  183. setCurPageSize(pageSize)
  184. setTableParams({
  185. ...initParams,
  186. ...searchParams,
  187. ...sortObj,
  188. page,
  189. page_size: pageSize
  190. })
  191. }
  192. /**
  193. * @useImperativeHandle
  194. * forwardRef引用父组件的ref实例
  195. * ,
  196. */
  197. useImperativeHandle(ref, () => ({
  198. // 更新列表
  199. update(page?: number): void {
  200. resetAction(page)
  201. },
  202. // 更新列表,并重置搜索字段
  203. resetForm(page?: number): void {
  204. if (searchForm.current) searchForm.current.resetFields()
  205. setSearchParams({})
  206. resetAction(page)
  207. },
  208. // 仅重置搜索字段
  209. resetField(field?: string[]): void {
  210. return field
  211. ? searchForm.current.resetFields([...field])
  212. : searchForm.current.resetFields()
  213. },
  214. // 获取当前列表数据
  215. getTableData(): CommonObjectType[] {
  216. return tableData
  217. }
  218. }))
  219. return (
  220. <div>
  221. {/* 搜索栏 */}
  222. {searchConfigList.length > 0 && (
  223. <div style={{ display: 'flex', justifyContent: 'space-between' }}>
  224. <SearchView
  225. ref={searchForm}
  226. config={searchConfigList}
  227. beforeSearch={beforeSearch}
  228. handleSearch={handleSearch}
  229. onFieldsChange={onFieldsChange}
  230. />
  231. {header}
  232. </div>
  233. )}
  234. {
  235. header && searchConfigList.length <= 0 && <div>{header}</div>
  236. }
  237. {/* 列表 */}
  238. <Table
  239. {...showCheckbox}
  240. {...showExpend}
  241. rowKey={rowKey}
  242. loading={loading}
  243. dataSource={tableData}
  244. columns={columns}
  245. onChange={onTableChange}
  246. size={tableSize}
  247. showHeader={showHeader}
  248. scroll={{ x: 1800 }}
  249. pagination={{
  250. size: pagationSize,
  251. total,
  252. pageSize: tableParams.page_size,
  253. current: tableParams.page,
  254. showQuickJumper: true,
  255. showSizeChanger: true,
  256. pageSizeOptions: ['20', '50', '100', '200', ...extraPagation],
  257. showTotal: (all) => `${all}`
  258. }}
  259. />
  260. </div>
  261. )
  262. }
  263. )
  264. MyTable.defaultProps = {
  265. searchConfigList: [],
  266. ref: null,
  267. extraProps: {},
  268. rowKey: 'id',
  269. rowClassName: '',
  270. small: false,
  271. showHeader: true,
  272. extraPagation: [],
  273. beforeSearch: () => { },
  274. onSelectRow: () => { },
  275. onFieldsChange: () => { },
  276. sortConfig: () => { },
  277. expandedRowRender: null,
  278. onExpand: () => { }
  279. }
  280. export default MyTable