diff --git a/src/AppConfig.js b/src/AppConfig.js index f771b9ea..a55649ce 100644 --- a/src/AppConfig.js +++ b/src/AppConfig.js @@ -25,7 +25,7 @@ if (isDev) { } debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' : window.location.search.indexOf('debug=s') !== -1 ? 'student' : - window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin' + window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'student' } window._debugType = debugType; export function initAxiosInterceptors(props) { diff --git a/src/glcc/api.js b/src/glcc/api.js index 61a02bab..adcec1fd 100644 --- a/src/glcc/api.js +++ b/src/glcc/api.js @@ -141,4 +141,56 @@ export function getPassList(params) { method: 'get', params, }); +} + +// 中期考核-查看中期考核信息(返回导师评分) +export function getMediumTermExamineInfo(taskId) { + return fetch({ + url: `/api/mediumTermExamineMaterial/getMediumTermExamineInfo/${taskId}`, + method: 'get' + }); +} + +// 中期考核-查看中期考核信息(不返回返回导师评分) +export function getBriefMediumTermExamineMaterial(taskId) { + return fetch({ + url: `/api/mediumTermExamineMaterial/getBriefMediumTermExamineMaterial/${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 + }); +} + +// 中期考核结果list +export function getMediumTermExamineInfoList(params) { + return fetch({ + url: `/api/mediumTermExamineMaterial/getMediumTermExamineInfoList`, + method: 'get', + params, + }); } \ No newline at end of file diff --git a/src/glcc/home/index.jsx b/src/glcc/home/index.jsx index 35c85a91..093891d3 100644 --- a/src/glcc/home/index.jsx +++ b/src/glcc/home/index.jsx @@ -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, checkTime3 } = 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) => {
查看各课题入选学生名单
} + + {/* 学生中期考核 */} + {!hasRole && checkTime1 && checkedTaskId && +
+ + 中期考核 +
+
学生提交考核材料
+ } + {/* 导师中期考核 */} + {hasRole && checkTime2 && +
+ + 中期考核 +
+
导师拟定中期考核结果
+ } + {/* 中期考核结果公示页 */} + {checkTime3 && +
+ + 考核结果 +
+
中期课题考核结果公示
+ } + {/* 项目报名 */}
@@ -102,7 +130,7 @@ export default (props) => {
选择课题,开启您的开源之旅
*/} - + {/* 导师审核 */} {/* {hasRole && new Date().getTime() < new Date('2022-07-01 0:0').getTime() &&
diff --git a/src/glcc/img/banner-interim.png b/src/glcc/img/banner-interim.png new file mode 100644 index 00000000..38f6bb7d Binary files /dev/null and b/src/glcc/img/banner-interim.png differ diff --git a/src/glcc/img/img1.png b/src/glcc/img/img1.png new file mode 100644 index 00000000..084309c1 Binary files /dev/null and b/src/glcc/img/img1.png differ diff --git a/src/glcc/img/img2.png b/src/glcc/img/img2.png new file mode 100644 index 00000000..5f8c18c2 Binary files /dev/null and b/src/glcc/img/img2.png differ diff --git a/src/glcc/img/resultBanner3.png b/src/glcc/img/resultBanner3.png new file mode 100644 index 00000000..b15d8c1e Binary files /dev/null and b/src/glcc/img/resultBanner3.png differ diff --git a/src/glcc/index.jsx b/src/glcc/index.jsx index f5908e00..d4277253 100644 --- a/src/glcc/index.jsx +++ b/src/glcc/index.jsx @@ -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,12 @@ 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-25 24:0').getTime(); + // 导师中期考核时间 + const checkTime2 = new Date().getTime() > new Date('2022-08-12 10:0').getTime() && new Date().getTime() < new Date('2022-08-25 24:0').getTime(); + // 中期考核结果公示8月26日0点 + const checkTime3 = new Date().getTime() > new Date('2022-08-26 0:0').getTime(); // 用户已报名课题id数组 const [applyTaskId, setApplyTaskId] = useState({}); @@ -78,6 +99,9 @@ const Glcc = (propsF) => { const [cancelCount,setCancelCount]=useState(0); // 用户是否已经被导师选中 const [lockedTaskName, setLockedTaskName] = useState(undefined); + // 用户与导师双向选定的课题id + const [checkedTaskId, setCheckedTaskId] = useState(undefined); + const [studentRegId, setStudentRegId] = useState(undefined); useEffect(()=>{ // 获取用户课题报名信息current_user user_id @@ -88,6 +112,8 @@ 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); + item.passStatus && setStudentRegId(item.studentRegId); }) setApplyTaskId(data); response.data&&setCancelCount(Number(response.data.cancelCount)); @@ -183,11 +209,35 @@ const Glcc = (propsF) => { )} > + {/* 中期审核-结果公示 */} + ( + + )} + > + + {/* 中期审核-学生 */} + ( + + )} + > + + {/* 中期审核-导师 */} + ( + + )} + > + {/* 首页 */} ( - + )} > diff --git a/src/glcc/interimReview/index.scss b/src/glcc/interimReview/index.scss new file mode 100644 index 00000000..d918848e --- /dev/null +++ b/src/glcc/interimReview/index.scss @@ -0,0 +1,229 @@ +.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;} + .blueSpan{ + color: $primary-color; + &:hover{color: $primary-color-hover;} + } + } + .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; + .has-error .ant-form-explain{ + position: absolute; + } + } + .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:#333; + padding-bottom: 25px; + border-bottom:1px dashed #bec5d5; + } + } + } + .reviewBox{ + .successReviewBox{ + color:#2dab4d; + background-color:rgba(82, 206, 152, 0.11); + border:1px solid rgba(36, 167, 67, 0.61); + margin: -5px 20px 20px; + padding: 6px 15px; + } + .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; + .nullDateTip{color: #ff3838;} + &.nullData .flexBox div{align-items: center;} + .blueBg{ + width: 85%; + min-height: 36px; + 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{ + width: 100%; + background-color:rgba(107, 136, 255, 0.05); + border-radius:4px; + color:#6c7283; + padding: 16px 30px 30px 20px; + .smallTil{ + color: #202d40; + } + .passStatusBox{ + display: inline-flex; + justify-content: center; + align-items: center; + width:59px; + height:28px; + color:#d2001d; + background-color:rgba(251, 0, 34, 0.06); + border:1px solid #df001f; + border-radius:6px; + &.pass{ + color:#2dab4d; + background-color:rgba(82, 206, 152, 0.11); + border-color:rgba(36, 167, 67, 0.61); + } + } + .blueSpan{color: $primary-color;} + } + .tutorRemark{ + word-break: break-all; + flex: 1; + color:#6c7283; + } + } +} +.interimBox.resultListBox{ + .searchBox{ + display: flex; + align-items: center; + } + .resultListTable th.columnsResult.actionBox .ant-table-column-title{ + visibility: visible; + } + .projectDetailBox.nodata{ + margin: 0 auto; + } +} \ No newline at end of file diff --git a/src/glcc/interimReview/result.jsx b/src/glcc/interimReview/result.jsx new file mode 100644 index 00000000..56efa766 --- /dev/null +++ b/src/glcc/interimReview/result.jsx @@ -0,0 +1,134 @@ +import React, { useEffect, useState } from 'react'; +import { Input, Table, Tooltip, Checkbox } from 'antd'; +import { getMediumTermExamineInfoList } 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, checkTime3}) { + // 输入搜索框 + 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([]); + + useEffect(()=>{ + // 未到时间 + if(!checkTime3){ + history.push('/glcc'); + } + },[]) + + useEffect(() => { + setLoading(true); + setExpandedRowKeys([]); + const params = { + curPage: current, + keyword, + pageSize + } + getMediumTermExamineInfoList(params).then(response => { + if (response && response.message === "success") { + response.data.rows.map((item, index)=>{ + item.id = (current-1)*pageSize+index + 1; + }) + 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) => {(current-1)*pageSize+index + 1} }, + { 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) => {window.open(`/glcc/subjects/detail/${item.taskId}`)}}>{text} }, + { title: '项目名称', dataIndex: 'projectName', className:"columnsResult", ellipsis: true, width: '14%', render: (text) => {text} }, + { title: '项目简介', dataIndex: 'introduce', className:"columnsResult", width: '13%', ellipsis: true}, + { title: '答辩视频', dataIndex: 'defenceVideoUrl', className:"columnsResult", width: '15%', ellipsis: true, render: (text, item) => {window.open(`/glcc/subjects/detail/${item.taskId}`)}}>{text}}, + { title: '考核结果', dataIndex: 'totalityEvaluation', align: 'center', className:"columnsResult actionBox", render: (text, item, index) => {text === 'D' || !text ? '未通过' : '通过'}}, + ] + + const customExpandIcon = (props) => { + if (props.expanded) { + return { + props.onExpand(props.record, e); + }}>项目简介 + } else { + return { + props.onExpand(props.record, e); + }}>项目简介 + } + } + + const expandRow = (record) => { + return + } + + // 展开收起行回调 + 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 ( +
+ +
+
+
开源夏令营 / 中期课题考核结果公示
+
+ { setCurrent(1); setKeyword(value) }} /> +
+
+ + + + + + + ) +} +export default CheckResult; \ No newline at end of file diff --git a/src/glcc/interimReview/studentSubmit.jsx b/src/glcc/interimReview/studentSubmit.jsx new file mode 100644 index 00000000..c20198ac --- /dev/null +++ b/src/glcc/interimReview/studentSubmit.jsx @@ -0,0 +1,134 @@ +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 { httpUrl, main_site_url } from '../fetch'; +import {getMediumTermExamineInfo, submitMedium, getBriefMediumTermExamineMaterial} from '../api'; +import './index.scss'; + +function StudentSubmit(props){ + const {form, checkedTaskId, checkTime1, studentRegId, history} = props; + const {getFieldDecorator, validateFieldsAndScroll } = form; + const [detail, setDetail] = useState(undefined); + const [reload, setReload] = useState(undefined); + const [fileList, setFileList] = useState(undefined); + // 学生提交材料时间 + const submitTime = new Date().getTime() < new Date('2022-08-21 24:0').getTime(); + // 学生查看导师评分时间 + const lookTime = new Date().getTime() > new Date('2022-08-24 24:0').getTime() && new Date().getTime() < new Date('2022-08-25 24:0').getTime(); + + useEffect(()=>{ + if(!checkTime1){ + history.push("/glcc"); + } + }, []) + + useEffect(()=>{ + // 查询是否已经提交考核材料 + if(lookTime){ + // 8.25学生可见导师评分 + checkedTaskId && getMediumTermExamineInfo(checkedTaskId).then(res=>{ + if(res && res.message === "success"){ + setDetail(res.data); + } + }) + }else{ + // 25号之前不可见 + checkedTaskId && getBriefMediumTermExamineMaterial(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: studentRegId + } + submitMedium(params).then(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
+ + + +
+
开源夏令营 / 提交中期考核材料
+
+
材料提交说明:
+
1、请各位学生下载PPT模板 ,根据课题开发进展,按照PPT模板要求填写课题学习调研方案、开发进度及开发成果、下半阶段工作计划等考核材料;
+
2、欢迎各位学生录制本课题答辩视频,将视频链接填写至下方视频介绍填写栏;
+
3、学生提交考核材料的时间为2022年8月12日8点至2022年8月21日24点,请在截止时间前提交。若在截止时间未提交中期考核表,则默认自动放弃,该课题将自动终止;
+
4、学生在2022年8月25日可在此页面查看自己考核成绩,若对考核成绩有异议,请及时联系导师进行更改。
+
+
+ + 中期考核 +
+ {submitTime && !detail ?
+ + {getFieldDecorator('defenceVideoUrl', { + rules: [{ required: true, message: '请输入视频链接!'}, {pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}], + })()} + + + {getFieldDecorator('codeOrPrUrl', { + rules: [{pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}], + })()} + + + {getFieldDecorator('pptAttachment', { + rules: [{ required: true, message: '请上传PPT附件!' }], + })( + )} + + + + + :
+
+ + +
   PPT附件{detail && }{detail ? {`${detail.pptAttachment.fileName}`} : }{detail && detail.pptAttachment && detail.pptAttachment.fileSizeString}
+
+ {!detail &&
很遗憾,您在指定时间内未提交考核材料
} + {lookTime && detail && !detail.glccTutorEvaluation &&
您的课题导师暂未评分,请提醒导师尽快提交中期考核评分
} + {detail && detail.glccTutorEvaluation &&
+
您的课题导师对您的中期考核评价如下,如有异议,请及时联系导师进行更改。
+
+ 工作态度: {detail.glccTutorEvaluation.workAttitudeEvaluation}
+ 开发进度: {detail.glccTutorEvaluation.developProgressEvaluation}
+ 项目完成质量: {detail.glccTutorEvaluation.projectQualityEvaluation}
+ 总体评分: {detail.glccTutorEvaluation.totalityEvaluation}{detail.glccTutorEvaluation.totalityEvaluation === 'D' ? '未通过' : '通过'} +
+
导师评语: {detail.glccTutorEvaluation.comment}
+
} +
} +
+
+} +export default Form.create()(StudentSubmit); \ No newline at end of file diff --git a/src/glcc/interimReview/tutorReview.jsx b/src/glcc/interimReview/tutorReview.jsx new file mode 100644 index 00000000..4a8db05e --- /dev/null +++ b/src/glcc/interimReview/tutorReview.jsx @@ -0,0 +1,183 @@ +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, hasAuditRole } 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, history} = props; + const {getFieldDecorator, setFieldsValue, validateFieldsAndScroll, resetFields } = form; + const [taskId, setTaskId] = useState(); + const [taskList, setTaskList] = useState([]); + const [wordNum, setWordNum] = useState(0); + const [detail, setDetail] = useState(undefined); + const [reload, setReload] = useState(undefined); + // 导师提交过之后是否是编辑状态 + const [isEdit, setIsEdit] = useState(false); + + useEffect(() => { + if(!checkTime2){ + history.push("/glcc"); + }else if (!current_user.login) { + history.push('/login?go_page=/glcc/middle/examination'); + }else{ + hasAuditRole({ userId: current_user.user_id }).then(res => { + if (!(res && res.message == 'success' && res.data.hasRole)) { + history.push('/glcc'); + } + }) + } + getAuditList({ userId: current_user.user_id, pass: 1 }).then(res => { + if (res.message === 'success') { + const filterStuNull = res.data.rows.filter(item=>{return item.studentName !== null}) + setTaskList(filterStuNull); + filterStuNull.length && setTaskId(filterStuNull[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){ + setWordNum(res.data.glccTutorEvaluation.comment.length); + setFieldsValue({...res.data.glccTutorEvaluation}); + } + } + }) + },[taskId, reload]) + + // 学生提交材料 + function submit(e){ + e.preventDefault(); + validateFieldsAndScroll((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"){ + setIsEdit(false); + message.success("修改成功"); + setReload(Math.random()); + } + }) + }else{ + submitTutorEvaluation(params).then(res=>{ + if(res && res.message === "success"){ + message.success("您已成功评分"); + setReload(Math.random()); + } + }) + } + } + }) + } + + const RadioGroup = + S + A + B + C + D + ; + + const helper = useCallback( + (label, name, rules, widget, className) => ( + + {getFieldDecorator(name, { rules, validateFirst: true })(widget)} + + ),[taskId, reload] + ); + + return
+ + +
+
开源夏令营 / 导师拟定考核结果
+
+
导师考核说明:
+
1、请各位导师根据“工作态度”“开发进度”“项目完成质量”“总体评分”四个角度,根据学生提交的考核材料与实际开发情况客观地进行打分。打分标准分为:S:特别优秀、A:优秀、B:良好、C:合格、D:不合格五个等级。
+
2、“总体评分”这一项将决定学生是否通过本次考核。若总体评分为“S、A、B、C”,则视为通过中期考核。若该结果为“D”,则该课题中期考核不通过,课题将自动终止。请各位导师谨慎做出评价。
+
3、导师提交打分结果后,可对考核结果进行更改,更改考核结果截止日期为2022年8月25日24点
+
4、北京时间2022年8月26日20点前GLCC官网将公布中期考核结果,敬请留意。
+
+
+ { resetFields(); setTaskId(e); setIsEdit(false); setWordNum(0); }} activeKey={taskId + ''}> + { + taskList.map((item, i) => { + return +
{item.studentName} — {item.taskName}
+
+ }) + } +
+ {detail ?
+ {/* 已评分提示语句 */} + {detail.glccTutorEvaluation &&
您已评分成功! 在审核期间,您可对评分结果进行更改
} + {/* 学生提交的资料 */} +
+
基本信息
+
+
     答辩视频:{detail.defenceVideoUrl}
+
代码/pr地址:{detail.codeOrPrUrl}
+
     PPT附件:{detail.pptAttachment.fileName}{detail.pptAttachment.fileSizeString}
+
+
+
导师评分
+ {/* 导师打分 */} +
+ {helper('工作态度', + 'workAttitudeEvaluation', + [{ required: true, message: "请打分" }], + RadioGroup + )} + {helper('工作进度', + 'developProgressEvaluation', + [{ required: true, message: "请打分" }], + RadioGroup + )} + {helper('项目完成质量', + 'projectQualityEvaluation', + [{ required: true, message: "请打分" }], + RadioGroup + )} + {helper('总体评分', + 'totalityEvaluation', + [{ required: true, message: "请打分" }], + RadioGroup + )} +
+ {helper('填写评语', + 'comment', + [{ required: true, message: "请输入评语!" }], +