index.tsx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import React, {
  2. forwardRef,
  3. useCallback,
  4. useEffect,
  5. useImperativeHandle,
  6. useMemo,
  7. useState
  8. } from 'react'
  9. import styles from './index.module.scss'
  10. import { DatePicker, Form, FormInstance, Input, Table, TableProps } from 'antd'
  11. import ImageLazy from '../ImageLazy'
  12. import classNames from 'classnames'
  13. import { resJiLianFu } from '@/utils/history'
  14. interface MyTableProps extends Omit<TableProps, 'onChange'> {
  15. yHeight?: number //设置表格的高度
  16. list: any //表格数据
  17. columnsTemp: any[][] //表格展示
  18. total?: number //总数
  19. pageNum?: number
  20. pageSize?: number
  21. pagingInfo?: any | boolean
  22. onChange?: (pageNum: number, pageSize: number) => void
  23. lastBtn?: any //后面的操作按钮
  24. startBtn?: any
  25. classKey?: string //一个组件多次使用的时候要传递,分别设置style
  26. // 表格简单的合并
  27. merge?: { type: string; num: number; loc: 'rowSpan' | 'colSpan' }
  28. // 定制化表头
  29. myTitle?: { name: string; Com: React.ReactNode }
  30. // 为空的定制字段
  31. isNull?: string
  32. // 设置宽度
  33. widthSet?: any
  34. rowKey?: string
  35. readOnly?: boolean
  36. }
  37. export interface MyTableMethods {
  38. form: FormInstance<any>
  39. }
  40. const MyTable = forwardRef<MyTableMethods, MyTableProps>(
  41. (
  42. {
  43. yHeight,
  44. list,
  45. columnsTemp,
  46. total,
  47. pageNum = 1,
  48. pageSize = 10,
  49. pagingInfo = {
  50. showQuickJumper: true,
  51. position: ['bottomCenter'],
  52. showSizeChanger: true
  53. },
  54. onChange,
  55. lastBtn = [],
  56. startBtn = [],
  57. classKey = '',
  58. merge,
  59. myTitle,
  60. isNull = '(空)',
  61. widthSet,
  62. rowKey = 'id',
  63. readOnly,
  64. ...rest
  65. },
  66. ref
  67. ) => {
  68. // 点击操作高亮
  69. const [clickAc, setClickAc] = useState(0)
  70. const [form] = Form.useForm()
  71. // 表格内容定制化
  72. const tableComObj = useCallback(
  73. (key: string, val: string[], id?: any, backFu?: (id: number) => void) => {
  74. const obj = {
  75. // 超链接打开
  76. A: (
  77. <a href={val[1]} target='_blank' title={val[1]} rel='noreferrer'>
  78. {val[0]}
  79. </a>
  80. ),
  81. // 点击触发事件
  82. S: (
  83. <span
  84. className={classNames('MTclick', clickAc === id ? 'MTclickAc' : '')}
  85. onClick={() => {
  86. if (id && backFu) {
  87. backFu(id)
  88. setClickAc(id)
  89. }
  90. }}
  91. >
  92. {val[1]}
  93. </span>
  94. )
  95. }
  96. return Reflect.get(obj, key)
  97. },
  98. [clickAc]
  99. )
  100. useEffect(() => {
  101. const dom = document.querySelector(`.MyTable${classKey} .ant-table-body`) as HTMLDivElement
  102. if (dom && yHeight) dom.style.height = yHeight + 'px'
  103. }, [classKey, yHeight])
  104. // 页码变化
  105. const paginationChange = useCallback(
  106. () => (pageNum: number, pageSize: number) => {
  107. if (onChange) {
  108. onChange(pageNum, pageSize)
  109. }
  110. },
  111. [onChange]
  112. )
  113. const dataChangeFu = useCallback(
  114. (v: any) => {
  115. /**
  116. * index:序号
  117. * txt:正常数据
  118. * img:图片
  119. * txtChange:判断显示不同字段
  120. * text:文字比较多的情况
  121. */
  122. const obj = {
  123. index: (_: any, __: any, index: number) => index + 1 + (pageNum - 1) * pageSize,
  124. txt: (item: any) =>
  125. v[3] && !item[v[2]] ? (
  126. <div dangerouslySetInnerHTML={{ __html: v[3] }}></div>
  127. ) : (
  128. item[v[2]] || isNull
  129. ),
  130. // 多个字段拼接
  131. ping: (item: any) => (item[v[2]] || '') + (resJiLianFu(item[v[3]]) || '') || isNull,
  132. // 这个模块特有的级联控制
  133. txtC: (item: any) =>
  134. v[1] === '年代' && item[v[2]] === '其他' ? '其他' : resJiLianFu(item[v[2]]),
  135. // 尺寸
  136. size: (item: any) => {
  137. let danWei = resJiLianFu(item.sizeUnit, ' ')
  138. let txt1 = item.sizeL ? `通长${item.sizeL}` : ''
  139. let txt2 = item.sizeW ? `通宽${item.sizeW}` : ''
  140. let txt3 = item.sizeH ? `通高${item.sizeH}` : ''
  141. txt1 = txt1 ? txt1 + danWei : ''
  142. txt2 = txt2 ? txt2 + danWei : ''
  143. txt3 = txt3 ? txt3 + danWei : ''
  144. let arr = [txt1, txt2, txt3]
  145. arr = arr.filter(v => v)
  146. if (!txt1 && !txt2 && !txt3) return '(空)'
  147. else return arr.join(' - ')
  148. },
  149. img: (item: any) =>
  150. v[3] && !item[v[2]] ? (
  151. <div dangerouslySetInnerHTML={{ __html: v[3] }}></div>
  152. ) : (
  153. <div className='tableImgAuto'>
  154. <ImageLazy
  155. width={60}
  156. height={60}
  157. srcBig={item.thumbPc || item.filePath}
  158. src={item[v[2]] || item.thumb}
  159. offline={(item[v[2]] || item.thumb).includes('http')}
  160. />
  161. </div>
  162. ),
  163. txtChange: (item: any) => Reflect.get(v[3], item[v[2]]) || v[4] || isNull,
  164. text: (item: any) => {
  165. let tempCom: any = item[v[2]] || isNull
  166. if (tempCom.length >= v[3]) {
  167. tempCom = tempCom.substring(0, v[3]) + '...'
  168. }
  169. if (v[4]) {
  170. tempCom = tableComObj(v[4], [tempCom, item[v[2]]], item.id, v[5])
  171. } else if ((item[v[2]] || '').length >= v[3]) {
  172. tempCom = (
  173. <span style={{ cursor: 'pointer' }} title={item[v[2]]}>
  174. {tempCom}
  175. </span>
  176. )
  177. }
  178. return tempCom
  179. },
  180. input: (item: any) => {
  181. return (
  182. <Form.Item noStyle name={`${item.id}-${v[2]}`}>
  183. <Input
  184. allowClear
  185. readOnly={readOnly}
  186. maxLength={v[3]?.maxLength}
  187. placeholder={v[3]?.placeholder || '请输入'}
  188. />
  189. </Form.Item>
  190. )
  191. },
  192. datePicker: (item: any) => {
  193. return (
  194. <Form.Item noStyle name={`${item.id}-${v[2]}`}>
  195. <DatePicker readOnly={readOnly} />
  196. </Form.Item>
  197. )
  198. },
  199. custom: (item: any) => {
  200. return (
  201. <Form.Item noStyle name={`${item.id}-${v[2]}`}>
  202. {v[3].render(readOnly)}
  203. </Form.Item>
  204. )
  205. }
  206. }
  207. return Reflect.get(obj, v[0])
  208. },
  209. [isNull, pageNum, pageSize, readOnly, tableComObj]
  210. )
  211. const columns = useMemo(() => {
  212. const arr: any = columnsTemp.map((v: any) => ({
  213. title: myTitle && v.includes(myTitle.name) ? myTitle.Com : v[1],
  214. render: dataChangeFu(v),
  215. width: widthSet && Reflect.get(widthSet, v[2]) ? Reflect.get(widthSet, v[2]) : 'auto',
  216. onCell:
  217. merge && v.includes(merge.type)
  218. ? // {rowSpan:3}
  219. (item: any, index: number) => ({
  220. rowSpan: index === 0 ? merge.num : 0
  221. })
  222. : ''
  223. }))
  224. return arr
  225. }, [columnsTemp, dataChangeFu, merge, myTitle, widthSet])
  226. useImperativeHandle(ref, () => ({
  227. form
  228. }))
  229. return (
  230. <Form form={form} component={false}>
  231. <Table
  232. className={`${styles.MyTable} MyTable${classKey}`}
  233. scroll={{ y: yHeight ? yHeight : '' }}
  234. dataSource={list}
  235. columns={[...startBtn, ...columns, ...lastBtn]}
  236. rowKey={rowKey}
  237. pagination={
  238. pagingInfo
  239. ? {
  240. ...pagingInfo,
  241. current: pageNum,
  242. pageSize: pageSize,
  243. total: total,
  244. onChange: paginationChange()
  245. }
  246. : false
  247. }
  248. {...rest}
  249. />
  250. </Form>
  251. )
  252. }
  253. )
  254. const MemoMyTable = React.memo(MyTable)
  255. export default MemoMyTable