import React, { useEffect, useRef, useState } from 'react'; import classNames from 'classnames'; import propTypes from 'prop-types'; import KeyCode from 'rc-util/lib/KeyCode'; import { Spin } from 'antd'; import Icon, { MenuOutlined } from '@ant-design/icons'; import { events } from '@wisdom-utils/utils/lib/helpers'; import Categories from './Categories'; import styles from './index.less'; import Menu from './Menu'; // eslint-disable-next-line import/extensions const ThLarge = props => ( <svg viewBox="0 0 1024 1024" version="1.1" width="14" height="14"> <path d="M592 64h384c26.51 0 48 21.49 48 48v320c0 26.51-21.49 48-48 48H592c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48z m-160 0H48C21.49 64 0 85.49 0 112v320c0 26.51 21.49 48 48 48h384c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zM0 592v320c0 26.51 21.49 48 48 48h384c26.51 0 48-21.49 48-48V592c0-26.51-21.49-48-48-48H48c-26.51 0-48 21.49-48 48z m592 368h384c26.51 0 48-21.49 48-48V592c0-26.51-21.49-48-48-48H592c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48z" fill="#737f97" /> </svg> ); const ThLargeIcon = props => <Icon component={ThLarge} {...props} />; const Panel = props => { const panelCls = classNames(styles.mainPane, props.visible ? styles.visible : styles.hidden); const domRef = useRef(); // eslint-disable-next-line no-debugger; const [currentMenu, setCurrentMenu] = useState(null); useEffect(() => { setCurrentMenu(props.data[props.currentMenuIndex]); }, [props.data, props.currentMenuIndex]); // eslint-disable-next-line no-underscore-dangle let _clickEvents = null; const handleKeyDown = event => { if (event.keyCode === KeyCode.ESC) { const { onClose } = props; event.stopPropagation(); if (onClose) { onClose(event); } } }; const domFocus = () => { if (domRef) { domRef.current.focus(); } }; const handleDocumentClick = e => { if (props.visible) { const node = domRef && domRef.current; if ( node && (node === e.target || node.contains(e.target) || (e.target !== document && !document.documentElement.contains(e.target))) ) { return; } // eslint-disable-next-line no-unused-expressions props.onClose && props.onClose(e); } }; const addDocumentEvents = () => { if (props.canCloseByOutSideClick) { _clickEvents = events.on(document, 'click', handleDocumentClick); } }; const removeDocumentEvents = () => { _clickEvents.off(); _clickEvents = null; }; const getCategories = () => { let { data } = props; // eslint-disable-next-line no-prototype-builtins data = data.filter(item => item.hasOwnProperty('extData')); return data; }; const handleCategories = index => { setCurrentMenu(props.data[index]); // eslint-disable-next-line no-unused-expressions props.onChange && props.onChange(index); }; const selectItem = (event, item) => { // eslint-disable-next-line no-unused-expressions props.onSelect && props.onSelect(item); }; useEffect(() => { if (props.visible) { domFocus(); } addDocumentEvents(); return () => removeDocumentEvents(); }, [addDocumentEvents, props.visible, removeDocumentEvents]); return ( <div className={panelCls} tabIndex="-1" onKeyDown={event => (props.visible && props.keyboard ? handleKeyDown(event) : undefined)} ref={domRef} > <div className={styles.header}> <ThLargeIcon /> <div className={styles['header-title']}>切换子系统</div> <span className={styles.subheader}> <MenuOutlined /> 子系统功能一览 </span> <span className={styles.marks}> <img src="https://panda-water.cn/web4/assets/images/waterMarks/%E8%8F%9C%E5%8D%95%E6%B0%B4%E5%8D%B0.SVG" alt="" /> </span> </div> <div className={styles.main}> <div className={styles['main-left']}> <Categories data={getCategories()} onChange={handleCategories} currentMenuIndex={props.currentMenuIndex} /> </div> <div className={styles['main-menus']}> <Spin spinning={!currentMenu}> <Menu data={currentMenu || []} handleClick={selectItem} /> </Spin> </div> </div> </div> ); }; Panel.propTypes = { visible: propTypes.bool, keyboard: propTypes.bool, onClose: propTypes.func, canCloseByOutSideClick: propTypes.bool, }; Panel.defaultProps = { visible: false, keyboard: true, canCloseByOutSideClick: true, onClose: () => {}, }; export default Panel;