mh_jy_safe_web/src/components/CustomPages/SE/SESafeSurveyTest.js
2025-08-25 10:08:30 +08:00

504 lines
27 KiB
JavaScript

import { message } from "antd/lib/index";
import { Button, Popconfirm, Row, Col, Checkbox, Radio, Form, Input, Select, Table, Upload, Icon, PageHeader, Modal, Spin } from 'antd';
import React from 'react';
import { initFilter, extendRule, extendInclude, setDataFieldValue, guid, initQueryFilter } from "../../../utils/common";
import ReactToPrint from "react-to-print";
import styles from '../../CustomPages/HI/StepForm.css';
import SEstyles from './SE.css';
import XLSX from 'xlsx';
import { connect } from 'dva';
import moment from 'moment';
const Option = Select.Option;
const answer = {
color: 'blue',
}
class SESafeSurveyTest extends React.Component {
constructor(props) {
super(props);
let viewAll = false;
if ((this.props.formParam && this.props.formParam.viewAll) || (this.props.login.user.APPROVE_ROLE_ID != null && this.props.data.tableKey == undefined)) {
viewAll = true;
}
this.state = {
papers: [],
viewAll,
safe: null,
UserList: [],
SelUsrID: null,
config: null,
score: 0,
NAME: '',
END_TIME: null,
readonly: true,
haveAnswer: false,
loading: false,
};
};
componentDidMount() {
if (window.navigator.userAgent.indexOf("Windows") < 1) {
this.setState({ isMobile: true })
}
if (this.props.data?.id)
this.loadData(this.props.data?.id);
}
componentWillReceiveProps(NextProps) {
if (NextProps.data?.id && this.props.data?.id != NextProps.data?.id) {
this.loadData(NextProps.data?.id);
}
}
BtnClose = () => {
if (typeof this.props.data.onCancel != "undefined" && typeof this.props.data.onCancel == 'function')
this.props.data.onCancel();
}
getUsers = () => {
let json = initFilter(this.props.login.OrgId);
json.OrgType = 2;
extendRule(json, 'SAFE_ID', 1, this.props.data.id);
extendInclude(json, 'Nav_User');
this.state.loading = true;
this.props.dispatch({
type: 'app/getDataByPost',
payload: json,
url: 'SE/SESafeSurvey/GetUsers',
onComplete: (ret) => {
this.state.loading = false;
if (ret && ret.length > 0) {
this.setState({
UserList: ret
})
if (this.state.viewAll) {
this.setState({
SelUsrID: ret[0].ID
}, () => {
this.getPapers();
});
} else {
let usr = ret.find(it => it.ID === this.props.login.user.ID);
if (usr) {
this.setState({
SelUsrID: usr.ID
}, () => {
this.getPapers();
});
} else {
message.warn("当前用户没有问卷");
}
}
}
}
});
}
getPapers() {
let SelUsrID = this.state.SelUsrID;
this.setState({ papers: [] });
if (!SelUsrID) {
return;
}
let json = initFilter(this.props.login.OrgId, '', 'Nav_Test.TYPE', 1);
json.OrgType = 2;
extendRule(json, 'SAFE_ID', 1, this.props.data.id);
extendRule(json, 'USER_ID', 1, SelUsrID);
extendInclude(json, 'Nav_Test');
//extendInclude(json, 'Nav_Test.Nav_File');
extendInclude(json, 'Nav_Safe');
extendInclude(json, 'Nav_Safe.Nav_LaunchDepartment');
extendInclude(json, 'Nav_Safe.Nav_LaunchUser');
extendInclude(json, 'Nav_Safe.Nav_Points');
extendInclude(json, 'Nav_Safe.Nav_Points.Nav_Point');
extendInclude(json, 'Nav_Safe.Nav_JoinDepartment');
extendInclude(json, 'Nav_Safe.Nav_JoinDepartment.Nav_Department');
extendInclude(json, 'Nav_User');
extendInclude(json, 'Nav_Department');
this.state.loading = true;
this.props.dispatch({
type: 'app/getDataByPost',
payload: json,
url: 'SE/SESafeSurvey/GetPapers',
onComplete: (ret) => {
this.state.loading = false;
if (ret && ret.Nav_Papers && ret.Nav_Papers.length > 0) {
let NAME = '';
let END_TIME = null;
if (ret.Nav_Papers.length > 0) {
NAME = ret.Nav_Papers[0].Nav_Safe.NAME;
END_TIME = ret.Nav_Papers[0].Nav_Safe.END_TIME;
}
if (moment().format("YYYY-MM-DD HH:mm:ss") > END_TIME&&this.props.data.tableKey != undefined) {
message.error('已过答题截止时间!');
this.props.dispatch({
type: 'app/getDataByPost',
url: 'HM/HMNoticeRelease/PersonalAgree',
payload: {
ID: this.props.data.id,
TaskID: this.props.data.TaskID,
},
})
} else {
let haveAnswer = ret.Nav_Papers.find(it => it.ANSWER != 0) ? true : false;
this.setState({
papers: ret.Nav_Papers.sort((a, b) => { return a.Nav_Test.TYPE - b.Nav_Test.TYPE }),
config: ret.Nav_Config,
safe: ret.Nav_Papers[0].Nav_Safe,
readonly: haveAnswer || this.state.viewAll,
haveAnswer: haveAnswer,
NAME: NAME,
END_TIME: END_TIME,
})
}
} else {
message.warn('未能成功获取此用户的问卷,请稍后重试');
}
}
});
}
loadData = () => {
if (this.props.data.id == "")
return;
this.getUsers();
}
onSave = () => {
if (this.state.readonly) {
return;
}
let data = JSON.parse(JSON.stringify(this.state.papers));
for (let i = 0; i < data.length; i++) {
if (data[i].ANSWER == 0) {
message.error(`${i + 1}题尚未选择答题,请完成所有答题后再进行提交`);
return;
}
if (data[i].Nav_Test.TYPE === 2 && ([0, 1, 2, 4, 8].indexOf(data[i].ANSWER) !== -1)) {
message.error(`${i + 1}题为多选题,请选择至少两个选项`);
return;
}
}
let saveData = () => {
let data = {
Nav_Config: JSON.parse(JSON.stringify(this.state.config)),
Nav_Papers: JSON.parse(JSON.stringify(this.state.papers)),
TaskID: this.props.data.TaskID,
}
this.props.dispatch({
type: 'app/getDataByPost',
payload: data,
url: 'SE/SESafeSurvey/SavePapers',
onComplete: (ret) => {
if (ret) {
message.success('提交成功');
this.BtnClose();
}
}
});
}
Modal.confirm({
title: '提示',
content: '确定要提交当前问卷么?提交之后不可再次更改',
onOk: () => {
saveData();
},
onCancel() {
},
})
}
fmtEnum(name, value) {
const enums = this.props.app.enums;
if (!enums || !enums[name]) return '';
return enums[name].enums[value] || '';
}
onTableBtnExport() {
let TableWrap = document.getElementById('tableId' + this.props.data.id);
let Table = TableWrap.getElementsByTagName('table')[0];
const wb = XLSX.utils.table_to_book(Table);
let name = '安全意识调查问卷';
if (this.state.papers && this.state.papers.length > 0) {
let user = this.state.papers[0].Nav_User;
name += `-${user.CODE}-${user.NAME}`;
}
name += '.xlsx';
XLSX.writeFile(wb, name)
}
getJoinDepartment() {
let arr = [];
if (this.state.safe && this.state.safe.Nav_JoinDepartment) {
for (let it of this.state.safe.Nav_JoinDepartment) {
if (it.Nav_Department) {
if (it.Nav_Department.NAME == "宁化行洛坑钨矿有限公司") {
arr.push("公司领导")
} else {
arr.push(it.Nav_Department.NAME)
}
}
}
}
return arr;
}
doOptionChange = (it, index, mask, evt) => {
let papers = this.state.papers;
if (evt.target.checked) {
if (it.Nav_Test.TYPE === 2) {
papers[index].ANSWER |= mask;
} else {
papers[index].ANSWER = mask;
}
} else {
papers[index].ANSWER = papers[index].ANSWER & (~mask);
}
this.setState({
papers,
})
}
CalcScore = () => {
if (!this.state.readonly) {
return "";
}
let score = 0;
let sscore = 1;
let mscore = 1;
let cscore = 1;
if (this.state.config) {
if (this.state.config.S_TEST_SCORE > 0) {
sscore = this.state.config.S_TEST_SCORE;
}
if (this.state.config.M_TEST_SCORE > 0) {
mscore = this.state.config.M_TEST_SCORE;
}
if (this.state.config.C_TEST_SCORE > 0) {
cscore = this.state.config.C_TEST_SCORE;
}
}
this.state.papers.map((it, idx) => {
if (it.ANSWER !== 0 && it.ANSWER == it.Nav_Test.ANSWER) {
switch (it.Nav_Test.TYPE) {
case 0: {
score += cscore;
break;
}
case 1: {
score += sscore;
break;
}
case 2: {
score += mscore;
break;
}
}
}
})
return score;
}
getType(type) {
let ret = '';
const { config } = this.state
switch (type) {
case 0: ret = `【是非题】(${config && config.C_TEST_SCORE || 1}分)`; break;
case 1: ret = `【单选题】(${config && config.S_TEST_SCORE || 1}分)`; break;
case 2: ret = `【多选题】(${config && config.M_TEST_SCORE || 1}分)`; break;
}
return ret;
}
render() {
const { safe, papers, SelUsrID, UserList } = this.state;
const SelUsr = SelUsrID && UserList.find(it => it.ID === SelUsrID);
return <div>
<div style={{ padding: '10px' }}>
<ReactToPrint
trigger={() => <Button type={'primary'} icon={'printer'} >打印</Button>}
content={() => this.componentRef}
/>
<Button style={{ marginLeft: '8px' }} onClick={() => this.onTableBtnExport()} icon="export" >导出</Button>
{
this.state.viewAll &&
<Select style={{ fontSize: 14, width: "100px", marginLeft: '8px' }}
showSearch
value={this.state.SelUsrID}
onChange={val => {
this.setState({
SelUsrID: val
}, () => {
this.getPapers();
})
}}
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{
this.state.UserList.map(usr =>
<Option key={usr.ID} value={usr.ID}>{usr.NAME}</Option>
)
}
</Select>
}
{
!this.state.readonly && (
<Button type="primary" style={{ marginLeft: '8px' }} onClick={() => { this.onSave(); }}>
提交问卷
</Button>
)
}
<span />
</div>
<div ref={el => (this.componentRef = el)} id={'tableId' + this.props.data.id} style={{ padding: '20px' }}>
<h1 style={{ textAlign: 'center' }}>安全意识调查问卷</h1>
<Spin spinning={this.state.loading}>
<table style={{ width: '100%', textAlign: 'center', borderTop: '1px solid #333', borderLeft: '1px solid #333' }} className={styles.PrintForm}>
<tbody>
<tr>
<td colSpan={4} rowSpan={1} className={styles.fontBold}>调查名称</td>
<td colSpan={20} rowSpan={1}>{safe ? safe.NAME : ''}</td>
</tr>
<tr>
<td colSpan={3} rowSpan={1} className={styles.fontBold}>发起时间</td>
<td colSpan={3} rowSpan={1}>{safe ? safe.LAUNCH_TIME : null}</td>
<td colSpan={3} rowSpan={1} className={styles.fontBold}>发起部门</td>
<td colSpan={3} rowSpan={1}>{safe ? safe.Nav_LaunchDepartment.NAME : ''}</td>
<td colSpan={3} rowSpan={1} className={styles.fontBold}>发起人员</td>
<td colSpan={3} rowSpan={1}>{safe ? safe.Nav_LaunchUser.NAME : ''}</td>
<td colSpan={3} rowSpan={1} className={styles.fontBold}>截止时间</td>
<td colSpan={3} rowSpan={1}>{safe ? safe.END_TIME : ''}</td>
</tr>
<tr>
<td colSpan={4} rowSpan={1} className={styles.fontBold}>参与人员</td>
<td colSpan={20} rowSpan={1}>{this.getJoinDepartment().join('、')}</td>
</tr>
<tr>
<td colSpan={4} rowSpan={1} className={styles.fontBold}>调查内容</td>
<td colSpan={20} rowSpan={1}>{safe && safe.Nav_Points && safe.Nav_Points.map(it => it.Nav_Point.NAME).join('、')}</td>
</tr>
<tr>
<td colSpan={4} rowSpan={1} className={styles.fontBold}>工号</td>
<td colSpan={4} rowSpan={1}>{SelUsr && SelUsr.CODE}</td>
<td colSpan={4} rowSpan={1} className={styles.fontBold}>答卷人</td>
<td colSpan={4} rowSpan={1}>{SelUsr && SelUsr.NAME}</td>
<td colSpan={4} rowSpan={1} className={styles.fontBold}>成绩</td>
<td colSpan={4} rowSpan={1}>{this.CalcScore()}</td>
</tr>
<tr>
<td colSpan={24} rowSpan={1} className={styles.fontBold}>问卷</td>
</tr>
{
!this.state.haveAnswer && this.state.viewAll && !this.state.loading && <tr>
<td colSpan={24} rowSpan={1} className={styles.fontBold}>此用户问卷未提交</td>
</tr>
}
{
(this.state.haveAnswer || !this.state.viewAll) && papers.map((it, idx) => {
return (
<tr key={it.ID}>
<td colSpan={24} rowSpan={1}>
<table border={0} className={SEstyles.TestPaperItem}>
<tbody>
<tr>
<td colSpan={24} rowSpan={1} className={SEstyles.TestTiltle}>
<span>{idx + 1}.</span>
<span>{it.Nav_Test.NAME}</span>
<span>{this.getType(it.Nav_Test.TYPE)}</span>
</td>
</tr>
<tr style={this.state.readonly && ((it.Nav_Test.ANSWER & 1) != 0) ? answer : null}>
{
it.Nav_Test.TYPE === 0 ?
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 1) != 0) ? styles.answer : null}>
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 1) != 0} onChange={evt => this.doOptionChange(it, idx, 1, evt)} />
<span>正确</span>
</td>
:
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 1) != 0) ? styles.answer : null}>
{
it.Nav_Test.TYPE === 1 ?
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 1) != 0} onChange={evt => this.doOptionChange(it, idx, 1, evt)} />
:
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 1) != 0} onChange={evt => this.doOptionChange(it, idx, 1, evt)} />
}
<span>A.</span>
<span>{it.Nav_Test.OPTION_A}</span>
</td>
}
</tr>
<tr style={this.state.readonly && ((it.Nav_Test.ANSWER & 2) != 0) ? answer : null}>
{
it.Nav_Test.TYPE === 0 ?
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 2) != 0) ? styles.answer : null}>
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 2) != 0} onChange={evt => this.doOptionChange(it, idx, 2, evt)} />
<span>错误</span>
</td>
:
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 2) != 0) ? styles.answer : null}>
{
it.Nav_Test.TYPE === 1 ?
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 2) != 0} onChange={evt => this.doOptionChange(it, idx, 2, evt)} />
:
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 2) != 0} onChange={evt => this.doOptionChange(it, idx, 2, evt)} />
}
<span>B.</span>
<span>{it.Nav_Test.OPTION_B}</span>
</td>
}
</tr>
{
it.Nav_Test.TYPE !== 0 &&
<tr style={this.state.readonly && ((it.Nav_Test.ANSWER & 4) != 0) ? answer : null}>
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 4) != 0) ? styles.answer : null}>
{
it.Nav_Test.TYPE === 1 ?
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 4) != 0} onChange={evt => this.doOptionChange(it, idx, 4, evt)} />
:
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 4) != 0} onChange={evt => this.doOptionChange(it, idx, 4, evt)} />
}
<span>C.</span>
<span>{it.Nav_Test.OPTION_C}</span>
</td>
</tr>
}
{
it.Nav_Test.TYPE !== 0 && it.Nav_Test.OPTION_D != "" && it.Nav_Test.OPTION_D != undefined &&
<tr style={this.state.readonly && ((it.Nav_Test.ANSWER & 8) != 0) ? answer : null}>
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 8) != 0) ? styles.answer : null}>
{
it.Nav_Test.TYPE === 1 ?
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 8) != 0} onChange={evt => this.doOptionChange(it, idx, 8, evt)} />
:
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 8) != 0} onChange={evt => this.doOptionChange(it, idx, 8, evt)} />
}
<span>D.</span>
<span>{it.Nav_Test.OPTION_D}</span>
</td>
</tr>
}
{
it.Nav_Test.TYPE !== 0 && it.Nav_Test.OPTION_E != "" && it.Nav_Test.OPTION_E != undefined &&
<tr style={this.state.readonly && ((it.Nav_Test.ANSWER & 16) != 0) ? answer : null}>
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 16) != 0) ? styles.answer : null}>
{
it.Nav_Test.TYPE === 1 ?
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 16) != 0} onChange={evt => this.doOptionChange(it, idx, 16, evt)} />
:
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 16) != 0} onChange={evt => this.doOptionChange(it, idx, 16, evt)} />
}
<span>E.</span>
<span>{it.Nav_Test.OPTION_E}</span>
</td>
</tr>
}
</tbody>
</table>
</td>
</tr>
)
})
}
</tbody>
</table>
</Spin>
</div>
</div>
}
}
export default connect(({ login, app }) => ({ login, app }))(SESafeSurveyTest)