You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

439 lines
19 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React, { useState, useEffect } from 'react'
import { history, Outlet, useLocation, matchRoutes, useModel } from '@umijs/max'
import { Menu, Tabs, Select } from 'antd'
import './SystemContentList.less'
import { formatRoute, getDefaultRoute } from '@/utils/routeUtils'
import styles from './TopNavBar.less'
import { Row, Col, Avatar, Dropdown, Button } from 'antd'
import { userInfo } from '@/utils/globalCommon'
import { HomeOutlined, LogoutOutlined, AppstoreOutlined, UserOutlined, SettingOutlined, DatabaseOutlined, FileTextOutlined, LockOutlined, AreaChartOutlined, CaretDownOutlined, BellOutlined, SearchOutlined, QuestionCircleOutlined } from '@ant-design/icons'
import { getPageQuery } from '@/utils/utils'
import menuTitle from '@/assets/img/智能管控平台.svg'
import menuTitle1 from '@/assets/img/智能管控平台-1.svg'
import fireHydrant from '@/assets/img/fireHydrant.svg'
import fireHydrant1 from '@/assets/img/fireHydrant1.svg'
import menuicon1 from '@/assets/img/menuicon1.svg'
import menuicon2 from '@/assets/img/menuicon2.svg'
import menuicon3 from '@/assets/img/menuicon1.svg'
import menuicon4 from '@/assets/img/menuicon1.svg'
import book from '@/assets/img/book.svg'
import danger from '@/assets/img/danger.svg'
import danger1 from '@/assets/img/danger1.svg'
import license from '@/assets/img/license.svg'
import people from '@/assets/img/people.svg'
import risk from '@/assets/img/risk.svg'
import { CustomBreadcrumb } from '@/components/GlobalComponent'
// 自定义菜单项渲染组件,支持根据激活状态显示不同图片
const CustomMenuItem = ({ item, selectedKeys }) => {
const isActive = selectedKeys.includes(item.key);
// 为每个菜单项定义激活状态的图片
// 如果没有专门的激活状态图片,则使用默认图片
const getActiveIcon = (baseIcon) => {
// 这里可以根据需要为每个图标定义对应的激活状态图片
// 目前暂时使用相同的图片,用户可以根据实际情况替换
return baseIcon;
};
const renderIcon = () => {
if (item.icon && typeof item.icon === 'object' && item.icon.props && item.icon.props.src) {
const iconSrc = isActive ? getActiveIcon(item.icon.props.src) : item.icon.props.src;
const baseStyle = item.icon.props.style || { width: '16px', height: '16px' };
const dynamicStyle = {
...baseStyle,
opacity: isActive ? 1 : 0.6
};
return <img
src={iconSrc}
alt={item.icon.props.alt || 'menu icon'}
style={dynamicStyle}
/>
}
return item.icon;
};
const renderMenuItem = (menuItem) => ({
...menuItem,
icon: renderIcon(),
children: menuItem.children?.map(child => renderMenuItem(child))
});
return renderMenuItem(item);
};
const SystemContentList = (props) => {
const dynamicRoute = window.dynamicRoute
console.log(dynamicRoute)
const location = useLocation()
const pathName = location.pathname
const [openKey, setOpenKey] = useState([])
const [selectedKey, setSelectedKey] = useState([])
const [menuItems, setMenuItems] = useState([])
const [systemType, setSystemType] = useState('应急管理系统')
const [isMenuCollapsed, setIsMenuCollapsed] = useState(false); // 添加菜单收缩状态
let defaultKey = ''
useEffect(() => {
console.log('dynamicRoute structure:', dynamicRoute)
if (!dynamicRoute || dynamicRoute?.length === 0) return
let newList = []
let routes = []
if (dynamicRoute?.length) {
let tempRoute = dynamicRoute?.filter(item => pathName.indexOf(item.key) !== -1) ?? []
newList = formatRoute(tempRoute[0]?.children)
routes = formatRoute(tempRoute[0]?.children, true)
defaultKey = getDefaultRoute(routes)
const mathRoute = matchRoutes(routes, pathName)
setRouteActive({ key: mathRoute?.length ? pathName : defaultKey }, routes)
}
setMenuItems(newList)
const fixedMenuItems = [
{
"path": "/topnavbar00/business/emergencyResource",
icon: <img src={menuicon1} alt="应急资源管理" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/business/emergencyResource",
"label": "应急资源管理"
},
// 应急预案管理
{
"path": "/topnavbar00/business/emergencyPlan",
icon: <img src={menuicon2} alt="应急预案管理" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/business/emergencyPlan",
"label": "应急预案管理"
},
// 应急演练管理
{
"path": "/topnavbar00/business/emergencyDrill",
icon: <img src={menuicon3} alt="应急演练管理" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/business/emergencyDrill",
"label": "应急演练管理"
},
// 应急值班管理
{
"path": "/topnavbar00/business/emergencyDuty",
icon: <img src={menuicon4} alt="应急值班管理" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/business/emergencyDuty",
"label": "应急值班管理"
},
// 事故接警单
{
"path": "/topnavbar00/business/emergencyAccident",
icon: <img src={menuicon1} alt="事故接警单" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/business/emergencyAccident",
"label": "事故接警单"
},
]
setMenuItems(fixedMenuItems)
// 初始化默认路由
const defaultRoute = fixedMenuItems[0]?.key || ''
const mathRoute = matchRoutes(fixedMenuItems, pathName)
setRouteActive({ key: mathRoute?.length ? pathName : defaultRoute }, fixedMenuItems)
}, [pathName])
const setRouteActive = (value, menu) => {
const curKey = value.key
const tempMenu = menu ?? menuItems ?? []
const mathRoute = matchRoutes(tempMenu, curKey)
let openKeys = []
let selectedKeys = []
mathRoute?.map((item, index) => {
mathRoute?.length !== index + 1 && (openKeys = [...openKeys, item.pathname])
mathRoute?.length === index + 1 && (selectedKeys = [...selectedKeys, item.pathname])
})
setOpenKey(openKeys)
setSelectedKey(selectedKeys)
history.replace(curKey)
}
// 切换菜单收缩状态
const toggleMenu = () => {
setIsMenuCollapsed(!isMenuCollapsed);
};
const { initialState: { menu }, setInitialState } = useModel('@@initialState')
const loginOut = async () => {
// await outLogin()
const { redirect } = getPageQuery()
if (window.location.pathname !== '/login/login' && !redirect) {
history.replace({
pathname: '/login',
// search: stringify({
// redirect: window.location.href,
// }),
})
setInitialState({ currentUser: null, menu: null, menuMap: null })
window.dynamicRoute = null
localStorage.clear()
}
}
const handleMenuClick = (e) => {
switch (e.key) {
case 'logout':
loginOut()
break
default:
break
}
}
const dropDownMenuItems = [
{
label: <><LogoutOutlined style={{ marginRight: '8px' }} />退出登录</>,
key: 'logout'
}
]
const dropDownMenu = () => (
<Menu items={dropDownMenuItems} onClick={handleMenuClick} selectedKeys={[]} className={styles.tabBarMenu} />
)
return (
<div className='pageContainer systemContent'>
<div
className='leftMenu'
style={{
width: isMenuCollapsed ? '80px' : '230px',
transition: 'width 0.3s ease',
position: 'relative', // 添加相对定位,使按钮可以相对于菜单定位
overflow: 'unset'
}}
>
<div className='menuTitle' style={{
marginBottom: '10px',
display: isMenuCollapsed ? 'none' : 'flex'
}}>
<img src={menuTitle} alt='menuTitle' style={{ marginTop: '20px', marginBottom: '2px', width: '172.44px', height: '51.28px' }} />
<img src={menuTitle1} alt='menuTitle1' style={{ width: '172.44px', height: '51.28px' }} />
</div>
<div style={{
textAlign: 'center',
marginBottom: 16,
borderRadius: "10px !important",
display: isMenuCollapsed ? 'none' : 'block'
}}>
<Select
value={systemType}
onChange={setSystemType}
style={{
width: 192,
height: 42
}}
options={[
{ value: '安全管理系统', label: '安全管理系统' },
{ value: '环保管理系统', label: '环保管理系统' },
{ value: '消防管理系统', label: '消防管理系统' },
{ value: '智能巡检系统', label: '智能巡检系统' },
{ value: '应急管理系统', label: '应急管理系统' }
]}
dropdownStyle={{
backgroundColor: '#003AA7',
borderColor: '#3D81FF'
}}
popupClassName="custom-select-dropdown"
className="custom-select"
suffixIcon={<CaretDownOutlined style={{ color: '#fff', fontSize: '16px' }} />}
/>
</div>
<style jsx>{`
.custom-select .ant-select-selector {
height: 42px !important;
border-radius: 8px !important;
border-color: #3D81FF !important;
background-color: #003AA7 !important;
color: #fff !important;
fontSize: 22px !important;
fontWeight: 600 !important;
}
.custom-select .ant-select-selection-item {
color: #fff !important;
fontSize: 22px !important;
fontWeight: 600 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0 !important;
padding-right: 50px !important;
font-size: 16px !important;
font-weight: 500 !important;
}
.custom-select .ant-select-arrow {
opacity: 0.66 !important;
color: #fff !important;
}
.custom-select-dropdown .ant-select-item-option-selected {
background-color: #3D81FF !important;
color: #fff !important;
}
.custom-select-dropdown .ant-select-item-option-active:not(.ant-select-item-option-selected) {
background-color: rgba(61, 129, 255, 0.1) !important;
color: #fff !important;
}
.custom-select-dropdown .ant-select-item-option-content {
color: #fff !important;
font-size: 16px !important;
font-weight: 600 !important;
}
.menuToggleBtn {
position: absolute;
right: -15px;
top: 50%;
width: 30px;
height: 30px;
background: #FDFDFF;
color: #5C5C5C;
border: 1px solid #FFFFFF;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 9999; /* 增加z-index确保按钮在最上层 */
font-size: 16px;
font-weight: bold;
outline: none;
transition: all 0.3s ease;
box-shadow: 0 0 5px 3px rgba(169, 185, 255, 0.33);
}
.menuToggleBtn:hover {
border: 1px solid #3D81FF;
background: #3D81FF;
color: white;
transform: scale(1.1);
}
`}</style>
{/* 菜单收缩按钮 */}
<button
className="menuToggleBtn"
onClick={toggleMenu}
aria-label={isMenuCollapsed ? "展开菜单" : "收缩菜单"}
>
{isMenuCollapsed ? ">" : "<"}
</button>
<Menu
openKeys={openKey}
selectedKeys={selectedKey}
// 使用自定义的itemRender方法处理激活状态的图标切换
items={menuItems.map(item => {
const isActive = selectedKey.includes(item.key);
// 处理当前项的图标
let icon = item.icon;
if (icon && typeof icon === 'object' && icon.props && icon.props.src) {
let iconSrc = icon.props.src;
// 根据激活状态切换不同的图片
if (isActive) {
// 工时仪表盘激活态使用fireHydrant1
if (item.key === '/topnavbar00/business/timesheet' && typeof fireHydrant !== 'undefined') {
iconSrc = fireHydrant;
}
// 隐患排查激活态使用danger1
else if (item.key === '/topnavbar00/business/hiddentrouble' && typeof danger1 !== 'undefined') {
iconSrc = danger1;
}
// 激活态使用danger1
else if (item.key === '/topnavbar00/business/staffsheet' && typeof danger1 !== 'undefined') {
iconSrc = danger1;
}
}
const baseStyle = icon.props.style || { width: '16px', height: '16px' };
const dynamicStyle = {
...baseStyle,
opacity: isActive ? 1 : 0.6
};
icon = <img
src={iconSrc}
alt={icon.props.alt}
style={dynamicStyle}
/>;
}
// 递归处理子项
const children = item.children?.map(child => {
const childIsActive = selectedKey.includes(child.key);
return { ...child };
});
return {
...item,
icon,
children,
// 根据菜单收缩状态决定是否显示标签文本
label: isMenuCollapsed ? null : item.label
};
})}
onClick={value => setRouteActive(value)}
onOpenChange={value => setOpenKey(value)}
mode={isMenuCollapsed ? 'vertical' : 'inline'}
/>
</div>
<div
className='rightContent'
style={{
width: isMenuCollapsed ? 'calc(100% - 80px)' : 'calc(100% - 230px)',
transition: 'width 0.3s ease'
}}
>
{/* <div style={{ width: '100%', backgroundColor: '#fff', marginBottom: '10px' }}> */}
<div className='tabBarHeader'>
<Row className='tabBarRow'>
{/* <Col xs={16} sm={16} md={16} lg={16} xl={16} className='tabBarLeft'>
<img src={Logo} alt='logo' className='leftLogo' />
<Menu mode='horizontal' className='leftMenu' selectedKeys={[activeKey]} items={menuItems} onClick={value => setRouteActive(value)} />
</Col> */}
<Col xs={20} sm={20} md={20} lg={20} xl={20} className='tabBarLeft'>
<CustomBreadcrumb />
</Col>
<Col xs={4} sm={4} md={4} lg={4} xl={4} className='tabBarRight'>
<Button type='text' className='tabBarRightBtn'><BellOutlined /></Button>
<Button type='text' className='tabBarRightBtn'><SearchOutlined /></Button>
<Button type='text' className='tabBarRightBtn'><QuestionCircleOutlined /></Button>
<Avatar className='tabBarRightAvaTor' src='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201707%2F31%2F20170731021444_2YUfe.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1669779871&t=ec025ed48a1668dee9cfa0e803b6f787' />
<span className='tabBarRightName'>{userInfo?.user_name_cn ? userInfo.user_name_cn : (userInfo?.user_name || '')}</span>
<Dropdown dropdownRender={dropDownMenu}>
<Button type='text' className='tabBarRightBtn'><SettingOutlined /></Button>
</Dropdown>
</Col>
</Row>
</div>
{/* </div> */}
<div style={{ padding: '12px', height: '100%' }}>
<div className='rightContentMain'>
<Outlet />
</div>
</div>
</div>
</div>
)
}
export default SystemContentList