index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * @Author: your name
  3. * @Date: 2021-09-06 10:28:12
  4. * @LastEditTime: 2021-10-18 10:41:23
  5. * @LastEditors: Please set LastEditors
  6. * @Description: In User Settings Edit
  7. * @FilePath: /MedicalWisdomCheckSys/src/components/MccsFileTree/index.tsx
  8. */
  9. import React, { ReactNode, useEffect, useState, MouseEvent } from 'react'
  10. import { Input, Spin, Image, Popconfirm } from 'antd';
  11. import { PlusOutlined } from '@ant-design/icons';
  12. import DirectoryTree from './components/DirectoryTree';
  13. import './index.less'
  14. import DelActionIcon from './images/del14px.png';
  15. import EditActionIcon from './images/edit14px.png';
  16. import AddActionIcon from './images/add.png';
  17. import FileIcon from './images/file.png';
  18. // const { DirectoryTree } = Tree;
  19. const { Search } = Input;
  20. //树形文件组件
  21. enum Types { 'add', 'del', 'edit', 'search' };
  22. type TypeVals = keyof typeof Types;
  23. type MccsFileTreeProps = {
  24. onSelectHandle?: (data: MccsFileTree.childTree) => void, //选中回调
  25. actionHandle?: ({ type, data }: { type: string, data: MccsFileTree.childTree }) => void, //操作回调,包括编辑/删除/新增/搜索
  26. searchHandle?: (val: any) => void,
  27. switcherIcon?: ReactNode,
  28. treeData: MccsFileTree.childTree[] | [],
  29. defaultSelected?: string, //传id
  30. formContent?: ReactNode,
  31. editable?: boolean
  32. }
  33. const MccsFileTree: React.FC<MccsFileTreeProps> = (props) => {
  34. const { treeData, onSelectHandle, actionHandle, defaultSelected, searchHandle, editable } = props;
  35. const [isLoading, setIsLoading] = useState(true);
  36. //当前选中的
  37. const [currentActivedIndex, setcurrentActivedIndex] = useState(defaultSelected ? defaultSelected : '');
  38. const actionFunc = (event:MouseEvent|undefined, type: TypeVals, data: MccsFileTree.childTree) => {
  39. event?.stopPropagation();
  40. actionHandle && actionHandle({ type, data: data });
  41. }
  42. //操作
  43. const Action = (props: MccsFileTree.childTree) => {
  44. const { isLeaf } = props;
  45. return (
  46. <div className='action'>
  47. {
  48. !isLeaf && ( //非叶子结点才可以新增
  49. <>
  50. <Image width={15} preview={false} onClick={(e) => actionFunc(e, 'add', props)} src={AddActionIcon} />
  51. <div style={{ width: 5 }}></div>
  52. </>
  53. )
  54. }
  55. <Image width={15} preview={false} onClick={(e) => actionFunc(e, 'edit', props)} src={EditActionIcon} />
  56. <div style={{ width: 5 }}></div>
  57. <Popconfirm
  58. title="是否确定删除?"
  59. onConfirm={(e)=>{actionFunc(e, 'del', props)}}
  60. okText="确定"
  61. cancelText="取消"
  62. >
  63. <Image width={15} preview={false} onClick={e=>e.stopPropagation()} src={DelActionIcon} />
  64. </Popconfirm>
  65. </div>
  66. )
  67. }
  68. //叶子结点结构
  69. const TreeNode = (nodeProps: MccsFileTree.childTree) => {
  70. const { title, id,code } = nodeProps;
  71. return (
  72. <div className={currentActivedIndex == id ? 'treeNode actived' : 'treeNode'} onClick={onSelectHandle ? () => {
  73. setcurrentActivedIndex(id);
  74. onSelectHandle(nodeProps)
  75. } : () => { setcurrentActivedIndex(id); }}>
  76. <div style={{ display: 'flex', marginRight: 5, justifyContent: 'center', alignItems: 'center' }} ><Image width={15} preview={false} src={FileIcon} /> </div>
  77. <div className='treeNodeInner'>{`${code} ${title}`}</div>
  78. {(currentActivedIndex == id && editable) && <Action {...nodeProps} /> /*点击展示操作项*/}
  79. </div>
  80. )
  81. }
  82. //递归树形结构
  83. const loop = (data: MccsFileTree.childTree, i: number) => {
  84. const { title, children = [], ...restProps } = data;
  85. const label = <div className="node">{`${restProps.code} ${title}`}</div>;
  86. if (data.isLeaf) {
  87. return <TreeNode key={data.id} currentActivedIndex={currentActivedIndex} setcurrentActivedIndex={setcurrentActivedIndex} title={title} {...restProps} />
  88. }
  89. return (
  90. <DirectoryTree key={data.id} currentActivedIndex={currentActivedIndex} setcurrentActivedIndex={setcurrentActivedIndex}
  91. nodeLabel={label} {...data} onClick={() => onSelectHandle ? onSelectHandle(data) : () => { }}
  92. action={editable && <Action {...data} />} defaultCollapsed={true}
  93. >
  94. {
  95. children.map((item, index) => {
  96. if (item.isLeaf) {
  97. return <TreeNode currentActivedIndex={currentActivedIndex} setcurrentActivedIndex={setcurrentActivedIndex} key={index} {...item} />
  98. } else {
  99. return loop(item, index);
  100. }
  101. })
  102. }
  103. </DirectoryTree>
  104. )
  105. }
  106. useEffect(() => {
  107. if (treeData.length > 0) {
  108. setIsLoading(false);
  109. }
  110. }, [treeData]);
  111. return (
  112. <div className='fileTree'>
  113. <div className="searchBar">
  114. {
  115. editable && (
  116. <div className="add" onClick={e => actionFunc(e, 'add', {
  117. title: '',
  118. id: `0`,
  119. isLeaf: false,
  120. code: `${new Date().getTime()}`,
  121. children: []
  122. })}><PlusOutlined /></div>
  123. )
  124. }
  125. <Search placeholder='请输入' className="inputArea" allowClear onSearch={(val, e) => searchHandle && searchHandle(val)} />
  126. </div>
  127. <div className='treeContainer'>
  128. {
  129. isLoading ? <div className='spinWrap'><Spin delay={500} /></div> : (
  130. <>
  131. {treeData.map((node, i) => {
  132. return loop(node, i);
  133. })}
  134. </>
  135. )
  136. }
  137. </div>
  138. </div>
  139. );
  140. };
  141. export default MccsFileTree