644 lines
19 KiB
JavaScript
644 lines
19 KiB
JavaScript
import React, { useState, useEffect, useRef, Component } from "react";
|
|
import { connect } from "dva";
|
|
import {
|
|
initFilter,
|
|
addRuleAndGroups,
|
|
guid,
|
|
extendInclude,
|
|
extendRule,
|
|
extendOrder,
|
|
extend,
|
|
initQueryFilter,
|
|
} from "../../../utils/common";
|
|
import { Table, Row, Col, Button, Select, DatePicker, message } from "antd";
|
|
import echarts from "echarts";
|
|
import moment from "moment";
|
|
const { Option } = Select;
|
|
class TrainSafeAnalysis extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
pagination: {},
|
|
retData: [],
|
|
totalUsers: 0,
|
|
totalActiveUsers: 0,
|
|
selectUser: "",
|
|
selectDepartment: "",
|
|
dates: [],
|
|
recordNums: [],
|
|
todayCount: 0,
|
|
NUM1: 0,
|
|
NUM2: 0,
|
|
NUM3: 0,
|
|
NUM4: 0,
|
|
NUM5: 0,
|
|
NUM6: 0,
|
|
NUM7: 0,
|
|
searchMonth: moment().format("YYYY-MM"),
|
|
showLoading: false,
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.state.columns1 = [
|
|
{
|
|
title: "序号",
|
|
render: (text, record, index) => `${index + 1}`,
|
|
},
|
|
{
|
|
width: "270px",
|
|
title: "课程名称",
|
|
dataIndex: "NAME",
|
|
},
|
|
{
|
|
width: "270px",
|
|
title: "培训起止时间",
|
|
dataIndex: "TIMERANGE",
|
|
},
|
|
{
|
|
title: "应参训人数",
|
|
dataIndex: "SHOULD_TRAINER",
|
|
},
|
|
{
|
|
title: "实际参训人数",
|
|
dataIndex: "ACTUAL_TRAINER",
|
|
},
|
|
{
|
|
title: "参训率",
|
|
render: (text, record) => (
|
|
<span>
|
|
{((record.ACTUAL_TRAINER / record.SHOULD_TRAINER) * 100).toFixed(
|
|
0
|
|
) + "%"}
|
|
</span>
|
|
),
|
|
},
|
|
{
|
|
title: "考核方式",
|
|
dataIndex: "METHOD",
|
|
},
|
|
{
|
|
title: "通过率",
|
|
dataIndex: "PASS_RATE",
|
|
render: (text, record) => (
|
|
<span>{(record.PASS_RATE * 100).toFixed(0) + "%"}</span>
|
|
),
|
|
},
|
|
{
|
|
title: "效果评估(优良率)",
|
|
dataIndex: "EFFORT_RATE",
|
|
render: (text, record) => (
|
|
<span>{(record.EFFORT_RATE * 1).toFixed(0) + "%"}</span>
|
|
),
|
|
},
|
|
];
|
|
this.loadData(this.state.searchMonth);
|
|
}
|
|
loadData = (startTime) => {
|
|
const json = initFilter(this.props.login.OrgId);
|
|
this.state.showLoading = true;
|
|
json.Parameter1 = startTime;
|
|
// this.props.dispatch({
|
|
// type: "app/getDataByPost",
|
|
// url: "BI/BIController/getSafeTrainData",
|
|
// payload: json,
|
|
// onlyData: false,
|
|
// onComplete: (ret) => {
|
|
// if (ret) {
|
|
let ret = {
|
|
"IsSuccessful": true,
|
|
"Data": {
|
|
"NUM1": 1,
|
|
"NUM2": 20,
|
|
"NUM3": 102,
|
|
"NUM4": 13,
|
|
"NUM5": 14,
|
|
"NUM6": 15,
|
|
"NUM7": 1277,
|
|
"trainRecords": [
|
|
{
|
|
"NAME": "安全生产法和道路交通法解读",
|
|
"TIMERANGE": "2025/1/1 11:30:00-2025/1/1 13:00:00",
|
|
"SHOULD_TRAINER": 1,
|
|
"ACTUAL_TRAINER": 1,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "安全生产法、道路交通 法",
|
|
"TIMERANGE": "2025/1/3 15:00:39-2025/1/3 16:31:46",
|
|
"SHOULD_TRAINER": 1,
|
|
"ACTUAL_TRAINER": 1,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "《福建省进一步加强矿山安全生产工作的若干措施》",
|
|
"TIMERANGE": "2025/1/6 16:00:00-2025/1/6 16:30:00",
|
|
"SHOULD_TRAINER": 24,
|
|
"ACTUAL_TRAINER": 24,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0.6086956521739131",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "关于做好2025年元旦春节期间有关工作的通知",
|
|
"TIMERANGE": "2025/1/6 16:00:00-2025/1/6 17:00:00",
|
|
"SHOULD_TRAINER": 19,
|
|
"ACTUAL_TRAINER": 19,
|
|
"METHOD": "口头测试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "1月典型事故警示教育",
|
|
"TIMERANGE": "2025/1/7 15:30:00-2025/1/7 16:30:00",
|
|
"SHOULD_TRAINER": 10,
|
|
"ACTUAL_TRAINER": 10,
|
|
"METHOD": "口头测试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/7 16:20:00-2025/1/7 17:20:00",
|
|
"SHOULD_TRAINER": 10,
|
|
"ACTUAL_TRAINER": 10,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/8 7:00:00-2025/1/8 8:00:00",
|
|
"SHOULD_TRAINER": 8,
|
|
"ACTUAL_TRAINER": 8,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "关于做好安全生产工作的通知",
|
|
"TIMERANGE": "2025/1/8 7:50:04-2025/1/8 9:50:12",
|
|
"SHOULD_TRAINER": 15,
|
|
"ACTUAL_TRAINER": 15,
|
|
"METHOD": "口头测试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/8 8:00:32-2025/1/8 9:00:56",
|
|
"SHOULD_TRAINER": 8,
|
|
"ACTUAL_TRAINER": 8,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/8 15:40:37-2025/1/8 16:40:59",
|
|
"SHOULD_TRAINER": 13,
|
|
"ACTUAL_TRAINER": 13,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/8 16:01:06-2025/1/8 17:01:07",
|
|
"SHOULD_TRAINER": 9,
|
|
"ACTUAL_TRAINER": 9,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0.5",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/8 16:01:17-2025/1/8 17:01:02",
|
|
"SHOULD_TRAINER": 6,
|
|
"ACTUAL_TRAINER": 6,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "1",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 8:15:00-2025/1/9 9:00:00",
|
|
"SHOULD_TRAINER": 13,
|
|
"ACTUAL_TRAINER": 13,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 8:15:00-2025/1/9 9:00:00",
|
|
"SHOULD_TRAINER": 20,
|
|
"ACTUAL_TRAINER": 20,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0.5",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 14:55:53-2025/1/9 15:55:12",
|
|
"SHOULD_TRAINER": 6,
|
|
"ACTUAL_TRAINER": 6,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 15:00:34-2025/1/9 16:00:20",
|
|
"SHOULD_TRAINER": 6,
|
|
"ACTUAL_TRAINER": 6,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 15:00:47-2025/1/9 16:00:11",
|
|
"SHOULD_TRAINER": 7,
|
|
"ACTUAL_TRAINER": 7,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 15:00:47-2025/1/9 16:00:11",
|
|
"SHOULD_TRAINER": 1,
|
|
"ACTUAL_TRAINER": 1,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 15:00:57-2025/1/9 16:00:17",
|
|
"SHOULD_TRAINER": 14,
|
|
"ACTUAL_TRAINER": 14,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0",
|
|
"EFFORT_RATE": "100"
|
|
},
|
|
{
|
|
"NAME": "福建省进一步加强矿山安全生产工作的若干措施",
|
|
"TIMERANGE": "2025/1/9 15:15:00-2025/1/9 16:00:03",
|
|
"SHOULD_TRAINER": 14,
|
|
"ACTUAL_TRAINER": 14,
|
|
"METHOD": "笔试",
|
|
"PASS_RATE": "0",
|
|
"EFFORT_RATE": "100"
|
|
}
|
|
],
|
|
"dateCountModel": [
|
|
{
|
|
"DATE": "2025-01-01 00:00:00",
|
|
"COUNT": 20,
|
|
"TYPE": 0
|
|
}
|
|
]
|
|
},
|
|
"TotalCount": 0,
|
|
"MessageType": 0
|
|
}
|
|
this.setState({
|
|
showLoading: false,
|
|
NUM1: ret.Data.NUM1,
|
|
NUM2: ret.Data.NUM2,
|
|
NUM3: ret.Data.NUM3,
|
|
NUM4: ret.Data.NUM4,
|
|
NUM5: ret.Data.NUM5,
|
|
NUM6: ret.Data.NUM6,
|
|
NUM7: ret.Data.NUM7,
|
|
retData: ret.Data.trainRecords,
|
|
},()=>{
|
|
this.chart1(ret.Data.dateCountModel);
|
|
})
|
|
|
|
// }
|
|
// },
|
|
// });
|
|
};
|
|
chart1 = (ret) => {
|
|
this.state.recordNums = [];
|
|
this.state.dates = [];
|
|
let color = [
|
|
"#0090FF",
|
|
"#36CE9E",
|
|
"#FFC005",
|
|
"#FF515A",
|
|
"#8B5CFF",
|
|
"#00CA69",
|
|
];
|
|
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;
|
|
};
|
|
for (let i = 0; i < ret.length; i++) {
|
|
this.state.recordNums.push(ret[i].COUNT);
|
|
this.state.dates.push(moment(ret[i].DATE).format("YYYY-MM"));
|
|
}
|
|
let chart1s = document.getElementById("chart1");
|
|
if (chart1s) {
|
|
let myChart = echarts.init(chart1s);
|
|
myChart.on("click", (params) => {
|
|
this.loadData(params.name);
|
|
});
|
|
myChart.setOption({
|
|
color: color,
|
|
grid: {
|
|
left: "5%",
|
|
right: "5%",
|
|
},
|
|
legend: {
|
|
bottom: "0px",
|
|
},
|
|
title: {
|
|
text: "月度培训完成走势图",
|
|
left: "center",
|
|
top: "2%",
|
|
},
|
|
tooltip: {
|
|
trigger: "axis",
|
|
axisPointer: {
|
|
type: "shadow",
|
|
},
|
|
},
|
|
xAxis: {
|
|
type: "category",
|
|
data: this.state.dates,
|
|
boundaryGap: false,
|
|
axisLabel: {
|
|
textStyle: {
|
|
color: "#333",
|
|
},
|
|
},
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: "#D9D9D9",
|
|
},
|
|
},
|
|
},
|
|
yAxis: {
|
|
type: "value",
|
|
axisLabel: {
|
|
textStyle: {
|
|
color: "#666",
|
|
},
|
|
},
|
|
nameTextStyle: {
|
|
color: "#666",
|
|
fontSize: 12,
|
|
lineHeight: 40,
|
|
},
|
|
splitLine: {
|
|
lineStyle: {
|
|
type: "dashed",
|
|
color: "#E9E9E9",
|
|
},
|
|
},
|
|
axisLine: {
|
|
show: false,
|
|
},
|
|
axisTick: {
|
|
show: false,
|
|
},
|
|
},
|
|
series: [
|
|
{
|
|
name: "培训记录数",
|
|
data: this.state.recordNums,
|
|
type: "line",
|
|
smooth: true,
|
|
symbolSize: 8,
|
|
zlevel: 3,
|
|
lineStyle: {
|
|
normal: {
|
|
color: color[0],
|
|
shadowBlur: 3,
|
|
shadowColor: hexToRgba(color[0], 0.5),
|
|
shadowOffsetY: 8,
|
|
},
|
|
},
|
|
areaStyle: {
|
|
normal: {
|
|
color: new echarts.graphic.LinearGradient(
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
[
|
|
{
|
|
offset: 0,
|
|
color: hexToRgba(color[0], 0.3),
|
|
},
|
|
{
|
|
offset: 1,
|
|
color: hexToRgba(color[0], 0.1),
|
|
},
|
|
],
|
|
false
|
|
),
|
|
shadowColor: hexToRgba(color[0], 0.1),
|
|
shadowBlur: 10,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
});
|
|
}
|
|
};
|
|
onChange = (type, value) => {
|
|
this.setState({
|
|
[type]: value,
|
|
});
|
|
};
|
|
paginationConfig = {
|
|
// pageSizeOptions: ["10", "20", "50"],
|
|
pageSize: 20,
|
|
// showSizeChanger: true,
|
|
size: "small",
|
|
};
|
|
render() {
|
|
return (
|
|
<div
|
|
style={{
|
|
backgroundColor: "white",
|
|
width: "1200px",
|
|
top: "0",
|
|
bottom: "0",
|
|
left: "0",
|
|
right: "0",
|
|
margin: "auto",
|
|
borderStyle: "solid",
|
|
borderColor: "#ccc",
|
|
borderWidth: "1px",
|
|
}}
|
|
>
|
|
<h1
|
|
style={{ textAlign: "center", marginTop: "30px", fontWeight: "bold" }}
|
|
>
|
|
安全教育与培训统计分析
|
|
</h1>
|
|
<Row gutter={10} style={{ marginTop: "14px" }}>
|
|
<Col span={1}> </Col>
|
|
<Col span={22}>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
justifyContent: "space-around",
|
|
border: "1px #888 solid",
|
|
padding: "8px 0px",
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
width: "120px",
|
|
height: "70px",
|
|
borderRadius: "8px",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignItems: "center",
|
|
justifyContent: "space-around",
|
|
// marginBottom: "10px",
|
|
}}
|
|
>
|
|
<span>安全培训教育</span>
|
|
{/* <br></br> */}
|
|
<div>
|
|
<span
|
|
style={{
|
|
fontWeight: "bold",
|
|
fontSize: "20px",
|
|
color: "brown",
|
|
}}
|
|
>
|
|
{this.state.NUM2}
|
|
</span>
|
|
次
|
|
</div>
|
|
</div>
|
|
<div
|
|
style={{
|
|
width: "120px",
|
|
height: "70px",
|
|
borderRadius: "8px",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignItems: "center",
|
|
justifyContent: "space-around",
|
|
// marginBottom: "10px",
|
|
}}
|
|
>
|
|
<span>三级安全教育</span>
|
|
{/* <br></br> */}
|
|
<div>
|
|
<span
|
|
style={{
|
|
fontWeight: "bold",
|
|
fontSize: "20px",
|
|
color: "brown",
|
|
}}
|
|
>
|
|
{this.state.NUM3}
|
|
</span>
|
|
次
|
|
</div>
|
|
</div>
|
|
<div
|
|
style={{
|
|
width: "120px",
|
|
height: "70px",
|
|
borderRadius: "8px",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignItems: "center",
|
|
justifyContent: "space-around",
|
|
// marginBottom: "10px",
|
|
}}
|
|
>
|
|
<span>题库总条数</span>
|
|
{/* <br></br> */}
|
|
<div>
|
|
<span
|
|
style={{
|
|
fontWeight: "bold",
|
|
fontSize: "20px",
|
|
color: "brown",
|
|
}}
|
|
>
|
|
{this.state.NUM7}
|
|
</span>
|
|
条
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Col>
|
|
<Col span={1}></Col>
|
|
</Row>
|
|
<Row gutter={10} style={{ marginTop: "14px" }}>
|
|
<Col span={1}> </Col>
|
|
<Col span={22}>
|
|
<div
|
|
className="dashboard-div-style"
|
|
style={{
|
|
// borderRadius: "10px",
|
|
backgroundColor: "white",
|
|
border: "1px solid rgb(232,232,232)"
|
|
// boxShadow: "0px 0px 10px rgba(0,0,0,.15)",
|
|
}}
|
|
>
|
|
<div id="chart1" style={{ width: "100%", height: "350px" }}></div>
|
|
</div>
|
|
</Col>
|
|
<Col span={1}></Col>
|
|
</Row>
|
|
{/* <hr
|
|
style={{
|
|
border: "1px dashed #ccc",
|
|
marginBottom: "20px",
|
|
marginTop: "20px",
|
|
}}
|
|
></hr> */}
|
|
<Row gutter={10} style={{ marginTop: "14px" }}>
|
|
<Col span={1}></Col>
|
|
<Col span={22} style={{ height: "100%" }}>
|
|
<div
|
|
// className="dashboard-div-style"
|
|
// style={{ boxShadow: "0px 0px 10px rgba(0,0,0,.15)" }}
|
|
>
|
|
<Table
|
|
dataSource={this.state.retData}
|
|
columns={this.state.columns1}
|
|
pagination={this.paginationConfig}
|
|
bordered
|
|
loading={this.state.showLoading}
|
|
size="small"
|
|
rowKey="1"
|
|
/>
|
|
</div>
|
|
</Col>
|
|
<Col span={1}></Col>
|
|
</Row>
|
|
<br />
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
export default connect(({ login, app }) => ({ login, app }))(TrainSafeAnalysis);
|