Merge pull request '导师审核' (#407) from durian/forgeplus-react:feature_GLCC2 into gitlink_server

This commit is contained in:
tongChong 2022-06-27 22:54:28 +08:00
commit 01cc3eae3f
24 changed files with 553 additions and 260 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

@ -190,11 +190,11 @@ function NoticeContent({ visible, showNotification, resetUserInfo, current_user:
className='hoverNotice-body' // className
onPullRefresh={() => { setNoticePage(noticePage + 1); }} //ajaxfunction
// type={2} //
count={noticeUnreadList.length} //
count={noticeUnreadList&&noticeUnreadList.length} //
pageSize={10} //
>
{
noticeUnreadList.map(item => {
Array.isArray(noticeUnreadList)&& noticeUnreadList.map(item => {
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className={`noticeCont ${item.notification_url?'pointer':''}`}>

View File

@ -132,4 +132,13 @@ export function auditPassTask(data) {
method: 'post',
data
});
}
// 导师审核结果
export function getPassList(params) {
return fetch({
url: '/api/studentApply/passList',
method: 'get',
params,
});
}

View File

@ -1,5 +1,5 @@
import React, { Fragment, useEffect, useState } from 'react';
import { Checkbox, Input, message, Modal, Table, Tooltip, Breadcrumb, Tabs, Button } from 'antd';
import React, { useEffect, useState } from 'react';
import { Modal, Table, Tooltip, Breadcrumb, Tabs, Button } from 'antd';
import { Link } from 'react-router-dom';
import moment from 'moment';
import './index.scss';
@ -23,7 +23,7 @@ function Check({ current_user, showNotification, history }) {
const [taskId, setTaskId] = useState();
const [havePass, setHavePass] = useState(false);
const disabledCheck = new Date().getTime() > new Date('2022-07-01').getTime();
const disabledCheck = new Date().getTime() > new Date('2022-07-01 00:00:00').getTime();
const columns = [
{
@ -31,7 +31,7 @@ function Check({ current_user, showNotification, history }) {
className: "taskTableColumns",
dataIndex: 'studentName',
key: 'studentName',
width: '9%',
width: '12%',
ellipsis: true,
render: (text, record) => {
return (
@ -104,7 +104,7 @@ function Check({ current_user, showNotification, history }) {
dataIndex: 'memo',
className: 'taskTableColumns',
ellipsis: true,
width: '20%',
width: '18%',
render: (text, record) => {
return (
<Tooltip title={text}>
@ -124,15 +124,18 @@ function Check({ current_user, showNotification, history }) {
title: '操作',
dataIndex: 'passStatus',
align: 'center',
width: '9%',
width: '11%',
className: "actionColumns taskTableColumns",
render: ((text, record, index) => {
return (
<div className='actionBox'>
{
text ? <Button disabled={disabledCheck} type="default" onClick={() => { checkStudent(record.id, 0) }}>撤销</Button> :
<Button disabled={disabledCheck} type="primary" disabled={havePass} onClick={() => { checkStudent(record.id, 1) }}>通过</Button>
}
{/* 学生已入选并且锁定 */}
{record.locked && !record.used && <Tooltip title="恭喜,该学生已成功入选您的课题!"><Button disabled type="primary" className='greenColBor'>已入选</Button></Tooltip>}
{/* 学生已经被其他导师锁定 */}
{record.locked && record.used && <Tooltip title="此学生已入选其他课题"><Button disabled type="primary" className='redColBor'>已被选</Button></Tooltip>}
{/* 学生未被锁定 */}
{!record.locked && !record.used && (text ? <Button disabled={disabledCheck} type="default" onClick={() => { checkStudent(record.id, 0) }}>撤销</Button> :
<Button disabled={disabledCheck || havePass} type="primary" onClick={() => { checkStudent(record.id, 1) }}>通过</Button>)}
</div>
)
})
@ -140,6 +143,9 @@ function Check({ current_user, showNotification, history }) {
];
useEffect(() => {
if(new Date().getTime() > new Date('2022-07-01 0:0').getTime()){
history.push('/403');
}
if (!current_user.user_id) {
history.push('/403');
}
@ -176,16 +182,22 @@ function Check({ current_user, showNotification, history }) {
})
}
//
function toFirst(data, index){
if(index != 0){
data.unshift(data.splice(index,1)[0]);
}
}
const customExpandIcon = (props) => {
if (props.expanded) {
return <a className='actionBox' style={{ marginRight: 8 }} onClick={e => {
props.onExpand(props.record, e);
}}>更多详情<i className="iconfont icon-changyongtubiao-xianxingdaochu-zhuanqu- font-12 ml5 down mr10"></i></a>
}}>更多详情<i className="iconfont icon-changyongtubiao-xianxingdaochu-zhuanqu- font-12 ml5 down"></i></a>
} else {
return <a className='actionBox' style={{ marginRight: 8 }} onClick={e => {
props.onExpand(props.record, e);
}}>更多详情<i className="iconfont icon-jiantou9 font-12 ml5 down mr10"></i></a>
}}>更多详情<i className="iconfont icon-jiantou9 font-12 ml5 down"></i></a>
}
}
@ -221,6 +233,7 @@ function Check({ current_user, showNotification, history }) {
<div className="info-item">
<span className="info-tit">学生证明</span>
<img className="info-img"
alt=''
onClick={() => { setVisible(true); setPicture(record.proveAttachmentId) }}
src={`${window.location.href.indexOf('test') > -1 ||
window.location.href.indexOf('localhost') > -1
@ -257,8 +270,15 @@ function Check({ current_user, showNotification, history }) {
}
taskId && getStudentList(params).then(res => {
if (res.data && Array.isArray(res.data.rows)) {
setData(res.data.rows);
let isPass = res.data.rows.some((item) => { return item.passStatus });
const data = res.data.rows;
//
data.map((item, index)=>{
if(item.locked && !item.used){
toFirst(data, index);
}
})
setData(data);
let isPass = res.data.rows.some((item) => { return (item.passStatus && !(item.locked&&item.used)) || (item.locked && !item.used) });
setHavePass(isPass);
}
setLoading(false);
@ -276,8 +296,9 @@ function Check({ current_user, showNotification, history }) {
<h4 className="head_tit">审核说明</h4>
<div className="head_content">1欢迎进入导师审核页各位导师可查看到您发布课题的全部学生报名信息</div>
<div className="head_content">2您可根据学生报名信息与学生进行邮箱或电话沟通了解学生详细情况选择满意的学生</div>
<div className="head_content">3每个课题仅允许审核通过一个学生在审核过程中您可以随时调整各学生的审核状态</div>
<div className="head_content">4请各位导师在7.1日前完成课题申请的审核7.1日将根据各导师审核信息公布各课题学生入选名单</div>
<div className="head_content">3每个课题仅允许审核通过一个学生在审核过程中您可以随时调整各学生的审核状态直到与学生匹配成功</div>
{/* <div className="head_content">4、6月28日后各导师可访问 <a href='/glcc/result'>https://www.gitlink.org.cn/glcc/result</a> 查询匹配结果(需使用导师账号登录)</div> */}
<div className="head_content">4请各位导师在7月1日前完成课题申请的审核7月1日凌晨1点平台将根据各导师审核信息正式公布各课题学生入选名单</div>
</div>
<Tabs className="task-tabs" onChange={(e) => { setTaskId(e) }} activeKey={taskId + ''}>
@ -310,7 +331,6 @@ function Check({ current_user, showNotification, history }) {
<Modal
visible={visible && picture}
title="学生证明"
visible={visible}
onCancel={() => { setVisible(false) }}
onOk={() => { setVisible(false) }}
className="picture-modal"
@ -318,6 +338,7 @@ function Check({ current_user, showNotification, history }) {
footer={null}
>
<img
alt=''
src={`${window.location.href.indexOf('test') > -1 ||
window.location.href.indexOf('localhost') > -1
? 'https://testforgeplus.trustie.net'

View File

@ -178,6 +178,14 @@
}
}
}
.redColBor .ant-btn-primary[disabled]{
border-color: #e44141;
span{color: #e44141;}
}
.greenColBor .ant-btn-primary[disabled]{
border-color: rgb(40, 190, 108);
span{color: rgb(40, 190, 108);}
}
}
tr:hover .actionColumns .cancelApply {
visibility: visible;

View File

@ -0,0 +1,137 @@
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";
import './index.scss';
import '../project/index.scss';
const { Search } = Input;
//
function CheckResult({current_user, history}) {
//
const [keyword, setKeyword] = useState(undefined);
const [data, setData] = useState([]);
// table
const [current, setCurrent] = useState(1);
const [total, setTotal] = useState(0);
const [pageSize, setPageSize] = useState(20);
const [loading, setLoading] = useState(false);
const [expandedRowKeys, setExpandedRowKeys] = useState([]);
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(()=>{
//
if(new Date().getTime() < new Date('2022-06-28 1:0').getTime()){
history.push('/glcc');
}
hasAuditRole({ userId: current_user.user_id }).then(res => {
// 7.1
if (!(res && res.message == 'success' && res.data.hasRole) && new Date().getTime() < new Date('2022-07-01 1:0').getTime()) {
history.push('/glcc');
}
})
},[])
useEffect(() => {
setLoading(true);
setExpandedRowKeys([]);
const params = {
curPage: current,
keyword,
pageSize,
}
getPassList(params).then(response => {
if (response && response.message === "success") {
setData(response.data.rows);
setTotal(response.data.total);
}
setLoading(false);
})
}, [keyword, current, pageSize])
const columns = [
{ title: '序号', dataIndex: 'index', align: 'center', className:"columnsResult", width: '6%', render: (text, item, index) => <span>{(current-1)*pageSize+index + 1}</span> },
{ title: '入选学生', dataIndex: 'studentName', className:"columnsResult taskName", width: '12%', ellipsis: true},
{ title: '学生专业', dataIndex: 'profession', className:"columnsResult taskName", width: '12%', ellipsis: true, render: (text) => <Tooltip title={text} placement="topLeft"><span className='toolTipSpan'>{text}</span></Tooltip>},
{ title: '学生年级', dataIndex: 'grade', className:"columnsResult taskName", width: '10%', ellipsis: true},
{ title: '课题导师', dataIndex: 'tutorName', className:"columnsResult", width: '10%', ellipsis: true},
{ title: '课题名称', dataIndex: 'taskName', className:"columnsResult", width: '20%', ellipsis: true, render: (text, item) => <Tooltip title={text} placement="topLeft"><span className='toolTipSpan link' onClick={()=>{window.open(`/glcc/subjects/detail/${item.id}?locked=${item.locked}`)}}>{text}</span></Tooltip> },
{ title: '项目名称', dataIndex: 'projectName', className:"columnsResult", ellipsis: true, width: '14%', render: (text) => <Tooltip title={text} placement="topLeft"><span className='toolTipSpan'>{text}</span></Tooltip> },
{ title: '操作', dataIndex: 'action', align: 'center', className:"columnsResult actionBox"},
]
const customExpandIcon = (props) => {
if (props.expanded) {
return <a className='toolTipSpan link' style={{marginRight: 8 }} onClick={e => {
props.onExpand(props.record, e);
}}><i className='iconfont icon-ketixiangqingicon mr5'></i>项目简介<i className="iconfont icon-changyongtubiao-xianxingdaochu-zhuanqu- font-12 ml5 down mr10"></i></a>
} else {
return <a className='toolTipSpan link' style={{marginRight: 8 }} onClick={e => {
props.onExpand(props.record, e);
}}><i className='iconfont icon-ketixiangqingicon mr5'></i>项目简介<i className="iconfont icon-jiantou9 font-12 ml5 down mr10"></i></a>
}
}
const expandRow = (record) => {
return <ProjectDetail detail={null} projectId={record.regId} showTask={false}/>
}
//
function onExpand(expanded, record){
const keys = new Set(expandedRowKeys);
if(expanded){
keys.add(record.id);
}else{
keys.delete(record.id);
}
setExpandedRowKeys(Array.from(keys));
}
// pagesize
function onShowSizeChange(current, pageSize){
window.scrollTo(0, 0);
setCurrent(1);
setPageSize(pageSize);
}
//
function changePage(page, pageSize){
window.scrollTo(0, 0);
setCurrent(page);
}
return (
<div className="resultListBox">
{time && <img className="resultBanner" src={resultBanner} alt=""></img>}
{new Date().getTime() > new Date('2022-07-01 1:0').getTime() && <img className="resultBanner" src={resultBanner2} alt=""></img>}
<div className='bgBox'>
<div className="resultList">
<div className='goBackBox'><a href='/glcc'>开源夏令营 / </a>入选学生名单{time && '预'}公示</div>
<Search className='search' placeholder='请输入学生姓名或课题名称进行搜索' allowClear enterButton onSearch={(value) => { setCurrent(1); setKeyword(value) }} />
<Table
loading={loading}
columns={columns}
dataSource={data}
expandedRowRender={expandRow}
expandIconColumnIndex={7}
expandIconAsCell={false}
expandIcon={customExpandIcon}
rowKey={'id'}
expandedRowKeys={expandedRowKeys}
onExpand={onExpand}
pagination={{current: current, pageSize: pageSize, total: total, showSizeChanger: true, onShowSizeChange:onShowSizeChange, showQuickJumper: true, onChange: changePage}}
className='resultListTable pb30'
/>
</div>
<img src={bgPng} alt='' className='bgPng3'/>
<img src={bgPng} alt='' className='bgPng4'/>
</div>
</div>
)
}
export default CheckResult;

View File

@ -0,0 +1,88 @@
.resultListBox{
background-image:linear-gradient(180deg,#e9f0ff 0%,#dee8ff 51.87%,#f3f4f8 100%);
.bgBox{
padding-bottom: 115px;
position: relative;
.bgPng3, .bgPng4{
width: 146px;
position: absolute;
z-index: 0;
top: 210px;
left: 150px;
}
.bgPng4{
top: 450px;
left: auto;
right: 310px;
}
}
.resultBanner{
width: 100%;
}
.resultList{
width: 1200px;
margin: 0 auto;
position: relative;
z-index: 1;
}
.goBackBox{
padding: 25px 0 8px;
color: #202d40;
font-size: 16px;
border-bottom: 1px dashed #bec5d5;
margin-bottom: 20px;
a{
color:#a4aabb;
}
}
.search{
width:509px;
height:48px;
display: block;
margin: 0 auto;
.ant-input-search-button{
height:48px;
}
}
.resultListTable{
margin-top: 20px;
background-color:rgba(255, 255, 255, 0.27);
border: 1px solid white;
.ant-table-placeholder{
background-color: rgba(255, 255, 255, 0.27);
border-bottom: none;
}
th.columnsResult{
background-color:#DFE8FF;
.ant-table-column-title{
font-weight:700;
color:#273778;
font-size:16px;
}
&.actionBox .ant-table-column-title{
visibility: hidden;
}
}
td.columnsResult{
background-color: #ECF2FF;
border-bottom: 1px dashed #bec5d5;
font-size: 15px;
color:#353f5e;
}
tr:hover td.columnsResult{
background-color:#fbfbfc;
}
.ant-pagination{
margin: 26px 20px 0 0;
}
}
.toolTipSpan{
cursor: default;
&.link{
color: #2545c9;
cursor: pointer;
&:hover{color:#5d7cff;}
&:active{color: #1140ff;}
}
}
}

View File

@ -17,7 +17,7 @@ import { hasAuditRole } from '../api';
import './index.scss';
export default (props) => {
const { current_user, isGlccApplyDate, showNotification, studentApplyStart, history, studentApplyEnd } = props;
const { current_user, isGlccApplyDate, showNotification, studentApplyStart, history, secondStudentApplyDate, isStudentApplyDate } = props;
// function goToApply() {
// if (isGlccApplyDate) {
// if (current_user && current_user.login) {
@ -32,6 +32,8 @@ export default (props) => {
// }
const [hasRole, setHhasRole] = useState(false);
const resultTime1 = new Date().getTime() > new Date('2022-06-28 1:0').getTime() && new Date().getTime() < new Date('2022-07-01 0:0').getTime();
const resultTime2 = new Date().getTime() > new Date('2022-07-01 1:0').getTime();
useEffect(() => {
if (!current_user.user_id) {
@ -48,7 +50,7 @@ export default (props) => {
//
if (!studentApplyStart) {
showNotification("不在报名时间报名开始时间为5月26日");
} else if(studentApplyEnd) {
} else if(!isStudentApplyDate && !secondStudentApplyDate) {
showNotification("课题申请时间已截止");
} else{
history.push("/glcc/subjects");
@ -59,6 +61,10 @@ export default (props) => {
history.push("/glcc/mentoradmin");
}
function goToCheckResult(){
history.push("/glcc/result");
}
return (
<div className="glcc">
{/* <Banner /> */}
@ -78,18 +84,26 @@ export default (props) => {
<span className="hover-none"><span className="til">查看项目</span> </span>
{/* <span className="hover-show">项目报名已截止</span> */}
</div>
<div className="pt6">查看夏令营各项目掌握项目课题详细信息</div>
<div className="pt6">掌握项目课题详细信息</div>
</Link>
{/* 学生报名 */}
{/* 学生报名6.24结束第一次报名6.29 1:00 - 6.30 24:00第二次报名 */}
<div className="apply" onClick={goToStudent}>
<div>
<img src={apply2} alt="" className="applyIcon" />
<span className="til">学生报名</span>
</div>
<div className="pt6">选择感兴趣的课题开启您的开源之旅</div>
<div className="pt6">选择课题开启您的开源之旅</div>
</div>
{/* 6.28.-7.1 审核结果仅对导师可见7.1之后对所有用户可见*/}
{resultTime2 && <div className="apply" onClick={goToCheckResult}>
<div>
<img src={apply2} alt="" className="applyIcon" />
<span className="til">名单{resultTime1 && '预'}公示</span>
</div>
<div className="pt6">查看各课题入选学生名单</div>
</div>}
{/* 导师审核 */}
{hasRole && <div className="apply" onClick={goToCheck}>
{hasRole && new Date().getTime() < new Date('2022-07-01 0:0').getTime() && <div className="apply" onClick={goToCheck}>
<div>
<img src={teacher} alt="" className="applyIcon" />
<span className="til">导师审核</span>
@ -118,7 +132,7 @@ export default (props) => {
</div>
</div>
</div>
<Lightspot isGlccApplyDate={isGlccApplyDate} current_user={current_user} showNotification={showNotification} studentApplyStart={studentApplyStart} studentApplyEnd={studentApplyEnd}/>
<Lightspot isGlccApplyDate={isGlccApplyDate} current_user={current_user} showNotification={showNotification} goToStudent={goToStudent}/>
<TimerShaft />
<Award />
<News />

View File

@ -24,6 +24,7 @@
}
.applyBox {
width: 1200px;
position: absolute;
top: 21vw;
left: 17.5vw;
@ -42,7 +43,7 @@
flex-direction: column;
justify-content: center;
width: 355px;
height: 118px;
&:not(:first-child){
margin-left: 35px;
}

View File

@ -12,7 +12,7 @@ import { Link } from 'react-router-dom';
function Lightspot(props) {
const {current_user, isGlccApplyDate, showNotification, studentApplyStart, studentApplyEnd} = props;
const {current_user, isGlccApplyDate, showNotification, goToStudent} = props;
function goToApply(){
if(isGlccApplyDate){
@ -27,17 +27,6 @@ function Lightspot(props) {
}
}
function goToStudent(){
//
if(!studentApplyStart){
showNotification("不在报名时间报名开始时间为5月26日");
} else if(studentApplyEnd) {
showNotification("课题申请时间已截止");
}else{
window.location.href="/glcc/subjects";
}
}
return (
<div className="lightspot">
<div className="glcc-content">

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

View File

@ -1,4 +1,4 @@
import React from "react";
import React, {useState, useEffect} from "react";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
@ -11,9 +11,8 @@ import "./index.scss";
import Loadable from "react-loadable";
import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
import { useState } from "react";
import { useEffect } from "react";
import { getStudentApplyInfo } from "./api";
import { message } from "antd";
//
@ -57,22 +56,28 @@ const Openmmlab = Loadable({
loader: () => import("./openmmlab"),
loading: Loading,
});
//
const Result = Loadable({
loader: () => import("./checkResult"),
loading: Loading,
});
const Glcc = (propsF) => {
const {current_user} = propsF;
const {current_user, showLoginDialog} = propsF;
// 415~520
const isGlccApplyDate = Date.parse(new Date()) < 1653062400000;
// new Date().getTime() > new Date('2022-05-26').getTime()
//
const studentApplyStart = new Date().getTime() > new Date('2022-05-26').getTime();
const isStudentApplyDate = new Date().getTime() > new Date('2022-05-26').getTime() && new Date().getTime() < new Date('2022-06-25 0:0').getTime();
const studentApplyEnd = new Date().getTime() > new Date('2022-06-25 0:0').getTime();
const secondStudentApplyDate = new Date().getTime() > new Date('2022-06-29 1:0').getTime() && new Date().getTime() < new Date('2022-06-30 0:0').getTime();
// id
const [applyTaskId, setApplyTaskId] = useState({});
//
const [studentInfoReset, setStudentInfoReset] = useState(undefined);
const [cancelCount,setCancelCount]=useState(0);
//
const [lockedTaskName, setLockedTaskName] = useState(undefined);
useEffect(()=>{
// current_user user_id
@ -82,6 +87,7 @@ const Glcc = (propsF) => {
const data = {};
response.data && response.data.registrationStudentTaskList.map(item=>{
data[item.taskId] = item.id;
item.locked && setLockedTaskName(item.taskName);
})
setApplyTaskId(data);
response.data&&setCancelCount(Number(response.data.cancelCount));
@ -89,6 +95,25 @@ const Glcc = (propsF) => {
})
},[studentInfoReset, current_user])
//
function applyTask(id){
//
if(current_user && current_user.login){
//
if(lockedTaskName){
message.error(`由于你已入选 ${lockedTaskName} 课题,无法申请其他课题`);
}else if(applyTaskId && Object.keys(applyTaskId).length >= 3){
//
message.error('最多只能同时报名三个课题');
}else{
//
window.location.href=`/glcc/student/apply/${id}`;
}
}else{
showLoginDialog();
}
}
return (
<div className="newMain clearfix">
<Switch {...propsF}>
@ -123,14 +148,14 @@ 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} secondStudentApplyDate={secondStudentApplyDate} applyTaskId={applyTaskId} applyTask={applyTask} />
)}
></Route>
{/* 项目/课题列表 */}
<Route
path="/glcc/projects"
render={(props) => (
<Project {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset}/>
<Project {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} applyTask={applyTask}/>
)}
></Route>
@ -138,7 +163,7 @@ const Glcc = (propsF) => {
<Route
path="/glcc/subjects"
render={(props) => (
<Project {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} cancelCount={cancelCount}/>
<Project {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} cancelCount={cancelCount} applyTask={applyTask}/>
)}
></Route>
@ -146,7 +171,15 @@ const Glcc = (propsF) => {
<Route
path="/glcc/openmmlab"
render={(props) => (
<Openmmlab {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset}/>
<Openmmlab {...propsF} {...props} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate} applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} applyTask={applyTask}/>
)}
></Route>
{/* 审核结果页面 */}
<Route
path="/glcc/result"
render={(props) => (
<Result current_user={current_user} history={props.history}/>
)}
></Route>
@ -154,7 +187,7 @@ const Glcc = (propsF) => {
<Route
path="/glcc"
render={(props) => (
<Home {...propsF} {...props} studentApplyStart={studentApplyStart} studentApplyEnd={studentApplyEnd}/>
<Home {...propsF} {...props} studentApplyStart={studentApplyStart} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate}/>
)}
></Route>

View File

@ -7,7 +7,7 @@ const $ = window.$;
const { TabPane } = Tabs;
function ProjectTabs({ list, applyTaskId, history, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd }) {
function ProjectTabs({ list, applyTaskId, history, current_user, showLoginDialog, isStudentApplyDate, secondStudentApplyDate, applyTask }) {
useEffect(()=>{
setTimeout(()=>{
@ -34,7 +34,7 @@ function ProjectTabs({ list, applyTaskId, history, current_user, showLoginDialog
key={i + ''} >
<div className="tab_content">
<div className="openmmlab_tab_content">
<ProjectDetail detail={item} applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} />
<ProjectDetail detail={item} applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate} applyTask={applyTask}/>
</div>
</div>

View File

@ -3,25 +3,9 @@ import { Button, message, Tooltip } from 'antd';
import Nodata from '../../../forge/Nodata';
import { getProjectById } from '../../api';
export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd }) => {
export default ({ detail, projectId, applyTaskId, isStudentApplyDate, secondStudentApplyDate, applyTask }) => {
const [info, setInfo] = useState(detail);
//
function applyTask(id){
//
if(current_user && current_user.login){
//
if(applyTaskId && Object.keys(applyTaskId).length >= 2){
message.error('最多只能同时报名两个课题');
}else{
//
window.location.href=`/glcc/student/apply/${id}`;
}
}else{
showLoginDialog();
}
}
useEffect(()=>{
if(!detail && projectId){
// Id
@ -42,7 +26,7 @@ export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog,
{info.registrationTaskList && info.registrationTaskList.length > 0 ? info.registrationTaskList.map((item, index)=>{
return <div className='taskItem mt15' key={index}>
<div className="left">
<div className="taskTitle" onClick={()=>{window.location.href=`/glcc/subjects/detail/${item.id}`}}><Tooltip title={item.taskName}>{item.taskName}</Tooltip></div>
<div className="taskTitle" onClick={()=>{window.location.href=`/glcc/subjects/detail/${item.id}?locked=${item.locked}`}}><Tooltip title={item.taskName}>{item.taskName}</Tooltip></div>
<div className='mt15 oneLine leftWidth'>导师姓名: &nbsp;&nbsp;{item.tutorName}</div>
{item.tutorMail && <div className='mb15 email oneLine leftWidth'>邮箱地址: &nbsp;&nbsp;<span><Tooltip title={item.tutorMail}>{item.tutorMail}</Tooltip></span></div>}
</div>
@ -50,8 +34,17 @@ export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog,
<div className="taskDesc">{item.taskDesc}</div>
{item.taskUrl && <div className="taskUrl oneLine">课题链接: &nbsp;&nbsp;<a href={item.taskUrl} target={"_blank"}>{item.taskUrl}</a></div>}
<div>
{(isStudentApplyDate || studentApplyEnd) && (applyTaskId && item.id && Object.keys(applyTaskId).includes(item.id.toString()) ? <Button onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}} className='lookDetail mr10'>报名详情</Button> : isStudentApplyDate && <Button type='primary' className='applyBut mr10' onClick={()=>{applyTask(item.id)}}>申请课题</Button>)}
<Button onClick={()=>{window.open(`/glcc/subjects/detail/${item.id}`)}} className='lookDetail'>课题详情</Button>
{/* 报名详情按钮 */}
{applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && <Button onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}} className='lookDetail mr10'>报名详情</Button>}
{/* 课题申请时间范围内: 申请课题 */}
{/* 第一次报名 */}
{isStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && <Button type='primary' className='applyBut mr10' onClick={()=>{applyTask(item.id)}}>申请课题</Button>}
{/* 第二次报名 锁定状态 */}
{secondStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? <Tooltip title={"该课题已有学生入选"}><Button type='primary' className='mr10' disabled>申请课题</Button></Tooltip> : <Button type='primary' className='applyBut mr10' onClick={()=>{applyTask(item.id)}}>申请课题</Button>)}
{/* 查看课题详情按钮 */}
<Button onClick={()=>{window.open(`/glcc/subjects/detail/${item.id}?locked=${item.locked}`)}} className='lookDetail'>课题详情</Button>
</div>
</div>
<div className="right oneLine taskUrl"><span className='taskReward'>{item.taskReward}</span></div>

View File

@ -4,27 +4,9 @@ import Nodata from '../../../forge/Nodata';
import { useEffect } from 'react';
import { getProjectById } from '../../api';
export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, showNotification }) => {
export default ({ detail, projectId, applyTaskId, isStudentApplyDate, secondStudentApplyDate, showTask=true, applyTask }) => {
const [info, setInfo] = useState(detail);
//
function applyTask(id){
//
if(current_user && current_user.login){
//
if(studentApplyEnd) {
showNotification("课题申请时间已截止");
}else if(applyTaskId && Object.keys(applyTaskId).length >= 2){
message.error('最多只能同时报名两个课题');
}else{
//
window.location.href=`/glcc/student/apply/${id}`;
}
}else{
showLoginDialog();
}
}
useEffect(()=>{
if(!detail && projectId){
// Id
@ -38,16 +20,17 @@ export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog,
return (
info ? <div className={`projectDetailBox ${detail ? '':'byTask'}`}>
<div className="projectDetailHead">
<div className={`projectDetailHead ${showTask? '' : 'byResult'}`}>
<span className='name'>{info.projectName}</span>
{info.projectType && <span className='type'>{info.projectType}</span>}
<p>GitLink项目地址:&nbsp;&nbsp;<a href={info.gitlinkUrl} className='linkUrl' target={"_blank"}>{info.gitlinkUrl}</a></p>
<div>项目简介:&nbsp;&nbsp;{info.projectIntro}</div>
</div>
{info.registrationTaskList && info.registrationTaskList.length > 0 ? info.registrationTaskList.map((item, index)=>{
{/* 从项目、课题列表展开的显示课题列表,结果公示页展开的不显示课题列表 */}
{showTask && (info.registrationTaskList && info.registrationTaskList.length > 0 ? info.registrationTaskList.map((item, index)=>{
return <div className='taskItem mt20' key={index}>
<div className="left">
<div className="taskTitle" onClick={()=>{window.location.href=`/glcc/subjects/detail/${item.id}`}}><Tooltip title={item.taskName}>{item.taskName}</Tooltip></div>
<div className="taskTitle" onClick={()=>{window.location.href=`/glcc/subjects/detail/${item.id}?locked=${item.locked}`}}><Tooltip title={item.taskName}>{item.taskName}</Tooltip></div>
<div className='mt20 oneLine leftWidth'>导师姓名: &nbsp;&nbsp;{item.tutorName}</div>
{item.tutorMail && <div className='mb20 email oneLine leftWidth'>邮箱地址: &nbsp;&nbsp;<span><Tooltip title={item.tutorMail}>{item.tutorMail}</Tooltip></span></div>}
</div>
@ -55,13 +38,22 @@ export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog,
<div className="taskDesc">{item.taskDesc}</div>
{item.taskUrl && <div className="taskUrl oneLine">课题链接: &nbsp;&nbsp;<a href={item.taskUrl} target={"_blank"}>{item.taskUrl}</a></div>}
<div>
{(isStudentApplyDate || studentApplyEnd) && (applyTaskId && item.id && Object.keys(applyTaskId).includes(item.id.toString()) ? <Button onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}} className='lookDetail mr10'>报名详情</Button> : isStudentApplyDate && <Button type='primary' className='applyBut mr10' onClick={()=>{applyTask(item.id)}}>申请课题</Button>)}
<Button onClick={()=>{window.open(`/glcc/subjects/detail/${item.id}`)}} className='lookDetail'>课题详情</Button>
{/* 报名详情按钮 */}
{applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && <Button onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}} className='lookDetail mr10'>报名详情</Button>}
{/* 课题申请时间范围内: 申请课题 */}
{/* 第一次报名 */}
{isStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && <Button type='primary' className='applyBut mr10' onClick={()=>{applyTask(item.id)}}>申请课题</Button>}
{/* 第二次报名 锁定状态 */}
{secondStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? <Tooltip title={"该课题已有学生入选"}><Button type='primary' className='mr10' disabled>申请课题</Button></Tooltip> : <Button type='primary' className='applyBut mr10' onClick={()=>{applyTask(item.id)}}>申请课题</Button>)}
{/* 查看课题详情按钮 */}
<Button onClick={()=>{window.open(`/glcc/subjects/detail/${item.id}?locked=${item.locked}`)}} className='lookDetail'>课题详情</Button>
</div>
</div>
<div className="right oneLine taskUrl"><span className='taskReward'>{item.taskReward}</span></div>
</div>
}) : <Nodata _html="课题暂无数据" small={true}/>}
}) : <Nodata _html="课题暂无数据" small={true}/>)}
</div>: <div className="projectDetailBox nodata"><Nodata _html="暂无数据" small={true}/></div>
)
}

View File

@ -20,7 +20,7 @@ const TaskList = Loadable({
});
function Project(propsF) {
const {location, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, applyTaskId, setStudentInfoReset, cancelCount} = propsF;
const {location} = propsF;
const {pathname} = location;
useEffect(()=>{
window.scrollTo(0, 0);

View File

@ -108,6 +108,10 @@
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;

View File

@ -10,7 +10,7 @@ import star from "../../img/star.png";
const { Search } = Input;
//
function ProjectList({ applyTaskId, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, location, showNotification, match }) {
function ProjectList({ applyTaskId, isStudentApplyDate, location, match, secondStudentApplyDate, applyTask }) {
let gitlinkLastUrl = match.params.gitlinkLastUrl && match.params.gitlinkLastUrl.replace(/\./g, '');
let openmmlab = location.search && location.search.split('=')[1];
//
@ -83,19 +83,14 @@ function ProjectList({ applyTaskId, current_user, showLoginDialog, isStudentAppl
onVisibleChange={(visible) => { changeVisible(visible, item) }}
key={index}
placement={(index + 1) % 3 === 0 ? 'bottomRight' : (index + 1) % 3 % 2 === 0 ? 'bottom' : 'bottomLeft'}
content={<ProjectDetail detail={item} applyTaskId={applyTaskId} current_user={current_user}
showLoginDialog={showLoginDialog}
isStudentApplyDate={isStudentApplyDate}
studentApplyEnd={studentApplyEnd}
showNotification={showNotification}
/>}
content={<ProjectDetail detail={item} applyTaskId={applyTaskId} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate} applyTask={applyTask}/>}
trigger='click'
overlayClassName='projectItemPopover'
autoAdjustOverflow={false}
>
<div className={`projectItem ${(index + 1) % 3 === 0 || (index + 1) % 3 % 2 === 0 ? '' : 'firstBox'} ${item.projectName.replace(/ /g, '')} ${item.gitlinkLastUrl.replace(/\./g, '')}`}>
<div className="border"></div>
{!gitlinkLastUrl && !openmmlab && item.recommendFlag ? <img className="projectLogoStar" src={star} /> : ''}
{!gitlinkLastUrl && !openmmlab && item.recommendFlag ? <img className="projectLogoStar" src={star} alt=''/> : ''}
<div className="projectLogo">
<img className="projectLogoImg" src={item.projectLogoId ? `${main_site_url}/api/attachments/${item.projectLogoId}` : logo} alt='' />
</div>

View File

@ -1,15 +1,15 @@
import React, {useEffect, useState } from 'react';
import { Button, message, Spin} from 'antd';
import { Button, Spin, Tooltip} from 'antd';
import { getTaskById } from '../../api';
import bgPng from "../../img/bgPng.png";
import '../index.scss';
import './index.scss';
import { getTaskById } from '../../api';
import banner from "../../img/studentProject.png";
import bgPng from "../../img/bgPng.png";
//
function TaskDetail(props) {
const {match, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, applyTaskId, showNotification} = props
const {match, location, isStudentApplyDate, secondStudentApplyDate, applyTaskId, applyTask} = props
const taskId = Number(match.params.taskId);
const locked = location.search && location.search.split('=')[1] === 'true';
const [detail, setDetail] = useState(undefined);
useEffect(()=>{
@ -20,24 +20,6 @@ function TaskDetail(props) {
})
},[])
//
function applyTask(id){
//
if(current_user && current_user.login){
//
if(studentApplyEnd) {
showNotification("课题申请时间已截止");
} else if(applyTaskId && Object.keys(applyTaskId).length >= 2){
message.error('最多只能同时报名两个课题');
}else{
//
window.location.href=`/glcc/student/apply/${id}`;
}
}else{
showLoginDialog();
}
}
return (
<div className="taskDetailBgBox">
{/* <img className="glcc-banner" src={banner} alt=''></img> */}
@ -66,7 +48,14 @@ function TaskDetail(props) {
<div><span className='smallTil'>课题简介</span></div>
<div className='desc'>{detail.taskDesc}</div>
</div>
{(isStudentApplyDate || studentApplyEnd) && (applyTaskId && taskId && Object.keys(applyTaskId).includes(taskId.toString()) ? <Button onClick={()=>{window.location.href=`/glcc/student/apply/${taskId}`}} className='lookDetail detailBut'>报名详情</Button> : isStudentApplyDate && <Button type='primary' className='applyBut detailBut' onClick={()=>{applyTask(taskId)}}>申请课题</Button>)}
{/* 报名详情按钮 */}
{applyTaskId && Object.keys(applyTaskId).includes(taskId.toString()) && <Button onClick={()=>{window.location.href=`/glcc/student/apply/${taskId}`}} className='lookDetail detailBut'>报名详情</Button>}
{/* 课题申请时间范围内: 申请课题 */}
{/* 第一次报名 */}
{isStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(taskId.toString())) && <Button type='primary' className='applyBut detailBut' onClick={()=>{applyTask(taskId)}}>申请课题</Button>}
{/* 第二次报名 锁定状态 */}
{secondStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(taskId.toString())) && (locked ? <Tooltip title={"该课题已有学生入选"}><Button type='primary' className='mr10' disabled>申请课题</Button></Tooltip> : <Button type='primary' className='applyBut mr10' onClick={()=>{applyTask(taskId)}}>申请课题</Button>)}
</div>
<img src={bgPng} alt='' className='bgPng1'/>
<img src={bgPng} alt='' className='bgPng2'/>

View File

@ -7,7 +7,7 @@ import bgPng from "../../img/bgPng.png";
const { Search } = Input;
//
function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd,cancelCount,showNotification}) {
function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDialog, isStudentApplyDate, secondStudentApplyDate,cancelCount,showNotification, applyTask}) {
const [visible, setVisible] = useState(false);
const [deleteTaskId, setDeleteTaskId] = useState(undefined);
//
@ -24,19 +24,25 @@ 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: '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: '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}?locked=${item.locked}`)}}>{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: 'taskReward', className:"taskTableColumns", ellipsis: true, width: '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>
{!studentApplyEnd && <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>)}
{/* 报名详情按钮 */}
{applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && <span onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}}><i className='iconfont icon-baomingxiangqingicon mr5'></i>报名详情</span>}
{/* 取消按钮5.26-6.25 */}
{applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) && isStudentApplyDate && <Tooltip title={"取消申请"}><i className='iconfont icon-shanchuicon3 ml20 cancelApply' onClick={()=>{deleteItem(item.id)}}></i></Tooltip>}
{/* 课题申请时间范围内: 申请课题 */}
{/* 第一次报名 */}
{isStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && <span onClick={()=>{applyTask(item.id)}}><i className='iconfont icon-shenqingketiicon applyTask mr5'></i><span className='applyTask'>申请课题</span></span>}
{/* 第二次报名 锁定状态 */}
{secondStudentApplyDate && !(applyTaskId && Object.keys(applyTaskId).includes(item.id.toString())) && (item.locked ? <Tooltip title={"该课题已有学生入选"}><span className='disabled'><i className='iconfont icon-shenqingketiicon mr5 disabled'></i><span className='disabled'>申请课题</span></span></Tooltip> : <span onClick={()=>{applyTask(item.id, item.locked)}}><i className='iconfont icon-shenqingketiicon applyTask mr5'></i><span className='applyTask'>申请课题</span></span>)}
</div>
)
})
@ -65,7 +71,7 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
}
const expandRow = (record) => {
return <ProjectDetail detail={null} projectId={record.regId} applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd} showNotification={showNotification}/>
return <ProjectDetail detail={null} projectId={record.regId} applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} showNotification={showNotification} secondStudentApplyDate={secondStudentApplyDate} applyTask={applyTask}/>
}
//
@ -79,24 +85,6 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
setExpandedRowKeys(Array.from(keys));
}
//
function applyTask(id){
//
if(current_user && current_user.login){
//
if(studentApplyEnd) {
showNotification("课题申请时间已截止");
} else if(applyTaskId && Object.keys(applyTaskId).length >= 2){
message.error('最多只能同时报名两个课题');
}else{
//
window.location.href=`/glcc/student/apply/${id}`;
}
}else{
showLoginDialog();
}
}
//
function cancelApply(){
const id = [];

View File

@ -38,6 +38,11 @@
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;

View File

@ -28,16 +28,19 @@ function Apply(props) {
//
// current_user && (current_user.user_id = 6)
// current_user && (current_user.userName = "使")
const isStudentApplyDate = new Date().getTime() > new Date('2022-05-26').getTime() && new Date().getTime() < new Date('2022-06-25 0:0').getTime();
const studentApplyEnd = new Date().getTime() > new Date('2022-06-25 0:0').getTime();
const isStudentApplyDate = new Date().getTime() > new Date('2022-06-29 01:00:00').getTime() && new Date().getTime() < new Date('2022-07-01 01:00:00').getTime();
const studentApplyEnd = new Date().getTime() > new Date('2022-07-01 01:00:00').getTime();
const { getFieldDecorator, validateFields, setFieldsValue, validateFieldsAndScroll } = form;
const [imageUrl, setImageUrl] = useState(undefined);
const [loading, setLoading] = useState(false);
const [reload, setReload] = useState();
const [locked, setLocked] = useState(false);
const [userApplyInfo, setUserApplyInfo] = useState(undefined);
const [editable, setEditable] = useState(isStudentApplyDate);
const [files, setFiles] = useState([]);
const [files1, setFiles1] = useState([]);
const [files2, setFiles2] = useState([]);
console.log('isStudentApplyDate:' + isStudentApplyDate)
const initTask = {
taskId,
memo: '',
@ -102,31 +105,40 @@ function Apply(props) {
if (Array.isArray(data.registrationStudentTaskList)) {
if (data.registrationStudentTaskList.length) {
let initTaskList = [];
let lockedCurrent = false;
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) {
lockedCurrent = item.locked;
}
if (i == 0) {
item.memoAttachment && setFiles([{
name: item.memoAttachment && item.memoAttachment.fileName || '已上传文件',
id: item.memoAttachmentId,
uid: item.memoAttachmentId
}]);
} else {
} 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,
}]);
}
if(item.enrollFirst){
applyInfo.enrollFirst=i;
}
// if (item.enrollFirst) {
// applyInfo.enrollFirst = i;
// }
if(item.status==2){
item.status==2
if (item.status == 2) {
item.status == 2
}
initTaskList.push(item);
@ -138,9 +150,10 @@ function Apply(props) {
// });
}
setMyTaskList(initTaskList);
// idid
if (data.registrationStudentTaskList.length === 1 && data.registrationStudentTaskList[0].taskId != taskId) {
setLocked(lockedCurrent);
// 3idid
let taskIdArr=data.registrationStudentTaskList.map(i=>{return i.taskId});
if (!lockedCurrent && data.registrationStudentTaskList.length < 3 && !taskIdArr.includes(taskId)) {
addTask(data.registrationStudentTaskList);
}
} else {
@ -183,15 +196,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;
}
}
// 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(),
@ -205,6 +218,7 @@ function Apply(props) {
registrationStudentTaskList: myTaskList
}
if (userApplyInfo) {
params.id = userApplyInfo.id;
studentApplyEdit(params).then(response => {
@ -293,8 +307,10 @@ function Apply(props) {
changeTaskItem('memoAttachmentId', '', i);
}
console.log(info.fileList);
if (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));
}
@ -315,46 +331,47 @@ function Apply(props) {
let taskListNew = List ? [...List] : [...myTaskList];
if (taskId != taskListNew[0].taskId) {
taskListNew.push(initTask);
let newTask = 'taskId' + (taskListNew.length - 1);
//
new Promise((resove) => {
setMyTaskList(() => {
resove();
return taskListNew
});
}).then(res => setFieldsValue({ 'taskId1': taskId }))
}).then(res => setFieldsValue({ [newTask]: taskId }))
} else {
taskListNew.push({ ...initTask, taskId: '' });
setMyTaskList(taskListNew);
}
}
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([]);
}
// 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);
}
// taskListNew.splice(i, 1);
// setMyTaskList(taskListNew);
// setFieldsValue(reWriteInfo);
// }
function changeTaskItem(field, val, i) {
let taskListNew = [...myTaskList];
@ -390,31 +407,32 @@ function Apply(props) {
<div className="form-tit">申请课题</div>
<Form className="glcc_info_form" onSubmit={handleSubmit}>
<h4 className="item-tit">基本信息</h4>
{/* className={editable ? "" : "disabledInput"} disabled={editable ?false : true} */}
{helper('学生姓名',
'',
'studentName',
[{ required: true, message: "请正确输入学生姓名" },
{ max: 32, message: '超出限制长度32位字符请重新编辑' }],
<Input placeholder="请输入学生姓名" onBlur={() => { verify("studentName") }} className={editable ? "" : "disabledInput"} disabled={editable ? false : true} />
<Input placeholder="请输入学生姓名" onBlur={() => { verify("studentName") }} className={"disabledInput"} disabled />
)}
{helper('所在高校',
'',
'school',
[{ required: true, message: "请正确输入所在高校" },
{ max: 32, message: '超出限制长度32位字符请重新编辑' }],
<Input placeholder="请输入所在高校" onBlur={() => { verify("school") }} className={editable ? "" : "disabledInput"} disabled={editable ? false : true} />
<Input placeholder="请输入所在高校" onBlur={() => { verify("school") }} className={"disabledInput"} disabled />
)}
{helper('所学专业',
'',
'profession',
[{ max: 32, message: '超出限制长度32位字符请重新编辑' }],
<Input placeholder="请输入所学专业" onBlur={() => { verify("profession") }} className={editable ? "" : "disabledInput"} disabled={editable ? false : true} />
<Input placeholder="请输入所学专业" onBlur={() => { verify("profession") }} className={"disabledInput"} disabled />
)}
<Form.Item label="地区">
{getFieldDecorator("location", {
rules: []
})(
<Cascader expandTrigger="hover" popupClassName="glcc_cascader" placeholder="请选择省份城市" options={locData} className={editable ? "" : "disabledInput"} disabled={editable ? false : true} />
<Cascader expandTrigger="hover" popupClassName="glcc_cascader" placeholder="请选择省份城市" options={locData} className={"disabledInput"} disabled />
)}
</Form.Item>
{helper('所在年级',
@ -431,7 +449,7 @@ function Apply(props) {
[{ required: true, message: "请正确输入联系电话" },
{ max: 14, message: '超出限制长度14位字符请重新编辑' },
{ pattern: /(^(\d{3,4}-)?\d{7,8})$|([1][3,4,5,6,7,8,9][0-9]{9})/, message: '请正确输入联系电话' }],
<Input placeholder="请输入联系电话" onBlur={() => { verify("phone") }} className={editable ? "" : "disabledInput"} disabled={editable ? false : true} />
<Input placeholder="请输入联系电话" onBlur={() => { verify("phone") }} className={"disabledInput"} disabled />
)}
{helper('邮箱地址',
'',
@ -441,7 +459,7 @@ function Apply(props) {
{ required: true, message: "请输入邮箱地址" },
{ max: 50, message: '超出限制长度50位字符请重新编辑' },
],
<Input placeholder="请输入邮箱地址" onBlur={() => { verify("mail") }} className={editable ? "" : "disabledInput"} disabled={editable ? false : true} />
<Input placeholder="请输入邮箱地址" onBlur={() => { verify("mail") }} className={"disabledInput"} disabled />
)}
<div className='introArea update_item'>{helper('学生证明',
@ -456,7 +474,7 @@ function Apply(props) {
accept=".png,.jpg,.jpeg"
beforeUpload={beforeUpload}
onChange={handleChange}
disabled={studentApplyEnd}
disabled
>
{imageUrl ? <img src={imageUrl} alt="avatar" style={{ maxWidth: '100px', maxHeight: '100px' }} /> : userApplyInfo && userApplyInfo.proveAttachmentId ?
<div><img src={`${getUrl()}/api/attachments/${userApplyInfo.proveAttachmentId}`} alt='' style={{ maxWidth: '100px' }} /></div> : <div>
@ -470,12 +488,12 @@ 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)
<h4 className="item-tit">课题信息<span className="item-tit-num">{i + 1}</span>)
{/* {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" dangerouslySetInnerHTML={{ __html: item.auditRemark }}></div>
<div className="mb5 ml20">希望您尽快修改并重新提交报名信息我们将再次审核万分感谢</div>
</div>}
{helper('课题名称',
@ -495,6 +513,7 @@ function Apply(props) {
{allTaskList.map(item => { return <Option value={item.id} disabled={chooseArr.includes(item.id)} key={item.id + ''}>{item.taskName}</Option> })}
</Select>
)}
{item.locked && item.passStatus && <div className="task-checked"><i className='iconfont icon-chenggongicon'></i>您已通过审核成功入选该课题</div>}
<div className='introArea'>{helper('自荐书',
<div className="memoExtra">如何写课题申请书<a href="https://forum.gitlink.org.cn/forums/7299/detail" target="_black">https://forum.gitlink.org.cn/forums/7299/detail</a></div>,
'memo' + i,
@ -507,7 +526,10 @@ function Apply(props) {
4课题实施规划课题实施拆解工作规划以及时间安排
5个人简介编程技能过往经验
6提示文本框表达内容有限建议您提供内容的pdf或url链接方式展示更精彩的陈述"
onBlur={(e) => { verify("memo" + i); changeTaskItem("memo", e.currentTarget.value, i) }} rows={7} className={editable ? "memoText disabledInput" : "memoText disabledInput"} disabled={studentApplyEnd} />
onBlur={(e) => { verify("memo" + i); changeTaskItem("memo", e.currentTarget.value, i) }}
rows={7}
className={editable ? "memoText disabledInput" : "memoText disabledInput"}
disabled={!(isStudentApplyDate && !item.id)} />
)}</div>
<div className='introArea'>{helper('附件',
@ -517,7 +539,7 @@ function Apply(props) {
<Upload
// action={getUploadActionUrl()}
action={httpUrl + `/busiAttachments/upload`}
fileList={i ? files1 : files}
fileList={i ? i == 1 ? files1 : files2 : files}
onChange={(info) => { bookChange(info, i) }}
onDownload={download}
beforeUpload={beforeUpload2}
@ -526,9 +548,9 @@ function Apply(props) {
downloadIcon: <i className="iconfont icon-xiazai-icon"></i>,
showRemoveIcon: true
}}
disabled={studentApplyEnd}
disabled={!(isStudentApplyDate && !item.id)}
>
<div className="glcc_btn">上传自荐书</div>
<div className="glcc_btn" >上传自荐书</div>
</Upload>
)}</div>
</Fragment>
@ -541,22 +563,23 @@ function Apply(props) {
}
{
myTaskList.length === 2 && <Form.Item className="priority"
label={<Fragment>对您而言哪个课题的优先级更高<span className="note">优先级将决定您申请课题的入选顺序若申请的2个课题同时通过审核将以高优先级的课题作为入选标准</span></Fragment>}
>
{getFieldDecorator("enrollFirst", {
rules: [{ required: true, message: "请选择课题优先级" },]
})(
<Radio.Group disabled={studentApplyEnd}>
<Radio value={0}>课题一</Radio>
<Radio value={1}>课题二</Radio>
</Radio.Group>
)}
</Form.Item>
// myTaskList.length >= 2 && <Form.Item className="priority"
// label={<Fragment><span className="note">2</span></Fragment>}
// >
// {getFieldDecorator("enrollFirst", {
// rules: [{ required: true, message: "" },]
// })(
// <Radio.Group disabled={studentApplyEnd}>
// <Radio value={0}></Radio>
// <Radio value={1}></Radio>
// <Radio value={2}></Radio>
// </Radio.Group>
// )}
// </Form.Item>
}
{!studentApplyEnd && <Form.Item className='subInfo introArea'>
<Button type="primary" htmlType="submit" className='sub' disabled={!editable}>提交</Button>
<Button type="primary" htmlType="submit" className='sub' disabled={!(editable && !locked)}>提交</Button>
</Form.Item>}
</Form>
</div>

View File

@ -12,18 +12,6 @@
.has-error .ant-form-split {
position: absolute;
}
.ant-btn-primary {
background-color: #466aff;
border-color: #466aff;
&:hover {
background-color: #5d7cff;
border-color: #5d7cff;
}
&:active {
background-color: #1140ff;
border-color: #1140ff;
}
}
.apply {
width: 1200px;
margin: 0 auto;
@ -196,16 +184,6 @@
.sub {
width: 200px;
height: 36px;
background-color: #466aff;
border-color: #466aff;
&:hover {
background-color: #5d7cff;
border-color: #5d7cff;
}
&:active {
background-color: #1140ff;
border-color: #1140ff;
}
}
}
.explain {
@ -249,12 +227,19 @@
font-size: 14px;
line-height: 30px;
text-align: center;
cursor: not-allowed;
// cursor: not-allowed;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
.ant-upload-disabled {
.glcc_btn {
cursor: not-allowed;
}
}
.add_task {
margin-left: 90px;
}
@ -317,6 +302,25 @@
background-color: #466aff;
}
}
.task-checked {
display: inline-block;
width: 287px;
height: 32px;
margin-left: 32px;
background-color: rgba(0, 223, 185, 0.1);
border: 1px solid #00be4c;
border-radius: 4px;
color: #00be4c;
font-size: 16px;
font-weight: 500;
line-height: 28px;
margin-top: 4px;
.iconfont {
margin: 0 9px 0 18px;
}
}
}
.reject-reason {
width: 100%;
@ -326,12 +330,12 @@
border: 1px solid #df4c4c;
color: #595e82;
font-size: 15px;
padding-left:22px;
padding-left: 22px;
margin-bottom: 30px;
.icon-shanchudiao{
.icon-shanchudiao {
position: relative;
top:1px;
top: 1px;
color: #e21b1b;
margin-right: 5px;
font-weight: 600;