From 65fb990d7c7c89ccd6628dd76e40dc7c9ed535a2 Mon Sep 17 00:00:00 2001 From: yupeng Date: Mon, 29 Sep 2025 15:05:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BA=BA=E5=91=98=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.js | 8 +- src/assets/img/gisTemp.svg | 32 ++ src/assets/img/personnelPosition1.svg | 4 + src/assets/img/personnelPosition2.svg | 4 + src/locales/zh-CN/menu.js | 6 +- .../nav_system_content/SystemContentList.js | 13 +- .../personnel_location/PersonnelLocation.js | 486 ++++++++++++++++++ .../personnel_location/PersonnelLocation.less | 452 ++++++++++++++++ src/pages/topnavbar/TopNavBar.js | 12 +- 9 files changed, 1012 insertions(+), 5 deletions(-) create mode 100644 src/assets/img/gisTemp.svg create mode 100644 src/assets/img/personnelPosition1.svg create mode 100644 src/assets/img/personnelPosition2.svg create mode 100644 src/pages/personnel_location/PersonnelLocation.js create mode 100644 src/pages/personnel_location/PersonnelLocation.less diff --git a/config/routes.js b/config/routes.js index ce3fc6c..3eac525 100644 --- a/config/routes.js +++ b/config/routes.js @@ -103,10 +103,16 @@ export default [ component: './hrefficiency_hiddentrouble/HiddenTrouble', }, // 安全教育培训 - { + { path:'/topnavbar00/hrefficiency/safetraining', name: 'safetraining', component: './safe_training/SafeTrainingList', + }, + // 人员定位 + { + path:'/topnavbar00/hrefficiency/personnellocation', + name: 'personnellocation', + component: './personnel_location/PersonnelLocation', } ], }, diff --git a/src/assets/img/gisTemp.svg b/src/assets/img/gisTemp.svg new file mode 100644 index 0000000..7a90aae --- /dev/null +++ b/src/assets/img/gisTemp.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/img/personnelPosition1.svg b/src/assets/img/personnelPosition1.svg new file mode 100644 index 0000000..6a45b20 --- /dev/null +++ b/src/assets/img/personnelPosition1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/img/personnelPosition2.svg b/src/assets/img/personnelPosition2.svg new file mode 100644 index 0000000..bd928a5 --- /dev/null +++ b/src/assets/img/personnelPosition2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/locales/zh-CN/menu.js b/src/locales/zh-CN/menu.js index 770da9b..fbd61ec 100644 --- a/src/locales/zh-CN/menu.js +++ b/src/locales/zh-CN/menu.js @@ -10,12 +10,14 @@ export default { 'menu.topnavbar00.hrefficiency.deptuph': '部门效率监控', 'menu.topnavbar00.hrefficiency.allstaffuph': '全员效率监控', 'menu.topnavbar00.hrefficiency.workreport': '工作报表', - 'menu.topnavbar00.hrefficiency.system': '系统管理', 'menu.topnavbar00.hrefficiency.system.organization': '组织管理', 'menu.topnavbar00.hrefficiency.system.role': '角色配置', 'menu.topnavbar00.hrefficiency.system.menu': '菜单配置', - 'menu.topnavbar00': '业务导航', + // 其他安全相关菜单 + 'menu.topnavbar00.hrefficiency.hiddentrouble': '隐患排查', + 'menu.topnavbar00.hrefficiency.safetraining': '安全教育培训', + 'menu.topnavbar00.hrefficiency.personnellocation': '人员定位', 'menu.topnavbar00.sysmenu': '系统配置', 'menu.topnavbar00.sysmenu.system': '系统管理', diff --git a/src/pages/nav_system_content/SystemContentList.js b/src/pages/nav_system_content/SystemContentList.js index 243e774..eeaf4be 100644 --- a/src/pages/nav_system_content/SystemContentList.js +++ b/src/pages/nav_system_content/SystemContentList.js @@ -20,6 +20,7 @@ import license from '@/assets/img/license.svg' import people from '@/assets/img/people.svg' import risk from '@/assets/img/risk.svg' import safeEducationLight from '@/assets/img/safeEducationLight.svg' +import personnelPosition2 from '@/assets/img/personnelPosition2.svg' import { CustomBreadcrumb } from '@/components/GlobalComponent' @@ -124,12 +125,18 @@ const SystemContentList = (props) => { "key": "/topnavbar00/hrefficiency/hiddentrouble", "label": "隐患排查" }, - { + { "path": "/topnavbar00/hrefficiency/safetraining", icon: 安全教育培训, "key": "/topnavbar00/hrefficiency/safetraining", "label": "安全教育培训" }, + { + "path": "/topnavbar00/hrefficiency/personnellocation", + icon: 人员定位, + "key": "/topnavbar00/hrefficiency/personnellocation", + "label": "人员定位" + }, { "path": "/topnavbar00/hrefficiency/system", icon: 工时仪表盘, @@ -379,6 +386,10 @@ const SystemContentList = (props) => { else if (item.key === '/topnavbar00/hrefficiency/safetraining' && typeof safeEducationLight !== 'undefined') { iconSrc = safeEducationLight; } + // 人员定位激活态使用personnelPosition2 + else if (item.key === '/topnavbar00/hrefficiency/personnellocation' && typeof personnelPosition2 !== 'undefined') { + iconSrc = personnelPosition2; + } } icon = ( + {text} + ), + }, + { + title: '工号', + dataIndex: 'empId', + key: 'empId', + width: 100, + render: (text) => ( + {text} + ), + }, + { + title: '岗位', + dataIndex: 'position', + key: 'position', + width: 120, + render: (text) => ( + {text} + ), + }, + { + title: '所属部门', + dataIndex: 'department', + key: 'department', + width: 120, + render: (text) => ( + {text} + ), + }, + { + title: '当前位置', + dataIndex: 'location', + key: 'location', + width: 150, + render: (text) => ( + {text} + ), + }, + { + title: '时间', + dataIndex: 'time', + key: 'time', + width: 150, + render: (text) => ( + {text} + ), + }, + { + title: '状态', + dataIndex: 'status', + key: 'status', + width: 80, + render: (text) => { + if (text === '正常') { + return {text}; + } else if (text === '预警') { + return {text}; + } else { + return {text}; + } + }, + }, + { + title: '操作', + key: 'action', + width: 80, + fixed: 'right', + render: (_, record) => ( + this.handleLocate(record)} + > + 定位 + + ), + }, + ]; + + // 获取地图配置选项 + getMapChartOption = () => { + return { + tooltip: { + trigger: 'item', + formatter: '{b}' + }, + series: [ + { + name: '人员分布', + type: 'scatter', + coordinateSystem: 'geo', + symbolSize: 20, + data: [ + { name: '张三', value: [116.404, 39.915], itemStyle: { color: '#52C41A' } }, + { name: '李四', value: [116.414, 39.925], itemStyle: { color: '#FAAD14' } }, + { name: '王五', value: [116.424, 39.935], itemStyle: { color: '#FAAD14' } }, + { name: '赵六', value: [116.434, 39.945], itemStyle: { color: '#FF4D4F' } }, + { name: '孙七', value: [116.444, 39.955], itemStyle: { color: '#52C41A' } }, + ], + emphasis: { + focus: 'series', + itemStyle: { + borderColor: '#fff', + borderWidth: 2 + } + } + } + ], + geo: { + map: 'beijing', + label: { + show: true + }, + roam: true, + itemStyle: { + areaColor: '#f0f2f5', + borderColor: '#999' + }, + emphasis: { + itemStyle: { + areaColor: '#e6f7ff' + } + } + } + }; + }; + + // 处理表格变化 + handleTableChange = (pagination, sorter) => { + const { dispatch } = this.props; + const { formValues } = this.state; + + const params = { + currentPage: pagination.current, + pageSize: pagination.pageSize, + ...formValues + }; + + sorter.field && (params.sorter = `${sorter.field}_${sorter.order}`); + }; + + // 处理行选择 + handleSelectRows = rows => { + this.setState({ + selectedRows: rows + }); + }; + + // 处理搜索 + handleSearch = values => { + this.setState({ + formValues: values + }); + }; + + // 处理定位 + handleLocate = (record) => { + this.setState({ + selectedPerson: record + }); + // 这里可以添加地图定位的逻辑 + console.log('定位人员:', record); + }; + + render() { + const { + selectedRows, + selectedPerson + } = this.state; + + return ( + + {/* 主要内容区域 - 地图、历史轨迹和人员警告在同一行 */} + + {/* 左侧:地图显示(占一半宽度) */} + + +
+ {/* 由于缺少实际地图组件,这里使用模拟的地图容器 */} +
+
+
+
+ 正常 (45) +
+
+
+ 预警 (32) +
+
+
+ 告警 (12) +
+
+
+ GIS地图 + {/* 地图上的标记点 */} +
+ 张三 - A区安控室 +
+
+ 李四 - A区发电室 +
+
+ 王五 - A区发电室 +
+
+ 赵六 - A区发电室 +
+
+ 孙七 - A区发电室 +
+
+
+
+ {/* 筛选栏 - 移至地图卡片内部 */} + +
+ + + + + 安全区域 + + 人员类型 + + + + + + + + + + +
+
+ + + {/* 中间:历史轨迹(占四分之一宽度) */} + + +
+ {historyTrailData.map((item, index) => ( +
+
+ +
+
+
{item.title}
+
+ {item.time} + {item.location} +
+
+
+ ))} +
+
+ + + {/* 右侧:人员警告信息(占四分之一宽度) */} + + +
+ {personnelWarningData.map((item, index) => ( +
+
+ {item.level === 'error' ? 严重 : 警告} +
+
+
{item.title}
+
+ {item.time} + {item.location} +
+
+
+ ))} +
+
+ +
+ + {/* 底部表格区域 */} +
+ + `共 ${total} 条`} + /> + +
+
+ ); + } +} + +export default PersonnelLocation; \ No newline at end of file diff --git a/src/pages/personnel_location/PersonnelLocation.less b/src/pages/personnel_location/PersonnelLocation.less new file mode 100644 index 0000000..d33d5a3 --- /dev/null +++ b/src/pages/personnel_location/PersonnelLocation.less @@ -0,0 +1,452 @@ +// Ant Design 5.x不再需要导入less主题文件 +// 直接定义我们需要的主题变量 +@primary-color: rgba(36, 114, 214, 1); // 与全局样式保持一致 +@success-color: #52c41a; +@warning-color: #faad14; +@error-color: #ff4d4f; +@bg-color: #f7f8fa; +@card-bg: #ffffff; +@border-color: #e8e8e8; +@text-primary: #333333; +@text-secondary: #666666; +@text-tertiary: #999999; + +// 阴影效果 +@shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); +@shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08); +@shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12); + +// 动画效果 +@transition-base: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +@transition-hover: all 0.2s ease-in-out; + +.card-container { + padding: 16px; + background-color: @bg-color; + min-height: 100vh; +} + +// 顶部工具栏样式 +.table-toolbar-container { + padding: 12px 16px; + background-color: @card-bg; + border-radius: 8px; + box-shadow: @shadow-sm; +} + +// 搜索和筛选控件样式 +.search-input { + width: 240px; + height: 36px; + border-radius: 6px; + font-size: 14px; + transition: @transition-hover; + &:focus { + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); + } +} + +.filter-select { + width: 140px; + height: 36px; + border-radius: 6px; + font-size: 14px; + transition: @transition-hover; +} + +// 按钮样式 +.button-style { + margin-left: 12px; + height: 36px; + padding: 0 16px; + border-radius: 6px; + font-size: 14px; + transition: @transition-hover; + &:hover { + transform: translateY(-1px); + box-shadow: @shadow-md; + } +} + +// 地图卡片样式 +.map-card { + width: 100%; + min-height: 400px; + border-radius: 8px; + overflow: hidden; + box-shadow: @shadow-md; + transition: @transition-hover; + display: flex; + flex-direction: column; + &:hover { + box-shadow: @shadow-lg; + } +} + +.map-container { + height: calc(100% - 120px); +} + +.mock-map { + width: 100%; + height: 100%; + position: relative; + background: linear-gradient(135deg, #f0f2f5 0%, #e6f7ff 100%); + border-radius: 0 0 8px 8px; + overflow: hidden; +} + +// 地图图例样式 +.map-legend { + position: absolute; + top: 16px; + right: 16px; + background: rgba(255, 255, 255, 0.95); + padding: 12px 16px; + border-radius: 8px; + box-shadow: @shadow-md; + z-index: 10; + backdrop-filter: blur(4px); +} + +.legend-item { + display: flex; + align-items: center; + margin-bottom: 6px; + font-size: 13px; + color: @text-secondary; + &:last-child { + margin-bottom: 0; + } +} + +.legend-dot { + width: 14px; + height: 14px; + border-radius: 50%; + margin-right: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +// 地图内容样式 +.map-content { + width: 100%; + height: 100%; + position: relative; +} + +.map-image { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 0 0 8px 8px; +} + +// 地图标记点样式 +.map-marker { + position: absolute; + width: 18px; + height: 18px; + border-radius: 50%; + cursor: pointer; + transform: translate(-50%, -50%); + box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.9); + transition: @transition-hover; + &:hover { + transform: translate(-50%, -50%) scale(1.2); + box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.95); + z-index: 20; + } +} + +// 标记点提示样式 +.marker-tooltip { + position: absolute; + top: -32px; + left: 50%; + transform: translateX(-50%); + background: rgba(0, 0, 0, 0.8); + color: white; + padding: 6px 12px; + border-radius: 6px; + font-size: 13px; + white-space: nowrap; + display: none; + animation: fadeIn 0.2s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateX(-50%) translateY(5px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } +} + +.map-marker:hover .marker-tooltip { + display: block; +} + +// 统计卡片样式 +.stats-card { + margin-bottom: 16px; + border-radius: 8px; + overflow: hidden; + box-shadow: @shadow-md; + transition: @transition-hover; + &:hover { + box-shadow: @shadow-lg; + } +} + +// 历史轨迹卡片样式 +.trail-card { + height: 100%; + min-height: 240px; + border-radius: 8px; + overflow: hidden; + box-shadow: @shadow-md; + transition: @transition-hover; + display: flex; + flex-direction: column; + &:hover { + box-shadow: @shadow-lg; + } +} + +// 人员警告卡片样式 +.warning-card { + height: 100%; + min-height: 240px; + border-radius: 8px; + overflow: hidden; + box-shadow: @shadow-md; + transition: @transition-hover; + display: flex; + flex-direction: column; + &:hover { + box-shadow: @shadow-lg; + } +} + +.trail-list { + flex: 1; + overflow-y: auto; + padding-right: 8px; +} + +// 轨迹项样式 +.trail-item { + display: flex; + padding: 12px 0; + border-bottom: 1px solid #f0f0f0; + transition: @transition-hover; + &:hover { + background-color: #fafafa; + padding-left: 8px; + border-left: 3px solid @primary-color; + } + &:last-child { + border-bottom: none; + } +} + +.trail-icon { + margin-right: 12px; + color: @primary-color; + font-size: 16px; + flex-shrink: 0; +} + +.trail-content { + flex: 1; +} + +.trail-title { + font-size: 14px; + color: @text-primary; + margin-bottom: 6px; + font-weight: 500; +} + +.trail-info { + font-size: 12px; + color: @text-tertiary; +} + +.trail-info span { + margin-right: 12px; +} + +// 表格容器样式 +.table-container { + margin-top: 16px; +} + +// 位置表格卡片样式 +.location-table-card { + min-height: 400px; + border-radius: 8px; + overflow: hidden; + box-shadow: @shadow-md; + transition: @transition-hover; + &:hover { + box-shadow: @shadow-lg; + } +} + +// 滚动条样式优化 +.trail-list::-webkit-scrollbar, +.warning-list::-webkit-scrollbar { + width: 6px; +} + +.trail-list::-webkit-scrollbar-track, +.warning-list::-webkit-scrollbar-track { + background: #f5f5f5; + border-radius: 3px; +} + +.trail-list::-webkit-scrollbar-thumb, +.warning-list::-webkit-scrollbar-thumb { + background: #d9d9d9; + border-radius: 3px; + transition: @transition-hover; + &:hover { + background: #bfbfbf; + } +} + +// Ant Design 表格样式覆盖 +.ant-table { + .ant-table-thead > tr > th { + background-color: #fafafa; + font-weight: 500; + border-bottom: 1px solid #e8e8e8; + } + .ant-table-tbody > tr:hover > td { + background-color: #f5f8ff !important; + } + .ant-table-pagination { + margin-top: 16px; + } +} + +// 状态标签样式 +.status-tag { + display: inline-block; + padding: 2px 8px; + border-radius: 10px; + font-size: 12px; + font-weight: 500; + &.status-normal { + background-color: #f6ffed; + color: @success-color; + border: 1px solid #b7eb8f; + } + &.status-warning { + background-color: #fff7e6; + color: @warning-color; + border: 1px solid #ffd591; + } + &.status-error { + background-color: #fff1f0; + color: @error-color; + border: 1px solid #ffccc7; + } +} + +// 人员警告列表样式 +.warning-list { + flex: 1; + overflow-y: auto; + padding-right: 8px; +} + +// 警告项样式 +.warning-item { + display: flex; + padding: 12px 0; + border-bottom: 1px solid #f0f0f0; + transition: @transition-hover; + &:hover { + background-color: #fafafa; + padding-left: 8px; + border-left: 3px solid @primary-color; + } + &:last-child { + border-bottom: none; + } + &.warning-warning { + border-left: 3px solid @warning-color; + } + &.warning-error { + border-left: 3px solid @error-color; + } +} + +.warning-icon { + margin-right: 12px; + flex-shrink: 0; +} + +.warning-content { + flex: 1; +} + +.warning-title { + font-size: 14px; + color: @text-primary; + margin-bottom: 6px; + font-weight: 500; +} + +.warning-info { + font-size: 12px; + color: @text-tertiary; +} + +.warning-info span { + margin-right: 12px; +} + +// 响应式布局适配 +@media (max-width: 1200px) { + .search-input { + width: 200px; + } + .filter-select { + width: 120px; + } +} + +@media (max-width: 768px) { + .card-container { + padding: 8px; + } + .table-toolbar-container { + padding: 12px 8px; + } + .search-input { + width: 100%; + margin-bottom: 12px; + } + .filter-select { + width: 100%; + margin-bottom: 12px; + } + .button-style { + margin-left: 0; + margin-right: 8px; + } + .map-card { + min-height: 300px; + } + .trail-card { + height: auto; + min-height: 200px; + } +} \ No newline at end of file diff --git a/src/pages/topnavbar/TopNavBar.js b/src/pages/topnavbar/TopNavBar.js index 23bad47..7dbad9a 100644 --- a/src/pages/topnavbar/TopNavBar.js +++ b/src/pages/topnavbar/TopNavBar.js @@ -43,7 +43,7 @@ const menuItem = [ key: '/topnavbar00/hrefficiency/basicinformation', // icon: , }, - { + { label: '重大危险源管理', key: '/topnavbar00/hrefficiency/safeMajorHazard', // icon: , @@ -53,6 +53,16 @@ const menuItem = [ key: '/topnavbar00/hrefficiency/hiddentrouble', // icon: , }, + { + label: '人员定位', + key: '/topnavbar00/hrefficiency/personnellocation', + // icon: , + }, + { + label: '安全教育培训', + key: '/topnavbar00/hrefficiency/safetraining', + // icon: , + }, { label: '系统管理', key: '/topnavbar00/hrefficiency/system',