仅供测试,请勿发布
This commit is contained in:
parent
b5c71a7cde
commit
c7bf20269d
@ -33,33 +33,35 @@ class BI00FullScreen extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {}
|
||||
componentDidMount() {
|
||||
window.open('#/popup', '_blank', 'noreferrer');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
width: '1200px',
|
||||
top: '0',
|
||||
bottom: '0',
|
||||
left: '0',
|
||||
right: '0',
|
||||
margin: 'auto',
|
||||
borderStyle: 'solid',
|
||||
borderColor: '#ccc',
|
||||
borderWidth: '1px',
|
||||
height: '100%',
|
||||
}}
|
||||
// style={{
|
||||
// backgroundColor: 'white',
|
||||
// width: '1200px',
|
||||
// top: '0',
|
||||
// bottom: '0',
|
||||
// left: '0',
|
||||
// right: '0',
|
||||
// margin: 'auto',
|
||||
// borderStyle: 'solid',
|
||||
// borderColor: '#ccc',
|
||||
// borderWidth: '1px',
|
||||
// height: '100%',
|
||||
// }}
|
||||
>
|
||||
<h1 style={{ textAlign: 'center', marginTop: '30px' }}>金源公司生产安全管控平台</h1>
|
||||
{/* <h1 style={{ textAlign: 'center', marginTop: '30px' }}>金源公司生产安全管控平台</h1>
|
||||
<Button
|
||||
type={this.state.filterType == 1 ? 'primary' : 'default'}
|
||||
onClick={() => window.open('#/popup', '_blank', 'noreferrer')}
|
||||
style={{ marginRight: '5px', alignItems: 'center', margin: 'auto' }}
|
||||
>
|
||||
管控平台入口
|
||||
</Button>
|
||||
</Button> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// TrainingContent.js - 安全培训页面组件
|
||||
import React from 'react';
|
||||
import { Row, Col, Select } from 'antd';
|
||||
import { Row, Col, Select, Table } from 'antd';
|
||||
import styles from './../fullinter.less';
|
||||
import echarts from 'echarts';
|
||||
const { Option } = Select;
|
||||
@ -12,7 +12,6 @@ class TrainingContent extends React.Component {
|
||||
chart1: null, // 各部门培训统计(柱状图)
|
||||
chart2: null, // 各部门培训完成率
|
||||
chart3: null, // 培训类型分布
|
||||
chart4: null, // 月度培训对比
|
||||
};
|
||||
this.chartResizeHandlers = {};
|
||||
this.isUnmounted = false;
|
||||
@ -181,6 +180,7 @@ class TrainingContent extends React.Component {
|
||||
this.echartsInstances.chart1.setOption(option);
|
||||
this.setupResizeHandler('chart1', this.renderChart1);
|
||||
};
|
||||
|
||||
// 生成月份选项(1-12月)
|
||||
getMonthOptions = () => {
|
||||
const months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
|
||||
@ -190,6 +190,7 @@ class TrainingContent extends React.Component {
|
||||
</Option>
|
||||
));
|
||||
};
|
||||
|
||||
getCompanyOptions = () => {
|
||||
const { companyData } = this.props;
|
||||
return companyData.map((company, index) => (
|
||||
@ -498,101 +499,75 @@ class TrainingContent extends React.Component {
|
||||
this.setupResizeHandler('chart3', this.renderChart3);
|
||||
};
|
||||
|
||||
// 图表4: 月度培训对比(分组柱状图)
|
||||
renderChart4 = async () => {
|
||||
if (this.isUnmounted) return;
|
||||
const elementExists = await this.waitForElement('trainingChart4');
|
||||
if (!elementExists || this.isUnmounted) return;
|
||||
// 表格4: 特种作业操作证统计表格
|
||||
renderCertificateTable = () => {
|
||||
const { trainingSubIDCard } = this.props;
|
||||
|
||||
if (this.echartsInstances.chart4) {
|
||||
this.echartsInstances.chart4.dispose();
|
||||
this.echartsInstances.chart4 = null;
|
||||
// 如果没有数据,返回空
|
||||
if (!trainingSubIDCard || trainingSubIDCard.length === 0) {
|
||||
return <div style={{ textAlign: 'center', padding: '50px', color: '#999' }}>暂无证书数据</div>;
|
||||
}
|
||||
|
||||
const chartDom = document.getElementById('trainingChart4');
|
||||
if (!chartDom) return;
|
||||
|
||||
this.echartsInstances.chart4 = echarts.init(chartDom);
|
||||
|
||||
// 近6个月各部门培训场次对比
|
||||
const months = ['1月', '2月', '3月', '4月', '5月', '6月'];
|
||||
const departments = ['安全部', '生产部', '技术部'];
|
||||
|
||||
const seriesData = [
|
||||
{ name: '安全部', data: [5, 6, 7, 8, 7, 9], color: '#4285F4' },
|
||||
{ name: '生产部', data: [8, 9, 10, 11, 12, 13], color: '#66bb6a' },
|
||||
{ name: '技术部', data: [4, 5, 6, 6, 7, 8], color: '#ffa94d' },
|
||||
];
|
||||
|
||||
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}<br/>`;
|
||||
params.forEach((param) => {
|
||||
result += `${param.marker}${param.seriesName}: ${param.value}场<br/>`;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
data: seriesData.map((s) => s.name),
|
||||
orient: 'horizontal',
|
||||
left: 'center',
|
||||
top: '15%',
|
||||
itemGap: 20,
|
||||
itemWidth: 18,
|
||||
itemHeight: 12,
|
||||
textStyle: { color: '#333', fontSize: 12 },
|
||||
},
|
||||
grid: {
|
||||
left: '8%',
|
||||
right: '5%',
|
||||
top: '25%',
|
||||
bottom: '8%',
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: months,
|
||||
axisLine: { lineStyle: { color: '#666' } },
|
||||
axisLabel: { textStyle: { color: '#333' } },
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '培训场次',
|
||||
axisLabel: { textStyle: { color: '#666' } },
|
||||
splitLine: { lineStyle: { color: '#e0e0e0' } },
|
||||
},
|
||||
series: seriesData.map((s) => ({
|
||||
name: s.name,
|
||||
type: 'bar',
|
||||
data: s.data,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: s.color,
|
||||
barBorderRadius: [4, 4, 0, 0],
|
||||
},
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
textStyle: { fontSize: 10 },
|
||||
formatter: '{c}',
|
||||
},
|
||||
barWidth: '25%',
|
||||
})),
|
||||
// 第一行是表头
|
||||
const headers = trainingSubIDCard[0] || [];
|
||||
// 数据行(从第二行开始)
|
||||
const dataRows = trainingSubIDCard.slice(1);
|
||||
// 计算每列的最小宽度(根据表头文字长度)
|
||||
const getColumnWidth = (header) => {
|
||||
const chineseCharWidth = 14; // 中文字符宽度(px)
|
||||
const paddingWidth = 32; // 单元格内边距
|
||||
const minWidth = 100; // 最小宽度
|
||||
const maxWidth = 200; // 最大宽度
|
||||
const textLength = header.length;
|
||||
const calculatedWidth = textLength * chineseCharWidth + paddingWidth;
|
||||
return Math.min(Math.max(calculatedWidth, minWidth), maxWidth);
|
||||
};
|
||||
|
||||
this.echartsInstances.chart4.setOption(option);
|
||||
this.setupResizeHandler('chart4', this.renderChart4);
|
||||
// 生成表格列配置
|
||||
const columns = headers.map((header, index) => ({
|
||||
title: header,
|
||||
dataIndex: `col${index}`,
|
||||
key: `col${index}`,
|
||||
align: 'center',
|
||||
width: getColumnWidth(header),
|
||||
fixed: index === 0 ? 'left' : index === headers.length - 1 ? 'right' : undefined,
|
||||
render: (text) => {
|
||||
if (header === '小计') {
|
||||
return <strong style={{ color: '#4285f4' }}>{text}</strong>;
|
||||
}
|
||||
// 如果是公司列,加粗显示
|
||||
if (header === '公司') {
|
||||
return <strong>{text}</strong>;
|
||||
}
|
||||
return text;
|
||||
},
|
||||
}));
|
||||
|
||||
// 转换数据格式为表格所需格式
|
||||
const tableData = dataRows.map((row, rowIndex) => {
|
||||
const rowData = { key: rowIndex };
|
||||
row.forEach((cell, colIndex) => {
|
||||
rowData[`col${colIndex}`] = cell;
|
||||
});
|
||||
return rowData;
|
||||
});
|
||||
|
||||
// 横向滚动配置(当列数过多时)
|
||||
const scrollConfig = columns.length > 10 ? { x: columns.length * 100, y: 380 } : {};
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%', overflow: 'hidden', padding: '10px' }}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={tableData}
|
||||
pagination={false}
|
||||
scroll={scrollConfig}
|
||||
size="small"
|
||||
bordered
|
||||
className={styles.certificateTable}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
setupResizeHandler = (chartName, renderMethod) => {
|
||||
@ -612,7 +587,6 @@ class TrainingContent extends React.Component {
|
||||
this.renderChart1();
|
||||
this.renderChart2();
|
||||
this.renderChart3();
|
||||
this.renderChart4();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
@ -647,16 +621,15 @@ class TrainingContent extends React.Component {
|
||||
prevProps.trainingSubDataMonth !== this.props.trainingSubDataMonth ||
|
||||
prevProps.selectedMonth !== this.props.selectedMonth
|
||||
) {
|
||||
// this.renderChart1();
|
||||
this.renderChart2();
|
||||
}
|
||||
if (
|
||||
prevProps.trainingSubBSType !== this.props.trainingSubBSType ||
|
||||
prevProps.selectedCompany !== this.props.selectedCompany
|
||||
) {
|
||||
// this.renderChart1();
|
||||
this.renderChart3();
|
||||
}
|
||||
// 当 trainingSubIDCard 变化时,表格会自动更新,不需要额外处理
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -690,10 +663,10 @@ class TrainingContent extends React.Component {
|
||||
<div id="trainingChart2" className={styles.trainingChartContainer}></div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 第二行 - 图表3和图表4 */}
|
||||
{/* 第二行 - 图表3和表格4 */}
|
||||
<div className={styles.trainingRow}>
|
||||
<div className={styles.trainingCard}>
|
||||
{/* 添加月份选择器 */}
|
||||
{/* 添加公司选择器 */}
|
||||
<div className={styles.monthSelectorWrapper}>
|
||||
<span className={styles.monthSelectorLabel}>选择公司:</span>
|
||||
<Select
|
||||
@ -701,6 +674,8 @@ class TrainingContent extends React.Component {
|
||||
onChange={onCompanyChange}
|
||||
style={{ width: 120 }}
|
||||
className={styles.monthSelect}
|
||||
allowClear
|
||||
placeholder="请选择公司"
|
||||
>
|
||||
{this.getCompanyOptions()}
|
||||
</Select>
|
||||
@ -708,7 +683,20 @@ class TrainingContent extends React.Component {
|
||||
<div id="trainingChart3" className={styles.trainingChartContainer}></div>
|
||||
</div>
|
||||
<div className={styles.trainingCard}>
|
||||
<div id="trainingChart4" className={styles.trainingChartContainer}></div>
|
||||
<div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
|
||||
<div
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
padding: '20px 0 0 0',
|
||||
fontWeight: 'bold',
|
||||
fontSize: '17px',
|
||||
color: '#000',
|
||||
}}
|
||||
>
|
||||
特种作业操作证统计
|
||||
</div>
|
||||
<div style={{ flex: 1, overflow: 'auto' }}>{this.renderCertificateTable()}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -59,7 +59,7 @@ class FullScreen extends React.Component {
|
||||
MonthRecordCount: [],
|
||||
MonthPersonCount: [],
|
||||
},
|
||||
trainingSubIDCard: {},
|
||||
trainingSubIDCard: [],
|
||||
trainingSubBSType: {},
|
||||
companyData: [],
|
||||
// 新增:当前选择的月份
|
||||
@ -128,6 +128,11 @@ class FullScreen extends React.Component {
|
||||
|
||||
handleTabClick = (name) => {
|
||||
this.setState({ activeTab: name });
|
||||
if (name === '首页') {
|
||||
this.getYearPXData();
|
||||
this.loadMediaFiles();
|
||||
this.getAnnouncementData();
|
||||
}
|
||||
// 当点击安全培训tab时,获取对应数据
|
||||
if (name === '安全培训') {
|
||||
this.getHomeSESubYearData();
|
||||
@ -290,7 +295,6 @@ class FullScreen extends React.Component {
|
||||
const currentDateStr = `${year}-${month}-${day}`; // 例如:2024-06-15
|
||||
|
||||
json.Parameter1 = currentDateStr; // 设置为当前日期
|
||||
json.Parameter2 = this.state.selectedCompany.toString(); // 月份
|
||||
this.props.dispatch({
|
||||
type: 'app/getDataByPost',
|
||||
payload: json,
|
||||
@ -314,7 +318,9 @@ class FullScreen extends React.Component {
|
||||
const currentDateStr = `${year}-${month}-${day}`; // 例如:2024-06-15
|
||||
|
||||
json.Parameter1 = currentDateStr; // 设置为当前日期
|
||||
json.Parameter2 = this.state.selectedCompany;
|
||||
if (this.state.selectedCompany) {
|
||||
json.Parameter2 = this.state.selectedCompany;
|
||||
}
|
||||
this.props.dispatch({
|
||||
type: 'app/getDataByPost',
|
||||
payload: json,
|
||||
@ -355,6 +361,7 @@ class FullScreen extends React.Component {
|
||||
selectedCompany,
|
||||
trainingSubBSType,
|
||||
companyData,
|
||||
trainingSubIDCard,
|
||||
} = this.state;
|
||||
// 如果是安全培训,显示专门的培训页面
|
||||
if (activeTab === '安全培训') {
|
||||
@ -369,6 +376,7 @@ class FullScreen extends React.Component {
|
||||
selectedCompany={selectedCompany}
|
||||
onMonthChange={this.handleMonthChange}
|
||||
onCompanyChange={this.handleCompanyChange}
|
||||
trainingSubIDCard={trainingSubIDCard}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -673,3 +673,36 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
// 证书表格样式
|
||||
.certificateTable {
|
||||
margin-bottom: 20px;
|
||||
:global {
|
||||
.ant-table {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-table-thead > tr > th {
|
||||
background-color: #f5f5f5;
|
||||
font-weight: bold;
|
||||
padding: 8px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ant-table-tbody > tr > td {
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.ant-table-tbody > tr:hover > td {
|
||||
background-color: #e6f7ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.totalRow {
|
||||
:global {
|
||||
td {
|
||||
background-color: #f0f0f0 !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user