forked from Gitlink/forgeplus-react
Merge branch 'gitlink_server' of http://106.75.45.236:3000/Gitlink/forgeplus-react into gitlink_server
This commit is contained in:
commit
ac195c9bf7
|
@ -1284,7 +1284,7 @@
|
|||
},
|
||||
"axios": {
|
||||
"version": "0.24.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/axios/-/axios-0.24.0.tgz",
|
||||
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.4"
|
||||
|
@ -7230,12 +7230,14 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -7250,17 +7252,20 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -7377,7 +7382,8 @@
|
|||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -7389,6 +7395,7 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -7403,6 +7410,7 @@
|
|||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -7410,12 +7418,14 @@
|
|||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
|
||||
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -7434,6 +7444,7 @@
|
|||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz",
|
||||
"integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
|
@ -7495,7 +7506,8 @@
|
|||
"npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
|
||||
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
|
||||
"optional": true
|
||||
},
|
||||
"npm-packlist": {
|
||||
"version": "1.4.8",
|
||||
|
@ -7523,7 +7535,8 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -7535,6 +7548,7 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -7648,6 +7662,7 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -16019,7 +16034,7 @@
|
|||
},
|
||||
"save-dev": {
|
||||
"version": "0.0.1-security",
|
||||
"resolved": "https://registry.npmjs.org/save-dev/-/save-dev-0.0.1-security.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/save-dev/-/save-dev-0.0.1-security.tgz",
|
||||
"integrity": "sha512-k6knZTDNK8PKKbIqnvxiOveJinuw2LcQjqDoaorZWP9M5AR2EPsnpDeSbeoZZ0pHr5ze1uoaKdK8NBGQrJ34Uw=="
|
||||
},
|
||||
"sax": {
|
||||
|
|
|
@ -60,8 +60,13 @@ body {
|
|||
.ant-progress-textno {
|
||||
color: #f5222d;
|
||||
}
|
||||
.CodeMirror pre.CodeMirror-line{
|
||||
font-size: 16px!important;
|
||||
.CodeMirror .CodeMirror-lines pre.CodeMirror-line{
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
font-family:"PingFang SC", "Segoe UI", Helvetica, Arial, "Apple Color Emoji", SimHei, SimSun, sans-serif, "Microsoft YaHei";
|
||||
}
|
||||
.react-codemirror2 .CodeMirror .CodeMirror-lines pre.CodeMirror-line{
|
||||
font-size: 12px;
|
||||
}
|
||||
/* md多空格 */
|
||||
.markdown-body p {
|
||||
|
|
|
@ -18,7 +18,7 @@ import moment from 'moment'
|
|||
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
|
||||
import SiderBar from './forge/Component/SiderBar';
|
||||
import SiderBarHelp from './glcc/siderBarHelp';
|
||||
import GlccModal from './modules/glccModal';
|
||||
// import GlccModal from './modules/glccModal';
|
||||
|
||||
import { SnackbarHOC } from 'educoder';
|
||||
import { initAxiosInterceptors } from './AppConfig'
|
||||
|
@ -293,7 +293,7 @@ class App extends Component {
|
|||
<ConfigProvider locale={zhCN}>
|
||||
<MuiThemeProvider theme={theme}>
|
||||
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
|
||||
<GlccModal />
|
||||
{/* <GlccModal /> */}
|
||||
{!pathName || (pathName && pathName.indexOf("glcc") === -1) ? <SiderBar /> : <SiderBarHelp/>}
|
||||
{/* <Router> */}
|
||||
<Switch>
|
||||
|
|
|
@ -89,8 +89,13 @@ export function initAxiosInterceptors(props) {
|
|||
|
||||
if (response.data.status === 404) {
|
||||
let responseURL = response.request ? response.request.responseURL:'';
|
||||
// 组织和个人的拥有情况,404不跳转
|
||||
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 ) {
|
||||
locationurl('/nopage');
|
||||
// 邀请页面不进行404跳转
|
||||
if( window.location.pathname.includes('/invite') && (responseURL.includes('/simple.json')||responseURL.includes('/detail.json')||responseURL.includes('/menu_list.json'))){
|
||||
}else{
|
||||
locationurl('/nopage');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ export function getImageUrl(path) {
|
|||
// https://www.educoder.net
|
||||
// https://testbdweb.trustie.net
|
||||
// const local = 'http://localhost:3000'
|
||||
path && !path.startsWith('/') && !path.startsWith('http') && (path = '/'.concat(path));
|
||||
const local = 'https://testforgeplus.trustie.net';
|
||||
if (isDev) {
|
||||
return `${local}/${path}`
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* eslint-disable react/jsx-no-duplicate-props */
|
||||
import React, { useState } from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { Modal, Button } from 'antd';
|
||||
import './index.scss';
|
||||
|
||||
InitModal.defaultProps = {
|
||||
okText: '确认', //确定按钮的文字
|
||||
cancelText: '取消', //取消按钮的文字
|
||||
className: '', //
|
||||
inputId: 'copyText', //要复制的文本的ID
|
||||
};
|
||||
|
||||
// 使用函数调用删除组件
|
||||
export default function DelModal(props) {
|
||||
renderModal({ ...props, type: 'delete' })
|
||||
}
|
||||
|
||||
// 使用函数调用选择模态框组件
|
||||
export function Confirm(props) {
|
||||
renderModal({ ...props, type: 'confirm' })
|
||||
}
|
||||
|
||||
function renderModal(props) {
|
||||
const { type, afterClose } = props;
|
||||
const div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
|
||||
function destroy() {
|
||||
afterClose && afterClose();
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div);
|
||||
if (unmountResult && div.parentNode) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
function modalType(type) {
|
||||
if (type === 'delete') {
|
||||
return <InitModal
|
||||
title="删除"
|
||||
contentTitle="确定要删除吗?"
|
||||
okText="确认删除"
|
||||
{...props}
|
||||
|
||||
afterClose={destroy}
|
||||
contentTitle={<React.Fragment>
|
||||
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
|
||||
{props.contentTitle}
|
||||
</React.Fragment>}
|
||||
/>
|
||||
} else if (type === 'confirm') {
|
||||
return <InitModal title="选择" afterClose={destroy} {...props} />
|
||||
} else {
|
||||
return <InitModal title="选择" afterClose={destroy} {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
setTimeout(() => {
|
||||
ReactDOM.render(
|
||||
modalType(type),
|
||||
div,
|
||||
);
|
||||
});
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
// 选择模态框组件
|
||||
function InitModal({
|
||||
onCancel,
|
||||
onOk,
|
||||
title,
|
||||
contentTitle,
|
||||
content,
|
||||
okText,
|
||||
cancelText,
|
||||
afterClose,
|
||||
className,
|
||||
}) {
|
||||
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
function onCancelModal() {
|
||||
setVisible(false);
|
||||
onCancel && onCancel()
|
||||
}
|
||||
|
||||
function onSuccess() {
|
||||
setVisible(false);
|
||||
onOk && onOk();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
onCancel={onCancelModal}
|
||||
afterClose={afterClose}
|
||||
title={title}
|
||||
className={`myself-modal ${className}`}
|
||||
centered
|
||||
footer={[
|
||||
<Button type="default" key="back" onClick={onCancelModal}>
|
||||
{cancelText}
|
||||
</Button>,
|
||||
<Button className="foot-submit" key="submit" onClick={onSuccess}>
|
||||
{okText}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div>
|
||||
{contentTitle && <p className="content-title">{contentTitle}</p>}
|
||||
<p className="content-descibe">{content}</p>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
.myself-modal {
|
||||
.ant-modal-header {
|
||||
padding: 9px 24px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.ant-modal-title {
|
||||
text-align: left;
|
||||
}
|
||||
.ant-modal-close {
|
||||
top: 0px !important;
|
||||
}
|
||||
.ant-modal-close-x {
|
||||
font-size: 24px;
|
||||
}
|
||||
.ant-modal-body {
|
||||
text-align: center;
|
||||
}
|
||||
.content-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 2rem 0 1rem !important;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
letter-spacing: 0;
|
||||
line-height: 29px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.red-circle {
|
||||
align-self: flex-start;
|
||||
color: #ca0002;
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
.content-descibe {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 33px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.ant-modal-footer {
|
||||
padding: 2rem 0;
|
||||
text-align: center;
|
||||
border: 0;
|
||||
.ant-btn {
|
||||
width: 6rem;
|
||||
}
|
||||
}
|
||||
.foot-submit {
|
||||
margin-left: 3rem;
|
||||
color: #df0002;
|
||||
&:hover {
|
||||
border-color: #df0002;
|
||||
}
|
||||
}
|
||||
.ant-btn-default:hover,
|
||||
.ant-btn-default:active,
|
||||
.ant-btn-default:focus {
|
||||
background: #f3f4f6;
|
||||
color: #333;
|
||||
border-color: #d0d0d0;
|
||||
}
|
||||
}
|
|
@ -80,7 +80,7 @@ function AddMember({getID,login,showNotification}){
|
|||
<AutoComplete
|
||||
dataSource={source}
|
||||
value={searchKey}
|
||||
style={{ width: 300 }}
|
||||
style={{ width: 250 }}
|
||||
onChange={changeInputUser}
|
||||
onSelect={selectInputUser}
|
||||
placeholder="搜索需要添加的用户..."
|
||||
|
@ -92,7 +92,8 @@ function AddMember({getID,login,showNotification}){
|
|||
onClick={addCollaborator}
|
||||
className="ml15"
|
||||
>
|
||||
<Icon type="plus" size="16"></Icon>
|
||||
{/* <Icon type="plus" size="16"></Icon> */}
|
||||
<i className="iconfont icon-tianjiafangda mr3"></i>
|
||||
添加成员
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -55,7 +55,7 @@ function LanguagePower({owner,projectsId}){
|
|||
{
|
||||
array && array.map((item,key)=>{
|
||||
return(
|
||||
<span style={{width:item.percent,backgroundColor:item.color}}></span>
|
||||
<span key={item.id||key} style={{width:item.percent,backgroundColor:item.color}}></span>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ function LanguagePower({owner,projectsId}){
|
|||
{
|
||||
array.map((item,key)=>{
|
||||
return(
|
||||
<span><i className="zero" style={{backgroundColor:`${item.color}`}}></i><span>{item.name}</span><span>{item.percent}</span></span>
|
||||
<span key={item.id||key}><i className="zero" style={{backgroundColor:`${item.color}`}}></i><span>{item.name}</span><span>{item.percent}</span></span>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -190,11 +190,11 @@ function NoticeContent({ visible, showNotification, resetUserInfo, current_user:
|
|||
className='hoverNotice-body' // 外部添加className加以区分
|
||||
onPullRefresh={() => { setNoticePage(noticePage + 1); }} //触发加载ajax的function
|
||||
// type={2} // 传送加载组件的状态
|
||||
count={noticeUnreadList.length} // 数据当前的总数量
|
||||
count={noticeUnreadList&¬iceUnreadList.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':''}`}>
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Modal, Button, } from 'antd';
|
||||
import { Base64 } from 'js-base64';
|
||||
import './index.scss';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getImageUrl } from 'educoder'
|
||||
import axios from 'axios';
|
||||
|
||||
const identify = {
|
||||
manager: "管理员",
|
||||
developer: "开发者",
|
||||
reporter: "报告者",
|
||||
owner: "所有者",
|
||||
}
|
||||
function Invite({ history, current_user, match, projectDetail, showNotification }) {
|
||||
|
||||
if (!current_user.login) {
|
||||
let { pathname, search } = window.location;
|
||||
window.location.href = `/login?go_page=${pathname}${search}`;
|
||||
}
|
||||
let permission = projectDetail && projectDetail.permission;
|
||||
const { projectsId, owner } = match.params;
|
||||
let inviteString = window.location.search && window.location.search.split('?invite=')[1];
|
||||
let data = inviteString && JSON.parse(Base64.decode(inviteString));
|
||||
const [detail, setDetail] = useState({});
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (permission && detail.role && detail.role == permission.toLocaleLowerCase() || permission == 'Owner') {
|
||||
showNotification(`您已经是${identify[detail.role]}了`)
|
||||
setTimeout(() => {
|
||||
history.push(`/${owner}/${projectsId}`);
|
||||
}, 2000)
|
||||
} else {
|
||||
setVisible(true)
|
||||
}
|
||||
}, [permission, detail.role]);
|
||||
|
||||
useEffect(() => {
|
||||
const url = `/${owner}/${projectsId}/project_invite_links/show_link.json?invite_sign=${data.sign}`;
|
||||
axios.get(url).then(res => {
|
||||
if (res && res.data) {
|
||||
setDetail(res.data);
|
||||
} else {
|
||||
showNotification('查询邀请链接失败');
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
function accept() {
|
||||
const url = `/${owner}/${projectsId}/project_invite_links/redirect_link.json?invite_sign=${data.sign}`;
|
||||
axios.post(url).then(res => {
|
||||
if (res && res.data.message == 'success') {
|
||||
if (detail.is_apply) {
|
||||
setVisible(false);
|
||||
Modal.success({ content: '提交申请成功,请等待该仓库管理员审核' });
|
||||
} else {
|
||||
history.push(`/${owner}/${projectsId}`);
|
||||
}
|
||||
}
|
||||
}).catch(error => { })
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
{data && <Modal
|
||||
visible={visible}
|
||||
className="invite_development"
|
||||
title={<div className="ownerImage"><img src={detail.project && getImageUrl(detail.project.owner.image_url)} /></div>}
|
||||
width="548px"
|
||||
closable={true}
|
||||
onCancel={() => { setVisible(false); history.push(`/${current_user.login}`) }}
|
||||
centered
|
||||
okText={'接受'}
|
||||
cancelText={'拒绝'}
|
||||
onOk={accept}
|
||||
maskClosable={false}
|
||||
>
|
||||
<Link className="invite_project link" target="_blank" to={`/${data.ownerLogin}/${data.projectId}`}>{detail.project && detail.project.owner.name}/{detail.project && detail.project.name}</Link>
|
||||
<div className="invite_content">
|
||||
<Link className="link" to={`/${detail.user && detail.user.login}`}>{detail.user && detail.user.name}</Link> 邀请您以{identify[detail.role]}的身份加入此代码库
|
||||
是否接受邀请?
|
||||
</div>
|
||||
</Modal>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default Invite;
|
|
@ -0,0 +1,100 @@
|
|||
.invite_development {
|
||||
font-family: PingFang SC;
|
||||
height: 366px;
|
||||
background-image: linear-gradient(
|
||||
359.37deg,
|
||||
#ebf3ff 0%,
|
||||
#eff5ff 55.01%,
|
||||
#cfdeff 100%
|
||||
);
|
||||
border: 1.5px solid #ffffff;
|
||||
border-radius: 4px;
|
||||
|
||||
.ant-modal-close{
|
||||
top:0 !important;
|
||||
}
|
||||
.ant-modal-close-x{
|
||||
font-size: 30px;
|
||||
color: #666;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
transform: scaleX(1.05);
|
||||
}
|
||||
.ant-modal-content {
|
||||
background-color: inherit;
|
||||
}
|
||||
.ant-modal-header {
|
||||
background: inherit;
|
||||
border: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.ownerImage {
|
||||
position: relative;
|
||||
top:-66px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: #e9f1ff;
|
||||
border: 1px solid #ffffff;
|
||||
border-radius: 50%;
|
||||
margin:0 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
img{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.invite_project {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.invite_content {
|
||||
width: 422px;
|
||||
padding: 24px 48px;
|
||||
background-color: rgba(225, 231, 255, 0.71);
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
margin: 10px auto;
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
color: #151d40;
|
||||
}
|
||||
.link {
|
||||
cursor: pointer;
|
||||
color: $primary-color;
|
||||
&:hover {
|
||||
color: $primary-color-hover;
|
||||
}
|
||||
}
|
||||
.ant-modal-footer {
|
||||
text-align: center;
|
||||
border: 0;
|
||||
padding-bottom: 55px;
|
||||
button {
|
||||
width: 150px;
|
||||
height: 42px;
|
||||
border-radius: 5px;
|
||||
font-size: 15px;
|
||||
&:first-child {
|
||||
background-color: rgba(196, 0, 14, 0.07);
|
||||
border: 1px solid;
|
||||
border-color: #f60011;
|
||||
color: #f60011;
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
& + button {
|
||||
margin-left: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -493,6 +493,7 @@ function CoderDepot(props){
|
|||
dirInfo.map((item,key)=>{
|
||||
return(
|
||||
<Catalogue
|
||||
key={item.id||key}
|
||||
owner={owner}
|
||||
item={item}
|
||||
projectsId={projectsId}
|
||||
|
|
|
@ -21,7 +21,7 @@ function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId , platform
|
|||
(!platform && item.image_type) ?
|
||||
<span><i className={`iconfont ${typeIco[`${item.type}`]} mr8`}></i>{item.name}</span>
|
||||
:
|
||||
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" && "submoduleStyle"}>
|
||||
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" ? "submoduleStyle":''}>
|
||||
<i className={`iconfont ${typeIco[`${item.type}`]} mr8`}></i>{item.name}
|
||||
</a>
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Link, Route, Switch } from 'react-router-dom';
|
|||
import { Content, AlignTop } from '../Component/layout';
|
||||
import DetailBanner from './sub/DetailBanner';
|
||||
import cookie from 'react-cookies';
|
||||
import { Base64 } from 'js-base64';
|
||||
import '../css/index.scss'
|
||||
import './list.scss';
|
||||
|
||||
|
@ -145,6 +146,10 @@ const WikiEdit = Loadable({
|
|||
loader: () => import('../Wiki/EditWiki'),
|
||||
loading: Loading,
|
||||
});
|
||||
const Invite = Loadable({
|
||||
loader: () => import('../Invite/Index'),
|
||||
loading: Loading,
|
||||
});
|
||||
/**
|
||||
* permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外)
|
||||
*/
|
||||
|
@ -227,12 +232,12 @@ class Detail extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
clearIssueCookies=(history)=>{
|
||||
clearIssueCookies = (history) => {
|
||||
const { pathname } = history;
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
let currentIssue = pathname.indexOf(`/${owner}/${projectsId}/issues`) === -1;
|
||||
if (currentIssue) {
|
||||
cookie.save('states', undefined,{ expires: 0,path:`/` });
|
||||
cookie.save('states', undefined, { expires: 0, path: `/` });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,15 +309,15 @@ class Detail extends Component {
|
|||
},
|
||||
disconnected: () => {
|
||||
console.log("###### cannot connected! ######");
|
||||
},
|
||||
},
|
||||
received: data => {
|
||||
console.log(`###### ---received data--- ######`);
|
||||
console.log(data);
|
||||
if (data) {
|
||||
if(deleteFlag){
|
||||
if (deleteFlag) {
|
||||
this.props.showNotification("镜像同步成功!");
|
||||
window.location.reload();
|
||||
}else{
|
||||
} else {
|
||||
if (data.project && data.project.mirror_status === 2) {
|
||||
this.deleteProjectBack();
|
||||
}
|
||||
|
@ -326,20 +331,20 @@ class Detail extends Component {
|
|||
cable.subscriptions.consumer.disconnect();
|
||||
}
|
||||
},
|
||||
onerror:()=>{
|
||||
onerror: () => {
|
||||
console.log("###### cannot connected! ######");
|
||||
}
|
||||
});
|
||||
|
||||
this.timerChannel = setTimeout(this.reloadDetail,5000);
|
||||
this.timerChannel = setTimeout(this.reloadDetail, 5000);
|
||||
}
|
||||
|
||||
reloadDetail=()=>{
|
||||
if(this.state.firstSync||this.state.secondSync){
|
||||
reloadDetail = () => {
|
||||
if (this.state.firstSync || this.state.secondSync) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
deleteProjectBack = () => {
|
||||
const { history } = this.props;
|
||||
|
@ -364,22 +369,33 @@ class Detail extends Component {
|
|||
axios.get(url).then((result) => {
|
||||
if (result && result.data) {
|
||||
if (result.data.status === 404) {
|
||||
this.props.history.push('/nopage');
|
||||
if (window.location.pathname.includes('/invite')) {
|
||||
let inviteString = window.location.search && window.location.search.split('?invite=')[1];
|
||||
let data = inviteString && JSON.parse(Base64.decode(inviteString));
|
||||
const { project = {}, projectDetail = {} } = this.state
|
||||
this.setState({
|
||||
project: Object.assign(project, { author: { name: data.ownerName } }),
|
||||
projectDetail: Object.assign(projectDetail, { name: data.projectName })
|
||||
});
|
||||
} else {
|
||||
this.props.history.push('/nopage');
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
projectDetail: result.data,
|
||||
project_id: result.data.project_id,
|
||||
isManager: result.data.permission && (result.data.permission === "Manager" || result.data.permission === "Admin" || result.data.permission === "Owner"),
|
||||
isReporter: result.data.permission && result.data.permission === "Reporter",
|
||||
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
||||
http_url: result.data.clone_url,
|
||||
praised: result.data.praised,
|
||||
watched: result.data.watched,
|
||||
watchers_count: result.data.watchers_count,
|
||||
praises_count: result.data.praises_count,
|
||||
forked_count: result.data.forked_count,
|
||||
defaultBranch: result.data.default_branch
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
projectDetail: result.data,
|
||||
project_id: result.data.project_id,
|
||||
isManager: result.data.permission && (result.data.permission === "Manager" || result.data.permission === "Admin" || result.data.permission === "Owner"),
|
||||
isReporter: result.data.permission && result.data.permission === "Reporter",
|
||||
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
||||
http_url: result.data.clone_url,
|
||||
praised: result.data.praised,
|
||||
watched: result.data.watched,
|
||||
watchers_count: result.data.watchers_count,
|
||||
praises_count: result.data.praises_count,
|
||||
forked_count: result.data.forked_count,
|
||||
defaultBranch: result.data.default_branch
|
||||
})
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
@ -464,7 +480,7 @@ class Detail extends Component {
|
|||
const url = `/${owner}/${projectsId}/forks.json`;
|
||||
axios.post(url).then(result => {
|
||||
if (result && result.data.status === 0) {
|
||||
if(result.data.message === "fork失败,你已拥有了这个项目"){
|
||||
if (result.data.message === "fork失败,你已拥有了这个项目") {
|
||||
this.props.history.push(`/${current_user && current_user.login}/${projectsId}`);
|
||||
return;
|
||||
}
|
||||
|
@ -490,7 +506,7 @@ class Detail extends Component {
|
|||
axios.post(url).then(result => {
|
||||
if (result && result.data && result.data.status === 0) {
|
||||
this.setState({
|
||||
secondSync:true
|
||||
secondSync: true
|
||||
})
|
||||
this.canvasChannel(true);
|
||||
} else {
|
||||
|
@ -527,10 +543,9 @@ class Detail extends Component {
|
|||
let pathname = checkPathname(projectsId, owner, url);
|
||||
|
||||
const { state } = this.props.history.location;
|
||||
|
||||
const common = {
|
||||
getDetail: this.getDetail,
|
||||
getBanner:this.getBanner,
|
||||
getBanner: this.getBanner,
|
||||
changeOpenDevops: this.changeOpenDevops,
|
||||
defaultBranch
|
||||
}
|
||||
|
@ -549,7 +564,7 @@ class Detail extends Component {
|
|||
<Link to={`/${owner}/${projectsId}`} className="projectN mt6">{projectDetail && projectDetail.name}</Link>
|
||||
</div>
|
||||
{projectDetail && projectDetail.private && <span className="privateTag mt6">私有</span>}
|
||||
{ !platform && <span className="privateTag red mt6">只读</span> }
|
||||
{!platform && <span className="privateTag red mt6">只读</span>}
|
||||
</AlignTop>
|
||||
<div className="mt8">
|
||||
{
|
||||
|
@ -718,7 +733,7 @@ class Detail extends Component {
|
|||
(props) => (<Setting {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/*修改里程碑*/}
|
||||
<Route path="/:owner/:projectsId/milestones/:meilid/edit"
|
||||
render={
|
||||
|
@ -758,18 +773,18 @@ class Detail extends Component {
|
|||
{/* 修改详情 edit*/}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId/edit"
|
||||
render={
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"edit"}/>)
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"edit"} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 复制详情 copyetail*/}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId/copyetail"
|
||||
render={
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"copy"}/>)
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"copy"} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 任务详情 */}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId"
|
||||
|
||||
{/* 任务详情 */}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId"
|
||||
render={
|
||||
(props) => (<OrderDetail {...this.props} {...this.state} {...props} {...common} />)
|
||||
}
|
||||
|
@ -861,6 +876,12 @@ class Detail extends Component {
|
|||
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 邀请 */}
|
||||
<Route path="/:owner/:projectsId/invite"
|
||||
render={
|
||||
(props) => (<Invite {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/:subIndex"
|
||||
render={
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||
|
|
|
@ -306,6 +306,14 @@
|
|||
}
|
||||
.files-md{
|
||||
padding:20px;
|
||||
h1,h2, h3, h4, h5, h6{
|
||||
margin-bottom: .5em !important;
|
||||
}
|
||||
}
|
||||
.readBox{
|
||||
h1,h2, h3, h4, h5, h6{
|
||||
margin-bottom: .5em !important;
|
||||
}
|
||||
}
|
||||
/* 详情-代码 */
|
||||
.branch-wrapper{
|
||||
|
|
|
@ -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}/>
|
||||
|
|
|
@ -37,7 +37,7 @@ class Milepost extends Component {
|
|||
const url = `/${owner}/${projectsId}/milestones.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
projectsId, page, limit, status, order_type, order_name
|
||||
page, limit, status, order_type, order_name
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
|
|
|
@ -105,7 +105,6 @@ class Tags extends Component {
|
|||
const url = `/projects/${owner}/${projectsId}/labels.json`;
|
||||
axios.post(url, {
|
||||
...values,
|
||||
project_id: projectsId,
|
||||
color: this.state.textcolor
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
|
|
|
@ -57,7 +57,6 @@ class NewMilepost extends Component {
|
|||
}
|
||||
axios.post(url, {
|
||||
...values,
|
||||
project_id: projectsId,
|
||||
effective_date: time,
|
||||
status: 'open'
|
||||
}).then(result => {
|
||||
|
|
|
@ -7,7 +7,7 @@ import Group from './CollaboratorGroup';
|
|||
import MemberByLink from './CollaboratorMemberByLink';
|
||||
|
||||
function Collaborator(props){
|
||||
const [ nav , setNav] = useState("3");
|
||||
const [ nav , setNav] = useState("1");
|
||||
const [ newId , setNewId] = useState(undefined);
|
||||
const [ newIdFlag , setNewIdFlag ] = useState(false);
|
||||
const [ addOperation , setAddOperation] = useState(true);
|
||||
|
@ -42,7 +42,7 @@ function Collaborator(props){
|
|||
{author && author.type === "Organization" && <span style={{cursor:"pointer"}} className={nav === "2" ? "font-15 text-black ml30 color-blue":"font-15 text-black ml30"} onClick={()=>{setNav("2");setNewId(undefined);setNewGroupId(undefined)}}>团队管理</span>}
|
||||
</span>
|
||||
{
|
||||
(nav === "1" || nav === "3") &&
|
||||
nav === "1" &&
|
||||
<AddMember getID={getID} login showNotification={props.showNotification}/>
|
||||
}
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useEffect, useState , useImperativeHandle , forwardRef } from 'react';
|
||||
import { Select, Checkbox, Button , Input , Spin , Table , Tooltip , Pagination , Popconfirm } from "antd";
|
||||
import axios from 'axios';
|
||||
import React, { useEffect, useState, useImperativeHandle, forwardRef } from 'react';
|
||||
import { Select, Checkbox, Button, Input, Spin, Table, Tooltip, Pagination, Popconfirm } from "antd";
|
||||
import axios from 'axios';
|
||||
import { Base64 } from 'js-base64';
|
||||
import NoneData from "../Nodata";
|
||||
import { Link } from "react-router-dom";
|
||||
import { getImageUrl } from "educoder";
|
||||
|
@ -8,28 +9,84 @@ import { getImageUrl } from "educoder";
|
|||
const { Search } = Input;
|
||||
const LIMIT = 15;
|
||||
const optionList = [
|
||||
{value: "manager",name: "管理员 - 拥有仓库设置功能、代码库读、写操作权限"},
|
||||
{value: "developer",name: "开发人员 - 拥有代码库读、写操作权限"},
|
||||
{value: "reporter",name: "报告者 - 拥有代码库读操作权限"}
|
||||
{ value: "manager", name: "管理员 - 拥有仓库设置功能、代码库读、写操作权限" },
|
||||
{ value: "developer", name: "开发人员 - 拥有代码库读、写操作权限" },
|
||||
{ value: "reporter", name: "报告者 - 拥有代码库读操作权限" }
|
||||
];
|
||||
function CollaboratorMemberByLink({projectsId,owner,project_id,author,showNotification,newId,flag}){
|
||||
function CollaboratorMemberByLink({ projectsId, owner, project_id, author, showNotification, newId, flag }) {
|
||||
|
||||
return(
|
||||
const [role, setRole] = useState('developer');
|
||||
const [is_apply, setIs_apply] = useState(true);
|
||||
const [inviteUrl, setinviteUrl] = useState('');
|
||||
const [copy, setCopy] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const url = `/${owner}/${projectsId}/project_invite_links/current_link.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
role,
|
||||
is_apply
|
||||
}
|
||||
}).then(res => {
|
||||
if (res && res.data) {
|
||||
let params = {
|
||||
projectName: res.data.project.name,
|
||||
projectId: res.data.project.identifier,
|
||||
// role: res.data.role,
|
||||
ownerLogin: res.data.project.owner.login,
|
||||
ownerName: res.data.project.owner.name,
|
||||
// userName: res.data.user.name,
|
||||
// userLogin: res.data.user.login,
|
||||
sign:res.data.sign,
|
||||
};
|
||||
let urlParams = JSON.stringify(params);
|
||||
let content = Base64.encode(urlParams);
|
||||
|
||||
setinviteUrl(`${window.location.origin}/${owner}/${projectsId}/invite?invite=${content}`);
|
||||
setCopy(false);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}, [role, is_apply]);
|
||||
|
||||
function inviteClick() {
|
||||
const copyEle = document.querySelector('#inviteUrl'); // 获取要复制的节点
|
||||
if (!copyEle) {
|
||||
console.error("您的CopyTool未设置正确的inputId");
|
||||
return;
|
||||
}
|
||||
copyEle.select(); // 执行选中元素
|
||||
if (document.execCommand('copy')) {
|
||||
document.execCommand('copy');
|
||||
setCopy(true);
|
||||
// copyEle.blur();
|
||||
document.getSelection().removeAllRanges();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='addMemByLinkBox'>
|
||||
<div className='font-16 mt20 mb5'>请选择邀请用户权限</div>
|
||||
<Select className='selectBox' defaultValue="developer">
|
||||
{optionList.map(item=>{
|
||||
return <Select.Option value={item.value}>{item.name}</Select.Option>
|
||||
<div className='font-16 mt20 mb10'>请选择邀请用户权限</div>
|
||||
<Select className='selectBox' defaultValue="developer" onChange={(v) => { setRole(v) }}>
|
||||
{optionList.map(item => {
|
||||
return <Select.Option value={item.value} key={item.value}>{item.name}</Select.Option>
|
||||
})}
|
||||
</Select>
|
||||
<Checkbox className='font-15 checkBox'>是否需要管理员审核</Checkbox>
|
||||
<div className='font-16 mt10 mb5'>邀请链接</div>
|
||||
<Input addonAfter={<Button type='primary'>复制链接</Button>} className='linkBox'/>
|
||||
<div className='tipBox mt20'>
|
||||
<div>注: </div>
|
||||
|
||||
<Checkbox checked={is_apply} className='font-15 checkBox' onChange={e => { setIs_apply(e.target.checked) }}>需要管理员审核</Checkbox>
|
||||
|
||||
<div className='font-16 mt25 mb10'>邀请链接</div>
|
||||
<Input
|
||||
id="inviteUrl"
|
||||
value={inviteUrl}
|
||||
readOnly
|
||||
addonAfter={<Button type='primary' className={`${copy?'success':''}`} onClick={inviteClick}>{copy ? '复制成功' : '复制链接'}</Button>} className='linkBox'
|
||||
/>
|
||||
<div className='tipBox mt25'>
|
||||
{/* <div>注: </div> */}
|
||||
<div className='ml5'>
|
||||
1、管理员可通过分享邀请链接的方式,邀请其他成员加入项目<br/>
|
||||
2、若已勾选管理员审核选项,用户接收邀请后管理员可在个人主页中“待办事项”窗口审核成员审核信息,若不需要管理员审核,成员接收邀请后,将直接加入项目
|
||||
1、管理员可通过分享邀请链接的方式,邀请其他成员加入项目<br />
|
||||
2、若已勾选管理员审核选项,用户接收邀请后管理员可在个人主页中“待办事项”窗口审核成员审核信息,若不需要管理员审核,成员接收邀请后,将直接加入项目<br />
|
||||
3、当前邀请链接有效期为三天
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -96,7 +96,6 @@ class NewTags extends Component {
|
|||
axios
|
||||
.post(url, {
|
||||
...values,
|
||||
project_id: projectsId,
|
||||
color: this.state.textcolor,
|
||||
})
|
||||
.then((result) => {
|
||||
|
|
|
@ -65,6 +65,15 @@
|
|||
}
|
||||
.addPanel{
|
||||
display: flex;
|
||||
|
||||
.icon-tianjiafangda{
|
||||
font-size: 16px !important;
|
||||
font-weight: bold;
|
||||
&+span{
|
||||
position: relative;
|
||||
top:-1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.red_btn{
|
||||
display: block;
|
||||
|
@ -249,17 +258,21 @@
|
|||
.selectBox {
|
||||
width: 55%;
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.checkBox{
|
||||
color:#151d40;
|
||||
}
|
||||
.tipBox{
|
||||
background-color:rgba(199, 209, 255, 0.17);
|
||||
// background-color:rgba(199, 209, 255, 0.17);
|
||||
color:#7e849e;
|
||||
padding: 20px 150px 20px 25px;
|
||||
// padding: 20px 150px 20px 25px;
|
||||
display: flex;
|
||||
}
|
||||
.success{
|
||||
background-color: #36cacf;
|
||||
border-color: #36cacf;
|
||||
}
|
||||
.linkBox{
|
||||
width: 55%;
|
||||
.ant-input-group-addon{
|
||||
|
|
|
@ -126,7 +126,8 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
}
|
||||
|
||||
function goBack() {
|
||||
history.push(`/${owner}/${projectsId}/wiki`);
|
||||
// history.push(`/${owner}/${projectsId}/wiki`);
|
||||
history.go(-1);
|
||||
}
|
||||
|
||||
function changeModal(e) {
|
||||
|
|
|
@ -5,6 +5,8 @@ import cookie from 'react-cookies';
|
|||
import CopyTool from '../Component/CopyTool';
|
||||
import DelModal from './components/ModalFun';
|
||||
import Welcome from './Welcome';
|
||||
import RenderHtml from "../../components/render-html";
|
||||
|
||||
import { wikiPages, getWiki, deleteWiki } from './api';
|
||||
import { httpUrl, TokenKey } from './fetch';
|
||||
import './Index.scss';
|
||||
|
@ -281,7 +283,7 @@ export default (props) => {
|
|||
{permission && <Button type="primary" onClick={goEdit}>编辑</Button>}
|
||||
</div>
|
||||
|
||||
<div className="wiki-content-detail editor-content-panel markdown-body" dangerouslySetInnerHTML={{ __html: itemDetail && itemDetail.simple_content }} ></div>
|
||||
{itemDetail&&itemDetail.simple_content&&<RenderHtml className="wiki-content-detail editor-content-panel" value={ itemDetail&&itemDetail.md_content } url={history.location}/>}
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
|
|
|
@ -242,6 +242,7 @@ form{
|
|||
cursor: pointer;
|
||||
padding-right: 20px;
|
||||
margin:0px;
|
||||
border-bottom: 1px solid #eee;
|
||||
a{
|
||||
width:100%;
|
||||
color: #202d40;
|
||||
|
|
|
@ -180,7 +180,7 @@ class InfosUser extends Component {
|
|||
placeholder="输入项目名称关键字进行搜索"
|
||||
enterButton="搜索"
|
||||
size="large"
|
||||
onSearch={this.get_projects}
|
||||
onSearch={()=>{this.get_projects()}}
|
||||
className="list-r-Search"
|
||||
value={search}
|
||||
onChange={this.changeSearchValue}
|
||||
|
|
|
@ -132,4 +132,13 @@ export function auditPassTask(data) {
|
|||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 导师审核结果
|
||||
export function getPassList(params) {
|
||||
return fetch({
|
||||
url: '/api/studentApply/passList',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
|
@ -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'
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 12: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: '10%', ellipsis: true},
|
||||
{ title: '学生院校', dataIndex: 'school', className:"columnsResult taskName", width: '12%', ellipsis: true,render: (text) => <Tooltip title={text} placement="topLeft"><span className='toolTipSpan'>{text}</span></Tooltip>},
|
||||
{ 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: '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.taskId}`)}}>{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 12: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;
|
|
@ -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;}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ import { hasAuditRole } from '../api';
|
|||
import './index.scss';
|
||||
|
||||
export default (props) => {
|
||||
const { current_user, isGlccApplyDate, showNotification, studentApplyStart, history } = 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 12:0').getTime();
|
||||
|
||||
useEffect(() => {
|
||||
if (!current_user.user_id) {
|
||||
|
@ -48,7 +50,9 @@ export default (props) => {
|
|||
// 学生报名时间
|
||||
if (!studentApplyStart) {
|
||||
showNotification("不在报名时间,报名开始时间为5月26日");
|
||||
} else {
|
||||
} else if(!isStudentApplyDate && !secondStudentApplyDate) {
|
||||
showNotification("课题申请时间已截止");
|
||||
} else{
|
||||
history.push("/glcc/subjects");
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +61,10 @@ export default (props) => {
|
|||
history.push("/glcc/mentoradmin");
|
||||
}
|
||||
|
||||
function goToCheckResult(){
|
||||
history.push("/glcc/result");
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="glcc">
|
||||
{/* <Banner /> */}
|
||||
|
@ -69,6 +77,14 @@ export default (props) => {
|
|||
</div> */}
|
||||
{/* 报名入口 */}
|
||||
<div className="applyBox">
|
||||
{/* 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>}
|
||||
{/* 项目报名 */}
|
||||
<Link to="/glcc/projects" className="apply project" >
|
||||
<div>
|
||||
|
@ -76,24 +92,25 @@ 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>
|
||||
{/* 学生报名 */}
|
||||
<div className="apply" onClick={goToStudent}>
|
||||
{/* 学生报名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>
|
||||
<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>
|
||||
</div>
|
||||
<div className="pt6">以赛代筛,挖掘高潜力人才</div>
|
||||
</div>}
|
||||
</div>} */}
|
||||
</div>
|
||||
{/* </div> */}
|
||||
<div className="introduce">
|
||||
|
@ -116,7 +133,7 @@ export default (props) => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Lightspot isGlccApplyDate={isGlccApplyDate} current_user={current_user} showNotification={showNotification} studentApplyStart={studentApplyStart} />
|
||||
<Lightspot isGlccApplyDate={isGlccApplyDate} current_user={current_user} showNotification={showNotification} goToStudent={goToStudent}/>
|
||||
<TimerShaft />
|
||||
<Award />
|
||||
<News />
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { Link } from 'react-router-dom';
|
|||
|
||||
|
||||
function Lightspot(props) {
|
||||
const {current_user, isGlccApplyDate, showNotification, studentApplyStart} = props;
|
||||
const {current_user, isGlccApplyDate, showNotification, goToStudent} = props;
|
||||
|
||||
function goToApply(){
|
||||
if(isGlccApplyDate){
|
||||
|
@ -27,15 +27,6 @@ function Lightspot(props) {
|
|||
}
|
||||
}
|
||||
|
||||
function goToStudent(){
|
||||
// 学生报名时间
|
||||
if(!studentApplyStart){
|
||||
showNotification("不在报名时间,报名开始时间为5月26日");
|
||||
}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 |
|
@ -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;
|
||||
// 判断时间是否在开源夏令营报名时间内(4月15日~5月20日)
|
||||
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').getTime();
|
||||
const studentApplyEnd = new Date().getTime() > new Date('2022-06-25').getTime();
|
||||
const isStudentApplyDate = new Date().getTime() > new Date('2022-05-26').getTime() && 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}/>
|
||||
<Home {...propsF} {...props} studentApplyStart={studentApplyStart} isStudentApplyDate={isStudentApplyDate} secondStudentApplyDate={secondStudentApplyDate}/>
|
||||
)}
|
||||
></Route>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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查询项目详情
|
||||
|
@ -50,7 +34,16 @@ export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog,
|
|||
<div className="taskDesc">{item.taskDesc}</div>
|
||||
{item.taskUrl && <div className="taskUrl oneLine">课题链接: <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>)}
|
||||
{/* 报名详情按钮 */}
|
||||
{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}`)}} className='lookDetail'>课题详情</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,25 +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 }) => {
|
||||
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(applyTaskId && Object.keys(applyTaskId).length >= 2){
|
||||
message.error('最多只能同时报名两个课题');
|
||||
}else{
|
||||
// 跳转到学生报名页
|
||||
window.location.href=`/glcc/student/apply/${id}`;
|
||||
}
|
||||
}else{
|
||||
showLoginDialog();
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(!detail && projectId){
|
||||
// 通过项目Id查询项目详情
|
||||
|
@ -36,13 +20,14 @@ 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项目地址: <a href={info.gitlinkUrl} className='linkUrl' target={"_blank"}>{info.gitlinkUrl}</a></p>
|
||||
<div>项目简介: {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>
|
||||
|
@ -53,13 +38,22 @@ export default ({ detail, projectId, applyTaskId, current_user, showLoginDialog,
|
|||
<div className="taskDesc">{item.taskDesc}</div>
|
||||
{item.taskUrl && <div className="taskUrl oneLine">课题链接: <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>)}
|
||||
{/* 报名详情按钮 */}
|
||||
{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}`)}} 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>
|
||||
)
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,7 +10,7 @@ import star from "../../img/star.png";
|
|||
const { Search } = Input;
|
||||
|
||||
// 项目列表
|
||||
function ProjectList({ applyTaskId, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, location, history, 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,18 +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}
|
||||
/>}
|
||||
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>
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
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} = props
|
||||
const {match, location, isStudentApplyDate, secondStudentApplyDate, applyTaskId, applyTask} = props
|
||||
const taskId = Number(match.params.taskId);
|
||||
const [detail, setDetail] = useState(undefined);
|
||||
|
||||
|
@ -20,22 +19,6 @@ function TaskDetail(props) {
|
|||
})
|
||||
},[])
|
||||
|
||||
// 申请课题按钮点击函数
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="taskDetailBgBox">
|
||||
{/* <img className="glcc-banner" src={banner} alt=''></img> */}
|
||||
|
@ -64,7 +47,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())) && (detail.locked ? <Tooltip title={"该课题已有学生入选"}><Button type='primary' className='mr10 detailBut' disabled>申请课题</Button></Tooltip> : <Button type='primary' className='applyBut mr10 detailBut' onClick={()=>{applyTask(taskId)}}>申请课题</Button>)}
|
||||
</div>
|
||||
<img src={bgPng} alt='' className='bgPng1'/>
|
||||
<img src={bgPng} alt='' className='bgPng2'/>
|
||||
|
|
|
@ -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);
|
||||
// 输入搜索框
|
||||
|
@ -27,16 +27,22 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
|
|||
{ 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: '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>
|
||||
<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}/>
|
||||
return <ProjectDetail detail={null} projectId={record.regId} applyTaskId={applyTaskId} current_user={current_user} showLoginDialog={showLoginDialog} isStudentApplyDate={isStudentApplyDate} showNotification={showNotification} secondStudentApplyDate={secondStudentApplyDate} applyTask={applyTask}/>
|
||||
}
|
||||
|
||||
// 展开收起行回调
|
||||
|
@ -79,22 +85,6 @@ function TaskList({applyTaskId, setStudentInfoReset, current_user, showLoginDial
|
|||
setExpandedRowKeys(Array.from(keys));
|
||||
}
|
||||
|
||||
// 申请课题按钮点击函数
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// 取消课题按钮点击函数
|
||||
function cancelApply(){
|
||||
const id = [];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,8 +4,9 @@ import { getUploadActionUrl, getUrl, appendFileSizeToUploadFileAll } from 'educo
|
|||
import { locData } from '../../forge/Utils/locData';
|
||||
import { getStudentApplyInfo, taskList, studentApply, studentApplyEdit } from '../api';
|
||||
import TextArea from 'antd/lib/input/TextArea';
|
||||
import {Confirm} from '../../components/ModalFun';
|
||||
import { httpUrl } from '../fetch';
|
||||
import banner from "../img/banner.png";
|
||||
// import banner from "../img/banner.png";
|
||||
import studentSvg from "../img/student.png";
|
||||
import './index.scss';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
@ -28,16 +29,20 @@ 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').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(true);
|
||||
const [userApplyInfo, setUserApplyInfo] = useState(undefined);
|
||||
const [editable, setEditable] = useState(isStudentApplyDate);
|
||||
const [files, setFiles] = useState([]);
|
||||
const [files1, setFiles1] = useState([]);
|
||||
const [files2, setFiles2] = useState([]);
|
||||
// console.log( new Date());
|
||||
// console.log('isStudentApplyDate:' + isStudentApplyDate)
|
||||
const initTask = {
|
||||
taskId,
|
||||
memo: '',
|
||||
|
@ -102,31 +107,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 && item.passStatus) {
|
||||
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);
|
||||
|
@ -139,9 +153,14 @@ function Apply(props) {
|
|||
}
|
||||
setMyTaskList(initTaskList);
|
||||
|
||||
// 如果只有一条报名数据,且课题id与当前id不一致,那么新增一条默认数据
|
||||
if (data.registrationStudentTaskList.length === 1 && data.registrationStudentTaskList[0].taskId != taskId) {
|
||||
// let idArr= data.registrationStudentTaskList.map(i=>{return i.id});
|
||||
// if(idArr.length===3){lockedCurrent=true;}
|
||||
// setLocked(lockedCurrent);
|
||||
// 如果未被锁定,且小于3条报名数据,且课题id与当前id不一致,那么新增一条默认数据
|
||||
let taskIdArr=data.registrationStudentTaskList.map(i=>{return i.taskId});
|
||||
if (!lockedCurrent && data.registrationStudentTaskList.length < 3 && !taskIdArr.includes(taskId)) {
|
||||
addTask(data.registrationStudentTaskList);
|
||||
setLocked(false);
|
||||
}
|
||||
} else {
|
||||
// 先增加数据再给选择框赋默认值,否则不生效
|
||||
|
@ -179,56 +198,65 @@ function Apply(props) {
|
|||
|
||||
// 学生报名夏令营
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
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(),
|
||||
mail: values.mail,
|
||||
phone: values.phone,
|
||||
proveAttachmentId: values.proveAttachmentId.file ? values.proveAttachmentId.file.response.id : userApplyInfo.proveAttachmentId,
|
||||
school: values.school,
|
||||
profession: values.profession,
|
||||
studentName: values.studentName,
|
||||
userId: current_user.user_id,
|
||||
registrationStudentTaskList: myTaskList
|
||||
}
|
||||
|
||||
if (userApplyInfo) {
|
||||
params.id = userApplyInfo.id;
|
||||
studentApplyEdit(params).then(response => {
|
||||
if (response && response.message === "success") {
|
||||
showNotification("修改信息成功");
|
||||
setStudentInfoReset(Math.random());
|
||||
setReload(Math.random());
|
||||
setLoading(false);
|
||||
history.push(`/glcc/subjects`)
|
||||
e.preventDefault();
|
||||
Confirm({
|
||||
title:'提示',
|
||||
content:'提交后将不允许修改报名信息,确认提交?',
|
||||
onOk:()=>{
|
||||
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(),
|
||||
mail: values.mail,
|
||||
phone: values.phone,
|
||||
proveAttachmentId: values.proveAttachmentId.file ? values.proveAttachmentId.file.response.id : userApplyInfo.proveAttachmentId,
|
||||
school: values.school,
|
||||
profession: values.profession,
|
||||
studentName: values.studentName,
|
||||
userId: current_user.user_id,
|
||||
registrationStudentTaskList: myTaskList
|
||||
}
|
||||
});
|
||||
} else {
|
||||
studentApply(params).then(response => {
|
||||
if (response && response.message === "success") {
|
||||
showNotification("报名成功");
|
||||
setStudentInfoReset(Math.random());
|
||||
setReload(Math.random());
|
||||
setLoading(false);
|
||||
history.push(`/glcc/subjects`)
|
||||
|
||||
|
||||
if (userApplyInfo) {
|
||||
params.id = userApplyInfo.id;
|
||||
studentApplyEdit(params).then(response => {
|
||||
if (response && response.message === "success") {
|
||||
showNotification("修改信息成功");
|
||||
setStudentInfoReset(Math.random());
|
||||
setReload(Math.random());
|
||||
setLoading(false);
|
||||
history.push(`/glcc/subjects`)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
studentApply(params).then(response => {
|
||||
if (response && response.message === "success") {
|
||||
showNotification("报名成功");
|
||||
setStudentInfoReset(Math.random());
|
||||
setReload(Math.random());
|
||||
setLoading(false);
|
||||
history.push(`/glcc/subjects`)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const helper = useCallback(
|
||||
|
@ -293,8 +321,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 +345,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,38 +421,39 @@ 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('所在年级',
|
||||
'',
|
||||
'grade',
|
||||
[],
|
||||
<Select placeholder="请选择所在年级" disabled={editable ? false : true} className={editable ? "" : "disabledInput"} dropdownClassName="glcc_select">
|
||||
<Select placeholder="请选择所在年级" className={"disabledInput"} disabled dropdownClassName="glcc_select">
|
||||
{gradeList.map(item => { return <Option value={item.name} key={item.id}>{item.name}</Option> })}
|
||||
</Select>
|
||||
)}
|
||||
|
@ -431,7 +463,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 +473,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,6 +488,7 @@ function Apply(props) {
|
|||
accept=".png,.jpg,.jpeg"
|
||||
beforeUpload={beforeUpload}
|
||||
onChange={handleChange}
|
||||
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>
|
||||
|
@ -469,12 +502,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('课题名称',
|
||||
|
@ -494,6 +527,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,
|
||||
|
@ -506,7 +540,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" : "memoText disabledInput"} />
|
||||
onBlur={(e) => { verify("memo" + i); changeTaskItem("memo", e.currentTarget.value, i) }}
|
||||
rows={7}
|
||||
className={!(isStudentApplyDate && !item.id) ? "memoText disabledInput" : "memoText"}
|
||||
disabled={!(isStudentApplyDate && !item.id)} />
|
||||
)}</div>
|
||||
|
||||
<div className='introArea'>{helper('附件',
|
||||
|
@ -516,7 +553,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}
|
||||
|
@ -525,8 +562,9 @@ function Apply(props) {
|
|||
downloadIcon: <i className="iconfont icon-xiazai-icon"></i>,
|
||||
showRemoveIcon: true
|
||||
}}
|
||||
disabled={!(isStudentApplyDate && !item.id)}
|
||||
>
|
||||
<div className="glcc_btn">上传自荐书</div>
|
||||
<div className="glcc_btn" >上传自荐书</div>
|
||||
</Upload>
|
||||
)}</div>
|
||||
</Fragment>
|
||||
|
@ -539,23 +577,24 @@ 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 >
|
||||
<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>
|
||||
}
|
||||
|
||||
<Form.Item className='subInfo introArea'>
|
||||
<Button type="primary" htmlType="submit" className='sub' disabled={!editable}>提交</Button>
|
||||
</Form.Item>
|
||||
{!studentApplyEnd && <Form.Item className='subInfo introArea'>
|
||||
<Button type="primary" htmlType="submit" className='sub' disabled={!(editable && !locked)}>提交</Button>
|
||||
</Form.Item>}
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -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: 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;
|
||||
|
|
Loading…
Reference in New Issue