forked from Gitlink/forgeplus-react
Merge pull request 'glcc二期报名修改' (#391) from tongChong/forgeplus-react:feature_GLCC into gitlink_server
This commit is contained in:
commit
b649f7a18c
|
@ -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 || 'student'
|
||||
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
||||
}
|
||||
window._debugType = debugType;
|
||||
export function initAxiosInterceptors(props) {
|
||||
|
|
|
@ -62,6 +62,7 @@ const Glcc = (propsF) => {
|
|||
const [applyTaskId, setApplyTaskId] = useState({});
|
||||
// 刷新用户课题报名信息
|
||||
const [studentInfoReset, setStudentInfoReset] = useState(undefined);
|
||||
const [cancelCount,setCancelCount]=useState(0);
|
||||
|
||||
useEffect(()=>{
|
||||
// 获取用户课题报名信息current_user user_id
|
||||
|
@ -73,6 +74,7 @@ const Glcc = (propsF) => {
|
|||
data[item.taskId] = item.id;
|
||||
})
|
||||
setApplyTaskId(data);
|
||||
response.data&&setCancelCount(Number(response.data.cancelCount));
|
||||
}
|
||||
})
|
||||
},[studentInfoReset, current_user])
|
||||
|
@ -104,7 +106,7 @@ const Glcc = (propsF) => {
|
|||
<Route
|
||||
path="/glcc/subjects/detail/:taskId"
|
||||
render={(props) => (
|
||||
<TaskDetail {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} applyTaskId={applyTaskId}/>
|
||||
<TaskDetail {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} applyTaskId={applyTaskId} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 项目/课题列表 */}
|
||||
|
@ -119,7 +121,7 @@ const Glcc = (propsF) => {
|
|||
<Route
|
||||
path="/glcc/subjects"
|
||||
render={(props) => (
|
||||
<Project {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset}/>
|
||||
<Project {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} cancelCount={cancelCount}/>
|
||||
)}
|
||||
></Route>
|
||||
{/* 首页 */}
|
||||
|
|
|
@ -20,7 +20,7 @@ const TaskList = Loadable({
|
|||
});
|
||||
|
||||
function Project(propsF) {
|
||||
const {location, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, applyTaskId, setStudentInfoReset} = propsF;
|
||||
const {location, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, applyTaskId, setStudentInfoReset, cancelCount} = propsF;
|
||||
const {pathname} = location;
|
||||
useEffect(()=>{
|
||||
window.scrollTo(0, 0);
|
||||
|
@ -42,19 +42,19 @@ function Project(propsF) {
|
|||
<Route
|
||||
path="/glcc/projects"
|
||||
render={(props) => (
|
||||
<ProjectList applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd}/>
|
||||
<ProjectList {...propsF} {...props}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/glcc/subjects"
|
||||
render={(props) => (
|
||||
<TaskList applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd}/>
|
||||
<TaskList {...propsF} {...props}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/glcc/student"
|
||||
render={(props) => (
|
||||
<TaskList applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd}/>
|
||||
<TaskList {...propsF} {...props}/>
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
|
|
|
@ -7,7 +7,7 @@ import bgPng from "../../img/bgPng.png";
|
|||
const { Search } = Input;
|
||||
|
||||
// 课题列表
|
||||
function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd}) {
|
||||
function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd,cancelCount,showNotification}) {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [deleteTaskId, setDeleteTaskId] = useState(undefined);
|
||||
// 输入搜索框
|
||||
|
@ -24,16 +24,17 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
|
|||
|
||||
const columns = [
|
||||
{ title: '序号', dataIndex: 'index', align: 'center', className:"taskTableColumns", width: '6%', render: (text, item, index) => <span>{(current-1)*pageSize+index + 1}</span> },
|
||||
{ title: '课题名称', dataIndex: 'taskName', className:"taskTableColumns taskName", width: '28%', ellipsis: true, render: (text, item) => <Tooltip title={text} placement="topLeft"><span onClick={()=>{window.open(`/glcc/subjects/detail/${item.id}`)}}>{text}</span></Tooltip> },
|
||||
{ title: '项目名称', dataIndex: 'projectName', className:"taskTableColumns", width: '28%', ellipsis: true, render: (text) => <Tooltip title={text} placement="topLeft">{text}</Tooltip> },
|
||||
{ title: '课题奖金', dataIndex: 'taskReward', className:"taskTableColumns", ellipsis: true, width: `${isStudentApplyDate || studentApplyEnd ? '15%' : ''}`, render: (text) => <Tooltip title={text} placement="topLeft"><span>{text}</span></Tooltip> },
|
||||
{ title: '课题名称', dataIndex: 'taskName', className:"taskTableColumns taskName", width: '24%', ellipsis: true, render: (text, item) => <Tooltip title={text} placement="topLeft"><span onClick={()=>{window.open(`/glcc/subjects/detail/${item.id}`)}}>{text}</span></Tooltip> },
|
||||
{ title: '课题类型', dataIndex: 'projectType', className:"taskTableColumns", width: '12%', ellipsis: true, },
|
||||
{ title: '项目名称', dataIndex: 'projectName', className:"taskTableColumns", width: '24%', ellipsis: true, render: (text) => <Tooltip title={text} placement="topLeft">{text}</Tooltip> },
|
||||
{ title: '课题奖金', dataIndex: 'taskReward', className:"taskTableColumns", ellipsis: true, width: `${isStudentApplyDate || studentApplyEnd ? '10%' : ''}`, render: (text) => <Tooltip title={text} placement="topLeft"><span>{text}</span></Tooltip> },
|
||||
{
|
||||
title: '操作', dataIndex: 'action', align: 'center', className:"actionColumns taskTableColumns", render: ((text, item, index) => {
|
||||
return (
|
||||
<div className='actionBox'>
|
||||
{(isStudentApplyDate || studentApplyEnd) && (applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) ? <Fragment>
|
||||
<span onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}}><i className='iconfont icon-baomingxiangqingicon mr5'></i>报名详情</span>
|
||||
<Tooltip title={"取消申请"}><i className='iconfont icon-shanchuicon3 ml20 cancelApply' onClick={()=>{setDeleteTaskId(item.id);setVisible(true)}}></i></Tooltip>
|
||||
<Tooltip title={"取消申请"}><i className='iconfont icon-shanchuicon3 ml20 cancelApply' onClick={()=>{deleteItem(item.id)}}></i></Tooltip>
|
||||
</Fragment>:isStudentApplyDate && <Fragment>
|
||||
<span onClick={()=>{applyTask(item.id)}}><i className='iconfont icon-shenqingketiicon applyTask mr5'></i><span className='applyTask'>申请课题</span></span></Fragment>)}
|
||||
</div>
|
||||
|
@ -42,6 +43,15 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
|
|||
},
|
||||
]
|
||||
|
||||
function deleteItem(id){
|
||||
if(cancelCount==2){
|
||||
showNotification("您的取消报名次数已用光,请联系导师处理相关报名审核信息");
|
||||
}else{
|
||||
setDeleteTaskId(id);
|
||||
setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
const customExpandIcon = (props) => {
|
||||
if (props.expanded) {
|
||||
return <a className='actionBox' style={{marginRight: 8 }} onClick={e => {
|
||||
|
@ -158,7 +168,7 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
|
|||
columns={columns}
|
||||
dataSource={data}
|
||||
expandedRowRender={expandRow}
|
||||
expandIconColumnIndex={4}
|
||||
expandIconColumnIndex={5}
|
||||
expandIconAsCell={false}
|
||||
expandIcon={customExpandIcon}
|
||||
rowKey={'id'}
|
||||
|
@ -170,16 +180,17 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
|
|||
<img src={bgPng} alt='' className='bgPng3'/>
|
||||
<img src={bgPng} alt='' className='bgPng4'/>
|
||||
<Modal
|
||||
okText="确认删除"
|
||||
okText="确认"
|
||||
cancelText="再想想"
|
||||
okType='default'
|
||||
title="删除"
|
||||
title="取消申请"
|
||||
visible={visible}
|
||||
onCancel={()=>{setVisible(false)}}
|
||||
onOk={cancelApply}
|
||||
wrapClassName='cancelApplyTask'
|
||||
>
|
||||
<div className='tilTask mt20'><span className='carefulIcon'>!</span>取消申请即删除本次报名记录,确定取消?</div>
|
||||
<p className='tipTask'>此操作将永久删除该报名记录,请进行确认以防数据的丢失</p>
|
||||
<div className='tilTask mt20'><span className='carefulIcon'>!</span>确定取消申请此课题?</div>
|
||||
<p className='tipTask'>取消申请后将删除此条申请记录。你仅有<span className="tipTaskTime"> {2-cancelCount} </span>次取消申请的机会</p>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -77,7 +77,11 @@ tr:hover .actionColumns .cancelApply{
|
|||
.tipTask{
|
||||
color:#666666;
|
||||
font-size:14px;
|
||||
margin: 30px 0 30px 86px !important;
|
||||
margin: 10px 0 10px 37px!important;
|
||||
}
|
||||
.tipTaskTime{
|
||||
font-size: 36px;
|
||||
color: #df0002;
|
||||
}
|
||||
.ant-modal-footer{
|
||||
border-top: none;
|
||||
|
@ -95,6 +99,9 @@ tr:hover .actionColumns .cancelApply{
|
|||
color: #df0002;}
|
||||
}
|
||||
}
|
||||
.ant-btn-default{
|
||||
margin-left:43px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.task.search{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useCallback, useEffect, useState, Fragment } from 'react';
|
||||
import { Breadcrumb, Button, Form, Input, Select, Upload, Cascader, Spin } from 'antd';
|
||||
import { Breadcrumb, Button, Form, Input, Select, Upload, Cascader, Spin, Radio } from 'antd';
|
||||
import { getUploadActionUrl, getUrl, appendFileSizeToUploadFileAll } from 'educoder';
|
||||
import { locData } from '../../forge/Utils/locData';
|
||||
import { getStudentApplyInfo, taskList, studentApply, studentApplyEdit } from '../api';
|
||||
|
@ -119,12 +119,21 @@ function Apply(props) {
|
|||
}]);
|
||||
}
|
||||
|
||||
initTaskList.push({
|
||||
id: item.id,
|
||||
memo: item.memo,
|
||||
memoAttachmentId: item.memoAttachmentId,
|
||||
taskId: item.taskId,
|
||||
});
|
||||
if(item.enrollFirst){
|
||||
applyInfo.enrollFirst=i;
|
||||
}
|
||||
|
||||
if(item.status==2){
|
||||
item.status==2
|
||||
}
|
||||
|
||||
initTaskList.push(item);
|
||||
// initTaskList.push({
|
||||
// id: item.id,
|
||||
// memo: item.memo,
|
||||
// memoAttachmentId: item.memoAttachmentId,
|
||||
// taskId: item.taskId,
|
||||
// });
|
||||
}
|
||||
setMyTaskList(initTaskList);
|
||||
|
||||
|
@ -172,6 +181,15 @@ function Apply(props) {
|
|||
validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
setLoading(true);
|
||||
if (myTaskList.length === 2) {
|
||||
if(values.enrollFirst==1){
|
||||
myTaskList[1].enrollFirst = true;
|
||||
myTaskList[0].enrollFirst = false;
|
||||
}else{
|
||||
myTaskList[1].enrollFirst = false;
|
||||
myTaskList[0].enrollFirst = true;
|
||||
}
|
||||
}
|
||||
const params = {
|
||||
grade: values.grade,
|
||||
location: Array.isArray(values.location) && values.location.join(),
|
||||
|
@ -354,14 +372,14 @@ function Apply(props) {
|
|||
<Breadcrumb.Item><Link to="/glcc/subjects">课题及项目列表</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item style={{ color: '#202D40' }}>学生报名</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
|
||||
<div className="head_introduce">
|
||||
<h4 className="head_tit">申请说明:</h4>
|
||||
<div className="head_content">1、学生报名时间为<span className="head_bold">2022年5月26日-6月24日</span>,请在报名截止时间(北京时间<span className="head_bold">2022年6月24日24点</span>)前提交报名信息。</div>
|
||||
<div className="head_content">2、本次GLCC夏令营基于GitLink代码托管平台完成编程任务,若您没有平台账户,请先注册后完成课题申请</div>
|
||||
<div className="head_content">3、每位学员最多可申请2个课题,至多有且仅有1个课题可以入选</div>
|
||||
<div className="head_content">4、建议在提交课题申请,与课题导师邮件沟通,详细了解课题描述、编码任务、技能要求&编程语言、预期产出结果等信息,以便您能够选择最适合的课题</div>
|
||||
<div className="head_content">5、提交申请后,请耐心等待,我们会在2022年7月1日公布入围结果。如有任何问题,请添加开源夏令营QQ群进行咨询</div>
|
||||
<div className="head_content">4、提交申请后,每位学员可实时修改自己的报名信息,但仅具有两次取消申请课题的机会,请谨慎选择课题或取消课题</div>
|
||||
<div className="head_content">5、建议在提交课题申请,与课题导师邮件沟通,详细了解课题描述、编码任务、技能要求&编程语言、预期产出结果等信息,以便您能够选择最适合的课题</div>
|
||||
<div className="head_content">6、提交申请后,请耐心等待,我们会在2022年7月1日公布入围结果。如有任何问题,请添加开源夏令营QQ群:210174286进行咨询</div>
|
||||
</div>
|
||||
<div className="main-tit">
|
||||
<img src={studentSvg} alt='' /><span className="tit-text">学生报名</span>
|
||||
|
@ -449,7 +467,14 @@ function Apply(props) {
|
|||
myTaskList.map((item, i) => {
|
||||
return (
|
||||
<Fragment key={item.taskId + '' + i}>
|
||||
<h4 className="item-tit">课题信息(<span className="item-tit-num">{i + 1}</span>/2) {myTaskList.length > 1 && <span className="delete" onClick={() => { deleteTask(i) }}><i className="iconfont icon-shanchu mr5"></i>删除</span>}</h4>
|
||||
<h4 className="item-tit">课题信息(<span className="item-tit-num">{i + 1}</span>/2)
|
||||
{/* {myTaskList.length > 1 && <span className="delete" onClick={() => { deleteTask(i) }}><i className="iconfont icon-shanchu mr5"></i>删除</span>} */}
|
||||
</h4>
|
||||
{item.status == 1 && item.auditRemark && <div className="reject-reason">
|
||||
<div className="mb5"><i className="iconfont icon-shanchudiao"></i>欢迎您报名CCF GitLink开源编程夏令营,感谢您对GLCC项目及课题的关注和支持!本次您的报名信息未通过初审,原因如下:</div>
|
||||
<div className="mb5 ml20" dangerouslySetInnerHTML={{__html:item.auditRemark}}></div>
|
||||
<div className="mb5 ml20">希望您尽快修改并重新提交报名信息,我们将再次审核,万分感谢!</div>
|
||||
</div>}
|
||||
{helper('课题名称',
|
||||
'',
|
||||
'taskId' + i,
|
||||
|
@ -458,8 +483,8 @@ function Apply(props) {
|
|||
placeholder="请选择课题名称"
|
||||
dropdownClassName="glcc_select"
|
||||
showSearch
|
||||
disabled={editable ? false : true}
|
||||
className={editable ? "" : "disabledInput"}
|
||||
disabled
|
||||
className={"disabledInput"}
|
||||
filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) > -1}
|
||||
onBlur={() => { verify("taskId" + i) }}
|
||||
onChange={(val) => { changeTaskItem("taskId", val, i) }}
|
||||
|
@ -508,7 +533,22 @@ function Apply(props) {
|
|||
}
|
||||
|
||||
{
|
||||
myTaskList.length < 2 && <Button className="add_task" type="primary" onClick={() => { addTask() }}>添加课题</Button>
|
||||
// myTaskList.length < 2 && <Button className="add_task" type="primary" onClick={() => { addTask() }}>添加课题</Button>
|
||||
}
|
||||
|
||||
{
|
||||
myTaskList.length === 2 && <Form.Item className="priority"
|
||||
label={<Fragment>对您而言,哪个课题的优先级更高?<span className="note">注:优先级将决定您申请课题的入选顺序,若申请的2个课题同时通过审核,将以高优先级的课题作为入选标准</span></Fragment>}
|
||||
>
|
||||
{getFieldDecorator("enrollFirst", {
|
||||
rules: [{ required: true, message: "请选择课题优先级" },]
|
||||
})(
|
||||
<Radio.Group >
|
||||
<Radio value={0}>课题一</Radio>
|
||||
<Radio value={1}>课题二</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
}
|
||||
|
||||
<Form.Item className='subInfo introArea'>
|
||||
|
|
|
@ -155,7 +155,6 @@
|
|||
border: none;
|
||||
color: #202d40;
|
||||
}
|
||||
|
||||
}
|
||||
.ant-cascader-picker {
|
||||
background: none;
|
||||
|
@ -291,39 +290,87 @@
|
|||
padding: 9px 11px;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
|
||||
.glcc_info_form .ant-row.ant-form-item.priority {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding-top: 5px;
|
||||
border-top: 1px dashed #bec5d5;
|
||||
.ant-col {
|
||||
width: 100%;
|
||||
}
|
||||
.ant-form-item-label {
|
||||
text-align: left;
|
||||
}
|
||||
.note {
|
||||
color: #ff3838;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ant-radio-checked::after {
|
||||
border: 1px solid #466aff;
|
||||
}
|
||||
.ant-radio-checked .ant-radio-inner {
|
||||
border-color: #466aff;
|
||||
}
|
||||
.ant-radio-inner::after {
|
||||
background-color: #466aff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.reject-reason {
|
||||
width: 100%;
|
||||
min-height: 45px;
|
||||
line-height: 42px;
|
||||
background-color: rgba(242, 216, 216, 0.63);
|
||||
border: 1px solid #df4c4c;
|
||||
color: #595e82;
|
||||
font-size: 15px;
|
||||
padding-left:22px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.icon-shanchudiao{
|
||||
position: relative;
|
||||
top:1px;
|
||||
color: #e21b1b;
|
||||
margin-right: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.glcc-banner {
|
||||
width: 100%;
|
||||
}
|
||||
.glcc_select,.ant-cascader-menus.glcc_cascader{
|
||||
.glcc_select,
|
||||
.ant-cascader-menus.glcc_cascader {
|
||||
background-image: linear-gradient(180deg, #eef3ff 0%, #ffffff 100%);
|
||||
border: 1px solid #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 0px 12px rgba(203, 220, 255, 0.47);
|
||||
|
||||
.ant-select-dropdown-menu-item{
|
||||
&:hover{
|
||||
.ant-select-dropdown-menu-item {
|
||||
&:hover {
|
||||
background-color: #e9efff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.glcc_select .ant-select-dropdown-menu-item-active:not(.ant-select-dropdown-menu-item-disabled){
|
||||
.glcc_select
|
||||
.ant-select-dropdown-menu-item-active:not(.ant-select-dropdown-menu-item-disabled) {
|
||||
background: #e9efff;
|
||||
}
|
||||
.glcc_cascader{
|
||||
.ant-cascader-menu{
|
||||
.glcc_cascader {
|
||||
.ant-cascader-menu {
|
||||
width: 240px;
|
||||
|
||||
&::-webkit-scrollbar-track{
|
||||
background-color: #E2E9FF;
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: #e2e9ff;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb{
|
||||
background-color: #BCCCFF;
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: #bcccff;
|
||||
}
|
||||
}
|
||||
.ant-cascader-menu:first-child{
|
||||
.ant-cascader-menu:first-child {
|
||||
width: 250px;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue