index.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import CustomListModel from '@/components/CustomList'
  2. import Tables from '@/components/Tables'
  3. import { quanpin } from '@/utils/fullScreen'
  4. import { FullscreenExitOutlined, FullscreenOutlined, RedoOutlined, SettingOutlined, SyncOutlined } from '@ant-design/icons'
  5. import { Button, Card, Col, Row, Space, Spin, Tooltip, } from 'antd'
  6. import { ColumnsType } from 'antd/lib/table'
  7. import React, { useEffect, useRef, useState, useCallback } from 'react'
  8. import { useModel } from 'umi'
  9. import style from './index.less'
  10. interface Prosp {
  11. // sortArr?: { label: string, value: string ,key:any}[],//排序参数名列表
  12. isZj?: boolean,//是否查总计
  13. tableTotal?: { [key: string]: string },//是个开启总计
  14. scroll?: { x?: number, y?: number },//开启行滑动并设置容器最大宽度
  15. columns: () => ColumnsType<any>,//table列表配置
  16. title?: string,//tabel的标题
  17. tooltip?: JSX.Element,//是否在标题后加问号展示说明
  18. dataSource: any[],//table的数据
  19. expandedRowRender?: (data: any) => JSX.Element,
  20. className?: string,//自定义class
  21. isdownload?: boolean,
  22. leftChild?: JSX.Element,
  23. config?: any,
  24. configName?: any,
  25. page?: number,
  26. pageSize?: number,
  27. size?: 'small' | 'middle' | 'large',
  28. total?: number,
  29. loading?: boolean,
  30. onChange?: (props: {
  31. pagination?: { current?: number, pageSize?: number, gzh?: string },
  32. filters?: any,
  33. sortData?: {
  34. column: { dataIndex: string },
  35. order?: "ascend" | "descend"
  36. }
  37. }) => void,
  38. ajax?: any,//接口刷新
  39. syncAjax?: any,//同步
  40. hoverable?: boolean,
  41. rowSelection?: any,
  42. myKey?: any,//自定义使用哪个值做key
  43. fixed?: {
  44. left: number,
  45. right: number
  46. },
  47. }
  48. function TableData(props: Prosp) {
  49. const { isZj, scroll, columns, title, dataSource, expandedRowRender, className, leftChild, page = undefined, rowSelection = false, pageSize = undefined, size = 'small', fixed = { left: 0, right: 1 }, total = 0, loading = false, onChange, config, configName, ajax, syncAjax, hoverable = true, myKey } = props
  50. const { state: userState } = useModel('useOperating.useUser')
  51. const { isFell } = userState
  52. const [visible, setVisible] = useState<boolean>(false)
  53. const [oldSelectData, setoldSelectData] = useState<any[]>([])
  54. const [oldFixed, setoldFixed] = useState<any>({ left: '0', right: '0' })
  55. const [newColumns, setNewColumns] = useState<any[]>([])
  56. // const [oldConfigName, setOldConfigName] = useState<any>('')//上次的配置名称
  57. const [selectData, setSelectData] = useState<{ selectData: any[], fixed: { left: number, right: number } }>({ selectData: [], fixed: { left: fixed.left, right: fixed.right } })
  58. const [tiptopShow, setTipTopShow] = useState({//tiptop开关
  59. ajaxShow: false,
  60. syncAjaxShow: false,
  61. configShow: false,
  62. })
  63. const ref = useRef(null)
  64. const oldName = useRef(null)
  65. const version = '1.0.0'
  66. // // /**重组选中的字段 */
  67. useEffect(() => {
  68. let oldConfigName = oldName.current || ''
  69. if (configName) {
  70. // if (dataSource?.length > 0) {
  71. const defSelectData = localStorage.getItem(`myAdMonitorConfig${version}_` + configName)
  72. const defFixed = localStorage.getItem(`myAdMonitorConfigFixed${version}_` + configName)
  73. const newConfig = config?.map((item: { data: any }) => item.data)?.flat()
  74. if (defSelectData && (selectData?.selectData?.length === 0 || configName !== oldConfigName)) {//首次查找个人配置是否存在,并且selectData为空,存在用个人配置设置selectData
  75. console.log('首次使用个人配置赋值')
  76. let newDefSelectData = JSON.parse(defSelectData)
  77. newDefSelectData = newDefSelectData.filter((item: any) => !!item && newConfig.some((c: { dataIndex: any }) => c.dataIndex === item.dataIndex))//去除空项
  78. setSelectData(() => ({ selectData: newDefSelectData, fixed: defFixed ? JSON.parse(defFixed) : { left: 0, right: 0 } }))
  79. }
  80. if (!defSelectData && (selectData?.selectData?.length === 0 || configName !== oldConfigName)) {//首次查找个人配置是否存在,并且selectData为空,不存在默认配置设置selectData
  81. let newSelectData: any[] = []
  82. config?.forEach((item: { data: { default: any }[] }) => {
  83. item?.data?.forEach((d: { default: any }) => {
  84. if (d.default) {
  85. newSelectData[d.default - 1] = d
  86. }
  87. })
  88. })
  89. console.log('首次使用默认配置赋值')
  90. setSelectData(() => ({ ...selectData, selectData: newSelectData }))
  91. }
  92. if ((JSON.stringify(oldSelectData) !== JSON.stringify(selectData?.selectData)) || (JSON.stringify(selectData.fixed) !== JSON.stringify(oldFixed))) {
  93. console.log('设置配置改变重新赋值')
  94. setoldSelectData(() => selectData.selectData)
  95. setoldFixed(() => selectData.fixed)
  96. let newArr: any = []
  97. selectData?.selectData?.forEach((data: { dataIndex: any, width: number }, index: number) => {
  98. columns()?.forEach((item: any) => {
  99. if (data.dataIndex === item.dataIndex) {
  100. if (index < Number(selectData?.fixed?.left)) {//设置左悬浮
  101. item['fixed'] = 'left'
  102. } else if (index > (selectData?.selectData?.length - Number(selectData?.fixed?.right) - 1)) {//设置右悬浮
  103. item['fixed'] = 'right'
  104. } else {
  105. item['fixed'] = false
  106. }
  107. if (data?.width) {
  108. item['width'] = data.width
  109. }
  110. newArr.push(item)
  111. }
  112. })
  113. })
  114. setNewColumns(() => newArr)
  115. }
  116. }
  117. if (configName !== oldConfigName) {
  118. oldName.current = configName
  119. }
  120. }, [selectData, oldSelectData, dataSource, oldFixed, configName, config, columns]) // selectData, oldSelectData, dataSource, oldFixed, configName, oldConfigName, config, columns
  121. //拖动宽度设置设置保存
  122. const handelResize = useCallback((columns: any) => {
  123. if (configName) {
  124. let newSelectData = selectData?.selectData?.map((item, index) => {
  125. item['width'] = columns[index]['width']
  126. return item
  127. })
  128. localStorage.setItem(`myAdMonitorConfig${version}_` + configName, JSON.stringify(newSelectData))
  129. }
  130. }, [configName, selectData])
  131. // 初始展示TIPTOP提示功能
  132. useEffect(() => {
  133. let time: any = null
  134. function timeOut(arg: any) {
  135. return new Promise((res, rel) => {
  136. time = setTimeout(() => {
  137. setTipTopShow({ ...tiptopShow, ...arg })
  138. res(true)
  139. }, 3000)
  140. })
  141. }
  142. async function isShow() {
  143. if (ajax) {
  144. setTipTopShow({ ...tiptopShow, ajaxShow: true })
  145. await timeOut({ ajaxShow: false })
  146. }
  147. if (syncAjax) {
  148. setTipTopShow({ ...tiptopShow, syncAjaxShow: true })
  149. await timeOut({ syncAjaxShow: false })
  150. }
  151. if (config) {
  152. setTipTopShow({ ...tiptopShow, configShow: true })
  153. await timeOut({ configShow: false })
  154. }
  155. }
  156. isShow()
  157. return () => {
  158. clearTimeout(time)
  159. time = null
  160. }
  161. }, [])
  162. const header = <Col span={24}>
  163. <Row gutter={[0, 10]}>
  164. <Col span={24} style={{
  165. display: 'flex',
  166. justifyContent: 'space-between',
  167. alignItems: 'end'
  168. }}>
  169. <Space>
  170. {leftChild}
  171. </Space>
  172. {/*紧凑*/}
  173. <div style={{ float: 'right', display: 'flex', flexFlow: 'row' }}>
  174. {
  175. ajax && <Button
  176. size='small'
  177. type='text'
  178. style={{ display: 'flex', alignItems: 'center' }}
  179. onClick={() => {
  180. ajax.refresh()
  181. }}>
  182. <span style={{ fontSize: 10, color: '#999' }}>刷新时间:{ajax?.data?.reqTime}</span>
  183. <Tooltip
  184. title='刷新'
  185. visible={tiptopShow.ajaxShow}
  186. onVisibleChange={(visible) => {
  187. setTipTopShow({ ...tiptopShow, ajaxShow: visible })
  188. }}
  189. ><RedoOutlined style={{ color: '#2196f3', fontSize: 17 }} /></Tooltip>
  190. </Button>
  191. }
  192. {
  193. syncAjax && <Button
  194. size='small'
  195. type='text'
  196. style={{ display: 'flex', alignItems: 'center' }}
  197. onClick={() => {
  198. syncAjax()
  199. }}>
  200. <Tooltip
  201. title='同步最新'
  202. visible={tiptopShow.syncAjaxShow}
  203. onVisibleChange={(visible) => {
  204. setTipTopShow({ ...tiptopShow, syncAjaxShow: visible })
  205. }}
  206. ><SyncOutlined style={{ color: 'red', fontSize: 17 }} /></Tooltip>
  207. </Button>
  208. }
  209. {config && <Button
  210. size='small'
  211. type='text'
  212. style={{ display: 'flex', alignItems: 'center' }}
  213. onClick={() => {
  214. setVisible(true)
  215. }}>
  216. <Tooltip title='设置'><SettingOutlined /></Tooltip>
  217. </Button>}
  218. <Button
  219. type='text'
  220. size='small'
  221. style={{ display: 'flex', alignItems: 'center' }}
  222. onClick={() => {
  223. if (ref?.current) {
  224. quanpin(ref?.current)
  225. }
  226. }}>
  227. {
  228. <Tooltip title={!isFell ? '全屏' : '退出全屏'}>{!isFell ? <FullscreenOutlined /> : <FullscreenExitOutlined />}</Tooltip>
  229. }
  230. </Button>
  231. {visible && <CustomListModel sysFixed={fixed} version={version} config={config} configName={configName} visible={visible} onClose={() => { setVisible(false) }} onChange={(arr: any) => { if (arr) { setSelectData({ selectData: [], fixed: { left: fixed.left, right: fixed.right } }) } else { setSelectData({ selectData: [], fixed: { left: fixed.left, right: fixed.right } }) } }} columns={newColumns} />}
  232. </div>
  233. </Col>
  234. </Row>
  235. </Col>
  236. const content = <Row gutter={[0, 20]} ref={ref} style={isFell ? { background: '#fff' } : {}}>
  237. {/**table */}
  238. <Col span={24}>
  239. <Card
  240. hoverable={hoverable}
  241. title={title}
  242. headStyle={{ textAlign: 'left' }}
  243. >
  244. <Row gutter={[0, 20]}>
  245. {header}
  246. <Tab {...{ size, newColumns, handelResize, className, isZj, rowSelection, columns, loading, scroll, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey }} />
  247. </Row>
  248. </Card>
  249. </Col>
  250. </Row >
  251. return <>
  252. {content}
  253. </>
  254. }
  255. /**表格 */
  256. const Tab = React.memo((props: any) => {
  257. const { size, newColumns, className, handelResize, columns, scroll, loading, rowSelection, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey } = props
  258. return < Col span={24} >
  259. <div className={`${style[size]} ${className ? style[className] : ''} `}>
  260. {dataSource || !ajax?.loading ? <Tables
  261. className={`all_table ${className ? className : ''}`}
  262. bordered
  263. sortDirections={['ascend', 'descend', null]}
  264. current={page}
  265. pageSize={pageSize}
  266. columns={newColumns?.length > 0 ? newColumns : columns()}
  267. dataSource={dataSource}
  268. scroll={scroll ? isFell ? { ...scroll, y: document.body.clientHeight - 300 } : scroll : {}}
  269. onChange={(pagination: any, filters: any, sorter: any) => onChange && onChange({ pagination, filters, sortData: sorter })}
  270. rowClassName={(record: { color: string }) => style[record['color']]}
  271. expandedRowRender={expandedRowRender ? expandedRowRender : undefined}
  272. size={size}
  273. total={total}
  274. loading={loading}
  275. defaultPageSize={20}
  276. rowSelection={rowSelection}
  277. handelResize={((columns: any) => handelResize(columns))}
  278. myKey={myKey}
  279. /> : <div className={style.example}>
  280. <Spin />
  281. </div>}
  282. </div>
  283. </Col >
  284. })
  285. export default React.memo(TableData)