报名/作品列表新增驳回以及搜索功能,报名/作品驳回操作

This commit is contained in:
谢思 2022-04-21 17:11:07 +08:00
parent eaf1cdfbfd
commit 1c279d7b06
8 changed files with 164 additions and 56 deletions

View File

@ -26,15 +26,15 @@ if (isDev) {
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'a' : parsed.debug || 'admin'
}
}
window._debugType = debugType;
export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener();
// var proxy = "http://192.168.1.40:3000";
// var proxy = "http://111.8.36.180:8000";
var proxy = "http://117.50.100.12:49999";
var proxy = "http://111.8.36.180:8000";
// var proxy = "http://117.50.100.12:49999";
//响应前的设置
axios.interceptors.request.use(

View File

@ -181,7 +181,7 @@ const Qz2022 = (props) => {
{/* 处于报名阶段正常跳转到报名页面,不处于右侧弹消息 */}
<li className={active === "apply" ? "active" : ""}>
<Link to={{ pathname: applyStatus && current_user && current_user.login ? '/competition/qz2022/apply' :'' }} onClick={()=>{current_user && current_user.login ? !applyStatus && props.showNotification("报名时间已截止") : props.showLoginDialog()}}>参赛报名</Link>
</li>
</li>
<li className={active === "refer" ? "active" : ""}>
<Link to={{ pathname: referStatus && !referEnd && current_user && current_user.login && enrollStatus && enrollStatus.enroll_status ? `/competition/qz2022/refer` : '' }} onClick={goToRefer}>提案提交</Link>
</li>
@ -243,7 +243,7 @@ const Qz2022 = (props) => {
{/* 参赛报名 */}
<Route path="/competition/qz2022/apply"
render={
() => (<Apply {...props} qzDetail={qzDetail} enrollStatus={enrollStatus} setReload={setReload} />)
() => (<Apply {...props} qzDetail={qzDetail} enrollStatus={enrollStatus} setReload={setReload}/>)
}
></Route>
{/* 提案提交 */}
@ -273,13 +273,13 @@ const Qz2022 = (props) => {
{/* 后台管理-报名列表 */}
<Route path="/competition/qz2022/management/applys"
render={
() => (<Management {...props} qzDetail={qzDetail} />)
() => (<Management {...props} qzDetail={qzDetail}/>)
}
></Route>
{/* 后台管理-作品列表 */}
<Route path="/competition/qz2022/management/production"
render={
() => (<Management {...props} qzDetail={qzDetail} />)
() => (<Management {...props} qzDetail={qzDetail}/>)
}
></Route>
{/* 大赛介绍 */}

View File

@ -15,6 +15,11 @@ export async function enrollCompetition(data){
return axios.post(`/competition_infos/qz2022/enroll.json`,data);
}
// 修改报名信息
export async function enrollUpdate(id, data){
return axios.post(`/competition_infos/${id}/enroll_update.json`,data);
}
// 统计启智2022 竞赛
export async function stattistics(data){
return axios.get( `/competition_infos/qz2022/statistics.json`);
@ -63,4 +68,9 @@ export async function deleteQz2022Notice(id){
// 编辑大赛介绍、大赛指南、关于我
export async function updateQz2022(data){
return axios.put(`/competition_infos/qz2022.json`,data);
}
// 修改竞赛报名状态
export async function updateEnroll(data){
return axios.post(`/competition_infos/qz2022/enroll_status_update.json`,data);
}

View File

@ -1,7 +1,7 @@
import React, {useState, useCallback} from "react";
import { Input, Select, Button, Form, message, Radio } from 'antd';
import { Input, Select, Button, Form, message, Radio, Modal } from 'antd';
import { Base64 } from 'js-base64';
import {enrollCompetition} from '../api';
import {enrollCompetition, enrollUpdate} from '../api';
import {current_main_site_url} from '../fetch';
import EditTable from "../editTable";
import apply_top from "../image/apply_top.png";
@ -22,13 +22,19 @@ export default Form.create()((props) => {
const [members, setMembers] = useState([]);
const [errorMessage, setErrorMessage] = useState(undefined);
const [sourceBy, setSourceBy] = useState(1);
const [visible, setVisible] = useState(false);
useEffect(()=>{
if(current_user && !current_user.login){
const applyStatus = qzDetail ? Date.parse(new Date()) < Date.parse(new Date(qzDetail.enroll_date)) : true;
if((current_user && !current_user.login) || !applyStatus){
history.push("/competition/qz2022");
}
},[])
if(enrollStatus && enrollStatus.status === 0){
setMembers(enrollStatus.enroll_info.members);
setSourceBy(enrollStatus.enroll_info.subject_source_type);
setFieldsValue(enrollStatus.enroll_info);
}
},[current_user, enrollStatus])
// form
const helper = useCallback(
@ -86,13 +92,24 @@ export default Form.create()((props) => {
members,
subject_source_type: sourceBy,
}
enrollCompetition(params).then(response=>{
// enrollStatusstatus
enrollStatus && enrollStatus.status === 0 && enrollUpdate(current_user.user_id, params).then(response=>{
if(response && response.data.message === "success"){
setReload(Math.random());
message.success('资料修改成功');
}else{
message.error(response.message);
}
setVisible(false);
})
enrollStatus && enrollStatus.status !== 0 && enrollCompetition(params).then(response=>{
if(response && response.data.message === "success"){
setReload(Math.random());
message.success('报名成功')
}else{
message.error(response.message);
}
setVisible(false);
})
}
})
@ -100,7 +117,6 @@ export default Form.create()((props) => {
//
function errorSource(rule, value, callback){
console.log(rule, value, sourceBy);
if(sourceBy === 1 && !value){
//
callback('请正确输入课题来源');
@ -108,34 +124,34 @@ export default Form.create()((props) => {
callback();
}
}
console.log(current_main_site_url);
return (
<div className="qz_main">
<div className="step">
<span className="left_tit">&nbsp;&nbsp;报名</span>
<img src={apply_top} className="step_icon"/>
<img src={apply_top} className="step_icon" alt=""/>
<div className="border_dashed"></div>
<div className="img_span">
<img src={enrollStatus && enrollStatus.enroll_status ? apply_one : apply_one_active} className="step_icon"/>
<img src={enrollStatus && (!enrollStatus.enroll_status || enrollStatus.status === 0) ? apply_one_active : apply_one} className="step_icon" alt=""/>
个人信息
</div>
<div className="border_dashed"></div>
<div className="img_span">
<img src={enrollStatus && enrollStatus.enroll_status ? apply_two_active : apply_two} className="step_icon"/>
<img src={enrollStatus && enrollStatus.enroll_status && enrollStatus.status !== 0 ? apply_two_active : apply_two} className="step_icon" alt=""/>
报名成功
</div>
<div className="border_dashed"></div>
<img src={apply_down} className="step_icon"/>
<img src={apply_down} className="step_icon" alt=""/>
</div>
{!(enrollStatus && enrollStatus.enroll_status) && <div className="apply_tip font-15">
<img src={apply_notice} className="apply_notice"/>
请认真核对报名信息务必与线下报名表信息一致
<img src={apply_notice} className="apply_notice" alt=""/>
请认真核对报名信息务必与线下报名表信息一致!
</div>}
<div className="apply_information mb60">
<div className="info_head">{!(enrollStatus && enrollStatus.enroll_status) && '填写'}报名信息</div>
{/* 报名表单 */}
{
!(enrollStatus && enrollStatus.enroll_status) &&
enrollStatus && (!enrollStatus.enroll_status || enrollStatus.status === 0) &&
<Form className="info_form">
{helper('参赛单位',
'org_name',
@ -184,7 +200,7 @@ console.log(current_main_site_url);
{sourceBy === 1 && helper('',
'subject_source_name',
[{ max: 32, message: '超出限制长度32位字符请重新编辑' },
{ validator: (rule, value, callback)=>{errorSource(rule, value, callback)}}],
{ validator: (rule, value, callback)=>{errorSource(rule, value, callback)}}],
<Input placeholder="请输入项目名称" onBlur={()=>{verify("subject_source_name")}}/>
)}
</div>}
@ -199,31 +215,43 @@ console.log(current_main_site_url);
<p className="error_message">{errorMessage}</p>
{/* */}
{qzDetail &&
<EditTable setMembers={setMembers} isLocal = {qzDetail.is_local}/>}
<EditTable members={enrollStatus && enrollStatus.enroll_info.members} setMembers={setMembers} isLocal = {qzDetail.is_local}/>}
</div>
</Form>}
{/* 已报名,报名信息 */}
{enrollStatus && enrollStatus.enroll_status &&
{enrollStatus && enrollStatus.enroll_status && enrollStatus.status !== 0 &&
<div className="info">
<div><span>参赛单位 : </span>{enrollStatus && enrollStatus.enroll_info.org_name}</div>
<div className="info-right"><span>参赛团队负责人姓名 : </span>{enrollStatus && enrollStatus.enroll_info.leader}</div>
{qzDetail && qzDetail.is_local && <div><span>职务 : </span>{enrollStatus && enrollStatus.enroll_info.org_job}</div>}
<div><span>参赛单位 : </span>{enrollStatus && enrollStatus.enroll_info.org_name}</div>
<div className="info-right"><span>参赛团队负责人姓名 : </span>{enrollStatus && enrollStatus.enroll_info.leader}</div>
{qzDetail && qzDetail.is_local && <div><span>职务 : </span>{enrollStatus && enrollStatus.enroll_info.org_job}</div>}
{qzDetail && qzDetail.is_local && <div className="info-right"><span>{Base64.decode('5Yab6KGU')} : </span>{enrollStatus && enrollStatus.enroll_info.org_rank}</div>}
<div><span>赛区 : </span>{enrollStatus && enrollStatus.enroll_info.zone}</div>
<div className="info-right"><span>赛项 : </span>{enrollStatus && enrollStatus.enroll_info.sub_competition}</div>
<div><span>赛区 : </span>{enrollStatus && enrollStatus.enroll_info.zone}</div>
<div className="info-right"><span>赛项 : </span>{enrollStatus && enrollStatus.enroll_info.sub_competition}</div>
{qzDetail && qzDetail.is_local && <div><span>课题来源 : </span>{enrollStatus && enrollStatus.enroll_info.subject_source_type === 0 ? "自主提报" : enrollStatus.enroll_info.subject_source_name}</div>}
<div className={`${qzDetail && qzDetail.is_local ? '':'info_bottom'}`}><span>电话 : </span>{enrollStatus && enrollStatus.enroll_info.phone}</div>
<div className={`info-right ${qzDetail && qzDetail.is_local ? 'ellipsis_div':''}`}><span>成员 : </span>{enrollStatus && enrollStatus.enroll_info.members && enrollStatus.enroll_info.members.map(item=>{return item.real_name + ','})}</div>
<div className={`${qzDetail && qzDetail.is_local ? '':'info_bottom'}`}><span>电话 : </span>{enrollStatus && enrollStatus.enroll_info.phone}</div>
<div className={`info-right ${qzDetail && qzDetail.is_local ? 'ellipsis_div':''}`}><span>成员 : </span>{enrollStatus && enrollStatus.enroll_info.members && enrollStatus.enroll_info.members.map(item=>{return item.real_name + ','})}</div>
</div>}
</div>
{!(enrollStatus && enrollStatus.enroll_status) && <div className="apply_but">
<Button type="primary" className="submit_info" onClick={applySubmit}>
{enrollStatus && (!enrollStatus.enroll_status || enrollStatus.status === 0) && <div className="apply_but">
<Button type="primary" className="submit_info" onClick={()=>{setVisible(true)}}>
提交资料
</Button>
<a href={qzDetail && qzDetail.is_local ? 'http://osredm.jk:81/api/attachments/1963' : `${current_main_site_url}/api/attachments/${window.location.host.indexOf("osredm")!== -1 ? "4122" : current_main_site_url.indexOf("49999") === -1 ? "3715" : "1896"}`}>
<Button className="add_member download ml20">下载报名表</Button>
</a>
</div>}
<Modal
title="提示"
visible={visible}
onOk={applySubmit}
onCancel={()=>{setVisible(false)}}
centered
wrapClassName="applyInfoCon"
cancelText=""
>
<div className="tips mb10"><i className="iconfont icon-shanchu_tc_icon1 font-24 mr10" style={{color: '#ffa13a'}}></i><span className="tipTitle font-16">确定提交报名信息</span></div>
<span>提交后报名信息将无法修改!</span>
</Modal>
</div>
)
})

View File

@ -153,4 +153,32 @@
.download{
padding: 0 10px;
}
}
.applyInfoCon .ant-modal-content{
.ant-modal-header{
padding: 10px 24px;
background-color: #eef1ff;
border-bottom:none;
}
.ant-modal-close{top: 1px !important;}
.ant-modal-close-x{font-size: 20px;}
.ant-modal-title{
font-weight: normal !important;
text-align: left;
}
.ant-modal-body{
padding: 50px 50px 40px;;
text-align: center;
.tipTitle{color: #181818;}
}
.tips{
display: flex;
justify-content: center;
align-items: center;
}
.ant-modal-footer{
border-top: none;
text-align: center;
padding-bottom: 40px;
}
}

View File

@ -29,7 +29,7 @@ class EditableCell extends React.Component {
renderCell = form => {
this.form = form;
const {dataIndex, title } = this.props;
const {record, dataIndex, title } = this.props;
return <Form.Item >
{form.getFieldDecorator(dataIndex, {
rules: [
@ -37,6 +37,7 @@ class EditableCell extends React.Component {
{max: 32, message: '超出限制长度32位字符,请重新编辑' }
],
validateFirst: true,
initialValue: record[dataIndex],
})(<Input onPressEnter={(e)=>{this.save(dataIndex,e)}} onBlur={(e)=>{this.save(dataIndex,e)}} placeholder="请输入"/>)}
</Form.Item>
};
@ -87,7 +88,7 @@ class EditableTable extends React.Component {
render: (text, record) =>
this.state.dataSource.length >= 1 ? (
<Popconfirm title="确定删除此成员?" onConfirm={() => this.handleDelete(record.key)}>
<img src={apply_delete} className="apply_delete"/>
<img src={apply_delete} className="apply_delete" alt=""/>
</Popconfirm>
) : null,
},
@ -120,18 +121,14 @@ class EditableTable extends React.Component {
render: (text, record) =>
this.state.dataSource.length >= 1 ? (
<Popconfirm title="确定删除此成员?" onConfirm={() => this.handleDelete(record.key)}>
<img src={apply_delete} className="apply_delete"/>
<img src={apply_delete} className="apply_delete" alt=""/>
</Popconfirm>
) : null,
},];
}
this.state = {
dataSource: [
{
key: '0',
}
],
count: 1,
dataSource: this.props.members,
count: this.props.members.length,
};
}

View File

@ -1,19 +1,18 @@
import React, { useState, useMemo, useEffect } from "react";
import { Base64 } from 'js-base64';
import {Select, Button, Tooltip, Input, Popconfirm } from 'antd';
import {Select, Button, Tooltip, Input, Popconfirm, message } from 'antd';
import {current_main_site_url} from '../fetch';
import PaginationTable from "../../components/paginationTable";
import './index.scss';
import '../index.scss';
import { getQzEnrollList, getQzProList } from "../api.js";
import { getQzEnrollList, getQzProList, updateEnroll } from "../api.js";
const Option = Select.Option;
const {Search} = Input;
function Introduce({history:{location:{pathname}},qzDetail }) {
// type01
const [type, setType] = useState(pathname.substring(pathname.lastIndexOf('/')+1, pathname.lenght));
const [reload, setReload] = useState();
const [loading, setLoading] = useState(false);
const [curPage, setCurPage] = useState(1);
const [dataList, setDataList] = useState([]);
@ -21,6 +20,7 @@ function Introduce({history:{location:{pathname}},qzDetail }) {
//
const [zone, setZone] = useState(undefined);
const [subCompetition, setSubCompetition] = useState(undefined);
const [keyword, setKeyword] = useState(undefined);
useEffect(() => {
setType(pathname.substring(pathname.lastIndexOf('/')+1, pathname.lenght));
@ -35,7 +35,8 @@ function Introduce({history:{location:{pathname}},qzDetail }) {
zone: zone === '-1' ? undefined : zone,
sub_competition: subCompetition === '-1' ? undefined : subCompetition,
page: curPage,
limit: 10
limit: 10,
keyword
}
if(type === "applys"){
//
@ -58,7 +59,20 @@ function Introduce({history:{location:{pathname}},qzDetail }) {
setLoading(false);
})
}
}, [type, zone, subCompetition, curPage])
}, [type, zone, subCompetition, curPage, keyword])
//
function reject(userId, index){
const params = {
user_id: userId,
status: index
}
updateEnroll(params).then(response=>{
if(response && response.status === 200){
message.success("操作成功");
}
})
}
let columns_apply = useMemo(() => {
return [
@ -100,6 +114,7 @@ function Introduce({history:{location:{pathname}},qzDetail }) {
return <Popconfirm
title="您确定驳回此用户的报名信息?"
icon={<i className="iconfont icon-shanchu_tc_icon mr3 font-15" style={{float: 'left', color: "red"}}></i>}
onConfirm={()=>{reject(record.user_id, 0)}}
><Button size="small">驳回</Button></Popconfirm>
}
}
@ -139,11 +154,12 @@ function Introduce({history:{location:{pathname}},qzDetail }) {
return <Popconfirm
title="您确定驳回此用户的作品信息?"
icon={<i className="iconfont icon-shanchu_tc_icon mr3 font-15" style={{float: 'left', color: "red"}}></i>}
onConfirm={()=>{reject(record.user_id, 1)}}
><Button size="small">驳回</Button></Popconfirm>
}
}
];
}, [qzDetail, reload]);
}, [qzDetail]);
//
if(qzDetail && qzDetail.is_local && columns_apply[2].title !== "职务"){
@ -229,7 +245,7 @@ function Introduce({history:{location:{pathname}},qzDetail }) {
<div className="search">
<div className="font-14">
<Search placeholder={`输入单位/负责人${type === "applys" ? "/电话" : ""}进行搜索`} onSearch={value => console.log(value)} enterButton style={{width: 300, marginRight: "30px"}}/>
<Search placeholder={`输入单位/负责人${type === "applys" ? "/电话" : ""}进行搜索`} onSearch={value => {setKeyword(value)}} allowClear enterButton style={{width: 300, marginRight: "30px"}}/>
<span>赛区: </span>
<Select defaultValue="-1" style={{ width: 150 }} onChange={(value)=>{setZone(value)}}>
<Option value='-1'>所有赛区</Option>

View File

@ -1,4 +1,5 @@
import React, { useState, useCallback, useMemo, useEffect } from "react";
import {Prompt} from 'react-router-dom'
import { Input, Select, Button, Form, DatePicker, Table, Pagination, Upload, Modal, Icon, message } from 'antd';
import { appendFileSizeToUploadFileAll } from 'educoder';
import { Link } from "react-router-dom";
@ -12,12 +13,16 @@ import refer from "../image/refer.svg";
import './index.scss';
import '../../index.scss';
import '../apply/index.scss';
const Option = Select.Option;
function Introduce({ form, showNotification, match, history, enrollStatus, current_user, qzDetail, setReload}) {
// loading
const [loading, setLoading] = useState(false);
const [files, setFiles] = useState();
//
const [changeFiles, setChangeFiles] = useState(false);
const [visible, setVisible] = useState(false);
useEffect(()=>{
// referStatus :
@ -40,12 +45,13 @@ function Introduce({ form, showNotification, match, history, enrollStatus, curre
}, [enrollStatus]);
function handleChange(info) {
if (info.file.status === 'uploading' || info.file.status == "done" || info.file.status === 'removed') {
if (info.file.status === 'uploading' || info.file.status === "done" || info.file.status === 'removed') {
setLoading(true);
setFiles(appendFileSizeToUploadFileAll(info.fileList).slice(-1))
}
if(info.file.status == "done" || info.file.status === 'removed'){
if(info.file.status === "done" || info.file.status === 'removed'){
setLoading(false);
setChangeFiles(true);
}
}
@ -76,7 +82,9 @@ function Introduce({ form, showNotification, match, history, enrollStatus, curre
}
uploadCompetition(params).then(response=>{
if(response && response.status === 200){
setChangeFiles(false);
setReload(Math.random());
setVisible(false);
message.success('提交作品成功');
}else{
message.error(response.data.message);
@ -84,10 +92,19 @@ function Introduce({ form, showNotification, match, history, enrollStatus, curre
})
}
}
//
const upload = enrollStatus && (!enrollStatus.upload_status || enrollStatus.status === 1);
return (
<div className="refer_bg">
{
changeFiles &&
<Prompt
when={true}
message={() => '您重新上传了作品文件暂未提交,确定离开此页面吗?'}
/>
}
<div className="qz_main refer">
<img src={refer} className="refer_img mb20"/>
<img src={refer} className="refer_img mb20" alt=""/>
<Upload
accept=".zip,.rar,.tar"
// action?debug=admin
@ -102,14 +119,26 @@ function Introduce({ form, showNotification, match, history, enrollStatus, curre
showRemoveIcon: false
}}
>
<Button className="upload"><Icon type="upload" />上传</Button>
<Button className="upload" disabled={!upload}><Icon type="upload"/>{!upload ? '已' : ''}上传</Button>
</Upload>
<Modal/>
{enrollStatus && enrollStatus.upload_status && <div className="refer_tip mt20 cover"><i className="iconfont icon-erciqueren_icon mr10"></i>您已提交作品再次提交将会覆盖您上一次的提交成果</div>}
{/* {enrollStatus && enrollStatus.status === 1 && <div className="refer_tip mt15 cover"><i className="iconfont icon-erciqueren_icon mr10"></i>您已上传作品,再次上传将会覆盖您上一次上传的压缩包文件。</div>} */}
<div className="refer_tip mt20">上传单个作品压缩包仅限上传一个压缩包</div>
<div className="refer_bor"></div>
<Button type="primary" onClick={referProduction} loading={loading}>提交作品</Button>
<Button type="primary" onClick={()=>{changeFiles ? setVisible(true) : message.error("您暂未上传作品文件")}} loading={loading} disabled={!upload}>{!upload ? '已' : ''}提交作品</Button>
</div>
<Modal
title="提示"
visible={visible}
onOk={referProduction}
onCancel={()=>{setVisible(false)}}
centered
wrapClassName="applyInfoCon"
cancelText=""
>
<div className="tips mb10"><i className="iconfont icon-shanchu_tc_icon1 font-24 mr10" style={{color: '#ffa13a'}}></i><span className="tipTitle font-16">确定提交作品</span></div>
<span>提交后作品文件将无法修改!</span>
</Modal>
</div>
)
}