forked from Gitlink/forgeplus-react
开源夏令营中期考核
This commit is contained in:
parent
5fbac9d61c
commit
5ba6b27722
|
@ -141,4 +141,39 @@ export function getPassList(params) {
|
|||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 中期考核-查看中期考核信息
|
||||
export function getMediumTermExamineInfo(taskId) {
|
||||
return fetch({
|
||||
url: `/api/mediumTermExamineMaterial/getMediumTermExamineInfo/${taskId}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 中期考核-提交中期考核信息
|
||||
export function submitMedium(data) {
|
||||
return fetch({
|
||||
url: `/api/mediumTermExamineMaterial/create`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 中期考核-导师提交中期考核评分
|
||||
export function submitTutorEvaluation(data) {
|
||||
return fetch({
|
||||
url: `/api/tutorEvaluation/create`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 中期考核-导师更新中期考核评分
|
||||
export function updateTutorEvaluation(data) {
|
||||
return fetch({
|
||||
url: `/api/tutorEvaluation/update`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
|
@ -11,13 +11,15 @@ import banner from "../img/banner.png";
|
|||
import introduce from "../img/introduce.png";
|
||||
import apply1 from "../img/apply1.png";
|
||||
import apply2 from "../img/apply2.png";
|
||||
import img1 from "../img/img1.png";
|
||||
import img2 from "../img/img2.png";
|
||||
import teacher from "../img/teacher.png";
|
||||
import logo from "../img/openmmlab/logo1.png";
|
||||
import { hasAuditRole } from '../api';
|
||||
import './index.scss';
|
||||
|
||||
export default (props) => {
|
||||
const { current_user, isGlccApplyDate, showNotification, studentApplyStart, history, secondStudentApplyDate, isStudentApplyDate } = props;
|
||||
const { current_user, isGlccApplyDate, showNotification, studentApplyStart, history, secondStudentApplyDate, isStudentApplyDate, checkedTaskId, checkTime1, checkTime2 } = props;
|
||||
// function goToApply() {
|
||||
// if (isGlccApplyDate) {
|
||||
// if (current_user && current_user.login) {
|
||||
|
@ -31,9 +33,9 @@ export default (props) => {
|
|||
// }
|
||||
// }
|
||||
|
||||
const [hasRole, setHhasRole] = useState(false);
|
||||
const [hasRole, setHasRole] = useState(false);
|
||||
const resultTime1 = new Date().getTime() > new Date('2022-06-28 1:0').getTime() && new Date().getTime() < new Date('2022-07-01 0:0').getTime();
|
||||
const resultTime2 = new Date().getTime() > new Date('2022-07-01 12:0').getTime();
|
||||
const resultTime2 = new Date().getTime() > new Date('2022-07-01 12:0').getTime() && new Date().getTime() < new Date('2022-08-12 0:0').getTime();
|
||||
|
||||
useEffect(() => {
|
||||
if (!current_user.user_id) {
|
||||
|
@ -41,7 +43,7 @@ export default (props) => {
|
|||
}
|
||||
hasAuditRole({ userId: current_user.user_id }).then(res => {
|
||||
if (res && res.message == 'success' && res.data.hasRole) {
|
||||
setHhasRole(true);
|
||||
setHasRole(true);
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
@ -85,6 +87,32 @@ export default (props) => {
|
|||
</div>
|
||||
<div className="pt6">查看各课题入选学生名单</div>
|
||||
</div>}
|
||||
|
||||
{/* 学生中期考核 */}
|
||||
{!hasRole && checkTime1 && checkedTaskId && <Link className="apply" to={`/glcc/middle/submit`}>
|
||||
<div>
|
||||
<img src={img1} alt="" className="applyIcon" />
|
||||
<span className="til">中期考核</span>
|
||||
</div>
|
||||
<div className="pt6">学生提交考核材料</div>
|
||||
</Link>}
|
||||
{/* 导师中期考核 */}
|
||||
{hasRole && checkTime2 && <Link className="apply" to={`/glcc/middle`}>
|
||||
<div>
|
||||
<img src={img1} alt="" className="applyIcon" />
|
||||
<span className="til">中期考核</span>
|
||||
</div>
|
||||
<div className="pt6">导师拟定中期考核结果</div>
|
||||
</Link>}
|
||||
{/* 中期考核结果公示页8月26日0点 */}
|
||||
{/* {new Date().getTime() > new Date('2022-07-01 0:0').getTime() && <Link className="apply" to={`/glcc/middle/result`}>
|
||||
<div>
|
||||
<img src={img1} alt="" className="applyIcon" />
|
||||
<span className="til">考核结果</span>
|
||||
</div>
|
||||
<div className="pt6">中期课题考核结果公示</div>
|
||||
</Link>} */}
|
||||
|
||||
{/* 项目报名 */}
|
||||
<Link to="/glcc/projects" className="apply project" >
|
||||
<div>
|
||||
|
@ -102,7 +130,7 @@ export default (props) => {
|
|||
</div>
|
||||
<div className="pt6">选择课题,开启您的开源之旅</div>
|
||||
</div> */}
|
||||
|
||||
|
||||
{/* 导师审核 */}
|
||||
{/* {hasRole && new Date().getTime() < new Date('2022-07-01 0:0').getTime() && <div className="apply" onClick={goToCheck}>
|
||||
<div>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
|
@ -61,6 +61,21 @@ const Result = Loadable({
|
|||
loader: () => import("./checkResult"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 中期考核-学生
|
||||
const StudentSubmit = Loadable({
|
||||
loader: () => import("./interimReview/studentSubmit"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 中期考核-导师
|
||||
const TutorReview = Loadable({
|
||||
loader: () => import("./interimReview/tutorReview"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 中期考核-结果公示
|
||||
const MiddleResult = Loadable({
|
||||
loader: () => import("./interimReview/result"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Glcc = (propsF) => {
|
||||
const {current_user, showLoginDialog} = propsF;
|
||||
// 判断时间是否在开源夏令营报名时间内(4月15日~5月20日)
|
||||
|
@ -70,6 +85,10 @@ const Glcc = (propsF) => {
|
|||
const studentApplyStart = new Date().getTime() > new Date('2022-05-26').getTime();
|
||||
const isStudentApplyDate = new Date().getTime() > new Date('2022-05-26').getTime() && new Date().getTime() < new Date('2022-06-25 0:0').getTime();
|
||||
const secondStudentApplyDate = new Date().getTime() > new Date('2022-06-29 1:0').getTime() && new Date().getTime() < new Date('2022-06-30 0:0').getTime();
|
||||
// 学生中期考核提交资料时间
|
||||
const checkTime1 = new Date().getTime() > new Date('2022-08-12 8:0').getTime() && new Date().getTime() < new Date('2022-08-18 24:0').getTime();
|
||||
// 导师中期考核时间
|
||||
const checkTime2 = new Date().getTime() > new Date('2022-08-12 10:0').getTime() && new Date().getTime() < new Date('2022-08-24 24:0').getTime();
|
||||
|
||||
// 用户已报名课题id数组
|
||||
const [applyTaskId, setApplyTaskId] = useState({});
|
||||
|
@ -78,6 +97,8 @@ const Glcc = (propsF) => {
|
|||
const [cancelCount,setCancelCount]=useState(0);
|
||||
// 用户是否已经被导师选中
|
||||
const [lockedTaskName, setLockedTaskName] = useState(undefined);
|
||||
// 用户与导师双向选定的课题id
|
||||
const [checkedTaskId, setCheckedTaskId] = useState(undefined);
|
||||
|
||||
useEffect(()=>{
|
||||
// 获取用户课题报名信息current_user user_id
|
||||
|
@ -88,6 +109,7 @@ const Glcc = (propsF) => {
|
|||
response.data && response.data.registrationStudentTaskList.map(item=>{
|
||||
data[item.taskId] = item.id;
|
||||
item.locked && setLockedTaskName(item.taskName);
|
||||
item.passStatus && setCheckedTaskId(item.taskId);
|
||||
})
|
||||
setApplyTaskId(data);
|
||||
response.data&&setCancelCount(Number(response.data.cancelCount));
|
||||
|
@ -183,11 +205,35 @@ const Glcc = (propsF) => {
|
|||
)}
|
||||
></Route>
|
||||
|
||||
{/* 中期审核-结果公示 */}
|
||||
<Route
|
||||
path="/glcc/middle/result"
|
||||
render={(props) => (
|
||||
<MiddleResult current_user={current_user} history={props.history}/>
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 中期审核-学生 */}
|
||||
<Route
|
||||
path="/glcc/middle/submit"
|
||||
render={(props) => (
|
||||
<StudentSubmit current_user={current_user} history={props.history} checkedTaskId={checkedTaskId} checkTime1={checkTime1}/>
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 中期审核-导师 */}
|
||||
<Route
|
||||
path="/glcc/middle"
|
||||
render={(props) => (
|
||||
<TutorReview current_user={current_user} history={props.history} checkTime2={checkTime2}/>
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 首页 */}
|
||||
<Route
|
||||
path="/glcc"
|
||||
render={(props) => (
|
||||
<Home {...propsF} {...props} studentApplyStart={studentApplyStart} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate}/>
|
||||
<Home {...propsF} {...props} studentApplyStart={studentApplyStart} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate} checkedTaskId={checkedTaskId} checkTime1={checkTime1} checkTime2={checkTime2}/>
|
||||
)}
|
||||
></Route>
|
||||
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
.interimBox{
|
||||
background-image:linear-gradient(180deg,#ebf2ff 0%,#ebf2ff 43.09%,#f3f4f8 100%);
|
||||
padding-bottom: 125px;
|
||||
position: relative;
|
||||
.bg1, .bg2{
|
||||
width: 150px;
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
left: 6%;
|
||||
}
|
||||
.bg2{
|
||||
top: auto;
|
||||
left: auto;
|
||||
right: 20%;
|
||||
bottom: 0;
|
||||
}
|
||||
&.glcc-check .bg1{top: 36%;}
|
||||
.bannerInterim{
|
||||
width: 100%;
|
||||
}
|
||||
.navBox{
|
||||
padding: 20px 0 10px;
|
||||
color:#202d40;
|
||||
border-bottom: 1px dashed #bec5d5;
|
||||
.linkBox{
|
||||
color:#a4aabb;
|
||||
&:hover{color: $primary-color;}
|
||||
}
|
||||
}
|
||||
.mainBox{
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
.tipBox{
|
||||
padding: 12px 20px;
|
||||
color:#6c7283;
|
||||
line-height: 2.5;
|
||||
background-color:#e4edff;
|
||||
.spanBox{color: #000;}
|
||||
div{line-height: 1.8;margin-bottom: 10px;}
|
||||
}
|
||||
.titleBox{color: #333;}
|
||||
.referBox{
|
||||
margin-top: 25px;
|
||||
background-color:rgba(255, 255, 255, 0.27);
|
||||
border:1px solid #ffffff;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
padding: 30px 0;
|
||||
position: relative;
|
||||
.referItem{
|
||||
width: 47%;
|
||||
display: flex;
|
||||
.ant-form-item-control-wrapper{flex-grow: 1;}
|
||||
&.oneCont{
|
||||
width: 97%;
|
||||
.ant-upload-list-item{width: 30%;}
|
||||
.ant-upload-list-item:hover .ant-upload-list-item-info{background: none;}
|
||||
}
|
||||
.ant-input, .uploadBox{
|
||||
border-color:#b3c3db;
|
||||
background: none !important;
|
||||
}
|
||||
.contentBox{
|
||||
padding: 10px 11px 20px
|
||||
}
|
||||
}
|
||||
&.tutor{
|
||||
border: none;
|
||||
margin-top: -20px;
|
||||
background: none;
|
||||
.remarkBox{
|
||||
position: relative;
|
||||
flex: 0.97;
|
||||
}
|
||||
.oneCont{display: block;}
|
||||
.wordNum{
|
||||
position: absolute;
|
||||
right: 55px;
|
||||
bottom: 10px;
|
||||
}
|
||||
.referItem{margin-bottom: 5px;}
|
||||
}
|
||||
}
|
||||
.tutorContent{
|
||||
border: 1px solid #fff;
|
||||
margin-top: 40px;
|
||||
background-color: #f1f6ff;
|
||||
.task-tabs {
|
||||
margin-top: 0px;
|
||||
border: none;
|
||||
background: none;
|
||||
.task-title-stuName{
|
||||
font-weight:700;
|
||||
color:#6c7283;
|
||||
padding-bottom: 25px;
|
||||
border-bottom:1px dashed #bec5d5;
|
||||
}
|
||||
}
|
||||
}
|
||||
.reviewBox{
|
||||
.title{
|
||||
color:#333333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.blueBox{
|
||||
display: inline-block;
|
||||
width:5px;
|
||||
height:14px;
|
||||
background-color:#466aff;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
.flexBox{
|
||||
color:#202d40;
|
||||
border-bottom: 1px dashed #bec5d5;
|
||||
div{
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-bottom: 10px;
|
||||
.blueSpan{
|
||||
color: $primary-color;
|
||||
word-break: break-all;
|
||||
display: block;
|
||||
flex: 1;
|
||||
}
|
||||
.pptAttachment{
|
||||
color: $primary-color;
|
||||
max-width: 80%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.resultBox{
|
||||
padding: 30px 20px 50px 20px;
|
||||
.blueBg{
|
||||
width: 85%;
|
||||
display: inline-block;
|
||||
padding: 4px 10px;
|
||||
background-color:rgba(70, 106, 255, 0.05);
|
||||
border-radius:4px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.mustSpan{
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
&::before{
|
||||
content: '*';
|
||||
color: #ff3838;
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 3px;
|
||||
}
|
||||
&.ppt::before{
|
||||
top: -2px;
|
||||
left: 12px;
|
||||
}
|
||||
}
|
||||
.flexBox{
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
.tutorRes{
|
||||
background-color:rgba(107, 136, 255, 0.05);
|
||||
border-radius:4px;
|
||||
color:#6c7283;
|
||||
padding: 16px 30px 30px 20px;
|
||||
.smallTil{
|
||||
color: #202d40;
|
||||
}
|
||||
.blueSpan{color: $primary-color;}
|
||||
}
|
||||
.tutorRemark{
|
||||
flex: 1;
|
||||
color:#6c7283;
|
||||
}
|
||||
}
|
||||
}
|
||||
.interimBox.resultListBox{
|
||||
.searchBox{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.resultListTable th.columnsResult.actionBox .ant-table-column-title{
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Input, Table, Tooltip, Checkbox } from 'antd';
|
||||
import { getPassList, hasAuditRole } from '../api';
|
||||
import ProjectDetail from '../project/component/projectDetail';
|
||||
import resultBanner from "../img/resultBanner3.png";
|
||||
import bgPng from "../img/bgPng.png";
|
||||
import './index.scss';
|
||||
import '../checkResult/index.scss';
|
||||
import '../project/taskList/index.scss';
|
||||
import '../project/index.scss';
|
||||
const { Search } = Input;
|
||||
|
||||
// 课题列表
|
||||
function CheckResult({current_user, history}) {
|
||||
// 输入搜索框
|
||||
// 已通过
|
||||
const [pass, setPass] = useState(false);
|
||||
const [keyword, setKeyword] = useState(undefined);
|
||||
const [data, setData] = useState([]);
|
||||
// table
|
||||
const [current, setCurrent] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [pageSize, setPageSize] = useState(20);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [expandedRowKeys, setExpandedRowKeys] = useState([]);
|
||||
const time = new Date().getTime() > new Date('2022-06-28 1:0').getTime() && new Date().getTime() < new Date('2022-07-01 0:0').getTime();
|
||||
|
||||
useEffect(()=>{
|
||||
// 未到时间
|
||||
if(new Date().getTime() < new Date('2022-06-28 1:0').getTime()){
|
||||
history.push('/glcc');
|
||||
}
|
||||
hasAuditRole({ userId: current_user.user_id }).then(res => {
|
||||
// 7.1之前 普通用户不可以进入此页面
|
||||
if (!(res && res.message == 'success' && res.data.hasRole) && new Date().getTime() < new Date('2022-07-01 12:0').getTime()) {
|
||||
history.push('/glcc');
|
||||
}
|
||||
})
|
||||
},[])
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
setExpandedRowKeys([]);
|
||||
const params = {
|
||||
curPage: current,
|
||||
keyword,
|
||||
pageSize,
|
||||
}
|
||||
getPassList(params).then(response => {
|
||||
if (response && response.message === "success") {
|
||||
setData(response.data.rows);
|
||||
setTotal(response.data.total);
|
||||
}
|
||||
setLoading(false);
|
||||
})
|
||||
}, [keyword, current, pageSize])
|
||||
|
||||
const columns = [
|
||||
{ title: '序号', dataIndex: 'index', align: 'center', className:"columnsResult", width: '6%', render: (text, item, index) => <span>{(current-1)*pageSize+index + 1}</span> },
|
||||
{ title: '入选学生', dataIndex: 'studentName', className:"columnsResult taskName", width: '10%', ellipsis: true},
|
||||
{ title: '课题导师', dataIndex: 'tutorName', className:"columnsResult", width: '10%', ellipsis: true},
|
||||
{ title: '课题名称', dataIndex: 'taskName', className:"columnsResult", width: '20%', ellipsis: true, render: (text, item) => <Tooltip title={text} placement="topLeft"><span className='toolTipSpan link' onClick={()=>{window.open(`/glcc/subjects/detail/${item.taskId}`)}}>{text}</span></Tooltip> },
|
||||
{ title: '项目名称', dataIndex: 'projectName', className:"columnsResult", ellipsis: true, width: '14%', render: (text) => <Tooltip title={text} placement="topLeft"><span className='toolTipSpan'>{text}</span></Tooltip> },
|
||||
{ title: '项目简介', dataIndex: 'introduce', className:"columnsResult", width: '13%', ellipsis: true},
|
||||
{ title: '答辩视频', dataIndex: 'tutorName', className:"columnsResult", width: '15%', ellipsis: true, render: (text, item) => <Tooltip title={text} placement="topLeft"><span className='toolTipSpan link' onClick={()=>{window.open(`/glcc/subjects/detail/${item.taskId}`)}}>{text}</span></Tooltip>},
|
||||
{ title: '考核结果', dataIndex: 'action', align: 'center', className:"columnsResult actionBox", render: (text, item, index) => <span>{'未通过'}</span>},
|
||||
]
|
||||
|
||||
const customExpandIcon = (props) => {
|
||||
if (props.expanded) {
|
||||
return <a className='toolTipSpan link' style={{marginRight: 8 }} onClick={e => {
|
||||
props.onExpand(props.record, e);
|
||||
}}><i className='iconfont icon-ketixiangqingicon mr5'></i>项目简介<i className="iconfont icon-changyongtubiao-xianxingdaochu-zhuanqu- font-12 ml5 down mr10"></i></a>
|
||||
} else {
|
||||
return <a className='toolTipSpan link' style={{marginRight: 8 }} onClick={e => {
|
||||
props.onExpand(props.record, e);
|
||||
}}><i className='iconfont icon-ketixiangqingicon mr5'></i>项目简介<i className="iconfont icon-jiantou9 font-12 ml5 down mr10"></i></a>
|
||||
}
|
||||
}
|
||||
|
||||
const expandRow = (record) => {
|
||||
return <ProjectDetail detail={null} projectId={record.regId} showTask={false}/>
|
||||
}
|
||||
|
||||
// 展开收起行回调
|
||||
function onExpand(expanded, record){
|
||||
const keys = new Set(expandedRowKeys);
|
||||
if(expanded){
|
||||
keys.add(record.id);
|
||||
}else{
|
||||
keys.delete(record.id);
|
||||
}
|
||||
setExpandedRowKeys(Array.from(keys));
|
||||
}
|
||||
|
||||
// 改变pagesize
|
||||
function onShowSizeChange(current, pageSize){
|
||||
window.scrollTo(0, 0);
|
||||
setCurrent(1);
|
||||
setPageSize(pageSize);
|
||||
}
|
||||
|
||||
// 切换页数
|
||||
function changePage(page, pageSize){
|
||||
window.scrollTo(0, 0);
|
||||
setCurrent(page);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="interimBox taskList resultListBox">
|
||||
<img className="bannerInterim" src={resultBanner} alt=""></img>
|
||||
<div className='bgBox'>
|
||||
<div className="resultList">
|
||||
<div className='goBackBox'><a href='/glcc'>开源夏令营 / </a>中期课题考核结果公示</div>
|
||||
<div className='searchBox'>
|
||||
<Checkbox onChange={(e)=>{setCurrent(1);setPass(e.target.checked)}}>已通过</Checkbox>
|
||||
<Search className='search' placeholder='请输入学生姓名或课题名称进行搜索' allowClear enterButton onSearch={(value) => { setCurrent(1); setKeyword(value) }} />
|
||||
<div style={{width: 100}}></div>
|
||||
</div>
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
expandedRowRender={expandRow}
|
||||
expandIconColumnIndex={5}
|
||||
expandIconAsCell={false}
|
||||
expandIcon={customExpandIcon}
|
||||
rowKey={'id'}
|
||||
expandedRowKeys={expandedRowKeys}
|
||||
onExpand={onExpand}
|
||||
pagination={{current: current, pageSize: pageSize, total: total, showSizeChanger: true, onShowSizeChange:onShowSizeChange, showQuickJumper: true, onChange: changePage}}
|
||||
className='resultListTable pb30'
|
||||
/>
|
||||
</div>
|
||||
<img src={bgPng} alt='' className='bgPng3'/>
|
||||
<img src={bgPng} alt='' className='bgPng4'/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default CheckResult;
|
|
@ -0,0 +1,114 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Form, Upload, Input, Icon, Button } from "antd";
|
||||
import { Link } from "react-router-dom";
|
||||
import banner from '../img/banner-interim.png';
|
||||
import img1 from '../img/img1.png';
|
||||
import bg from '../img/bgPng.png';
|
||||
import { main_site_url, httpUrl } from '../fetch';
|
||||
import {getMediumTermExamineInfo, submitMedium} from '../api';
|
||||
import './index.scss';
|
||||
|
||||
function StudentSubmit(props){
|
||||
const {form, checkedTaskId, checkTime1} = props;
|
||||
const {getFieldDecorator, validateFieldsAndScroll } = form;
|
||||
const [detail, setDetail] = useState(undefined);
|
||||
const [reload, setReload] = useState(undefined);
|
||||
const [fileList, setFileList] = useState(undefined);
|
||||
|
||||
useEffect(()=>{
|
||||
if(!checkTime1){
|
||||
window.location.href="/glcc";
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(()=>{
|
||||
// 查询是否已经提交考核材料
|
||||
checkedTaskId && getMediumTermExamineInfo(checkedTaskId).then(res=>{
|
||||
if(res && res.message === "success"){
|
||||
setDetail(res.data);
|
||||
}
|
||||
})
|
||||
},[checkedTaskId, reload])
|
||||
|
||||
// 学生提交材料
|
||||
function submit(e){
|
||||
e.preventDefault();
|
||||
validateFieldsAndScroll((err, values) => {
|
||||
if(!err){
|
||||
const {pptAttachment, defenceVideoUrl, codeOrPrUrl} = values;
|
||||
const pptAttachmentId = pptAttachment.file.response.data.id;
|
||||
const params = {
|
||||
pptAttachmentId,
|
||||
codeOrPrUrl,
|
||||
defenceVideoUrl,
|
||||
taskId: checkedTaskId,
|
||||
studentRegId: detail.studentRegId
|
||||
}
|
||||
console.log('params', params);
|
||||
submitMedium(params).then(res=>{
|
||||
console.log('提交', res);
|
||||
if(res && res.message === "success"){
|
||||
setReload(Math.random());
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
// 检查文件上传是否符合规定
|
||||
function changeFileList(e) {
|
||||
const {fileList} = e;
|
||||
const lastFile = fileList.splice(fileList.length-1, fileList.length);
|
||||
setFileList(lastFile);
|
||||
}
|
||||
return <div className="interimBox">
|
||||
<img src={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>提交中期考核材料</div>
|
||||
<div className="tipBox mt30">
|
||||
<div className="font-15 spanBox">材料提交说明:</div>
|
||||
<div>1、请各位学生下载PPT模板 ,根据课题开发进展,按照PPT模板要求填写课题学习调研方案、开发进度及开发成果、下半阶段工作计划等考核材料;</div>
|
||||
<div>2、欢迎各位学生录制本课题答辩视频,将视频链接填写至下方视频介绍填写栏;</div>
|
||||
<div>3、学生提交考核材料的时间为<span className="spanBox">2022年8月12日8点至2022年8月18日24点</span>,请在截止时间前提交。若在截止时间未提交中期考核表,则默认自动放弃,该课题将自动终止。</div>
|
||||
</div>
|
||||
<div className="titleBox mt25 font-18">
|
||||
<img src={img1} alt="" width={24} className="mr5"/>
|
||||
中期考核
|
||||
</div>
|
||||
{!detail ? <Form className="referBox" onSubmit={submit} colon={false}>
|
||||
<Form.Item label="答辩视频" className="referItem">
|
||||
{getFieldDecorator('defenceVideoUrl', {
|
||||
rules: [{ required: true, message: '请输入视频链接!'}, {pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}],
|
||||
})(<Input placeholder="请输入视频链接"/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="代码/pr地址" className="referItem">
|
||||
{getFieldDecorator('codeOrPrUrl', {
|
||||
rules: [{pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}],
|
||||
})(<Input placeholder="请输入代码或pr链接"/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="PPT附件" className="referItem oneCont">
|
||||
{getFieldDecorator('pptAttachment', {
|
||||
rules: [{ required: true, message: '请输入代码或pr链接!' }],
|
||||
})(<Upload className="avatar-uploader" action={httpUrl + `/busiAttachments/upload`} onChange={changeFileList} fileList={fileList}>
|
||||
<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">提交</Button>
|
||||
</Form.Item>
|
||||
</Form> : <div className="reviewBox referBox resultBox">
|
||||
<div className="flexBox">
|
||||
<div className="mustSpan mb20"> 答辩视频<a className="blueBg ml10" href={detail.defenceVideoUrl}>{detail.defenceVideoUrl}</a></div>
|
||||
<div>代码/pr地址<a className="blueBg ml10" href={detail.codeOrPrUrl} target="_blank">{detail.codeOrPrUrl}</a></div>
|
||||
<div className="mustSpan ppt mb20"> PPT附件<i className="iconfont icon-lianjie3 font-13 mr5 ml10"></i><a className="pptAttachment mr10" href={`${httpUrl}/busiAttachments/download/${detail.pptAttachment.id}`}>{`${main_site_url}/api/attachments/${detail.pptAttachment.fileName}`}</a>{detail.pptAttachment.fileSizeString}</div>
|
||||
</div>
|
||||
{detail.glccTutorEvaluation && <div className="tutorRes">
|
||||
<div>您的课题导师对您的中期考核评价如下,如有异议,请及时联系导师进行更改。</div>
|
||||
<div className="mt10 mb10 smallTil">工作态度: <span className="blueSpan ml5">A</span><br/>开发进度: <span className="blueSpan ml5">B</span><br/>项目完成质量: <span className="blueSpan ml5">C</span><br/>总体评分: <span className="blueSpan ml5">D</span></div>
|
||||
<div className="flexBox"><div><span className="smallTil">导师评语: </span><span className="ml10 tutorRemark">此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语此处为导师评语</span></div></div>
|
||||
</div>}
|
||||
</div>}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
export default Form.create()(StudentSubmit);
|
|
@ -0,0 +1,172 @@
|
|||
import React, {useState, useEffect, useCallback} from "react";
|
||||
import { Form, Input, Icon, Button, Tabs, Radio, message } from "antd";
|
||||
import { Link } from "react-router-dom";
|
||||
import bg from '../img/bgPng.png';
|
||||
import { getAuditList, getMediumTermExamineInfo, submitTutorEvaluation, updateTutorEvaluation } from '../api';
|
||||
import './index.scss';
|
||||
import '../check/index.scss'
|
||||
import Nodata from "../../forge/Nodata";
|
||||
import {httpUrl} from '../fetch';
|
||||
const { TabPane } = Tabs;
|
||||
const { TextArea } = Input;
|
||||
|
||||
function TutorReview(props){
|
||||
const {form, current_user, showNotification, checkTime2} = props;
|
||||
const {getFieldDecorator, setFieldsValue, validateFieldsAndScroll } = form;
|
||||
const [taskId, setTaskId] = useState();
|
||||
const [taskList, setTaskList] = useState([]);
|
||||
const [wordNum, setWordNum] = useState(0);
|
||||
const [detail, setDetail] = useState(undefined);
|
||||
const [reload, setReload] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if(!checkTime2){
|
||||
window.location.href="/glcc";
|
||||
}else{
|
||||
getAuditList({ userId: current_user.user_id, pass: 1 }).then(res => {
|
||||
if (res.message == 'success') {
|
||||
setTaskList(res.data.rows);
|
||||
res.data.rows.length && setTaskId(res.data.rows[0].id);
|
||||
} else {
|
||||
res && showNotification(res.message || '查询课题列表失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(()=>{
|
||||
// 查询是否已经提交考核材料
|
||||
taskId && getMediumTermExamineInfo(taskId).then(res=>{
|
||||
if(res && res.message === "success"){
|
||||
setDetail(res.data);
|
||||
if(res && res.data && res.data.glccTutorEvaluation){
|
||||
const {totalityEvaluation, comment} = res.data.glccTutorEvaluation;
|
||||
console.log('totalityEvaluation', totalityEvaluation, comment);
|
||||
setFieldsValue({...res.data.glccTutorEvaluation});
|
||||
}
|
||||
}
|
||||
})
|
||||
},[taskId, reload])
|
||||
|
||||
// 学生提交材料
|
||||
function submit(e){
|
||||
e.preventDefault();
|
||||
validateFieldsAndScroll((err, values) => {
|
||||
console.log('aaa', err, values);
|
||||
if(!err){
|
||||
const params = {
|
||||
...values,
|
||||
mediumTermExamineMaterialId: detail.id,
|
||||
tutorUserId: detail.studentRegId
|
||||
}
|
||||
if(detail.glccTutorEvaluation){
|
||||
params['id'] = detail.glccTutorEvaluation.id;
|
||||
updateTutorEvaluation(params).then(res=>{
|
||||
if(res && res.message === "success"){
|
||||
console.log('评论', res);
|
||||
message.success("修改成功");
|
||||
setReload(Math.random());
|
||||
}
|
||||
})
|
||||
}else{
|
||||
submitTutorEvaluation(params).then(res=>{
|
||||
if(res && res.message === "success"){
|
||||
console.log('评论', res);
|
||||
message.success("您已成功评分");
|
||||
setReload(Math.random());
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const RadioGroup = <Radio.Group>
|
||||
<Radio value={'A'}>A</Radio>
|
||||
<Radio value={'B'}>B</Radio>
|
||||
<Radio value={'C'}>C</Radio>
|
||||
<Radio value={'D'}>D</Radio>
|
||||
</Radio.Group>;
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, className) => (
|
||||
<Form.Item label={label} className={`referItem ${className}`}>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||||
</Form.Item>
|
||||
),[taskId, reload]
|
||||
);
|
||||
|
||||
return <div className="interimBox glcc-check">
|
||||
<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>导师拟定考核结果</div>
|
||||
<div className="tipBox mt30">
|
||||
<div className="font-15 spanBox">导师考核说明:</div>
|
||||
<div>1、请各位导师根据“工作态度”“开发进度”“项目完成质量”“总体评分”四个角度,根据学生提交的考核材料与实际开发情况客观地进行打分。打分标准分为:S:特别优秀、A:优秀、B:良好、C:合格、D:不合格五个等级。</div>
|
||||
<div>2、“总体评分”这一项将决定学生是否通过本次考核。若总体评分为“S、A、B、C”,则视为通过中期考核。若该结果为“D”,则该课题中期考核不通过,课题将自动终止。请各位导师谨慎做出评价。</div>
|
||||
<div>3、在审核阶段 (<span className="spanBox">2022年8月12日10点至2022年8月24日24点</span>) 导师提交打分结果后,可对考核结果进行更改,期间考核结果也将实时反馈给学生。</div>
|
||||
<div>4、北京时间<span className="spanBox">2022年8月26日20点</span>前GLCC官网将公布中期考核结果,敬请留意。</div>
|
||||
</div>
|
||||
<div className="tutorContent">
|
||||
<Tabs className="task-tabs" onChange={(e) => { setTaskId(e) }} activeKey={taskId + ''}>
|
||||
{
|
||||
taskList.map((item, i) => {
|
||||
return <TabPane tab={`课题${i + 1}`} key={item.id} >
|
||||
<div className="task-title-stuName font-16">{item.studentName} — {item.taskName}</div>
|
||||
</TabPane>
|
||||
})
|
||||
}
|
||||
</Tabs>
|
||||
{detail ? <div className="reviewBox">
|
||||
{/* 学生提交的资料 */}
|
||||
<div className="stuCont pl20 pr20">
|
||||
<div className="title font-16 mb15"><span className="blueBox"></span>基本信息</div>
|
||||
<div className="flexBox">
|
||||
<div> 答辩视频:<a className="blueSpan ml10" href={detail.defenceVideoUrl} target="_blank">{detail.defenceVideoUrl}</a></div>
|
||||
<div>代码/pr地址:<a className="blueSpan ml10" href={detail.codeOrPrUrl} target="_blank">{detail.codeOrPrUrl}</a></div>
|
||||
<div> PPT附件:<i className="iconfont icon-lianjie3 font-13 mr5 ml10"></i><a className="mr10 pptAttachment" href={`${httpUrl}/busiAttachments/download/${detail.pptAttachment.id}`}>{detail.pptAttachment.fileName}</a>{detail.pptAttachment.fileSizeString}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="title font-16 pl20 mt25"><span className="blueBox"></span>导师评分</div>
|
||||
{/* 导师打分 */}
|
||||
<Form className="referBox tutor" onSubmit={submit} labelAlign="left" labelCol={{ span: 5 }} colon={false}>
|
||||
{helper('工作态度',
|
||||
'workAttitudeEvaluation',
|
||||
[{ required: true, message: "请打分" }],
|
||||
RadioGroup
|
||||
)}
|
||||
{helper('工作进度',
|
||||
'developProgressEvaluation',
|
||||
[{ required: true, message: "请打分" }],
|
||||
RadioGroup
|
||||
)}
|
||||
{helper('项目完成质量',
|
||||
'projectQualityEvaluation',
|
||||
[{ required: true, message: "请打分" }],
|
||||
RadioGroup
|
||||
)}
|
||||
{helper('总体评分',
|
||||
'totalityEvaluation',
|
||||
[{ required: true, message: "请打分" }],
|
||||
RadioGroup
|
||||
)}
|
||||
<div className="remarkBox">
|
||||
{helper('填写评语',
|
||||
'comment',
|
||||
[{ required: true, message: "请输入评语!" }],
|
||||
<TextArea rows={8} placeholder="请对学生项目表现进行总体评价" className="contentBox" maxLength={500} onChange={(e)=>{setWordNum(e.target.value.length);}}/>,
|
||||
'oneCont'
|
||||
)}
|
||||
<div className="wordNum">{wordNum} / 500</div>
|
||||
</div>
|
||||
<Form.Item className="referItem oneCont">
|
||||
<Button style={{width: '100px', height: '36px'}} className="mt20" type="primary" htmlType="submit">{detail.glccTutorEvaluation ? '修改' : '提交'}</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>:<Nodata _html="该课题学生暂未提交中期考核材料,请提醒学生尽快提交"/>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
export default Form.create()(TutorReview);
|
Loading…
Reference in New Issue