2025-08-25 10:08:30 +08:00
|
|
|
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';
|
2026-03-06 17:29:29 +08:00
|
|
|
import { initFilter, extendRule, extendInclude, setDataFieldValue, guid, initQueryFilter, showFiles, getFileShow } from "../../../utils/common";
|
2025-08-25 10:08:30 +08:00
|
|
|
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';
|
2026-03-06 17:29:29 +08:00
|
|
|
import configc from "../../../config.js";
|
2025-08-25 10:08:30 +08:00
|
|
|
|
|
|
|
|
const Option = Select.Option;
|
|
|
|
|
const answer = {
|
|
|
|
|
color: 'blue',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SE018PaperPage extends React.Component {
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
let viewAll = false;
|
|
|
|
|
if ((this.props.formParam && this.props.formParam.viewAll) || this.props.data.tableKey == undefined) {
|
|
|
|
|
viewAll = true;
|
|
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
this.player = null;
|
|
|
|
|
this.videoRef = React.createRef();
|
|
|
|
|
this.lastTimeRef = React.createRef(0);
|
2025-08-25 10:08:30 +08:00
|
|
|
this.state = {
|
|
|
|
|
papers: [],
|
|
|
|
|
viewAll,
|
|
|
|
|
record: null,
|
|
|
|
|
notify: null,
|
|
|
|
|
UserList: [],
|
|
|
|
|
SelUsrID: null,
|
|
|
|
|
config: null,
|
|
|
|
|
score: 0,
|
|
|
|
|
NAME: '',
|
|
|
|
|
END_TIME: null,
|
|
|
|
|
readonly: true,
|
|
|
|
|
loading: false,
|
2026-03-06 17:29:29 +08:00
|
|
|
isCourEdit: false, //是否 有课件的考试
|
|
|
|
|
isViedo: false,
|
|
|
|
|
isVideoEnd: true,
|
|
|
|
|
filepath: '',
|
|
|
|
|
filepathf: [],
|
|
|
|
|
btnText: '提交问卷', //'下一题'
|
|
|
|
|
perPaper: [], //每次的答题 wyw 20260306
|
|
|
|
|
listPath: [],
|
|
|
|
|
indexCour: -1 //课件
|
2025-08-25 10:08:30 +08:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
componentDidMount() {
|
2026-03-06 17:29:29 +08:00
|
|
|
this.videoRef?.current?.addEventListener('timeupdate', this.handleTimeUpdate);
|
2025-08-25 10:08:30 +08:00
|
|
|
if (window.navigator.userAgent.indexOf("Windows") < 1) {
|
|
|
|
|
this.setState({ isMobile: true })
|
|
|
|
|
}
|
|
|
|
|
if (this.props.data?.id)
|
|
|
|
|
this.loadData(this.props.data?.id);
|
|
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
componentWillUnmount() {
|
|
|
|
|
this.videoRef?.current?.removeEventListener('timeupdate', this.handleTimeUpdate);
|
|
|
|
|
|
|
|
|
|
if (this.player) {
|
|
|
|
|
this.player.destroy();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
handleTimeUpdate = (event) => {
|
|
|
|
|
const currentTime = event.target.currentTime;
|
|
|
|
|
if (currentTime < this.state.lastTime) {
|
|
|
|
|
event.target.currentTime = this.state.lastTime;
|
|
|
|
|
} else {
|
|
|
|
|
this.setState({
|
|
|
|
|
currentTime: currentTime,
|
|
|
|
|
lastTime: currentTime,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-25 10:08:30 +08:00
|
|
|
|
|
|
|
|
componentWillReceiveProps(NextProps) {
|
|
|
|
|
if (this.props.data.USER_ID !== NextProps.data.USER_ID) {
|
|
|
|
|
this.state.SelUsrID = NextProps.data.USER_ID;
|
|
|
|
|
this.loadData(this.props.data?.id);
|
|
|
|
|
}
|
|
|
|
|
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);
|
2025-12-22 15:33:31 +08:00
|
|
|
json.Parameter22 = this.props.data.ORG_ID_HV;
|
2025-08-25 10:08:30 +08:00
|
|
|
json.OrgType = 2;
|
2026-02-04 14:42:22 +08:00
|
|
|
if (this.props.data.TaskID) {
|
|
|
|
|
extendRule(json, 'TEXT_ID', 1, this.props.data.id);
|
|
|
|
|
} else {
|
|
|
|
|
extendRule(json, 'RECORD_ID', 1, this.props.data.id);
|
|
|
|
|
}
|
2025-08-25 10:08:30 +08:00
|
|
|
extendInclude(json, 'Nav_User');
|
|
|
|
|
this.state.loading = true;
|
|
|
|
|
this.props.dispatch({
|
|
|
|
|
type: 'app/getDataByPost',
|
|
|
|
|
payload: json,
|
|
|
|
|
url: 'SE/SETrainRecord/GetUsers',
|
|
|
|
|
onComplete: (ret) => {
|
|
|
|
|
this.state.loading = false;
|
|
|
|
|
if (ret && ret.length > 0) {
|
|
|
|
|
this.setState({
|
|
|
|
|
UserList: ret
|
|
|
|
|
})
|
|
|
|
|
if (this.state.viewAll) {
|
|
|
|
|
if (this.state.SelUsrID == null) {
|
|
|
|
|
this.setState({ SelUsrID: this.props.data?.USER_ID }, () => {
|
|
|
|
|
this.getPapers();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
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("当前用户没有问卷");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.state.SelUsrID = this.props.data?.USER_ID;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
getPapers = () => {
|
|
|
|
|
let SelUsrID = this.state.SelUsrID;
|
|
|
|
|
this.setState({ papers: [] });
|
|
|
|
|
if (!SelUsrID) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-04 14:42:22 +08:00
|
|
|
var scort = 'Nav_Test.TYPE'
|
|
|
|
|
if (!this.props.data.TaskID) {
|
|
|
|
|
scort = 'TEXT_ID'
|
|
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
let json = initFilter(this.props.login.OrgId, this.props.data.TaskID, scort, 1);
|
2025-12-22 15:33:31 +08:00
|
|
|
json.Parameter22 = this.props.data.ORG_ID_HV;
|
2025-08-25 10:08:30 +08:00
|
|
|
json.OrgType = 2;
|
2026-02-04 14:42:22 +08:00
|
|
|
if (this.props.data.TaskID) {
|
|
|
|
|
extendRule(json, 'TEXT_ID', 1, this.props.data.id);
|
|
|
|
|
} else {
|
|
|
|
|
extendRule(json, 'RECORD_ID', 1, this.props.data.id);
|
|
|
|
|
}
|
2025-08-25 10:08:30 +08:00
|
|
|
extendRule(json, 'USER_ID', 1, SelUsrID);
|
|
|
|
|
extendInclude(json, 'Nav_Record');
|
|
|
|
|
extendInclude(json, 'Nav_Record.Nav_Notify');
|
|
|
|
|
extendInclude(json, 'Nav_Record.Nav_Notify.Nav_LaunchDepartment');
|
|
|
|
|
extendInclude(json, 'Nav_Record.Nav_Notify.Nav_LaunchUser');
|
|
|
|
|
extendInclude(json, 'Nav_Record.Nav_Notify.Nav_TrainContentList');
|
|
|
|
|
extendInclude(json, 'Nav_Record.Nav_Notify.Nav_TrainType');
|
2025-11-20 22:03:40 +08:00
|
|
|
extendInclude(json, 'Nav_Record.Nav_Notify');
|
2025-08-25 10:08:30 +08:00
|
|
|
extendInclude(json, 'Nav_Record.Nav_Notify.Nav_TrainContentList.Nav_Point');
|
|
|
|
|
extendInclude(json, 'Nav_Test');
|
|
|
|
|
extendInclude(json, 'Nav_User');
|
|
|
|
|
this.state.loading = true;
|
|
|
|
|
this.props.dispatch({
|
|
|
|
|
type: 'app/getDataByPost',
|
|
|
|
|
payload: json,
|
|
|
|
|
url: 'SE/SETrainRecord/GetUserPapers',
|
|
|
|
|
onComplete: (ret) => {
|
|
|
|
|
this.state.loading = false;
|
2026-03-06 17:29:29 +08:00
|
|
|
var isCourEdit = false
|
|
|
|
|
if (this.props.data.tableKey == '1' && ret.listPath != null && ret.listPath.length > 0) {
|
|
|
|
|
isCourEdit = true //考试 有 课件
|
|
|
|
|
this.state.listPath = ret.listPath
|
|
|
|
|
}
|
|
|
|
|
if (ret.listPath.length > 1) {
|
|
|
|
|
this.state.btnText = '下一题'
|
|
|
|
|
}
|
|
|
|
|
// this.onSave()
|
|
|
|
|
|
2025-08-25 10:08:30 +08:00
|
|
|
if (ret && ret.Nav_Papers && ret.Nav_Papers.length > 0) {
|
|
|
|
|
let papers = ret.Nav_Papers.sort((a, b) => { return a.Nav_Test.TYPE - b.Nav_Test.TYPE });
|
|
|
|
|
let config = ret.Nav_Config;
|
|
|
|
|
let record = ret.Nav_Papers[0].Nav_Record;
|
|
|
|
|
let notify = record ? record.Nav_Notify : null;
|
|
|
|
|
let NAME = record.Nav_Notify.NAME;
|
|
|
|
|
let hasAnswered = false;
|
|
|
|
|
for (let i = 0; i < ret.Nav_Papers.length; i++) {
|
|
|
|
|
if (ret.Nav_Papers[i].ANSWER !== 0) {
|
|
|
|
|
hasAnswered = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
|
|
|
|
|
var perPaper = []
|
|
|
|
|
if (isCourEdit == false)
|
|
|
|
|
perPaper = papers //提供显示
|
2025-08-25 10:08:30 +08:00
|
|
|
this.setState({
|
|
|
|
|
papers,
|
2026-03-06 17:29:29 +08:00
|
|
|
perPaper: perPaper,
|
2025-08-25 10:08:30 +08:00
|
|
|
config,
|
|
|
|
|
record,
|
|
|
|
|
notify,
|
|
|
|
|
readonly: hasAnswered,
|
|
|
|
|
NAME: NAME,
|
2026-03-06 17:29:29 +08:00
|
|
|
isCourEdit: isCourEdit,
|
|
|
|
|
listPath: this.state.listPath,
|
|
|
|
|
btnText: this.state.btnText,
|
2025-08-25 10:08:30 +08:00
|
|
|
})
|
2026-03-06 17:29:29 +08:00
|
|
|
if (isCourEdit == true) {
|
|
|
|
|
this.onSave()
|
|
|
|
|
}
|
2025-08-25 10:08:30 +08:00
|
|
|
} else {
|
|
|
|
|
message.error('未能成功获取此用户的在线试卷,请稍后重试');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
loadData = () => {
|
|
|
|
|
if (this.props.data.id == "")
|
|
|
|
|
return;
|
|
|
|
|
this.getUsers();
|
|
|
|
|
}
|
|
|
|
|
onSave = () => {
|
|
|
|
|
if (this.state.readonly) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
if (this.state.indexCour > -1) {
|
|
|
|
|
let data = JSON.parse(JSON.stringify(this.state.perPaper));
|
|
|
|
|
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;
|
|
|
|
|
}
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
|
|
|
|
|
var replaceModel = {}
|
|
|
|
|
this.state.papers.forEach(e => {
|
|
|
|
|
replaceModel = this.state.perPaper.filter(ep => e.ID == ep.ID)
|
|
|
|
|
if (replaceModel != null) {
|
|
|
|
|
e = replaceModel
|
|
|
|
|
}
|
|
|
|
|
})
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
|
|
|
|
|
if (this.state.btnText == "提交问卷" && this.state.indexCour > -1) {
|
|
|
|
|
//数据提交
|
|
|
|
|
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,
|
|
|
|
|
TEXT_ID: this.props.data.id,
|
|
|
|
|
}
|
|
|
|
|
this.props.dispatch({
|
|
|
|
|
type: 'app/getDataByPost',
|
|
|
|
|
payload: data,
|
|
|
|
|
url: 'SE/SETrainRecord/SavePapers',
|
|
|
|
|
onComplete: (ret) => {
|
|
|
|
|
if (ret && ret.IsOperateSuccessful) {
|
|
|
|
|
if (ret.IsPass) {
|
|
|
|
|
message.success(ret.Msg)
|
|
|
|
|
} else {
|
|
|
|
|
message.warn(ret.Msg)
|
|
|
|
|
}
|
2026-02-04 14:42:22 +08:00
|
|
|
} else {
|
2026-03-06 17:29:29 +08:00
|
|
|
message.error('提交失败,请稍后重试');
|
2026-02-04 14:42:22 +08:00
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
this.BtnClose();
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: '提示',
|
|
|
|
|
content: '确定要提交当前问卷么?提交之后不可再次更改',
|
|
|
|
|
onOk: () => {
|
|
|
|
|
saveData();
|
|
|
|
|
},
|
|
|
|
|
onCancel() {
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
//下一题
|
|
|
|
|
this.state.indexCour++
|
|
|
|
|
//下一题
|
|
|
|
|
if (this.state.indexCour == this.state.listPath.length - 1) {
|
|
|
|
|
this.state.btnText = '提交问卷' //最后一题
|
|
|
|
|
} else {
|
|
|
|
|
this.state.btnText = '下一题'
|
|
|
|
|
}
|
|
|
|
|
this.state.filepath = this.state.listPath[this.state.indexCour]
|
|
|
|
|
var perPaper = this.state.papers.filter(e => e.FILE_PATH == this.state.filepath)
|
|
|
|
|
|
|
|
|
|
if (this.state.filepath.indexOf('/VIDEO/') > -1) {
|
|
|
|
|
this.state.isViedo = true
|
|
|
|
|
this.state.isVideoEnd = false
|
|
|
|
|
this.state.filepath = configc.videoServerHost + this.state.filepath
|
|
|
|
|
this.state.filepathf = []
|
|
|
|
|
} else if (this.state.filepath.indexOf('.mp4') > -1 || this.state.filepath
|
|
|
|
|
.indexOf('.avi') > -1) {
|
|
|
|
|
//暂时不应该进来
|
|
|
|
|
this.state.isViedo = true
|
|
|
|
|
this.state.isVideoEnd = false
|
|
|
|
|
this.state.filepath = configc.picServerHost + this.state.filepath
|
|
|
|
|
this.state.filepathf = []
|
|
|
|
|
} else {
|
|
|
|
|
this.state.isViedo = false
|
|
|
|
|
this.state.isVideoEnd = true
|
|
|
|
|
this.state.filepath = this.state.filepath
|
|
|
|
|
this.state.filepathf = getFileShow(this.state.filepath)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
|
indexCour: this.state.indexCour,
|
|
|
|
|
btnText: this.state.btnText,
|
|
|
|
|
perPaper: perPaper,
|
|
|
|
|
filepath: this.state.filepath,
|
|
|
|
|
isViedo: this.state.isViedo,
|
|
|
|
|
isVideoEnd: this.state.isVideoEnd,
|
|
|
|
|
filepathf: this.state.filepathf,
|
|
|
|
|
})
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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.NAME == "宁化行洛坑钨矿有限公司") {
|
|
|
|
|
arr.push({
|
|
|
|
|
id: it.Nav_Department.ID,
|
|
|
|
|
name: "公司领导"
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
arr.push({
|
|
|
|
|
id: it.Nav_Department.ID,
|
|
|
|
|
name: it.Nav_Department.NAME
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
doOptionChange = (it, index, mask, evt) => {
|
2026-03-06 17:29:29 +08:00
|
|
|
let perPaper = this.state.perPaper;
|
2025-08-25 10:08:30 +08:00
|
|
|
if (evt.target.checked) {
|
|
|
|
|
if (it.Nav_Test.TYPE === 2) {
|
2026-03-06 17:29:29 +08:00
|
|
|
perPaper[index].ANSWER |= mask;
|
2025-08-25 10:08:30 +08:00
|
|
|
} else {
|
2026-03-06 17:29:29 +08:00
|
|
|
perPaper[index].ANSWER = mask;
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
} else {
|
2026-03-06 17:29:29 +08:00
|
|
|
perPaper[index].ANSWER = perPaper[index].ANSWER & (~mask);
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
this.setState({
|
2026-03-06 17:29:29 +08:00
|
|
|
perPaper,
|
2025-08-25 10:08:30 +08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
returnModel(level) {
|
|
|
|
|
let str = '';
|
|
|
|
|
if (level == undefined) {
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
if (level.indexOf('1') >= 0) {
|
|
|
|
|
str += '讲授法 ';
|
|
|
|
|
}
|
|
|
|
|
if (level.indexOf('2') >= 0) {
|
|
|
|
|
str += '视听法 ';
|
|
|
|
|
}
|
|
|
|
|
if (level.indexOf('3') >= 0) {
|
|
|
|
|
str += '研讨法 ';
|
|
|
|
|
}
|
|
|
|
|
if (level.indexOf('4') >= 0) {
|
|
|
|
|
str += '演示法 ';
|
|
|
|
|
}
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
CalcScore = () => {
|
|
|
|
|
if (!this.state.readonly) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2026-02-04 14:42:22 +08:00
|
|
|
|
2025-08-25 10:08:30 +08:00
|
|
|
let score = 0;
|
2026-02-04 14:42:22 +08:00
|
|
|
// 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;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// })
|
|
|
|
|
// forEach (this.state.papers, (it, idx) => {
|
|
|
|
|
// this.state.papers
|
|
|
|
|
// });
|
|
|
|
|
this.state.papers.forEach(element => {
|
|
|
|
|
if (score < element.SCORE) {
|
|
|
|
|
score = element.SCORE;
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
2026-02-04 14:42:22 +08:00
|
|
|
});
|
2025-08-25 10:08:30 +08:00
|
|
|
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;
|
|
|
|
|
}
|
2026-03-06 17:29:29 +08:00
|
|
|
onEnd = () => {
|
|
|
|
|
this.setState({
|
|
|
|
|
isVideoEnd: true
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
TimeUpdate = () => {
|
|
|
|
|
const currentTime = this.videoRef.current.currentTime;
|
|
|
|
|
if (currentTime > this.lastTimeRef.current + 1) {
|
|
|
|
|
this.videoRef.current.currentTime = this.lastTimeRef.current
|
|
|
|
|
message.error(`禁止快进`);
|
|
|
|
|
} else {
|
|
|
|
|
this.lastTimeRef.current = currentTime
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-25 10:08:30 +08:00
|
|
|
render() {
|
2026-03-06 17:29:29 +08:00
|
|
|
const { record, perPaper, SelUsrID, UserList, notify, btnText, filepath, isViedo, isCourEdit, isVideoEnd, filepathf } = this.state;
|
2025-08-25 10:08:30 +08:00
|
|
|
const SelUsr = SelUsrID && UserList.find(it => it.ID === SelUsrID);
|
|
|
|
|
return <div>
|
|
|
|
|
<div style={{ padding: '10px' }}>
|
|
|
|
|
{
|
|
|
|
|
this.state.viewAll &&
|
|
|
|
|
<Select style={{ fontSize: 14, width: "100px", display: "none" }}
|
|
|
|
|
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>
|
|
|
|
|
}
|
|
|
|
|
<span />
|
|
|
|
|
<ReactToPrint
|
|
|
|
|
trigger={() => <Button type={'primary'} icon={'printer'} >打印</Button>}
|
|
|
|
|
content={() => this.componentRef}
|
|
|
|
|
/>
|
|
|
|
|
<Button style={{ marginLeft: '8px' }} onClick={() => this.onTableBtnExport()} icon="export" >导出</Button>
|
|
|
|
|
{
|
|
|
|
|
!this.state.readonly && (
|
2026-03-06 17:29:29 +08:00
|
|
|
<Button type="primary" style={{ marginLeft: '8px' }} onClick={() => { this.onSave(); }}>{btnText}</Button>
|
2025-08-25 10:08:30 +08:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
<div ref={el => (this.componentRef = el)} id={'tableId' + this.props.data.id}>
|
|
|
|
|
<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} className={styles.fontBold}>{notify ? notify.NAME : null}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>编号</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify ? notify.CODE : null}</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>培训时间</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify ? `${moment(notify.TRAIN_START_TIME).format('YYYY-MM-DD')} - ${moment(notify.TRAIN_END_TIME).format('YYYY-MM-DD')}` : null}</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>培训地点</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify ? notify.TRAIN_ADDR : null}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>组织部门</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify && notify.Nav_LaunchDepartment ? notify.Nav_LaunchDepartment.NAME : null}</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>记录/考核人</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify && notify.Nav_LaunchUser ? notify.Nav_LaunchUser.NAME : null}</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>培训老师</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify ? notify.TRAIN_TEACHER : null}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>培训学时</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify ? notify.HOURS : null}</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>培训形式</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} >{notify ? this.returnModel(notify.TRAIN_MODEL) : null}</td>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>考核方式</td>
|
2025-11-21 13:21:35 +08:00
|
|
|
<td colSpan={4} rowSpan={1} >{notify && notify.CHECKTYPE && this.props.app.enums.PlanCheckType.enums[notify.CHECKTYPE]}</td>
|
2025-08-25 10:08:30 +08:00
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>培训内容</td>
|
|
|
|
|
<td colSpan={20} rowSpan={1} >{
|
|
|
|
|
notify && notify.Nav_TrainContentList && notify.Nav_TrainContentList.map(it => {
|
|
|
|
|
return 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>
|
2026-03-06 17:29:29 +08:00
|
|
|
{/* isViedo, isCourEdit */}
|
|
|
|
|
{
|
|
|
|
|
isCourEdit && isViedo ? <tr >
|
|
|
|
|
<td colSpan={24} rowSpan={1} className={styles.fontBold}>
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}>
|
|
|
|
|
{
|
|
|
|
|
<video ref={this.videoRef} style={{ marginTop: 5, height: window.innerHeight - 200 }} onEnded={() => this.onEnd()} onTimeUpdate={() => this.TimeUpdate()} src={filepath} controls>
|
|
|
|
|
<source src={filepath} type="video/mp4" />
|
|
|
|
|
</video>
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
</tr> : null
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
isCourEdit && !isViedo ? <tr >
|
|
|
|
|
<td colSpan={4} rowSpan={1} className={styles.fontBold}>课件附件</td>
|
|
|
|
|
<td colSpan={20} rowSpan={1} className={styles.fontBold}>
|
|
|
|
|
{
|
|
|
|
|
showFiles(filepathf, configc.picServerHost, this)
|
|
|
|
|
}
|
|
|
|
|
</td>
|
|
|
|
|
</tr> : null
|
|
|
|
|
}
|
2025-08-25 10:08:30 +08:00
|
|
|
<tr>
|
|
|
|
|
<td colSpan={24} rowSpan={1} className={styles.fontBold}>问卷</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{
|
2026-03-06 17:29:29 +08:00
|
|
|
isVideoEnd && perPaper.map((it, idx) => {
|
2025-08-25 10:08:30 +08:00
|
|
|
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}>
|
2026-02-02 16:21:36 +08:00
|
|
|
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 1) != 0} onChange={evt => this.doOptionChange(it, idx, 1, evt)} >正确</Radio>
|
2025-08-25 10:08:30 +08:00
|
|
|
</td>
|
|
|
|
|
:
|
|
|
|
|
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 1) != 0) ? styles.answer : null}>
|
|
|
|
|
{
|
|
|
|
|
it.Nav_Test.TYPE === 1 ?
|
2026-02-04 14:42:22 +08:00
|
|
|
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 1) != 0} onChange={evt => this.doOptionChange(it, idx, 1, evt)} >A.{it.Nav_Test.OPTION_A}</Radio>
|
2025-08-25 10:08:30 +08:00
|
|
|
:
|
2026-02-04 14:42:22 +08:00
|
|
|
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 1) != 0} onChange={evt => this.doOptionChange(it, idx, 1, evt)} >A.{it.Nav_Test.OPTION_A}</Checkbox>
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
</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}>
|
2026-02-02 16:21:36 +08:00
|
|
|
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 2) != 0} onChange={evt => this.doOptionChange(it, idx, 2, evt)} >错误</Radio>
|
2025-08-25 10:08:30 +08:00
|
|
|
</td>
|
|
|
|
|
:
|
|
|
|
|
<td colSpan={24} rowSpan={1} className={this.state.readonly && ((it.Nav_Test.ANSWER & 2) != 0) ? styles.answer : null}>
|
|
|
|
|
{
|
|
|
|
|
it.Nav_Test.TYPE === 1 ?
|
2026-02-04 14:42:22 +08:00
|
|
|
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 2) != 0} onChange={evt => this.doOptionChange(it, idx, 2, evt)} >B.{it.Nav_Test.OPTION_B}</Radio>
|
2025-08-25 10:08:30 +08:00
|
|
|
:
|
2026-02-04 14:42:22 +08:00
|
|
|
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 2) != 0} onChange={evt => this.doOptionChange(it, idx, 2, evt)} >B.{it.Nav_Test.OPTION_B}</Checkbox>
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
</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 ?
|
2026-02-04 14:42:22 +08:00
|
|
|
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 4) != 0} onChange={evt => this.doOptionChange(it, idx, 4, evt)} >C.{it.Nav_Test.OPTION_C}</Radio>
|
2025-08-25 10:08:30 +08:00
|
|
|
:
|
2026-02-04 14:42:22 +08:00
|
|
|
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 4) != 0} onChange={evt => this.doOptionChange(it, idx, 4, evt)} >C.{it.Nav_Test.OPTION_C}</Checkbox>
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
</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 ?
|
2026-02-04 14:42:22 +08:00
|
|
|
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 8) != 0} onChange={evt => this.doOptionChange(it, idx, 8, evt)} >D.{it.Nav_Test.OPTION_D}</Radio>
|
2025-08-25 10:08:30 +08:00
|
|
|
:
|
2026-02-04 14:42:22 +08:00
|
|
|
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 8) != 0} onChange={evt => this.doOptionChange(it, idx, 8, evt)} >D.{it.Nav_Test.OPTION_D}</Checkbox>
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
</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 ?
|
2026-02-04 14:42:22 +08:00
|
|
|
<Radio disabled={this.state.readonly} checked={(it.ANSWER & 16) != 0} onChange={evt => this.doOptionChange(it, idx, 16, evt)} >E.{it.Nav_Test.OPTION_E}</Radio>
|
2025-08-25 10:08:30 +08:00
|
|
|
:
|
2026-02-04 14:42:22 +08:00
|
|
|
<Checkbox disabled={this.state.readonly} checked={(it.ANSWER & 16) != 0} onChange={evt => this.doOptionChange(it, idx, 16, evt)} >E.{it.Nav_Test.OPTION_E}</Checkbox>
|
2025-08-25 10:08:30 +08:00
|
|
|
}
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</Spin>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default connect(({ login, app }) => ({ login, app }))(SE018PaperPage)
|