开源夏令营2期issue

This commit is contained in:
谢思 2022-05-19 17:06:34 +08:00
parent a884146577
commit 258b6d651f
12 changed files with 125 additions and 72 deletions

View File

@ -10,7 +10,7 @@ function Award() {
<div className="glcc-content">
<div className="award-item">
<div className="award-tit">丰厚现金奖励</div>
<div className="award-content">根据项目难度设置高低三个阶梯课题对应奖金为<span className="number">12000</span> <span className="number">9000</span> 元和 <span className="number">6000</span> </div>
<div className="award-content">根据课题开发耗时对应奖金从<span className="number">6000</span>元至<span className="number">12000</span>元不等详细可以课题详情中具体奖金标准</div>
<div className="award-line"></div>
</div>
@ -28,7 +28,7 @@ function Award() {
<div className="award-item">
<div className="award-tit">夏令营大礼包</div>
<div className="award-content">夏令营纪念文化衫帆布包鼠标垫开源系列图书社区周边等此外还会评选出若干优秀社区明星导师最佳课题开源之星等单项奖</div>
<div className="award-content">夏令营纪念文化衫帆布包鼠标垫开源系列图书社区周边等此外还会评选出若干优秀社区明星导师最佳课题开源之星等单项奖</div>
<div className="award-line"></div>
</div>
</div>

View File

@ -5,32 +5,32 @@ import './index.scss';
const stepArr = [{
title: "Step1",
date: "4.15",
content: "GLCC发布"
content: "GLCC夏令营活动发布"
},
{
title: "Step2",
date: "4.15-5.20",
content: "社区启动报名"
date: "4.15-5.19",
content: "社区项目报名,提交课题"
},
{
title: "Step2",
date: "5.20",
content: "公示社区名单"
date: "5.20-5.25",
content: "公示社区项目名单"
},
{
title: "Step2",
date: "5.21-6.19",
content: "学生提交proposal"
date: "5.26-6.24",
content: "学生报名提交Proposal"
},
{
title: "Step2",
date: "7.1",
content: "公示项目申请审核结果",
content: "公示入选学生名单",
noArrow: true,
},
{
title: "Step2",
date: "7.4-8.12",
date: "7.1-8.12",
content: "项目开发第一阶段",
},
{
@ -40,13 +40,13 @@ const stepArr = [{
},
{
title: "Step2",
date: "10.1-10.14",
content: "结项审核",
date: "10.1-10.21",
content: "结项审核,并公示考核结果",
},
{
title: "Step2",
date: "11.11",
content: "公布优秀项目&学员",
date: "10.21-11.11",
content: "评选公布优秀项目和学员&学员",
noArrow: true,
}
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 KiB

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@ -1,12 +1,28 @@
import React, { useState } from 'react';
import { Button } from 'antd';
import { Button, message } from 'antd';
import Nodata from '../../../forge/Nodata';
import { useEffect } from 'react';
import { getProjectById } from '../../api';
export default ({ detail, projectId, applyTaskId }) => {
export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd }) => {
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
@ -40,22 +56,22 @@ export default ({ detail, projectId, applyTaskId }) => {
<div className="projectDetailHead">
<span className='name'>{info.projectName}</span>
{info.projectType && <span className='type'>{info.projectType}</span>}
<p>{info.gitlinkUrl}</p>
<div>{info.officialWebsiteUrl}</div>
<p>GitLink项目地址: {info.gitlinkUrl}</p>
<div>项目简介: {info.projectIntro}</div>
</div>
{info.registrationTaskList && info.registrationTaskList.length > 0 ? info.registrationTaskList.map(item=>{
return <div className='taskItem mt20'>
<div className="left">
<div className="taskTitle">{item.taskName}</div>
<div className='mt20'>导师姓名: &nbsp;&nbsp;{item.tutorName}</div>
<div className='mb20 email'>邮箱地址: &nbsp;&nbsp;<span>{item.tutorMail}</span></div>
<div className='mt20 oneLine leftWidth'>导师姓名: &nbsp;&nbsp;{item.tutorName}</div>
<div className='mb20 email oneLine leftWidth'>邮箱地址: &nbsp;&nbsp;<span>{item.tutorMail}</span></div>
</div>
<div className="center">
<div className="taskDesc">{item.taskDesc}</div>
<div className="taskUrl">课题链接: &nbsp;&nbsp;<span>{item.taskUrl}</span></div>
<div>{applyTaskId && item.id && Object.keys(applyTaskId).includes(item.id.toString()) ? <Button onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}}>报名详情</Button> : <Button type='primary' className='applyBut' onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}}>申请课题</Button>}</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'>报名详情</Button> : isStudentApplyDate && <Button type='primary' className='applyBut' onClick={()=>{applyTask(item.id)}}>申请课题</Button>)}</div>
</div>
<div className="right"> {item.taskReward}</div>
<div className="right oneLine"> {item.taskReward}</div>
</div>
}) : <Nodata _html="课题暂无数据" small={true}/>}
</div>: <div className="projectDetailBox nodata"><Nodata _html="暂无数据" small={true}/></div>

View File

@ -20,8 +20,12 @@ const TaskList = Loadable({
});
function Project(propsF) {
const {location, current_user} = propsF;
const {location, current_user, showLoginDialog} = propsF;
const {pathname} = location;
const isStudentApplyDate = Date.parse(new Date()) > 1653494400000 && Date.parse(new Date()) < 1656086400000;
const studentApplyEnd = Date.parse(new Date()) > 1656086400000;
// const studentApplyEnd = false;
// const isStudentApplyDate = true;
// id
const [applyTaskId, setApplyTaskId] = useState({});
@ -57,13 +61,13 @@ function Project(propsF) {
<Route
path="/glcc/student/1"
render={(props) => (
<ProjectList applyTaskId={applyTaskId}/>
<ProjectList applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd}/>
)}
></Route>
<Route
path="/glcc/student/2"
render={(props) => (
<TaskList applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset}/>
<TaskList applyTaskId={applyTaskId} setStudentInfoReset={setStudentInfoReset} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd}/>
)}
></Route>
</Switch>

View File

@ -76,7 +76,7 @@
padding: 30px 30px 50px;
.taskItem{
.center{
width: 60%;
// width: 60%;
}
.right{padding-right: 10px;}
}
@ -104,10 +104,15 @@
.taskItem {
display: flex;
justify-content: space-between;
background-color: #ffffff;
box-shadow: 0px 0px 12px rgba(71, 105, 198, 0.4);
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: 250px;
width: 316px;
background-image: url('../img/projectDetailTaskBg.png');
background-size: 100% 100%;
padding: 22px 20px;
@ -117,9 +122,10 @@
font-size:18px;
}
.email span{color:#466aff;}
.leftWidth{width: 270px;}
}
.center{
width: 66%;
width: 650px;
text-align: left;
padding: 20px;
display: flex;
@ -141,6 +147,7 @@
}
}
.right{
min-width: 150px;
font-weight:700;
color:#ff8800;
font-size:24px;
@ -157,4 +164,8 @@
.ant-popover-inner-content{
padding: 30px 30px 50px;
}
}
.lookDetail:hover, .lookDetail:focus{
border-color: #466aff;
color: #466aff;
}

View File

@ -1,5 +1,5 @@
import React , { useEffect , useState } from 'react';
import { Input, Popover, Table, Tooltip } from 'antd';
import { Input, Popover, Spin, Table, Tooltip } from 'antd';
import { main_site_url } from '../../fetch';
import './index.scss';
import { projectList } from '../../api';
@ -7,12 +7,14 @@ import ProjectDetail from '../component/projectDetail';
const {Search} = Input;
//
function ProjectList({applyTaskId}) {
function ProjectList({applyTaskId, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd}) {
//
const [keyword, setKeyword] = useState(undefined);
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(()=>{
setLoading(true);
const params = {
curPage: 1,
keyword,
@ -22,6 +24,7 @@ function ProjectList({applyTaskId}) {
if(response && response.message === "success"){
setData(response.data.rows);
}
setLoading(false);
})
},[keyword])
@ -29,18 +32,20 @@ function ProjectList({applyTaskId}) {
<div className="taskList listBox">
<div className="list">
<div className='search'><Search placeholder='请输入项目名称进行搜索' allowClear enterButton onSearch={(value)=>{setKeyword(value)}}/></div>
<div className='projectListBox'>
{data && data.map((item, index)=>{
return <Popover placement= {(index+1)%3 === 0 ? 'bottomRight' : (index+1)%3%2 === 0 ? 'bottom' : 'bottomLeft'} content={<ProjectDetail detail={item} applyTaskId={applyTaskId}/>} trigger='click' overlayClassName='projectItemPopover'>
<div className={`projectItem ${(index+1)%3 === 0 || (index+1)%3%2 === 0 ? '' : 'firstBox'}`}>
<div className="border"></div>
<div className="projectLogo"><img src={`${main_site_url}/api/attachments/${item.projectLogoId}`} alt=''/></div>
<div className="title">{item.projectName}</div>
<div className="intro">{item.projectIntro}</div>
</div>
</Popover>
})}
</div>
<Spin spinning={loading}>
<div className='projectListBox'>
{data && data.map((item, index)=>{
return <Popover 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}/>} trigger='click' overlayClassName='projectItemPopover' autoAdjustOverflow={false} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd}>
<div className={`projectItem ${(index+1)%3 === 0 || (index+1)%3%2 === 0 ? '' : 'firstBox'}`}>
<div className="border"></div>
<div className="projectLogo"><img src={`${main_site_url}/api/attachments/${item.projectLogoId}`} alt=''/></div>
<div className="title">{item.projectName}</div>
<div className="intro">{item.projectIntro}</div>
</div>
</Popover>
})}
</div>
</Spin>
</div>
</div>
)

View File

@ -1,15 +1,3 @@
.actionBox{
display: flex;
align-items: center;
color: #466aff;
cursor: pointer;
.iconfont{
margin: 0 10px 0 14px;
}
.applyTask{
color:#eb9350;
}
}
.projectListBox{
display: flex;
flex-wrap: wrap;

View File

@ -6,7 +6,7 @@ import ProjectDetail from '../component/projectDetail';
const { Search } = Input;
//
function TaskList({applyTaskId, setStudentInfoReset}) {
function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd}) {
const [visible, setVisible] = useState(false);
const [deleteTaskId, setDeleteTaskId] = useState(undefined);
//
@ -16,21 +16,22 @@ function TaskList({applyTaskId, setStudentInfoReset}) {
const [current, setCurrent] = useState(1);
const [total, setTotal] = useState(0);
const [pageSize, setPageSize] = useState(20);
const [loading, setLoading] = useState(false);
const columns = [
{ title: '序号', dataIndex: 'index', align: 'center', className:"taskTableColumns", render: (text, item, index) => index + 1 },
{ title: '课题名称', dataIndex: 'taskName', className:"taskTableColumns taskName", width: '28%', render: (text, item) => <Tooltip title={text}><span onClick={()=>{window.location.href=item.taskUrl}}>{text}</span></Tooltip> },
{ title: '项目名称', dataIndex: 'tutorName', className:"taskTableColumns", width: '28%', render: (text) => <Tooltip title={text}>{text}</Tooltip> },
{ title: '课题奖金', dataIndex: 'taskReward', className:"taskTableColumns", render: (text) => <span> {text}</span> },
{ title: '序号', dataIndex: 'index', align: 'center', className:"taskTableColumns", width: '6%', render: (text, item, index) => index + 1 },
{ title: '课题名称', dataIndex: 'taskName', className:"taskTableColumns taskName", width: '28%', ellipsis: true, render: (text, item) => <Tooltip title={text} placement="topLeft"><span onClick={()=>{window.location.href=item.taskUrl}}>{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", width: `${isStudentApplyDate || studentApplyEnd ? '15%' : ''}`, render: (text) => <span> {text}</span> },
{
title: '操作', dataIndex: 'action', align: 'center', className:"actionColumns taskTableColumns", render: ((text, item, index) => {
return (
<div className='actionBox'>
{applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) ? <Fragment>
{(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>
</Fragment>:<Fragment>
<span onClick={()=>{window.location.href=`/glcc/student/apply/${item.id}`}}><i className='iconfont icon-shenqingketiicon applyTask mr5'></i><span className='applyTask' onClick={()=>{applyTask(item.id)}}>申请课题</span></span></Fragment>}
</Fragment>:isStudentApplyDate && <Fragment>
<span onClick={()=>{applyTask(item.id)}}><i className='iconfont icon-shenqingketiicon applyTask mr5'></i><span className='applyTask'>申请课题</span></span></Fragment>)}
</div>
)
})
@ -50,17 +51,22 @@ function TaskList({applyTaskId, setStudentInfoReset}) {
}
const expandRow = (record) => {
return <ProjectDetail detail={null} projectId={record.regId} applyTaskId={applyTaskId}/>
return <ProjectDetail detail={null} projectId={record.regId} applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} studentApplyEnd={studentApplyEnd}/>
}
//
function applyTask(id){
//
if(applyTaskId.length >= 2){
message.error('最多只能同时报名两个课题');
//
if(current_user && current_user.login){
//
if(applyTaskId && Object.keys(applyTaskId).length >= 2){
message.error('最多只能同时报名两个课题');
}else{
//
window.location.href=`/glcc/student/apply/${id}`;
}
}else{
//
window.location.href=`/glcc/student/apply/${id}`;
showLoginDialog();
}
}
@ -90,7 +96,15 @@ function TaskList({applyTaskId, setStudentInfoReset}) {
setCurrent(page);
}
//
function toFirst(data, index){
if(index != 0){
data.unshift(data.splice(index,1)[0]);
}
}
useEffect(() => {
setLoading(true);
const params = {
curPage: current,
keyword,
@ -98,9 +112,16 @@ function TaskList({applyTaskId, setStudentInfoReset}) {
}
taskList(params).then(response => {
if (response && response.message === "success") {
// task
const ids = Object.keys(applyTaskId);
const data = response.data.rows;
data.map((item, index)=>{
ids.includes(item.id.toString()) && toFirst(data, index);
})
setData(response.data.rows);
setTotal(response.data.total)
}
setLoading(false);
})
}, [keyword, current, pageSize])
@ -109,6 +130,7 @@ function TaskList({applyTaskId, setStudentInfoReset}) {
<div className="list">
<div className='search'><Search placeholder='请输入课题名称进行搜索' allowClear enterButton onSearch={(value) => { setKeyword(value) }} /></div>
<Table
loading={loading}
columns={columns}
dataSource={data}
expandedRowRender={expandRow}

View File

@ -3,6 +3,13 @@
.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);
}
}
.taskTableColumns span div span{
font-size: 16px;

View File

@ -320,7 +320,7 @@ function Apply(props) {
<div className='apply'>
<Breadcrumb className='glcc_breadcrumb font-16'>
<Breadcrumb.Item><Link to="/glcc">开源夏令营</Link></Breadcrumb.Item>
<Breadcrumb.Item><Link to="/glcc/student/2">查看项目</Link></Breadcrumb.Item>
<Breadcrumb.Item><Link to="/glcc/student/2">课题及项目列表</Link></Breadcrumb.Item>
<Breadcrumb.Item>学生报名</Breadcrumb.Item>
</Breadcrumb>