import React, { useState, useEffect, useMemo, useRef } from 'react'; import { connect } from 'dva'; import { withRouter, matchPath } from 'dva/router'; import { Scrollbars } from 'react-custom-scrollbars'; import { Icon, Row, Col, Progress, Tabs } from 'antd'; import EnergyIcon from '../utils/energyIcon'; import { $consts } from '../plugins'; import styles from './fullinter.less'; import echarts from 'echarts'; import realGif from '../assets/layout/mofang.png'; import logo from '../assets/layout/headerno-logo-new.png'; import debounce from 'lodash.debounce'; import storage from '../utils/storage'; import { initFilter } from '../utils/common'; import { FullScreenContainer, BorderBox8, BorderBox10, ScrollBoard, CapsuleChart, WaterLevelPond, BorderBox7, BorderBox6, } from '@jiaminghi/data-view-react'; import { color } from 'echarts/lib/export'; import { title } from 'process'; const { TabPane } = Tabs; const getScale = () => { const width = 1920, height = 1200; // 此处可以根据实际设计稿尺寸修改 let ww = window.innerWidth / width; let wh = window.innerHeight / height; return ww < wh ? ww : wh; }; class FullScreen extends React.Component { constructor(props) { super(props); this.state = { safetySloganOne: '', animationDuration: 20, sliderColor: '#de4e58', sliderSize: '24px', nowDate: '', riskTypeRate: {}, //风险等级占比 jobTodayTop3: {}, //当日工作票排名前三 hiddenRectifyRate: {}, //隐患整改率 taskTop3: {}, //各事项排名前三 jobFinishRate: {}, //作业现场完成情况统计 safeCheckSum: {}, //各公司安全检查统计 riskChangeData: [ { name: '隐患数量', value: 103 }, { name: '延期整改数', value: 18 }, { name: '按期整改数', value: 85 }, ], configBanner: [ { name: '首页', value: 103 }, { name: '风险管控', value: 103 }, { name: '隐患治理', value: 103 }, { name: '班组建设', value: 103 }, { name: '危险作业', value: 103 }, { name: '安全培训', value: 103 }, ], checkData: [ { name: '公司检查', value: 103 }, { name: '部门检查', value: 79 }, { name: '车间检查', value: 86 }, { name: '班组检查', value: 94 }, ], widthp: '70%', scrollConfig: { header: ['检查类型', '检查次数', '完成率'], data: [ ['巡回检查', '322', '99%'], ['例行检查', '255', '99%'], ['日常检查', '253', '99%'], ['专业检查', '123', '99%'], ['巡回检查', '322', '99%'], ['例行检查', '255', '99%'], ['日常检查', '253', '99%'], ['专业检查', '123', '99%'], ], waitTime: 200000, }, safescrollConfig: { header: ['部门', '车间', '活动', '进度'], data: [ ['矿山部', '穿爆车间', '班前会议', '98%'], ['矿山部', '金宇宁化分公司', '班前会议', '98%'], ['选矿部', '破碎车间', '班前会议', '95%'], ['矿山部', '磨重车间', '班前会议', '92%'], ['矿山部', '机电设备管理科', '班前会议', '83%'], ['矿山部', '钨细泥回收车间', '班前会议', '93%'], ['矿山部', '穿爆车间', '班前会议', '90%'], ['矿山部', '穿爆车间', '班前会议', '90%'], ['矿山部', '穿爆车间', '班前会议', '90%'], ], index: true, columnWidth: [80, 200, 300, 200, 200], align: ['center'], waitTime: 2000, }, chartConfig: { data: [ { name: '电工日常班', value: 97, }, { name: '电工三班', value: 95, }, { name: '破碎一班', value: 91, }, { name: '磨重二班', value: 86, }, { name: '磨重三班', value: 83, }, { name: '电工日常班', value: 97, }, { name: '电工三班', value: 95, }, { name: '破碎一班', value: 91, }, { name: '磨重二班', value: 86, }, { name: '磨重三班', value: 83, }, { name: '电工日常班', value: 97, }, { name: '电工三班', value: 95, }, { name: '破碎一班', value: 91, }, { name: '磨重二班', value: 86, }, { name: '磨重三班', value: 83, }, ], showValue: true, }, riskData: [ { color: '#c92a2a', value: 2, name: '重大风险' }, { color: '#FF6710', value: 5, name: '较大风险' }, { color: '#FFDD1E', value: 15, name: '一般风险' }, { color: '#0091FF', value: 30, name: '低风险' }, ], WaterLevelPondconfig1: { data: [75], shape: 'round', }, WaterLevelPondconfig2: { data: [85], shape: 'round', }, WaterLevelPondconfig3: { data: [95], shape: 'round', }, completeData: [ { name: '班组会议完成率', value: 75, }, { name: '岗位交接班完成率', value: 85, }, { name: '岗位当班记录完成率', value: 95, }, ], // completeDatatwo: { // name: "岗位交接班完成率", // value: 85, // id: "completetwo", // }, // completeDatathree: { // name: "岗位当班记录完成率", // value: 95, // id: "completethree", // }, meetingData: [ { name: '班前会议', value: 32, }, { name: '班组活动', value: 132, }, { name: '岗位交接班', value: 32, }, { name: '岗位当班', value: 132, }, { name: '班前会议', value: 32, }, { name: '班组活动', value: 132, }, { name: '岗位交接班', value: 32, }, { name: '岗位当班', value: 132, }, ], roaData: [ { name: '总任务数', value: 1456, }, { name: '超时待办数', value: 132, }, { name: '安全检查数', value: 1456, }, { name: '检查完成率', value: 32, }, { name: '职业危害', value: 132, }, { name: '管控措施', value: 1456, }, { name: '安全检查库', value: 132, }, { name: '危险源库', value: 32, }, { name: '培训计划完成率', value: 132, }, { name: '用户活跃度', value: 1456, }, { name: '系统用户数', value: 132, }, { name: '正常已办数', value: 32, }, { name: '未完成数', value: 132, }, ], scale: getScale(), }; this.echartsInstances = { riskLevel: null, opretionTrend: null, completeone: null, }; } setScale = debounce(() => { // debounce节流 // 获取到缩放比,设置它 let scale = getScale(); this.setState({ scale }); }, 500); componentDidMount() { window.addEventListener('resize', this.setScale); // 得到呈现的屏幕宽高比 // this.getHomeTitle(); this.getHomeDataArray(); this.setState({ activeTab: '首页' }); this.riskLevel(); this.safedanger(); this.completeChart(this.state.completeData); this.timer = setInterval(() => { this.setState({ nowDate: this.getDate(), }); }, 1000); } componentDidUpdate(prevProps, prevState) { // 当从其他tab切换回首页时 if (prevState.activeTab !== this.state.activeTab && this.state.activeTab === '首页') { console.log('切换到首页,初始化图表'); // 延迟确保DOM已渲染 setTimeout(() => { this.riskLevel(); this.safedanger(); this.completeChart(this.state.completeData); }, 300); // 稍微增加延迟时间 } // 当离开首页时,清理图表 if (prevState.activeTab === '首页' && this.state.activeTab !== '首页') { console.log('离开首页,清理图表'); this.cleanupCharts(); } } getHomeDataArray = () => { var orgId = storage('lacal').getItem('webOrgId')?.val; //登录后有存储登录信息 let json = initFilter(orgId); this.props.dispatch({ type: 'app/getDataByPost', payload: json, url: 'BI/BIKanBanController/ReturnAllData', onComplete: (ret) => { console.log(ret, '877777'); if (ret) { console.log('首页标题数据', ret); this.setState({ riskTypeRate: ret.riskTypeRate, jobTodayTop3: ret.jobTodayTop3, hiddenRectifyRate: ret.hiddenRectifyRate, taskTop3: ret.taskTop3, jobFinishRate: ret.jobFinishRate, safeCheckSum: ret.safeCheckSum, }); } }, }); }; // 添加清理方法 cleanupCharts = () => { // 清理风险分级图表 if (this.echartsInstances.riskLevel) { this.echartsInstances.riskLevel.dispose(); this.echartsInstances.riskLevel = null; } // 清理运行走势图 if (this.echartsInstances.opretionTrend) { this.echartsInstances.opretionTrend.dispose(); this.echartsInstances.opretionTrend = null; } // 清理完成率图表 if (this.echartsInstances.completeone) { this.echartsInstances.completeone.dispose(); this.echartsInstances.completeone = null; } // 移除resize监听器 if (this.riskResizeHandler) { window.removeEventListener('resize', this.riskResizeHandler); this.riskResizeHandler = null; } if (this.trendResizeHandler) { window.removeEventListener('resize', this.trendResizeHandler); this.trendResizeHandler = null; } if (this.completeResizeHandler) { window.removeEventListener('resize', this.completeResizeHandler); this.completeResizeHandler = null; } }; handleTabClick = (name) => { // 如果从首页切换到其他tab,先清理图表 if (this.state.activeTab === '首页' && name !== '首页') { this.cleanupCharts(); } this.setState({ activeTab: name }); const tabActions = { 首页: () => { console.log('跳转到首页'); // 首页图表会在componentDidUpdate中初始化 }, 风险管控: () => { console.log('跳转到风险管控'); }, 隐患治理: () => { console.log('跳转到隐患治理'); }, // ... 其他tab }; if (tabActions[name]) { tabActions[name](); } }; componentWillUnmount() { window.removeEventListener('resize', this.setScale); clearInterval(this.timer); this.cleanupCharts(); } getHomeTitle = () => { console.log('获取首页标题数据'); var orgId = storage('lacal').getItem('webOrgId')?.val; //登录后有存储登录信息 let json = initFilter(orgId); console.log(json, '首页标题数据'); this.props.dispatch({ type: 'app/getDataByPost', payload: json, url: 'PF/HomeTitle/OrderPaged', onComplete: (ret) => { console.log(ret, '877777'); if (ret) { console.log('首页标题数据', ret); this.setState({ safetySloganOne: ret[0].TITLE, // safetySloganOne: "1.安全方针:以人为本、关注健康、依法治企、安全发展。 2.安全理念:一切风险皆可控,一切事故皆可防!3.安全方针:以人为本、关注健康、依法治企、安全发展。4.安全方针:以人为本、关注健康、依法治企、安全发展。5.安全方针:以人为本、关注健康、依法治企、安全发展。 6.安全理念:一切风险皆可控,一切事故皆可防!7.安全方针:以人为本、关注健康、依法治企、安全发展。8.安全方针:以人为本、关注健康、依法治企、安全发展。", animationDuration: ret[0].SECOND, sliderColor: ret[0].COCOR, sliderSize: ret[0].FONTSIZE, }); } }, }); }; callback = (key) => { console.log(key); }; getDate = () => { var myDate = new Date(); var year = myDate.getFullYear(); //获取当前年 var mon = myDate.getMonth() + 1; //获取当前月 var date = myDate.getDate(); //获取当前日 // var hours = myDate.getHours(); //获取当前小时 // var minutes = myDate.getMinutes(); //获取当前分钟 if (myDate.getHours() < 10) { var hours = '0' + myDate.getHours(); } else { hours = myDate.getHours(); //获取当前小时 } if (myDate.getMinutes() < 10) { var minutes = '0' + myDate.getMinutes(); } else { minutes = myDate.getMinutes(); //获取当前分钟 } if (myDate.getSeconds() < 10) { var seconds = '0' + myDate.getSeconds(); } else { seconds = myDate.getSeconds(); //获取当前秒 } var now = year + ' 年 ' + mon + ' 月 ' + date + ' 日 ' + '\t\t\t' + hours + ' : ' + minutes + ' : ' + seconds; return now; }; completeChart = (evt) => { if (this.echartsInstances.completeone) { this.echartsInstances.completeone.dispose(); this.echartsInstances.completeone = null; } let completeCharts = document.getElementById('completeone'); if (!completeCharts) { requestAnimationFrame(() => { this.completeChart(evt); }); return; } console.log('初始化完成率图表'); this.echartsInstances.completeone = echarts.init(completeCharts); let seriesArr = []; let centerArr = [ ['20%', '50%'], ['50%', '50%'], ['80%', '50%'], ]; evt.forEach((item, index) => { seriesArr.push({ center: centerArr[index], axisLine: { show: true, lineStyle: { color: [ [0.25, '#c23531'], [0.5, '#EFC631'], [0.75, '#63869e'], [1, '#91c7ae'], ], width: 8, }, radius: '90%', // 控制轴线本身的半径 }, axisTick: { show: false, }, splitLine: { length: 8, // 刻度线长度 distance: 25, // 向内移动距离,负值越大越向内 lineStyle: { color: '#fff', // 刻度线颜色 width: 2, // 刻度线宽度 }, }, axisLabel: { distance: 15, // 标签与刻度线的距离 textStyle: { color: '#fff', fontSize: 10, }, // 调整标签偏移 offset: [0, 0], // [水平偏移, 垂直偏移] }, itemStyle: { normal: { color: 'auto', }, }, radius: '80%', pointer: { show: true, width: '8%', length: '20%', }, title: { textStyle: { // fontWeight: 'bolder', fontSize: 14, color: '#fff', }, offsetCenter: [0, '100%'], }, detail: { textStyle: { fontWeight: 'bolder', fontSize: 20, color: '#fff', }, offsetCenter: [0, '68%'], // formatter: '{value}万\n(5048人)', }, min: 0, max: 100, // name: '米类仪表盘', type: 'gauge', show: false, splitNumber: 10, data: [ { name: item.name, value: item.value, }, ], }); }); this.echartsInstances.completeone.setOption({ series: seriesArr, }); // 监听resize const resizeHandler = () => { if (this.echartsInstances.completeone) { this.echartsInstances.completeone.resize(); } }; if (this.completeResizeHandler) { window.removeEventListener('resize', this.completeResizeHandler); } this.completeResizeHandler = resizeHandler; window.addEventListener('resize', resizeHandler); }; safedanger = () => { if (this.echartsInstances.opretionTrend) { this.echartsInstances.opretionTrend.dispose(); this.echartsInstances.opretionTrend = null; } const opretionTrends = document.getElementById('opretionTrend'); if (!opretionTrends) { requestAnimationFrame(() => { this.safedanger(); }); return; } console.log('初始化运行走势图'); this.echartsInstances.opretionTrend = echarts.init(opretionTrends); // ... 原有配置代码 let bgColor = '#000'; let color = [ '#0090FF', '#36CE9E', '#e690d1', '#FF515A', '#8B5CFF', '#00CA69', '#FFC107', '#E91E63', '#9C27B0', '#3F51B5', '#2196F3', '#4CAF50', '#FF9800', '#795548', '#607D8B', ]; const seriesNames = [ '选矿部门', '矿山部门', '尾矿部门', '机电部门', '安全部门', '生产部门', '技术部门', '维修部门', '运输部门', '仓储部门', '质检部门', '环保部门', '研发部门', '行政部门', '财务部门', ]; // 生成x轴数据(12个月) let xAxisData = []; for (let i = 1; i <= 12; i++) { xAxisData.push(i.toString()); } // 生成15个系列的数据 let seriesArr = []; for (let i = 0; i < 15; i++) { let yAxisData = []; for (let j = 0; j < 12; j++) { // 生成60-100的随机数据 yAxisData.push(Math.floor(Math.random() * 40) + 60); } seriesArr.push({ name: seriesNames[i], type: 'line', smooth: true, symbolSize: 6, data: yAxisData, }); } const hexToRgba = (hex, opacity) => { let rgbaColor = ''; let reg = /^#[\da-f]{6}$/i; if (reg.test(hex)) { rgbaColor = `rgba(${parseInt('0x' + hex.slice(1, 3))},${parseInt('0x' + hex.slice(3, 5))},${parseInt( '0x' + hex.slice(5, 7) )},${opacity})`; } return rgbaColor; }; const option = { title: [ { text: '各家公司的安全教育培训学时统计', x: 'center', y: '5%', textStyle: { fontSize: 16, color: '#fff', }, }, ], backgroundColor: '', color: color, legend: { type: 'scroll', // 如果项目多可以使用滚动 orient: 'vertical', // 设置为垂直排列 right: 10, // 距离右侧的距离 top: 'center', // 垂直居中 align: 'left', // 文本左对齐 textStyle: { color: '#fff', // 文字颜色 fontSize: 12, }, itemStyle: { color: 'inherit', borderWidth: 0, opacity: 1, }, symbol: 'rect', // 实心矩形 symbolSize: [12, 8], // 大小 itemWidth: 10, // 图例标记的宽度 itemHeight: 10, // 图例标记的高度 itemGap: 15, // 图例每项之间的间隔 pageButtonItemGap: 3, pageButtonGap: 5, pageButtonPosition: 'end', pageIconColor: '#00caf7', width: 100, // 限制宽度 height: 250, // 限制高度,超出就会显示滚动 }, tooltip: { trigger: 'axis', formatter: function (params) { let html = ''; params.forEach((v) => { html += `
${v.seriesName} ${v.value} %`; }); return html; }, extraCssText: 'background: #fff; border-radius: 0;box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);color: #333;', axisPointer: { type: 'shadow', shadowStyle: { // color: "#ffffff", shadowColor: 'rgba(225,225,225,1)', shadowBlur: 5, }, }, }, grid: { top: '15%', left: '5%', right: '15%', // 为图例留出空间 bottom: '15%', containLabel: true, }, xAxis: [ { type: 'category', boundaryGap: false, axisLabel: { formatter: '{value}月', textStyle: { color: '#fff', }, }, axisTick: { show: false, }, axisLine: { lineStyle: { color: '#fff', }, }, data: xAxisData, }, ], yAxis: [ { type: 'value', axisLabel: { textStyle: { color: '#fff', }, }, nameTextStyle: { color: '#fff', fontSize: 12, lineHeight: 40, }, splitLine: { show: false, lineStyle: { type: 'dashed', color: '#fff', }, }, axisLine: { show: false, lineStyle: { color: '#00c7ff', width: 1, type: 'solid', }, }, axisTick: { show: false, }, }, ], series: seriesArr, }; this.echartsInstances.opretionTrend.setOption(option); // 监听resize const resizeHandler = () => { if (this.echartsInstances.opretionTrend) { this.echartsInstances.opretionTrend.resize(); } }; if (this.trendResizeHandler) { window.removeEventListener('resize', this.trendResizeHandler); } this.trendResizeHandler = resizeHandler; window.addEventListener('resize', resizeHandler); }; riskLevel = () => { // 如果已有实例,先销毁 if (this.echartsInstances.riskLevel) { this.echartsInstances.riskLevel.dispose(); this.echartsInstances.riskLevel = null; } const riskLevels = document.getElementById('riskLevelFull'); if (!riskLevels) { console.warn('风险分级图表容器未找到'); // 使用requestAnimationFrame而不是setTimeout requestAnimationFrame(() => { this.riskLevel(); }); return; } console.log('初始化风险分级图表'); // 初始化echarts实例并保存引用 this.echartsInstances.riskLevel = echarts.init(riskLevels); const option = { color: ['#c92a2a', '#FF6710', '#FFDD1E', '#0091FF', '#fa8a89'], title: [ { text: '风险分级占比', x: 'center', y: '5%', textStyle: { fontSize: 16, color: '#fff', }, }, ], tooltip: { trigger: 'item', formatter: function (params) { const color = params.color; return `
${params.name}: ${params.value}
`; }, backgroundColor: 'rgba(255, 255, 255, 0.5)', borderColor: '#FFFFFF', borderWidth: 2, textStyle: { color: '#000', fontSize: 14, fontWeight: 'normal', }, }, series: [ { name: '访问来源', type: 'pie', minAngle: 20, radius: ['40%', '60%'], center: ['50%', '50%'], clockwise: true, avoidLabelOverlap: true, hoverOffset: 15, label: { show: true, position: 'inside', formatter: '{a|{b}:{c}}{e|({d}%)}\n', color: '#FFFFFF', textBorderWidth: 0, rich: { a: { padding: [-15, 0, 0, 0], fontSize: 15, color: '#FFFFFF', textBorderWidth: 0, textShadow: 'none', }, e: { fontSize: 14, color: '#FFFFFF', padding: [-15, 0, 0, 5], textBorderWidth: 0, textShadow: 'none', }, }, }, labelLine: { normal: { show: false, }, }, data: this.state.riskTypeRate, }, ], }; this.echartsInstances.riskLevel.setOption(option); // 监听窗口大小变化 const resizeHandler = () => { if (this.echartsInstances.riskLevel) { this.echartsInstances.riskLevel.resize(); } }; // 移除旧的监听器 if (this.riskResizeHandler) { window.removeEventListener('resize', this.riskResizeHandler); } this.riskResizeHandler = resizeHandler; window.addEventListener('resize', resizeHandler); }; render() { const width = 1920, height = 1200; // 固定好16:9的宽高比,计算出最合适的缩放比,宽高比可根据需要自行更改 const { scale, safetySloganOne, animationDuration, sliderColor, sliderSize, activeTab } = this.state; const renderContent = () => { if (activeTab === '首页') { return ( <> {/* 首页内容 - 原来的两行布局 */}
{/* 原第一行内容 */} {/* 风险等级基本信息 */}
{this.state.riskTypeRate.map((item, index) => (
{item.riskType}
{item.count}
))}
{/* 中间内容 */}
安全方针:以人为本、关注健康、依法治企、安全发展。
安全理念:一切风险皆可控,一切事故皆可防!
{/* 右边内容 */}
{this.state.meetingData.map((item, index) => (
{item.name}
{item.value}
))}
{/* 第二行内容 */}
{this.state.riskChangeData.map((item, index) => (
{item.name}
{item.value}
))}
整改率
83.98%
各家公司安全检查统计
); } else { // 其他tab的内容 - 这里可以替换为你想要的其他内容 return (
{activeTab} 页面
这里是 {activeTab} 的内容展示区域
请根据实际需求替换此内容
); } }; return (
{/* 头部保持不变 */}
logo
{this.state.configBanner.slice(0, 3).map((item, index) => (
this.handleTabClick(item.name)} onKeyPress={(e) => e.key === 'Enter' && this.handleTabClick(item.name)} tabIndex={0} title={`点击进入${item.name}`} role="button" style={{ cursor: 'pointer' }} > {item.name}
))}
金源公司安全生产管控平台
{this.state.configBanner.slice(3, 6).map((item, index) => (
this.handleTabClick(item.name)} onKeyPress={(e) => e.key === 'Enter' && this.handleTabClick(item.name)} tabIndex={0} title={`点击进入${item.name}`} role="button" style={{ cursor: 'pointer' }} > {item.name}
))}
{/* {this.state.nowWeek} */} {this.state.nowDate}
{/* 条件渲染的内容区域 */} {renderContent()}
); } } export default withRouter(connect(({ login }) => ({ login }))(FullScreen));