// HiddenSolve.js - 隐患解决页面组件 import React from 'react'; import { Select } from 'antd'; import styles from './../fullinter.less'; import echarts from 'echarts'; const { Option } = Select; class HiddenSolve extends React.Component { constructor(props) { super(props); this.echartsInstances = { hiddenBarChart: null, // 各公司隐患统计柱状图(使用 hiddenList) hiddenRectifyChart: null, // 隐患整改情况柱状图(使用 hiddenRectifyList) }; this.chartResizeHandlers = {}; this.isUnmounted = false; } // 获取公司选项(使用 props 传入的 companyData,与 TrainingContent 一致) getCompanyOptions = () => { const { companyData } = this.props; if (!companyData || companyData.length === 0) { return []; } return companyData.map((company, index) => ( )); }; // 根据选中的公司ID获取公司名称(用于筛选模拟数据) getSelectedCompanyName = () => { const { companyData, selectedCompany } = this.props; if (!selectedCompany || !companyData || companyData.length === 0) { return null; } const selectedCompanyObj = companyData.find((company) => company.ID === selectedCompany); return selectedCompanyObj ? selectedCompanyObj.NAME : null; }; waitForElement = (elementId, maxRetries = 10) => { return new Promise((resolve) => { let retries = 0; const checkInterval = setInterval(() => { const element = document.getElementById(elementId); if (element || retries >= maxRetries) { clearInterval(checkInterval); resolve(!!element); } retries++; }, 50); }); }; // 图表1: 各公司隐患统计柱状图(使用 hiddenList 数据) renderHiddenBarChart = async () => { if (this.isUnmounted) return; const elementExists = await this.waitForElement('hiddenBarChart'); if (!elementExists || this.isUnmounted) return; if (this.echartsInstances.hiddenBarChart) { this.echartsInstances.hiddenBarChart.dispose(); this.echartsInstances.hiddenBarChart = null; } const chartDom = document.getElementById('hiddenBarChart'); if (!chartDom) return; this.echartsInstances.hiddenBarChart = echarts.init(chartDom); const { hiddenSubData } = this.props; let hiddenList = hiddenSubData?.hiddenList || []; if (hiddenList.length === 0) { this.echartsInstances.hiddenBarChart.setOption({ title: { text: '各公司隐患统计', x: 'center', y: '25%', textStyle: { fontSize: 16, color: '#999' }, }, graphic: { type: 'text', left: 'center', top: 'middle', style: { text: '暂无数据', fill: '#999', fontSize: 14, }, }, }); return; } const companyNames = hiddenList.map((item) => item.companyName); const majorCounts = hiddenList.map((item) => item.majorCount); const generalCounts = hiddenList.map((item) => item.generalCount); const option = { title: { text: '各公司隐患统计', x: 'center', y: '5%', textStyle: { fontSize: 16, color: '#000', fontWeight: 'bold' }, }, tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, formatter: function (params) { let result = `${params[0].axisValue}
`; params.forEach((param) => { result += `${param.marker}${param.seriesName}: ${param.value}
`; }); return result; }, }, legend: { data: ['重大隐患', '一般隐患'], orient: 'vertical', right: '3%', top: '5%', itemGap: 16, itemWidth: 18, itemHeight: 12, textStyle: { color: '#000', fontSize: 14 }, }, grid: { left: '8%', right: '5%', top: '18%', bottom: '8%', containLabel: true, }, xAxis: [ { type: 'category', data: companyNames, axisLine: { show: false }, axisTick: { show: false }, axisLabel: { textStyle: { color: '#000' }, rotate: companyNames.length > 4 ? 15 : 0, interval: 0, fontSize: 12, }, }, ], yAxis: [ { type: 'value', show: true, axisLine: { show: false }, axisTick: { show: false }, axisLabel: { show: true, textStyle: { color: '#000' }, }, splitLine: { show: false }, name: '隐患数量', nameTextStyle: { fontSize: 12 }, }, ], series: [ { name: '重大隐患', type: 'bar', data: majorCounts, itemStyle: { normal: { color: '#c92a2a', // 红色 }, }, label: { show: true, position: 'top', textStyle: { color: '#c92a2a', fontSize: 12 }, formatter: (params) => `${params.value}`, }, barWidth: '35%', }, { name: '一般隐患', type: 'bar', data: generalCounts, itemStyle: { normal: { color: '#4285F4', // 蓝色 }, }, label: { show: true, position: 'top', textStyle: { color: '#4285F4', fontSize: 12 }, formatter: (params) => `${params.value}`, }, barWidth: '35%', }, ], }; this.echartsInstances.hiddenBarChart.setOption(option); this.setupResizeHandler('hiddenBarChart', this.renderHiddenBarChart); }; // 图表2: 隐患整改情况柱状图(使用 hiddenRectifyList 数据) renderHiddenRectifyChart = async () => { if (this.isUnmounted) return; const elementExists = await this.waitForElement('hiddenRectifyChart'); if (!elementExists || this.isUnmounted) return; if (this.echartsInstances.hiddenRectifyChart) { this.echartsInstances.hiddenRectifyChart.dispose(); this.echartsInstances.hiddenRectifyChart = null; } const chartDom = document.getElementById('hiddenRectifyChart'); if (!chartDom) return; this.echartsInstances.hiddenRectifyChart = echarts.init(chartDom); const { hiddenSubData } = this.props; let hiddenRectifyList = hiddenSubData?.hiddenRectifyList || []; if (hiddenRectifyList.length === 0) { this.echartsInstances.hiddenRectifyChart.setOption({ title: { text: '各公司隐患整改情况', x: 'center', y: '25%', textStyle: { fontSize: 16, color: '#999' }, }, graphic: { type: 'text', left: 'center', top: 'middle', style: { text: '暂无数据', fill: '#999', fontSize: 14, }, }, }); return; } const companyNames = hiddenRectifyList.map((item) => item.companyName); const majorTotal = hiddenRectifyList.map((item) => item.majorCount); const majorRectified = hiddenRectifyList.map((item) => (item.majorCount || 0) - (item.majorCountNo || 0)); const generalTotal = hiddenRectifyList.map((item) => item.generalCount); const generalRectified = hiddenRectifyList.map((item) => (item.generalCount || 0) - (item.generalCountNo || 0)); const option = { title: { text: '各公司隐患整改情况', x: 'center', y: '5%', textStyle: { fontSize: 16, color: '#000', fontWeight: 'bold' }, }, tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, formatter: function (params) { let result = `${params[0].axisValue}
`; params.forEach((param) => { result += `${param.marker}${param.seriesName}: ${param.value}
`; }); return result; }, }, legend: { data: ['重大隐患总数', '重大隐患已整改', '一般隐患总数', '一般隐患已整改'], orient: 'vertical', right: '3%', top: '5%', itemGap: 12, itemWidth: 18, itemHeight: 12, textStyle: { color: '#000', fontSize: 12 }, }, grid: { left: '8%', right: '5%', top: '18%', bottom: '8%', containLabel: true, }, xAxis: [ { type: 'category', data: companyNames, axisLine: { show: false }, axisTick: { show: false }, axisLabel: { textStyle: { color: '#000' }, rotate: companyNames.length > 4 ? 15 : 0, interval: 0, fontSize: 12, }, }, ], yAxis: [ { type: 'value', show: true, axisLine: { show: false }, axisTick: { show: false }, axisLabel: { show: true, textStyle: { color: '#000' }, }, splitLine: { show: false }, name: '隐患数量', nameTextStyle: { fontSize: 12 }, }, ], series: [ { name: '重大隐患总数', type: 'bar', data: majorTotal, itemStyle: { normal: { color: '#c92a2a', // 红色 }, }, label: { show: true, position: 'top', textStyle: { color: '#c92a2a', fontSize: 11 }, formatter: (params) => `${params.value}`, }, barWidth: '20%', }, { name: '重大隐患已整改', type: 'bar', data: majorRectified, itemStyle: { normal: { color: '#ffa94d', // 橙色 }, }, label: { show: true, position: 'top', textStyle: { color: '#ffa94d', fontSize: 11 }, formatter: (params) => `${params.value}`, }, barWidth: '20%', }, { name: '一般隐患总数', type: 'bar', data: generalTotal, itemStyle: { normal: { color: '#4285F4', // 蓝色 }, }, label: { show: true, position: 'top', textStyle: { color: '#4285F4', fontSize: 11 }, formatter: (params) => `${params.value}`, }, barWidth: '20%', }, { name: '一般隐患已整改', type: 'bar', data: generalRectified, itemStyle: { normal: { color: '#ffe066', // 黄色 }, }, label: { show: true, position: 'top', textStyle: { color: '#d4a000', fontSize: 11 }, formatter: (params) => `${params.value}`, }, barWidth: '20%', }, ], }; this.echartsInstances.hiddenRectifyChart.setOption(option); this.setupResizeHandler('hiddenRectifyChart', this.renderHiddenRectifyChart); }; // 排名列表组件(支持公司筛选) renderRankingList = () => { const { hiddenSubData, selectedCompany, onCompanyChange, companyData } = this.props; let hiddenRanking = hiddenSubData?.hiddenRanking || []; // 根据选中的公司筛选数据 const selectedCompanyName = this.getSelectedCompanyName(); if (selectedCompanyName) { hiddenRanking = hiddenRanking.filter((item) => item.companyName === selectedCompanyName); } if (hiddenRanking.length === 0) { return (
{selectedCompanyName ? `${selectedCompanyName} 暂无隐患排名数据` : '暂无隐患排名数据'}
); } return (
隐患排名
{/* 公司筛选器 - 与 TrainingContent 样式保持一致 */}
选择公司:
{hiddenRanking.map((item, index) => ( ))}
排名 公司 隐患名称 数量
{index + 1} {item.companyName} {item.hiddenName} {item.qty}
); }; setupResizeHandler = (chartName, renderMethod) => { const resizeHandler = () => { if (this.echartsInstances[chartName] && !this.isUnmounted) { this.echartsInstances[chartName].resize(); } }; this.chartResizeHandlers[chartName] = resizeHandler; window.addEventListener('resize', resizeHandler); }; initAllCharts = () => { if (this.isUnmounted) return; setTimeout(() => { if (this.isUnmounted) return; this.renderHiddenBarChart(); this.renderHiddenRectifyChart(); }, 100); }; disposeAllCharts = () => { Object.keys(this.echartsInstances).forEach((key) => { if (this.echartsInstances[key]) { try { this.echartsInstances[key].dispose(); } catch (e) { console.warn(`Dispose chart ${key} error:`, e); } this.echartsInstances[key] = null; } }); Object.keys(this.chartResizeHandlers).forEach((key) => { if (this.chartResizeHandlers[key]) { window.removeEventListener('resize', this.chartResizeHandlers[key]); } }); this.chartResizeHandlers = {}; }; componentDidMount() { this.isUnmounted = false; this.initAllCharts(); } componentDidUpdate(prevProps) { // 当 hiddenSubData 或 selectedCompany 变化时重新渲染图表 if ( prevProps.hiddenSubData !== this.props.hiddenSubData || prevProps.selectedCompany !== this.props.selectedCompany ) { this.renderHiddenBarChart(); this.renderHiddenRectifyChart(); } } componentWillUnmount() { this.isUnmounted = true; this.disposeAllCharts(); } render() { const { selectedCompany, onCompanyChange } = this.props; return (
{/* 第一行 - 柱状图(left)+ 排名列表(right) */}
{/* 添加公司筛选器(左上角,与 TrainingContent 样式一致) */}
{this.renderRankingList()}
{/* 第二行 - 隐患整改情况柱状图 */}
); } } export default HiddenSolve;