/* eslint-disable no-debugger */ /* eslint-disable array-callback-return */ /* eslint-disable no-plusplus */ /* eslint-disable consistent-return */ import React, { useEffect, useState, useRef } from 'react'; import { notification, Tooltip, Modal, Spin, Empty } from 'antd'; import Tree from '@/components/ExpendableTree'; import { FileAddTwoTone, FolderAddTwoTone, FolderFilled, FileOutlined, DeleteTwoTone, DeliveredProcedureOutlined, } from '@ant-design/icons'; import classnames from 'classnames'; import styles from './webMenu.less'; import AddForm from './AddForm'; import EditForm from './editForm'; import CheckList from './checkBox'; import ImportOrExport from './ImportOrExport'; import { addWebMenu, // 增 deleteWebMenu, // 删 editWebMenu, // 改 getWebMenuInfo, // 查 dragMenu, // 菜单拖拽 getWebModuleTree, pEditWebMenu, } from '@/services/webConfig/api'; const MiniMenu = props => { const { menu, configFiles, subSystemValue, updateMenuTree, userMode, webid, productList } = props; const [flag, setFlag] = useState(1); // 刷新标志 const [loading, setLoading] = useState(false); // 加载 const [menuID, setMenuID] = useState(''); // 选中的树ID const [nodeType, setNodeType] = useState(''); // 选中的节点类型 const [info, setInfo] = useState({}); const [infoAll, setInfoAll] = useState({}); const [importOrExportVisible, setImportOrExportVisible] = useState(false); // 导入导出弹窗 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 [newTreeList, setNewTreeList] = useState([]); const [checkList, setCheckList] = useState([]); const [flagg, setFlagg] = useState(0); const [expendKey, setExpendKey] = useState(''); // 保存默认展开项 const [menuList, setMenuList] = useState([]); // 菜单树 const [keepId, setKeepId] = useState(''); const [mapDataList, setMapDataList] = useState(new Set()); /* ***************************************************** */ const [curMenuType, setCurMenuType] = useState(''); const parentRef = useRef(); // 获取菜单信息 useEffect(() => { console.log(menuID, flag); if (flag === 1) { setExpendKey(menuID); } console.log(expendKey); getInfo(); }, [menuID, webid]); // useEffect(() => { // getTree(); // }, []); useEffect(() => { getTree(); return () => { setLoading(false); }; }, [webid]); // 处理数据 const mapTree = val => { const obj = { ...val }; const hasChild = obj.children.length > 0; return { title: ( <div className={styles.title}> <div className={styles.titleText}>{obj.text}</div> <div className={styles.tip}> {obj.menuType === 'Web4MenuGroup' && ( <Tooltip title="导入导出菜单组" className={styles.fs}> <DeliveredProcedureOutlined style={{ color: '#178BF7' }} onClick={e => importAndExport(obj, e)} /> </Tooltip> )} {obj.menuType === 'Web4MenuGroup' && ( <Tooltip title="新增菜单组" className={styles.fs}> <FolderAddTwoTone onClick={e => addMenuGroupTip(obj, e)} /> </Tooltip> )} {obj.menuType === 'Web4MenuGroup' && ( <Tooltip title="新增功能菜单" className={styles.fs}> <FileAddTwoTone onClick={e => addMenuTip(obj, e)} /> </Tooltip> )} <Tooltip title="删除菜单" className={styles.fs}> <DeleteTwoTone onClick={e => deleteMenuTip(obj, e)} /> </Tooltip> </div> </div> ), key: obj.menuID, icon: obj.menuType === 'Web4MenuGroup' ? <FolderFilled /> : <FileOutlined />, menuType: obj.menuType, children: hasChild ? obj.children.map(i => mapTree(i)) : [], }; }; const mapData = (val, e) => { const obj = { ...val }; const hasChild = obj.children.length > 0; if (hasChild) { obj.children.map(i => mapData(i)); } mapDataList.add(obj); }; // 树的点击事件 const handleSelect = (prop, treeNode) => { console.log(prop); console.log(treeNode); if (treeNode) { const { node: { menuType }, } = treeNode; console.log(menuType); switch (menuType) { case 'Web4MenuGroup': setNodeType(2); setAddType(2); break; default: setNodeType(1); setAddType(1); break; } } if (prop[0]) { setMenuID(prop[0]); } }; const getInfo = id => { if (!menuID) { return; } setLoading(true); getWebMenuInfo({ menuID, _dc: Date.now(), }) .then(res => { setLoading(false); if (res.code === 0) { let infoList = res.data.relatedRoleList.map(item => ({ groupName: item.groupName, isChecked: item.isChecked, list: item.list, checkedList: new Set([]), })); setInfo(infoList); setInfoAll({ ...res.data }); let data = new Set(); infoList.map(item => { if (item.isChecked == true) { data.add(item.groupName); } item.list.map(i => { if (i.related) { item.checkedList.add(i.relatedRoleCode); } }); }); setCheckList(data); } else { notification.error({ message: '提示', duration: 10, description: res.msg || '获取失败', }); } }) .catch(err => { setLoading(false); console.error(err); }); }; // 删除的回调 const deleteMenuTip = (val, e) => { e.stopPropagation(); console.log(val); console.log(e); setModalTitle(val.text); setNodeObj(val); setDelVisible(true); }; const delMenu = () => { setModalLoading(true); deleteWebMenu({ menuID: nodeObj.menuID, _dc: Date.now(), }) .then(res => { setModalLoading(false); if (res.code === 0) { setDelVisible(false); // setFlag(flag + 1); if (nodeObj.menuID == menuID) { getTree(); setMenuID(keepId.menuID); setNodeType(2); setNodeObj(keepId); } else { getTree(); } // updateMenuTree('delete', nodeObj); notification.success({ message: '提示', duration: 3, description: '删除成功', }); } else { notification.error({ message: '提示', duration: 10, description: res.msg || '删除失败', }); } }) .catch(err => { setModalLoading(false); console.error(err); }); }; // 导入导出菜单组 const importAndExport = (val, e) => { e.stopPropagation(); setNodeObj(val); setImportOrExportVisible(true); }; // 新增菜单组 const addMenuGroupTip = (val, e) => { e.stopPropagation(); setModalTitle(`在${val.text}下新增菜单组`); setNodeObj(val); setAddType(2); setAddVisible(true); }; const rootAddGroup = () => { setNodeObj(''); setModalTitle('新增最上级菜单组'); setAddType(2); setAddVisible(true); }; // 新增功能菜单 const addMenuTip = (val, e) => { e.stopPropagation(); setNodeObj(val); setModalTitle(`在${val.text}下新增功能菜单`); setAddType(1); setAddTwoVisible(true); }; const rootAdd = () => { setModalTitle('新增最上级功能菜单'); setNodeObj(''); setAddType(1); setAddTwoVisible(true); }; const handleGeturl = val => { let url; const isSite = val.includes('CityTemp'); if (isSite) { url = val; } else { url = localStorage.getItem('pd2-baseUrl') ? localStorage.getItem('pd2-baseUrl') + val : val; } return url; }; // 导入或导出弹窗回调 const onFinishCallBack = () => {}; // 新增提交的回调 const submitCallback = (prop, item) => { console.log(subSystemValue, 'subSystemValue'); setSubmitLoading(true); let baseUrl = handleGeturl(prop.imageUrl); let obj = { ...prop, baseUrl }; const parentID = item.menuID ? Number(item.menuID) : -1; addWebMenu({ _dc: Date.now(), parentID, subSystemValue, ...obj, }) .then(res => { setSubmitLoading(false); if (res.code === 0) { console.log(res.data); setAddVisible(false); setAddTwoVisible(false); // setFlag(flag + 1); console.log(prop); getTree(res.data); // updateMenuTree('add', item); notification.success({ message: '提示', description: '新增成功', duration: 3, }); } else { notification.error({ message: '提示', description: res.msg || '新增失败', duration: 10, }); } }) .catch(err => { setSubmitLoading(false); console.error(err); }); }; const treeCallback = value => { if (value) { console.log(value); } }; // 编辑的回调 const editSubmitCallback = prop => { setLoading(true); let baseUrl = handleGeturl(prop.imageUrl); let obj = { ...prop, baseUrl }; console.log(obj); if (nodeType === 1) { // obj.relatedRoleList = roleList || ''; editWebMenu({ _dc: Date.now(), menuID: Number(menuID), // subSystemValue, ...obj, }) .then(res => { setLoading(false); if (res.code === 0) { // setFlag(flag + 1); getTree(); // updateMenuTree('edit'); notification.success({ message: '提示', duration: 3, description: '编辑成功', }); } else { notification.error({ message: '提示', duration: 3, description: res.msg || '编辑失败', }); } }) .catch(err => { // eslint-disable-next-line no-console console.error(err); setLoading(false); }); } else { // 新接口改为editWebMenu 原来为pEditWebMenu editWebMenu({ _dc: Date.now(), menuID: Number(menuID), // subSystemValue, ...obj, product: null, baseUrl: null, hideInMenu: false, }) .then(res => { setLoading(false); if (res.code === 0) { // setFlag(flag + 1); getTree(); // updateMenuTree('edit'); notification.success({ message: '提示', duration: 3, description: '编辑成功', }); } else { notification.error({ message: '提示', duration: 3, description: res.msg || '编辑失败', }); } }) .catch(err => { // eslint-disable-next-line no-console console.error(err); setLoading(false); }); } }; const valueCallback = val => { console.log(val); // let arr = [...val]; // let arr2 = []; // arr.map(item => { // if (item.related) { // arr2.push(item.relatedRoleCode); // } // }); setRoleList(val.toString()); }; // 返回拖拽完毕后的信息 const loop = (data, key, parentID, callback) => { for (let i = 0; i < data.length; i++) { if (data[i].menuID === key) { return callback(data[i], i, data, parentID); } if (data[i].children) { loop(data[i].children, key, data[i].menuID, callback); } } }; const getTree = e => { getWebModuleTree(userMode || 'super') .then(res => { setLoading(false); const { code, data } = res; if (code === 0) { let arr = data .filter(item => item.id === 'Web4SingleStation') .map(r => r.children.filter(i => i.id === webid)) .flat(2); let arr2 = arr[0].children.find(item => item.text === '菜单管理').children || []; setMenuList(arr2 || []); if (e) { arr2.map(item => mapData(item, e)); console.log([...mapDataList]); let aa = [...mapDataList].find(i => i.menuID == e); console.log(aa); setMenuID(aa.menuID); setExpendKey(aa.menuID); console.log(expendKey); switch (aa.menuType) { case 'Web4MenuGroup': setNodeType(2); setAddType(2); break; default: setNodeType(1); setAddType(1); break; } } setKeepId(arr2[0]); // 进页面后默认展示第一条数据 if (arr2.length > 0) { if (flag === 1) { setMenuID(arr2[0].menuID); switch (arr2[0].menuType) { case 'Web4MenuGroup': setNodeType(2); setAddType(2); break; default: setNodeType(1); setAddType(1); break; } } setFlag(flag + 1); } } }) .catch(err => { setLoading(false); }); }; // 树的拖动 const handleDrop = infos => { const dropKey = infos.node.key; const dragKey = infos.dragNode.key; const dropPos = infos.node.pos.split('-'); const dropPosition = infos.dropPosition - Number(dropPos[dropPos.length - 1]); const data = [...menuList]; // 找到拖拽的元素 let dragObj; let dropObj; let id; let dragList; loop(data, dropKey, -1, item => { dropObj = item; }); loop(data, dragKey, -1, (item, index, arr) => { if (infos.dropToGap || dropObj.menuType !== 'Web4Menu') { arr.splice(index, 1); dragObj = item; } }); if (!infos.dropToGap) { // Drop on the content loop(data, dropKey, -1, item => { item.children = item.children || []; if (item.menuType !== 'Web4Menu') { // where to insert 示例添加到头部,可以是随意位置 item.children.unshift(dragObj); id = item.menuID; dragList = item.children.map(val => val.menuID); } }); } else if ( (infos.node.props.children || []).length > 0 && // Has children infos.node.props.expanded && // Is expanded dropPosition === 1 // On the bottom gap ) { loop(data, dropKey, -1, item => { item.children = item.children || []; // where to insert 示例添加到头部,可以是随意位置 item.children.unshift(dragObj); id = item.menuID; dragList = item.children.map(val => val.menuID); }); } else { let ar; let i; loop(data, dropKey, -1, (item, index, arr, parentID) => { ar = arr; i = index; id = parentID; }); if (dropPosition === -1) { ar.splice(i, 0, dragObj); } else { ar.splice(i + 1, 0, dragObj); } dragList = ar.map(val => val.menuID); } // 如果拖拽到菜单下不做任何处理 if (!dragList) { return; } console.log(dragList, 'dragList'); dragMenu({ menuID: dragKey, newParentID: id || -1, menuList: String(dragList) || '', _version: 9999, _dc: Date.now(), }).then(res => { if (res.code === 0) { // updateMenuTree(); getTree(); // setFlag(flag + 1); } else { notification.error({ message: '提示', duration: 3, description: res.msg || '操作失败', }); } }); }; 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)}> <Tooltip title="导入导出菜单组" className={styles.fs}> <DeliveredProcedureOutlined style={{ color: '#178BF7', marginRight: '10px' }} onClick={() => { setNodeObj(''); setImportOrExportVisible(true); }} /> </Tooltip> <Tooltip title="新增最上级菜单组"> <FolderAddTwoTone className={`${styles.icon1} ${styles.icon}`} onClick={() => rootAddGroup()} /> </Tooltip> <Tooltip title="新增最上级功能菜单"> <FileAddTwoTone onClick={() => rootAdd()} className={`${styles.icon2} ${styles.icon}`} /> </Tooltip> </div> </div> {menuList.length > 0 && ( <div style={{ height: 'calc(100vh - 240px)', overflowY: 'scroll' }}> <Tree showIcon onSelect={handleSelect} treeData={menuList.map(item => mapTree(item))} blockNode draggable autoExpandParent selectedKeys={[menuID]} onDrop={handleDrop} expandedKeys={expendKey} /> </div> )} </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)} onConfirm={() => { submitCallback(); }} > <AddForm nodeObj={nodeObj} addType={addType} configFiles={configFiles} submitCallback={submitCallback} submitLoading={submitLoading} productList={productList} /> </Modal> <Modal visible={addTwoVisible} title={modalTitle} bodyStyle={{ width: '100%', minHeight: '100px' }} style={{ top: 80 }} width="600px" destroyOnClose footer={null} maskClosable={false} cancelText="取消" okText="确认" onCancel={() => setAddTwoVisible(false)} > <AddForm submitLoading={submitLoading} nodeObj={nodeObj} configFiles={configFiles} addType={addType} productList={productList} submitCallback={submitCallback} /> </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} > {nodeObj.children && nodeObj.children.length > 0 ? ( <span> 是否删除<span style={{ color: 'red' }}>{modalTitle}</span>及其子菜单? </span> ) : ( <span> 是否删除<span style={{ color: 'red' }}>{modalTitle}</span>? </span> )} </Modal> <div className={classnames({ [styles.middle]: true, })} > 菜单配置 {nodeType ? ( <EditForm nodeType={nodeType} info={info} infoAll={infoAll} checkList={checkList} configFiles={configFiles} productList={productList} submitCallback={editSubmitCallback} valueCallback={valueCallback} /> ) : ( <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="当前未选中菜单" /> )} </div> <ImportOrExport visible={importOrExportVisible} onFinish={onFinishCallBack} onCancel={() => { setImportOrExportVisible(false); getTree(); }} subSystemValue={subSystemValue} nodeObj={nodeObj} /> {/* <div className={classnames({ [styles.rightBox]: true, })} > 关联角色 <CheckList info={info} nodeType={nodeType} valueCallback={valueCallback} /> </div> */} </div> </Spin> ); }; export default MiniMenu;