import React, { useState, useMemo, useRef, createContext } from 'react'; import { Tree, Input, Popconfirm, Tooltip, Divider, Modal, message } from 'antd'; import { MinusSquareOutlined, FormOutlined, PlusSquareOutlined, ArrowDownOutlined, ArrowRightOutlined } from '@ant-design/icons'; import getPrem from '@/utils/getPrem'; import { useRequest } from 'ahooks'; import { doFetch } from '@/utils/doFetch'; import { useEffect } from 'react'; import Login from '@/pages/user/Login'; const ReachableContext = createContext(null); let { Search } = Input, { TreeNode } = Tree; const getParentKey = (key, tree) => { let parentKey; for (let i = 0; i < tree.length; i++) { const node = tree[i]; if (node.children) { if (node.children.some((item) => { return item.key === key })) { parentKey = node.key; } else if (getParentKey(key, node.children)) { parentKey = getParentKey(key, node.children); } } } return parentKey; }; function TreeRender({ url, deleteurl, saveurl, onselected, params, noaction, maxWidth }) { const [search, setsearch] = useState(""); const [savetitle, setsavetitle] = useState(null); const [modal, setModal] = useState({ visible: false }); const [expandall, setexpandall] = useState(false); const [expandedKeys, onExpand] = useState(); const { data, loading, refresh } = useRequest(() => { return doFetch({ url, params: params ?? {} }) }); const [autoExpandParent, setAutoExpandParent] = useState(true); const allkeys = useMemo(() => { let res = []; const fn = (source) => { source.map(el => { res.push(el) el.children && el.children.length > 0 ? fn(el.children) : "" // 子级递归 }) } fn(data?.data?.dataList ?? []); return res.filter(it => it.children).map(it => it.key) }, [data]) const alldata = useMemo(() => { let res = []; const fn = (source) => { source.map(el => { res.push(el) el.children && el.children.length > 0 ? fn(el.children) : "" // 子级递归 }) } fn(data?.data?.dataList ?? []); return res }, [data]) const treeData = useMemo(() => { let res = data?.data?.dataList ?? []; return [ { title: "全部", key: "00000000", children: res } ] }, [data]); const onChange = (e) => { const { value } = e.target; const dataLists = getAllList(); const newExpandedKeys = dataLists.map((item) => { if (item.title.indexOf(value) > -1) { return getParentKey(item.key, treeData); } return null; }).filter((item, i, self) => item && self.indexOf(item) === i); setsearch(value); if(newExpandedKeys.length>0){ setexpandall(true); setAutoExpandParent(true) }else{ setexpandall(false); setAutoExpandParent(false) } onExpand(newExpandedKeys); }; const loop = data => data.map(item => { const index = item.title.indexOf(search); const beforeStr = item.title.substr(0, index); const afterStr = item.title.substr(index + search.length); let title = index > -1 ? ( <Tooltip title={item.title} placement="bottom"> <span style={{ display: "inline-block", maxWidth: maxWidth ?? 88, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}> {beforeStr} <span style={{ color: '#f50' }}>{search}</span> {afterStr} </span> </Tooltip> ) : ( <Tooltip title={item.title} placement="bottom"> <span style={{ display: "inline-block", maxWidth: maxWidth ?? 88, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.title}</span> </Tooltip> ); const actiontitle = ( <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}> {title} <div> { item.key && item.key != "0" && <Tooltip title="编辑" onClick={(e) => { e.stopPropagation(); setsavetitle(null) if (getPrem("enElectricityMeterType_save", "ifs")) { setModal({ visible: true, closable: true, title: "修改节点名称", okText: "修改", cancelText: "取消", placeholder: item.title, key: item.key }) } }}> <FormOutlined style={{ color: "#1890ff" }} /> </Tooltip> } { item.key && <Divider type='vertical' style={{ margin: "0 6px" }}></Divider> } <Tooltip title="新增"> <PlusSquareOutlined disabled={!getPrem("enElectricityMeterType_save", "ifs")} onClick={(e) => { e.stopPropagation(); setsavetitle(null) if (getPrem("enElectricityMeterType_save", "ifs")) { setModal({ visible: true, closable: true, title: "新增子结构", okText: "新增", cancelText: "取消", placeholder: item.title, key: item.key }) } }} style={{ color: `${getPrem("enElectricityMeterType_save", "ifs") ? "green" : ""}` }} /></Tooltip> { (!item.children || item.children.length == 0) && <Divider type='vertical' style={{ margin: "0 6px" }}></Divider> } { (!item.children || item.children.length == 0) && (item.key != "0") && <Popconfirm placement='bottom' title="是否删除该节点?" okText="删除" cancelText="取消" onConfirm={() => { doFetch({ url: deleteurl, params: { id: item.key } }).then(res => { if (res.code == '0000') { message.success("操作成功") refresh(); } }) }} disabled={!getPrem("enElectricityMeterType_deleteById", "ifs")} > <Tooltip title="删除"> <MinusSquareOutlined onClick={(e) => { e.stopPropagation() }} style={{ color: "red" }} /> </Tooltip> </Popconfirm> } {/* { item.key === "00000000" && <Divider type='vertical' style={{ margin: "0 6px" }}></Divider> } */} {/* { item.key === "00000000" && <Tooltip title={expandall ? "收起" : "展开"} onClick={(e) => { e.stopPropagation(); setexpandall(!expandall) onExpand(expandall ? [] : allkeys) }}> {expandall ? <ArrowDownOutlined /> : <ArrowRightOutlined />} </Tooltip> } */} </div> </div> ) if (item.key === "00000000") { title = ( <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flex: 1 }}> {title} <Tooltip title={expandall ? "收起" : "展开"} onClick={(e) => { e.stopPropagation(); setexpandall(!expandall) onExpand(expandall ? [] : allkeys) setAutoExpandParent(!expandall) }}> {expandall ? <ArrowDownOutlined /> : <ArrowRightOutlined />} </Tooltip> </div> ) } // if (item.children) { // return ( // <TreeNode key={item.key} title={actiontitle}> // {loop(item.children)} // </TreeNode> // ); // } // return <TreeNode key={item.key} title={title} />; // return ( // <TreeNode key={item.key} title={noaction ? title : actiontitle}> // {item.children && loop(item.children)} // </TreeNode> // ); if (item.children) { return { title: noaction ? title : actiontitle, key: item.key, children: loop(item.children), level: item.level }; } return { title: noaction ? title : actiontitle, key: item.key, level: item.level }; }); useEffect(() => { setexpandall(true); onExpand(allkeys) }, [allkeys]); function getAllList() { const dataLists = []; const generateLists = data => { for (let i = 0; i < data.length; i++) { const node = data[i]; const key = node.key; dataLists.push({ key, title: node.title, level: node.level }); if (node.children) { generateLists(node.children, node.key); } } }; generateLists(treeData); return dataLists; } return ( <div> <Modal {...modal} onCancel={() => { setModal(s => ({ ...s, visible: false })) }} onOk={() => { if (modal.okText == "修改") { return new Promise((resolve, reject) => { if (savetitle) { doFetch({ url: saveurl, params: { materieTypeName: savetitle, id: modal.key, } }).then(res => { if (res.code == "0000") { message.success("操作成功") refresh() setModal({ visible: false }) } }) resolve() } else { message.warn("请输入修改的名称") reject() } }) } else { return new Promise((resolve, reject) => { if (savetitle) { doFetch({ url: saveurl, params: { materieTypeName: savetitle, parentId: modal.key, } }).then(res => { if (res.code == "0000") { message.success("操作成功") refresh() setModal({ visible: false }) } }) resolve() } else { message.warn("请输入修改的名称") reject() } }) } }} > { modal.okText == "修改" ? <div> <Input placeholder={modal.placeholder} allowClear value={savetitle} onChange={(e) => { setsavetitle(e.target.value) }}></Input> </div> : <div> <div style={{ marginBottom: 15, color: "#f50", fontSize: 16 }}>当前结构:{modal.placeholder}</div> <Input placeholder="子结构" allowClear onChange={(e) => { setsavetitle(e.target.value) }}></Input> </div> } </Modal> <Search value={search} style={{ margin: '16px 0 8px 0' }} placeholder="搜索" onChange={onChange} /> <Tree onSelect={(selectedKeys, e) => { onselected?.(selectedKeys, e, alldata) }} autoExpandParent={autoExpandParent} defaultExpandAll={true} expandedKeys={expandedKeys} onExpand={(expandedKeys, { expanded: bool, node }) => { onExpand(expandedKeys); setAutoExpandParent(false); if (!bool && node.key == "00000000") { setexpandall(false) } else { setexpandall(true) } }} treeData={loop(treeData ?? [])} > {/* {loop(treeData ? treeData : [])} */} </Tree> </div> ); } export default TreeRender;