/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable no-param-reassign */ import React, { useState, Suspense, useRef, useMemo } from 'react'; import { Layout, Menu, Skeleton, Input, Row, Col, Empty } from 'antd'; import { Link, history, useModel, useLocation } from '@umijs/max'; import styles from './index.less'; import { Scrollbars } from 'react-custom-scrollbars'; import { collectPerms, cancelCollectPerms, mtosave } from '@/services/login'; import * as Ant4Icons from '@ant-design/icons'; const { Sider } = Layout; function strToHump(str) { if (!str) return; let strArr = str.split('-'); for (let i = 0; i < strArr.length; i++) { strArr[i] = strArr[i].charAt(0).toUpperCase() + strArr[i].substr(1); } let res = strArr.join(''); return res + 'Outlined'; } let CardItems = (datav, i, getstar, addHistory) => { let name = datav.name, collected = datav.isExist == '1', icon = datav.icon ? strToHump(datav.icon) : 'ToolOutlined', ItemIcon = icon ? Ant4Icons[icon] : Ant4Icons['ToolOutlined']; return ( <div key={i} className={styles.carditem} onClick={async () => { history.push(datav.path); await addHistory(datav.key); }} > <a className={styles.diylink}> {' '} {React.createElement(Ant4Icons[icon], { style: { marginRight: 6 } })} {name} </a> {collected ? ( <Ant4Icons.StarFilled className={styles.collected} onClick={async (e) => { getstar(e, collected, datav.key); }} /> ) : ( <Ant4Icons.StarOutlined className={styles.tocollect} onClick={async (e) => { getstar(e, collected, datav.key); }} /> )} </div> ); }, coles = { xs: 24, sm: 24, md: 12, lg: 8, xl: 6, xxl: 4 }; function SiderMenu({ logo, collapsed, onCollapse, fixSiderbar, theme, isMobile, name, menuData }) { let location = useLocation(); const [anchor, setanchor] = useState(); const [search, setsearch] = useState(); const scrollRef = useRef(); const { alive, changealive } = useModel('useGlobal'); const { initialState: { getmenuData, newMenu }, setInitialState, } = useModel('@@initialState'); const getMenuData = newMenu?.userHavePermList ?? [], collectPerm = newMenu?.collectPerm ?? [], recentUsePermList = newMenu?.recentUsePermList ?? []; let scrollToAnchor = (anchorName) => { if (anchorName) { setanchor(anchorName); let anchorElement = document.getElementById(anchorName); if (scrollRef) { // anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' }); scrollRef?.current?.scrollTop(anchorElement.offsetTop); } } }; let filterMenu = (alldata, search) => { if (!search) { return alldata; } alldata = alldata ?? []; let newdata = alldata.filter((item) => { return ( item.routes && item.routes.some((it) => { return it.name.indexOf(search) != -1; }) ); }); return newdata.map((item) => { return { ...item, routes: item.routes.filter((it) => { return it.name.indexOf(search) != -1; }), }; }); }; const refreshs = async () => { const menuDatas = await getmenuData(); if (menuDatas) { await setInitialState((s) => { return { ...s, newMenu: menuDatas }; }); } }; async function getstar(e, collected, permissionId) { e.stopPropagation(); if (collected) { let cancelData = await cancelCollectPerms({ permissionId }); if (cancelData.code == '0000') { await refreshs(); } } else { let collectData = await collectPerms({ permissionId }); if (collectData.code == '0000') { await refreshs(); } } } async function addHistory(permissionId) { let cancelData = await mtosave({ permissionId }); if (cancelData.code == '0000') { changealive(false); await refreshs(); } } const collectList = useMemo(() => { return collectPerm.map((item, i) => { const icon = item.icon ?? strToHump(item.icon), ItemIcon = icon ? Ant4Icons[icon] : Ant4Icons.ToolOutlined; return { key: item.path, icon: <ItemIcon />, label: ( <div style={{ flex: 1, display: 'flex', justifyContent: 'space-between', alignItems: 'center', }} > {item.name} <Ant4Icons.CloseOutlined className={styles.closeicon} style={{ fontSize: 12 }} onClick={async (e) => { e.stopPropagation(); await getstar(e, true, item.key); }} /> </div> ), }; }); }, [collectPerm]); return ( <Sider trigger={null} collapsible collapsed={collapsed} width={208} theme={'dark'} collapsedWidth={48} > <div style={{ height: '100vh', display: 'flex', flexDirection: 'column', position: 'relative', top: 0, }} > <Suspense fallback={<div style={{ width: '100vw', height: '100vh' }} />}> <div style={{ height: 'calc(100vh - 48px)', overflow: 'auto' }}> { <div className={styles.fate}> <Scrollbars thumbMinSize={10} autoHide style={{ width: '100%', height: '100%', position: 'absolute', left: 0, zIndex: 999, backgroundColor: '#001529', }} hideTracksWhenNotNeeded={true} > <div className={styles.logo} id="logo"> <Link to="/welcome"> <img src={logo} alt="logo" /> <h1 style={{ fontSize: 12 }}>{name}</h1> </Link> </div> <Menu collapsedWidth={48} mode="inline" theme="dark" selectedKeys={[location.pathname]} collapsed={collapsed.toString()} onClick={async ({ item, key, keyPath, domEvent }) => { if (key == '0') { changealive(!alive); return; } await addHistory(item.key); history.push(key); }} items={[ { key: '0', icon: alive ? ( <Ant4Icons.RightCircleOutlined /> ) : ( <Ant4Icons.DownCircleOutlined /> ), label: '产品与服务', type: 'sub1', }, ...collectList, ]} /> </Scrollbars> <div className={alive ? styles.containbox : styles.containboxs} style={{ transition: 'all 0.4s', display: 'flex', flexDirection: 'column', }} > <Skeleton active loading={false}> <header style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderBottom: '#ddd solid 1px', paddingBottom: 8, }} > <Input prefix={<Ant4Icons.SearchOutlined style={{ color: 'rgba(0,0,0,1)' }} />} placeholder="输入关键词查找模块" allowClear className={styles.diyinput} value={search} onChange={(e) => { setsearch(e.target.value); }} /> <Ant4Icons.CloseOutlined style={{ fontSize: 16, marginLeft: 24, color: '#ff6800' }} onClick={() => { changealive(false); }} /> </header> <section style={{ display: 'flex', justifyContent: 'space-between', flex: 1, overflow: 'hidden', }} > <div style={{ flex: 1, height: '100%', overflow: 'auto', overflowX: 'hidden', }} > <Scrollbars thumbMinSize={10} autoHide style={{ width: '100%', height: '100%' }} ref={scrollRef} hideTracksWhenNotNeeded={true} > <div className={styles.section} style={{ marginBottom: 18 }}> <h2>历史记录</h2> <Row gutter={0}> {recentUsePermList && recentUsePermList.map((item, i) => { return ( <Col key={i} {...coles}> {CardItems(item, i, getstar, addHistory)} </Col> ); })} </Row> </div> {search && <p>搜索条件:{search},搜索结果:</p>} <div className={styles.column}> {getMenuData && filterMenu(getMenuData, search).map((item, i) => { const icon = item.icon ?? strToHump(item.icon), ItemIcon = icon ? Ant4Icons[icon] : Ant4Icons['ToolOutlined']; return ( <div className={styles.item} key={i}> <h2 id={item.key} className={anchor == item.key ? styles.activeh2 : ''} > {' '} <ItemIcon style={{ marginRight: 6 }} /> {item.name} </h2> {item.routes && item.routes.map((it, ins) => { return it ? CardItems(it, ins, getstar, addHistory) : null; })} </div> ); })} </div> {filterMenu(getMenuData, search).length == 0 && <Empty />} </Scrollbars> </div> <div className={styles.rt}> {getMenuData && getMenuData.map((item, i) => { const icon = item.icon ?? strToHump(item.icon), ItemIcon = icon ? Ant4Icons[icon] : Ant4Icons['ToolOutlined']; return ( <p className={styles.rtcarditem} key={i} onClick={() => { scrollToAnchor(item.key); }} > <ItemIcon style={{ marginRight: 6 }} /> {item.name} </p> ); })} </div> </section> </Skeleton> </div> </div> } </div> </Suspense> </div> </Sider> ); } export default SiderMenu;