Merge branch 'feature_GLCC' of http://106.75.45.236:3000/tongChong/forgeplus-react into feature_IDE

This commit is contained in:
何童崇 2022-06-02 11:21:23 +08:00
commit 10fc7bf457
11 changed files with 167 additions and 48 deletions

View File

@ -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) {

View File

@ -7,7 +7,7 @@ import Loadable from 'react-loadable';
import Loading from '../../Loading';
const About = Loadable({
loader: () => import('./About'),
loader: () => import('./subIndex'),
loading: Loading,
})
const New = Loadable({
@ -66,7 +66,8 @@ export default ((props)=>{
{/* 原本的两种合为一个 */}
<Route path="/:owner/:projectsId/devops"
render={
(p) =>{return( p.location && p.location.state && p.location.state.open_devops?<Dispose {...props} {...p}/>:<About {...props} {...p}/>)}
// (p) =>{return( p.location && p.location.state && p.location.state.open_devops?<Dispose {...props} {...p}/>:<About {...props} {...p}/>)}
(p) =>{return(<About {...props} {...p}/>)}
}
></Route>
</Switch>

View File

@ -0,0 +1,13 @@
import React from 'react';
import About from './About';
import Dispose from './Dispose';
function SubIndex(props) {
return(
props && props.open_devops ?
<Dispose {...props} />
:
<About {...props} />
)
}
export default SubIndex;

View File

@ -32,7 +32,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
}
}).catch(error=>{})
}
console.log("detail:",open_devops);
return(
<div className="f-wrap-between mt25">
<QuitBox visible={visible} onCancel={()=>setVisible(false)} name={projectDetail && projectDetail.name} onSuccess={onSuccess}/>

View File

@ -6,8 +6,9 @@ function ListItem({item,key,OIdentifier}) {
return(
<div className="team_project" key={key}>
<p className="t_p_title">
<span className="flex1">
<span className="flex1" style={{display:"flex",alignItems:"center"}}>
<Link to={`/${OIdentifier}/${item.identifier}`} className="name">{item.name}</Link>
{!item.is_public && <span className="privateTag">私有</span> }
{ item.forked_from_project_id && <i className="iconfont icon-fork font-18 color-orange ml8" /> }
{
item.type && item.type === 2 ?

View File

@ -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>
{/* 首页 */}

View File

@ -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>

View File

@ -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: '22%', 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: '10%', ellipsis: true, },
{ title: '项目名称', dataIndex: 'projectName', className:"taskTableColumns", width: '22%', ellipsis: true, render: (text) => <Tooltip title={text} placement="topLeft">{text}</Tooltip> },
{ title: '课题奖金', dataIndex: 'taskReward', className:"taskTableColumns", ellipsis: true, width: `${isStudentApplyDate || studentApplyEnd ? '18%' : ''}`, 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 => {
@ -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>
)

View File

@ -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{

View File

@ -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,17 @@ function Apply(props) {
}]);
}
initTaskList.push({
id: item.id,
memo: item.memo,
memoAttachmentId: item.memoAttachmentId,
taskId: item.taskId,
});
if(item.enrollFirst){
applyInfo.enrollFirst=i;
}
initTaskList.push(item);
// initTaskList.push({
// id: item.id,
// memo: item.memo,
// memoAttachmentId: item.memoAttachmentId,
// taskId: item.taskId,
// });
}
setMyTaskList(initTaskList);
@ -172,6 +177,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 +368,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>
@ -447,9 +461,17 @@ function Apply(props) {
{
myTaskList.map((item, i) => {
console.log(item )
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 +480,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 +530,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'>

View File

@ -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;
}
}