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.

476 lines
22 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 riskClassification from '@/assets/img/riskclassification.svg'
import trouble from '@/assets/img/trouble.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 licenseLight from '@/assets/img/licenseLight.svg'
import people from '@/assets/img/people.svg'
import risk from '@/assets/img/risk.svg'
import safeEducationLight from '@/assets/img/safeEducationLight.svg'
import bookDark from '@/assets/img/bookDark.svg'
import bookLight from '@/assets/img/bookLight.svg'
import personnelPosition2 from '@/assets/img/personnelPosition2.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;
return <img
src={iconSrc}
alt={item.icon.props.alt || 'menu icon'}
style={item.icon.props.style || { width: '16px', height: '16px' }}
/>
}
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/hrefficiency/basicinformation",
icon: <img src={fireHydrant1} alt="安全管理基础信息" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/basicinformation",
"label": "安全管理基础信息"
},
{
"path": "/topnavbar00/hrefficiency/safeMajorHazard",
icon: <img src={danger} alt="重大危险源管理" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/safeMajorHazard",
"label": "重大危险源管理"
},
{
"path": "/topnavbar00/hrefficiency/riskclassification",
icon: <img src={risk} alt="风险分级管控" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/riskclassification",
"label": "风险分级管控"
},
{
"path": "/topnavbar00/hrefficiency/hiddentrouble",
icon: <img src={risk} alt="工时仪表盘" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/hiddentrouble",
"label": "隐患排查"
},
{
"path": "/topnavbar00/hrefficiency/safetraining",
icon: <img src={bookDark} alt="安全教育培训" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/safetraining",
"label": "安全教育培训"
},
{
"path": "/topnavbar00/hrefficiency/personnellocation",
icon: <img src={people} alt="人员定位" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/personnellocation",
"label": "人员定位"
},
{
"path": "/topnavbar00/hrefficiency/specialoperationpermit",
icon: <img src={license} alt="特殊作业许可" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/specialoperationpermit",
"label": "特殊作业许可"
},
{
"path": "/topnavbar00/hrefficiency/system",
icon: <img src={people} alt="工时仪表盘" style={{ width: '16px', height: '16px' }} />,
"key": "/topnavbar00/hrefficiency/system",
"label": "系统管理",
"children": [
{
"path": "/topnavbar00/hrefficiency/system/systemOrganization",
"key": "/topnavbar00/hrefficiency/system/systemOrganization",
"label": "组织管理"
},
{
"path": "/topnavbar00/hrefficiency/system/systemRole",
"key": "/topnavbar00/hrefficiency/system/systemRole",
"label": "角色配置"
},
{
"path": "/topnavbar00/hrefficiency/system/systemMenu",
"key": "/topnavbar00/hrefficiency/system/systemMenu",
"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,
display: isMenuCollapsed ? 'none' : 'block'
}}>
<Select
value={systemType}
onChange={setSystemType}
style={{
width: 192,
height: 42,
borderColor: '#3D81FF',
backgroundColor: '#003AA7',
borderRadius: 0,
color: '#fff',
fontSize: 22,
fontWeight: 600
}}
options={[
{ 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: 0 !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/hrefficiency/timesheet' && typeof fireHydrant !== 'undefined') {
iconSrc = fireHydrant;
}
// 隐患排查激活态使用danger1
else if (item.key === '/topnavbar00/hrefficiency/hiddentrouble' && typeof danger1 !== 'undefined') {
iconSrc = danger1;
}
// 激活态使用danger1
else if (item.key === '/topnavbar00/hrefficiency/staffsheet' && typeof danger1 !== 'undefined') {
iconSrc = danger1;
}
// 安全教育培训激活态使用bookLight
else if (item.key === '/topnavbar00/hrefficiency/safetraining' && typeof bookLight !== 'undefined') {
iconSrc = bookLight;
}
// 风险分级管控 菜单图标 激活态使用 riskclassification
else if (item.key === '/topnavbar00/hrefficiency/riskclassification' && typeof riskClassification !== 'undefined') {
iconSrc = riskClassification;
}
// 人员定位激活态使用personnelPosition2
else if (item.key === '/topnavbar00/hrefficiency/personnellocation' && typeof personnelPosition2 !== 'undefined') {
iconSrc = personnelPosition2;
}
// 特殊作业许可激活态使用licenseLight
else if (item.key === '/topnavbar00/hrefficiency/specialoperationpermit' && typeof licenseLight !== 'undefined') {
iconSrc = licenseLight;
}
}
icon = <img
src={iconSrc}
alt={icon.props.alt}
style={icon.props.style}
/>;
}
// 递归处理子项
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