diff --git a/src/forge/Issues/Component/comments/list.scss b/src/forge/Issues/Component/comments/list.scss index 0d54ede8..6230b613 100644 --- a/src/forge/Issues/Component/comments/list.scss +++ b/src/forge/Issues/Component/comments/list.scss @@ -106,6 +106,7 @@ } .commentContentBox{ display: flex; + align-items: flex-start; } .commentContentRight{ flex: 1; diff --git a/src/glcc/api.js b/src/glcc/api.js index f15c7a95..e86f2a6f 100644 --- a/src/glcc/api.js +++ b/src/glcc/api.js @@ -45,8 +45,7 @@ export function studentApplyEdit(data) { }); } -// 获取当前学生用户报名信息 -// 课题列表 +// 项目列表 export function projectList(params) { return fetch({ url: `/api/applyInformation/list`, @@ -55,6 +54,15 @@ export function projectList(params) { }); } +// 0元项目列表 +export function freeProjectList(params) { + return fetch({ + url: `/api/applyInformation/projectListFor0`, + method: 'get', + params + }); +} + // 课题列表 export function taskList(params) { return fetch({ @@ -64,6 +72,15 @@ export function taskList(params) { }); } +// 0元课题列表 +export function freeTaskList(params) { + return fetch({ + url: `/api/applyInformation/taskListFor0`, + method: 'get', + params + }); +} + // 项目id查询项目详情 export function getProjectById(id, params) { return fetch({ @@ -222,4 +239,13 @@ export function deleteApplyInfo(data) { method: 'post', data }); -} \ No newline at end of file +} + +// 判断课题是否有学生报名 +export async function findStudentTaskByTaskId(params) { + return await fetch({ + url: '/api/applyInformation/findStudentTaskByTaskId', + method: 'get', + params: params, + }); +} diff --git a/src/glcc/apply/editInfo.jsx b/src/glcc/apply/editInfo.jsx index b9198b41..b9b836e4 100644 --- a/src/glcc/apply/editInfo.jsx +++ b/src/glcc/apply/editInfo.jsx @@ -1,7 +1,7 @@ import React , { useCallback, useEffect , useState } from 'react'; import { Button, Form, Input, Select, Upload, message, Popconfirm } from 'antd'; import {getUploadActionUrl} from 'educoder'; -import {applyGlcc, updateApplyGlcc} from '../api'; +import {applyGlcc, findStudentTaskByTaskId, updateApplyGlcc} from '../api'; import TextArea from 'antd/lib/input/TextArea'; import { main_site_url } from '../fetch'; import TaskApply from './taskApply'; @@ -13,7 +13,7 @@ function EditRepoApplyInfo(props) { const {form, applyInfo, current_user, round, cateList, setReload, isAddRepo, setIsAddRepo, setIsEdit, setEditRepoCount} = props; const phonereg = /(^|\s*\+?0?0?86|\D)(1\d{2})[-\s]{0,3}(\d{4})[-\s]{0,3}(\d{4})(?=\D|$)/ const emailreg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ - const {getFieldDecorator, validateFields, setFieldsValue, validateFieldsAndScroll } = form; + const {getFieldDecorator, validateFields, setFieldsValue, validateFieldsAndScroll, getFieldValue } = form; const [imageUrl, setImageUrl] = useState(undefined); // 提交按钮loading效果 const [loading, setLoading] = useState(false); @@ -27,7 +27,7 @@ function EditRepoApplyInfo(props) { const taskCountArr = [] registrationTaskList.map((item, index)=>{ taskCountArr.push(index+1); - const{taskName, taskUrl, taskDifficulty, taskReward, tutorName, tutorMail, taskDesc, tutorPhone} = item; + const{taskName, taskUrl, taskDifficulty, taskReward, tutorName, tutorMail, taskDesc, tutorPhone, id} = item; taskInfo[`taskName${index+1}`] = taskName; taskInfo[`taskUrl${index+1}`] = taskUrl; taskInfo[`taskDifficulty${index+1}`] = taskDifficulty; @@ -36,6 +36,7 @@ function EditRepoApplyInfo(props) { taskInfo[`tutorMail${index+1}`] = tutorMail; taskInfo[`taskDesc${index+1}`] = taskDesc; taskInfo[`tutorPhone${index+1}`] = tutorPhone; + taskInfo[`taskId${index+1}`] = id; }) setTaskCount(taskCountArr); setTimeout(() => { @@ -76,6 +77,7 @@ function EditRepoApplyInfo(props) { const registrationTaskList = [] taskCount && taskCount.map(item=>{ registrationTaskList.push({ + id: values[`taskId${item}`], taskName: values[`taskName${item}`], taskUrl: values[`taskUrl${item}`], taskDifficulty: values[`taskDifficulty${item}`], @@ -157,14 +159,19 @@ function EditRepoApplyInfo(props) { // 添加课题输入框 function addTaskApplyForm(){ - setTaskCount(taskCount.concat([taskCount.length+1])); + setTaskCount(taskCount.concat([taskCount[taskCount.length-1]+1])); } // 删除课题报名 - function deleteTaskApply(index){ - const arr = [...taskCount]; - arr.splice(index-1, 1) - setTaskCount(arr); + async function deleteTaskApply(index){ + const delTaskId = getFieldValue(`taskId${index}`); + const res = delTaskId ? await findStudentTaskByTaskId({ taskId: delTaskId }) : "newTask"; + if((res && res.data && res.data.length)){ + message.error("已有学生报名,不允许删除"); + }else{ + const arr = taskCount.filter(item=>item!== index); + setTaskCount(arr); + } } // 取消编辑点击函数 @@ -267,7 +274,7 @@ function EditRepoApplyInfo(props) {
课题信息({index+1}/5)
{index>0 && } - + })} {taskCount && taskCount.length<5 &&
diff --git a/src/glcc/apply/index.jsx b/src/glcc/apply/index.jsx index c30ce005..7ee5d178 100644 --- a/src/glcc/apply/index.jsx +++ b/src/glcc/apply/index.jsx @@ -75,7 +75,7 @@ function Apply(props) {

申请说明

1、项目报名时间为4月29日—5月30日,请在报名截止时间(北京时间2023年5月30日24点)前提交报名信息。
-
2、本次GLCC夏令营建议使用GitLink为代码托管平台,学生基于GitLink上项目完成编程任务。同时也欢迎使用其他代码托管平台的项目参与活动。目前GLCC只对夏令营期间使用GitLink托管的项目提供部分资金支持。
+
2、本次GLCC夏令营建议使用GitLink为代码托管平台,学生基于GitLink上项目完成编程任务。同时也欢迎使用其他代码托管平台的项目参与活动。目前GLCC只对夏令营期间使用GitLink托管的项目提供部分奖金支持。
3、如果您的项目还未迁移到GitLink上,迁移事项请查看迁移说明文档。如在迁移过程中遇到问题,请加qq群: 1071514693 联系qq群管理员。
4、提交社区和题目信息后,欢迎与组委会联系沟通宣传推广和后续合作工作。联系人微信: _TigerWang(备注GitLink编程夏令营)
5、奖金默认由项目方支持,请根据课题难度设定金额。若您可能无法支撑本课题奖金,GLCC组委会将进行资助评审,择优资助。如未获得资助,将下线该课题
diff --git a/src/glcc/apply/taskApply.jsx b/src/glcc/apply/taskApply.jsx index a263f9bd..86ed6c5f 100644 --- a/src/glcc/apply/taskApply.jsx +++ b/src/glcc/apply/taskApply.jsx @@ -4,7 +4,7 @@ import TextArea from 'antd/lib/input/TextArea'; const Option = Select.Option; // 课题信息编辑 function TaskApply(props) { - const {helper, disabled, taskKey, phonereg, emailreg} = props; + const {helper, disabled, taskKey, phonereg, emailreg, getFieldDecorator} = props; // 低、中、高 const difficultyList = [ {id: 1, name: "低"}, @@ -26,6 +26,9 @@ function TaskApply(props) { return(
+ {helper('课题名称', '', `taskName${taskKey}`, diff --git a/src/glcc/check/index.jsx b/src/glcc/check/index.jsx index 74ab5162..76c10ff7 100644 --- a/src/glcc/check/index.jsx +++ b/src/glcc/check/index.jsx @@ -131,9 +131,9 @@ function Check({ current_user, showNotification, currentRound }) { {record.locked && !record.used && } {/* 学生已经被其他导师锁定 */} {record.locked && record.used && } - {/* 学生未被锁定 */} - {!record.locked && !record.used && (text ? : - )} + {/* 导师邮箱与系统绑定邮箱进行判断 + 学生未被锁定 */} + {record.tutorMail === current_user.email && (!record.locked && !record.used && (text ? : + ))}
) }) diff --git a/src/glcc/checkResult/index.jsx b/src/glcc/checkResult/index.jsx index 5b31d1a8..de5a9d2c 100644 --- a/src/glcc/checkResult/index.jsx +++ b/src/glcc/checkResult/index.jsx @@ -2,8 +2,6 @@ import React, { useEffect, useState } from 'react'; import { Input, Table, Tooltip } from 'antd'; import { getPassList, hasAuditRole } from '../api'; import ProjectDetail from '../project/component/projectDetail'; -// 预公示banner -import resultBanner from "../img/resultBanner.png"; // 公示banner import resultBanner2 from "../img/resultBanner2.png"; import bgPng from "../img/bgPng.png"; @@ -12,7 +10,7 @@ import '../project/index.scss'; const { Search } = Input; // 课题列表 -function CheckResult({current_user, history}) { +function CheckResult({current_user, history, round}) { // 输入搜索框 const [keyword, setKeyword] = useState(undefined); const [data, setData] = useState([]); @@ -22,7 +20,6 @@ function CheckResult({current_user, history}) { 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(()=>{ // 未到时间 @@ -44,6 +41,7 @@ function CheckResult({current_user, history}) { curPage: current, keyword, pageSize, + round } getPassList(params).then(response => { if (response && response.message === "success") { @@ -58,9 +56,9 @@ function CheckResult({current_user, history}) { { 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: 'school', className:"columnsResult taskName", width: '12%', ellipsis: true,render: (text) => {text}}, - { title: '学生专业', dataIndex: 'profession', className:"columnsResult taskName", width: '12%', ellipsis: true, render: (text) => {text}}, + { title: '学生专业', dataIndex: 'profession', className:"columnsResult taskName", width: '12%', ellipsis: true, render: (text) => {text || '-'}}, { 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: 'taskName', className:"columnsResult", width: '20%', ellipsis: true, render: (text, item) => {window.open(`/glcc/2023/subjects/detail/${item.taskId}`)}}>{text} }, { title: '项目名称', dataIndex: 'projectName', className:"columnsResult", ellipsis: true, width: '14%', render: (text) => {text} }, { title: '操作', dataIndex: 'action', align: 'center', className:"columnsResult actionBox"}, ] @@ -107,11 +105,10 @@ function CheckResult({current_user, history}) { return (
- {time && } - {new Date().getTime() > new Date('2022/07/01 12:0').getTime() && } +
-
开源夏令营 / 入选学生名单{time && '预'}公示
+
开源夏令营 / 入选学生名单公示
{ setCurrent(1); setKeyword(value) }} /> { + const [info, setInfo] = useState(detail); + + useEffect(()=>{ + if(!detail && projectId){ + // 通过项目Id查询项目详情 + getProjectById(projectId, {round: 2, isFree: true}).then(response=>{ + if(response && response.message === 'success'){ + setInfo(response.data) + } + }) + } + },[detail]) + + return ( + info ?
+
+ {info.projectName} + {info.projectType && {info.projectType}} +

GitLink项目地址:  {info.gitlinkUrl}

+
项目简介:  {info.projectIntro}
+
+ {/* 课题列表 */} + {info.registrationTaskList && info.registrationTaskList.length ? info.registrationTaskList.map((item, index)=>{ + return
+
+
{item.taskName}
+
导师姓名:   {item.tutorName}
+ {item.tutorMail &&
邮箱地址:   {item.tutorMail}
} +
+
+
{item.taskDesc}
+ {item.taskUrl &&
课题链接:   {item.taskUrl}
} +
+
+
¥{item.taskReward}
+
+ }) : } +
:
+ ) +} \ No newline at end of file diff --git a/src/glcc/freeProject/index.jsx b/src/glcc/freeProject/index.jsx new file mode 100644 index 00000000..5c433b74 --- /dev/null +++ b/src/glcc/freeProject/index.jsx @@ -0,0 +1,66 @@ +import React from 'react'; +import { Spin } from 'antd'; +import { Route, Switch } from "react-router-dom"; +import banner from "../img/studentProject2.png"; +import './index.scss'; +import Loadable from "react-loadable"; +import Loading from "../../Loading"; +import { Link } from 'react-router-dom'; +import { useEffect } from 'react'; + +// 项目列表页面 +const ProjectList = Loadable({ + loader: () => import("./projectList"), + loading: Loading, +}); +// 课题列表页面 +const TaskList = Loadable({ + loader: () => import("./taskList"), + loading: Loading, +}); + +function FreeProject(propsF) { + const {location: {pathname}} = propsF; + useEffect(()=>{ + window.scrollTo(0, 0); + },[]) +console.log('FreeProject'); + return( +
+
+ +
+
+ 课题列表 + 项目列表 +
+
+ 开源夏令营 / + 无奖金课题及项目列表 +
+
+

申请说明:

+
1、参与GitLink编程夏令营无奖金项目的同学,请通过邮件或电话与课题导师直接沟通并根据导师课题要求完成课题,无需在GLCC平台报名课题
+
2、参与GitLink编程夏令营无奖金项目的同学,如完成课题并经导师评定通过,将会在GLCC官网进行公示(无奖金奖励)。
+
3、活动最终解释权归GLCC所有。
+
+ + + ( + + )} + > + ( + + )} + > + + +
+ ) +} +export default FreeProject; \ No newline at end of file diff --git a/src/glcc/freeProject/index.scss b/src/glcc/freeProject/index.scss new file mode 100644 index 00000000..b9551b81 --- /dev/null +++ b/src/glcc/freeProject/index.scss @@ -0,0 +1,229 @@ +.glcc_project{ + background-color: #ebf2ff; + .head{ + background-color:rgba(188, 208, 255, 0.27); + border:1px solid #ffffff; + text-align: center; + a{ + padding: 18px 20px 20px; + display: inline-block; + color: #273778; + font-size: 18px; + font-weight:700; + line-height: 30px; + &.active{ + border-bottom: 1px solid #5474df;; + } + &:last-child{ + margin-left: 40px; + } + } + } + .gobackBox{ + width: 1200px; + margin: 0 auto; + padding: 25px 0 12px; + color: #202d40; + font-size: 16px; + border-bottom: 1px dashed #bec5d5; + a{ + color:#a4aabb; + } + } + .listBox{ + background-image:linear-gradient(180deg,#ebf2ff 0%,#ebf2ff 43.09%,#f3f4f8 100%); + position: relative; + .bgPng3, .bgPng4{ + width: 146px; + position: absolute; + z-index: 0; + top: 162px; + left: 100px; + } + .bgPng4{ + top: 450px; + left: auto; + right: 310px; + } + } +} +.glcc-banner { + width: 100%; +} +// 项目详情框 +.projectDetailBox{ + &.byTask{ + background-image:linear-gradient(180deg,#f1f5ff 0%,#ffffff 100%); + border:1px solid #ffffff; + border-radius:4px; + box-shadow:0px 0px 10px rgba(100, 141, 255, 0.2); + padding: 30px 30px 50px; + .taskItem{ + .center{ + width: 640px; + } + } + } + &.nodata{width: 200px;} + font-size:15px; + line-height:30px; + .projectDetailHead{ + color:#465474; + padding-bottom: 12px; + border-bottom: 1px dashed #bec5d5; + line-height: 36px; + &.byResult{ + margin: -15px -10px -40px; + border-bottom: none; + } + .name{ + font-weight:700; + color:#3753c5; + font-size:20px; + } + .type{ + display: inline-block; + border:1px solid #6680bb; + border-radius:4px; + margin-left: 12px; + padding: 4px 6px; + line-height: 26px; + } + .linkUrl{ + color: #466aff; + } + } + .taskItem { + display: flex; + justify-content: space-between; + border:1px solid #ffffff; + &:hover{ box-shadow: 0px 0px 12px rgba(71, 105, 198, 0.4);} + .oneLine{ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .left{ + width: 316px; + background-image: url('../img/projectDetailTaskBg.png'); + background-size: 100% 100%; + padding: 22px 20px; + color:#25304a; + .taskTitle{ + color:#1834a7; + font-size:18px; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + text-overflow: ellipsis; + } + .email span{color:#466aff;} + .leftWidth{width: 270px;} + } + .center{ + width: 665px; + text-align: left; + padding: 20px; + display: flex; + flex-direction: column; + justify-content: space-between; + .taskDesc{ + color:#6b6b6b; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + text-overflow: ellipsis; + } + .taskUrl{ + color:#465474; + font-size:16px; + line-height: 28px; + margin-bottom: 5px; + a{color:#466aff;} + } + .applyBut{ + background-color:#466aff; + border-color: #466aff; + &:hover{background-color:#5d7cff;} + &:focus{background-color:#1140ff;} + } + .taskReward{color:#ff8800;} + } + .right{ + margin-top: 35px; + padding-right: 10px; + width: 120px; + font-weight:700; + color:#ff8800; + font-size:24px; + } + } +} +.ant-popover.projectItemPopover{ + width: 1200px; + z-index: 1000; + .ant-popover-content .ant-popover-arrow{ + border-width: 12px; + } +} +.projectItemPopover .ant-popover-inner{ + transform: translateY(8px); + background-image:linear-gradient(180deg,#f1f5ff 0%,#ffffff 100%); + border:1px solid #ffffff; + border-radius:4px; + box-shadow:0px 0px 10px rgba(100, 141, 255, 0.2); + .ant-popover-inner-content{ + padding: 30px 30px 50px; + } +} +.lookDetail{ + border-color: #466aff; + color: #466aff; + &:hover{ + border-color: #5d7cff; + color: #5d7cff; + } + &:focus{ + border-color: #1140ff; + color: #1140ff; + } +} +.projectBannerBox{ + position: relative; + .stuApplytimeBox{ + background-image: url('../img/studentProject1.png'); + position: absolute; + color: #FFDC95; + font-size: 20px; + bottom: 28%; + left: 50%; + margin-left: -250px; + width: 500px; + height: 60px; + line-height: 60px; + text-align: center; + background-size: 100% 100%; + } +} +.head_introduce { + width: 1200px; + margin: 0 auto; + background: #e4edff; + padding: 20px; +} +.head_tit { + color: #000000; + font-size: 15px; + line-height: 2; +} +.head_content { + color: #6c7283; + font-size: 14px; + line-height: 38px; +} +.head_bold { + font-weight: 700; + color: #333; +} \ No newline at end of file diff --git a/src/glcc/freeProject/projectList/index.jsx b/src/glcc/freeProject/projectList/index.jsx new file mode 100644 index 00000000..a10f15f7 --- /dev/null +++ b/src/glcc/freeProject/projectList/index.jsx @@ -0,0 +1,75 @@ +import React, { useEffect, useState } from 'react'; +import { Input, Popover, Spin } from 'antd'; +import { main_site_url } from '../../fetch'; +import './index.scss'; +import { freeProjectList, projectList } from '../../api'; +import ProjectDetail from '../component/projectDetail'; +import bgPng from "../../img/bgPng.png"; +import logo from "../../img/logo.png"; +import star from "../../img/star.png"; +import Nodata from '../../../forge/Nodata'; +const { Search } = Input; + +// 项目列表 +function ProjectList() { + const [data, setData] = useState([]); + const [loading, setLoading] = useState(false); + + useEffect(() => { + setLoading(true); + const params = { + curPage: 1, + pageSize: 10000, + round: 2 + } + freeProjectList(params).then(response => { + if (response && response.message === "success") { + setData(response.data.rows); + } + setLoading(false); + }) + }, []) + + // 修改taskList盒子的高度,防止弹框过高影响整体页面 + function changeVisible(visible, item) { + if (visible) { + let height = document.documentElement.clientWidth / 1920 * 500 + 70 + document.querySelector(`.${item.gitlinkLastUrl}`).offsetTop + item.registrationTaskList.length * 320; + document.querySelector('#taskList').style.height = height + 'px'; + } else { + document.querySelector('#taskList').style.height = 'auto'; + } + } + + return ( +
+ +
+ {data && data.map((item, index) => { + return { changeVisible(visible, item) }} + key={index} + placement={(index + 1) % 3 === 0 ? 'bottomRight' : (index + 1) % 3 % 2 === 0 ? 'bottom' : 'bottomLeft'} + content={} + trigger='click' + overlayClassName='projectItemPopover' + autoAdjustOverflow={false} + > +
+
+
+ +
+
{item.projectName}
+
{item.projectIntro}
+
+
+ })} +
+ {data && !data.length &&
} +
+ + +
+ ) +} +export default ProjectList; \ No newline at end of file diff --git a/src/glcc/freeProject/projectList/index.scss b/src/glcc/freeProject/projectList/index.scss new file mode 100644 index 00000000..e2a12910 --- /dev/null +++ b/src/glcc/freeProject/projectList/index.scss @@ -0,0 +1,85 @@ +.projectListBox{ + width: 1200px; + margin: 0 auto; + position: relative; + z-index: 1; + display: flex; + flex-wrap: wrap; + // justify-content: space-between; + .projectItem{ + position: relative; + width: 30%; + background-image: linear-gradient(180deg,rgba(232, 237, 255, 0.85) 0%,rgba(255, 255, 255, 0.85) 100%); + border: 1px solid; + border-color: #ffffff; + border-radius: 4px; + box-shadow:0px 0px 8px rgba(93, 131, 255, 0.26); + text-align: center; + margin-bottom: 50px; + background-image: url('../../img/projectBg.png'); + background-size: 100% 100%; + margin-left: 5%; + &.firstBox{ + margin-left: 0; + } + &:hover{ + cursor: pointer; + background-image: none; + // #E8EDFF—#FFFFFF(85%) + background-image: linear-gradient(180deg,rgba(232, 237, 255, 0.85) 0%,rgba(255, 255, 255, 0.85) 100%); + } + .border{ + height: 5px; + background-color:#657edf; + border-radius:2px 2px 0px 0px; + } + .projectLogoStar{ + position: absolute; + top:30px; + right: 130px; + width: 28px; + z-index: 10; + transform: rotate(46deg); + } + .projectLogo{ + position: relative; + width: 100px; + height: 100px; + border: 1px solid #fff; + background-color: #fff; + border-radius: 50%; + text-align: center; + overflow: hidden; + margin: 25px auto 10px; + line-height: 95px; + .projectLogoImg{ + width: 100%; + // height: 100%; + // display: block; + } + + } + .title{ + color:#2a51bf; + font-size:17px; + line-height:30px; + margin-bottom: 15px; + padding: 0 50px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .intro{ + color:#4f5d84; + font-size:15px; + margin-bottom: 15px; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + text-overflow: ellipsis; + text-align: left; + padding: 0 14px; + } + } +} \ No newline at end of file diff --git a/src/glcc/freeProject/taskList/index.jsx b/src/glcc/freeProject/taskList/index.jsx new file mode 100644 index 00000000..10925832 --- /dev/null +++ b/src/glcc/freeProject/taskList/index.jsx @@ -0,0 +1,106 @@ +import React, { useEffect, useState } from 'react'; +import { Table, Tooltip } from 'antd'; +import './index.scss'; +import { freeTaskList, taskList } from '../../api'; +import ProjectDetail from '../component/projectDetail'; +import bgPng from "../../img/bgPng.png"; + +// 课题列表 +function TaskList() { + 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 columns = [ + { title: '序号', dataIndex: 'index', align: 'center', className:"taskTableColumns", width: '6%', render: (text, item, index) => {(current-1)*pageSize+index + 1} }, + { title: '课题名称', dataIndex: 'taskName', className:"taskTableColumns taskName", width: '28%', ellipsis: true, render: (text, item) => {text} }, + { title: '课题类型', dataIndex: 'projectType', className:"taskTableColumns", width: '12%', ellipsis: true, }, + { title: '项目名称', dataIndex: 'projectName', className:"taskTableColumns", width: '24%', ellipsis: true, render: (text) => {text} }, + { title: '课题奖金', dataIndex: 'taskReward', className:"taskTableColumns", ellipsis: true, width: '10%', render: (text) => {text} }, + { title: '操作', dataIndex: 'action', align: 'center', className:"actionColumns taskTableColumns"}, + ] + + 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); + } + + useEffect(() => { + setExpandedRowKeys([]); + setLoading(true); + const params = { + curPage: current, + pageSize, + round: 2 + } + freeTaskList(params).then(response => { + if (response && response.message === "success") { + setData(response.data.rows); + setTotal(response.data.total); + } + setLoading(false); + }) + }, [current, pageSize]) + + return ( +
+
+
+ + + + + ) +} +export default TaskList; \ No newline at end of file diff --git a/src/glcc/freeProject/taskList/index.scss b/src/glcc/freeProject/taskList/index.scss new file mode 100644 index 00000000..f1c77ad7 --- /dev/null +++ b/src/glcc/freeProject/taskList/index.scss @@ -0,0 +1,116 @@ +.taskList{ + padding-bottom: 50px; + .ant-table{ + border: 1px solid white; + } + .ant-pagination-item-active, .ant-pagination-item:hover, .ant-pagination-next:not(.ant-pagination-disabled) .ant-pagination-item-link:hover, .ant-select-selection:hover, .ant-pagination-options-quick-jumper:hover input{ + border-color: #466aff; + a{color: #466aff;} + } + .ant-pagination-disabled .ant-pagination-item-link:hover .anticon{ + color: rgba(0, 0, 0, 0.25); + } + .listTable{ + width: 1200px; + margin: 0 auto; + position: relative; + z-index: 1; + } +} +.taskTableColumns span div span{ + font-size: 16px; + font-weight:700; + color:#273778; +} +.taskTableColumns span{ + font-size: 15px; + color: #353f5e; +} +.ant-table-tbody .taskTableColumns.taskName span{ + color: #2545c9; +} +.ant-table-thead > tr > .taskTableColumns, .ant-table-tbody > tr > .taskTableColumns{ + background-color:#F1F6FF; + border-bottom: 1px dashed #bec5d5; +} +.ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > .taskTableColumns{ + background-color:#fbfbfc; +} +.actionColumns{ + display: flex; + .actionBox, .actionBox span{ + cursor: pointer; + color: #466aff; + &:hover{color:#5d7cff !important;} + &:active{color:#1140ff !important;} + &.disabled .disabled{ + &:hover, &:active{color:#a4aabb !important;} + color:#a4aabb; + cursor: not-allowed; + } + } + .applyTask, span.applyTask{ + color:#eb9350; + &:hover{color: #FFB074 !important;} + &:active{color:#D66A17 !important;} + } + .cancelApply{visibility: hidden;} +} +tr:hover .actionColumns .cancelApply{ + visibility: visible; + color: #E31E1E; +} +.cancelApplyTask{ + .ant-modal-close{top: 0px !important;} + .ant-modal-header{ + padding: 8px 20px; + background-color: #e9edff; + .ant-modal-title{text-align: left;} + } + .carefulIcon{ + width: 36px; + height: 36px; + background: #ca0002; + display: inline-block; + border-radius: 50%; + text-align: center; + line-height: 36px; + font-size: 18px; + color: white; + margin-right: 15px; + } + .tilTask{ + color:#333333; + font-size:16px; + margin-left: 35px; + } + .tipTask{ + color:#666666; + font-size:14px; + margin: 10px 0 10px 37px!important; + } + .tipTaskTime{ + font-size: 36px; + color: #df0002; + } + .ant-modal-footer{ + border-top: none; + text-align: center; + padding-bottom: 50px; + .ant-btn{ + &.ant-btn-default{ + color: #df0002; + } + &:hover{ + border-color: #466aff; + color: #466aff; + &.ant-btn-default{ + border-color: #df0002; + color: #df0002;} + } + } + .ant-btn-default{ + margin-left:43px; + } + } +} \ No newline at end of file diff --git a/src/glcc/home/index.jsx b/src/glcc/home/index.jsx index 22720eb2..16e0086f 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} = props; + const { current_user, history, round, match:{params:{id=2023}}, period, showLoginDialog, glccSettings, repoPublic, showMatchingBut, isResultPublic} = props; useEffect(() => { if (!current_user.user_id) { @@ -30,10 +30,6 @@ export default (props) => { } }, []) - function goToCheckResult(){ - history.push("/glcc/result"); - } - // 页面跳转,判断是否登录 function gotoCheckLogin(url){ if(current_user && current_user.login){ @@ -86,11 +82,20 @@ export default (props) => { {repoPublic &&
- 查看项目 + 有奖金项目
掌握项目课题详细信息
} + {/* 0元项目 */} + +
+ + 无奖金项目 +
+
欢迎广大学生踊跃参与
+ + {/* 学生报名6.24结束第一次报名,6.29 1:00 - 6.30 24:00第二次报名 */} {(period === "stuApply" || period === "stuApply1") &&
{gotoCheckLogin(`/glcc/${id}/subjects`)}}>
@@ -108,14 +113,15 @@ export default (props) => {
以赛代筛,挖掘高潜力人才
} - {/* 6.28.-7.1 审核结果仅对导师可见,7.1之后对所有用户可见*/} - {/* {resultTime2 &&
+ + {/* 学生-课题匹配结果公示 */} + {isResultPublic &&
{history.push("/glcc/result");}}>
- 名单{resultTime1 ? '预' : ''}公示 + 名单公示
查看各课题入选学生名单
-
} */} +
} {/* 学生结项考核 */} {/* {!hasRole && checkedTaskId && @@ -159,7 +165,7 @@ export default (props) => {
OpenMMLab是深度学习时代最完整的计算机视觉开源算法体系。自开源以来,累计发布了超过20个算法库,有超过300个算法2300多个预训练模型。所有算法均具备风格统一、模型丰富、质量高、易复现等特点。在社区生态上,OpenMMLab一直秉持开放、认真、持续成长的原则,积极推动社区建设发展
-
+
} diff --git a/src/glcc/img/studentProject2.png b/src/glcc/img/studentProject2.png new file mode 100644 index 00000000..21bd32d3 Binary files /dev/null and b/src/glcc/img/studentProject2.png differ diff --git a/src/glcc/index.jsx b/src/glcc/index.jsx index 701c1021..d33d0bfa 100644 --- a/src/glcc/index.jsx +++ b/src/glcc/index.jsx @@ -46,6 +46,12 @@ const Project = Loadable({ loader: () => import("./project"), loading: Loading, }); + +// 开源夏令营0元项目、课题列表页面 +const FreeProject = Loadable({ + loader: () => import("./freeProject"), + loading: Loading, +}); // 课题详情页面 const TaskDetail = Loadable({ loader: () => import("./project/taskDetail"), @@ -92,6 +98,9 @@ const Glcc = (propsF) => { const [applyRepo, setApplyRepo] = useState(false); // 导师-学生配对阶段 const [isMatching, setIsMatching] = useState(false); + // 导师-学生配对结果公示阶段 + const [isResultPublic, setIsResultPublic] = useState(false); + console.log('isResultPublic', isResultPublic); useEffect(()=>{ if(id && id === "2022"){ @@ -113,8 +122,11 @@ const Glcc = (propsF) => { // 是否处于导师-学生配对阶段 const matching = res.data.filter(item=>item.name === "matching"); matching[0] && setIsMatching(judge(nowTime, matching[0].value, "range")) - // 过滤掉 项目课题公示时间、项目/课题补录 - const filterRepoPublic = res.data.filter(item=>["repoPublic", "repoApply1"].indexOf(item.name) === -1); + // 是否处于导师-学生配对结果公示阶段 + const resultPublic = res.data.filter(item=>item.name === "stuPublic"); + resultPublic[0] && setIsResultPublic(judge(nowTime, resultPublic[0].value, "range")) + // 过滤掉 可并行进行的阶段 + const filterRepoPublic = res.data.filter(item=>["repoPublic", "repoApply1", "matching", "stuPublic"].indexOf(item.name) === -1); const periodIndex = filterRepoPublic.findIndex(item=>judge(nowTime, item.value, "range")); periodIndex !== -1 && setPeriod(filterRepoPublic[periodIndex].name); } @@ -124,7 +136,8 @@ const Glcc = (propsF) => { // 判断是否处于此段时间范围内 function judge(nowTime, timeRnge, type){ const timeArr = timeRnge.split(",").map(item=>{ - const data = item && item.replaceAll('-', '/'); + // replaceAll不兼容低版本浏览器(如搜狗) + const data = item && item.replace(/-/g,'/'); return new Date(data).getTime() }); return type === "range" ? nowTime > timeArr[0] && nowTime < timeArr[1] : nowTime > timeArr[0] @@ -132,6 +145,8 @@ const Glcc = (propsF) => { // 用户已报名课题id数组 const [applyTaskId, setApplyTaskId] = useState({}); + // 用户当前有效报名课题id数组(补录阶段subround: 1) + const [apply1TaskId, setApply1TaskId] = useState({}); // 刷新用户课题报名信息 const [studentInfoReset, setStudentInfoReset] = useState(undefined); const [cancelCount,setCancelCount]=useState(0); @@ -163,13 +178,19 @@ const Glcc = (propsF) => { if(response && response.message === "success"){ // setData(response.data.rows); const data = {}; + const data1 = {}; 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); + // 取当前报名的课题数() + if(item.subRound === 1){ + data1[item.taskId] = item.id; + } }) setApplyTaskId(data); + setApply1TaskId(data1); response.data && setCancelCount(Number(response.data.cancelCount)); } }) @@ -182,9 +203,9 @@ const Glcc = (propsF) => { // 判断该学生是否已经被某位导师选中 if(lockedTaskName){ message.error(`由于你已入选 ${lockedTaskName} 课题,无法申请其他课题`); - }else if(applyTaskId && Object.keys(applyTaskId).length >= 2){ + }else if(apply1TaskId && Object.keys(apply1TaskId).length >= 2){ // 判断用户是否已经报名两个课题 - message.error('最多只能同时报名两个课题'); + message.error('超出可报名课题数量上限'); }else{ // 跳转到学生报名页 window.location.href=`/glcc/student/apply/${id}`; @@ -198,7 +219,7 @@ const Glcc = (propsF) => {
{/* 学生报名 */} - {period === "stuApply" && ( @@ -225,6 +246,15 @@ const Glcc = (propsF) => { )} >} + + {/* 导师-学生配对结果公示页面 */} + {isResultPublic && ( + + )} + >} + {/* 帮助中心 */} { {!(round === 2 && !repoPublic) && ( - + )} >} {/* 项目/课题列表 */} {!(round === 2 && !repoPublic) && ( - + )} >} @@ -250,23 +280,30 @@ const Glcc = (propsF) => { {!(round === 2 && !repoPublic) && ( - + )} >} + {/* 0元项目/课题列表 */} + ( + + )} + > + + ( + + )} + > + {/* openmmlab列表 */} ( - - )} - > - - {/* 审核结果页面 */} - ( - + )} > @@ -298,7 +335,7 @@ const Glcc = (propsF) => { ( - + )} > @@ -306,7 +343,7 @@ const Glcc = (propsF) => { ( - + )} > diff --git a/src/glcc/openmmlab/index.jsx b/src/glcc/openmmlab/index.jsx index 4945c030..eba15b8a 100644 --- a/src/glcc/openmmlab/index.jsx +++ b/src/glcc/openmmlab/index.jsx @@ -9,6 +9,7 @@ import { projectList } from '../api'; import './index.scss'; function Openmmlab(props) { + const {location:{pathname}} = props; const [list, setList] = useState([]); @@ -19,8 +20,9 @@ function Openmmlab(props) { useEffect(() => { const params = { curPage: 1, - keyword: 'openmmlab', - pageSize: 10000 + keyword: 'openmmlab-', + pageSize: 10000, + round: pathname && pathname.endsWith("/2022") ? 1 : 2 } projectList(params).then(response => { if (response && response.message === "success") { @@ -40,23 +42,23 @@ function Openmmlab(props) {
- +
- +
项目精选
- + -
+ {pathname.endsWith("/2022") &&
导师一览
-
+
} ) } diff --git a/src/glcc/openmmlab/projectTab/index.jsx b/src/glcc/openmmlab/projectTab/index.jsx index 9dfc1e1e..dab77452 100644 --- a/src/glcc/openmmlab/projectTab/index.jsx +++ b/src/glcc/openmmlab/projectTab/index.jsx @@ -7,7 +7,7 @@ const $ = window.$; const { TabPane } = Tabs; -function ProjectTabs({ list, applyTaskId, history, current_user, showLoginDialog, applyTask }) { +function ProjectTabs({ list, applyTaskId, history, current_user, showLoginDialog, applyTask, year, period }) { useEffect(()=>{ setTimeout(()=>{ @@ -16,7 +16,6 @@ function ProjectTabs({ list, applyTaskId, history, current_user, showLoginDialog },(e)=>{ }); },1000) - },[]) return ( @@ -34,7 +33,7 @@ function ProjectTabs({ list, applyTaskId, history, current_user, showLoginDialog key={i + ''} >
- +
diff --git a/src/glcc/openmmlab/projectTab/index.scss b/src/glcc/openmmlab/projectTab/index.scss index 0b8b64e1..624d1dab 100644 --- a/src/glcc/openmmlab/projectTab/index.scss +++ b/src/glcc/openmmlab/projectTab/index.scss @@ -1,6 +1,9 @@ .ant-tabs.openmmlab_tab { background-color: #2c374e; color: #fff; + .ant-tabs-left-content{ + border-left: none; + } .ant-tabs-bar { width: calc((100vw - 1200px) / 2 + 216px); @@ -59,7 +62,7 @@ .tab_type { opacity: .8; display: block; - width: 72px; + width: 105px; height: 30px; border: 1px solid#ffffff; border-radius: 4px; @@ -85,7 +88,7 @@ } .openmmlab_tab_content { width:954px; - height:813px; + // height:813px; padding: 21px 30px 50px; // color: rgba(0,0,0,.65); background-image: url('../../img/openmmlab/tabBackground.png') ; diff --git a/src/glcc/openmmlab/projectTab/projectDetail.jsx b/src/glcc/openmmlab/projectTab/projectDetail.jsx index fd7c0b1d..48f8b65d 100644 --- a/src/glcc/openmmlab/projectTab/projectDetail.jsx +++ b/src/glcc/openmmlab/projectTab/projectDetail.jsx @@ -3,7 +3,7 @@ import { Button, message, Tooltip } from 'antd'; import Nodata from '../../../forge/Nodata'; import { getProjectById } from '../../api'; -export default ({ detail, projectId, applyTaskId, applyTask }) => { +export default ({ detail, projectId, applyTaskId, applyTask, year, period }) => { const [info, setInfo] = useState(detail); useEffect(()=>{ @@ -26,7 +26,7 @@ export default ({ detail, projectId, applyTaskId, applyTask }) => { {info.registrationTaskList && info.registrationTaskList.length > 0 ? info.registrationTaskList.map((item, index)=>{ return
-
{window.location.href=`/glcc/2022/subjects/detail/${item.id}`}}>{item.taskName}
+
{window.location.href=`/glcc/${year}/subjects/detail/${item.id}`}}>{item.taskName}
导师姓名:   {item.tutorName}
{item.tutorMail &&
邮箱地址:   {item.tutorMail}
}
@@ -35,16 +35,16 @@ export default ({ detail, projectId, applyTaskId, applyTask }) => { {item.taskUrl &&
课题链接:   {item.taskUrl}
}
{/* 报名详情按钮 */} - {applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && } + {year === "2023" && applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && } {/* 课题申请时间范围内: 申请课题 */} {/* 第一次报名 */} - {false && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && } + {year === "2023" && period === "stuApply" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && } {/* 第二次报名 锁定状态 */} - {false && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? : )} + {year === "2023" && period === "stuApply1" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? : )} {/* 查看课题详情按钮 */} - +
¥{item.taskReward}
diff --git a/src/glcc/openmmlab/sliderLeft/index.jsx b/src/glcc/openmmlab/sliderLeft/index.jsx index b3d13bf4..9fc64fa0 100644 --- a/src/glcc/openmmlab/sliderLeft/index.jsx +++ b/src/glcc/openmmlab/sliderLeft/index.jsx @@ -62,6 +62,59 @@ const arithmeticArr = [ }, ]; +const arithmeticArr2023 = [ + { + name: "MMEngine算法演示", + describe: "MMEngine 是一个基于 PyTorch 实现的,用于训练深度学习模型的基础库。它为开发人员提供了坚实的工程基础,以此避免在工作流上编写冗余代码。作为 OpenMMLab 所有代码库的训练引擎,其在不同研究领域支持了上百个算法。此外,MMEngine 也可以用于非 OpenMMLab 项目中。", + source: 'https://www.gitlink.org.cn/api/attachments/422473', + type: 'img', + }, + { + name: "MMPreTrain算法演示", + describe: "MMPretrain 是一个全新升级的预训练开源算法框架,旨在提供各种强大的预训练主干网络,并支持不同的预训练策略。MMPretrain 源自著名的开源项目 MMClassification 和 MMSelfSup,并开放一系列新功能。 目前,预训练阶段对于视觉识别至关重要,凭借丰富而强大的预训练模型,我们能够改进各种下游视觉任务。", + type: 'img', + source: 'https://www.gitlink.org.cn/api/attachments/422508' + }, + { + name: "MMDetection算法演示", + describe: "MMDetection 是 OpenMMLab 中的通用目标检测算法平台,目前已经支持了 70+ 算法和 500+ 个预训练模型,支持目标检测、实例分割和全景分割。是 OpenMMLab 算法库中的MMDetection3D 和 MMRotate 的核心依赖,为 MMOCR、MMPose 和 MMTracking 提供了检测组件", + source: 'https://www.gitlink.org.cn/api/attachments/388003', + type: 'img', + }, + { + name: "MMDetection3D算法演示", + describe: "MMDetection3D 是 OpenMMLab 中的通用 3D 感知算法平台,目前已经支持了室内外多个主流数据集的单模态/多模态 3D 检测和点云分割算法。同时 MMDetection3D 可以无缝使用 MMDetection 中的所有组件,为多模态感知提供了丰富的基础模块", + source: 'https://www.gitlink.org.cn/api/attachments/387953', + type: 'img', + }, + { + name: "MMSegmentation算法演示", + describe: "MMSegmentation 是 OpenMMLab 中的语义分割算法工具箱,目前已经支持了 49 个算法,600+ 个预训练模型。为语义分割任务的统一实现和模型评估提供了一个框架,并且高质量实现了常用的语义分割方法和数据集。", + source: 'https://www.gitlink.org.cn/api/attachments/422474', + type: 'img', + }, + { + name: "MMAction2算法演示", + describe: "MMAction2 是一个基于 PyTorch 的开源工具箱,支持众多视频理解模型,包括动作识别、基于骨架的动作识别、时空动作检测和时间动作定位。 此外,它支持广泛使用的学术数据集,并提供许多有用的工具,帮助用户探索模型和数据集,以及实现高质量的算法。", + source: 'https://www.gitlink.org.cn/api/attachments/422475', + type: 'img', + }, + { + name: "MMPose算法演示", + describe: "MMPose 是 OpenMMLab 中的姿态估计算法库,目前已经支持了近 30 个算法和 300+ 预训练模型,涵盖了人体、人脸、人手、动物等多类目标的姿态估计。秉承 OpenMMLab 系列的结构化框架设计,MMPose 很适合作为算法复现和创新的平台", + source: 'https://www.gitlink.org.cn/api/attachments/388257.mp4', + type: 'mp4', + img: 'https://www.gitlink.org.cn/api/attachments/388256' + }, + { + name: "MMagic算法演示", + describe: "MMagic 是 OpenMMLab 中的图像&视频生成和编辑的开源算法平台,涵盖 GAN,diffusion model 多种生成模型,支持 Stable Diffusion 的微调和多种 diffusion 应用。同时支持图像修复、图文生成、3D生成、图像修补、抠图、超分辨率和生成等多种任务。利用 MMagic,通过组合不同模块轻松构建自定义的生成模型。", + source: 'https://www.gitlink.org.cn/api/attachments/422478.mp4', + img: 'https://www.gitlink.org.cn/api/attachments/388256', + type: 'mp4', + }, +]; + let setting = { infinite: true, dots: true, @@ -76,11 +129,12 @@ let setting = { autoplay: true, arrows: false, } -function SliderLeft() { - +function SliderLeft(props) { + const {pathname} = props; + const arr = pathname.endsWith("/2022") ? arithmeticArr : arithmeticArr2023 return ( - {arithmeticArr.map(item => { + {arr.map(item => { return
{item.type == 'img' && } @@ -97,8 +151,8 @@ function SliderLeft() { { item.name === 'MMDetection3D算法演示' &&
7 个数据集
-
17 种不同算法
-
80+ 个预训练模型
+
{pathname.endsWith("/2022") ? "17" : "30+"} 种不同算法
+
{pathname.endsWith("/2022") ? "80" : "90"}+ 个预训练模型
}
diff --git a/src/glcc/openmmlab/sliderLeft/index.scss b/src/glcc/openmmlab/sliderLeft/index.scss index 61d1ca10..828579a1 100644 --- a/src/glcc/openmmlab/sliderLeft/index.scss +++ b/src/glcc/openmmlab/sliderLeft/index.scss @@ -90,6 +90,9 @@ // max-height: 100%; } } + .MMagic .introduce-video{ + max-height: 112%; + } .MMDetection3D,.MMClassification { padding:30px 0; diff --git a/src/glcc/openmmlab/sliderRight/index.jsx b/src/glcc/openmmlab/sliderRight/index.jsx index 7dd8eb96..876bd6df 100644 --- a/src/glcc/openmmlab/sliderRight/index.jsx +++ b/src/glcc/openmmlab/sliderRight/index.jsx @@ -17,15 +17,11 @@ let setting = { vertical: true, } -function SliderLeft({list,history}) { +function SliderLeft({list,year}) { function goDetail(projectName){ - // history.push({ - // pathname:'/glcc/projects', - // state:{projectName:projectName.replace(/ /g,'-')} - // }) - window.open(`/glcc/2022/projects?projectName=${projectName.replace(/ /g,'')}`); + window.open(`/glcc/${year}/projects?projectName=${projectName.replace(/ /g,'')}`); } return ( diff --git a/src/glcc/project/component/projectDetail.jsx b/src/glcc/project/component/projectDetail.jsx index a76eee08..66a61397 100644 --- a/src/glcc/project/component/projectDetail.jsx +++ b/src/glcc/project/component/projectDetail.jsx @@ -10,7 +10,7 @@ export default ({ detail, projectId, applyTaskId, period, showTask=true, applyTa useEffect(()=>{ if(!detail && projectId){ // 通过项目Id查询项目详情 - getProjectById(projectId, {round}).then(response=>{ + getProjectById(projectId, {round, isFree: false}).then(response=>{ if(response && response.message === 'success'){ setInfo(response.data) } @@ -39,13 +39,13 @@ export default ({ detail, projectId, applyTaskId, period, showTask=true, applyTa {item.taskUrl &&
课题链接:   {item.taskUrl}
}
{/* 报名详情按钮 */} - {applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && } + {round === 2 && applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && } {/* 课题申请时间范围内: 申请课题 */} {/* 第一次报名 */} - {period === "stuApply" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && } + {round === 2 && period === "stuApply" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && } {/* 第二次报名 锁定状态 */} - {period === "stuApply1" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? : )} + {round === 2 && period === "stuApply1" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? : )} {/* 查看课题详情按钮 */} diff --git a/src/glcc/project/taskDetail/index.jsx b/src/glcc/project/taskDetail/index.jsx index bd678b75..ee812529 100644 --- a/src/glcc/project/taskDetail/index.jsx +++ b/src/glcc/project/taskDetail/index.jsx @@ -7,7 +7,7 @@ import './index.scss'; // 课题列表 function TaskDetail(props) { - const {match, location, period, applyTaskId, applyTask, match:{params:{id}}} = props + const {match, location, period, applyTaskId, applyTask, match:{params:{id}}, currentRound, round} = props const taskId = Number(match.params.taskId); const [detail, setDetail] = useState(undefined); @@ -48,13 +48,13 @@ function TaskDetail(props) {
{detail.taskDesc}
{/* 报名详情按钮 */} - {applyTaskId && Object.keys(applyTaskId).includes(taskId.toString()) && } + {round === currentRound && applyTaskId && Object.keys(applyTaskId).includes(taskId.toString()) && } {/* 课题申请时间范围内: 申请课题 */} {/* 第一次报名 */} - {period==="stuApply" && !(applyTaskId && Object.keys(applyTaskId).includes(taskId.toString())) && } + {detail.taskReward > 0 && round === currentRound && period==="stuApply" && !(applyTaskId && Object.keys(applyTaskId).includes(taskId.toString())) && } {/* 第二次报名 锁定状态 */} - {period === "stuApply1" && !(applyTaskId && Object.keys(applyTaskId).includes(taskId.toString())) && (detail.locked ? : )} + {detail.taskReward > 0 && round === currentRound && period === "stuApply1" && !(applyTaskId && Object.keys(applyTaskId).includes(taskId.toString())) && (detail.locked ? : )}
diff --git a/src/glcc/project/taskList/index.jsx b/src/glcc/project/taskList/index.jsx index 26f36eb0..a21f4e24 100644 --- a/src/glcc/project/taskList/index.jsx +++ b/src/glcc/project/taskList/index.jsx @@ -7,7 +7,7 @@ import bgPng from "../../img/bgPng.png"; const { Search } = Input; // 课题列表 -function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDialog,cancelCount,showNotification, applyTask, round, match:{params:{id}}, period }) { +function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDialog,cancelCount,showNotification, applyTask, round, match:{params:{id}}, period, currentRound, lockedTaskName }) { const [visible, setVisible] = useState(false); const [deleteTaskId, setDeleteTaskId] = useState(undefined); // 输入搜索框 @@ -21,6 +21,8 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial const [expandedRowKeys, setExpandedRowKeys] = useState([]); // 已报名 const [apply, setApply] = useState(false); + // 可申请课题 + const [isAvailable, setIsAvailable] = useState(false); const columns = [ { title: '序号', dataIndex: 'index', align: 'center', className:"taskTableColumns", width: '6%', render: (text, item, index) => {(current-1)*pageSize+index + 1} }, @@ -33,16 +35,16 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial return (
{/* 报名详情按钮 */} - {applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && {window.location.href=`/glcc/student/apply/${item.id}`}}>报名详情} + {round === currentRound && applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && {window.location.href=`/glcc/student/apply/${item.id}`}}>报名详情} - {/* 取消按钮5.26-6.25 */} - {(period === "stuApply" || period === "stuApply1") && applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && {deleteItem(item.id)}}>} + {/* 取消按钮 */} + {round === currentRound && (period === "stuApply" || period === "stuApply1") && applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && !lockedTaskName && {deleteItem(item.id)}}>} {/* 课题申请时间范围内: 申请课题 */} {/* 第一次报名 */} - {period === "stuApply" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && {applyTask(item.id)}}>申请课题} - {/* 第二次报名 锁定状态 */} - {period === "stuApply1" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? 申请课题 : {applyTask(item.id, item.locked)}}>申请课题)} + {round === currentRound && period === "stuApply" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && {applyTask(item.id)}}>申请课题} + {/* 补录阶段 锁定状态 */} + {round === currentRound && period === "stuApply1" && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? 申请课题 : {applyTask(item.id, item.locked)}}>申请课题)}
) }) @@ -130,13 +132,22 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial keyword, pageSize, userId: apply ? current_user.user_id : '', - round + round, + locked: isAvailable ? false : undefined } + console.log('params', params); taskList(params).then(response => { if (response && response.message === "success") { + const data = response.data.rows; + if(period === "stuApply1"){ + // 将可再报名的课题置顶 + const applyIds = data.filter(item=>!item.locked).map(item=>item.id); + data.map((item, index)=>{ + applyIds.includes(item.id) && toFirst(data, index); + }) + } // 将已报名task任务置顶 const ids = Object.keys(applyTaskId); - const data = response.data.rows; data.map((item, index)=>{ ids.includes(item.id.toString()) && toFirst(data, index); }) @@ -145,13 +156,16 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial } setLoading(false); }) - }, [keyword, current, pageSize, applyTaskId, apply, round]) + }, [keyword, current, pageSize, applyTaskId, apply, round, isAvailable]) return (
- {round === 2 && current_user && current_user.login ? {setCurrent(1);setApply(e.target.checked)}}>已报名 :
} +
+ {round === 2 && current_user && current_user.login ? {setCurrent(1);setApply(e.target.checked)}}>已报名 :
} + {round === 2 && period === "stuApply1" && {setCurrent(1);setIsAvailable(e.target.checked)}}>可申请课题} +
{ setCurrent(1); setKeyword(value) }} />
diff --git a/src/glcc/student/index.jsx b/src/glcc/student/index.jsx index f81c94cd..8eeaaf35 100644 --- a/src/glcc/student/index.jsx +++ b/src/glcc/student/index.jsx @@ -24,21 +24,18 @@ const gradeList = [ { id: '博士及以上', name: '博士及以上' } ]; function Apply(props) { - const { form, current_user, showNotification, match, history, setStudentInfoReset, period, round } = props; + const { form, current_user, showNotification, match, setStudentInfoReset, period, round } = props; const taskId = Number(match.params.taskId); - // 可用于开发时不同账号报名 - // current_user && (current_user.user_id = 6) - // current_user && (current_user.userName = "创新使者") const { getFieldDecorator, validateFields, setFieldsValue, validateFieldsAndScroll } = form; const [imageUrl, setImageUrl] = useState(undefined); const [loading, setLoading] = useState(false); const [reload, setReload] = useState(); - const [locked, setLocked] = useState(true); + const [locked, setLocked] = useState(false); const [userApplyInfo, setUserApplyInfo] = useState(undefined); const [editable, setEditable] = useState(false); - const [files, setFiles] = useState([]); - const [files1, setFiles1] = useState([]); - const [files2, setFiles2] = useState([]); + const [fileList, setFileList] = useState([]); + // 当前有效课题数量 + const [taskCount, setTaskCount] = useState(0); const initTask = { taskId, memo: '', @@ -96,32 +93,21 @@ function Apply(props) { if (data.registrationStudentTaskList.length) { let initTaskList = []; let lockedCurrent = false; + const fileListInit = []; for (const [i, item] of data.registrationStudentTaskList.entries()) { applyInfo['memo' + i] = item.memo; applyInfo['taskId' + i] = item.taskId; applyInfo['memoAttachmentId' + i] = item.memoAttachmentId; - if (item.locked && item.passStatus) { + applyInfo['subRound' + i] = item.subRound; + if (item.locked) { lockedCurrent = item.locked; } - if (i == 0) { - item.memoAttachment && setFiles([{ - name: item.memoAttachment && item.memoAttachment.fileName || '已上传文件', - id: item.memoAttachmentId, - uid: item.memoAttachmentId - }]); - } else if(i==1) { - item.memoAttachment && setFiles1([{ - name: item.memoAttachment && item.memoAttachment.fileName || '已上传文件', - id: item.memoAttachmentId, - uid: item.memoAttachmentId, - }]); - } else { - item.memoAttachment && setFiles2([{ - name: item.memoAttachment && item.memoAttachment.fileName || '已上传文件', - id: item.memoAttachmentId, - uid: item.memoAttachmentId, - }]); - } + fileListInit.push(item.memoAttachment ? [{ + name: item.memoAttachment.fileName || '已上传文件', + id: item.memoAttachmentId, + uid: item.memoAttachmentId + }]: undefined) + setFileList(fileListInit); if (item.enrollFirst) { applyInfo.enrollFirst = i; @@ -140,17 +126,18 @@ function Apply(props) { // }); } setMyTaskList(initTaskList); - - // let idArr= data.registrationStudentTaskList.map(i=>{return i.id}); - // if(idArr.length===3){lockedCurrent=true;} - // setLocked(lockedCurrent); - // 如果未被锁定,且小于3条报名数据,且课题id与当前id不一致,那么新增一条默认数据 + setLocked(lockedCurrent); + // subRound为0是已经匹配的数据,认为不是有效数据 + const length = data.registrationStudentTaskList.filter(item=>item.subRound === 1).length + setTaskCount(length); + // 如果未被锁定,且有效报名数据小于2,且课题id与当前id不一致,那么新增一条默认数据 let taskIdArr=data.registrationStudentTaskList.map(i=>{return i.taskId}); - if (!lockedCurrent && data.registrationStudentTaskList.length < 3 && !taskIdArr.includes(taskId)) { - addTask(data.registrationStudentTaskList); - setLocked(false); + if (!lockedCurrent && length < 2 && !taskIdArr.includes(taskId)) { + addTask(length, data.registrationStudentTaskList); } } else { + // 用户报名过glcc,但是没有填报课题信息 + setTaskCount(1); // 先增加数据再给选择框赋默认值,否则不生效 new Promise((resove) => { setMyTaskList(() => { @@ -164,6 +151,8 @@ function Apply(props) { setFieldsValue(applyInfo); setUserApplyInfo(response.data); } else { + // 用户从未报名glcc + setTaskCount(1); // 先增加数据再给选择框赋默认值,否则不生效 new Promise((resove) => { setMyTaskList(() => { @@ -201,7 +190,8 @@ function Apply(props) { // registrationStudentTaskList需要传round字段 item.round = round; // 课题优先级 - item.enrollFirst = index === enrollFirst + item.enrollFirst = index === enrollFirst; + item.subRound= values[`subRound${index}`] === 0 ? 0 : 1; }) } const params = { @@ -308,18 +298,10 @@ function Apply(props) { if (info.file.status === 'removed') { changeTaskItem('memoAttachmentId', '', i); } - if (i==1) { - setFiles1(appendFileSizeToUploadFileAll(info.fileList).slice(-1)); - }else if (i==2) { - setFiles2(appendFileSizeToUploadFileAll(info.fileList).slice(-1)); - } else { - setFiles(appendFileSizeToUploadFileAll(info.fileList).slice(-1)); - } + const fileListInit = [...fileList]; + fileListInit[i] = appendFileSizeToUploadFileAll(info.fileList).slice(-1); + setFileList(fileListInit); } - - // if (info.file.status === "done" || info.file.status === 'removed') { - // setLoading(false); - // } } // 支持文件下载 @@ -328,7 +310,8 @@ function Apply(props) { window.open(`${httpUrl}/busiAttachments/download/${fileId}`); } - function addTask(List) { + function addTask(count, List) { + setTaskCount(1 + count); let taskListNew = List ? [...List] : [...myTaskList]; if (taskId != taskListNew[0].taskId) { taskListNew.push(initTask); @@ -346,33 +329,6 @@ function Apply(props) { } } - function deleteTask(i) { - let taskListNew = myTaskList.slice(); - let reWriteInfo; - if (i) { - reWriteInfo = { - taskId1: '', - memo1: '', - memoAttachmentId1: '' - } - setFiles1([]); - } else { - reWriteInfo = { - taskId0: taskListNew[1].taskId, - memo0: taskListNew[1].memo, - memoAttachmentId0: taskListNew[1].memoAttachmentId, - taskId1: '', - memo1: '', - memoAttachmentId1: '' - } - setFiles(files1); - setFiles1([]); - } - - taskListNew.splice(i, 1); - setMyTaskList(taskListNew); - setFieldsValue(reWriteInfo); - } function changeTaskItem(field, val, i) { let taskListNew = [...myTaskList]; @@ -489,13 +445,15 @@ function Apply(props) { return (

课题信息({i + 1}) - {/* {myTaskList.length > 1 && { deleteTask(i) }}>删除} */}

{item.status === 1 && item.auditRemark &&
欢迎您报名CCF GitLink开源编程夏令营,感谢您对GLCC项目及课题的关注和支持!本次您的报名信息未通过初审,原因如下:
希望您尽快修改并重新提交报名信息,我们将再次审核,万分感谢!
} + {helper('课题名称', '', 'taskId' + i, @@ -504,18 +462,16 @@ function Apply(props) { placeholder="请选择课题名称" dropdownClassName="glcc_select" showSearch - className={!editable || (item.id && item.status !== 1) ? "disabledInput" : ""} - disabled={!editable || (item.id && item.status !== 1)} - // disabled - // className={"disabledInput"} + className={!editable || (item.id && item.status !== 1) || item.subRound === 0 ? "disabledInput" : ""} + disabled={!editable || (item.id && item.status !== 1) || item.subRound === 0} filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) > -1} onBlur={() => { verify("taskId" + i) }} onChange={(val) => { changeTaskItem("taskId", val, i) }} > - {allTaskList.map(item => { return })} + {allTaskList.map(item => { return })} )} - {item.locked && item.passStatus &&
您已通过审核,成功入选该课题
} + {item.locked &&
您已通过审核,成功入选该课题
}
{helper('自荐书', , 'memo' + i, @@ -540,9 +496,8 @@ function Apply(props) { 'memoAttachmentId' + i, [], { bookChange(info, i) }} onDownload={download} beforeUpload={beforeUpload2} @@ -561,9 +516,7 @@ function Apply(props) { }) } - { - myTaskList.length < 2 && - } + {taskCount < 2 && !locked && } { myTaskList.length >= 2 && - 课题一 - 课题二 - {myTaskList.length === 3 && 课题三} + {myTaskList.map((item, index) =>{ + return 课题{index+1} + })} )}