仅供测试,请勿发布

This commit is contained in:
yunkexin 2026-04-23 11:29:34 +08:00
parent 746535dfee
commit b5c71a7cde
3 changed files with 182 additions and 44 deletions

View File

@ -335,7 +335,7 @@ class HomeContent extends React.Component {
title: {
text: '当月工作培训统计数量',
x: 'center',
y: 'center',
y: '25%',
textStyle: { fontSize: 16, color: '#999' },
},
graphic: {
@ -343,7 +343,7 @@ class HomeContent extends React.Component {
left: 'center',
top: 'middle',
style: {
text: '暂无培训数据',
text: '暂无数据',
fill: '#999',
fontSize: 14,
},

View File

@ -60,7 +60,7 @@ class TrainingContent extends React.Component {
title: {
text: '本年度各公司培训分析',
x: 'center',
y: 'center',
y: '25%',
textStyle: { fontSize: 16, color: '#999' },
},
graphic: {
@ -68,7 +68,7 @@ class TrainingContent extends React.Component {
left: 'center',
top: 'middle',
style: {
text: '暂无培训数据',
text: '暂无数据',
fill: '#999',
fontSize: 14,
},
@ -190,6 +190,14 @@ class TrainingContent extends React.Component {
</Option>
));
};
getCompanyOptions = () => {
const { companyData } = this.props;
return companyData.map((company, index) => (
<Option key={index + 1} value={company.ID}>
{company.NAME}
</Option>
));
};
// 图表2: 各部门培训完成率(横向柱状图)
renderChart2 = async () => {
@ -219,7 +227,7 @@ class TrainingContent extends React.Component {
title: {
text: '本年度各公司培训分析',
x: 'center',
y: 'center',
y: '25%',
textStyle: { fontSize: 16, color: '#999' },
},
graphic: {
@ -227,7 +235,7 @@ class TrainingContent extends React.Component {
left: 'center',
top: 'middle',
style: {
text: '暂无培训数据',
text: '暂无数据',
fill: '#999',
fontSize: 14,
},
@ -357,60 +365,131 @@ class TrainingContent extends React.Component {
this.echartsInstances.chart3 = echarts.init(chartDom);
// 培训类型分布数据
const trainingTypes = [
{ name: '安全法规培训', value: 35 },
{ name: '操作规程培训', value: 28 },
{ name: '应急演练培训', value: 20 },
{ name: '职业健康培训', value: 12 },
{ name: '其他培训', value: 5 },
];
// 使用 props 传入的 trainingSubData 数据(来自 getHomeSESubYear 接口)
const { trainingSubBSType } = this.props;
const listNAME = trainingSubBSType?.listNAME || [];
const monthRecordCount = trainingSubBSType?.MonthRecordCount || []; // 培训场次
const monthPersonCount = trainingSubBSType?.MonthPersonCount || []; // 培训人次
// 如果没有数据,显示暂无数据提示
if (listNAME.length === 0) {
this.echartsInstances.chart3.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 option = {
title: {
text: '培训类型分布',
text: '当月公司的培训类型情况',
x: 'center',
y: '5%',
textStyle: { fontSize: 16, color: '#000', fontWeight: 'bold' },
},
tooltip: {
trigger: 'item',
trigger: 'axis',
axisPointer: { type: 'shadow' },
formatter: function (params) {
return `${params.name}: ${params.value}场 (${params.percent}%)`;
let result = `${params[0].axisValue}<br/>`;
params.forEach((param) => {
result += `${param.marker}${param.seriesName}: ${param.value}<br/>`;
});
return result;
},
},
legend: {
orient: 'vertical',
right: '5%',
top: 'middle',
itemGap: 12,
itemWidth: 14,
itemHeight: 10,
textStyle: { color: '#333', fontSize: 11 },
formatter: function (name) {
const item = trainingTypes.find((t) => t.name === name);
return `${name} ${item?.value || 0}`;
},
data: ['培训人次', '培训场次'],
right: '3%', // 靠右
top: '5%', // 垂直居中
itemGap: 16,
itemWidth: 18,
itemHeight: 12,
textStyle: { color: '#000', fontSize: 14 },
},
color: ['#4285F4', '#66bb6a', '#ffa94d', '#ab47bc', '#ef5350'],
grid: {
left: '5%',
right: '5%', // 为右侧垂直图例留出空间
top: '18%',
bottom: '8%',
containLabel: true,
},
xAxis: [
{
type: 'category',
data: listNAME,
axisLine: { show: false },
axisTick: { show: false },
axisLabel: {
textStyle: { color: '#000' },
rotate: listNAME.length > 4 ? 15 : 0,
interval: 0,
},
},
],
yAxis: [
{
type: 'value',
show: true,
axisLine: { show: false },
axisTick: { show: false },
axisLabel: {
show: true,
textStyle: { color: '#000' },
},
splitLine: { show: false },
name: '',
nameTextStyle: { show: false },
},
],
series: [
{
name: '培训场次',
type: 'pie',
radius: ['45%', '70%'],
center: ['40%', '55%'],
avoidLabelOverlap: false,
name: '培训人次',
type: 'bar',
data: monthPersonCount,
itemStyle: {
normal: {
color: '#4285F4', // 蓝色
},
},
label: {
show: true,
position: 'outside',
formatter: '{b}: {d}%',
textStyle: { fontSize: 11, color: '#333' },
position: 'top',
textStyle: { color: '#4285F4', fontSize: 12 },
formatter: (params) => `${params.value}`,
},
emphasis: {
label: { show: true, fontSize: 14, fontWeight: 'bold' },
barWidth: '35%',
},
{
name: '培训场次',
type: 'bar',
data: monthRecordCount,
itemStyle: {
normal: {
color: '#ffe066', // 黄色
},
},
labelLine: { length: 8, length2: 8, smooth: true },
data: trainingTypes,
label: {
show: true,
position: 'top',
textStyle: { color: '#d4a000', fontSize: 12 },
formatter: (params) => `${params.value}`,
},
barWidth: '35%',
},
],
};
@ -565,13 +644,19 @@ class TrainingContent extends React.Component {
componentDidUpdate(prevProps) {
// 当 trainingSubData 或 trainingSubDataMonth 变化时重新渲染图表
if (
prevProps.trainingSubData !== this.props.trainingSubData ||
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();
}
}
componentWillUnmount() {
@ -580,7 +665,7 @@ class TrainingContent extends React.Component {
}
render() {
const { selectedMonth = 1, onMonthChange } = this.props;
const { selectedMonth = 1, onMonthChange, onCompanyChange, selectedCompany } = this.props;
return (
<div className={styles.trainingContentWrapper}>
<div className={styles.trainingGrid}>
@ -608,6 +693,18 @@ class TrainingContent extends React.Component {
{/* 第二行 - 图表3和图表4 */}
<div className={styles.trainingRow}>
<div className={styles.trainingCard}>
{/* 添加月份选择器 */}
<div className={styles.monthSelectorWrapper}>
<span className={styles.monthSelectorLabel}>选择公司</span>
<Select
value={selectedCompany}
onChange={onCompanyChange}
style={{ width: 120 }}
className={styles.monthSelect}
>
{this.getCompanyOptions()}
</Select>
</div>
<div id="trainingChart3" className={styles.trainingChartContainer}></div>
</div>
<div className={styles.trainingCard}>

View File

@ -61,8 +61,10 @@ class FullScreen extends React.Component {
},
trainingSubIDCard: {},
trainingSubBSType: {},
companyData: [],
// 新增:当前选择的月份
selectedMonth: new Date().getMonth() + 1, // 默认当前月份1-12
selectedCompany: '',
};
this.isUnmounted = false;
}
@ -132,6 +134,7 @@ class FullScreen extends React.Component {
this.getHomeSESubYearMonthData();
this.getHomeSESubIDCardData();
this.getBSTypeMonthData();
this.getCompanyData();
}
};
@ -238,6 +241,13 @@ class FullScreen extends React.Component {
this.getHomeSESubYearMonthData();
});
};
handleCompanyChange = (company) => {
console.log(company, '11111');
this.setState({ selectedCompany: company }, () => {
// 重新获取月份数据
this.getBSTypeMonthData();
});
};
// 获取安全培训页面数据
getHomeSESubYearMonthData = () => {
const orgId = storage('lacal').getItem('webOrgId')?.val;
@ -280,6 +290,7 @@ 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,
@ -303,6 +314,7 @@ class FullScreen extends React.Component {
const currentDateStr = `${year}-${month}-${day}`; // 例如2024-06-15
json.Parameter1 = currentDateStr; // 设置为当前日期
json.Parameter2 = this.state.selectedCompany;
this.props.dispatch({
type: 'app/getDataByPost',
payload: json,
@ -316,18 +328,47 @@ class FullScreen extends React.Component {
},
});
};
getCompanyData = () => {
const orgId = storage('lacal').getItem('webOrgId')?.val;
const json = initFilter(orgId);
this.props.dispatch({
type: 'app/getDataByPost',
payload: json,
url: 'FM/Organization/OrderPaged',
onComplete: (ret) => {
if (ret && !this.isUnmounted) {
this.setState({
companyData: ret,
});
}
},
});
};
renderOtherTabContent = () => {
const { activeTab, trainingData, trainingSubData, trainingSubDataMonth, selectedMonth } = this.state;
const {
activeTab,
trainingData,
trainingSubData,
trainingSubDataMonth,
selectedMonth,
selectedCompany,
trainingSubBSType,
companyData,
} = this.state;
// 如果是安全培训,显示专门的培训页面
if (activeTab === '安全培训') {
return (
<TrainingContent
trainingData={trainingData}
trainingSubData={trainingSubData}
trainingSubBSType={trainingSubBSType}
companyData={companyData}
trainingSubDataMonth={trainingSubDataMonth}
selectedMonth={selectedMonth}
selectedCompany={selectedCompany}
onMonthChange={this.handleMonthChange}
onCompanyChange={this.handleCompanyChange}
/>
);
}