import React, { useEffect, useState } from 'react'; import { message, notification, Tooltip, Modal, Input, Button, Spin, Empty, } from 'antd'; import { FileAddTwoTone, FolderAddTwoTone, FolderFilled, FileOutlined, DeleteTwoTone, } from '@ant-design/icons'; import classnames from 'classnames'; import { miniAppSiteTree, getMiniAppModuleTree, addMenu, getMenuInfo, deleteMenu, editMenu, getRoleListPlain, dragMenu, } from '@/services/mobileConfig/api'; import styles from './miniMenu.less'; import { appConnector } from '@/containers/App/store'; import Tree from '@/components/ExpendableTree'; import AddForm from './AddForm'; import EditForm from './editForm'; import CheckList from './checkBox'; const MiniMenu = props => { const { userMode, clientName, parentKey } = props; const [flag, setFlag] = useState(1); // 刷新标志 const [treeFlag, setTreeFlag] = useState(true); const [treeData, setTreeData] = useState([]); // 树的数据 const [loading, setLoading] = useState(false); // 加载 const [menuID, setMenuID] = useState(''); // 选中的树ID const [saveID, setSaveID] = useState(''); // 保存选择的树id const [nodeType, setNodeType] = useState(''); // 选中的节点类型 const [info, setInfo] = useState({}); const [addVisible, setAddVisible] = useState(false); // 新增弹窗 const [addTwoVisible, setAddTwoVisible] = useState(false); // 编辑弹窗 const [delVisible, setDelVisible] = useState(false); // 删除弹窗 const [nodeObj, setNodeObj] = useState({}); const [addType, setAddType] = useState(''); // 添加下级类型 const [modalTitle, setModalTitle] = useState(''); const [roleList, setRoleList] = useState([]); // 复选框选中的值 const [modalLoading, setModalLoading] = useState(false); const [submitLoading, setSubmitLoading] = useState(false); const [addList, setAddList] = useState([]); const [newTreeList, setNewTreeList] = useState([]); // 获取菜单树 useEffect(() => { console.log(props); updateTrees(); }, [flag]); // 获取角色列表 useEffect(() => { getRoleListPlain({ subSystemValue: clientName || 'miniapp', _dc: Date.now(), _version: 9999, }).then(res => { if (res.success) { setAddList(res.list); } }); }, [flag, clientName]); // 获取菜单信息 useEffect(() => { getInfo(); }, [menuID]); // 更新树 const updateTrees = () => { setLoading(true); getMiniAppModuleTree({ userMode: userMode || 'super', }) .then(res => { console.log(res, 'res'); // const result1 = res[0].children[0].children[2].children; // setNewTreeList(JSON.parse(JSON.stringify(result1))); // setTreeData(result1); // setLoading(false); if (res.code === 0) { const { data } = res; setLoading(false); let obj = data[0].children.find(item => item.id === parentKey); const result = obj.children[1].children; setNewTreeList(JSON.parse(JSON.stringify(result))); setTreeData(result); console.log(result); // 第一次加载,默认选择第一个组织 // if (treeFlag) { // handleSelect([result[0].menuID], false); // setTreeFlag(false); // } } else { notification({ message: '提示', duration: 10, description: '获取菜单失败', }); } }) .catch(err => { setLoading(false); message.error(err); }); }; // 处理数据 const mapTree = val => { const obj = { ...val }; const hasChild = obj.children.length > 0; return { title: ( <div className={styles.title}> <div>{obj.text}</div> <div className={styles.tip}> {obj.menuType === 'MiniAppMenuGroup' && ( <Tooltip title="新增菜单组" className={styles.fsize}> <FolderAddTwoTone onClick={() => addMenuGroupTip(obj)} /> </Tooltip> )} {obj.menuType === 'MiniAppMenuGroupTwo' && ( <Tooltip title="新增功能菜单" className={styles.fsize}> <FileAddTwoTone onClick={() => addMenuTip(obj)} /> </Tooltip> )} <Tooltip title="删除菜单" className={styles.fsize}> <DeleteTwoTone onClick={() => deleteMenuTip(obj)} /> </Tooltip> </div> </div> ), key: obj.menuID, icon: obj.menuType !== 'MiniAppMenuThree' && obj.menuType !== 'MiniAppMenu' ? ( <FolderFilled /> ) : ( <FileOutlined /> ), menuType: obj.menuType, children: hasChild ? obj.children.map(i => mapTree(i)) : [], }; }; // 树的点击事件 const handleSelect = (prop, treeNode) => { console.log(prop, treeNode); if (treeNode) { const { node, node: { menuType }, } = treeNode; console.log(menuType); switch (menuType) { case 'MiniAppMenuGroup': setNodeType(1); setAddType(2); break; case 'MiniAppMenuGroupTwo': setNodeType(2); setAddType(4); break; case 'MiniAppMenu': setNodeType(3); setAddType(3); break; case 'MiniAppMenuThree': setNodeType(4); setAddType(4); break; default: break; } } if (prop[0]) { setMenuID(prop[0]); setSaveID(prop[0]); } else { setMenuID(saveID); } }; const getInfo = id => { if (!menuID) { return; } setLoading(true); getMenuInfo({ menuID, _version: 9999, _dc: Date.now(), }) .then(res => { setLoading(false); if (res.success) { setInfo({ ...res }); } else { notification.error({ message: '提示', duration: 10, description: res.message || '获取失败', }); } console.log(res, 'resss'); }) .catch(err => { setLoading(false); console.error(err); }); }; // 删除的回调 const deleteMenuTip = val => { console.log(val, 'val'); setModalTitle(val.text); setNodeObj(val); setDelVisible(true); }; const delMenu = () => { setModalLoading(true); deleteMenu({ menuID: nodeObj.menuID, _dc: Date.now(), _version: 9999, }) .then(res => { setModalLoading(false); if (res.success) { setDelVisible(false); setFlag(flag + 1); setNodeType(''); setNodeObj(''); notification.success({ message: '提示', duration: 3, description: '删除成功', }); } else { notification.error({ message: '提示', duration: 10, description: res.message || '删除失败', }); } }) .catch(err => { setModalLoading(false); console.log(err); }); }; // 新增菜单组 const addMenuGroupTip = val => { console.log(val, 'addgroup'); setModalTitle(`在${val.text}下新增菜单组`); setNodeObj(val); setAddVisible(true); }; const rootAddGroup = () => { setNodeObj(''); // setNodeType(1); setModalTitle('新增最上级菜单组'); setAddType(1); setAddVisible(true); }; // 新增功能菜单 const addMenuTip = val => { console.log(val, 'add'); setNodeObj(val); setModalTitle(`在${val.text}下新增功能菜单`); setAddTwoVisible(true); }; const rootAdd = () => { setModalTitle('新增最上级功能菜单'); setNodeObj(''); // setNodeType(3); setAddType(3); setAddTwoVisible(true); }; // 新增提交的回调 const submitCallback = (prop, item) => { setSubmitLoading(true); let obj = { ...prop }; // if (addType === 3 || addType === 4) { // obj.relatedRoleList = String(roleList) || ''; // } console.log(obj); const parentID = item.menuID ? item.menuID : -1; addMenu({ _dc: Date.now(), parentID, subSystemValue: clientName || 'miniapp', _version: 9999, ...obj, }) .then(res => { setSubmitLoading(false); if (res.success) { setAddVisible(false); setAddTwoVisible(false); setFlag(flag + 1); notification.success({ message: '提示', description: '新增成功', duration: 3, }); } else { notification.error({ message: '提示', description: res.message || '新增失败', duration: 10, }); } }) .catch(err => { setSubmitLoading(false); console.error(err); }); }; // 编辑的回调 const editSubmitCallback = prop => { setLoading(true); console.log(prop); let obj = { ...prop }; if (nodeType === 3 || nodeType === 4) { obj.relatedRoleList = String(roleList) || ''; } editMenu({ _dc: Date.now(), menuID, subSystemValue: clientName || 'miniapp', _version: 9999, ...obj, }) .then(res => { setLoading(false); if (res.success) { setFlag(flag + 1); notification.success({ message: '提示', duration: 3, description: '编辑成功', }); } else { notification.error({ message: '提示', duration: 3, description: res.message || '编辑失败', }); } console.log(res, 'resres'); }) .catch(err => { console.error(err); setLoading(false); }); }; // 复选框选中值 const valueCallback = val => { console.log(val, 'val'); // relatedRoleCode let arr = [...val]; let arr2 = []; arr.map(item => { if (item.related) { arr2.push(item.relatedRoleCode); } }); setRoleList(arr2); }; // 树的拖动 const handleDrop = infos => { console.log(infos, 'newTree'); const { pos } = infos.node.props; const dragKey = infos.dragNode.props.eventKey; const dragPos = infos.dragNode.props.pos.split('-'); // 拖动的节点 const dropKey = infos.node.props.eventKey; const dropPos = infos.node.props.pos.split('-'); // 拖动结束的节点 const endIndex = Number(dropPos[dropPos.length - 1]); const dropPosition = infos.dropPosition - Number(dropPos[dropPos.length - 1]); // let obj = findNum(newTreeList, dragKey, getArrList); let obj; findNum(newTreeList, dragKey, (arr, id, parentId, index) => { obj = { arr, id, parentId, index }; return { arr, id, parentId, index }; }); console.log(obj, 'obj'); let arrList = []; if ( dragPos.length !== dropPos.length || dragPos[dragPos.length - 2] !== dropPos[dropPos.length - 2] ) { notification.warning({ message: '提示', duration: 3, description: '操作失败', }); return null; } let idIndex; obj.arr.map((item, index) => { if (item.menuID === obj.id) { idIndex = index; return; } arrList.push(item.menuID); }); if (idIndex > endIndex) { if (dropPosition === -1) { arrList.splice(endIndex, 0, obj.id); } else if (dropPosition === 1) { arrList.splice(endIndex + 1, 0, obj.id); } } else if (idIndex < endIndex) { if (dropPosition === -1) { arrList.splice(endIndex - 1, 0, obj.id); } else if (dropPosition === 1) { arrList.splice(endIndex, 0, obj.id); } } dragMenu({ menuID: obj.id, newParentID: obj.parentId || -1, menuList: String(arrList) || '', _version: 9999, _dc: Date.now(), }).then(res => { console.log(res); if (res.success) { setFlag(flag + 1); } else { notification.error({ message: '提示', duration: 3, description: res.message || '操作失败', }); } }); }; const findNum = (array, id, callback, parentId = '') => { let ptId = parentId; let arrFlag = true; array.map((item, index) => { if (item.menuID === id) { callback(array, id, parentId, index); arrFlag = false; return; } if (arrFlag && item.children && item.children.length > 0) { ptId = item.menuID; findNum(item.children, id, callback, ptId); } }); }; const getArrList = (arr, id, parentId, index) => { console.log(arr, 'arr', id, 'id', parentId, 'parentId', index, 'index'); return { arr, id, parentId, index }; }; return ( <Spin spinning={loading} tip="loading..."> <div className={classnames({ [styles.box]: true, })} > <div className={classnames({ [styles.left]: true, })} > <div className={classnames({ [styles.leftTop]: true, })} > 菜单列表 <div className={classnames({ [styles.tRight]: true, })} > <Tooltip title="新增最上级菜单组"> <FolderAddTwoTone className={`${styles.icon1} ${styles.icon}`} onClick={() => rootAddGroup()} /> </Tooltip> <Tooltip title="新增最上级功能菜单"> <FileAddTwoTone onClick={() => rootAdd()} className={`${styles.icon2} ${styles.icon}`} /> </Tooltip> </div> </div> {treeData.length > 0 ? ( <Tree showIcon onSelect={handleSelect} treeData={treeData.map(item => mapTree(item))} blockNode draggable autoExpandParent onDrop={handleDrop} // onDragEnter={handleDragEnter} selectedKeys={[menuID]} // expandedKeys={[menuID]} /> ) : ( <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无菜单" /> )} </div> <Modal visible={addVisible} title={modalTitle} bodyStyle={{ width: '100%', minHeight: '100px' }} style={{ top: 80 }} width="600px" destroyOnClose footer={null} cancelText="取消" okText="确认" maskClosable={false} onCancel={() => setAddVisible(false)} > <AddForm nodeType={nodeType} nodeObj={nodeObj} addType={addType} submitCallback={submitCallback} submitLoading={submitLoading} valueCallback={valueCallback} addList={addList} /> </Modal> <Modal visible={addTwoVisible} title={modalTitle} bodyStyle={{ width: '100%', minHeight: '100px', maxHeight: '700px', overflowY: 'scroll', }} style={{ top: 80 }} width="600px" destroyOnClose footer={null} cancelText="取消" okText="确认" maskClosable={false} onCancel={() => setAddTwoVisible(false)} > <AddForm submitLoading={submitLoading} nodeType={nodeType} nodeObj={nodeObj} addType={addType} addList={addList} submitCallback={submitCallback} valueCallback={valueCallback} /> </Modal> <Modal visible={delVisible} title="请确认" bodyStyle={{ width: '100%', minHeight: '100px' }} style={{ top: 80 }} width="400px" destroyOnClose cancelText="取消" okText="确认" maskClosable={false} onCancel={() => setDelVisible(false)} onOk={() => delMenu()} confirmLoading={modalLoading} > 是否删除<span style={{ color: 'red' }}>{modalTitle}</span>? </Modal> <div className={classnames({ [styles.middle]: true, })} > 菜单配置 {nodeType ? ( <div style={{ marginTop: '10px' }}> <EditForm nodeType={nodeType} info={info} submitCallback={editSubmitCallback} valueCallback={valueCallback} /> {/* <div className={classnames({ [styles.rightBox]: true, })} > 关联角色 <CheckList info={info} nodeType={nodeType} valueCallback={valueCallback} /> </div> */} </div> ) : ( <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="当前未选中菜单" /> )} </div> </div> </Spin> ); }; export default MiniMenu;