index.tsx 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
  2. import styles from './index.module.scss'
  3. import { useDispatch, useSelector } from 'react-redux'
  4. import { Z1_APIdel, Z1_APIgetDict } from '@/store/action/Z1dict'
  5. import { RootState } from '@/store'
  6. import { Button, Cascader, Input, Tree, TreeDataNode } from 'antd'
  7. import { treeResIdFu, Z1toTowFu } from './data'
  8. import { TypeZ1dict } from './type'
  9. import Z1add, { Z1AddInfoType } from './Z1add'
  10. import MyPopconfirm from '@/components/MyPopconfirm'
  11. import { MessageFu } from '@/utils/message'
  12. import { filterTreeByName } from '@/utils/history'
  13. function Z1dict() {
  14. const [loding, setLoding] = useState(false)
  15. const dispatch = useDispatch()
  16. useEffect(() => {
  17. dispatch(Z1_APIgetDict())
  18. }, [dispatch])
  19. // 级联改变
  20. const [topId, setTopId] = useState(['10000', '12000'])
  21. // 传给新增、编辑子组件(没有数据或者删除了的时候-既右侧没有操作的时候)
  22. const isNoAcIds = useRef<string[]>([])
  23. useEffect(() => {
  24. isNoAcIds.current = ['0', ...topId]
  25. if (topId && topId.length)
  26. dispatch(
  27. Z1_APIgetDict(topId[1], data => {
  28. setLoding(true)
  29. if (data && data.length) {
  30. setAcShu(data[0].id)
  31. const txtDom: HTMLDivElement = document.querySelector('.ant-select-selection-item')!
  32. if (txtDom) {
  33. acShuTxtRef.current = txtDom.title
  34. }
  35. }
  36. })
  37. )
  38. }, [dispatch, topId])
  39. const onChange = useCallback((value: any) => {
  40. // console.log('级联改变', value)
  41. setTopId(value)
  42. }, [])
  43. const { dictAll, dictList } = useSelector((state: RootState) => state.Z1dict)
  44. // 点击重置
  45. const resetFu = useCallback(
  46. (flag: boolean) => {
  47. // 重置 flag为true
  48. // 新增和编辑 为false
  49. if (flag) {
  50. setTopId(['10000', '12000'])
  51. } else dispatch(Z1_APIgetDict(topId[1]))
  52. setValue('')
  53. setValue2('')
  54. },
  55. [dispatch, topId]
  56. )
  57. // 当前选中的树节点ID
  58. const [acShu, setAcShu] = useState('0')
  59. // 树节点文字信息
  60. const acShuTxtRef = useRef('')
  61. // 点击树节点
  62. const onSelect = (id: any) => {
  63. // console.log('点击树节点', id)
  64. if (id[0]) {
  65. setAcShu(id[0])
  66. // const txtDom: HTMLDivElement = document.querySelector('.ant-select-selection-item')!
  67. // console.log('-------11', txtDom.title)
  68. // if (txtDom) acShuTxtRef.current = txtDom.title
  69. }
  70. }
  71. const [value, setValue] = useState('')
  72. const [value2, setValue2] = useState('')
  73. const timeRef = useRef(-1)
  74. const valueChange = useCallback((val: string) => {
  75. setValue(val.trim())
  76. clearTimeout(timeRef.current)
  77. timeRef.current = window.setTimeout(() => {
  78. setValue2(val.trim())
  79. }, 500)
  80. }, [])
  81. // value变化的时候获取所有dom 设置隐藏
  82. const treeDataTemp = useMemo(() => {
  83. if (value2) {
  84. return filterTreeByName(dictList, value2)
  85. } else return dictList
  86. }, [dictList, value2])
  87. // 搜索高亮
  88. const treeData = useMemo(() => {
  89. const loop = (dataTemp: any[]): TreeDataNode[] => {
  90. const data = dataTemp || []
  91. return data.map(item => {
  92. const strTitle = ((item.num ? item.num + ' ' : '') + item.name) as string
  93. const strTitleD = strTitle.toUpperCase()
  94. const valueD = value.toUpperCase()
  95. const index = strTitleD.indexOf(valueD)
  96. const beforeStr = strTitle.substring(0, index)
  97. const afterStr = strTitle.slice(index + value.length)
  98. const title =
  99. index > -1 ? (
  100. <span key={item.id}>
  101. {beforeStr}
  102. <span className='site-tree-search-value'>{value}</span>
  103. {afterStr}
  104. </span>
  105. ) : (
  106. <span key={item.id}>{strTitle}</span>
  107. )
  108. if (item.children) {
  109. return { title, key: item.id, children: loop(item.children) }
  110. }
  111. return {
  112. title,
  113. key: item.id
  114. }
  115. })
  116. }
  117. return loop(treeDataTemp)
  118. }, [treeDataTemp, value])
  119. // 右侧信息
  120. const rightData = useMemo(() => {
  121. let obj = {} as TypeZ1dict
  122. if (treeDataTemp && treeDataTemp.length) obj = treeResIdFu(treeDataTemp, acShu)
  123. return obj || {}
  124. }, [acShu, treeDataTemp])
  125. // 点击新增和编辑
  126. const [addInfo, setAddInfo] = useState({} as Z1AddInfoType)
  127. const addSonFu = useCallback(
  128. (id: string) => {
  129. setAddInfo({
  130. id,
  131. txt: id === '-1' ? '新增' : '编辑',
  132. acInfo: rightData
  133. })
  134. },
  135. [rightData]
  136. )
  137. // 点击删除
  138. const delTree = useCallback(
  139. async (id: string) => {
  140. const res = await Z1_APIdel(id)
  141. if (res.code === 0) {
  142. MessageFu.success('删除成功!')
  143. resetFu(false)
  144. }
  145. },
  146. [resetFu]
  147. )
  148. return (
  149. <div className={styles.Z1dict}>
  150. <div className='pageTitle'>数据字典</div>
  151. {/* 顶部 */}
  152. <div className='Z1top'>
  153. <div className='Z1topll'>
  154. {dictAll.length ? (
  155. <Cascader
  156. style={{ width: 240 }}
  157. value={topId}
  158. options={Z1toTowFu(dictAll)}
  159. fieldNames={{ label: 'name', value: 'id', children: 'children' }}
  160. onChange={onChange}
  161. allowClear={false}
  162. />
  163. ) : (
  164. <div style={{ width: 240 }}></div>
  165. )}
  166. &emsp;
  167. <Input
  168. style={{ width: 240 }}
  169. placeholder='请输入字典值'
  170. maxLength={30}
  171. value={value}
  172. onChange={e => valueChange(e.target.value)}
  173. />
  174. </div>
  175. <div className='Z1toprr'>
  176. <Button
  177. type='primary'
  178. onClick={() =>
  179. setAddInfo({
  180. id: '-1',
  181. txt: '新增',
  182. acInfo: rightData
  183. })
  184. }
  185. >
  186. 新增
  187. </Button>
  188. &emsp;
  189. <Button onClick={() => resetFu(true)}>重置</Button>
  190. </div>
  191. </div>
  192. {/* 主体 */}
  193. <div className='Z1main'>
  194. <div className='Z1m1ll'>
  195. {treeDataTemp && treeDataTemp.length ? (
  196. <Tree
  197. // 默认全部展开
  198. defaultExpandAll={true}
  199. // 数据
  200. treeData={treeData}
  201. // 自定义字段
  202. // fieldNames={{ title: 'name', key: 'id', children: 'children' }}
  203. // 选中
  204. selectedKeys={[acShu]}
  205. // 点击
  206. onSelect={onSelect}
  207. />
  208. ) : null}
  209. {loding && treeDataTemp.length === 0 ? <div className='Z1m1llNone'>暂无数据</div> : null}
  210. </div>
  211. <div className='Z1m1rr'>
  212. {rightData.id ? (
  213. <>
  214. <div className='Z1mr1'>操作</div>
  215. <div className='Z1mr2'>
  216. <Button type='text' onClick={() => addSonFu(rightData.id)}>
  217. 编辑
  218. </Button>
  219. &emsp;
  220. <MyPopconfirm txtK='删除' onConfirm={() => delTree(rightData.id)} />
  221. </div>
  222. {/* <div className='Z1mr3'>
  223. <div className='Z1mr3ll'>id:</div>
  224. <div className='Z1mr3rr'>{rightData.id}</div>
  225. </div> */}
  226. <div className='Z1mr3'>
  227. <div className='Z1mr3ll'>字典值:</div>
  228. <div className='Z1mr3rr'>{rightData.name}</div>
  229. </div>
  230. <div className='Z1mr3'>
  231. <div className='Z1mr3ll'>层级:</div>
  232. <div className='Z1mr3rr'>{rightData.level - 2}</div>
  233. </div>
  234. <div className='Z1mr3'>
  235. <div className='Z1mr3ll'>排序值:</div>
  236. <div className='Z1mr3rr'>{rightData.sort}</div>
  237. </div>
  238. </>
  239. ) : null}
  240. </div>
  241. </div>
  242. {/* 新增/编辑页面 中图法分类 */}
  243. {addInfo.id ? (
  244. <Z1add
  245. acShuTxt={acShuTxtRef.current}
  246. addInfo={addInfo}
  247. addFu={() => resetFu(false)}
  248. closeFu={() => setAddInfo({} as Z1AddInfoType)}
  249. isNoAcIds={isNoAcIds.current}
  250. />
  251. ) : null}
  252. </div>
  253. )
  254. }
  255. const MemoZ1dict = React.memo(Z1dict)
  256. export default MemoZ1dict