diff --git a/src/glcc/api.js b/src/glcc/api.js index e86f2a6f..c0e710cd 100644 --- a/src/glcc/api.js +++ b/src/glcc/api.js @@ -152,6 +152,15 @@ export function getAuditList(params) { }); } +// 审核课题列表(匹配成功) +export function getLockedAuditList(params) { + return fetch({ + url: '/api/applyInformation/lockedAuditList', + method: 'get', + params, + }); +} + // 导师审核报名课题 export function auditPassTask(data) { return fetch({ @@ -249,3 +258,31 @@ export async function findStudentTaskByTaskId(params) { params: params, }); } + +// 返回年月日时间 +export function formatParsedResult(setting, type= "range") { + if(setting && setting[0]){ + const dataMap = setting[0].value.split(','); + const startDate = new Date(dataMap[0]); + const endDate = new Date(dataMap[1]); + + const startYear = startDate.getFullYear(); + const startMonth = startDate.getMonth() + 1; + const startDay = startDate.getDate(); + const startHour = startDate.getHours(); + + const endYear = endDate.getFullYear(); + const endMonth = endDate.getMonth() + 1; + const endDay = endDate.getDate(); + const endHour = endDate.getHours(); + + let result = `${startYear}年${startMonth}月${startDay}日${startHour}点-${endYear}年${endMonth}月${endDay}日${endHour}点`; + if(type === "start"){ + result= `${startYear}年${startMonth}月${startDay}日${startHour}点`; + }else if(type === "end"){ + result= `${endYear}年${endMonth}月${endDay}日${endHour}点`; + } + + return result; + } +} \ No newline at end of file diff --git a/src/glcc/home/index.jsx b/src/glcc/home/index.jsx index 16e0086f..6dde7f5c 100644 --- a/src/glcc/home/index.jsx +++ b/src/glcc/home/index.jsx @@ -22,7 +22,7 @@ import './index.scss'; // period: 项目报名阶段("repoApply") // match:{params:{id=2023}} 注意默认值记得每届修改 export default (props) => { - const { current_user, history, round, match:{params:{id=2023}}, period, showLoginDialog, glccSettings, repoPublic, showMatchingBut, isResultPublic} = props; + const { current_user, history, round, match:{params:{id=2023}}, period, showLoginDialog, glccSettings, repoPublic, showMatchingBut, isResultPublic, hasRole, isMediumExamineByToTutor, checkedTaskId} = props; useEffect(() => { if (!current_user.user_id) { @@ -51,7 +51,7 @@ export default (props) => { */} {/* 往期回顾 */} {round !== 2 &&
- +
考核结果 @@ -123,30 +123,30 @@ export default (props) => {
查看各课题入选学生名单
} - {/* 学生结项考核 */} - {/* {!hasRole && checkedTaskId && + {/* 学生中期考核 */} + {period === "mediumExamine1" && checkedTaskId &&
- 结项考核 + 中期考核
学生提交考核材料
- } */} - {/* 导师结项考核 */} - {/* {hasRole && new Date().getTime() > new Date('2022/10/01 8:0').getTime() && + } + {/* 导师中期考核 */} + {hasRole && isMediumExamineByToTutor &&
- 结项考核 + 中期考核
-
导师拟定结项考核结果
- } */} +
导师拟定中期考核结果
+ } {/* 结项考核结果公示页 */} - {/* { + {period === "mediumExamine3" &&
考核结果
-
结项课题考核结果公示
- } */} +
中期课题考核结果公示
+ }
} {/* */}
diff --git a/src/glcc/img/banner-interim1.png b/src/glcc/img/banner-interim1.png new file mode 100644 index 00000000..457e2796 Binary files /dev/null and b/src/glcc/img/banner-interim1.png differ diff --git a/src/glcc/img/resultBanner4.png b/src/glcc/img/resultBanner4.png new file mode 100644 index 00000000..c56307f3 Binary files /dev/null and b/src/glcc/img/resultBanner4.png differ diff --git a/src/glcc/index.jsx b/src/glcc/index.jsx index d33d0bfa..3b4afac0 100644 --- a/src/glcc/index.jsx +++ b/src/glcc/index.jsx @@ -100,7 +100,8 @@ const Glcc = (propsF) => { const [isMatching, setIsMatching] = useState(false); // 导师-学生配对结果公示阶段 const [isResultPublic, setIsResultPublic] = useState(false); - console.log('isResultPublic', isResultPublic); + // 导师中期考核评审阶段 + const [isMediumExamineByToTutor, setIsMediumExamineByToTutor] = useState(false); useEffect(()=>{ if(id && id === "2022"){ @@ -125,8 +126,11 @@ const Glcc = (propsF) => { // 是否处于导师-学生配对结果公示阶段 const resultPublic = res.data.filter(item=>item.name === "stuPublic"); resultPublic[0] && setIsResultPublic(judge(nowTime, resultPublic[0].value, "range")) + // 是否处于导师中期考核评审阶段 + const mediumExamine2 = res.data.filter(item=>item.name === "mediumExamine2"); + mediumExamine2[0] && setIsMediumExamineByToTutor(judge(nowTime, mediumExamine2[0].value, "range")) // 过滤掉 可并行进行的阶段 - const filterRepoPublic = res.data.filter(item=>["repoPublic", "repoApply1", "matching", "stuPublic"].indexOf(item.name) === -1); + const filterRepoPublic = res.data.filter(item=>["repoPublic", "repoApply1", "matching", "stuPublic", "mediumExamine2"].indexOf(item.name) === -1); const periodIndex = filterRepoPublic.findIndex(item=>judge(nowTime, item.value, "range")); periodIndex !== -1 && setPeriod(filterRepoPublic[periodIndex].name); } @@ -164,17 +168,17 @@ const Glcc = (propsF) => { const [hasRole, setHasRole] = useState(false); useEffect(() => { - // 登录状态+导师-学生配对阶段 - current_user && current_user.user_id && isMatching && hasAuditRole({ userId: current_user.user_id, round: currentRound }).then(res => { + // 登录状态+导师-学生配对阶段/中期审核 + current_user && current_user.user_id && (isMatching || isMediumExamineByToTutor) && hasAuditRole({ userId: current_user.user_id, round: currentRound }).then(res => { if (res && res.message === 'success' && res.data.hasRole) { setHasRole(true); } }) - }, [current_user, isMatching]) + }, [current_user, isMatching, isMediumExamineByToTutor]) useEffect(()=>{ - // 获取用户课题报名信息(todo:学生报名阶段请求) - (period === "stuApply" || period === "stuApply1") && current_user && current_user.login && getStudentApplyInfo({userId: current_user.user_id, round: round}).then(response=>{ + // 获取用户课题报名信息 + (period === "stuApply" || period === "stuApply1" || period === "mediumExamine1") && current_user && current_user.login && getStudentApplyInfo({userId: current_user.user_id, round: round}).then(response=>{ if(response && response.message === "success"){ // setData(response.data.rows); const data = {}; @@ -182,8 +186,9 @@ const Glcc = (propsF) => { response.data && response.data.registrationStudentTaskList.map(item=>{ data[item.taskId] = item.id; item.locked && setLockedTaskName(item.taskName); - item.passStatus && item.mediumExaminationPass && setCheckedTaskId(item.taskId); - item.passStatus && item.mediumExaminationPass && setStudentRegId(item.studentRegId); + // 结项考核: && item.mediumExaminationPass + item.locked && setCheckedTaskId(item.taskId); + item.locked && setStudentRegId(item.studentRegId); // 取当前报名的课题数() if(item.subRound === 1){ data1[item.taskId] = item.id; @@ -308,34 +313,34 @@ const Glcc = (propsF) => { > {/* 中期审核-结果公示 */} - ( )} - > + >} {/* 中期审核-学生 */} - ( - + )} - > + >} {/* 中期审核-导师 */} - ( - + )} - > + >} {/* 首页 */} ( - + )} > @@ -343,7 +348,7 @@ const Glcc = (propsF) => { ( - + )} > diff --git a/src/glcc/interimReview/result.jsx b/src/glcc/interimReview/result.jsx index a32c810d..4aa7536d 100644 --- a/src/glcc/interimReview/result.jsx +++ b/src/glcc/interimReview/result.jsx @@ -3,6 +3,7 @@ import { Input, Table, Tooltip, Checkbox } from 'antd'; import { getMediumTermExamineInfoList } from '../api'; import ProjectDetail from '../project/component/projectDetail'; import resultBanner from "../img/resultBanner3.png"; +import resultBanner1 from "../img/resultBanner4.png"; import bgPng from "../img/bgPng.png"; import './index.scss'; import '../checkResult/index.scss'; @@ -11,7 +12,7 @@ import '../project/index.scss'; const { Search } = Input; // 课题列表 -function CheckResult({current_user, history, round, id}) { +function CheckResult({round, id}) { // 输入搜索框 const [keyword, setKeyword] = useState(undefined); const [data, setData] = useState([]); @@ -29,7 +30,7 @@ function CheckResult({current_user, history, round, id}) { curPage: current, keyword, pageSize, - term: 2, + term: id === "2023" ? 1 : 2, round } getMediumTermExamineInfoList(params).then(response => { @@ -97,10 +98,10 @@ function CheckResult({current_user, history, round, id}) { return (
- +
-
开源夏令营 / 结项课题考核结果公示
+
开源夏令营 / {id === "2023" ? '中期' : '结项'}课题考核结果公示
{ setCurrent(1); setKeyword(value) }} />
diff --git a/src/glcc/interimReview/studentSubmit.jsx b/src/glcc/interimReview/studentSubmit.jsx index 75974551..ff4619b2 100644 --- a/src/glcc/interimReview/studentSubmit.jsx +++ b/src/glcc/interimReview/studentSubmit.jsx @@ -2,28 +2,37 @@ import React, { useEffect, useState } from "react"; import { Form, Upload, Input, Icon, Button, message, Modal } from "antd"; import { Link } from "react-router-dom"; 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} from '../api'; +import {getMediumTermExamineInfo, submitMedium, formatParsedResult} from '../api'; import './index.scss'; function StudentSubmit(props){ - const {form, checkedTaskId, studentRegId, history} = props; + const {form, checkedTaskId, studentRegId, period, currentRound, glccSettings, isMediumExamineByToTutor} = props; + const mediumExamine = glccSettings && glccSettings.filter(item=>item.name === "mediumExamine1"); + const mediumExamine2 = glccSettings && glccSettings.filter(item=>item.name === "mediumExamine2"); + let overtime = false; + if(mediumExamine2 && mediumExamine2[0]){ + 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]; + } 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 submitTime = new Date().getTime() < new Date('2022/10/17 24:0').getTime(); - // 学生提醒导师评分时间 - const lookTime = new Date().getTime() > new Date('2022/10/15 0:0').getTime() && new Date().getTime() < new Date('2022/10/23 24:0').getTime(); useEffect(()=>{ // 查询是否已经提交考核材料 - checkedTaskId && getMediumTermExamineInfo(checkedTaskId,{term: 2}).then(res=>{ + checkedTaskId && getMediumTermExamineInfo(checkedTaskId,{round: currentRound, term: period === "mediumExamine1" ? 1 : 2}).then(res=>{ if(res && res.message === "success"){ setDetail(res.data); } @@ -37,18 +46,19 @@ function StudentSubmit(props){ validateFieldsAndScroll((err, values) => { if(!err){ Modal.confirm({ - title: "确认提交结项考核材料?", + title: `确认提交${period === "mediumExamine1" ? '中期' : '结项'}考核材料?`, content: "提交后将无法修改考核材料,请进行二次确认", onOk: ()=>{ const {pptAttachment, defenceVideoUrl, codeOrPrUrl} = values; - const pptAttachmentId = pptAttachment.file.response.data.id; + const pptAttachmentId = pptAttachment.file && pptAttachment.file.response && pptAttachment.file.response.data.id; const params = { pptAttachmentId, codeOrPrUrl, defenceVideoUrl, taskId: checkedTaskId, studentRegId: studentRegId, - term: 2 + round: currentRound, + term: period === "mediumExamine1" ? 1 : 2 } submitMedium(params).then(res=>{ if(res && res.message === "success"){ @@ -72,30 +82,38 @@ function StudentSubmit(props){ } }) } - // 检查文件上传是否符合规定 + function changeFileList(e) { - const {fileList} = e; - const lastFile = fileList.splice(fileList.length-1, fileList.length); - setFileList(lastFile); + const {file} = e; + file && file.status && setFileList([file]); + } + + // 检查文件上传是否符合规定 + function beforeUpload(file){ + const isLt100M = file.size / 1024 / 1024 < 100; + if (!isLt100M) { + message.error(`文件大小必须小于${100}MB!`); + } + return isLt100M; } return
- +
-
开源夏令营 / 提交结项考核材料
+
开源夏令营 / 提交{period === "mediumExamine1" ? '中期' : '结项'}考核材料
材料提交说明:
-
1、请各位学生下载PPT模板 ,根据课题开发进展,按照PPT模板要求填写课题学习调研方案、开发进度及开发成果等考核材料;
+
1、请各位学生下载PPT模板 ,根据课题开发进展,按照PPT模板要求填写课题学习调研方案、开发进度及开发成果等考核材料;
2、欢迎各位学生录制本课题答辩视频,将视频链接填写至下方视频介绍填写栏;
-
3、学生提交考核材料的时间为2022年10月1日8点至2022年10月14日24点,请在截止时间前提交;
+
3、学生提交考核材料的时间为{formatParsedResult(mediumExamine)},请在截止时间前提交;
4、若导师已给出评分,各位学生可在此页面查看自己的结项考核成绩。对考核成绩有异议的学生请及时联系您的导师。
- 结项考核 + {period === "mediumExamine1" ? '中期' : '结项'}考核
- {submitTime && !detail ?
+ {period === "mediumExamine1" && !detail ? {getFieldDecorator('defenceVideoUrl', { rules: [{ required: true, message: '请输入视频链接!'}, {pattern: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/,message: "请正确输入链接"}], @@ -109,7 +127,7 @@ function StudentSubmit(props){ {getFieldDecorator('pptAttachment', { rules: [{ required: true, message: '请上传PPT附件!' }], - })( + })( )} @@ -122,8 +140,8 @@ function StudentSubmit(props){
   PPT附件{detail && }{detail ? {`${detail.pptAttachment.fileName}`} : }{detail && detail.pptAttachment && detail.pptAttachment.fileSizeString}
{!detail &&
很遗憾,您在指定时间内未提交考核材料
} - {detail && lookTime && !detail.glccTutorEvaluation &&
您的课题导师暂未评分,请提醒导师尽快提交结项考核评分
} - {detail && new Date().getTime() > new Date('2022/10/24 10:0').getTime() && !detail.glccTutorEvaluation &&
很遗憾,您的导师尚未评分,您未通过结项考核
} + {detail && isMediumExamineByToTutor && !detail.glccTutorEvaluation &&
您的课题导师暂未评分,请提醒导师尽快提交结项考核评分
} + {detail && overtime && !detail.glccTutorEvaluation &&
很遗憾,您的导师尚未评分,您未通过结项考核
} {detail && detail.glccTutorEvaluation &&
您的课题导师对您的结项考核评价如下,如有异议,请及时联系导师进行更改。
diff --git a/src/glcc/interimReview/tutorReview.jsx b/src/glcc/interimReview/tutorReview.jsx index 0820ce2a..c0636232 100644 --- a/src/glcc/interimReview/tutorReview.jsx +++ b/src/glcc/interimReview/tutorReview.jsx @@ -2,7 +2,7 @@ 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 { getLockedAuditList, getMediumTermExamineInfo, submitTutorEvaluation, updateTutorEvaluation, hasAuditRole, formatParsedResult } from '../api'; import './index.scss'; import '../check/index.scss' import Nodata from "../../forge/Nodata"; @@ -11,7 +11,7 @@ const { TabPane } = Tabs; const { TextArea } = Input; function TutorReview(props){ - const {form, current_user, showNotification, history} = props; + const {form, current_user, showNotification, history, hasRole, isMediumExamineByToTutor, currentRound, glccSettings} = props; const {getFieldDecorator, setFieldsValue, validateFieldsAndScroll, resetFields } = form; const [taskId, setTaskId] = useState(); const [taskList, setTaskList] = useState([]); @@ -22,20 +22,15 @@ function TutorReview(props){ const [isEdit, setIsEdit] = useState(false); // 导师提交信息之后按钮置灰(确保无重复提交) const [disabled, setDisabled] = useState(false); - + const mediumExamine2 = glccSettings && glccSettings.filter(item=>item.name === "mediumExamine2"); + const mediumExamine3 = glccSettings && glccSettings.filter(item=>item.name === "mediumExamine3"); useEffect(() => { - if(!new Date().getTime() > new Date('2022/10/01 8:0').getTime()){ + if(!isMediumExamineByToTutor || !hasRole){ history.push("/glcc"); }else if (!current_user.login) { - history.push('/login?go_page=/glcc/final/examination'); - }else{ - hasAuditRole({ userId: current_user.user_id }).then(res => { - if (!(res && res.message == 'success' && res.data.hasRole)) { - history.push('/glcc'); - } - }) + history.push('/login?go_page=/glcc/middle/examination'); } - getAuditList({ userId: current_user.user_id, pass: 1 }).then(res => { + getLockedAuditList({ userId: current_user.user_id, pass: 1, round: currentRound }).then(res => { if (res.message === 'success') { const filterStuNull = res.data.rows.filter(item=>{return item.studentName !== null}) setTaskList(filterStuNull); @@ -48,7 +43,8 @@ function TutorReview(props){ useEffect(()=>{ // 查询是否已经提交考核材料 - taskId && getMediumTermExamineInfo(taskId,{term: 2}).then(res=>{ + // 结项考核 + taskId && getMediumTermExamineInfo(taskId,{round: currentRound, term: isMediumExamineByToTutor ? 1 : 2}).then(res=>{ if(res && res.message === "success"){ setDetail(res.data); if(res && res.data && res.data.glccTutorEvaluation){ @@ -69,7 +65,8 @@ function TutorReview(props){ ...values, mediumTermExamineMaterialId: detail.id, tutorUserId: detail.studentRegId, - term: 2 + round: currentRound, + term: isMediumExamineByToTutor ? 1 : 2 } if(detail.glccTutorEvaluation){ params['id'] = detail.glccTutorEvaluation.id; @@ -88,6 +85,8 @@ function TutorReview(props){ } }) } + }else{ + setDisabled(false); } }) } @@ -116,9 +115,13 @@ function TutorReview(props){
导师考核说明:
1、请各位导师从“工作态度”“开发进度”“项目完成质量”“总体评分”四个角度,根据学生提交的考核材料与实际开发情况客观地进行打分。打分标准分为:S:特别优秀、A:优秀、B:良好、C:合格、D:不合格五个等级。
-
2、“总体评分”这一项将决定学生是否通过本次考核。若总体评分为“S、A、B、C”,则视为通过结项考核。若该结果为“D”,则该课题结项考核不通过,不予发放结项奖金。请各位导师谨慎做出评价。
+
2、“总体评分”这一项将决定学生是否通过本次考核。若总体评分为“S、A、B、C”,则视为通过中期考核。若该结果为“D”,则该课题中期考核不通过,课题将自动终止。请各位导师谨慎做出评价。
+
3、导师提交打分结果后,可对考核结果进行更改,更改考核结果截止日期为{mediumExamine2 && formatParsedResult(mediumExamine2, 'end')}
+
4、北京时间{mediumExamine3 && formatParsedResult(mediumExamine3, "start")}前GLCC官网将公布中期考核结果,敬请留意。
+ {/* 结项考核文案 */} + {/*
2、“总体评分”这一项将决定学生是否通过本次考核。若总体评分为“S、A、B、C”,则视为通过结项考核。若该结果为“D”,则该课题结项考核不通过,不予发放结项奖金。请各位导师谨慎做出评价。
3、导师提交打分结果后,可对考核结果进行更改,期间考核结果也将实时反馈给学生;更改考核结果截止时间为2022年10月20日24点
-
4、北京时间2022年10月24日20点前GLCC官网将公布结项考核结果,敬请留意。
+
4、北京时间2022年10月24日20点前GLCC官网将公布结项考核结果,敬请留意。
*/}
{ resetFields(); setTaskId(e); setIsEdit(false); setWordNum(0); setDisabled(false);}} activeKey={taskId + ''}> @@ -175,7 +178,7 @@ function TutorReview(props){
{wordNum} / 2000
{/* 导师结项考核时间为true */} - {false && + {isMediumExamineByToTutor && {(!detail.glccTutorEvaluation || (detail.glccTutorEvaluation && isEdit)) && } {detail.glccTutorEvaluation && !isEdit && } }