mh_jy_safe_web/src/components/CustomPages/BI/BI064FormRunAnalysis.js
何美荣 d41c91fc8e 1
2026-05-19 17:19:09 +08:00

715 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import { connect } from 'dva';
import moment from 'moment'
import { initFilter } from '../../../utils/common';
import { Table, Row, Spin, Card, Modal, DatePicker,Col, Button, Form ,Select} from 'antd';
import DropDownPagination from '../../common/DropDownPaginationEx';
const { Option } = Select;
class BI064FormRunAnalysis extends React.Component {
constructor(props) {
super(props);
this.state = {
depart: {},
inputText: '',
inputText2: '',
inputText3: '',
startTime:moment(this.getDate(), 'YYYY-MM-DD 00:00:00'),//moment(new Date()).add(-1, "month").format('YYYY-MM-DD 00:00:00'),
endTime:moment(this.getEndDate(), 'YYYY-MM-DD 23:59:59'),
selectForms:['安全风险辨识与评估计划','安全风险辨识表', '安全风险辨识结果表', '安全风险辨识结果汇总表', '安全风险评估表',
'安全风险评估汇总表', '风险检查关联表','安全检查通知','安全检查记录','安全检查记录汇总','隐患上报','手动隐患上报完善',
'隐患确认单','隐患整改通知单', '隐患整改记录', '延期整改申请'],
retData: [], // 表单运行数据
companyData: [], // 公司数据
loading: true,
tableData: [], // 处理后的表格数据
columns: [], // 动态生成的列
scoreVisible: false,
scoreTitle: '',
standardScoreTemp: [],
scoreColumns: [
// {
// title: '序号',
// render: (text, record, index) => `${index + 1}`
// },
{
title: '待办名称',
dataIndex: 'NOTICE_TITLE',
},
{
title: '姓名',
dataIndex: 'USER_NAME',
},
{
title: '开始时间',
dataIndex: 'TASK_STARTDT',
},
{
title: '结束时间',
dataIndex: 'TASK_ENDDT',
},
{
title: '实际处理时间',
dataIndex: 'TASK_DT',
},
{
title: '处理状态',
dataIndex: 'NOTICE_STATUS',
render: (text, record) => {
const currentTime = new Date();
const endTime = new Date(record.TASK_ENDDT);
if (text == 1) {
return '正常完成';
} else if (text == 2) {
return '超时完成';
} else if (text == 0 && endTime >= currentTime) {
return '进行中';
} else if (text == 0 && endTime < currentTime) {
return '超期未完成';
} else {
return '未知状态';
}
},
},
],
};
}
getDate=()=>{
let date = new Date()
let y = date.getFullYear()
let m = date.getMonth() + 1
let d = date.getDate();
// 当前日期
let nowDate = y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d);
// 一月的时候年份要减一
// if(m == 1) {
// y--
// m = 12
// }else if(m == 3 && d > 28) {
// //三月要考虑是否为闰年
// m--
// if(y%4 == 0 && y%100!=0 || y%400 == 0) {
// d = 29
// }else {
// d-28
// }
// }else if((m != 12 || m != 8 )&& d == 31) {
// //31号的月份要考虑上个月是否有31号
// m--
// d = 30
// }else {
// m--
// }
// 一个月前的日期(默认月份)
//let pastDate = y + (m < 10 ? "0" + m : m) + (d < 10 ? "0" + d : d)
let pastDate = moment(nowDate).add(-1, "day").format('YYYY-MM-DD 00:00:00')
return pastDate;
}
getEndDate=()=>{
let date = new Date()
let y = date.getFullYear()
let m = date.getMonth() + 1
let d = date.getDate();
// 当前日期
let nowDate = y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d);
let pastDate = moment(nowDate).add(-1, "day").add(23,'hour').add(59,'m').add(59,'s')//format('YYYY-MM-DD 23:59:59')
return pastDate;
}
componentDidMount() {
this.loadData();
}
// 加载数据
loadData = () => {
this.getBaseData();
};
handleSearch = ({ data, record }) => {
this.setState({
depart: {
...this.state.depart,
ID: data[0],
NAME: record?.NAME,
},
inputText: record ? record?.NAME : this.state.inputText,
});
};
handleSearch2 = (value) => {
let temps = ['安全风险辨识与评估计划','安全风险辨识表', '安全风险辨识结果表', '安全风险辨识结果汇总表', '安全风险评估表',
'安全风险评估汇总表', '风险检查关联表','安全检查通知','安全检查记录','安全检查记录汇总','隐患上报','手动隐患上报完善',
'隐患确认单','隐患整改通知单', '隐患整改记录', '延期整改申请'];
if(value === "双重预防机制" )
{
temps = ['安全风险辨识与评估计划','安全风险辨识表', '安全风险辨识结果表', '安全风险辨识结果汇总表', '安全风险评估表',
'安全风险评估汇总表', '风险检查关联表','安全检查通知','安全检查记录','安全检查记录汇总','隐患上报','手动隐患上报完善',
'隐患确认单','隐患整改通知单', '隐患整改记录', '延期整改申请'];
}
if(value === "作业现场安全管理" )
{
temps = [ '班前会议', '岗位当班记录', '交接班记录', '班组活动记录','一般作业活动记录', '作业方案讨论记录','关键许可工作票',
'安全技术交底表','关键许可作业活动记录','矿山动火作业工作票','技术交底表','安全交底表','领导带班下井记录'];
}
if(value === "安全教育与培训" )
{
temps = ['安全意识调查', '培训需求调查','培训通知', '培训通知(转训)','培训记录', '培训效果评估调查表', '三级安全教育培训记录',
'新三级安全教育记录', '新三级安全教育卡' ];
}
this.setState({
inputText2: value,
selectForms:temps
})
}
handleSearch3 = (value) => {
this.setState({
inputText3: value
})
}
startChange=(value)=>{
this.setState({
startTime:value
})
};
endChange=(value)=>{
this.setState({
endTime:value
})
};
// 获取公司数据
getBaseData = () => {
const json = initFilter(this.props.login.OrgId);
// let json = initFilter("00300000-0000-0000-0000-000000000000");
this.props.dispatch({
type: 'app/getDataByPost',
url: 'FM/Organization/OrderEntities',
payload: json,
onlyData: false,
onComplete: (ret) => {
if (ret && ret.Data) {
let keyword = ret.Data[0]?.NAME;
if (this.props.login.OrgId === '00300000-0000-0000-0000-000000000000') {
keyword = ret.Data.filter((t) => t.ID == this.props.login.OrgId)[0]?.NAME;
}
this.setState({ companyData: ret.Data, inputText: keyword }, () => {
this.getrealData();
// this.processData();
});
}
},
});
};
// 获取表单运行数据
getrealData = () => {
// const json = initFilter(this.props.login.OrgId);
let json = initFilter('00300000-0000-0000-0000-000000000000', this.state.inputText,"","","",this.state.startTime,this.state.endTime);
this.props.dispatch({
type: 'app/getDataByPost',
url: 'BI/BIStatiscialAnalysisController/GetTaskViewInfo',
payload: json,
onlyData: false,
onComplete: (ret) => {
if (ret && ret.Data) {
if(this.state.inputText2)
{
ret.Data= ret.Data.filter((t) => t.MOULD_NAME === this.state.inputText2);
}
if(this.state.inputText3)
{
ret.Data= ret.Data.filter((t) => t.FORM_NAME === this.state.inputText3);
}
this.setState({ retData: ret.Data, loading: false }, () => {
this.processData();
});
} else {
this.setState({ loading: false });
}
},
});
};
// 处理数据,生成表格所需格式
processData = () => {
const { retData, companyData, inputText } = this.state;
if (!retData.length || !companyData.length) return;
let companyDataTemp = companyData.filter((t) => t.NAME === inputText);
// 获取所有模块和表单的列表
const modules = [...new Set(retData.map((item) => item.MOULD_NAME))];
const forms = [];
// 按模块组织表单
modules.forEach((module) => {
const moduleForms = [
...new Set(retData.filter((item) => item.MOULD_NAME === module).map((item) => item.FORM_NAME)),
];
moduleForms.forEach((form) => {
forms.push({
module,
form,
key: `${module}_${form}`,
});
});
});
// 处理每个公司的数据
const tableData = forms.map((formItem) => {
const { module, form, key } = formItem;
const rowData = {
key,
module,
form,
};
// 为每个公司添加数据
companyDataTemp.forEach((company) => {
const companyName = company.NAME;
const companyDataKey = companyName.replace(/\s+/g, '');
// 查找该公司该表单的数据
const formData = retData.find(
(item) => item.MOULD_NAME === module && item.FORM_NAME === form && item.COMPANY_NAME === companyName
);
if (formData) {
// 计算完成率和及时率
// const finishRate =
// formData.TOTAL_QTY > 0
// ? (((formData.NORMAL_FINISH + formData.OVER_FINISH + formData.DOING) / formData.TOTAL_QTY) * 100).toFixed(
// 0
// )
// : '0';
// const normalRate =
// formData.NORMAL_FINISH + formData.OVER_FINISH + formData.DOING > 0
// ? (
// (formData.NORMAL_FINISH / (formData.NORMAL_FINISH + formData.OVER_FINISH + formData.DOING)) *
// 100
// ).toFixed(0)
// : '0';
rowData[`${companyDataKey}_details`] = formData.details || []; // 假设返回数据中有details字段
rowData[`${companyDataKey}_total`] = formData.TOTAL_QTY;
rowData[`${companyDataKey}_normal`] = formData.NORMAL_FINISH;
rowData[`${companyDataKey}_overtime`] = formData.OVER_FINISH;
rowData[`${companyDataKey}_doing`] = formData.DOING;
rowData[`${companyDataKey}_unfinish`] = formData.UNFINISH;
rowData[`${companyDataKey}_overUnfinish`] = formData.OVER_UNFINISH;
rowData[`${companyDataKey}_finishRate`] = formData.FINISH_RATE;
rowData[`${companyDataKey}_normalRate`] = formData.NORMAL_RATE;
} else {
// 如果没有数据,设置默认值
// 如果没有数据,设置默认值
rowData[`${companyDataKey}_details`] = [];
rowData[`${companyDataKey}_total`] = 0;
rowData[`${companyDataKey}_normal`] = 0;
rowData[`${companyDataKey}_overtime`] = 0;
rowData[`${companyDataKey}_doing`] = 0;
rowData[`${companyDataKey}_unfinish`] = 0;
rowData[`${companyDataKey}_overUnfinish`] = 0;
rowData[`${companyDataKey}_finishRate`] = '0';
rowData[`${companyDataKey}_normalRate`] = '0';
}
});
return rowData;
});
// 计算每个模块的行数,用于合并单元格
const moduleRowCounts = {};
let currentModule = null;
let count = 0;
tableData.forEach((row, index) => {
if (row.module !== currentModule) {
if (currentModule !== null) {
moduleRowCounts[currentModule] = count;
}
currentModule = row.module;
count = 1;
} else {
count++;
}
// 最后一个模块
if (index === tableData.length - 1) {
moduleRowCounts[currentModule] = count;
}
});
// 将行数信息添加到tableData中供render使用
const tableDataWithRowSpan = tableData.map((row, index) => {
// 找到该模块的起始索引
const moduleStartIndex = tableData.findIndex((item) => item.module === row.module);
// 如果是该模块的第一行设置rowSpan为该模块的行数
if (index === moduleStartIndex) {
return {
...row,
moduleRowSpan: moduleRowCounts[row.module] || 1,
};
} else {
// 不是第一行设置rowSpan为0表示不显示
return {
...row,
moduleRowSpan: 0,
};
}
});
// 生成表格列
const columns = this.generateColumns(companyDataTemp, tableDataWithRowSpan);
this.setState({ tableData: tableDataWithRowSpan, columns });
};
// 动态生成表格列
generateColumns = (companyData) => {
const baseColumns = [
{
// width: '150px',
title: '模块',
dataIndex: 'module',
key: 'module',
// fixed: 'left',
align: 'center',
onCell: (record) => ({
style: {
minWidth: '150px', // 设置最小宽度
whiteSpace: 'nowrap', // 防止换行
},
}),
render: (value, row, index) => {
const obj = {
children: value,
props: {},
};
// 设置rowSpan属性
if (row.moduleRowSpan !== undefined) {
obj.props.rowSpan = row.moduleRowSpan;
}
return obj;
},
},
{
// width: '200px',
title: '表单',
dataIndex: 'form',
key: 'form',
// fixed: 'left',
align: 'center',
onCell: () => ({
style: {
minWidth: '200px',
whiteSpace: 'nowrap',
},
}),
},
];
// 为每个公司生成列组
companyData.forEach((company) => {
const companyName = company.NAME;
const companyDataKey = companyName.replace(/\s+/g, '');
const companyColumns = {
title: `${companyName}运行数据`,
children: [
{
title: '总任务数',
dataIndex: `${companyDataKey}_total`,
key: `${companyDataKey}_total`,
width: '150px',
align: 'center',
render: (text, record) => (
<span>
<a onClick={() => this.showDetail(record, 1, companyName)}>{record[`${companyDataKey}_total`]}</a>
</span>
),
},
{
title: '正常完成',
dataIndex: `${companyDataKey}_normal`,
key: `${companyDataKey}_normal`,
width: '150px',
align: 'center',
render: (text, record) => (
<span>
<a onClick={() => this.showDetail(record, 2, companyName)}>{record[`${companyDataKey}_normal`]}</a>
</span>
),
},
{
title: '超时完成',
dataIndex: `${companyDataKey}_overtime`,
key: `${companyDataKey}_overtime`,
width: '150px',
align: 'center',
render: (text, record) => (
<span>
<a onClick={() => this.showDetail(record, 3, companyName)}>{record[`${companyDataKey}_overtime`]}</a>
</span>
),
},
{
title: '进行中',
dataIndex: `${companyDataKey}_doing`,
key: `${companyDataKey}_doing`,
width: '150px',
align: 'center',
render: (text, record) => (
<span>
<a onClick={() => this.showDetail(record, 4, companyName)}>{record[`${companyDataKey}_doing`]}</a>
</span>
),
},
{
title: '超期未完成',
dataIndex: `${companyDataKey}_overUnfinish`,
key: `${companyDataKey}_overUnfinish`,
width: '150px',
align: 'center',
render: (text, record) => (
<span>
<a onClick={() => this.showDetail(record, 5, companyName)}>
{record[`${companyDataKey}_overUnfinish`]}
</a>
</span>
),
},
{
title: '完成率',
dataIndex: `${companyDataKey}_finishRate`,
key: `${companyDataKey}_finishRate`,
width: '150px',
align: 'center',
render: (text) => <span>{text}%</span>,
},
{
title: '及时率',
dataIndex: `${companyDataKey}_normalRate`,
key: `${companyDataKey}_normalRate`,
align: 'center',
width: '150px',
render: (text) => <span>{text}%</span>,
},
],
};
baseColumns.push(companyColumns);
});
console.log('生成的列:', baseColumns);
return baseColumns;
};
showDetail = (record, type, companyName) => {
const currentTime = new Date();
const companyDataKey = companyName.replace(/\s+/g, '');
// 从record中获取该公司的明细数据
const details = record[`${companyDataKey}_details`] || [];
let filteredDetails = [];
switch (type) {
case 1: // 总任务数
filteredDetails = details;
break;
case 2: // 正常完成
filteredDetails = details.filter((item) => item.NOTICE_STATUS == 1);
break;
case 3: // 超时完成
filteredDetails = details.filter((item) => item.NOTICE_STATUS == 2);
break;
case 4: // 进行中
filteredDetails = details.filter((item) => item.NOTICE_STATUS == 0 && new Date(item.TASK_ENDDT) >= currentTime);
break;
case 5: // 超期未完成
filteredDetails = details.filter((item) => item.NOTICE_STATUS == 0 && new Date(item.TASK_ENDDT) < currentTime);
break;
default:
filteredDetails = details;
}
const typeTitles = {
1: '总任务数',
2: '正常完成',
3: '超时完成',
4: '进行中',
5: '超期未完成',
};
this.setState({
standardScoreTemp: filteredDetails,
scoreVisible: true,
scoreTitle: `${companyName} - ${record.module} - ${record.form}${typeTitles[type]}明细`,
});
};
clearScoreData = () => {
this.setState({
scoreVisible: false,
// standardScore: [],//newtmpData
});
};
render() {
const { tableData, columns, loading,selectForms } = this.state;
const formItemLayout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
return (
<div>
<div
style={{
backgroundColor: 'white',
width: '100%',
minHeight: '100vh',
margin: 'auto',
borderStyle: 'solid',
borderColor: '#ccc',
borderWidth: '1px',
padding: '20px',
}}
>
<Modal
visible={this.state.scoreVisible}
title={this.state.scoreTitle}
maskClosable={false}
onCancel={this.clearScoreData}
footer={null}
className="antd-modal-fullscreen"
closeModal={this.clearScoreData}
>
<Table
dataSource={this.state.standardScoreTemp}
columns={this.state.scoreColumns}
pagination={false}
bordered
size="small"
/>
</Modal>
<h1
style={{
textAlign: 'center',
marginTop: '20px',
marginBottom: '30px',
fontWeight: 'bold',
fontSize: '24px',
}}
>
系统运行情况统计分析
</h1>
<Row style={{ width: '100%', margin: 'auto' }}>
<Col span={5}>
<Form.Item label={'公司名称'} {...formItemLayout}>
<DropDownPagination
inputDataApi={'FM/Organization/OrderPaged'}
fieldName={'NAME'}
data={this.state.depart}
onSelect={this.handleSearch}
onFilter={({ params }) => {
params.OrderType = 1;
params.OrgId = this.props.login.OrgId;
}}
/>
</Form.Item>
</Col>
<Col span={5}>
<Form.Item
label={'模块'}
{...formItemLayout}
>
<Select
style={{ width: '180px' }}
allowClear
onChange={this.handleSearch2}
>
<Option value="双重预防机制">双重预防机制</Option>
<Option value="作业现场安全管理">作业现场安全管理</Option>
<Option value="安全教育与培训">安全教育与培训</Option>
</Select>
</Form.Item>
</Col>
<Col span={5}>
<Form.Item
label={'表单'}
{...formItemLayout}
>
<Select
style={{ width: '180px' }}
allowClear
onChange={this.handleSearch3}
>
{
selectForms && selectForms.map(item => (
<Option key={item}>{item}</Option>
))
}
</Select>
</Form.Item>
</Col>
<Col span={5} style={{ marginLeft: "10px" }}>
<Form.Item
label={'开始时间:'}
{...formItemLayout}
>
<DatePicker showTime
// defaultValue={moment(this.state.startTime, 'YYYY-MM-DD 00:00:00')}
value={this.state.startTime}
format="YYYY-MM-DD HH:mm:ss" onChange={this.startChange}/>
</Form.Item>
</Col>
<Col span={5} style={{ marginLeft: "10px" }}>
<Form.Item
label={'结束时间:'}
{...formItemLayout}
>
<DatePicker showTime
// defaultValue={moment(this.state.endTime, 'YYYY-MM-DD 23:59:59')}
value={this.state.endTime}
format="YYYY-MM-DD HH:mm:ss" onChange={this.endChange}/>
</Form.Item>
</Col>
<Col span={2} style={{ marginLeft: '20px' }}>
<Button type="primary" onClick={() => this.getrealData()}>
查询
</Button>
</Col>
</Row>
<Row>
<Spin spinning={loading}>
{/* <Card> */}
<Table
style={{
width: '100%',
textAlign: 'center',
}}
scroll={{ x: 1500, y: 600 }}
dataSource={tableData}
columns={columns}
pagination={false}
loading={loading}
size="middle"
bordered
rowKey="key"
/>
{/* </Card> */}
</Spin>
</Row>
</div>
</div>
);
}
}
export default connect(({ login, app }) => ({ login, app }))(BI064FormRunAnalysis);