diff --git a/src/assets/img/book.svg b/src/assets/img/book.svg
new file mode 100644
index 0000000..d1aef3b
--- /dev/null
+++ b/src/assets/img/book.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/danger.svg b/src/assets/img/danger.svg
new file mode 100644
index 0000000..e87d4a6
--- /dev/null
+++ b/src/assets/img/danger.svg
@@ -0,0 +1,10 @@
+
diff --git a/src/assets/img/danger1.svg b/src/assets/img/danger1.svg
new file mode 100644
index 0000000..9be66a6
--- /dev/null
+++ b/src/assets/img/danger1.svg
@@ -0,0 +1,10 @@
+
diff --git a/src/assets/img/fireHydrant.svg b/src/assets/img/fireHydrant.svg
new file mode 100644
index 0000000..a15c04a
--- /dev/null
+++ b/src/assets/img/fireHydrant.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/assets/img/fireHydrant1.svg b/src/assets/img/fireHydrant1.svg
new file mode 100644
index 0000000..0c7b497
--- /dev/null
+++ b/src/assets/img/fireHydrant1.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/assets/img/license.svg b/src/assets/img/license.svg
new file mode 100644
index 0000000..a6996e5
--- /dev/null
+++ b/src/assets/img/license.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/img/people.svg b/src/assets/img/people.svg
new file mode 100644
index 0000000..7e68013
--- /dev/null
+++ b/src/assets/img/people.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/img/risk.svg b/src/assets/img/risk.svg
new file mode 100644
index 0000000..d51b483
--- /dev/null
+++ b/src/assets/img/risk.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/trouble.svg b/src/assets/img/trouble.svg
new file mode 100644
index 0000000..94d7763
--- /dev/null
+++ b/src/assets/img/trouble.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/智能管控平台-1.svg b/src/assets/img/智能管控平台-1.svg
new file mode 100644
index 0000000..06f318c
--- /dev/null
+++ b/src/assets/img/智能管控平台-1.svg
@@ -0,0 +1,40 @@
+
diff --git a/src/assets/img/智能管控平台.svg b/src/assets/img/智能管控平台.svg
new file mode 100644
index 0000000..e46fcc8
--- /dev/null
+++ b/src/assets/img/智能管控平台.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/components/GlobalComponent/Breadcrumb.jsx b/src/components/GlobalComponent/Breadcrumb.jsx
new file mode 100644
index 0000000..711faac
--- /dev/null
+++ b/src/components/GlobalComponent/Breadcrumb.jsx
@@ -0,0 +1,268 @@
+import React, { useState, useEffect } from 'react';
+import { Breadcrumb } from 'antd';
+import { CloseCircleOutlined } from '@ant-design/icons';
+import { history, useLocation } from '@umijs/max';
+import './breadcrumb.less';
+
+const CustomBreadcrumb = () => {
+ // 从sessionStorage初始化面包屑数据,与Vue实例保持一致
+ const [breadcrumbList, setBreadcrumbList] = useState(() => {
+ return JSON.parse(sessionStorage.getItem('breadcrumb')) || [];
+ });
+
+ const [currentRouterName, setCurrentRouterName] = useState('');
+
+ const location = useLocation();
+
+ // 递归搜索window.dynamicRoute中匹配当前路径的路由项
+ const findMatchedRoute = (routes, pathname) => {
+ for (const route of routes) {
+ // 检查当前路由项是否匹配
+ if (route.key === pathname) {
+ return route;
+ }
+ // 如果有子路由,递归搜索
+ if (route.children && route.children.length > 0) {
+ const matchedChild = findMatchedRoute(route.children, pathname);
+ if (matchedChild) {
+ return matchedChild;
+ }
+ }
+ }
+ return null;
+ };
+
+ // 获取当前路由的真实信息
+ const getCurrentRoute = () => {
+ const pathname = location.pathname || '/';
+ const href = window.location.href;
+
+ console.log('当前路径:', pathname);
+
+ // 使用自定义函数在window.dynamicRoute中匹配当前路径
+ let matchedRoute = null;
+ if (window.dynamicRoute && Array.isArray(window.dynamicRoute)) {
+ matchedRoute = findMatchedRoute(window.dynamicRoute, pathname);
+ }
+
+ console.log('匹配的路由:', matchedRoute);
+
+ // 如果有匹配的路由,获取路由信息
+ if (matchedRoute) {
+ // 使用route.label作为标题,route.key作为路径标识符
+ const routeTitle = matchedRoute.label || '未知页面';
+ const routeKey = matchedRoute.key || pathname;
+
+ return {
+ name: routeKey.replace(/\//g, '_').slice(1) || 'home',
+ path: pathname,
+ href,
+ fullPath: href,
+ meta: {
+ title: routeTitle,
+ affix: pathname === '/'
+ }
+ };
+ }
+
+ // 如果没有从window.dynamicRoute中匹配到路由,使用原来的逻辑处理
+ // 将路径按照/分割,获取最后一段作为名称
+ const parts = pathname.split('/').filter(Boolean);
+
+ // 根路径处理
+ if (parts.length === 0) {
+ return {
+ name: 'home',
+ path: pathname,
+ href,
+ fullPath: href,
+ meta: {
+ title: '首页',
+ affix: true
+ }
+ };
+ }
+
+ // 获取最后一段作为页面名称
+ const lastPart = parts[parts.length - 1];
+
+ // 使用最后一段作为标题
+ const routeTitle = lastPart || '未知页面';
+
+ return {
+ name: lastPart.replace(/\//g, '_') || 'home',
+ path: pathname,
+ href,
+ fullPath: href,
+ meta: {
+ title: routeTitle,
+ affix: pathname === '/'
+ }
+ };
+ };
+
+ // 生成面包屑数据 - 修复了path指向错误的问题
+ const generateBreadcrumb = () => {
+ // 从当前路由获取信息
+ const currentRoute = getCurrentRoute();
+ const { meta: { title }, name, path } = currentRoute;
+
+ // 如果title存在,将路由信息添加到breadcrumbList数组
+ if (title) {
+ const newBreadcrumbList = [...breadcrumbList];
+ newBreadcrumbList.push({
+ name,
+ path: path, // 正确使用当前路由的path属性
+ title
+ });
+
+ // 使用reduce方法对breadcrumbList进行去重处理,与Vue组件完全一致
+ const uniqueList = newBreadcrumbList.reduce((accumulator, current) => {
+ const x = accumulator.find(item => item.name === current.name);
+
+ if (!x) {
+ return accumulator.concat(current);
+ } else {
+ accumulator.forEach((val, i) => {
+ if (val.name == current.name) {
+ val.title = current.title;
+ val.path = current.path;
+ }
+ });
+ return accumulator;
+ }
+ }, []);
+
+ // 将处理后的面包屑数据存储到sessionStorage中
+ setBreadcrumbList(uniqueList);
+ sessionStorage.setItem('breadcrumb', JSON.stringify(uniqueList));
+ }
+ };
+
+ // 处理导航逻辑
+ const toPath = (item) => {
+ const currentRoute = getCurrentRoute();
+ // 如果路径相同,点击导航则不跳转
+ if (item.name === currentRoute.name) {
+ return '';
+ }
+ // 如果是固定路由,则不跳转
+ if (item.meta?.affix) {
+ return '';
+ } else {
+ // 跳转路由
+ return item.path;
+ }
+ };
+
+ // 关闭面包屑项,先跳转再删除面包屑
+ const cloneCurrentPage = (item, index) => {
+ // 如果没有面包屑页面或只剩一个页面,跳转到根目录
+ if (!breadcrumbList || breadcrumbList.length <= 1) {
+ // 使用window.location.href进行有感刷新
+ window.location.href = '/';
+ return;
+ }
+
+ const updatedList = [...breadcrumbList];
+ updatedList.splice(index, 1);
+
+ let length = updatedList.length;
+ // 先进行页面跳转
+ if (currentRouterName === item.name && length > 0) {
+ // 使用history进行无刷新跳转
+ history.push(updatedList[length - 1].path);
+ }
+
+ // 然后删除面包屑项
+ setBreadcrumbList(updatedList);
+ sessionStorage.setItem('breadcrumb', JSON.stringify(updatedList));
+ };
+
+ // 处理面包屑项点击事件
+ const handleItemClick = (item) => {
+ const path = toPath(item);
+ if (path) {
+ console.log(currentRouterName, 'yp')
+ // 使用history进行无刷新跳转
+ history.push(path);
+ }
+ };
+
+ // 组件挂载时初始化
+ useEffect(() => {
+ const currentRoute = getCurrentRoute();
+ setCurrentRouterName(currentRoute.name);
+ generateBreadcrumb();
+ }, []);
+
+ // 监听路由变化,当路由变化时触发generateBreadcrumb方法
+ useEffect(() => {
+ const handleRouteChange = () => {
+ const currentRoute = getCurrentRoute();
+ setCurrentRouterName(currentRoute.name);
+ generateBreadcrumb();
+ };
+
+ // 监听浏览器前进后退事件
+ window.addEventListener('popstate', handleRouteChange);
+
+ // 重写pushState和replaceState方法以捕获更多路由变化
+ const originalPushState = window.history.pushState;
+ const originalReplaceState = window.history.replaceState;
+
+ window.history.pushState = function (...args) {
+ originalPushState.apply(this, args);
+ handleRouteChange();
+ };
+
+ window.history.replaceState = function (...args) {
+ originalReplaceState.apply(this, args);
+ handleRouteChange();
+ };
+
+ // 监听hash变化(针对hash路由)
+ window.addEventListener('hashchange', handleRouteChange);
+
+ return () => {
+ window.removeEventListener('popstate', handleRouteChange);
+ window.removeEventListener('hashchange', handleRouteChange);
+ // 还原原始方法
+ window.history.pushState = originalPushState;
+ window.history.replaceState = originalReplaceState;
+ };
+ }, [breadcrumbList, location]);
+
+ // 当location.pathname变化时,自动更新currentRouterName
+ useEffect(() => {
+ const currentRoute = getCurrentRoute();
+ setCurrentRouterName(currentRoute.name);
+ }, [location.pathname]);
+
+ return (
+
+
+ {breadcrumbList.map((item, index) => (
+ handleItemClick(item)}
+ className={`breadcrumb-item ${item.name === currentRouterName ? 'breadcrumb-item-active' : ''}`}
+ >
+
+ {item.title}
+ {
+ e.stopPropagation();
+ cloneCurrentPage(item, index);
+ }}
+ />
+
+
+ ))}
+
+
+ );
+};
+
+export default CustomBreadcrumb;
\ No newline at end of file
diff --git a/src/components/GlobalComponent/breadcrumb.less b/src/components/GlobalComponent/breadcrumb.less
new file mode 100644
index 0000000..8efef5b
--- /dev/null
+++ b/src/components/GlobalComponent/breadcrumb.less
@@ -0,0 +1,163 @@
+// 面包屑容器样式
+.bread-crumb {
+ // display: flex;
+ align-items: center;
+ overflow-x: auto;
+ overflow-y: hidden;
+ height: auto;
+ max-width: 100%;
+ margin: 8px 0;
+ padding: 0 12px;
+ background-color: transparent;
+ flex-wrap: nowrap;
+ justify-content: flex-start;
+ box-sizing: border-box;
+}
+
+// 面包屑容器滚动条样式
+.bread-crumb::-webkit-scrollbar {
+ height: 4px;
+}
+
+.bread-crumb::-webkit-scrollbar-track {
+ background-color: #f1f1f1;
+ border-radius: 2px;
+}
+
+.bread-crumb::-webkit-scrollbar-thumb {
+ background-color: #c1c1c1;
+ border-radius: 2px;
+}
+
+.bread-crumb::-webkit-scrollbar-thumb:hover {
+ background-color: #a1a1a1;
+}
+
+// 面包屑导航容器
+.ant-breadcrumb {
+ display: flex !important;
+ flex-wrap: nowrap !important;
+ align-items: center;
+ gap: 8px;
+ margin: 0;
+ padding: 0;
+}
+
+// 面包屑项基础样式
+.breadcrumb-item {
+ height: 32px;
+ padding: 0 12px;
+ border-radius: 8px;
+ // 使用rgba格式设置带透明度的背景色,最后一个参数0.13表示13%的透明度
+ background-color: rgba(186, 186, 186, 0.13);
+ // border: 1px solid #E8E8E8;
+ margin-right: 8px;
+ display: flex;
+ align-items: center;
+ transition: all 0.3s ease;
+ cursor: pointer;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 180px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
+ box-sizing: border-box;
+
+ // 移除默认的分隔符
+ .ant-breadcrumb-separator {
+ display: none !important;
+ }
+
+ // 链接样式
+ .ant-breadcrumb-link {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ color: #808080 !important;
+ background: transparent !important;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: 100%;
+ }
+
+ // 悬停效果
+ &:hover {
+ border-color: #0056FF;
+ // transform: translateY(-1px);
+ box-shadow: 0 4px 8px rgba(0, 86, 255, 0.1);
+ }
+}
+
+// 面包屑项选中状态样式
+.breadcrumb-item-active {
+ background-color: rgba(94, 121, 246, 0.13);
+ // border-color: #0056FF;
+
+ .ant-breadcrumb-link {
+ color: #0056FF !important;
+ font-weight: 500;
+ }
+}
+
+// 面包屑文本选中状态样式 - 对应第252行代码中的条件样式
+.breadcrumb-item-text-active {
+ color: #0056FF !important;
+ font-weight: 500;
+}
+
+// 面包屑项内容容器
+.breadcrumb-item-content {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: 100%;
+}
+
+// 面包屑项文本样式
+.breadcrumb-item-text {
+ font-weight: 500;
+ font-size: 16px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ flex: 1;
+
+ .breadcrumb-item-text-active {
+ color: #0056FF !important;
+ }
+}
+
+// 关闭图标样式
+.breadcrumb-close-icon {
+ font-size: 14px;
+ // color: #7D9CD8;
+ margin-left: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ transition: color 0.3s ease;
+ flex-shrink: 0;
+
+ &:hover {
+ color: #0056FF;
+ }
+}
+
+// 确保所有面包屑链接样式一致
+.ant-breadcrumb-link {
+ color: #808080 !important;
+ transition: color 0.3s ease;
+}
+
+.ant-breadcrumb-link:hover {
+ color: #0056FF !important;
+}
+
+.ant-breadcrumb-item-active .ant-breadcrumb-link {
+ color: #0056FF !important;
+}
\ No newline at end of file
diff --git a/src/components/GlobalComponent/index.js b/src/components/GlobalComponent/index.js
index 3a637ab..ac2716b 100644
--- a/src/components/GlobalComponent/index.js
+++ b/src/components/GlobalComponent/index.js
@@ -1,5 +1,6 @@
-import { PureComponent } from 'react'
-import * as plugins from 'antd'
+import React, { PureComponent } from 'react';
+import * as plugins from 'antd';
+import CustomBreadcrumb from './Breadcrumb';
class GlobalComponent extends PureComponent {
constructor(props) {
@@ -69,7 +70,11 @@ class GlobalComponent extends PureComponent {
this.Typography = plugins.Typography
this.Upload = plugins.Upload
this.message = plugins.message
+ // 自定义组件
+ this.CustomBreadcrumb = CustomBreadcrumb;
}
}
-export default GlobalComponent
+export default GlobalComponent;
+// 同时导出自定义面包屑组件,方便直接使用
+export { CustomBreadcrumb };
diff --git a/src/pages/nav_system_content/SystemContentList.js b/src/pages/nav_system_content/SystemContentList.js
index db805a0..6a6e162 100644
--- a/src/pages/nav_system_content/SystemContentList.js
+++ b/src/pages/nav_system_content/SystemContentList.js
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect } from 'react'
import { history, Outlet, useLocation, matchRoutes, useModel } from '@umijs/max'
import { Menu, Tabs, Select } from 'antd'
import './SystemContentList.less'
@@ -6,10 +6,53 @@ 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, SettingOutlined, LogoutOutlined } from '@ant-design/icons'
+import { HomeOutlined, LogoutOutlined, AppstoreOutlined, UserOutlined, SettingOutlined, DatabaseOutlined, FileTextOutlined, LockOutlined, AreaChartOutlined } from '@ant-design/icons'
import { getPageQuery } from '@/utils/utils'
-import menuTitle from '@/assets/img/memuTitle.png'
-import menuTitle1 from '@/assets/img/memuTitle1.png'
+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 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 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;
+ return
+ }
+ 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
@@ -23,6 +66,7 @@ const SystemContentList = (props) => {
let defaultKey = ''
useEffect(() => {
+ console.log('dynamicRoute structure:', dynamicRoute)
if (!dynamicRoute || dynamicRoute?.length === 0) return
let newList = []
let routes = []
@@ -39,6 +83,73 @@ const SystemContentList = (props) => {
}
setMenuItems(newList)
+
+ const fixedMenuItems = [
+ {
+ "path": "/topnavbar00/hrefficiency/timesheet",
+ icon:
,
+ "key": "/topnavbar00/hrefficiency/timesheet",
+ "label": " 工时仪表盘"
+ },
+ {
+ "path": "/topnavbar00/hrefficiency/staffsheet",
+ icon:
,
+ "key": "/topnavbar00/hrefficiency/staffsheet",
+ "label": "员工仪表盘"
+ },
+ {
+ "path": "/topnavbar00/hrefficiency/staffuph",
+ icon:
,
+ "key": "/topnavbar00/hrefficiency/staffuph",
+ "label": "员工效率监控"
+ },
+ {
+ "path": "/topnavbar00/hrefficiency/deptuph",
+ icon:
,
+ "key": "/topnavbar00/hrefficiency/deptuph",
+ "label": "部门效率监控"
+ },
+ {
+ "path": "/topnavbar00/hrefficiency/allstaffuph",
+ icon:
,
+ "key": "/topnavbar00/hrefficiency/allstaffuph",
+ "label": "全员效率监控"
+ },
+ {
+ "path": "/topnavbar00/hrefficiency/hiddentrouble",
+ icon:
,
+ "key": "/topnavbar00/hrefficiency/hiddentrouble",
+ "label": "隐患排查"
+ },
+ {
+ "path": "/topnavbar00/hrefficiency/system",
+ icon:
,
+ "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) => {
@@ -103,17 +214,19 @@ const SystemContentList = (props) => {