合并竞赛迭代代码

This commit is contained in:
何童崇 2022-04-27 18:12:02 +08:00
parent f254b9cb71
commit f47f2b8f37
8 changed files with 590 additions and 5 deletions

View File

@ -0,0 +1,115 @@
import { Button, message, Modal, Select, Tooltip,Table } from "antd";
import React, { useEffect, useMemo, useState } from "react";
import Link from "react-router-dom/Link";
import axios from "axios";
import './index.scss';
const Option = Select.Option;
// current_status 1 2 3 4 5 6
function Competition(props){
const {mygetHelmetapi, showNotification, history} = props;
const {main_web_site_url} = mygetHelmetapi;
const {hash} = history && history.location;
const [loading, setLoading] = useState(false);
//
const [competitionList, setCompetitionList] = useState(undefined);
const [reload, setReload] = useState(undefined);
//
const columns = useMemo(() => {
return [
{
title: "序号",
dataIndex: "index",
key: "index",
align: "center",
render:(text,record,i)=>{
return i+1
}
},
{
title: "唯一标识",
dataIndex: "identifier",
key: "identifier",
align: "center",
},
{
title: "赛事标题",
dataIndex: "title",
key: "title",
align: "center",
render:(text, record)=>{
return <Tooltip title={`标识: ${record.identifier}, 竞赛副标题: ${record.subtitle}`}><a href={`${main_web_site_url}/competitions/${record.identifier}/home`} target="_blank" className="primary-link">{text}</a></Tooltip>
}
},
{
title: "报名截止时间",
dataIndex: "enroll_date",
key: "enroll_date",
align: "center",
},
{
title: "提案截止时间",
dataIndex: "upload_date",
key: "upload_date",
align: "center",
},
{
title: "是否内网环境",
dataIndex: "is_local",
key: "is_local",
align: "center",
render:(text,record)=>{
return text?'是':'否'
}
},
{
title: '操作',
dataIndex: 'id',
key: 'action',
fixed: 'right',
render: (text, record)=>{
return <Button size="small" type="link" href={`/managements/competition/customize/edit/${record.identifier}`}>编辑</Button>
}
}
];
}, []);
//
useEffect(()=>{
setLoading(true);
let url = "/competition_infos.json";
axios.get(url).then((res) => {
if(res.data.message === 'success'){
setCompetitionList(res.data.data||[])
}
}).catch((error) => {
}).finally(()=>{
setLoading(false);
})
}, [])
return(
<div className="centerbox competitionList">
<Button type="primary" className="mb10" onClick={()=>{history.push('/managements/competition/customize/add')}}>新增</Button>
<Table
loading={loading}
dataSource={competitionList}
columns={columns}
// total={total}
// setCurPage={(page)=>{updateUrl(page)}}
// current={curPage}
pagination={false}
// pageSize={10}
/>
</div>
)
}
export default Competition;

View File

@ -0,0 +1,63 @@
a.primary-link{
color: #4154f1;
&:hover{
opacity: 0.8;
}
}
.gary_span{
color: rgba(176, 176, 176, 1);
}
// 发布评审任务弹框样式
.publishReview{
width: 1050px !important;
.ant-modal-body{
padding: 0;
}
.ant-modal-confirm-btns {
margin: 15px 35px 10px;
}
.ant-modal-confirm-title{
border-bottom: 1px solid #eeeeee;
padding: 20px 25px;
background: #f2f2ff;
font-size: 18px;
}
.ant-modal-confirm-body > .anticon{
display: none;
}
.ant-modal-confirm-body > .anticon + .ant-modal-confirm-title + .ant-modal-confirm-content{
margin-left: 0;
}
.ant-modal-confirm-content{
&>p{
font-size: 16px;
color: #333333;
border-bottom: 1px solid #eeeeee;
padding: 10px 35px;
font-weight: bold;
}
&>div{
padding: 10px 45px;
}
.tip{
padding: 10px 35px;
i{
color: #ca0002;
}
.publicTitle {
font-size: 15px;
margin-left: 3px;
}
}
}
.pagination-table .ant-table-tbody > tr > td{
padding: 3px 8px;
}
}
.competitionList{
.ant-select-selection{
width: 115px;
}
}

View File

@ -0,0 +1,322 @@
import React, { useEffect, useState, useCallback } from "react";
import { Input, Row, Col, Button, Form, message, Spin, Checkbox, DatePicker, Upload, Icon } from 'antd';
import axios from "axios";
import moment from 'moment';
import MDEditor from 'src/modules/tpm/challengesnew/tpm-md-editor';
import { getUploadActionUrl } from 'educoder';
import './index.scss';
const format = "YYYY-MM-DD HH:mm:ss";
export default Form.create()(({ form, match, history, current_user }) => {
const id = match.params.id
const { getFieldDecorator, validateFields, setFieldsValue } = form;
const [content, setContent] = useState('');
const [guide, setGuide] = useState('');
const [about_us, setAbout_us] = useState('');
const [loading, setLoading] = useState(false);
useEffect(() => {
if (id) {
setLoading(true);
const url = `/competition_infos/${id}/edit.json`;
axios.get(url).then((res) => {
if (res.data.message === 'success') {
let details = res.data.data
let initValue = {
title: details.title,
identifier: details.identifier,
content: details.content,
banner_url: details.banner_url,
video_url: details.video_url,
enroll_template: details.enroll_template,
guide: details.guide,
is_local: details.is_local,
zones_local: details.zones_local,
sub_competitions: details.sub_competitions,
zones: details.zones,
enroll_date: moment(details.enroll_date),
upload_date: moment(details.upload_date),
about_us: details.about_us,
manager_ids: details.manager_ids,
};
setFieldsValue(initValue);
setContent(details.content);
setGuide(details.guide);
setAbout_us(details.about_us);
}
setLoading(false);
}).catch((error) => {
}).finally(() => {
setLoading(false);
})
}
}, [id])
// form
const helper = useCallback(
(label, name, rules, widget) => (
<Form.Item label={label} >
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
),
[]
);
//
function verify(dataIndex) {
validateFields([dataIndex], (error, values) => {
if (error && error[dataIndex]) {
return;
}
})
}
function onContentChange(value, key) {
setFieldsValue({
[key]: value
});
if (key === 'content') {
setContent(value);
} else if (key === 'guide') {
setGuide(value);
} else if (key === 'about_us') {
setAbout_us(value);
}
};
function handleChange(info, key) {
if (info.file.status === 'uploading') {
setLoading(true);
}
if (info.file.status === "done" || info.file.status === 'removed') {
setLoading(false);
if (info.file.response.id) {
if (key === 'banner_url') {
setFieldsValue({
[key]: `/api/attachments/${info.file.response.id}`
})
} else if (key === 'video_url') {
setFieldsValue({
[key]: `/api/attachments/${info.file.response.id}.mp4`
})
} else if (key === 'enroll_template') {
setFieldsValue({
[key]: `/api/attachments/${info.file.response.id}`
})
}
}
}
}
function submit() {
validateFields((error, values) => {
if (!error) {
setLoading(true);
if (id) {
const url = `/competition_infos/${id}.json`
axios.put(url, values).then(res => {
dealRes(res)
})
} else {
const url = `/competition_infos.json`
axios.post(url, values).then(res => {
dealRes(res)
})
}
}
})
}
function dealRes(res){
if (res && res.data.message === "success") {
message.success('保存成功');
history.push('/managements/competition/customize');
} else {
message.error(res ? res.data.message : '保存失败');
}
setLoading(false);
}
return (
<Spin spinning={loading}>
<div className="centerbox competition_setting">
<Button type="link" onClick={() => { history.push('/managements/competition/customize'); }} className="mb10">返回</Button>
{helper('赛事名称',
'title',
[{ required: true, message: "请正确输入赛事名称" }],
<Input placeholder="请输入参赛单位" onBlur={() => { verify("title") }} />
)}
{helper('赛事唯一标识',
'identifier',
[{ required: true, message: "请正确输入赛事唯一标识" }],
<Input placeholder="请输入参赛单位" onBlur={() => { verify("identifier") }} />
)}
<Form.Item className="mb0 mdEditor" label={'大赛介绍'}>
<MDEditor
placeholder={"请输入大赛介绍"}
height={500}
mdID={"competition-content"}
initValue={content}
onChange={(value) => { onContentChange(value, 'content') }}
/>
{getFieldDecorator("content", {
rules: [{ required: true, message: "请输入大赛介绍" }],
validateFirst: true,
})(<Input style={{ display: "none" }} />)}
</Form.Item>
<Form.Item className="video-box" label="Banner图">
<Row gutter={8}>
<Col span={12}>
{getFieldDecorator('banner_url', {
rules: [{ required: true, message: '请上传Banner图或填写Banner图地址' }],
})(<Input placeholder="请上传Banner图或填写Banner图地址" onBlur={() => { verify("video_url") }} />)}
</Col>
<Col span={12}>
<Upload
accept=".png,jpg,.jpeg,.svg"
action={getUploadActionUrl()}
onChange={(info) => { handleChange(info, 'banner_url') }}
showUploadList={false}
>
<Button className="upload"><Icon type="upload" />上传Banner图</Button>
</Upload>
</Col>
</Row>
</Form.Item>
<Form.Item className="video-box" label="视频地址" >
<Row gutter={8}>
<Col span={12}>
{getFieldDecorator('video_url', {
rules: [{ required: true, message: '请上传视频或填写视频地址' }],
})(<Input placeholder="请上传视频或填写视频地址" onBlur={() => { verify("video_url") }} />)}
</Col>
<Col span={12}>
<Upload
accept=".mp4"
action={getUploadActionUrl()}
onChange={(info) => { handleChange(info, 'video_url') }}
showUploadList={false}
>
<Button className="upload"><Icon type="upload" />上传视频</Button>
</Upload>
</Col>
</Row>
</Form.Item>
<Form.Item className="video-box" label="报名资料文件" >
<Row gutter={8}>
<Col span={12}>
{getFieldDecorator('enroll_template', {
rules: [{ required: true, message: '请上传报名资料文件' }],
})(<Input placeholder="请上传报名资料文件" onBlur={() => { verify("enroll_template") }} />)}
</Col>
<Col span={12}>
<Upload
action={getUploadActionUrl()}
onChange={(info) => { handleChange(info, 'enroll_template') }}
showUploadList={false}
>
<Button className="upload"><Icon type="upload" />上传报名资料文件</Button>
</Upload>
</Col>
</Row>
</Form.Item>
<Form.Item label={'是否内网环境'} >
{getFieldDecorator('is_local',{valuePropName:"checked"})(<Checkbox />)}
</Form.Item>
{helper('赛区(内网)',
'zones_local',
[{ required: true, message: "请填写赛区" }],
<Input placeholder="请填写赛区" onBlur={() => { verify("zones_local") }} />
)}
{helper('赛区(外网)',
'zones',
[{ required: true, message: "请填写赛区" }],
<Input placeholder="请填写赛区" onBlur={() => { verify("zones") }} />
)}
{helper('赛项',
'sub_competitions',
[{ required: true, message: "请填写赛项" }],
<Input placeholder="请填写赛项" onBlur={() => { verify("sub_competitions") }} />
)}
{helper(
"报名截止时间",
"enroll_date",
[],
<DatePicker
format={format}
placeholder="请选择时间"
showTime
/>,
moment(new Date(), format)
)}
{helper(
"提交作品截止时间",
"upload_date",
[],
<DatePicker
format={format}
placeholder="请选择时间"
showTime
/>,
moment(new Date(), format)
)}
<Form.Item className="mb0 mdEditor" label={'赛事指南'}>
<MDEditor
placeholder={"请输入赛事指南"}
height={500}
mdID={"competition-guide"}
initValue={guide}
onChange={(value) => { onContentChange(value, 'guide') }}
/>
{getFieldDecorator("guide", {
rules: [{ required: true, message: "请输入赛事指南" }],
validateFirst: true,
})(<Input style={{ display: "none" }} />)}
</Form.Item>
<Form.Item className="mb0 mdEditor" label={'联系我们'}>
<MDEditor
placeholder={"请输入联系我们"}
height={500}
mdID={"competition-about"}
initValue={about_us}
onChange={(value) => { onContentChange(value, 'about_us') }}
/>
{getFieldDecorator("about_us", {
rules: [{ required: true, message: "请输入联系我们" }],
validateFirst: true,
})(<Input style={{ display: "none" }} />)}
</Form.Item>
{helper('管理员配置配置方式用户id:赛区名称,用户id:赛区名称)',
'manager_ids',
[],
<Input placeholder="请配置管理员" onBlur={() => { verify("manager_ids") }} />
)}
<div className="mt20">
<Button className="mr30" type="primary" onClick={submit}>提交</Button>
<Button onClick={() => { history.push('/managements/competition/customize'); }}>取消</Button>
</div>
</div>
</Spin>
)
})

View File

@ -0,0 +1,26 @@
.competition_setting{
background: #fff;
padding: 10px 15px;
.ant-form-item{
min-height: 3.5rem;
margin-bottom:0;
}
.ant-form-explain{
position: absolute;
}
.ant-form-item-label{
min-width: 125px;
}
.ant-form-item-control-wrapper{
display: inline-block;
min-width: calc(100% - 126px);
}
.mdEditor{
.ant-form-item-control-wrapper{
display: block;
}
}
.video-box .ant-form-item-label{
vertical-align: baseline;
}
}

View File

@ -96,7 +96,15 @@ const CompetitionList = Loadable({
loader: () => import("../military/expert/competionList"),
loading: Loading,
});
// 定制化竞赛列表,如启智
const CompetionCustomize =Loadable({
loader: () => import("../managements/competition/competionCustomize"),
loading: Loading,
})
const CompetionSetting=Loadable({
loader: () => import("../managements/competition/setting"),
loading: Loading,
});
// 公告管理
const NoticeManage = Loadable({
loader: () => import("./notice"),
@ -278,6 +286,27 @@ const Managements = (propsF) => {
<NoticeManage {...propsF} {...props} />
)}
></Route>
{/* 定制竞赛配置详情 */}
<Route
path="/managements/competition/customize/edit/:id"
render={(props) => (
<CompetionSetting {...propsF} {...props} />
)}
></Route>
<Route
path="/managements/competition/customize/add"
render={(props) => (
<CompetionSetting {...propsF} {...props} />
)}
></Route>
{/* 定制竞赛配置列表 */}
<Route
path="/managements/competition/customize"
render={(props) => (
<CompetionCustomize {...propsF} {...props} />
)}
></Route>
</Switch>
</Layouts>
</div>

View File

@ -55,6 +55,7 @@ export default props => {
<Menu.Item><a rel="noopener noreferrer" href={`${main_web_site_url}/admin/competitions/list`}>竞赛列表</a></Menu.Item>
<Menu.Item><a rel="noopener noreferrer" href={`${main_web_site_url}/admin/competitions/region_zone_edit`}>赛区配置</a></Menu.Item>
<Menu.Item title="competition" key="competitionReview" ><Link to="/managements/expert/competition">竞赛评审列表</Link></Menu.Item>
<Menu.Item title="competition" key="competitionCustomize" ><Link to="/managements/competition/customize">定制竞赛配置</Link></Menu.Item>
</Menu>
});

View File

@ -97,7 +97,15 @@ const CompetitionList = Loadable({
loader: () => import("./expert/competionList"),
loading: Loading,
})
// 定制化竞赛列表,如启智
const CompetionCustomize =Loadable({
loader: () => import("../managements/competition/competionCustomize"),
loading: Loading,
})
const CompetionSetting=Loadable({
loader: () => import("../managements/competition/setting"),
loading: Loading,
})
const Managements = (propsF) => {
return (
@ -228,6 +236,27 @@ const Managements = (propsF) => {
<CompetitionList {...propsF} {...props} />
)}
></Route>
{/* 定制竞赛配置详情 */}
<Route
path="/managements/competition/customize/edit/:id"
render={(props) => (
<CompetionSetting {...propsF} {...props} />
)}
></Route>
<Route
path="/managements/competition/customize/add"
render={(props) => (
<CompetionSetting {...propsF} {...props} />
)}
></Route>
{/* 定制竞赛配置列表 */}
<Route
path="/managements/competition/customize"
render={(props) => (
<CompetionCustomize {...propsF} {...props} />
)}
></Route>
</Switch>
</div>
);

View File

@ -23,15 +23,15 @@ function Chat({ isLocal }) {
</div>
</div>
<div className="links qz_main">
<div onClick={() => { window.open(isLocal ? 'http://www.osredm.jk/forums/theme/76' : 'https://fc.osredm.com/forums/theme/107') }}>
<div onClick={() => { window.open(isLocal ? 'http://fc.osredm.jk/forums/theme/76' : 'https://fc.osredm.com/forums/theme/107') }}>
<img src={chat1} alt=""></img>
<div>参赛咨询</div>
</div>
<div onClick={() => { window.open(isLocal ? 'http://www.osredm.jk/forums/theme/77' : 'https://fc.osredm.com/forums/theme/108') }}>
<div onClick={() => { window.open(isLocal ? 'http://fc.osredm.jk/forums/theme/77' : 'https://fc.osredm.com/forums/theme/108') }}>
<img src={chat2} alt=""></img>
<div>选手交流</div>
</div>
<div onClick={() => { window.open(isLocal ? 'http://www.osredm.jk/forums/theme/78' : 'https://fc.osredm.com/forums/theme/109') }}>
<div onClick={() => { window.open(isLocal ? 'http://fc.osredm.jk/forums/theme/78' : 'https://fc.osredm.com/forums/theme/109') }}>
<img src={chat3} alt=""></img>
<div>专家答疑</div>
</div>