forked from Gitlink/forgeplus-react
274 lines
14 KiB
JavaScript
274 lines
14 KiB
JavaScript
import React, { useEffect, useState, Fragment } from "react";
|
||
import { Form, Upload, Input, Icon, Button, message, Modal, Checkbox, notification} from "antd";
|
||
import { Link } from "react-router-dom";
|
||
import axios from "axios";
|
||
import banner from '../img/banner-interim.png';
|
||
import banner1 from '../img/banner-interim1.png';
|
||
import img1 from '../img/img1.png';
|
||
import bg from '../img/bgPng.png';
|
||
import { httpUrl, main_site_url } from '../fetch';
|
||
import {getMediumTermExamineInfo, submitMedium, formatParsedResult, hasFinalExam} from '../api';
|
||
import './index.scss';
|
||
|
||
function StudentSubmit(props){
|
||
const {form, checkedTaskId, studentRegId, period, currentRound, glccSettings, isMediumExamineByToTutor, isFinalExamineByToTutor,history, current_user} = props;
|
||
const mediumExamine = glccSettings && glccSettings.filter(item=>item.name === "mediumExamine1");
|
||
const mediumExamine2 = glccSettings && glccSettings.filter(item=>item.name === "mediumExamine2");
|
||
const finalExamine = glccSettings && glccSettings.filter(item=>item.name === "finalExamine1");
|
||
const finalExamine2 = glccSettings && glccSettings.filter(item=>item.name === "finalExamine2");
|
||
let overtime = false;
|
||
if (mediumExamine2 && mediumExamine2[0] && period === "mediumExamine1") {
|
||
const nowTime = new Date().getTime();
|
||
const timeArr = mediumExamine2[0].value.split(",").map((item) => {
|
||
// replaceAll不兼容低版本浏览器(如搜狗)
|
||
const data = item && item.replace(/-/g, "/");
|
||
return new Date(data).getTime();
|
||
});
|
||
overtime = nowTime > timeArr[1];
|
||
} else if (finalExamine2 && finalExamine2[0] && period != "mediumExamine1") {
|
||
const nowTime = new Date().getTime();
|
||
const timeArr = finalExamine2[0].value.split(",").map((item) => {
|
||
// replaceAll不兼容低版本浏览器(如搜狗)
|
||
const data = item && item.replace(/-/g, '/');
|
||
return new Date(data).getTime()
|
||
});
|
||
overtime = nowTime > timeArr[1];
|
||
}
|
||
const {getFieldDecorator, validateFieldsAndScroll } = form;
|
||
const [detail, setDetail] = useState(undefined);
|
||
const [reload, setReload] = useState(undefined);
|
||
const [fileList, setFileList] = useState(undefined);
|
||
// 学生提交信息之后按钮置灰(确保无重复提交)
|
||
const [disabled, setDisabled] = useState(false);
|
||
// 是否授权主办方
|
||
const [isAuthed, setIsAuthed] = useState(false);
|
||
|
||
useEffect(()=>{
|
||
if(period != "mediumExamine1"){
|
||
hasFinalExam({round:currentRound,userId:current_user.user_id}).then((res)=>{
|
||
if(res && res.data && res.data.hasRole) return;
|
||
history.push("/glcc");
|
||
}).catch((err)=>{
|
||
history.push("/glcc");
|
||
})
|
||
}
|
||
},[])
|
||
|
||
useEffect(()=>{
|
||
// 查询是否已经提交考核材料
|
||
checkedTaskId && getMediumTermExamineInfo(checkedTaskId,{round: currentRound, term: period === "mediumExamine1" ? 1 : 2}).then(res=>{
|
||
if(res && res.message === "success"){
|
||
setDetail(res.data);
|
||
}
|
||
})
|
||
},[checkedTaskId, reload])
|
||
|
||
// 学生提交材料
|
||
function submit(e){
|
||
setDisabled(true);
|
||
e.preventDefault();
|
||
validateFieldsAndScroll((err, values) => {
|
||
if(!err){
|
||
Modal.confirm({
|
||
title: `确认提交${period === "mediumExamine1" ? '中期' : '结项'}考核材料?`,
|
||
content: "提交后将无法修改考核材料,请进行二次确认",
|
||
onOk: ()=>{
|
||
const {pptAttachment, defenceVideoUrl, codeOrPrUrl} = values;
|
||
const pptAttachmentId = pptAttachment.file && pptAttachment.file.response && pptAttachment.file.response.data.id;
|
||
const params = {
|
||
pptAttachmentId,
|
||
codeOrPrUrl,
|
||
defenceVideoUrl,
|
||
taskId: checkedTaskId,
|
||
studentRegId: studentRegId,
|
||
round: currentRound,
|
||
isAuthed,
|
||
term: period === "mediumExamine1" ? 1 : 2
|
||
}
|
||
submitMedium(params).then(res=>{
|
||
if(res && res.message === "success"){
|
||
if(!res.data){
|
||
message.success("提交成功");
|
||
setReload(Math.random());
|
||
}else if(res.data.code === '-1'){
|
||
message.error('不可重复提交');
|
||
}
|
||
}else{
|
||
setDisabled(false);
|
||
}
|
||
})
|
||
},
|
||
onCancel:()=>{
|
||
setDisabled(false);
|
||
}
|
||
})
|
||
}else{
|
||
setDisabled(false);
|
||
const { codeOrPrUrl } = values;
|
||
if (codeOrPrUrl) {
|
||
checkPrLink("", codeOrPrUrl, () => {});
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
function changeFileList(e) {
|
||
const {file} = e;
|
||
if(file && file.response && file.response.message && file.response.message == '文件上传失败'){
|
||
message.error('文件上传失败,请重新上传');
|
||
setFileList([])
|
||
}else{
|
||
file && file.status && setFileList([file]);
|
||
}
|
||
}
|
||
|
||
function changeEmpower(e){
|
||
setIsAuthed(e.target.checked);
|
||
}
|
||
|
||
// 检查文件上传是否符合规定
|
||
function beforeUpload(file){
|
||
const isLt100M = file.size / 1024 / 1024 < 100;
|
||
if (!isLt100M) {
|
||
message.error(`文件大小必须小于${100}MB!`);
|
||
}
|
||
return isLt100M;
|
||
}
|
||
function checkPrLink(rule, value, callback) {
|
||
if (value) {
|
||
axios
|
||
.get(`https://www.gitlink.org.cn/check_pr_url`, {
|
||
params: {
|
||
url: value,
|
||
task: checkedTaskId,
|
||
term: period === "mediumExamine1" ? 1 : 2,
|
||
},
|
||
})
|
||
.then((response) => {
|
||
if (response && response.data && response.data.state && response.data.state.length > 0) {
|
||
callback("");
|
||
const description = (
|
||
<div
|
||
dangerouslySetInnerHTML={{ __html: response.data.state_html }}
|
||
></div>
|
||
);
|
||
notification.open({
|
||
message: "提示",
|
||
description,
|
||
key:'notificationKey',
|
||
style: {
|
||
zIndex: 99999999,
|
||
},
|
||
});
|
||
}
|
||
callback();
|
||
});
|
||
} else {
|
||
callback("请输入视频链接");
|
||
}
|
||
}
|
||
return <div className="interimBox">
|
||
<img src={period === "mediumExamine1" ? banner1 : banner} alt="" className="bannerInterim"/>
|
||
<img src={bg} alt="" className="bg1"/>
|
||
<img src={bg} alt="" className="bg2"/>
|
||
<div className="mainBox">
|
||
<div className="navBox font-16"><Link to={`/glcc`} className="linkBox">开源夏令营 / </Link>提交{period === "mediumExamine1" ? '中期' : '结项'}考核材料</div>
|
||
<div className="tipBox mt30">
|
||
<div className="font-15 spanBox">材料提交说明:</div>
|
||
<div>1、请各位学生<a href={`https://www.gitlink.org.cn/api/attachments/${period === "mediumExamine1" ? '428107' : '427720'}`} className="blueSpan">下载PPT模板</a> ,根据课题开发进展,按照PPT模板要求填写课题学习调研方案、开发进度及开发成果等考核材料;</div>
|
||
<div>2、欢迎各位学生录制本课题答辩视频,将视频链接填写至下方视频介绍填写栏;</div>
|
||
<div>3、学生提交考核材料的时间为<span className="spanBox">{formatParsedResult( period === "mediumExamine1" ? mediumExamine : finalExamine)}</span>,请在截止时间前提交;</div>
|
||
<div>4、若导师已给出评分,各位学生可在此页面查看自己的结项考核成绩。对考核成绩有异议的学生请及时联系您的导师。</div>
|
||
</div>
|
||
<div className="titleBox mt25 font-18">
|
||
<img src={img1} alt="" width={24} className="mr5"/>
|
||
{period === "mediumExamine1" ? '中期' : '结项'}考核
|
||
</div>
|
||
{(period === "mediumExamine1" || period === "finalExamine1") && !detail ? <Form className="referBox" onSubmit={submit} colon={false}>
|
||
{
|
||
period === "mediumExamine1" || period === "finalExamine1" ?
|
||
<Fragment>
|
||
<Form.Item label="答辩视频" className="referItem oneCont oneLine">
|
||
{getFieldDecorator('defenceVideoUrl', {
|
||
rules: [{ required: true, message: '请输入视频链接!'}, {pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}],
|
||
})(<Input placeholder="请输入视频链接" maxLength={900}/>)}
|
||
</Form.Item>
|
||
<Form.Item className="referItem oneCont isEmpower">
|
||
<Checkbox checked={isAuthed} onChange={changeEmpower}>
|
||
授权主办方进行下载和剪辑,用作比赛宣传
|
||
</Checkbox>
|
||
</Form.Item>
|
||
<Form.Item label="pr地址" className="referItem oneCont oneLine inputErrColor">
|
||
{getFieldDecorator('codeOrPrUrl', {
|
||
rules: [
|
||
{
|
||
required: true,
|
||
validator: (rule, value, callback) => {
|
||
checkPrLink(rule, value, callback, checkedTaskId);
|
||
},
|
||
},
|
||
],
|
||
validateTrigger: "onBlur",
|
||
})(<Input placeholder="请输入pr地址" maxLength={900}/>)}
|
||
</Form.Item>
|
||
<Form.Item className="referItem oneCont referTips">
|
||
<p>注: 按主办方要求,GLCC官方资助课题最终需要在Gitlink平台进行pr提交。</p>
|
||
<p>请和导师确认您的课题是否官方赞助,如为官方赞助,请确保终期考核的pr提交在Gitlink平台上进行,否则将会影响您的最终考核。</p>
|
||
</Form.Item>
|
||
</Fragment>
|
||
:
|
||
<Fragment>
|
||
<Form.Item label="答辩视频" className="referItem">
|
||
{getFieldDecorator('defenceVideoUrl', {
|
||
rules: [{ required: true, message: '请输入视频链接!'}, {pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}],
|
||
})(<Input placeholder="请输入视频链接" maxLength={900}/>)}
|
||
</Form.Item>
|
||
<Form.Item label="代码/pr地址" className="referItem">
|
||
{getFieldDecorator('codeOrPrUrl', {
|
||
rules: [{pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}],
|
||
})(<Input placeholder="请输入代码或pr链接" maxLength={900}/>)}
|
||
</Form.Item>
|
||
</Fragment>
|
||
}
|
||
<Form.Item label="PPT附件" className="referItem oneCont">
|
||
{getFieldDecorator('pptAttachment', {
|
||
rules: [{ required: true, message: '请上传PPT附件!' }],
|
||
})(<Upload className="avatar-uploader" action={httpUrl + `/busiAttachments/upload`} beforeUpload={beforeUpload} onChange={changeFileList} fileList={fileList}>
|
||
{period === "mediumExamine1"?
|
||
<Button className="uploadBox" style={{color:'#466aff'}}>上传GLCC中期汇报ppt</Button>
|
||
:
|
||
period === 'finalExamine1' ?
|
||
<Button className="uploadBox" style={{ color: "#466aff" }}>上传GLCC结项汇报ppt</Button>
|
||
:
|
||
<Button className="uploadBox"><Icon type="upload" /> 上传</Button>
|
||
}
|
||
</Upload>)}
|
||
</Form.Item>
|
||
<Form.Item className="referItem oneCont">
|
||
<Button style={{width: '100px', height: '36px'}} className="mt30 ml20" type="primary" htmlType="submit" disabled={disabled && !detail}>提交</Button>
|
||
</Form.Item>
|
||
</Form> : <div className={`reviewBox referBox resultBox ${!detail ? 'nullData' : ''}`}>
|
||
<div className="flexBox">
|
||
<div className="mustSpan mb20"> 答辩视频<span className="blueBg ml10"><a href={detail && detail.defenceVideoUrl} target="_blank">{detail && detail.defenceVideoUrl}</a></span></div>
|
||
<div style={{ margin: "-10px 0 20px 90px" }}><Checkbox checked={detail && detail.isAuthed ? true: false} disabled></Checkbox><span style={{ marginLeft: "5px" }}>授权主办方进行下载和剪辑,用作比赛宣传</span></div>
|
||
<div>代码/pr地址<span className="blueBg ml10"><a href={detail && detail.codeOrPrUrl} target="_blank">{detail && detail.codeOrPrUrl}</a></span></div>
|
||
<div className="mustSpan ppt mb20"> PPT附件{detail && <i className="iconfont icon-lianjie3 font-13 mr5 ml10"></i>}{detail ? <a className="pptAttachment mr10" href={`${httpUrl}/busiAttachments/download/${detail.pptAttachment.id}`}>{`${detail.pptAttachment.fileName}`}</a> : <Button className="uploadBox ml10" disabled><Icon type="upload" /> 上传</Button>}{detail && detail.pptAttachment && detail.pptAttachment.fileSizeString}</div>
|
||
</div>
|
||
{!detail && <div className="nullDateTip font-15">很遗憾,您在指定时间内未提交考核材料</div>}
|
||
{detail && (isMediumExamineByToTutor || isFinalExamineByToTutor) && !detail.glccTutorEvaluation && <div className="font-15 nullDateTip">您的课题导师暂未评分,请提醒导师尽快提交结项考核评分</div>}
|
||
{detail && overtime && !detail.glccTutorEvaluation && <div className="font-15 nullDateTip">很遗憾,您的导师尚未评分,您未通过结项考核</div>}
|
||
{detail && detail.glccTutorEvaluation && <div className="tutorRes">
|
||
<div>您的课题导师对您的结项考核评价如下,如有异议,请及时联系导师进行更改。</div>
|
||
<div className="mt10 mb10 smallTil">
|
||
工作态度: <span className="blueSpan ml5">{detail.glccTutorEvaluation.workAttitudeEvaluation}</span><br/>
|
||
开发进度: <span className="blueSpan ml5">{detail.glccTutorEvaluation.developProgressEvaluation}</span><br/>
|
||
项目完成质量: <span className="blueSpan ml5">{detail.glccTutorEvaluation.projectQualityEvaluation}</span><br/>
|
||
总体评分: <span className="blueSpan ml5">{detail.glccTutorEvaluation.totalityEvaluation}</span><span className={`passStatusBox ml20 font-15 ${detail.glccTutorEvaluation.totalityEvaluation === 'D' ? '' : 'pass'}`}>{detail.glccTutorEvaluation.totalityEvaluation === 'D' ? '未通过' : '通过'}</span>
|
||
</div>
|
||
<div className="flexBox"><div><span className="smallTil">导师评语: </span><span className="ml10 tutorRemark">{detail.glccTutorEvaluation.comment}</span></div></div>
|
||
</div>}
|
||
</div>}
|
||
</div>
|
||
</div>
|
||
}
|
||
export default Form.create()(StudentSubmit); |